1 // Written in the D programming language.
2 
3 /**
4 This is a submodule of $(MREF std, math).
5 
6 It contains several versions of remainder calculation.
7 
8 Copyright: Copyright The D Language Foundation 2000 - 2011.
9 License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
10 Authors:   $(HTTP digitalmars.com, Walter Bright), Don Clugston,
11            Conversion of CEPHES math library to D by Iain Buclaw and David Nadlinger
12 Source: $(PHOBOSSRC std/math/remainder.d)
13 
14 Macros:
15      TABLE_SV = <table border="1" cellpadding="4" cellspacing="0">
16                 <caption>Special Values</caption>
17                 $0</table>
18      NAN = $(RED NAN)
19      PLUSMN = &plusmn;
20      PLUSMNINF = &plusmn;&infin;
21  */
22 
23 module std.math.remainder;
24 
25 static import core.stdc.math;
26 
27 /************************************
28  * Calculates the remainder from the calculation x/y.
29  * Returns:
30  * The value of x - i * y, where i is the number of times that y can
31  * be completely subtracted from x. The result has the same sign as x.
32  *
33  * $(TABLE_SV
34  *  $(TR $(TH x)              $(TH y)             $(TH fmod(x, y))   $(TH invalid?))
35  *  $(TR $(TD $(PLUSMN)0.0)   $(TD not 0.0)       $(TD $(PLUSMN)0.0) $(TD no))
36  *  $(TR $(TD $(PLUSMNINF))   $(TD anything)      $(TD $(NAN))       $(TD yes))
37  *  $(TR $(TD anything)       $(TD $(PLUSMN)0.0)  $(TD $(NAN))       $(TD yes))
38  *  $(TR $(TD !=$(PLUSMNINF)) $(TD $(PLUSMNINF))  $(TD x)            $(TD no))
39  * )
40  */
41 real fmod(real x, real y) @trusted nothrow @nogc
42 {
43     version (CRuntime_Microsoft)
44     {
45         return x % y;
46     }
47     else
48         return core.stdc.math.fmodl(x, y);
49 }
50 
51 ///
52 @safe unittest
53 {
54     import std.math.operations : feqrel;
55     import std.math.traits : isIdentical, isNaN;
56 
57     assert(isIdentical(fmod(0.0, 1.0), 0.0));
58     assert(fmod(5.0, 3.0).feqrel(2.0) > 16);
59     assert(isNaN(fmod(5.0, 0.0)));
60 }
61 
62 /************************************
63  * Breaks x into an integral part and a fractional part, each of which has
64  * the same sign as x. The integral part is stored in i.
65  * Returns:
66  * The fractional part of x.
67  *
68  * $(TABLE_SV
69  *  $(TR $(TH x)              $(TH i (on input))  $(TH modf(x, i))   $(TH i (on return)))
70  *  $(TR $(TD $(PLUSMNINF))   $(TD anything)      $(TD $(PLUSMN)0.0) $(TD $(PLUSMNINF)))
71  * )
72  */
73 real modf(real x, ref real i) @trusted nothrow @nogc
74 {
75     version (CRuntime_Microsoft)
76     {
77         import std.math.traits : copysign, isInfinity;
78         import std.math.rounding : trunc;
79 
80         i = trunc(x);
81         return copysign(isInfinity(x) ? 0.0 : x - i, x);
82     }
83     else
84         return core.stdc.math.modfl(x,&i);
85 }
86 
87 ///
88 @safe unittest
89 {
90     import std.math.operations : feqrel;
91 
92     real frac;
93     real intpart;
94 
95     frac = modf(3.14159, intpart);
96     assert(intpart.feqrel(3.0) > 16);
97     assert(frac.feqrel(0.14159) > 16);
98 }
99 
100 /****************************************************
101  * Calculate the remainder x REM y, following IEC 60559.
102  *
103  * REM is the value of x - y * n, where n is the integer nearest the exact
104  * value of x / y.
105  * If |n - x / y| == 0.5, n is even.
106  * If the result is zero, it has the same sign as x.
107  * Otherwise, the sign of the result is the sign of x / y.
108  * Precision mode has no effect on the remainder functions.
109  *
110  * remquo returns `n` in the parameter `n`.
111  *
112  * $(TABLE_SV
113  *  $(TR $(TH x)               $(TH y)            $(TH remainder(x, y)) $(TH n)   $(TH invalid?))
114  *  $(TR $(TD $(PLUSMN)0.0)    $(TD not 0.0)      $(TD $(PLUSMN)0.0)    $(TD 0.0) $(TD no))
115  *  $(TR $(TD $(PLUSMNINF))    $(TD anything)     $(TD -$(NAN))         $(TD ?)   $(TD yes))
116  *  $(TR $(TD anything)        $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)$(NAN)) $(TD ?)   $(TD yes))
117  *  $(TR $(TD != $(PLUSMNINF)) $(TD $(PLUSMNINF)) $(TD x)               $(TD ?)   $(TD no))
118  * )
119  */
120 real remainder(real x, real y) @trusted nothrow @nogc
121 {
122     return core.stdc.math.remainderl(x, y);
123 }
124 
125 /// ditto
126 real remquo(real x, real y, out int n) @trusted nothrow @nogc  /// ditto
127 {
128     return core.stdc.math.remquol(x, y, &n);
129 }
130 
131 ///
132 @safe @nogc nothrow unittest
133 {
134     import std.math.operations : feqrel;
135     import std.math.traits : isNaN;
136 
137     assert(remainder(5.1, 3.0).feqrel(-0.9) > 16);
138     assert(remainder(-5.1, 3.0).feqrel(0.9) > 16);
139     assert(remainder(0.0, 3.0) == 0.0);
140 
141     assert(isNaN(remainder(1.0, 0.0)));
142     assert(isNaN(remainder(-1.0, 0.0)));
143 }
144 
145 ///
146 @safe @nogc nothrow unittest
147 {
148     import std.math.operations : feqrel;
149 
150     int n;
151 
152     assert(remquo(5.1, 3.0, n).feqrel(-0.9) > 16 && n == 2);
153     assert(remquo(-5.1, 3.0, n).feqrel(0.9) > 16 && n == -2);
154     assert(remquo(0.0, 3.0, n) == 0.0 && n == 0);
155 }