1 // Written in the D programming language.
4 * Builtin mathematical intrinsics
6 * Source: $(DRUNTIMESRC core/_math.d)
8 * TABLE_SV = <table border="1" cellpadding="4" cellspacing="0">
9 * <caption>Special Values</caption>
13 * SUP = <span style="vertical-align:super;font-size:smaller">$0</span>
14 * POWER = $1<sup>$2</sup>
17 * PLUSMNINF = ±∞
21 * Copyright: Copyright Digital Mars 2000 - 2011.
22 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
23 * Authors: $(HTTP digitalmars.com, Walter Bright),
33 /*****************************************
34 * Returns x rounded to a long value using the FE_TONEAREST rounding mode.
35 * If the integer value of x is
36 * greater than long.max, the result is
39 extern (C
) real rndtonl(real x
);
42 /***********************************
43 * Returns cosine of x. x is in radians.
46 * $(TR $(TH x) $(TH cos(x)) $(TH invalid?))
47 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) )
48 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes) )
51 * Results are undefined if |x| >= $(POWER 2,64).
54 float cos(float x
); /* intrinsic */
55 double cos(double x
); /* intrinsic */ /// ditto
56 real cos(real x
); /* intrinsic */ /// ditto
58 /***********************************
59 * Returns sine of x. x is in radians.
62 * $(TR $(TH x) $(TH sin(x)) $(TH invalid?))
63 * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes))
64 * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no))
65 * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD yes))
68 * Results are undefined if |x| >= $(POWER 2,64).
71 float sin(float x
); /* intrinsic */
72 double sin(double x
); /* intrinsic */ /// ditto
73 real sin(real x
); /* intrinsic */ /// ditto
75 /*****************************************
76 * Returns x rounded to a long value using the current rounding mode.
77 * If the integer value of x is
78 * greater than long.max, the result is
82 long rndtol(float x
); /* intrinsic */
83 long rndtol(double x
); /* intrinsic */ /// ditto
84 long rndtol(real x
); /* intrinsic */ /// ditto
86 /***************************************
87 * Compute square root of x.
90 * $(TR $(TH x) $(TH sqrt(x)) $(TH invalid?))
91 * $(TR $(TD -0.0) $(TD -0.0) $(TD no))
92 * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD yes))
93 * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no))
97 float sqrt(float x
); /* intrinsic */
98 double sqrt(double x
); /* intrinsic */ /// ditto
99 real sqrt(real x
); /* intrinsic */ /// ditto
101 /*******************************************
102 * Compute n * 2$(SUPERSCRIPT exp)
106 float ldexp(float n
, int exp
); /* intrinsic */
107 double ldexp(double n
, int exp
); /* intrinsic */ /// ditto
108 real ldexp(real n
, int exp
); /* intrinsic */ /// ditto
111 static if (real.mant_dig
== 113)
113 assert(ldexp(1.0L, -16384) == 0x1p
-16384L);
114 assert(ldexp(1.0L, -16382) == 0x1p
-16382L);
116 else static if (real.mant_dig
== 106)
118 assert(ldexp(1.0L, 1023) == 0x1p
1023L);
119 assert(ldexp(1.0L, -1022) == 0x1p
-1022L);
120 assert(ldexp(1.0L, -1021) == 0x1p
-1021L);
122 else static if (real.mant_dig
== 64)
124 assert(ldexp(1.0L, -16384) == 0x1p
-16384L);
125 assert(ldexp(1.0L, -16382) == 0x1p
-16382L);
127 else static if (real.mant_dig
== 53)
129 assert(ldexp(1.0L, 1023) == 0x1p
1023L);
130 assert(ldexp(1.0L, -1022) == 0x1p
-1022L);
131 assert(ldexp(1.0L, -1021) == 0x1p
-1021L);
134 assert(false, "Only 128bit, 80bit and 64bit reals expected here");
137 /*******************************
138 * Compute the absolute value.
140 * $(TR $(TH x) $(TH fabs(x)))
141 * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) )
142 * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) )
144 * It is implemented as a compiler intrinsic.
146 * x = floating point value
148 * References: equivalent to `std.math.fabs`
150 @safe pure nothrow @nogc
153 double fabs(double x
); /// ditto
154 real fabs(real x
); /// ditto
157 /**********************************
158 * Rounds x to the nearest integer value, using the current rounding
160 * If the return value is not equal to x, the FE_INEXACT
161 * exception is raised.
162 * $(B nearbyint) performs
163 * the same operation, but does not set the FE_INEXACT exception.
165 float rint(float x
); /* intrinsic */
166 double rint(double x
); /* intrinsic */ /// ditto
167 real rint(real x
); /* intrinsic */ /// ditto
169 /***********************************
170 * Building block functions, they
171 * translate to a single x87 instruction.
174 float yl2x(float x
, float y
); /* intrinsic */
175 double yl2x(double x
, double y
); /* intrinsic */ /// ditto
176 real yl2x(real x
, real y
); /* intrinsic */ /// ditto
178 float yl2xp1(float x
, float y
); /* intrinsic */
179 double yl2xp1(double x
, double y
); /* intrinsic */ /// ditto
180 real yl2xp1(real x
, real y
); /* intrinsic */ /// ditto
184 version (INLINE_YL2X
)
186 assert(yl2x(1024.0L, 1) == 10);
187 assert(yl2xp1(1023.0L, 1) == 10);
191 /*************************************
192 * Round argument to a specific precision.
194 * D language types specify only a minimum precision, not a maximum. The
195 * `toPrec()` function forces rounding of the argument `f` to the precision
196 * of the specified floating point type `T`.
197 * The rounding mode used is inevitably target-dependent, but will be done in
198 * a way to maximize accuracy. In most cases, the default is round-to-nearest.
201 * T = precision type to round to
202 * f = value to convert
204 * f in precision of type `T`
206 T
toPrec(T
:float)(float f
) { pragma(inline
, false); return f
; }
208 T
toPrec(T
:float)(double f
) { pragma(inline
, false); return cast(T
) f
; }
210 T
toPrec(T
:float)(real f
) { pragma(inline
, false); return cast(T
) f
; }
212 T
toPrec(T
:double)(float f
) { pragma(inline
, false); return f
; }
214 T
toPrec(T
:double)(double f
) { pragma(inline
, false); return f
; }
216 T
toPrec(T
:double)(real f
) { pragma(inline
, false); return cast(T
) f
; }
218 T
toPrec(T
:real)(float f
) { pragma(inline
, false); return f
; }
220 T
toPrec(T
:real)(double f
) { pragma(inline
, false); return f
; }
222 T
toPrec(T
:real)(real f
) { pragma(inline
, false); return f
; }
226 // Test all instantiations work with all combinations of float.
230 f
= toPrec
!float(f
+ f
);
231 f
= toPrec
!float(d
+ d
);
232 f
= toPrec
!float(r
+ r
);
233 d
= toPrec
!double(f
+ f
);
234 d
= toPrec
!double(d
+ d
);
235 d
= toPrec
!double(r
+ r
);
236 r
= toPrec
!real(f
+ f
);
237 r
= toPrec
!real(d
+ d
);
238 r
= toPrec
!real(r
+ r
);
241 bool approxEqual(T
)(T lhs
, T rhs
)
243 return fabs((lhs
- rhs
) / rhs
) <= 1e-2 ||
fabs(lhs
- rhs
) <= 1e-5;
246 enum real PIR
= 0xc.90fdaa
22168c
235p
-2;
247 enum double PID
= 0x1.921fb54442d18p
+1;
248 enum float PIF
= 0x1.921fb6p
+1;
249 static assert(approxEqual(toPrec
!float(PIR
), PIF
));
250 static assert(approxEqual(toPrec
!double(PIR
), PID
));
251 static assert(approxEqual(toPrec
!real(PIR
), PIR
));
252 static assert(approxEqual(toPrec
!float(PID
), PIF
));
253 static assert(approxEqual(toPrec
!double(PID
), PID
));
254 static assert(approxEqual(toPrec
!real(PID
), PID
));
255 static assert(approxEqual(toPrec
!float(PIF
), PIF
));
256 static assert(approxEqual(toPrec
!double(PIF
), PIF
));
257 static assert(approxEqual(toPrec
!real(PIF
), PIF
));
259 assert(approxEqual(toPrec
!float(PIR
), PIF
));
260 assert(approxEqual(toPrec
!double(PIR
), PID
));
261 assert(approxEqual(toPrec
!real(PIR
), PIR
));
262 assert(approxEqual(toPrec
!float(PID
), PIF
));
263 assert(approxEqual(toPrec
!double(PID
), PID
));
264 assert(approxEqual(toPrec
!real(PID
), PID
));
265 assert(approxEqual(toPrec
!float(PIF
), PIF
));
266 assert(approxEqual(toPrec
!double(PIF
), PIF
));
267 assert(approxEqual(toPrec
!real(PIF
), PIF
));