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 = ±
20 PLUSMNINF = ±∞
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 */
fmod(real x,real y)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 */
modf(real x,ref real i)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 */
remainder(real x,real y)120 real remainder(real x, real y) @trusted nothrow @nogc
121 {
122 return core.stdc.math.remainderl(x, y);
123 }
124
125 /// ditto
remquo(real x,real y,out int n)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 }
156