00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef KLEE_UTIL_FLOATS_H
00013 #define KLEE_UTIL_FLOATS_H
00014
00015 #include "klee/util/Bits.h"
00016 #include "IntEvaluation.h"
00017
00018 #include "llvm/Support/MathExtras.h"
00019
00020 namespace klee {
00021 namespace floats {
00022
00023
00024
00025
00026
00027
00028 inline double UInt64AsDouble( uint64_t bits ) {
00029 double ret;
00030 assert( sizeof(bits) == sizeof(ret) );
00031 memcpy( &ret, &bits, sizeof bits );
00032 return ret;
00033 }
00034
00035
00036 inline float UInt64AsFloat( uint64_t bits ) {
00037 uint32_t tmp = bits;
00038 float ret;
00039 assert( sizeof(tmp) == sizeof(ret) );
00040 memcpy( &ret, &tmp, sizeof tmp );
00041 return ret;
00042 }
00043
00044
00045
00046
00047
00048
00049
00050 inline uint64_t DoubleAsUInt64( double d ) {
00051 uint64_t ret;
00052 assert( sizeof(d) == sizeof(ret) );
00053 memcpy( &ret, &d, sizeof d );
00054 return ret;
00055 }
00056
00057
00058 inline uint64_t FloatAsUInt64( float f ) {
00059 uint32_t tmp;
00060 assert( sizeof(tmp) == sizeof(f) );
00061 memcpy( &tmp, &f, sizeof f );
00062 return (uint64_t)tmp;
00063 }
00064
00065
00066
00067
00068
00069
00070 const unsigned FLT_BITS = 32;
00071 const unsigned DBL_BITS = 64;
00072
00073
00074
00075
00076
00077
00078
00079
00080 inline uint64_t add(uint64_t l, uint64_t r, unsigned inWidth) {
00081 switch( inWidth ) {
00082 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) + UInt64AsFloat(r)), FLT_BITS);
00083 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) + UInt64AsDouble(r)), DBL_BITS);
00084 default: assert(0 && "invalid floating point width");
00085 }
00086 }
00087
00088
00089 inline uint64_t sub(uint64_t l, uint64_t r, unsigned inWidth) {
00090 switch( inWidth ) {
00091 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) - UInt64AsFloat(r)), FLT_BITS);
00092 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) - UInt64AsDouble(r)), DBL_BITS);
00093 default: assert(0 && "invalid floating point width");
00094 }
00095 }
00096
00097
00098 inline uint64_t mul(uint64_t l, uint64_t r, unsigned inWidth) {
00099 switch( inWidth ) {
00100 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) * UInt64AsFloat(r)), FLT_BITS);
00101 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) * UInt64AsDouble(r)), DBL_BITS);
00102 default: assert(0 && "invalid floating point width");
00103 }
00104 }
00105
00106
00107 inline uint64_t div(uint64_t l, uint64_t r, unsigned inWidth) {
00108 switch( inWidth ) {
00109 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64(UInt64AsFloat(l) / UInt64AsFloat(r)), FLT_BITS);
00110 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64(UInt64AsDouble(l) / UInt64AsDouble(r)), DBL_BITS);
00111 default: assert(0 && "invalid floating point width");
00112 }
00113 }
00114
00115
00116 inline uint64_t mod(uint64_t l, uint64_t r, unsigned inWidth) {
00117 switch( inWidth ) {
00118 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64( fmod(UInt64AsFloat(l), UInt64AsFloat(r)) ), FLT_BITS);
00119 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64( fmod(UInt64AsDouble(l), UInt64AsDouble(r)) ), DBL_BITS);
00120 default: assert(0 && "invalid floating point width");
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 inline bool isNaN(uint64_t l, unsigned inWidth) {
00131 switch( inWidth ) {
00132 case FLT_BITS: return llvm::IsNAN( UInt64AsFloat(l) );
00133 case DBL_BITS: return llvm::IsNAN( UInt64AsDouble(l) );
00134 default: assert(0 && "invalid floating point width");
00135 }
00136 }
00137
00138 inline uint64_t eq(uint64_t l, uint64_t r, unsigned inWidth) {
00139 switch( inWidth ) {
00140 case FLT_BITS: return UInt64AsFloat(l) == UInt64AsFloat(r);
00141 case DBL_BITS: return UInt64AsDouble(l) == UInt64AsDouble(r);
00142 default: assert(0 && "invalid floating point width");
00143 }
00144 }
00145
00146 inline uint64_t ne(uint64_t l, uint64_t r, unsigned inWidth) {
00147 switch( inWidth ) {
00148 case FLT_BITS: return UInt64AsFloat(l) != UInt64AsFloat(r);
00149 case DBL_BITS: return UInt64AsDouble(l) != UInt64AsDouble(r);
00150 default: assert(0 && "invalid floating point width");
00151 }
00152 }
00153
00154 inline uint64_t lt(uint64_t l, uint64_t r, unsigned inWidth) {
00155 switch( inWidth ) {
00156 case FLT_BITS: return UInt64AsFloat(l) < UInt64AsFloat(r);
00157 case DBL_BITS: return UInt64AsDouble(l) < UInt64AsDouble(r);
00158 default: assert(0 && "invalid floating point width");
00159 }
00160 }
00161
00162 inline uint64_t le(uint64_t l, uint64_t r, unsigned inWidth) {
00163 switch( inWidth ) {
00164 case FLT_BITS: return UInt64AsFloat(l) <= UInt64AsFloat(r);
00165 case DBL_BITS: return UInt64AsDouble(l) <= UInt64AsDouble(r);
00166 default: assert(0 && "invalid floating point width");
00167 }
00168 }
00169
00170 inline uint64_t gt(uint64_t l, uint64_t r, unsigned inWidth) {
00171 switch( inWidth ) {
00172 case FLT_BITS: return UInt64AsFloat(l) > UInt64AsFloat(r);
00173 case DBL_BITS: return UInt64AsDouble(l) > UInt64AsDouble(r);
00174 default: assert(0 && "invalid floating point width");
00175 }
00176 }
00177
00178 inline uint64_t ge(uint64_t l, uint64_t r, unsigned inWidth) {
00179 switch( inWidth ) {
00180 case FLT_BITS: return UInt64AsFloat(l) >= UInt64AsFloat(r);
00181 case DBL_BITS: return UInt64AsDouble(l) >= UInt64AsDouble(r);
00182 default: assert(0 && "invalid floating point width");
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 inline uint64_t trunc(uint64_t l, unsigned outWidth, unsigned inWidth) {
00193
00194
00195 if (inWidth==64 && outWidth==64) {
00196 return l;
00197 } else {
00198 assert(inWidth==64 && "can only truncate from a 64-bit double");
00199 assert(outWidth==32 && "can only truncate to a 32-bit float");
00200 float trunc = (float)UInt64AsDouble(l);
00201 return bits64::truncateToNBits(FloatAsUInt64(trunc), outWidth);
00202 }
00203 }
00204
00205
00206 inline uint64_t ext(uint64_t l, unsigned outWidth, unsigned inWidth) {
00207
00208
00209 if (inWidth==64 && outWidth==64) {
00210 return l;
00211 } else {
00212 assert(inWidth==32 && "can only extend from a 32-bit float");
00213 assert(outWidth==64 && "can only extend to a 64-bit double");
00214 double ext = (double)UInt64AsFloat(l);
00215 return bits64::truncateToNBits(DoubleAsUInt64(ext), outWidth);
00216 }
00217 }
00218
00219
00220 inline uint64_t toUnsignedInt( uint64_t l, unsigned outWidth, unsigned inWidth ) {
00221 switch( inWidth ) {
00222 case FLT_BITS: return bits64::truncateToNBits((uint64_t)UInt64AsFloat(l), outWidth );
00223 case DBL_BITS: return bits64::truncateToNBits((uint64_t)UInt64AsDouble(l), outWidth );
00224 default: assert(0 && "invalid floating point width");
00225 }
00226 }
00227
00228
00229 inline uint64_t toSignedInt( uint64_t l, unsigned outWidth, unsigned inWidth ) {
00230 switch( inWidth ) {
00231 case FLT_BITS: return bits64::truncateToNBits((int64_t)UInt64AsFloat(l), outWidth);
00232 case DBL_BITS: return bits64::truncateToNBits((int64_t)UInt64AsDouble(l), outWidth);
00233 default: assert(0 && "invalid floating point width");
00234 }
00235 }
00236
00237
00238 inline uint64_t UnsignedIntToFP( uint64_t l, unsigned outWidth ) {
00239 switch( outWidth ) {
00240 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64((float)l), outWidth);
00241 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64((double)l), outWidth);
00242 default: assert(0 && "invalid floating point width");
00243 }
00244 }
00245
00246
00247 inline uint64_t SignedIntToFP( uint64_t l, unsigned outWidth, unsigned inWidth ) {
00248 switch( outWidth ) {
00249 case FLT_BITS: return bits64::truncateToNBits(FloatAsUInt64((float)(int64_t)ints::sext(l, 64, inWidth)), outWidth);
00250 case DBL_BITS: return bits64::truncateToNBits(DoubleAsUInt64((double)(int64_t)ints::sext(l,64, inWidth)), outWidth);
00251 default: assert(0 && "invalid floating point width");
00252 }
00253 }
00254
00255 }
00256 }
00257
00258 #endif //KLEE_UTIL_FLOATS_H