1 module gcc.fpmath; 2 3 enum 4 { 5 FP_NAN = 1, 6 FP_INFINITE, 7 FP_ZERO, 8 FP_SUBNORMAL, 9 FP_NORMAL, 10 } 11 12 enum RealFormat 13 { 14 SameAsDouble, 15 DoubleDouble, 16 Intel80, 17 } 18 19 struct Info { 20 static if (real.sizeof == double.sizeof) { 21 static const RealFormat realFormat = RealFormat.SameAsDouble; 22 } else version (PPC) { 23 static const RealFormat realFormat = RealFormat.DoubleDouble; 24 union real_rec { 25 real f; 26 struct { double hd, ld; } 27 } 28 } else version (PPC64) { 29 static const RealFormat realFormat = RealFormat.DoubleDouble; 30 union real_rec { 31 real f; 32 struct { double hd, ld; } 33 } 34 } else version (X86) { 35 static const RealFormat realFormat = RealFormat.Intel80; 36 union real_rec { 37 real f; 38 struct { uint li, mi, hi; } 39 } 40 } else version (X86_64) { 41 static const RealFormat realFormat = RealFormat.Intel80; 42 union real_rec { 43 real f; 44 struct { uint li, mi, hi; } 45 } 46 } else { 47 static assert(0); 48 } 49 } 50 51 union float_rec { 52 float f; 53 uint i; 54 } 55 56 int signbit(float f) 57 { 58 float_rec r = void; 59 r.f = f; 60 return r.i & 0x80000000; 61 } 62 63 int fpclassify(float f) 64 { 65 float_rec r = void; 66 r.f = f; 67 uint i = r.i & 0x7fffffff; 68 69 if (! i) 70 return FP_ZERO; 71 else if (i < 0x00800000) 72 return FP_SUBNORMAL; 73 else if (i < 0x7f800000) 74 return FP_NORMAL; 75 else if (i < 0x7f800001) 76 return FP_INFINITE; 77 else 78 return FP_NAN; 79 } 80 81 union double_rec { 82 double f; 83 struct { 84 version (BigEndian) 85 uint hi, li; 86 else 87 uint li, hi; 88 } 89 } 90 91 int signbit(double f) 92 { 93 double_rec r = void; 94 r.f = f; 95 return r.hi & 0x80000000; 96 } 97 98 int fpclassify(double f) 99 { 100 double_rec r = void; 101 r.f = f; 102 uint i = r.hi & 0x7fffffff; 103 104 if (! (i | r.li)) 105 return FP_ZERO; 106 else if (i < 0x00100000) 107 return FP_SUBNORMAL; 108 else if (i < 0x7ff00000) 109 return FP_NORMAL; 110 else if (i == 0x7ff00000 && ! r.li) 111 return FP_INFINITE; 112 else 113 return FP_NAN; 114 } 115 116 int signbit(real f) 117 { 118 static if (Info.realFormat == RealFormat.SameAsDouble) { 119 return signbit(cast(double) f); 120 } else static if (Info.realFormat == RealFormat.DoubleDouble) { 121 Info.real_rec r = void; 122 r.f = f; 123 return signbit(r.hd); 124 } else static if (Info.realFormat == RealFormat.Intel80) { 125 Info.real_rec r = void; 126 r.f = f; 127 return r.hi & 0x00008000; 128 } 129 } 130 131 int fpclassify(real f) 132 { 133 static if (Info.realFormat == RealFormat.SameAsDouble) { 134 return fpclassify(cast(double) f); 135 } else static if (Info.realFormat == RealFormat.DoubleDouble) { 136 Info.real_rec r = void; 137 r.f = f; 138 return fpclassify(r.hd); 139 } else static if (Info.realFormat == RealFormat.Intel80) { 140 Info.real_rec r = void; 141 r.f = f; 142 uint i = r.hi & 0x00007fff; 143 uint li = r.li | (r.mi & 0x7fffffff) ; 144 if (! i && ! li) 145 return FP_ZERO; 146 else if (i < 0x00000001 && (r.mi & 0x80000000) == 0) 147 return FP_SUBNORMAL; 148 else if (i < 0x00007fff) 149 return FP_NORMAL; 150 else if (i == 0x00007fff && ! li) 151 return FP_INFINITE; 152 else 153 return FP_NAN; 154 } 155 } 156 157 unittest 158 { 159 static if (Info.realFormat == RealFormat.SameAsDouble) { 160 const real xrsn = 0x1p-1050; 161 } else static if (Info.realFormat == RealFormat.DoubleDouble) { 162 const real xrsn = 0x1p-1050; 163 } else static if (Info.realFormat == RealFormat.Intel80) { 164 const real xrsn = 0x1p-16390; 165 } 166 167 static float[] xfi = [ float.nan, -float.nan, float.infinity, -float.infinity, 168 0.0f, -0.0f, 0x1p-135f, -0x1p-135f, 4.2f, -4.2f ]; 169 static double[] xdi = [ double.nan, -double.nan, double.infinity, -double.infinity, 170 0.0, -0.0, 0x1p-1050, -0x1p-1050, 4.2, -4.2 ]; 171 static real[] xri = [ real.nan, -real.nan, real.infinity, -real.infinity, 172 0.0L, -0.0L, xrsn, -xrsn, 4.2L, -4.2L ]; 173 static int[] xo = [ FP_NAN, FP_NAN, FP_INFINITE, FP_INFINITE, 174 FP_ZERO, FP_ZERO, FP_SUBNORMAL, FP_SUBNORMAL, FP_NORMAL, FP_NORMAL]; 175 176 foreach (int i, int cls; xo) { 177 assert( fpclassify(xfi[i]) == xo[i] ); 178 assert( fpclassify(xdi[i]) == xo[i] ); 179 assert( fpclassify(xri[i]) == xo[i] ); 180 assert( ( signbit(xfi[i]) ?1:0 ) == (i & 1) ); 181 assert( ( signbit(xdi[i]) ?1:0 ) == (i & 1) ); 182 assert( ( signbit(xri[i]) ?1:0 ) == (i & 1) ); 183 } 184 }