1 // Written in the D programming language
2 
3 /**
4  * Floating-point decimal arithmetic.
5  *
6  * An implementation of the
7  * General Decimal Arithmetic Specification.
8  *
9  * Authors: Paul D. Anderson
10  *
11  * Copyright: Copyright 2009-2016 by Paul D. Anderson.
12  *
13  * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>
14  *
15  * Standards: Conforms to the
16  *  General Decimal Arithmetic Specification,
17  *  Version 1.70, (25 March 2009).
18  */
19 
20 /*
21 
22  *  carry out internal operations at a precision different from the type
23  *  precision.
24  */
25 
26 /*
27   TODO: For each function --
28     1. Ensure algorithm is properly implemented.
29     2. Ensure context flags are being set properly.
30     3. Ensure function passes GDA tests.
31     4. Determine additional tests needed and implement them.
32     5. Ensure all special cases are enumerated.
33     6. Automate all tests, if possible.
34     7. Determine what effect the context has on the function and
35       if it should be explained.
36     8. Ensure all documentation is complete:
37       a. Header - description, inputs, return value(s)
38       b. Code - variables, control statements, branches, return points.
39     9. Move most tests to the test module.
40 */
41 
42 // TODO: (testing) opEquals unit test should include numerically equal testing.
43 
44 // TODO: (testing) write some test cases for flag setting. test the add/sub/mul/div functions
45 
46 module eris.decimal.arithmetic;
47 
48 import eris.decimal;
49 import std.string;
50 import std.algorithm;
51   import std.stdio;
52 
53 unittest {
54   writeln("     arithmetic.tests     ");
55   writeln("==========================");
56 }
57 
58 version(unittest)
59 {
60   import std.stdio;
61   import eris.decimal.test;
62 }
63 
64 
65 //--------------------------------
66 // classification functions
67 //--------------------------------
68 
69 /**
70  *  Returns a string indicating the class and sign of the argument.
71  *
72  *  Classes are: sNaN, NaN, Infinity, Zero, Normal, and Subnormal.
73  *  The sign of any NaN values is ignored in the classification.
74  *  The argument is not rounded and no flags are changed.
75  *
76  * Standards: Implements the 'class' function in the specification. (p. 42)
77  *
78  * Flags: None
79  *
80  */
81 public string classify(D)(in D num) if (isDecimal!D)
82 {
83   if (num.isFinite)
84   {
85     if (num.isZero)      { return num.sign ? "-Zero" : "+Zero"; }
86     if (num.isNormal)    { return num.sign ? "-Normal" : "+Normal"; }
87     if (num.isSubnormal) { return num.sign ? "-Subnormal" : "+Subnormal"; }
88   }
89   if (num.isInfinite)  { return num.sign ? "-Infinity" : "+Infinity"; }
90   if (num.isSignal) { return "sNaN"; }
91   return "NaN";
92 }
93 
94 unittest
95 {  // classify
96   static struct S { TD num; string expect; }
97   S[] s =
98   [
99     { TD.nan,         "NaN" },
100     { TD.snan,        "sNaN" },
101     { TD.infinity,    "+Infinity" },
102     { TD("1E-10"),    "+Normal" },
103     { TD("-0"),       "-Zero" },
104     // definitions of normal and subnormal depend on context -- pass these?
105     { TD("-0.9E-368"), "-Subnormal" },
106   ];
107   auto f = FunctionTest!(S,string)("classify");
108   foreach (t; s) f.test(t, classify(t.num));
109   writefln(f.report);
110 }
111 
112 /**
113  *  Returns the truncated base 10 logarithm of the argument.
114  *
115  *  "...The integer which is the exponent of the magnitude
116  *  of the most significant digit of the operand.
117  *  (As though the operand were truncated to a single digit
118  *  while maintaining the value of that digit and without
119  *  limiting the resulting exponent)". (p. 47)
120  *
121  *  Standards: Implements the 'logb' function in the specification. (p. 47)
122  *
123  *  Flags: INVALID_OPERATION, DIVISION_BY_ZERO.
124  *
125  */
126 public int ilogb(D)(in D num) if (isDecimal!D)
127 {
128   if (num.isInfinite || num.isNaN)
129   {
130     invalidOperation!D;
131     return int.init;
132   }
133   if (num.isZero)
134   {
135     contextFlags.set(DIVISION_BY_ZERO);
136     return int.init;
137   }
138   return num.digits + num.expo - 1;
139 }
140 
141 unittest
142 {  // ilogb
143   static struct S { TD num; int expect; }
144   S[] s =
145   [
146     { 250,    2 },
147     { 2.5,    0 },
148     { 0.03,  -2 },
149     { "Inf",  0 },  // sets INVALID_OPERATION flag
150     { 0,      0 },  // sets DIVISION_BY_ZERO flag
151   ];
152   auto f = FunctionTest!(S,int)("ilogb");
153   foreach (t; s) f.test(t, ilogb(t.num));
154   writefln(f.report);
155 }
156 
157 /**
158  *  Returns the truncated base 10 logarithm of the argument.
159  *
160  *  "...The integer which is the exponent of the magnitude
161  *  of the most significant digit of the operand.
162  *  (As though the operand were truncated to a single digit
163  *  while maintaining the value of that digit and without
164  *  limiting the resulting exponent)". (p. 47)
165  *
166  * Flags: INVALID_OPERATION, DIVISION_BY_ZERO
167  *
168  *
169  *  Standard: Implements the 'logb' function in the specification. (p. 47)
170  *
171  */
172 public D logb(D)(in D num) if (isDecimal!D)
173 {
174   if (num.isNaN) return invalidOperand(num);
175   if (num.isInfinite) return D.infinity;
176   if (num.isZero)
177   {
178     contextFlags.set(DIVISION_BY_ZERO);
179     return D.infinity(true);
180   }
181   int exp = num.digits + num.expo - 1;
182   return D(exp);
183 }
184 
185 unittest
186 {  // logb
187   static struct S { TD num; TD expect; }
188   S[] s =
189   [
190     { 250,    2 },
191     { 2.5,    0 },
192     { 0.03,  -2 },
193     { "Inf", "Inf" },
194     { 0,     "-Inf" },
195     { "NaN", "NaN" }, // NOTE: this test will fail: NaN != NaN
196   ];
197   auto f = FunctionTest!(S,TD)("logb");
198   foreach (t; s) f.test(t, logb(t.num));
199   writefln(f.report);
200 }
201 
202 /**
203  *  If the first operand is infinite then that operand is returned,
204  *  otherwise the result is the first operand modified by
205  *  adding the value of the second operand to its exponent.
206  *
207  *  The second operand must be a finite integer (<= int.max && >= int.min)
208  *   with an exponent of zero.
209  *
210  *  Remarks: The result may overflow or underflow.
211  *
212  *  Standards: Implements the 'scaleb' function in the specification. (p. 48)
213  *
214  *  Flags: INVALID_OPERATION, UNDERFLOW, OVERFLOW.
215  *
216  */
217 public D scaleb(D)(in D left, in D right) if (isDecimal!D)
218 {
219   D scaled = left.dup;
220 
221   if (left.isNaN || right.isNaN) return invalidOperand(left,right);
222 
223   if (left.isInfinite) return scaled;
224 
225   if (right.isInfinite || right.expo != 0)
226   {
227     return invalidOperand(right);
228   }
229 //  if (right > D.IntMax || right < D.IntMin)
230   if (right > D(int.max) || right < D(int.min))
231   {
232     return invalidOperand(right);
233   }
234 
235   int scale = /*cast(int)*/right.coff.toInt;
236 
237   if (right.isNegative)
238   {
239     scale = -scale;
240   }
241   // TODO: (behavior) check for overflow/underflow (GDA "scaleb").
242   scaled.expo = scaled.expo + scale;
243   return scaled;
244 }
245 
246 unittest
247 {  // scaleb
248   static struct S { TD left; TD right; TD expect; }
249   S[] s =
250   [
251     { "7.50", "-2", "0.0750" },
252 //    { "7.50", "-3", "0.0750" },
253   ];
254   auto f = FunctionTest!(S,TD)("scaleb");
255   foreach (t; s) f.test(t, scaleb(t.left, t.right));
256   writefln(f.report);
257 }
258 
259 //--------------------------------
260 // unary functions
261 //--------------------------------
262 
263 /**
264  *  Rounds the argument to an integer using the specified rounding mode.
265  *  The default rounding mode is the current context mode. //FIXTHIS
266  */
267 /*public D round(D)(D num, Round mode = D.mode)
268 {
269   if (num.isNaN)
270     {
271     contextFlags.set(INVALID_OPERATION);
272     return D.nan;
273   }
274   return roundToInt(num, mode);
275 }*/
276 
277 /+
278 unittest
279 {  // round
280   static struct S { TD num; TD expect; }
281   S[] s =
282   [
283 /*    { " 1",          "2", " 1.00000001" },
284     { "-1.00000003", "0", "-1.00000002" },*/
285   ];
286   auto f = FunctionTest!(S,TD)("round");
287   foreach (t; s) f.test(t, round(t.num));
288   writefln(f.report);
289 }
290 +/
291 
292 
293 /**
294  *
295  *  Returns the operand reduced to its simplest form.
296  *
297  *  <code>reduce</code> has the same semantics as the plus operation,
298  *  except that a finite result is
299  *  reduced to its simplest form, with all trailing
300  *  zeros removed and its sign preserved.
301  *
302  *  zeros removed and its sign preserved.
303  *
304  *  Standard: Implements the 'reduce' function in the specification. (p. 37)
305  *  "This operation was called 'normalize' prior to
306  *  version 1.68 of the specification." (p. 37)
307  *
308  *  Flags: INVALID_OPERATION
309  *
310  */
311 public D reduce(D)(in D num,
312     Context context = D.context) if (isDecimal!D)
313 {
314   // special cases
315   if (num.isNaN) return invalidOperand(num);
316   if (!num.isFinite) return num.dup;
317 
318   // round the argument
319   D reduced = plus(num, context);
320 
321   // have to check again -- rounding may have made it infinite
322   if (!reduced.isFinite) return reduced;
323 
324   int digits = reduced.digits;
325   auto temp = reduced.coff;
326   int zeros = clipZeros(temp, digits);
327   if (zeros)
328   {
329     reduced.coff = temp;
330     reduced.digits = digits - zeros;
331     reduced.expo = reduced.expo + zeros;
332   }
333 
334   return reduced;
335 }
336 
337 // just a wrapper
338 public D normalize(D)(in D num,
339     Context context = D.context) if (isDecimal!D)
340 {
341   return reduce(num, context);
342 }
343 
344 unittest
345 {  // reduce
346   // test results depend on context
347   static struct S { TD num; TD expect; }
348   S[] s =
349   [
350     { "1.200", "1.2" },
351 //    { "1.200", "1.3" },  // should fail
352 //  FIXTHIS: should fail but doesn't
353     { "1.200", "1.20" },  // NOTE: should fail but doesn't
354     { "1.2001", "1.2001" },
355     { "1.2000000000000001", "1.2" },
356   ];
357   auto f = FunctionTest!(S,TD)("reduce");
358   foreach (t; s) f.test(t, reduce(t.num));
359   writefln(f.report);
360 }
361 
362 /**
363  *  Returns the absolute value of the argument.
364  *
365  *  The result is equivalent to plus(arg) for positive numbers
366  *  and to minus(arg) for negative numbers.
367  *
368  *  Note: This operation rounds the result and may set flags.
369  *  To return the absolute value without rounding or setting flags
370  *  use the 'copyAbs' function.
371  *
372  *  Standards: Implements the 'abs' function in the specification. (p. 26)
373  *
374  *  Flags: INVALID_OPERATION
375  */
376 public D abs(D)(in D arg, Context context = D.context) if (isDecimal!D)
377 {
378   if (arg.isNaN) return invalidOperand(arg);
379   return round(arg.copyAbs, context);
380 }
381 
382 unittest
383 {  // abs
384   static struct S { TD arg; TD expect; }
385   S[] s =
386   [
387     { "-Inf", "Inf" },
388     { "101.5", "101.5" },
389     { "-101.5", "101.5" },
390     // test results that are rounded are dependent on context
391     { "-1.234567890123456749E+23", "1.2345678901234567E+23" },  // rounds the argument
392   ];
393   auto f = FunctionTest!(S,TD)("abs");
394   foreach (t; s) f.test(t, abs(t.arg));
395   writefln(f.report);
396 }
397 
398 /**
399  *  Returns -1, 0, or 1 if the argument is
400  *  negative, zero, or positive, respectively.
401  *  The sign of zero is ignored: returns 0 for +0 or -0.
402  */
403 public int sgn(D)(in D num) if (isDecimal!D)
404 {
405   if (num.isZero) return 0;
406   return num.isNegative ? -1 : 1;
407 }
408 
409 unittest
410 {  // sgn
411   static struct S { TD num; int expect; }
412   S[] s =
413   [
414     {  "-123", -1 },
415     {  "2345",  1 },
416     { "-2345", -1 },
417     {     "0",  0 },
418     {    "-0",  0 },
419     {  "0.00",  0 },
420     {  "-Inf", -1 },
421   ];
422   auto f = FunctionTest!(S,int)("sgn");
423   foreach (t; s) f.test(t, sgn(t.num));
424   writefln(f.report);
425 }
426 
427 /**
428  *  Returns -1, 0, or 1
429  *  if the argument is negative, zero, or positive, respectively.
430  */
431 /*public int sgn(D:BigInt)(D arg) {
432   if (arg < 0) return -1;
433   if (arg > 0) return 1;
434   return 0;
435 }*/
436 
437 /**
438  *  Returns a copy of the argument with the same sign as the argument.
439  *  The result is equivalent to add('0', arg).
440  *
441  *  Note: This operation rounds the result and may set flags.
442  *  To copy without rounding or setting flags use the 'copy' function.
443  *
444  *  Standards: Implements the 'plus' function in the specification. (p. 33)
445  *
446  *  Flags: INVALID_OPERATION
447  */
448 public D plus(D)(in D num, Context context = D.context)
449     if (isDecimal!D)
450 {
451   if (num.isNaN) return invalidOperand(num);
452 //if (!__ctfe) writefln("num = %s", num);
453   return round(num, context);
454 }
455 
456 unittest
457 {  // plus -- depends on context
458   static struct S { TD num; TD expect; }
459   S[] s =
460   [
461     { "1.3", "1.3" },
462     { "101.5", "101.5" },
463     { "-101.5", "-101.5" },
464   ];
465   auto f = FunctionTest!(S,TD)("plus");
466   foreach (t; s) f.test(t, plus(t.num));
467   writefln(f.report);
468 }
469 
470 /**
471  *
472  *  Returns a copy of the argument with the opposite sign.
473  *  The result is equivalent to subtract('0', arg).
474  *
475  *  This operation rounds the argument and may set flags.
476  *  To copy without rounding or setting flags use the 'copyNegate' function.
477  *
478  *  Implements the 'minus' function in the specification. (p. 37)
479  *
480  *  Flags: INVALID_OPERATION
481  *
482  */
483 public D minus(D)(in D num, Context context = D.context)
484     if (isDecimal!D)
485 {
486   if (num.isNaN) return invalidOperand(num);
487   return round(num.copyNegate, context);
488 }
489 
490 unittest
491 {  // minus -- depends on context
492   static struct S { TD num; TD expect; }
493   S[] s =
494   [
495     { "1.3", "-1.3" },
496     { "101.5", "-101.5" },
497     { "-101.5", "101.5" },
498   ];
499   auto f = FunctionTest!(S,TD)("minus");
500   foreach (t; s) f.test(t, minus(t.num));
501   writefln(f.report);
502 }
503 
504 //-----------------------------------
505 // next-plus, next-minus, next-toward
506 //-----------------------------------
507 
508 /**
509  *
510  *  Returns the smallest representable number that is larger than
511  *  the argument.
512  *
513  *  Implements the 'next-plus' function in the specification. (p. 34)
514  *
515  *  Note that the overflow flag is not set by this operation.
516  *
517  *  Flags: INVALID_OPERATION
518  *
519  */
520 public D nextPlus(D)(in D num, Context context = D.context)
521   if (isDecimal!D)
522 {
523   if (num.isNaN) return invalidOperand(num);
524 
525   if (num.isInfinite) {
526     if (num.sign) {
527       return D.max.copyNegate;
528     }
529     else {
530       return num;
531     }
532   }
533   int adjustedExpo = num.expo + num.digits - context.precision;
534   if (adjustedExpo < D.tinyExpo) {
535       return D(0, D.tinyExpo, true);
536   }
537 
538   D increment = D(1, adjustedExpo);
539   D next = add(num, increment, context, false);
540   if (next > D.max) {
541     next = D.infinity;
542   }
543 
544   // FIXTHIS: need to pass setFlags value
545   return round(next);
546 }
547 
548 unittest
549 {  // nextPlus -- depends on context
550   static struct S { TD num; TD expect; }
551   S[] s =
552   [
553 /*    D99 tests
554     { "1",        "1.00000001" },
555     { "-1E-107",    "-0E-107" },
556     { "-1.00000003", "-1.00000002" },
557     { "-Infinity",   "-9.99999999E+99" },
558     { "9.99999999E+99",   "Infinity" },  // overflow flag should not be set!
559     { "1E+101",   "Infinity" },*/
560 
561     { "1",      "1.000000000000001" },
562     { "-1E-384",  "-0E-384" },
563     { "-1.000000000000003", "-1.000000000000002" },
564     { "-Infinity",  "-9.999999999999999E+369" },
565     { "9.999999999999999E+369",   "Infinity" },  // overflow flag should not be set!
566     { "1E+371",   "Infinity" },
567   ];
568   auto f = FunctionTest!(S,TD)("nextPlus");
569   foreach (t; s) f.test(t, nextPlus(t.num));
570   writefln(f.report);
571 }
572 
573 /**
574  *  Returns the largest representable number that is smaller than
575  *  the argument.
576  *
577  *  Standards: Implements the 'next-minus' function in the specification. (p. 34)
578  *
579  *  Flags: INVALID_OPERATION.
580  *
581  *  Note: The overflow flag is not set by this operation.
582  */
583 public D nextMinus(D)(in D num,  Context context = D.context)
584     if (isDecimal!D)
585 {
586   if (num.isNaN) return invalidOperand(num);
587 
588   if (num.isInfinite) {
589     return num.sign ? num : D.max;
590   }
591 
592   int adjustedExpo = num.expo + num.digits - context.precision;
593   if (num.coff == 1) adjustedExpo--;
594   if (adjustedExpo < D.tinyExpo) {
595     return D(0, D.tinyExpo);
596   }
597 
598   D increment = D(1, adjustedExpo);
599   D next = sub(num, increment, context);
600   if (next < D.max.copyNegate) {
601     next = D.infinity.copyNegate;
602   }
603   return next;
604 }
605 
606 unittest
607 {  // nextMinus -- depends on context
608   static struct S { TD num; TD expect; }
609   S[] s =
610   [
611     { "1",           "0.9999999999999999" },
612     { "1E-384",        "0E-384" },
613     { "-1.000000000000003",    "-1.000000000000004" },
614     { "Infinity",      "9.999999999999999E+369" },
615     { "-9.999999999999999E+368",  "-Infinity" },
616   ];
617   auto f = FunctionTest!(S,TD)("nextMinus");
618   foreach (t; s) f.test(t, nextMinus(t.num));
619   writefln(f.report);
620 }
621 
622 /**
623  *
624  *  Returns the representable number that is closest to the first operand
625  *  in the direction of the second operand.
626  *
627  *  Implements the 'next-toward' function in the specification. (p. 34-35)
628  *
629  *  Flags: INVALID_OPERATION
630  *
631  */
632 // TODO: anomalous flag settings
633 public D nextToward(D)(in D left, in D right,
634     Context context = D.context) if (isDecimal!D)
635 {
636 //     D nan;
637   if (left.isNaN || right.isNaN) return invalidOperand(left, right);
638 
639   // compare them but don't round yet
640   int comp = compare(left, right, context);
641   if (comp < 0) return nextPlus(left, context);
642   if (comp > 0) return nextMinus(left, context);
643 
644   return round(left.copySign(right), context);
645 }
646 
647 unittest
648 {  // nextToward -- depends on context
649   static struct S { TD left; TD right; TD expect; }
650   S[] s =
651   [
652 /*    { " 1",          "2", " 1.00000001" },
653     { "-1.00000003", "0", "-1.00000002" },*/
654   ];
655   auto f = FunctionTest!(S,TD)("nextToward");
656   foreach (t; s) f.test(t, nextToward(t.left, t.right));
657   writefln(f.report);
658 }
659 
660 //--------------------------------
661 // comparison functions
662 //--------------------------------
663 
664 /**
665  *  Compares two operands numerically to the current precision.
666  *
667  *  Note: The operands are rounded before they are compared.
668  *  This may result in unexpected results. For instance,
669  *  if both operands are too large (small) for the context
670  *  they will both be rounded to infinity (zero) and the function will
671  *  return 0, indicating that they are equal, even though they are
672  *  numerically different before rounding.
673  *
674  *  To compare numbers without rounding, use compareTotal.
675  *
676  *  Returns: -1, 0, or +1 if the second operand is, respectively,
677  *  less than, equal to, or greater than the first operand.
678  *
679  *  Standards: Implements the 'compare' function in the specification. (p. 27)
680  *
681  *  Flags: INVALID_OPERATION
682  *
683  */
684 public int compare(D)(in D left, in D right, Context context = D.context)
685     if (isDecimal!D)
686 {
687   // any operation with a signaling NaN is invalid.
688   // if both are signaling, return as if left > right.
689   if (left.isSignal || right.isSignal)
690   {
691     contextFlags.set(INVALID_OPERATION);
692     return left.isSignal ? 1 : -1;
693   }
694 
695   // if both are NaN, return as if left > right.
696   if (left.isNaN || right.isNaN)
697   {
698     return left.isNaN ? 1 : -1;
699   }
700 
701   // if either is zero...
702   if (left.isZero)
703   {
704     if (right.isZero) return 0;
705     return right.isNegative ? 1 : -1;
706   }
707   if (right.isZero)
708   {
709     return left.isNegative ? -1 : 1;
710   }
711 
712   // if signs differ, just compare the signs
713   if (left.sign != right.sign)
714   {
715     // check for zeros: +0 and -0 are equal
716     if (left.isZero && right.isZero) return 0;
717     return left.sign ? -1 : 1;
718   }
719 
720   // if either is infinite...
721   if (left.isInfinite || right.isInfinite)
722   {
723     if (left.isInfinite && right.isInfinite) return 0;
724     return left.isInfinite ? 1 : -1;
725   }
726 
727   D lf = left.dup;
728   D rt = right.dup;
729 
730   // TODO: (testing) test compare at precision limits.
731   // restrict operands to current precision
732   if (lf.digits > context.precision)
733   {
734     lf = round(lf, context);
735   }
736   if (rt.digits > context.precision)
737   {
738     rt = round(rt, context);
739   }
740 
741   // TODO: this will return inf == inf after rounding
742   // Check again for infinities
743   if (lf.isInfinite || rt.isInfinite)
744   {
745     if (lf.isInfinite && rt.isInfinite) return 0;
746     return lf.isInfinite ? 1 : -1;
747   }
748 
749   // compare the magnitudes of the numbers
750   lf = lf.reduce;
751   rt = rt.reduce;
752   int diff = (lf.expo + lf.digits) - (rt.expo + rt.digits);
753   if (diff != 0)
754   {
755     if (!lf.sign)
756     {
757       if (diff > 0) return 1;
758       if (diff < 0) return -1;
759     }
760     else
761     {
762       if (diff > 0) return -1;
763       if (diff < 0) return 1;
764     }
765   }
766   // align the operands
767   alignOps(lf, rt);  // both operands now have the same exponent
768 
769   // The only remaining difference is in the coefficients.
770   if (lf.coff == rt.coff) return 0;
771   return (lf.coff > rt.coff) ? 1 : -1;
772 }
773 
774 unittest
775 {  // compare -- depends on context?
776   static struct S { TD left; TD right; int expect; }
777   S[] s =
778   [
779     { " 3  ", " 2.1 ",  1 },
780     { "-3  ", " 2.1 ", -1 },
781     { " 2.1", "-3   ",  1 },
782     { " 2.1", " 2.1 ",  0 },
783     { " 2.1", " 2.10",  0 },
784     { " Inf", "-Inf ",  1 },
785     { " Inf", " Inf ",  0 },
786     { " Inf", " 12  ",  1 },
787     { "-Inf", " 12  ", -1 },
788   ];
789   auto f = FunctionTest!(S,int)("compare");
790   foreach (t; s) f.test(t, compare(t.left, t.right));
791   writefln(f.report);
792 }
793 
794 /**
795  *  Returns true if the operands are equal to the type precision.
796  *  Finite numbers are equal if they are numerically equal
797  *  to the type precision.
798  *  Infinities are equal if they have the same sign.
799  *  Zeros are equal regardless of sign.
800  *  A NaN is not equal to any number, not even another NaN.
801  *  In particular, a decimal NaN is not equal to itself (this != this).
802  *
803  *  Note: The operands are rounded before they are compared.
804  *  This may result in unexpected results. For instance,
805  *  if both operands are too large (small) for the context
806  *  they will both be rounded to infinity (zero) and the function will
807  *  return true, indicating that they are equal, even though they are
808  *  numerically different before rounding.
809  *
810  *  Flags: INVALID_OPERATION
811  */
812 public bool equals(D)(in D left, in D right, Context context = D.context)
813     if (isDecimal!D)
814 {
815   // any operation with a signaling NaN is invalid.
816   if (left.isSignal || right.isSignal)
817   {
818     contextFlags.set(INVALID_OPERATION);
819     return false;
820   }
821   // if either is NaN...
822   // NaN is never equal to any number, not even another NaN
823   if (left.isNaN || right.isNaN) return false;
824 
825   // if they are identical...
826   if (left is right) return true;
827 
828   // if either is zero...
829   if (left.isZero || right.isZero)
830   {
831     // ...they are equal if both are zero (regardless of sign)
832     return (left.isZero && right.isZero);
833   }
834 
835   // if their signs differ they are not equal (except for zero, handled above)
836   if (left.sign != right.sign) return false;
837 
838   // if either is infinite...
839   if (left.isInfinite || right.isInfinite) {
840     // ...they are equal only if both are infinite (with the same sign)
841     return (left.isInfinite && right.isInfinite);
842   }
843 
844   // if they have the same representation, they are equal
845   if (left.expo == right.expo && left.coff == right.coff)
846   {
847     return true;
848   }
849 
850   // round operands to the current precision
851   auto lf = round(left, context);
852   auto rt = round(right, context);
853 
854   // if they are not of the same magnitude they are not equal
855   if (lf.expo + lf.digits != rt.expo + rt.digits) return false;
856   // align the operands
857   alignOps(lf, rt);
858   // they are equal if their coefficients are equal
859   return lf.coff == rt.coff;
860 }
861 
862 unittest
863 {  // equals -- depends on context
864   static struct S { TD left; TD right; bool expect; }
865   S[] s =
866   [
867     { " 123.4567     ", " 123.4568   ", false},
868     { " 123.4567     ", " 123.4567   ", true },
869     { " 234123.4567121236 ", " 234123.45671212356", true }, // equals to precision
870     { " 1000000E-8   ", " 1E-2       ", true },
871     { "+100000000E-08", "+1E+00      ", true },
872     { "-1.00000000   ", "-1          ", true },
873   ];
874   auto f = FunctionTest!(S,bool)("equals");
875   foreach (t; s) f.test(t, equals(t.left, t.right));
876   writefln(f.report);
877 }
878 
879 /**
880  *  Returns true if the operands are equal to the specified precision. Special
881  *  values are handled as in the equals() function. This function allows
882  *  comparison at precision values other than the type precision.
883  */
884 public bool precisionEquals(D)(D left, D right, int precision) if (isDecimal!D)
885 {
886   auto context = Context(precision, D.maxExpo, D.mode);
887   return (equals(left, right, context));
888 }
889 
890 unittest
891 {  // precisionEquals -- depends on context
892   static struct S { TD left; TD right; int prec; bool expect; }
893   S[] s =
894   [
895 /*    { " 123.4567     ", " 123.4568   ", false},
896     { " 123.4567     ", " 123.4567   ", true },
897     { " 234123.4567121236 ", " 234123.45671212356", true }, // equals to precision
898     { " 1000000E-8   ", " 1E-2       ", true },
899     { "+100000000E-08", "+1E+00      ", true },
900     { "-1.00000000   ", "-1          ", true },*/
901   ];
902   auto f = FunctionTest!(S,bool)("precisionEquals");
903   foreach (t; s) f.test(t, precisionEquals(t.left, t.right, t.prec));
904   writefln(f.report);
905 }
906 /**
907  *  Compares the numeric values of two numbers. CompareSignal is identical to
908  *  compare except that quiet NaNs are treated as if they were signaling.
909  *  This operation may set the invalid-operation flag.
910  *  Implements the 'compare-signal' function in the specification. (p. 27)
911  *  Flags: INVALID_OPERATION
912  */
913 public int compareSignal(D) (in D left, in D right,
914     Context context = D.context) if (isDecimal!D)
915 {
916 
917   // any operation with NaN is invalid.
918   // if both are NaN, return as if left > right.
919   if (left.isNaN || right.isNaN) {
920     contextFlags.set(INVALID_OPERATION);
921     return left.isNaN ? 1 : -1;
922   }
923   return (compare!D(left, right, context));
924 }
925 
926 unittest
927 {  // compareSignal -- depends on context
928   static struct S { TD left; TD right; int expect; }
929   S[] s =
930   [
931 /*    { " 3  ", " 2.1 ",  1 },
932     { "-3  ", " 2.1 ", -1 },
933     { " 2.1", "-3   ",  1 },
934     { " 2.1", " 2.1 ",  0 },
935     { " 2.1", " 2.10",  0 },
936     { " Inf", "-Inf ",  1 },
937     { " Inf", " Inf ",  0 },
938     { " Inf", " 12  ",  1 },
939     { "-Inf", " 12  ", -1 },*/
940   ];
941   auto f = FunctionTest!(S,int)("compSignal");
942   foreach (t; s) f.test(t, compareSignal(t.left, t.right));
943   writefln(f.report);
944 }
945 
946 unittest
947 {
948   write("-- compareSignal....");
949   TD left, right;
950   int value;
951   left = 0;
952   right = 5;
953   assertGreaterThan(right,left);
954   contextFlags.resetFlags(INVALID_OPERATION);
955   right = TD.snan;
956   value = compare(left, right);
957   assertTrue(contextFlags.getFlags(INVALID_OPERATION));
958   contextFlags.resetFlags(INVALID_OPERATION);
959   right = TD.nan;
960   value = compare(left, right);
961   assertFalse(contextFlags.getFlags(INVALID_OPERATION));
962   contextFlags.set(INVALID_OPERATION, false);
963   right = TD.nan;
964   value = compareSignal(left, right);
965   assertTrue(contextFlags.getFlags(INVALID_OPERATION));
966   writeln("passed");
967 }
968 
969 
970 /**
971  *  Takes two numbers and compares the operands using their
972  *   abstract representation rather than their numerical value.
973  *  Numbers (representations which are not NaNs) are ordered such that
974  *  a larger numerical value is higher in the ordering.
975  *  If two representations have the same numerical value
976  *  then the exponent is taken into account;
977  *  larger (more positive) exponents are higher in the ordering.
978  *  Returns -1 If the first operand is lower in the total ordering
979  *  and returns 1 if the first operand is higher in the total ordering.
980  *  Returns 0 only if the numbers are equal and have the same representation.
981  *  Implements the 'compare-total' function in the specification. (p. 42-43)
982  *  Flags: NONE.
983  */
984 public int compareTotal(D)(in D left, in D right) if (isDecimal!D)
985 {
986   if (left.isFinite && right.isFinite
987     && left.sign == right.sign
988     && left.expo == right.expo
989     && left.coff == right.coff)
990   return 0;
991 
992   int ret1 =  1;
993   int ret2 = -1;
994 
995   // if signs differ...
996   if (left.sign != right.sign) {
997     return left.sign ? ret2 : ret1;
998   }
999 
1000   // if both numbers are signed swap the return values
1001   if (left.sign) {
1002     ret1 = -1;
1003     ret2 =  1;
1004   }
1005 
1006   // if either is zero...
1007   if (left.isZero || right.isZero) {
1008     // if both are zero compare exponents
1009     if (left.isZero && right.isZero) {
1010       auto result = left.expo - right.expo;
1011       if (result == 0) return 0;
1012       return (result > 0) ? ret1 : ret2;
1013     }
1014     return left.isZero ? ret1 : ret2;
1015   }
1016 
1017   // if either is infinite...
1018   if (left.isInfinite || right.isInfinite) {
1019     if (left.isInfinite && right.isInfinite) {
1020       return 0;
1021     }
1022     return left.isInfinite ? ret1 : ret2;
1023   }
1024 
1025   // if either is quiet...
1026   if (left.isQuiet || right.isQuiet) {
1027     // if both are quiet compare payloads.
1028     if (left.isQuiet && right.isQuiet) {
1029       auto result = left.coff - right.coff;
1030       if (result == 0) return 0;
1031       return (result > 0) ? ret1 : ret2;
1032     }
1033     return left.isQuiet ? ret1 : ret2;
1034   }
1035 
1036   // if either is signaling...
1037   if (left.isSignal || right.isSignal) {
1038     // if both are signaling compare payloads.
1039     if (left.isSignal && right.isSignal) {
1040       auto result = left.coff - right.coff;
1041       if (result == 0) return 0;
1042       return (result > 0) ? ret1 : ret2;
1043     }
1044     return left.isSignal ? ret1 : ret2;
1045   }
1046 
1047   // if both exponents are equal, any difference is in the coefficient
1048   if (left.expo == right.expo) {
1049     auto result = left.coff - right.coff;
1050     if (left.coff == right.coff) return 0;
1051     return (left.coff > right.coff) ? ret1 : ret2;
1052   }
1053 
1054   // if the (finite) numbers have different magnitudes...
1055   int diff = (left.expo + left.digits) - (right.expo + right.digits);
1056   if (diff > 0) return ret1;
1057   if (diff < 0) return ret2;
1058 
1059   // we know the numbers have the same magnitude
1060   // and that the exponents are not equal -- align the operands
1061    D lf = left.dup;
1062   D rt = right.dup;
1063   alignOps(lf, rt);  // the operands now have the same exponent.
1064 
1065   // if equal after alignment, compare the original exponents
1066   if (lf.coff == rt.coff) {
1067     return (left.expo > right.expo) ? ret1 : ret2;
1068   }
1069   // otherwise return the numerically larger
1070   return (lf.coff > rt.coff) ? ret2 : ret1;
1071 }
1072 
1073 unittest
1074 {  // compareTotal
1075   static struct S { TD left; TD right; int expect; }
1076   S[] s =
1077   [
1078     { " 12.30", " 12.3  ", -1},
1079     { " 12.30", " 12.30 ",  0},
1080     { " 12.3 ", " 12.300",  1},
1081   ];
1082   auto f = FunctionTest!(S,int)("compTotal");
1083   foreach (t; s) f.test(t, compareTotal(t.left, t.right));
1084   writefln(f.report);
1085 }
1086 
1087 /**
1088  *  compare-total-magnitude takes two numbers and compares them
1089  *  using their abstract representation rather than their numerical value
1090  *  with their sign ignored and assumed to be 0.
1091  *  The result is identical to that obtained by using compare-total
1092  *  on two operands which are the copy-abs copies of the operands.
1093  *  Implements the 'compare-total-magnitude' function in the specification.
1094  *  (p. 43)
1095  *  Flags: NONE.
1096  */
1097 int compareTotalMagnitude(D)(D left, D right) if (isDecimal!D)
1098 {
1099   return compareTotal(left.copyAbs, right.copyAbs);
1100 }
1101 
1102 /**
1103  *  Returns true if the numbers have the same exponent.
1104  *  If either operand is NaN or Infinity, returns true if and only if
1105  *  both operands are NaN or Infinity, respectively.
1106  *  Flags: NONE
1107  *
1108  * Standards: Implements the 'same-quantum' function in the specification. (p. 48)
1109  */
1110 public bool sameQuantum(D)(in D left, in D right) if (isDecimal!D)
1111 {
1112   if (left.isNaN || right.isNaN)
1113   {
1114     return left.isNaN && right.isNaN;
1115   }
1116   if (left.isInfinite || right.isInfinite)
1117   {
1118     return left.isInfinite && right.isInfinite;
1119   }
1120   return left.expo == right.expo;
1121 }
1122 
1123 unittest
1124 {  // sameQuantum
1125   static struct S { TD left; TD right; bool expect; }
1126   S[] s =
1127   [
1128     { "2.17", "0.001", false },
1129     { "2.17", "0.01 ", true },
1130     { "2.17", "0.1  ", false },
1131   ];
1132   auto f = FunctionTest!(S,bool)("sameQuant");
1133   foreach (t; s) f.test(t, sameQuantum(t.left, t.right));
1134   writefln(f.report);
1135 }
1136 
1137 /**
1138  *  Returns the maximum of the two operands (or NaN).
1139  *
1140  *  If either is a signaling NaN, or both are quiet NaNs, a NaN is returned.
1141  *  Otherwise, any finite or infinite number is larger than a NaN.
1142  *
1143  *  If they are not numerically equal, the larger is returned.
1144  *  If they are numerically equal:
1145  *  1. If the signs differ, the one with the positive sign is returned.
1146  *  2. If they are positive, the one with the larger exponent is returned.
1147  *  3. If they are negative, the one with the smaller exponent is returned.
1148  *  4. Otherwise, they are indistinguishable; the first is returned.
1149  *  The returned number will be rounded to the current context.
1150  *  Implements the 'max' function in the specification. (p. 32)
1151  *  Flags: INVALID_OPERATION, ROUNDED.
1152  *
1153  */
1154 public D max(D)(in D left, in D right,  Context context = D.context)
1155   if (isDecimal!D)
1156 {
1157   // if both are NaNs or either is an sNan, return NaN.
1158   if (left.isNaN && right.isNaN || left.isSignal || right.isSignal) {
1159     contextFlags.set(INVALID_OPERATION);
1160     return D.nan;
1161   }
1162   // if both are infinite, return the one with a positive sign
1163   if (left.isInfinite && right.isInfinite) {
1164     return left.isNegative ? right.dup : left.dup;
1165   }
1166 
1167   // result will be a finite number or infinity
1168   // use left as default value
1169   D result = left.dup;
1170 
1171   // if one op is a quiet NaN return the other
1172   if (left.isQuiet || right.isQuiet) {
1173     if (left.isQuiet) result = right;
1174   }
1175   // if the signs differ, return the unsigned operand
1176   else if (left.sign != right.sign) {
1177     if (left.sign) result = right;
1178   }
1179   else {
1180     // if not numerically equal, return the larger
1181     int comp = compare!D(left, right, context);
1182     if (comp != 0) {
1183       if (comp < 0) result = right;
1184     }
1185     // if they have the same exponent they are identical, return either
1186     else if (left.expo == right.expo) {
1187       // no assignment -- use default value
1188     }
1189     // if they are non-negative, return the one with larger exponent.
1190     else if (left.sign == 0) {
1191       if (left.expo < right.expo) result = right;
1192     }
1193     else {
1194       // they are negative; return the one with smaller exponent.
1195       if (left.expo > right.expo) result = right;
1196     }
1197   }
1198   // result must be rounded
1199   return round(result, context);
1200 }
1201 
1202 unittest
1203 {  // max -- depends on context
1204   static struct S { TD left; TD right; TD expect; }
1205   S[] s =
1206   [
1207     {   3, 2, 3 },
1208     { -10, 3, 3 },
1209   ];
1210   auto f = FunctionTest!(S,TD)("max");
1211   foreach (t; s) f.test(t, max(t.left, t.right));
1212   writefln(f.report);
1213 }
1214 
1215 /// Returns the larger of the two operands (or NaN). Returns the same result
1216 /// as the 'max' function if the signs of the operands are ignored.
1217 /// Implements the 'max-magnitude' function in the specification. (p. 32)
1218 /// Flags: NONE.
1219 public D maxMagnitude(D)(in D left, in D right,
1220     Context context = D.context) if (isDecimal!D)
1221 {
1222   if (left.copyAbs > right.copyAbs)
1223   {
1224     return round(left, context);
1225   }
1226   else
1227   {
1228     return round(right, context);
1229   }
1230 }
1231 
1232 unittest
1233 {  // maxMagnitude -- depends on context
1234   static struct S { TD left; TD right; TD expect; }
1235   S[] s =
1236   [
1237     {   -1, -2, -2 },
1238     {    1, -2, -2 },
1239     {    1,  2,  2 },
1240     {   -1,  2,  2 },
1241   ];
1242   auto f = FunctionTest!(S,TD)("maxMag");
1243   foreach (t; s) f.test(t, maxMagnitude(t.left, t.right));
1244   writefln(f.report);
1245 }
1246 
1247 /// Returns the minimum of the two operands (or NaN).
1248 /// If either is a signaling NaN, or both are quiet NaNs, a NaN is returned.
1249 /// Otherwise, Any (finite or infinite) number is smaller than a NaN.
1250 /// If they are not numerically equal, the smaller is returned.
1251 /// If they are numerically equal:
1252 /// 1. If the signs differ, the one with the negative sign is returned.
1253 /// 2. If they are negative, the one with the larger exponent is returned.
1254 /// 3. If they are positive, the one with the smaller exponent is returned.
1255 /// 4. Otherwise, they are indistinguishable; the first is returned.
1256 /// Implements the 'min' function in the specification. (p. 32-33)
1257 /// Flags: INVALID_OPERATION, ROUNDED.
1258 public D min(D)(in D left, in D right,
1259     Context context = D.context) if (isDecimal!D)
1260 {
1261   // if both are NaNs or either is an sNan, return NaN.
1262   if (left.isNaN && right.isNaN || left.isSignal || right.isSignal) {
1263     contextFlags.set(INVALID_OPERATION);
1264     return D.nan;
1265   }
1266   // if both are infinite, return the one with a negative sign
1267   if (left.isInfinite && right.isInfinite) {
1268     return left.isNegative ? left.dup : right.dup;
1269   }
1270   // result will be a finite number or infinity
1271   D min;
1272 
1273   // if one op is a quiet NaN return the other
1274   if (left.isQuiet || right.isQuiet) {
1275     min = left.isQuiet? right : left;
1276   }
1277     // if the signs differ, return the negative operand
1278   else if (left.sign != right.sign) {
1279     min = left.sign ? left : right;
1280   }
1281   // if not numerically equal, return the lesser
1282   else {
1283     int comp = compare(left, right, context);
1284     if (comp != 0) {
1285       min = comp > 0 ? right : left;
1286     }
1287     // if they have the same exponent they are identical, return either
1288     else if (left.expo == right.expo) {
1289       min = left;
1290     }
1291     // if they are non-negative, return the one with smaller exponent.
1292     else if (left.sign == 0) {
1293       min = left.expo > right.expo ? right : left;
1294     }
1295     // else they are negative; return the one with larger exponent.
1296     else {
1297       min = left.expo > right.expo ? right : left;
1298     }
1299   }
1300   // min must be rounded
1301   return round(min, context);
1302 }
1303 
1304 unittest
1305 {  // min -- depends on context
1306   static struct S { TD left; TD right; TD expect; }
1307   S[] s =
1308   [
1309     {   3, 2,   2 },
1310     { -10, 3, -10 },
1311   ];
1312   auto f = FunctionTest!(S,TD)("min");
1313   foreach (t; s) f.test(t, min(t.left, t.right));
1314   writefln(f.report);
1315 }
1316 
1317 /// Returns the smaller of the two operands (or NaN). Returns the same result
1318 /// as the 'min' function if the signs of the operands are ignored.
1319 /// Implements the 'min-magnitude' function in the specification. (p. 33)
1320 /// Flags: INVALID_OPERATION, ROUNDED.
1321 public D minMagnitude(D)(in D left, in D right,
1322     Context context = D.context) if (isDecimal!D)
1323 {
1324   if (left.copyAbs < right.copyAbs)
1325   {
1326     return round(left, context);
1327   }
1328   else
1329   {
1330     return round(right, context);
1331   }
1332 /*  // one of each
1333   if (left.copyAbs > right.copyAbs) {
1334     return round(right, context);
1335   }
1336   return round(left, context);*/
1337 }
1338 
1339 unittest
1340 {  // minMagnitude -- depends on context
1341   static struct S { TD left; TD right; TD expect; }
1342   S[] s =
1343   [
1344     {   -1, -2, -1 },
1345     {    1, -2,  1 },
1346     {    1,  2,  1 },
1347     {   -1,  2, -1 },
1348   ];
1349   auto f = FunctionTest!(S,TD)("minMag");
1350   foreach (t; s) f.test(t, minMagnitude(t.left, t.right));
1351   writefln(f.report);
1352 }
1353 
1354 /// Returns a number with a coefficient of 1 and
1355 /// the same exponent as the argument.
1356 /// Flags: NONE.
1357 public D quantum(D)(in D x)  {
1358   return D(1, x.expo);
1359 }
1360 
1361 unittest
1362 {  // quantum
1363   static struct S { TD x; TD expect; }
1364   S[] s =
1365   [
1366     { "23.14E-12", "1E-14" },
1367   ];
1368   auto f = FunctionTest!(S,TD)("quantum");
1369   foreach (t; s) f.test(t, quantum(t.x));
1370   writefln(f.report);
1371 }
1372 
1373 //--------------------------------
1374 // decimal shift and rotate
1375 //--------------------------------
1376 
1377 /// Shifts the first operand by the specified number of DECIMAL digits.
1378 /// (NOT BINARY digits!) Positive values of the second operand shift the
1379 /// first operand left (multiplying by tens). Negative values shift right
1380 /// (dividing by tens). If the number is NaN, or if the shift value is less
1381 /// than -precision or greater than precision, an INVALID_OPERATION is signaled.
1382 /// An infinite number is returned unchanged.
1383 /// Implements the 'shift' function in the specification. (p. 49)
1384 public D shift(D, U=D)(in D x, in D y,
1385     Context context = D.context) if (isDecimal!D)
1386 {
1387   // check for NaN
1388   if (x.isNaN || y.isNaN) return invalidOperand(x, y);
1389   if (y.expo != 0) return invalidOperand(y);
1390   if (y.coff > context.precision ||
1391     y.coff < -context.precision) return invalidOperand(y);
1392   int n = y.coff.toInt;
1393   if (y.sign) n = -n;
1394   return shift(x, n, context);
1395 }
1396 
1397 /// Shifts the first operand by the specified number of DECIMAL digits.
1398 /// (NOT BINARY digits!) Positive values of the second operand shift the
1399 /// first operand left (multiplying by tens). Negative values shift right
1400 /// (dividing by tens). If the first operand is NaN, or if the shift value is less
1401 /// than -precision or greater than precision, an INVALID_OPERATION is signaled.
1402 /// An infinite number is returned unchanged.
1403 /// Implements the 'shift' function in the specification. (p. 49)
1404 public D shift(D, U:int)(in D arg, U n,
1405     Context context = D.context) if (isDecimal!D)
1406 {
1407 
1408   // check for NaN
1409   if (arg.isNaN) return invalidOperand(arg);
1410 
1411   // shift by zero returns the argument
1412   if (n == 0) return arg.dup;
1413 
1414   // shift of an infinite number returns the argument
1415   if (arg.isInfinite) return arg.dup;
1416 
1417   int precision = context.precision;
1418 
1419   // shifting by more than precision is invalid.
1420   if (n < -precision || n > precision)
1421   {
1422     return invalidOperation!D;
1423   }
1424 
1425   auto copy = arg.dup;
1426 
1427   if (n > 0)
1428   {
1429     // shift left
1430     copy.coff = copy.coff * pow10b(n);
1431     copy.digits = countDigits(copy.coff);
1432     if (copy.digits > context.precision)
1433     {
1434       copy.coff = copy.coff % pow10b(precision);
1435       copy.digits = precision;
1436     }
1437   }
1438   else
1439   {
1440     // shift right
1441     copy.coff = copy.coff / pow10b(-n);
1442     copy.digits = countDigits(copy.coff);
1443   }
1444   return copy;
1445 }
1446 
1447 unittest
1448 {  // shift  -- depends on context
1449   static struct S { TD x; TD y; TD expect; }
1450   S[] s =
1451   [
1452 // 9 digit data
1453 /*    { 34, 8, 400000000 },
1454     { 12, 9, 0 },
1455     { 123456789, -2, 1234567 },
1456     { 123456789,  0, 123456789 },
1457     { 123456789,  2, 345678900 },*/
1458     { 34, 8, 3400000000 },
1459     { 12, 9, 12000000000 },
1460     { 123456789, -2, 1234567 },
1461     { 123456789,  0, 123456789 },
1462     { 123456789,  2, 12345678900 },
1463   ];
1464   auto f = FunctionTest!(S,TD)("shift");
1465   foreach (t; s) f.test(t, shift(t.x, t.y));
1466   writefln(f.report);
1467 }
1468 
1469 /// Rotates the first operand by the specified number of decimal digits.
1470 /// (Not binary digits!) Positive values of the second operand rotate the
1471 /// first operand left (multiplying by tens). Negative values rotate right
1472 /// (divide by 10s). If the number is NaN, or if the rotate value is less
1473 /// than -precision or greater than precision, an INVALID_OPERATION is signaled.
1474 /// An infinite number is returned unchanged.
1475 /// Implements the 'rotate' function in the specification. (p. 47-48)
1476 public D rotate(D, U=D)(in D x, in U y,
1477     Context context = D.context) if (isDecimal!D)
1478 {
1479   if (x.isNaN) return invalidOperand(x);
1480   if (y.isNaN) return invalidOperand(y);
1481   if (y.expo != 0) return invalidOperand(y);
1482   if (y.coff > context.precision ||
1483     y.coff < -context.precision) return invalidOperand(y);
1484   int n = y.coff.toInt;
1485   if (y.sign) n = -n;
1486   return rotate(x, n, context);
1487 }
1488 
1489 // Rotates the first operand by the specified number of decimal digits.
1490 /// (Not binary digits!) Positive values of the second operand rotate the
1491 /// first operand left (multiplying by tens). Negative values rotate right
1492 /// (divide by 10s). If the number is NaN, or if the rotate value is less
1493 /// than -precision or greater than precision, an INVALID_OPERATION is signaled.
1494 /// An infinite number is returned unchanged.
1495 /// Implements the 'rotate' function in the specification. (p. 47-48)
1496 public D rotate(D, U:int)(in D arg, U n,
1497     Context context = D.context) if (isDecimal!D)
1498 {
1499 
1500   // check for NaN
1501   if (arg.isNaN) return invalidOperand(arg);
1502 
1503   // shift by zero returns the argument
1504   if (n == 0) return arg.dup;
1505 
1506   // shift of an infinite number returns the argument
1507   if (arg.isInfinite) return arg.dup;
1508 
1509   int precision = context.precision;
1510 
1511   // shifting by more than precision is invalid.
1512   if (n < -precision || n > precision) {
1513     return invalidOperation!D;
1514   }
1515 
1516   auto copy = arg.dup;
1517 
1518   // TODO: test this
1519   // if coefficient is longer than the precision truncate leading digits
1520   if (copy.digits > precision)
1521   {
1522     copy.coff = copy.coff % pow10b(precision);
1523   }
1524 
1525   if (n > 0) {
1526     // rotate left
1527     copy.coff = copy.coff * pow10b(n);
1528     copy.digits = countDigits(copy.coff);
1529     if (copy.digits > context.precision) {
1530       BigInt divisor = pow10b(precision);
1531       BigInt mod, div;
1532       divMod(copy.coff, divisor, div, mod);
1533       copy.coff = div + mod;
1534       copy.digits = countDigits(copy.coff);
1535     }
1536   }
1537   else {
1538     // rotate right
1539     n = -n;
1540     BigInt divisor = pow10b(n);
1541     BigInt mod, div;
1542     divMod(copy.coff, divisor, div, mod);
1543     copy.coff = mod * pow10b(precision - n) + div;
1544     copy.digits = countDigits(copy.coff);
1545   }
1546   return copy;
1547 }
1548 
1549 unittest
1550 {  // rotate -- depends on context
1551   static struct S { TD x; TD y; TD expect; }
1552   S[] s =
1553   [
1554 /*    { 34, 8, 400000003 },
1555     { 12, 9, 12 },
1556     { 123456789,   2, 345678912 },
1557     { 123456789,   0, 123456789 },
1558     { 123456789,  -2, 891234567 },
1559     { 123456789,  -5, 567891234 },
1560     { 1234567890, -2, 902345678 },
1561     { 912345678900000, 2, 890000067 },
1562     { 123000456789,  2, 45678900 },
1563     { 123000456789, -2, 890004567 },*/
1564     { 34, 15, 4000000000000003 },
1565     { 12, 16, 12 },
1566     { 1234567890123456,   2, 3456789012345612 },
1567     { 1234567890123456,   0, 1234567890123456 },
1568     { 1234567890123456,  -2, 5612345678901234 },
1569     { 1234567890123456,  -5, 2345612345678901 },
1570     { 1234567890,        -2, 9000000012345678 },
1571     { 8912345678900000,   2, 1234567890000089 },
1572     { 1230004567891234,   2, 3000456789123412 },
1573     { 123000456789,      -2, 8900001230004567 },
1574   ];
1575   auto f = FunctionTest!(S,TD)("rotate");
1576   foreach (t; s) f.test(t, rotate(t.x, t.y));
1577   writefln(f.report);
1578 }
1579 
1580 //------------------------------------------
1581 // binary arithmetic operations
1582 //------------------------------------------
1583 
1584 /// Adds the two operands.
1585 /// The result may be rounded and context flags may be set.
1586 /// Implements the 'add' function in the specification. (p. 26)
1587 /// Flags: INVALID_OPERATION, OVERFLOW.
1588 public D add(D)(in D left, in D right,
1589     Context context = D.context, bool setFlags = true) if (isDecimal!D)
1590 {
1591   if (left.isNaN || right.isNaN) return invalidOperand(left, right);
1592 
1593   // if both operands are infinite...
1594   if (left.isInfinite && right.isInfinite) {
1595     // if the signs differ return NaN and set invalid operation flag
1596     if (left.sign != right.sign) {
1597       return invalidOperation!D;
1598     }
1599     // both infinite with same sign, return the first
1600     return left.dup;
1601   }
1602   // if only the first is infinite, return it
1603   if (left.isInfinite) {
1604     return left.dup;
1605   }
1606   // if only the second is infinite, return it
1607   if (right.isInfinite) {
1608     return right.dup;
1609   }
1610 
1611   D sum = D.zero;
1612   // add(0, 0)
1613   if (left.isZero && right.isZero) {
1614     sum = left;
1615     // the exponent is the smaller of the two exponents
1616     sum.expo = std.algorithm.min(left.expo, right.expo);
1617     // the sign is the logical AND of the two signs
1618     sum.sign = left.sign && right.sign;
1619     return sum;
1620   }
1621   // add(0,f)
1622   if (left.isZero) return right.dup;
1623   // add(f,0)
1624   if (right.isZero) return left.dup;
1625 
1626   // sum is finite and not zero.
1627   auto lf = left.dup;
1628   auto rt = right.dup;
1629   // align the operands
1630   alignOps(lf, rt);
1631   // if the operands have the same sign add the aligned coefficients
1632   if (lf.sign == rt.sign) {
1633     sum.coff = lf.coff + rt.coff;
1634     sum.sign = lf.sign;
1635   }
1636   // otherwise subtract the lesser from the greater
1637   else {
1638     if (lf.coff >= rt.coff) {
1639       sum.coff = lf.coff - rt.coff;
1640       sum.sign = lf.sign;
1641     }
1642     else {
1643       sum.coff = rt.coff - lf.coff;
1644       sum.sign = rt.sign;
1645     }
1646   }
1647   sum.digits = countDigits(sum.coff);
1648   sum.expo = lf.expo;
1649   // round the result
1650   return round(sum, context, setFlags);
1651 }
1652 
1653 
1654 /// Adds the two operands.
1655 /// The result may be rounded and context flags may be set.
1656 /// Implements the 'add' function in the specification. (p. 26)
1657 /// Flags: INVALID_OPERATION, OVERFLOW.
1658 public D add(D, U)(in D left, in U right,
1659     Context context = D.context, bool setFlags = true)
1660     if (isDecimal!D && isConvertible!U)
1661 {
1662   return add(left, D(right), context, setFlags);
1663 }
1664 
1665 unittest
1666 {  // add -- depends on context
1667   static struct S { TD x; TD y; TD expect; }
1668   S[] s =
1669   [
1670     { "12", "7.00", "19.00" },
1671     { "1E+2", "1E+4", "1.01E+4" },
1672     { "1234567890123456789", "5432109876543210987", "6.666677766666668E+18" },
1673     { "1.3", "-2.07", "-0.77" },
1674 //    { "1.3", "2.07", "-0.77" }, // uncomment to test failure
1675   ];
1676   auto f = FunctionTest!(S,TD)("add");
1677   foreach (t; s) f.test(t, add(t.x, t.y));
1678   writefln(f.report);
1679 }
1680 
1681 /// Subtracts the second operand from the first operand.
1682 /// The result may be rounded and context flags may be set.
1683 /// Implements the 'subtract' function in the specification. (p. 26)
1684 public D sub(D, U:D) (in D left, in U right,
1685     Context context = D.context, bool setFlags = true)
1686   if (isDecimal!D)
1687 {
1688   return add(left, right.copyNegate, context, setFlags);
1689 }   // end sub(left, right)
1690 
1691 
1692 /// Subtracts the second operand from the first operand.
1693 /// The result may be rounded and context flags may be set.
1694 /// Implements the 'subtract' function in the specification. (p. 26)
1695 public D sub(D, U)(in D x, U y,
1696     Context context = D.context, bool setFlags = true)
1697     if (isDecimal!D && isConvertible!U)
1698 {
1699   return add(x, D(y).copyNegate, context, setFlags);
1700 }  // end sub(x, y)
1701 
1702 unittest
1703 {  // sub -- depends on context
1704   static struct S { TD x; TD y; TD expect; }
1705   S[] s =
1706   [
1707     { "1.3", "1.07", "0.23" },
1708     { "1.3", "1.30", "0.00" },
1709     { "1.3", "2.07", "-0.77" },
1710 //    { "1.3", "2.07", "0.77" },  // uncomment to test failure
1711   ];
1712   auto f = FunctionTest!(S,TD)("sub");
1713   foreach (t; s) f.test(t, sub(t.x, t.y));
1714   writefln(f.report);
1715 }
1716 
1717 ///
1718 /// Multiplies the two operands.
1719 /// The result may be rounded and context flags may be set.
1720 /// Implements the 'multiply' function in the specification. (p. 33-34)
1721 public D mul(D)(in D x, in D y, Context context = D.context)
1722     if (isDecimal!D)
1723 //public D mul(D)(in D x, in D y,
1724 //    Context context = D.context) if (isDecimal!D)
1725 {
1726   // if invalid, return NaN
1727   if (x.isNaN || y.isNaN) return invalidOperand(x,y);
1728 
1729   // infinity * zero => invalid operation
1730   if (x.isZero && y.isInfinite || x.isInfinite && y.isZero) {
1731     return invalidOperand(x,y);
1732   }
1733   // if either operand is infinite, return infinity
1734   if (x.isInfinite || y.isInfinite) {
1735     return D.infinity(x.sign ^ y.sign);
1736   }
1737 
1738   // mul(0,f) or (f,0)
1739   if (x.isZero || y.isZero) {
1740     D z = D.zero;
1741     // TODO: (behavior) is the exponent really the sum of the operand exponents? (how about just use the larger?
1742     z.expo = std.algorithm.min(D.maxExpo, x.expo + y.expo);
1743     z.sign = x.sign ^ y.sign;
1744     return (z);
1745   }
1746 
1747   // at this point the product is a finite, non-zero number
1748   D product = D.zero.dup;
1749   product.coff = x.coff * y.coff;
1750   product.expo = std.algorithm.min(D.maxExpo, x.expo + y.expo);
1751   product.sign = x.sign ^ y.sign;
1752   product.digits = countDigits(product.coff);
1753 
1754   return round(product, context);
1755 }
1756 
1757 /// Multiplies a decimal number by a long integer.
1758 /// The result may be rounded and context flags may be set.
1759 /// Not a required function, but useful because it avoids
1760 /// an unnecessary conversion to a decimal when multiplying by an integer.
1761 public D mul(D, U : long)(in D x, in U n, Context context = D.context)
1762 //    if (isDecimal!D && isIntegral!U)
1763 //public D mul(D)(in D x, long n, Context context = D.context)
1764     if (isDecimal!D)
1765 {
1766   // if invalid, return NaN
1767   if (x.isNaN) return invalidOperand(x);
1768 
1769   // infinity * zero => invalid operation
1770   if (x.isInfinite && n == 0) {
1771     return invalidOperand(x);
1772   }
1773   // if decimal operand is infinite, return infinity
1774   if (x.isInfinite) {
1775     return D.infinity(x.sign ^ (n < 0));
1776   }
1777 
1778   // mul(0,f) or (f,0)
1779   if (x.isZero || n == 0) {
1780     D z = D.zero;
1781     z.expo = x.expo;
1782     z.sign = x.sign ^ (n < 0);
1783     return (z);
1784   }
1785 
1786   // at this point the product is a finite, non-zero number
1787   D product = D.zero;
1788   product.coff = x.coff * n;
1789   product.expo = x.expo;
1790   product.sign = x.sign ^ (n < 0);
1791   product.digits = countDigits(product.coff);
1792   return round(product, context);
1793 }  // end mul(x, n)
1794 
1795 /// Multiplies the two operands.
1796 /// The result may be rounded and context flags may be set.
1797 /// Implements the 'multiply' function in the specification. (p. 33-34)
1798 public D mul(D, U)(in D x, in U y, Context context = D.context)
1799     if (isDecimal!D && isConvertible!U)
1800 {
1801   return mul(x, D(y), context);
1802 }  // end mul(x, y)
1803 
1804 unittest
1805 {  // mul -- depends on context
1806   static struct S { TD x; TD y; TD expect; }
1807   S[] s =
1808   [
1809     { "1.20", "3", "3.60" },
1810 //    { "1.20", "3", "3.61" },  // uncomment to test failure
1811     { "7", "3", "21" },
1812     { "-7000", "3", "-21000" },
1813     { "Infinity", "3", "Infinity" },
1814   ];
1815   auto f = FunctionTest!(S,TD)("mul");
1816   foreach (t; s) f.test(t, mul(t.x, t.y));
1817   writefln(f.report);
1818 }
1819 
1820 /// Squares the argument and returns the result.
1821 /// The result may be rounded and context flags may be set.
1822 public D sqr(D)(in D arg, Context context = D.context) if (isDecimal!D)
1823 {
1824   // if operand is invalid, return NaN
1825   if (arg.isNaN) {
1826     return invalidOperand(arg);
1827   }
1828   // if operand is infinite, return infinity
1829   if (arg.isInfinite) {
1830     return D.infinity;
1831   }
1832   // if operand is zero, return zero
1833   if (arg.isZero) {
1834     return D.zero;
1835   }
1836 
1837   // product is non-zero
1838   D copy = arg.copy;
1839   copy.coff = copy.coff * copy.coff;
1840 // TODO : why does this fail ("not an lvalue")
1841 //  copy.expo *= 2; //copy.expo * 2;
1842   copy.expo = 2 * copy.expo;
1843   copy.sign = false;
1844   copy.digits = countDigits(copy.coff);
1845   return round(copy, context);
1846 }
1847 
1848 unittest
1849 {  // sqr -- depends on context
1850   static struct S { TD x; TD expect; }
1851   S[] s =
1852   [
1853     { "-Inf", "Inf" },
1854     { "101.5", "10302.25" },
1855     { "-101.5", "10302.25" },
1856 /*    { "-1.23456789012E+23", "1.52415788E+46" },
1857     { "0.8535533905932737622000", "0.728553391" },*/
1858     { "-1.23456789012E+23", "1.524157875315348E+46" },
1859     { "0.8535533905932737622000", "0.7285533905932738" },
1860   ];
1861   auto f = FunctionTest!(S,TD)("sqr");
1862   foreach (t; s) f.test(t, sqr(t.x));
1863   writefln(f.report);
1864 }
1865 
1866 //TODO: need to test high-precision numbers. Requires
1867 // a test with a high-precision context.
1868 unittest
1869 {  // sqr -- depends on context
1870 }
1871 
1872 
1873 /// Multiplies the first two operands and adds the third operand to the result.
1874 /// The result of the multiplication is not rounded prior to addition.
1875 /// The result may be rounded and context flags may be set.
1876 /// Implements the 'fused-multiply-add' function in the specification. (p. 30)
1877 public D fma(D)(in D x, in D y, in D z,
1878     Context context = D.context) if (isDecimal!D)
1879 {
1880   D xy = mul(x, y, Context(context.precision, D.maxExpo, ROUND_NONE));
1881   return add(xy, z, context);
1882 }
1883 
1884 unittest
1885 {  // fma -- depends on context
1886   static struct S { TD x; TD y; TD z; TD expect; }
1887   S[] s =
1888   [
1889     { 3,  5, 7, 22 },
1890     { 3, -5, 7, -8 },
1891 /*    { "888565290", "1557.96930", "-86087.7578", "1.38435736E+12" },
1892     { 888565290, 1557.96930, -86087.7578, 1.38435736E+12 },*/
1893     { "888565290", "1557.96930", "-86087.7578", "1384357356777.839" },
1894     { 888565290, 1557.96930, -86087.7578, "1384357356777.839" },
1895   ];
1896   auto f = FunctionTest!(S,TD)("fma");
1897   foreach (t; s) f.test(t, fma(t.x, t.y, t.z));
1898   writefln(f.report);
1899 }
1900 
1901 /// Divides the first operand by the second operand and returns their quotient.
1902 /// Division by zero sets a flag and returns infinity.
1903 /// The result may be rounded and context flags may be set.
1904 /// Implements the 'divide' function in the specification. (p. 27-29)
1905 public D div(D)(in D x, in D y,
1906     Context context = D.context) if (isDecimal!D)
1907 {
1908   // check for NaN and division by zero
1909   if (x.isNaN || y.isNaN) return invalidOperand(x, y);
1910   if (y.isZero) return divisionByZero(x, y);
1911 
1912   // copy the arguments
1913   auto dvnd = x.dup;
1914   auto dvsr = y.dup;
1915   auto quo = D.zero;
1916 
1917   int diff = dvnd.expo - dvsr.expo;
1918   if (diff > 0) {
1919     dvnd.coff = shiftBig(dvnd.coff, diff);
1920     dvnd.expo = dvnd.expo - diff;
1921     dvnd.digits = dvnd.digits + diff;
1922   }
1923   int shift = 4 + context.precision + cast(int)dvsr.digits - cast(int)dvnd.digits;
1924   if (shift > 0) {
1925     dvnd.coff = shiftBig(dvnd.coff, shift);
1926     dvnd.expo = dvnd.expo - shift;
1927     dvnd.digits = dvnd.digits + shift;
1928   }
1929   // the divisor may have become zero. Check again.
1930   if (dvsr.isZero)
1931     return divisionByZero(x, y);
1932   quo.coff = dvnd.coff / dvsr.coff;
1933   quo.expo = dvnd.expo - dvsr.expo;
1934   quo.sign = dvnd.sign ^ dvsr.sign;
1935   quo.digits = countDigits(quo.coff);
1936   quo = round(quo, context);
1937   // TODO: what's up with this? revisit
1938   quo = reduceToIdeal(quo, diff);
1939   return quo;
1940 }
1941 
1942 /// Divides the first operand by the second operand and returns their quotient.
1943 /// Division by zero sets a flag and returns infinity.
1944 /// The result may be rounded and context flags may be set.
1945 /// Implements the 'divide' function in the specification. (p. 27-29)
1946 public D div(D, U : long)(in D x, in U n,
1947     Context context = D.context) if (isDecimal!D)
1948 {
1949   // check for NaN and division by zero
1950   if (x.isNaN) return invalidOperand(x);
1951   if (n == 0) return divisionByZero(x, n);
1952 
1953   auto dvnd = x.dup;
1954   auto quo = D.zero;
1955 
1956   int diff = dvnd.expo;
1957   if (diff > 0) {
1958     dvnd.coff = shiftBig(dvnd.coff, diff);
1959     dvnd.expo = dvnd.expo - diff;
1960     dvnd.digits = dvnd.digits + diff;
1961   }
1962   int shift = 4 + context.precision + countDigits(cast(uint)n) - dvnd.digits;
1963   if (shift > 0) {
1964     dvnd.coff = shiftBig(dvnd.coff, shift);
1965     dvnd.expo = dvnd.expo - shift;
1966     dvnd.digits = dvnd.digits + shift;
1967   }
1968 
1969   quo.coff = dvnd.coff / n;
1970   quo.expo = dvnd.expo; // - n.expo;
1971   quo.sign = dvnd.sign ^ (n < 0);
1972   quo.digits = countDigits(quo.coff);
1973   quo = round(quo, context);
1974   quo = reduceToIdeal(quo, diff);
1975   return quo;
1976 }
1977 
1978 /// Divides the first operand by the second operand and returns their quotient.
1979 /// Division by zero sets a flag and returns infinity.
1980 /// The result may be rounded and context flags may be set.
1981 /// Implements the 'divide' function in the specification. (p. 27-29)
1982 public D div(D, U)(in D x, in U z, Context context = D.context)
1983     if (isDecimal!D && isConvertible!U)
1984 {
1985   return div(x, D(z), context);
1986 }  // end div(x, z)
1987 
1988 /**
1989  * Reduces operand to simplest form. All trailing zeros are removed.
1990  * Reduces operand to specified exponent.
1991  */
1992  // TODO: (behavior) has non-standard flag setting
1993 // NOTE: flags only
1994 private D reduceToIdeal(D)(D x, int ideal) if (isDecimal!D) {
1995   if (!x.isFinite()) {
1996     return x;
1997   }
1998   int zeros = trailingZeros(x.coff, x.digits);
1999 
2000   int idealshift = ideal - x.expo;
2001   int  canshift = idealshift > zeros ? zeros : idealshift;
2002   x.coff = shiftBig(x.coff, -canshift);
2003   x.expo = x.expo + canshift;
2004 
2005   if (x.coff == 0) {
2006     x = D.zero;
2007   }
2008   x.digits = countDigits(x.coff);
2009   return x;
2010 }
2011 unittest
2012 {  // div  -- depends on context
2013   static struct S { TD x; TD y; TD expect; }
2014   S[] s =
2015   [
2016 /*    { 1, 3, "0.333333333" },
2017     { 2, 3, "0.666666667" },*/
2018     { 1, 3, "0.3333333333333333" },
2019     { 2, 3, "0.6666666666666667" },
2020     { 5, 2, "2.5" },
2021     { 1, 10, "0.1" },
2022     { 12, 12, 1 },
2023     { "8.00", "2", "4.00" },
2024     { "2.400", "2.0", "1.20" },
2025     { 1000, 10,  100 },
2026     { 1000,  1, 1000 },
2027     { "2.4E+6", "2.0", "1.2E+6" },
2028 //    { "1.3", "2.07", "0.77" },  // uncomment to test failure
2029   ];
2030   auto f = FunctionTest!(S,TD)("div");
2031   foreach (t; s) f.test(t, div(t.x, t.y));
2032   writefln(f.report);
2033 }
2034 
2035 /*public D integerPart(D)(D x) if (isDecimal!D)
2036 {
2037   int exp = x.expo;
2038   int digits = x.digits;
2039   if (exp >= 0) return x;
2040   exp = -exp;
2041   if (exp >= digits) return D.zero(x.sign);  // TODO: review conditions for -0
2042 
2043 
2044 }*/
2045 
2046 // TODO: (behavior) Does this implement the actual spec operation?
2047 /// Divides the first operand by the second and returns the integer portion
2048 /// of the quotient.
2049 /// Division by zero sets a flag and returns infinity.
2050 /// The result may be rounded and context flags may be set.
2051 /// Implements the 'divide-integer' function in the specification. (p. 30)
2052 public D divideInteger(D)(in D x, in D y)  {
2053   D quo;
2054   remQuo(x,y,quo);
2055   return quo;
2056 }
2057 
2058 // TODO: (behavior) Does this implement the actual spec operation?
2059 /// Divides the first operand by the second and returns the integer portion
2060 /// of the quotient.
2061 /// Division by zero sets a flag and returns infinity.
2062 /// The result may be rounded and context flags may be set.
2063 /// Implements the 'divide-integer' function in the specification. (p. 30)
2064 public D remQuo(D)(in D x, in D y, out D quo) if (isDecimal!D)
2065 {
2066   // check for NaN and division by zero
2067   if (x.isNaN || y.isNaN) return invalidOperand(x, y);
2068   if (y.isZero) return divisionByZero(x, y);
2069 
2070   auto dividend = x.dup;
2071   auto dvsr  = y.dup;
2072   quo.sign = dividend.sign ^ dvsr.sign;
2073   if (x.isZero) {
2074     quo = D.zero(quo.sign);
2075     return quo.dup;
2076   }
2077 //    auto rem = D.zero;
2078 
2079   // align the operands
2080   alignOps(dividend, dvsr);
2081 
2082   BigInt div, mod;
2083   divMod(dividend.coff, dvsr.coff, div, mod);
2084   quo = D(div);
2085   D rem = D(mod);
2086   // number of digits cannot exceed precision
2087   int digits = countDigits(quo.coff);
2088   if (digits > D.precision) {
2089     rem = D.nan;
2090     return invalidOperation!D;
2091   }
2092   quo.digits = digits;
2093   rem.digits = countDigits(rem.coff);
2094   rem.sign = quo.sign;
2095   return rem;
2096 }
2097 
2098 unittest
2099 {  // divideInteger
2100   static struct S { TD x; TD y; TD expect; }
2101   S[] s =
2102   [
2103     {  1,  3, 0 },
2104     {  2,  3, 0 },
2105     {  3,  3, 1 },
2106     {  3, "2.999", 1 },
2107     { 10,  3, 3 },
2108         {  1,  0.3, 3 },
2109     {  1,  3, 0 },
2110     {  5,  2, 2 },
2111     {  1, 10, 0 },
2112     { 12, 12, 1 },
2113     {  8,  2, 4 },
2114     { "2.400", 2, 1 },
2115     { 1000, 10,  100 },
2116     { 1000,  1, 1000 },
2117     { "2.4E+6", "2.0", "1.2E+6" },
2118   ];
2119   auto f = FunctionTest!(S,TD)("divInt");
2120   foreach (t; s) f.test(t, divideInteger(t.x, t.y));
2121   writefln(f.report);
2122 }
2123 
2124 /// Divides the first operand by the second and returns the
2125 /// fractional remainder.
2126 /// Division by zero sets a flag and returns infinity.
2127 /// The sign of the remainder is the same as that of the first operand.
2128 /// The result may be rounded and context flags may be set.
2129 /// Implements the 'remainder' function in the specification. (p. 37-38)
2130 // TODO: (behavior) do we need a context version??
2131 public D remainder(D)(in D x, in D y,
2132     Context context = D.context) if (isDecimal!D)
2133 {
2134   // check for NaN and division by zero
2135   if (x.isNaN || y.isNaN) return invalidOperand(x, y);
2136   if (y.isZero) return divisionByZero(x, y);
2137 
2138   D quo = divideInteger!D(x, y,);
2139   D rem = x - (y * quo);
2140   return rem;
2141 }
2142 
2143 unittest
2144 {  // remainder
2145   static struct S { TD x; TD y; TD expect; }
2146   S[] s =
2147   [
2148     { 2.1, 3,  2.1 },
2149     {  10, 3,  1 },
2150 //    { -10, 3, -1 },  // fails
2151     {   3, "2.999", "0.001" },
2152         {10.2, 1, 0.2 },
2153         {  10, 0.3, 0.1 },
2154     { 3.6, 1.3, 1 },
2155     {  5,  2, 1 },
2156     {  1, 10, 1 },
2157     { 12, 12, 0 },
2158     {  8,  2, 0 },
2159     { "2.400", 2, "0.400" },
2160     { 1000, 10, 0 },
2161     { 1000,  1, 0 },
2162     { "2.4E+6", "2.0", "0.0" },
2163   ];
2164   auto f = FunctionTest!(S,TD)("remainder");
2165   foreach (t; s) f.test(t, remainder(t.x, t.y));
2166   writefln(f.report);
2167 }
2168 
2169 /// Divides the first operand by the second and returns the
2170 /// fractional remainder.
2171 /// Division by zero sets a flag and returns Infinity.
2172 /// The sign of the remainder is the same as that of the first operand.
2173 /// This function corresponds to the "remainder" function
2174 /// in the General Decimal Arithmetic Specification.
2175 public D remainderNear(D)(in D x, in D y) if (isDecimal!D)
2176 {
2177   // check for NaN and division by zero
2178   if (x.isNaN || y.isNaN) return invalidOperand(x, y);
2179   if (y.isZero) return divisionByZero(x, y);
2180   D quo = x/y;
2181   // TODO: (behavior) roundToIntegralValue?
2182   D rem = x - y * roundToInt(quo);
2183   return rem;
2184 }
2185 
2186 unittest
2187 {  // remainderNear
2188   static struct S { TD x; TD y; TD expect; }
2189   S[] s =
2190   [
2191     { 2.1, 3, -0.9 },
2192     {   3, 2, -1 },
2193     { -10, 3, -1 },
2194     {  10, 3, 1 },
2195     {   3, "2.999", "0.001" },
2196         { 10.2, 1, 0.2 },
2197         {  10, 0.3, 0.1 },
2198     { 3.6, 1.3, -0.3 },
2199   ];
2200   auto f = FunctionTest!(S,TD)("remNear");
2201   foreach (t; s) f.test(t, remainderNear(t.x, t.y));
2202   writefln(f.report);
2203 }
2204 
2205 //--------------------------------
2206 // rounding routines
2207 //--------------------------------
2208 
2209 /// Returns the number which is equal in value and sign
2210 /// to the first operand with the exponent of the second operand.
2211 /// The returned value is rounded to the current precision.
2212 /// This operation may set the invalid-operation flag.
2213 /// Implements the 'quantize' function in the specification. (p. 36-37)
2214 public D quantize(D)(in D left, in D right,
2215     Context context = D.context) if (isDecimal!D)
2216 {
2217   if (left.isNaN || right.isNaN) return invalidOperand(left, right);
2218 
2219   // if one operand is infinite and the other is not...
2220   if (left.isInfinite != right.isInfinite) {
2221     return invalidOperation!D;
2222   }
2223   // if both arguments are infinite
2224   if (left.isInfinite && right.isInfinite) {
2225     return left.dup;
2226   }
2227   D result = left.dup;
2228   int diff = left.expo - right.expo;
2229 
2230   if (diff == 0) {
2231     return result;
2232   }
2233 
2234   // TODO: (behavior) this shift can cause integer overflow for fixed size decimals
2235   if (diff > 0) {
2236     result.coff = shiftBig(result.coff, diff/*, precision*/);
2237     result.digits = result.digits + diff;
2238     result.expo = right.expo;
2239     if (result.digits > D.precision) {
2240       result = D.nan;
2241     }
2242     return result;
2243   }
2244   else {
2245     int precision = (-diff > left.digits) ? 0 : left.digits + diff;
2246     result = round(result, precision, context.mode);
2247     result.expo = right.expo;
2248     if (result.isZero && left.isNegative) {
2249       result.sign = true;
2250     }
2251     return result;
2252   }
2253 }
2254 
2255 // TODO: need to handle NaNs
2256 unittest
2257 {  // quantize
2258   static struct S { TD x; TD y; TD expect; }
2259   S[] s =
2260   [
2261     { "2.17", "0.001", "2.170" },
2262     { "2.17", "0.01", "2.17" },
2263     { "2.17", "0.1", "2.2" },
2264     { "2.17", "1", "2" },
2265     { "2.17", "1E+1", "0E+1" },
2266 
2267     { "-Infinity", "Infinity", "-Infinity" },
2268     { "2", "Infinity", "NaN" },
2269     { "-0.1", "1", "-0" },
2270     { "-0", "1E+5", "-0E+5" },
2271 //    { "+35236450.6", "1E-2", "NaN" },
2272     { "+35236450.6", "1E-2", "35236450.60" },
2273 
2274 //    { "-35236450.6", "1E-2", "NaN" },
2275     { "-35236450.6", "1E-2", "-35236450.60" },
2276     { "217", "1E-1", "217.0" },
2277     { "217", "1E+0", "217" },
2278     { "217", "1E+1", "2.2E+2" },
2279     { "217", "1E+2", "2E+2" },
2280   ];
2281   auto f = FunctionTest!(S,TD)("quantize");
2282   foreach (t; s) f.test(t, quantize(t.x, t.y));
2283   writefln(f.report);
2284 }
2285 
2286 /// Returns the nearest integer value to the argument.
2287 /// Context flags may be set.
2288 /// Implements the 'round-to-integral-exact' function
2289 /// in the specification. (p. 39)
2290 /// if setFlags is false, this is the 'round-to-integral-value' function.
2291 public D roundToInt(D)(in D num,
2292   in Round mode = HALF_EVEN, bool setFlags = true)
2293     if (isDecimal!D)
2294 {
2295   if (num.isSignal) return invalidOperation!D;
2296   if (num.isSpecial) return num;
2297   if (num.expo >= 0) return num;
2298 
2299   // TODO: (behavior) need to prevent precision overrides
2300   int precision = num.digits + num.expo;
2301   return round(num, precision, mode, setFlags);
2302 }
2303 
2304 unittest
2305 {  // roundToInt
2306   static struct S { TD x; TD expect; }
2307   S[] s =
2308   [
2309     { 2.1, 2 },
2310     { 0.7, 1 },
2311     { 100, 100 },
2312     { "101.5",  102 },
2313     { "-101.5", -102 },
2314     { "10E+5", "1.0E+6" },
2315     { "7.89E+77", "7.89E+77" },
2316     { "-Inf", "-Inf" },
2317   ];
2318   auto f = FunctionTest!(S,TD)("roundToInt");
2319   foreach (t; s) f.test(t, roundToInt(t.x));
2320   writefln(f.report);
2321 }
2322 
2323 /// Aligns the two operands by raising the smaller exponent
2324 /// to the value of the larger exponent, and adjusting the
2325 /// coefficient so the value remains the same.
2326 /// Both operands will have the same exponent on their return.
2327 /// No flags are set and the result is not rounded.
2328 private void alignOps(D, U)(ref D x, ref U y) if (isDecimal!D && isDecimal!U)
2329 {
2330   int diff = x.expo - y.expo;
2331   if (diff > 0) {
2332     x.coff = shiftBig(x.coff, diff);
2333     x.expo = y.expo;
2334   }
2335   else if (diff < 0) {
2336     y.coff = shiftBig(y.coff, -diff);
2337     y.expo = x.expo;
2338   }
2339 }
2340 
2341 /// Aligns the two operands by raising the smaller exponent
2342 /// to the value of the larger exponent, and adjusting the
2343 /// coefficient so the value remains the same.
2344 /// Both operands will have the same exponent on their return.
2345 /// No flags are set and the result is not rounded.
2346 private void alignOps(D, U:long)(ref D x, U n) if (isDecimal!D)
2347 {
2348   int diff = x.expo;
2349   if (x.expo == 0) return;
2350 
2351   if (x.expo > 0) {
2352     x.coff = shiftBig(x.coff, x.expo);
2353     x.expo = 0;
2354   }
2355   else if (diff < 0) {
2356     y.coff = shiftBig(y.coff, -diff);
2357     y.expo = x.expo;
2358   }
2359 }
2360 
2361 unittest { // alignOps
2362    write("-- alignOps.........");
2363   TD arg1, arg2;
2364   arg1 = TD("1.3E35");
2365   arg2 = TD("-17.4E29");
2366   alignOps(arg1, arg2);
2367   assertEqual(arg1.coff, 13000000);
2368   assertEqual(arg2.expo, 28);
2369   writeln("passed");
2370 }
2371 
2372 //--------------------------------
2373 // validity functions
2374 //--------------------------------
2375 
2376 /// Sets the invalid-operation flag and returns a quiet NaN.
2377 // TODO: combine this with invalidOperand?
2378 package D invalidOperation(D)(ushort payload = 0)
2379     if (isDecimal!D)
2380 {
2381   contextFlags.set(INVALID_OPERATION);
2382   return D.nan(payload);
2383 }
2384 
2385 unittest {  // invalidOperation
2386   TD arg, expect, actual;
2387   // TODO: (testing) Can't actually test payloads at this point.
2388   arg = TD("sNaN123");
2389   expect = TD("NaN123");
2390   actual = abs!TD(arg);
2391   assertTrue(actual.isQuiet);
2392   assertTrue(contextFlags.getFlags(INVALID_OPERATION));
2393   assertEqual(actual.toAbstract, expect.toAbstract);
2394 }
2395 
2396 /// Returns a quiet NaN and sets the invalid-operation flag.
2397 /// "The result of any arithmetic operation which has an operand
2398 /// which is a NaN (a quiet NaN or a signaling NaN) is [s,qNaN]
2399 /// or [s,qNaN,d]. The sign and any diagnostic information is copied
2400 /// from the first operand which is a signaling NaN, or if neither is
2401 /// signaling then from the first operand which is a NaN."
2402 /// -- General Decimal Arithmetic Specification, p. 24
2403 //@safe
2404 package D invalidOperand(D)(in D num) if (isDecimal!D)
2405 {
2406   // flag the invalid operation
2407   contextFlags.set(INVALID_OPERATION);
2408 /*  // if the operand is a quiet NaN return it.
2409   if (num.isQuiet) return num.dup;
2410   // Otherwise change the signalling NaN to a quiet NaN.
2411   if (num.isSignal) return D.nan(cast(ushort)num.coff);
2412   // if the operand is neither quiet nor signaling something else is wrong
2413   // so return NaN.*/
2414   return D.nan;
2415 }
2416 
2417 /// Returns a quiet NaN and sets the invalid-operation flag.
2418 /// "The result of any arithmetic operation which has an operand
2419 /// which is a NaN (a quiet NaN or a signaling NaN) is [s,qNaN]
2420 /// or [s,qNaN,d]. The sign and any diagnostic information is copied
2421 /// from the first operand which is a signaling NaN, or if neither is
2422 /// signaling then from the first operand which is a NaN."
2423 /// -- General Decimal Arithmetic Specification, p. 24
2424 //@safe
2425 package D invalidOperand(D)(in D left, in D right) if (isDecimal!D)
2426 {
2427   // flag the invalid operation
2428   contextFlags.set(INVALID_OPERATION);
2429 //  // if either operand is signaling return a quiet NaN.
2430 //  // NOTE: sign is ignored.
2431 //  if (left.isSignal) return D.nan; //(cast(ushort)left.coff);
2432 //  if (right.isSignal) return D.nan; //(cast(ushort)right.coff);
2433 //  // if the operand is a quiet NaN return it.
2434 //  if (left.isQuiet) return left;
2435 //  if (right.isQuiet) return right;
2436 //  // if neither of the operands is quiet or signaling,
2437 //  // the operands are invalid for some reason. return a quiet NaN.
2438   return D.nan;
2439 }
2440 
2441 /// Checks for invalid operands and division by zero.
2442 /// If found, the function returns NaN or infinity, respectively,
2443 /// and sets the context flags.
2444 /// This is a helper function implementing checks for division by zero
2445 /// and invalid operation in the specification. (p. 51-52)
2446 // precondition: divisor is zero.
2447 private D divisionByZero(D)(in D dividend, in D divisor) if (isDecimal!D)
2448 {
2449   // division of zero by zero is undefined
2450   if (dividend.isZero) return invalidOperation!D;
2451   // set flag and return signed infinity
2452   contextFlags.set(DIVISION_BY_ZERO);
2453   return D.infinity(dividend.sign ^ divisor.sign);
2454 }
2455 
2456 /// Checks for invalid operands and division by zero.
2457 /// If found, the function returns NaN or infinity, respectively,
2458 /// and sets the context flags.
2459 /// This is a helper function implementing checks for division by zero
2460 /// and invalid operation in the specification. (p. 51-52)
2461 // precondition: divisor is zero.
2462 private D divisionByZero(D, U:long)(in D dividend, U divisor)
2463     if (isDecimal!D)
2464 {
2465   // division of zero by zero is undefined
2466   if (dividend.isZero) return invalidOperation!D;
2467   // set flag and return signed infinity
2468   contextFlags.set(DIVISION_BY_ZERO);
2469   return D.infinity(dividend.sign ^ (divisor < 0));
2470 }
2471 
2472 unittest {
2473   write("divisionByZero......");
2474   writeln("test missing");
2475 }
2476 
2477 unittest
2478 {
2479   writeln("==========================");
2480 }
2481