@@ 518-721 (lines=204) @@ | ||
515 | // decimal128 exponent bias |
|
516 | var EXPONENT_BIAS = 6176; |
|
517 | ||
518 | Decimal128.prototype.toString = function() { |
|
519 | // Note: bits in this routine are referred to starting at 0, |
|
520 | // from the sign bit, towards the coefficient. |
|
521 | ||
522 | // bits 0 - 31 |
|
523 | var high; |
|
524 | // bits 32 - 63 |
|
525 | var midh; |
|
526 | // bits 64 - 95 |
|
527 | var midl; |
|
528 | // bits 96 - 127 |
|
529 | var low; |
|
530 | // bits 1 - 5 |
|
531 | var combination; |
|
532 | // decoded biased exponent (14 bits) |
|
533 | var biased_exponent; |
|
534 | // the number of significand digits |
|
535 | var significand_digits = 0; |
|
536 | // the base-10 digits in the significand |
|
537 | var significand = new Array(36); |
|
538 | for(var i = 0; i < significand.length; i++) significand[i] = 0; |
|
539 | // read pointer into significand |
|
540 | var index = 0; |
|
541 | ||
542 | // unbiased exponent |
|
543 | var exponent; |
|
544 | // the exponent if scientific notation is used |
|
545 | var scientific_exponent; |
|
546 | ||
547 | // true if the number is zero |
|
548 | var is_zero = false; |
|
549 | ||
550 | // the most signifcant significand bits (50-46) |
|
551 | var significand_msb; |
|
552 | // temporary storage for significand decoding |
|
553 | var significand128 = {parts: new Array(4)}; |
|
554 | // indexing variables |
|
555 | var i; |
|
556 | var j, k; |
|
557 | ||
558 | // Output string |
|
559 | var string = []; |
|
560 | ||
561 | // Unpack index |
|
562 | var index = 0; |
|
563 | ||
564 | // Buffer reference |
|
565 | var buffer = this.bytes; |
|
566 | ||
567 | // Unpack the low 64bits into a long |
|
568 | low = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
569 | midl = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
570 | ||
571 | // Unpack the high 64bits into a long |
|
572 | midh = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
573 | high = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
574 | ||
575 | // Unpack index |
|
576 | var index = 0; |
|
577 | ||
578 | // Create the state of the decimal |
|
579 | var dec = { |
|
580 | low: new Long(low, midl), |
|
581 | high: new Long(midh, high) }; |
|
582 | ||
583 | if(dec.high.lessThan(Long.ZERO)) { |
|
584 | string.push('-'); |
|
585 | } |
|
586 | ||
587 | // Decode combination field and exponent |
|
588 | combination = (high >> 26) & COMBINATION_MASK; |
|
589 | ||
590 | if((combination >> 3) == 3) { |
|
591 | // Check for 'special' values |
|
592 | if(combination == COMBINATION_INFINITY) { |
|
593 | return string.join('') + "Infinity"; |
|
594 | } else if(combination == COMBINATION_NAN) { |
|
595 | return "NaN"; |
|
596 | } else { |
|
597 | biased_exponent = (high >> 15) & EXPONENT_MASK; |
|
598 | significand_msb = 0x08 + ((high >> 14) & 0x01); |
|
599 | } |
|
600 | } else { |
|
601 | significand_msb = (high >> 14) & 0x07; |
|
602 | biased_exponent = (high >> 17) & EXPONENT_MASK; |
|
603 | } |
|
604 | ||
605 | exponent = biased_exponent - EXPONENT_BIAS; |
|
606 | ||
607 | // Create string of significand digits |
|
608 | ||
609 | // Convert the 114-bit binary number represented by |
|
610 | // (significand_high, significand_low) to at most 34 decimal |
|
611 | // digits through modulo and division. |
|
612 | significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14); |
|
613 | significand128.parts[1] = midh; |
|
614 | significand128.parts[2] = midl; |
|
615 | significand128.parts[3] = low; |
|
616 | ||
617 | if(significand128.parts[0] == 0 && significand128.parts[1] == 0 |
|
618 | && significand128.parts[2] == 0 && significand128.parts[3] == 0) { |
|
619 | is_zero = true; |
|
620 | } else { |
|
621 | for(var k = 3; k >= 0; k--) { |
|
622 | var least_digits = 0; |
|
623 | // Peform the divide |
|
624 | var result = divideu128(significand128); |
|
625 | significand128 = result.quotient; |
|
626 | least_digits = result.rem.low_; |
|
627 | ||
628 | // We now have the 9 least significant digits (in base 2). |
|
629 | // Convert and output to string. |
|
630 | if(!least_digits) continue; |
|
631 | ||
632 | for(var j = 8; j >= 0; j--) { |
|
633 | // significand[k * 9 + j] = Math.round(least_digits % 10); |
|
634 | significand[k * 9 + j] = least_digits % 10; |
|
635 | // least_digits = Math.round(least_digits / 10); |
|
636 | least_digits = Math.floor(least_digits / 10); |
|
637 | } |
|
638 | } |
|
639 | } |
|
640 | ||
641 | // Output format options: |
|
642 | // Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd |
|
643 | // Regular - ddd.ddd |
|
644 | ||
645 | if(is_zero) { |
|
646 | significand_digits = 1; |
|
647 | significand[index] = 0; |
|
648 | } else { |
|
649 | significand_digits = 36; |
|
650 | var i = 0; |
|
651 | ||
652 | while(!significand[index]) { |
|
653 | i++; |
|
654 | significand_digits = significand_digits - 1; |
|
655 | index = index + 1; |
|
656 | } |
|
657 | } |
|
658 | ||
659 | scientific_exponent = significand_digits - 1 + exponent; |
|
660 | ||
661 | // The scientific exponent checks are dictated by the string conversion |
|
662 | // specification and are somewhat arbitrary cutoffs. |
|
663 | // |
|
664 | // We must check exponent > 0, because if this is the case, the number |
|
665 | // has trailing zeros. However, we *cannot* output these trailing zeros, |
|
666 | // because doing so would change the precision of the value, and would |
|
667 | // change stored data if the string converted number is round tripped. |
|
668 | ||
669 | if(scientific_exponent >= 34 || scientific_exponent <= -7 || |
|
670 | exponent > 0) { |
|
671 | // Scientific format |
|
672 | string.push(significand[index++]); |
|
673 | significand_digits = significand_digits - 1; |
|
674 | ||
675 | if(significand_digits) { |
|
676 | string.push('.'); |
|
677 | } |
|
678 | ||
679 | for(var i = 0; i < significand_digits; i++) { |
|
680 | string.push(significand[index++]); |
|
681 | } |
|
682 | ||
683 | // Exponent |
|
684 | string.push('E'); |
|
685 | if(scientific_exponent > 0) { |
|
686 | string.push('+' + scientific_exponent); |
|
687 | } else { |
|
688 | string.push(scientific_exponent); |
|
689 | } |
|
690 | } else { |
|
691 | // Regular format with no decimal place |
|
692 | if(exponent >= 0) { |
|
693 | for(var i = 0; i < significand_digits; i++) { |
|
694 | string.push(significand[index++]); |
|
695 | } |
|
696 | } else { |
|
697 | var radix_position = significand_digits + exponent; |
|
698 | ||
699 | // non-zero digits before radix |
|
700 | if(radix_position > 0) { |
|
701 | for(var i = 0; i < radix_position; i++) { |
|
702 | string.push(significand[index++]); |
|
703 | } |
|
704 | } else { |
|
705 | string.push('0'); |
|
706 | } |
|
707 | ||
708 | string.push('.'); |
|
709 | // add leading zeros after radix |
|
710 | while(radix_position++ < 0) { |
|
711 | string.push('0'); |
|
712 | } |
|
713 | ||
714 | for(var i = 0; i < significand_digits - Math.max(radix_position - 1, 0); i++) { |
|
715 | string.push(significand[index++]); |
|
716 | } |
|
717 | } |
|
718 | } |
|
719 | ||
720 | return string.join(''); |
|
721 | } |
|
722 | ||
723 | Decimal128.prototype.toJSON = function() { |
|
724 | return { "$numberDecimal": this.toString() }; |
@@ 13628-13829 (lines=202) @@ | ||
13625 | // decimal128 exponent bias |
|
13626 | var EXPONENT_BIAS = 6176; |
|
13627 | ||
13628 | Decimal128.prototype.toString = function () { |
|
13629 | // Note: bits in this routine are referred to starting at 0, |
|
13630 | // from the sign bit, towards the coefficient. |
|
13631 | ||
13632 | // bits 0 - 31 |
|
13633 | var high; |
|
13634 | // bits 32 - 63 |
|
13635 | var midh; |
|
13636 | // bits 64 - 95 |
|
13637 | var midl; |
|
13638 | // bits 96 - 127 |
|
13639 | var low; |
|
13640 | // bits 1 - 5 |
|
13641 | var combination; |
|
13642 | // decoded biased exponent (14 bits) |
|
13643 | var biased_exponent; |
|
13644 | // the number of significand digits |
|
13645 | var significand_digits = 0; |
|
13646 | // the base-10 digits in the significand |
|
13647 | var significand = new Array(36); |
|
13648 | for (var i = 0; i < significand.length; i++) significand[i] = 0; |
|
13649 | // read pointer into significand |
|
13650 | var index = 0; |
|
13651 | ||
13652 | // unbiased exponent |
|
13653 | var exponent; |
|
13654 | // the exponent if scientific notation is used |
|
13655 | var scientific_exponent; |
|
13656 | ||
13657 | // true if the number is zero |
|
13658 | var is_zero = false; |
|
13659 | ||
13660 | // the most signifcant significand bits (50-46) |
|
13661 | var significand_msb; |
|
13662 | // temporary storage for significand decoding |
|
13663 | var significand128 = { parts: new Array(4) }; |
|
13664 | // indexing variables |
|
13665 | var i; |
|
13666 | var j, k; |
|
13667 | ||
13668 | // Output string |
|
13669 | var string = []; |
|
13670 | ||
13671 | // Unpack index |
|
13672 | var index = 0; |
|
13673 | ||
13674 | // Buffer reference |
|
13675 | var buffer = this.bytes; |
|
13676 | ||
13677 | // Unpack the low 64bits into a long |
|
13678 | low = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
13679 | midl = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
13680 | ||
13681 | // Unpack the high 64bits into a long |
|
13682 | midh = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
13683 | high = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; |
|
13684 | ||
13685 | // Unpack index |
|
13686 | var index = 0; |
|
13687 | ||
13688 | // Create the state of the decimal |
|
13689 | var dec = { |
|
13690 | low: new Long(low, midl), |
|
13691 | high: new Long(midh, high) }; |
|
13692 | ||
13693 | if (dec.high.lessThan(Long.ZERO)) { |
|
13694 | string.push('-'); |
|
13695 | } |
|
13696 | ||
13697 | // Decode combination field and exponent |
|
13698 | combination = high >> 26 & COMBINATION_MASK; |
|
13699 | ||
13700 | if (combination >> 3 == 3) { |
|
13701 | // Check for 'special' values |
|
13702 | if (combination == COMBINATION_INFINITY) { |
|
13703 | return string.join('') + "Infinity"; |
|
13704 | } else if (combination == COMBINATION_NAN) { |
|
13705 | return "NaN"; |
|
13706 | } else { |
|
13707 | biased_exponent = high >> 15 & EXPONENT_MASK; |
|
13708 | significand_msb = 0x08 + (high >> 14 & 0x01); |
|
13709 | } |
|
13710 | } else { |
|
13711 | significand_msb = high >> 14 & 0x07; |
|
13712 | biased_exponent = high >> 17 & EXPONENT_MASK; |
|
13713 | } |
|
13714 | ||
13715 | exponent = biased_exponent - EXPONENT_BIAS; |
|
13716 | ||
13717 | // Create string of significand digits |
|
13718 | ||
13719 | // Convert the 114-bit binary number represented by |
|
13720 | // (significand_high, significand_low) to at most 34 decimal |
|
13721 | // digits through modulo and division. |
|
13722 | significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14); |
|
13723 | significand128.parts[1] = midh; |
|
13724 | significand128.parts[2] = midl; |
|
13725 | significand128.parts[3] = low; |
|
13726 | ||
13727 | if (significand128.parts[0] == 0 && significand128.parts[1] == 0 && significand128.parts[2] == 0 && significand128.parts[3] == 0) { |
|
13728 | is_zero = true; |
|
13729 | } else { |
|
13730 | for (var k = 3; k >= 0; k--) { |
|
13731 | var least_digits = 0; |
|
13732 | // Peform the divide |
|
13733 | var result = divideu128(significand128); |
|
13734 | significand128 = result.quotient; |
|
13735 | least_digits = result.rem.low_; |
|
13736 | ||
13737 | // We now have the 9 least significant digits (in base 2). |
|
13738 | // Convert and output to string. |
|
13739 | if (!least_digits) continue; |
|
13740 | ||
13741 | for (var j = 8; j >= 0; j--) { |
|
13742 | // significand[k * 9 + j] = Math.round(least_digits % 10); |
|
13743 | significand[k * 9 + j] = least_digits % 10; |
|
13744 | // least_digits = Math.round(least_digits / 10); |
|
13745 | least_digits = Math.floor(least_digits / 10); |
|
13746 | } |
|
13747 | } |
|
13748 | } |
|
13749 | ||
13750 | // Output format options: |
|
13751 | // Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd |
|
13752 | // Regular - ddd.ddd |
|
13753 | ||
13754 | if (is_zero) { |
|
13755 | significand_digits = 1; |
|
13756 | significand[index] = 0; |
|
13757 | } else { |
|
13758 | significand_digits = 36; |
|
13759 | var i = 0; |
|
13760 | ||
13761 | while (!significand[index]) { |
|
13762 | i++; |
|
13763 | significand_digits = significand_digits - 1; |
|
13764 | index = index + 1; |
|
13765 | } |
|
13766 | } |
|
13767 | ||
13768 | scientific_exponent = significand_digits - 1 + exponent; |
|
13769 | ||
13770 | // The scientific exponent checks are dictated by the string conversion |
|
13771 | // specification and are somewhat arbitrary cutoffs. |
|
13772 | // |
|
13773 | // We must check exponent > 0, because if this is the case, the number |
|
13774 | // has trailing zeros. However, we *cannot* output these trailing zeros, |
|
13775 | // because doing so would change the precision of the value, and would |
|
13776 | // change stored data if the string converted number is round tripped. |
|
13777 | ||
13778 | if (scientific_exponent >= 34 || scientific_exponent <= -7 || exponent > 0) { |
|
13779 | // Scientific format |
|
13780 | string.push(significand[index++]); |
|
13781 | significand_digits = significand_digits - 1; |
|
13782 | ||
13783 | if (significand_digits) { |
|
13784 | string.push('.'); |
|
13785 | } |
|
13786 | ||
13787 | for (var i = 0; i < significand_digits; i++) { |
|
13788 | string.push(significand[index++]); |
|
13789 | } |
|
13790 | ||
13791 | // Exponent |
|
13792 | string.push('E'); |
|
13793 | if (scientific_exponent > 0) { |
|
13794 | string.push('+' + scientific_exponent); |
|
13795 | } else { |
|
13796 | string.push(scientific_exponent); |
|
13797 | } |
|
13798 | } else { |
|
13799 | // Regular format with no decimal place |
|
13800 | if (exponent >= 0) { |
|
13801 | for (var i = 0; i < significand_digits; i++) { |
|
13802 | string.push(significand[index++]); |
|
13803 | } |
|
13804 | } else { |
|
13805 | var radix_position = significand_digits + exponent; |
|
13806 | ||
13807 | // non-zero digits before radix |
|
13808 | if (radix_position > 0) { |
|
13809 | for (var i = 0; i < radix_position; i++) { |
|
13810 | string.push(significand[index++]); |
|
13811 | } |
|
13812 | } else { |
|
13813 | string.push('0'); |
|
13814 | } |
|
13815 | ||
13816 | string.push('.'); |
|
13817 | // add leading zeros after radix |
|
13818 | while (radix_position++ < 0) { |
|
13819 | string.push('0'); |
|
13820 | } |
|
13821 | ||
13822 | for (var i = 0; i < significand_digits - Math.max(radix_position - 1, 0); i++) { |
|
13823 | string.push(significand[index++]); |
|
13824 | } |
|
13825 | } |
|
13826 | } |
|
13827 | ||
13828 | return string.join(''); |
|
13829 | }; |
|
13830 | ||
13831 | Decimal128.prototype.toJSON = function () { |
|
13832 | return { "$numberDecimal": this.toString() }; |