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>)&middot;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>&middot;<i>m</i>&middot;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 }