1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.Float; 13 14 import hunt.Exceptions; 15 import hunt.Nullable; 16 import hunt.Number; 17 18 import std.conv; 19 import std.math; 20 21 /** 22 */ 23 class Float : AbstractNumber!float { 24 /** 25 * A constant holding the positive infinity of type 26 * {@code float}. It is equal to the value returned by 27 * {@code Float.intBitsToFloat(0x7f800000)}. 28 */ 29 enum float POSITIVE_INFINITY = float.infinity; // 1.0f / 0.0f; 30 31 /** 32 * A constant holding the negative infinity of type 33 * {@code float}. It is equal to the value returned by 34 * {@code Float.intBitsToFloat(0xff800000)}. 35 */ 36 enum float NEGATIVE_INFINITY = -float.infinity; // -1.0f / 0.0f; 37 38 /** 39 * A constant holding a Not-a-Number (NaN) value of type 40 * {@code float}. It is equivalent to the value returned by 41 * {@code Float.intBitsToFloat(0x7fc00000)}. 42 */ 43 enum float NaN = float.nan; // 0.0f / 0.0f; 44 45 /** 46 * A constant holding the largest positive finite value of type 47 * {@code float}, (2-2<sup>-23</sup>)·2<sup>127</sup>. 48 * It is equal to the hexadecimal floating-point literal 49 * {@code 0x1.fffffeP+127f} and also equal to 50 * {@code Float.intBitsToFloat(0x7f7fffff)}. 51 */ 52 enum float MAX_VALUE = float.max; // 0x1.fffffeP+127f; // 3.4028235e+38f 53 54 /** 55 * A constant holding the smallest positive normal value of type 56 * {@code float}, 2<sup>-126</sup>. It is equal to the 57 * hexadecimal floating-point literal {@code 0x1.0p-126f} and also 58 * equal to {@code Float.intBitsToFloat(0x00800000)}. 59 * 60 */ 61 enum float MIN_NORMAL = float.min_normal; // 0x1.0p-126f; // 1.17549435E-38f 62 63 /** 64 * A constant holding the smallest positive nonzero value of type 65 * {@code float}, 2<sup>-149</sup>. It is equal to the 66 * hexadecimal floating-point literal {@code 0x0.000002P-126f} 67 * and also equal to {@code Float.intBitsToFloat(0x1)}. 68 */ 69 enum float MIN_VALUE = float.min_10_exp; //0x0.000002P-126f; // 1.4e-45f 70 71 /** 72 * Maximum exponent a finite {@code float} variable may have. It 73 * is equal to the value returned by {@code 74 * Math.getExponent(Float.MAX_VALUE)}. 75 * 76 */ 77 enum int MAX_EXPONENT = 127; 78 79 /** 80 * Minimum exponent a normalized {@code float} variable may have. 81 * It is equal to the value returned by {@code 82 * Math.getExponent(Float.MIN_NORMAL)}. 83 * 84 */ 85 enum int MIN_EXPONENT = -126; 86 87 /** 88 * The number of bits used to represent a {@code float} value. 89 * 90 */ 91 enum int SIZE = 32; 92 93 /** 94 * The number of bytes used to represent a {@code float} value. 95 * 96 */ 97 enum int BYTES = SIZE / 8; 98 99 /** 100 * Constructs a newly allocated {@code Float} object that 101 * represents the primitive {@code float} argument. 102 * 103 * @param value the value to be represented by the {@code Float}. 104 */ 105 this(float value) { 106 super(value); 107 } 108 109 /** 110 * Constructs a newly allocated {@code Float} object that 111 * represents the argument converted to type {@code float}. 112 * 113 * @param value the value to be represented by the {@code Float}. 114 */ 115 this(double value) { 116 super(cast(float)value); 117 } 118 119 120 static float parseFloat(string s) { 121 return to!float(s); 122 } 123 124 /** 125 * Constructs a newly allocated {@code Float} object that 126 * represents the floating-point value of type {@code float} 127 * represented by the string. The string is converted to a 128 * {@code float} value as if by the {@code valueOf} method. 129 * 130 * @param s a string to be converted to a {@code Float}. 131 * @throws NumberFormatException if the string does not contain a 132 * parsable number. 133 * @see java.lang.Float#valueOf(java.lang.string) 134 */ 135 this(string s){ 136 super(parseFloat(s)); 137 } 138 139 /** 140 * Returns {@code true} if this {@code Float} value is a 141 * Not-a-Number (NaN), {@code false} otherwise. 142 * 143 * @return {@code true} if the value represented by this object is 144 * NaN; {@code false} otherwise. 145 */ 146 bool isNaN() { 147 return isNaN(value); 148 } 149 150 /** 151 * Returns {@code true} if this {@code Float} value is 152 * infinitely large in magnitude, {@code false} otherwise. 153 * 154 * @return {@code true} if the value represented by this object is 155 * positive infinity or negative infinity; 156 * {@code false} otherwise. 157 */ 158 bool isInfinite() { 159 return isInfinite(value); 160 } 161 162 /** 163 * Returns a hash code for a {@code double} value; compatible with 164 * {@code Double.hashCode()}. 165 * 166 * @param value the value to hash 167 * @return a hash code value for a {@code double} value. 168 */ 169 override size_t toHash() @safe nothrow { 170 return hashOf(value); 171 } 172 173 /** 174 * Returns a {@code Float} instance representing the specified 175 * {@code float} value. 176 * If a new {@code Float} instance is not required, this method 177 * should generally be used in preference to the constructor 178 * {@link #Float(float)}, as this method is likely to yield 179 * significantly better space and time performance by caching 180 * frequently requested values. 181 * 182 * @param f a float value. 183 * @return a {@code Float} instance representing {@code f}. 184 */ 185 static Float valueOf(float f) { 186 return new Float(f); 187 } 188 189 /** 190 * Returns a representation of the specified floating-point value 191 * according to the IEEE 754 floating-point "single format" bit 192 * layout, preserving Not-a-Number (NaN) values. 193 * 194 * <p>Bit 31 (the bit that is selected by the mask 195 * {@code 0x80000000}) represents the sign of the floating-point 196 * number. 197 * Bits 30-23 (the bits that are selected by the mask 198 * {@code 0x7f800000}) represent the exponent. 199 * Bits 22-0 (the bits that are selected by the mask 200 * {@code 0x007fffff}) represent the significand (sometimes called 201 * the mantissa) of the floating-point number. 202 * 203 * <p>If the argument is positive infinity, the result is 204 * {@code 0x7f800000}. 205 * 206 * <p>If the argument is negative infinity, the result is 207 * {@code 0xff800000}. 208 * 209 * <p>If the argument is NaN, the result is the integer representing 210 * the actual NaN value. Unlike the {@code floatToIntBits} 211 * method, {@code floatToRawIntBits} does not collapse all the 212 * bit patterns encoding a NaN to a single "canonical" 213 * NaN value. 214 * 215 * <p>In all cases, the result is an integer that, when given to the 216 * {@link #intBitsToFloat(int)} method, will produce a 217 * floating-point value the same as the argument to 218 * {@code floatToRawIntBits}. 219 * 220 * @param value a floating-point number. 221 * @return the bits that represent the floating-point number. 222 */ 223 static int floatToRawIntBits(float value) { 224 byte* ptr = cast(byte*)&value; 225 // trace("%(%02X %)", ptr[0..float.sizeof]); 226 return *(cast(int*)ptr); 227 } 228 229 /** 230 * Returns the {@code float} value corresponding to a given 231 * bit representation. 232 * The argument is considered to be a representation of a 233 * floating-point value according to the IEEE 754 floating-point 234 * "single format" bit layout. 235 * 236 * <p>If the argument is {@code 0x7f800000}, the result is positive 237 * infinity. 238 * 239 * <p>If the argument is {@code 0xff800000}, the result is negative 240 * infinity. 241 * 242 * <p>If the argument is any value in the range 243 * {@code 0x7f800001} through {@code 0x7fffffff} or in 244 * the range {@code 0xff800001} through 245 * {@code 0xffffffff}, the result is a NaN. No IEEE 754 246 * floating-point operation provided by Java can distinguish 247 * between two NaN values of the same type with different bit 248 * patterns. Distinct values of NaN are only distinguishable by 249 * use of the {@code Float.floatToRawIntBits} method. 250 * 251 * <p>In all other cases, let <i>s</i>, <i>e</i>, and <i>m</i> be three 252 * values that can be computed from the argument: 253 * 254 * <blockquote><pre>{@code 255 * int s = ((bits >> 31) == 0) ? 1 : -1; 256 * int e = ((bits >> 23) & 0xff); 257 * int m = (e == 0) ? 258 * (bits & 0x7fffff) << 1 : 259 * (bits & 0x7fffff) | 0x800000; 260 * }</pre></blockquote> 261 * 262 * Then the floating-point result equals the value of the mathematical 263 * expression <i>s</i>·<i>m</i>·2<sup><i>e</i>-150</sup>. 264 * 265 * <p>Note that this method may not be able to return a 266 * {@code float} NaN with exactly same bit pattern as the 267 * {@code int} argument. IEEE 754 distinguishes between two 268 * kinds of NaNs, quiet NaNs and <i>signaling NaNs</i>. The 269 * differences between the two kinds of NaN are generally not 270 * visible in Java. Arithmetic operations on signaling NaNs turn 271 * them into quiet NaNs with a different, but often similar, bit 272 * pattern. However, on some processors merely copying a 273 * signaling NaN also performs that conversion. In particular, 274 * copying a signaling NaN to return it to the calling method may 275 * perform this conversion. So {@code intBitsToFloat} may 276 * not be able to return a {@code float} with a signaling NaN 277 * bit pattern. Consequently, for some {@code int} values, 278 * {@code floatToRawIntBits(intBitsToFloat(start))} may 279 * <i>not</i> equal {@code start}. Moreover, which 280 * particular bit patterns represent signaling NaNs is platform 281 * dependent; although all NaN bit patterns, quiet or signaling, 282 * must be in the NaN range identified above. 283 * 284 * @param bits an integer. 285 * @return the {@code float} floating-point value with the same bit 286 * pattern. 287 */ 288 static float intBitsToFloat(int bits) { 289 byte* ptr = cast(byte*)&bits; 290 // trace("%(%02X %)", ptr[0..float.sizeof]); 291 return *(cast(float*)ptr); 292 } 293 294 /** 295 * Returns {@code true} if the specified number is a 296 * Not-a-Number (NaN) value, {@code false} otherwise. 297 * 298 * @param v the value to be tested. 299 * @return {@code true} if the argument is NaN; 300 * {@code false} otherwise. 301 */ 302 static bool isNaN(float v) { 303 return std.math.isNaN(v); 304 } 305 306 /** 307 * Returns {@code true} if the specified number is infinitely 308 * large in magnitude, {@code false} otherwise. 309 * 310 * @param v the value to be tested. 311 * @return {@code true} if the argument is positive infinity or 312 * negative infinity; {@code false} otherwise. 313 */ 314 static bool isInfinite(float v) { 315 return std.math.isInfinity(v); 316 } 317 318 /** 319 * Returns {@code true} if the argument is a finite floating-point 320 * value; returns {@code false} otherwise (for NaN and infinity 321 * arguments). 322 * 323 * @param f the {@code float} value to be tested 324 * @return {@code true} if the argument is a finite 325 * floating-point value, {@code false} otherwise. 326 */ 327 static bool isFinite(float f) { 328 return std.math.isInfinity(f); 329 } 330 331 } 332 333 334 /** 335 * This class contains additional constants documenting limits of the 336 * {@code float} type. 337 * 338 * @author Joseph D. Darcy 339 */ 340 341 class FloatConsts { 342 /** 343 * Don't let anyone instantiate this class. 344 */ 345 private this() {} 346 347 /** 348 * The number of logical bits in the significand of a 349 * {@code float} number, including the implicit bit. 350 */ 351 enum int SIGNIFICAND_WIDTH = 24; 352 353 /** 354 * The exponent the smallest positive {@code float} subnormal 355 * value would have if it could be normalized. 356 */ 357 enum int MIN_SUB_EXPONENT = Float.MIN_EXPONENT - 358 (SIGNIFICAND_WIDTH - 1); 359 360 /** 361 * Bias used in representing a {@code float} exponent. 362 */ 363 enum int EXP_BIAS = 127; 364 365 /** 366 * Bit mask to isolate the sign bit of a {@code float}. 367 */ 368 enum int SIGN_BIT_MASK = 0x80000000; 369 370 /** 371 * Bit mask to isolate the exponent field of a 372 * {@code float}. 373 */ 374 enum int EXP_BIT_MASK = 0x7F800000; 375 376 /** 377 * Bit mask to isolate the significand field of a 378 * {@code float}. 379 */ 380 enum int SIGNIF_BIT_MASK = 0x007FFFFF; 381 382 // static { 383 // // verify bit masks cover all bit positions and that the bit 384 // // masks are non-overlapping 385 // assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) && 386 // (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) && 387 // ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) && 388 // ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0))); 389 // } 390 }