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 */ 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 }