emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js
author Martin Soch <Martin.Soch@oracle.com>
Tue, 05 Feb 2013 16:32:14 +0100
brancharithmetic
changeset 675 7d3da112e2c1
parent 669 3754580b6c67
child 676 eecf6077ec4e
permissions -rw-r--r--
Long - conversion to exact string representation works.
     1 // empty line needed here
     2 Number.prototype.add32 = function(x) { return (this + x) | 0; };
     3 Number.prototype.sub32 = function(x) { return (this - x) | 0; };
     4 Number.prototype.mul32 = function(x) { 
     5     return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
     6 };
     7 
     8 Number.prototype.toInt8 = function()  { return (this << 24) >> 24; };
     9 Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
    10 
    11 var __m32 = 0xFFFFFFFF;
    12 
    13 Number.prototype.next32 = function(low) {
    14   if (this === 0) {
    15     return low;
    16   }
    17   var l = new Number(low);
    18   l.hi = this | 0;
    19   return l;
    20 };
    21 
    22 Number.prototype.high32 = function() { 
    23     return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
    24 };
    25 Number.prototype.toInt32 = function() { return this | 0; };
    26 Number.prototype.toFP = function() {
    27     return this.hi ? this.hi * (__m32+1) + this : this;
    28 };
    29 Number.prototype.toLong = function() {
    30     var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0;
    31     return hi.next32(Math.floor(this % (__m32+1)));
    32 };
    33 
    34 Number.prototype.toExactString = function() {
    35     if (this.hi) {
    36         var res = 0;
    37         var a = [ 6,9,2,7,6,9,4,9,2,4 ];
    38         var s = '';
    39         var digit;
    40         var neg = this.hi < 0;
    41         if (neg) {
    42             var x = this.neg64();
    43             var hi = x.hi;
    44             var low = x;
    45         } else {
    46             var hi = this.hi;
    47             var low = this;
    48         }
    49         for (var i = 0; i < a.length; i++) {
    50             res += hi * a[i];
    51             var low_digit = low % 10;
    52             digit = (res % 10) + low_digit;
    53 
    54             low = Math.floor(low / 10);
    55             res = Math.floor(res / 10);
    56 
    57             if (digit >= 10) {
    58                 digit -= 10;
    59                 res++;
    60             }
    61             s = String(digit).concat(s);
    62         }
    63         return (neg ? '-' : '').concat(res).concat(s);
    64     }
    65     return String(this);
    66 };
    67 
    68 Number.prototype.add64 = function(x) {
    69     var low = this + x;
    70     carry = 0;
    71     if (low > __m32) {
    72         carry = 1;
    73         low -= (__m32+1);
    74     }
    75     var hi = (this.high32() + x.high32() + carry) | 0;
    76     return hi.next32(low);
    77 };
    78 
    79 Number.prototype.sub64 = function(x) {
    80     var low = this - x;
    81     carry = 0;
    82     if (low < 0) {
    83         carry = 1;
    84         low += (__m32+1);
    85     }
    86     var hi = (this.high32() - x.high32() - carry) | 0;
    87     return hi.next32(low);
    88 };
    89 
    90 Number.prototype.mul64 = function(x) {
    91     var low = this.mul32(x);
    92     low += (low < 0) ? (__m32+1) : 0;
    93     // first count upper 32 bits of (this.low * x.low)
    94     var hi_hi = 0;
    95     var hi_low = 0;
    96     var m = 1;
    97     for (var i = 0; i < 32; i++) {
    98         if (x & m) {
    99             hi_hi += this >>> 16;
   100             hi_low += this & 0xFFFF
   101         }
   102         hi_low >>= 1;
   103         hi_low += (hi_hi & 1) ? 0x8000 : 0;
   104         hi_hi >>= 1;
   105         m <<= 1;
   106     }
   107     var hi = (hi_hi << 16) + hi_low;
   108     
   109     var m1 = this.high32().mul32(x);
   110     var m2 = this.mul32(x.high32());
   111     hi = hi.add32(m1).add32(m2);
   112     
   113     return hi.next32(low);
   114 };
   115 
   116 Number.prototype.div64 = function(x) {
   117     var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough
   118     if (low > __m32) {
   119         var hi = Math.floor(low / (__m32+1)) | 0;
   120         return hi.next32(low % (__m32+1));
   121     }
   122     return low;
   123 };
   124 
   125 Number.prototype.and64 = function(x) {
   126     var low = this & x;
   127     low += (low < 0) ? (__m32+1) : 0;
   128     if (this.hi && x.hi) {
   129         var hi = this.hi & x.hi;
   130         return hi.next32(low);
   131     };
   132     return low;
   133 };
   134 
   135 Number.prototype.or64 = function(x) {
   136     var low = this | x;
   137     low += (low < 0) ? (__m32+1) : 0;
   138     if (this.hi || x.hi) {
   139         var hi = this.hi | x.hi;
   140         return hi.next32(low);
   141     };
   142     return low;
   143 };
   144 
   145 Number.prototype.xor64 = function(x) {
   146     var low = this ^ x;
   147     low += (low < 0) ? (__m32+1) : 0;
   148     if (this.hi || x.hi) {
   149         var hi = this.hi ^ x.hi;
   150         return hi.next32(low);
   151     };
   152     return low;
   153 };
   154 
   155 Number.prototype.shl64 = function(x) {
   156     if (x >= 32) {
   157         var hi = this << (x - 32);
   158         return hi.next32(0);
   159     } else {
   160         var hi = this.high32() << x;
   161         var low_reminder = this >> (32 - x);
   162         hi |= low_reminder;
   163         var low = this << x;
   164         low += (low < 0) ? (__m32+1) : 0;
   165         return hi.next32(low);
   166     }
   167 };
   168 
   169 Number.prototype.shr64 = function(x) {
   170     if (x >= 32) {
   171         var low = this.high32() >> (x - 32);
   172         low += (low < 0) ? (__m32+1) : 0;
   173         return low;
   174     } else {
   175         var low = this >> x;
   176         var hi_reminder = this.high32() << (32 - x);
   177         low |= hi_reminder;
   178         low += (low < 0) ? (__m32+1) : 0;
   179         var hi = this.high32() >> x;
   180         return hi.next32(low);
   181     }
   182 };
   183 
   184 Number.prototype.ushr64 = function(x) {
   185     if (x >= 32) {
   186         var low = this.high32() >>> (x - 32);
   187         low += (low < 0) ? (__m32+1) : 0;
   188         return low;
   189     } else {
   190         var low = this >>> x;
   191         var hi_reminder = this.high32() << (32 - x);
   192         low |= hi_reminder;
   193         low += (low < 0) ? (__m32+1) : 0;
   194         var hi = this.high32() >>> x;
   195         return hi.next32(low);
   196     }
   197 };
   198 
   199 Number.prototype.compare64 = function(x) {
   200     if (this.hi == x.hi) {
   201         return (this == x) ? 0 : ((this < x) ? -1 : 1);
   202     }
   203     return (this.hi < x.hi) ? -1 : 1;
   204 };
   205 
   206 Number.prototype.neg64 = function() {
   207     var hi = this.high32();
   208     var low = this;
   209     if ((hi === 0) && (low < 0)) { return -low; }
   210     hi = ~hi;
   211     low = ~low;
   212     low += (low < 0) ? (__m32+1) : 0;
   213     var ret = hi.next32(low);
   214     return ret.add64(1);
   215 };