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