rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js
changeset 772 d382dacfd73f
parent 737 b2731af0357d
child 778 6f8683517f1f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Tue Feb 26 16:54:16 2013 +0100
     1.3 @@ -0,0 +1,544 @@
     1.4 +// empty line needed here
     1.5 +Number.prototype.add32 = function(x) { return (this + x) | 0; };
     1.6 +Number.prototype.sub32 = function(x) { return (this - x) | 0; };
     1.7 +Number.prototype.mul32 = function(x) { 
     1.8 +    return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
     1.9 +};
    1.10 +Number.prototype.neg32 = function() { return (-this) | 0; };
    1.11 +
    1.12 +Number.prototype.toInt8 = function()  { return (this << 24) >> 24; };
    1.13 +Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
    1.14 +
    1.15 +var __m32 = 0xFFFFFFFF;
    1.16 +
    1.17 +Number.prototype.next32 = function(low) {
    1.18 +  if (this === 0) {
    1.19 +    return low;
    1.20 +  }
    1.21 +  var l = new Number(low);
    1.22 +  l.hi = this | 0;
    1.23 +  return l;
    1.24 +};
    1.25 +
    1.26 +Number.prototype.high32 = function() { 
    1.27 +    return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
    1.28 +};
    1.29 +Number.prototype.toInt32 = function() { return this | 0; };
    1.30 +Number.prototype.toFP = function() {
    1.31 +    return this.hi ? this.hi * (__m32+1) + this : this;
    1.32 +};
    1.33 +Number.prototype.toLong = function() {
    1.34 +    var hi = (this > __m32) ? (Math.floor(this / (__m32+1))) | 0 : 0;
    1.35 +    return hi.next32(Math.floor(this % (__m32+1)));
    1.36 +};
    1.37 +
    1.38 +Number.prototype.toExactString = function() {
    1.39 +    if (this.hi) {
    1.40 +        // check for Long.MIN_VALUE
    1.41 +        if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
    1.42 +            return '-9223372036854775808';
    1.43 +        }
    1.44 +        var res = 0;
    1.45 +        var a = [ 6,9,2,7,6,9,4,9,2,4 ];
    1.46 +        var s = '';
    1.47 +        var digit;
    1.48 +        var neg = this.hi < 0;
    1.49 +        if (neg) {
    1.50 +            var x = this.neg64();
    1.51 +            var hi = x.hi;
    1.52 +            var low = x;
    1.53 +        } else {
    1.54 +            var hi = this.hi;
    1.55 +            var low = this;
    1.56 +        }
    1.57 +        for (var i = 0; i < a.length; i++) {
    1.58 +            res += hi * a[i];
    1.59 +            var low_digit = low % 10;
    1.60 +            digit = (res % 10) + low_digit;
    1.61 +
    1.62 +            low = Math.floor(low / 10);
    1.63 +            res = Math.floor(res / 10);
    1.64 +
    1.65 +            if (digit >= 10) {
    1.66 +                digit -= 10;
    1.67 +                res++;
    1.68 +            }
    1.69 +            s = String(digit).concat(s);
    1.70 +        }
    1.71 +        s = String(res).concat(s).replace(/^0+/, '');
    1.72 +        return (neg ? '-' : '').concat(s);
    1.73 +    }
    1.74 +    return String(this);
    1.75 +};
    1.76 +
    1.77 +Number.prototype.add64 = function(x) {
    1.78 +    var low = this + x;
    1.79 +    carry = 0;
    1.80 +    if (low > __m32) {
    1.81 +        carry = 1;
    1.82 +        low -= (__m32+1);
    1.83 +    }
    1.84 +    var hi = (this.high32() + x.high32() + carry) | 0;
    1.85 +    return hi.next32(low);
    1.86 +};
    1.87 +
    1.88 +Number.prototype.sub64 = function(x) {
    1.89 +    var low = this - x;
    1.90 +    carry = 0;
    1.91 +    if (low < 0) {
    1.92 +        carry = 1;
    1.93 +        low += (__m32+1);
    1.94 +    }
    1.95 +    var hi = (this.high32() - x.high32() - carry) | 0;
    1.96 +    return hi.next32(low);
    1.97 +};
    1.98 +
    1.99 +Number.prototype.mul64 = function(x) {
   1.100 +    var low = this.mul32(x);
   1.101 +    low += (low < 0) ? (__m32+1) : 0;
   1.102 +    // first count upper 32 bits of (this.low * x.low)
   1.103 +    var hi_hi = 0;
   1.104 +    var hi_low = 0;
   1.105 +    var m = 1;
   1.106 +    for (var i = 0; i < 32; i++) {
   1.107 +        if (x & m) {
   1.108 +            hi_hi += this >>> 16;
   1.109 +            hi_low += this & 0xFFFF
   1.110 +        }
   1.111 +        hi_low >>= 1;
   1.112 +        hi_low += (hi_hi & 1) ? 0x8000 : 0;
   1.113 +        hi_hi >>= 1;
   1.114 +        m <<= 1;
   1.115 +    }
   1.116 +    var hi = (hi_hi << 16) + hi_low;
   1.117 +    
   1.118 +    var m1 = this.high32().mul32(x);
   1.119 +    var m2 = this.mul32(x.high32());
   1.120 +    hi = hi.add32(m1).add32(m2);
   1.121 +    
   1.122 +    return hi.next32(low);
   1.123 +};
   1.124 +
   1.125 +Number.prototype.and64 = function(x) {
   1.126 +    var low = this & x;
   1.127 +    low += (low < 0) ? (__m32+1) : 0;
   1.128 +    if (this.hi && x.hi) {
   1.129 +        var hi = this.hi & x.hi;
   1.130 +        return hi.next32(low);
   1.131 +    };
   1.132 +    return low;
   1.133 +};
   1.134 +
   1.135 +Number.prototype.or64 = function(x) {
   1.136 +    var low = this | x;
   1.137 +    low += (low < 0) ? (__m32+1) : 0;
   1.138 +    if (this.hi || x.hi) {
   1.139 +        var hi = this.hi | x.hi;
   1.140 +        return hi.next32(low);
   1.141 +    };
   1.142 +    return low;
   1.143 +};
   1.144 +
   1.145 +Number.prototype.xor64 = function(x) {
   1.146 +    var low = this ^ x;
   1.147 +    low += (low < 0) ? (__m32+1) : 0;
   1.148 +    if (this.hi || x.hi) {
   1.149 +        var hi = this.hi ^ x.hi;
   1.150 +        return hi.next32(low);
   1.151 +    };
   1.152 +    return low;
   1.153 +};
   1.154 +
   1.155 +Number.prototype.shl64 = function(x) {
   1.156 +    if (x >= 32) {
   1.157 +        var hi = this << (x - 32);
   1.158 +        return hi.next32(0);
   1.159 +    } else {
   1.160 +        var hi = this.high32() << x;
   1.161 +        var low_reminder = this >> (32 - x);
   1.162 +        hi |= low_reminder;
   1.163 +        var low = this << x;
   1.164 +        low += (low < 0) ? (__m32+1) : 0;
   1.165 +        return hi.next32(low);
   1.166 +    }
   1.167 +};
   1.168 +
   1.169 +Number.prototype.shr64 = function(x) {
   1.170 +    if (x >= 32) {
   1.171 +        var low = this.high32() >> (x - 32);
   1.172 +        low += (low < 0) ? (__m32+1) : 0;
   1.173 +        return low;
   1.174 +    } else {
   1.175 +        var low = this >> x;
   1.176 +        var hi_reminder = this.high32() << (32 - x);
   1.177 +        low |= hi_reminder;
   1.178 +        low += (low < 0) ? (__m32+1) : 0;
   1.179 +        var hi = this.high32() >> x;
   1.180 +        return hi.next32(low);
   1.181 +    }
   1.182 +};
   1.183 +
   1.184 +Number.prototype.ushr64 = function(x) {
   1.185 +    if (x >= 32) {
   1.186 +        var low = this.high32() >>> (x - 32);
   1.187 +        low += (low < 0) ? (__m32+1) : 0;
   1.188 +        return low;
   1.189 +    } else {
   1.190 +        var low = this >>> x;
   1.191 +        var hi_reminder = this.high32() << (32 - x);
   1.192 +        low |= hi_reminder;
   1.193 +        low += (low < 0) ? (__m32+1) : 0;
   1.194 +        var hi = this.high32() >>> x;
   1.195 +        return hi.next32(low);
   1.196 +    }
   1.197 +};
   1.198 +
   1.199 +Number.prototype.compare64 = function(x) {
   1.200 +    if (this.high32() === x.high32()) {
   1.201 +        return (this < x) ? -1 : ((this > x) ? 1 : 0);
   1.202 +    }
   1.203 +    return (this.high32() < x.high32()) ? -1 : 1;
   1.204 +};
   1.205 +
   1.206 +Number.prototype.neg64 = function() {
   1.207 +    var hi = this.high32();
   1.208 +    var low = this;
   1.209 +    if ((hi === 0) && (low < 0)) { return -low; }
   1.210 +    hi = ~hi;
   1.211 +    low = ~low;
   1.212 +    low += (low < 0) ? (__m32+1) : 0;
   1.213 +    var ret = hi.next32(low);
   1.214 +    return ret.add64(1);
   1.215 +};
   1.216 +
   1.217 +(function(numberPrototype) {
   1.218 +    function __handleDivByZero() {
   1.219 +        var exception = new vm.java_lang_ArithmeticException;
   1.220 +        vm.java_lang_ArithmeticException(false).constructor
   1.221 +          .cons__VLjava_lang_String_2.call(exception, "/ by zero");
   1.222 +
   1.223 +        throw exception;
   1.224 +    }
   1.225 +
   1.226 +    function __Int64(hi32, lo32) {
   1.227 +        this.hi32 = hi32 | 0;
   1.228 +        this.lo32 = lo32 | 0;
   1.229 +
   1.230 +        this.get32 = function(bitIndex) {
   1.231 +            var v0;
   1.232 +            var v1;
   1.233 +            bitIndex += 32;
   1.234 +            var selector = bitIndex >>> 5;
   1.235 +            switch (selector) {
   1.236 +                case 0:
   1.237 +                    v0 = 0;
   1.238 +                    v1 = this.lo32;
   1.239 +                    break;
   1.240 +                case 1:
   1.241 +                    v0 = this.lo32;
   1.242 +                    v1 = this.hi32;
   1.243 +                    break;
   1.244 +                case 2:
   1.245 +                    v0 = this.hi32;
   1.246 +                    v1 = 0;
   1.247 +                    break
   1.248 +                default:
   1.249 +                    return 0;
   1.250 +            }
   1.251 +
   1.252 +            var shift = bitIndex & 31;
   1.253 +            if (shift === 0) {
   1.254 +                return v0;
   1.255 +            }
   1.256 +
   1.257 +            return (v1 << (32 - shift)) | (v0 >>> shift);
   1.258 +        }
   1.259 +
   1.260 +        this.get16 = function(bitIndex) {
   1.261 +            return this.get32(bitIndex) & 0xffff;
   1.262 +        }
   1.263 +
   1.264 +        this.set16 = function(bitIndex, value) {
   1.265 +            bitIndex += 32;
   1.266 +            var shift = bitIndex & 15;
   1.267 +            var svalue = (value & 0xffff) << shift; 
   1.268 +            var smask = 0xffff << shift;
   1.269 +            var selector = bitIndex >>> 4;
   1.270 +            switch (selector) {
   1.271 +                case 0:
   1.272 +                    break;
   1.273 +                case 1:
   1.274 +                    this.lo32 = (this.lo32 & ~(smask >>> 16))
   1.275 +                                    | (svalue >>> 16);
   1.276 +                    break;
   1.277 +                case 2:
   1.278 +                    this.lo32 = (this.lo32 & ~smask) | svalue;
   1.279 +                    break;
   1.280 +                case 3:
   1.281 +                    this.lo32 = (this.lo32 & ~(smask << 16))
   1.282 +                                    | (svalue << 16);
   1.283 +                    this.hi32 = (this.hi32 & ~(smask >>> 16))
   1.284 +                                    | (svalue >>> 16);
   1.285 +                    break;
   1.286 +                case 4:
   1.287 +                    this.hi32 = (this.hi32 & ~smask) | svalue;
   1.288 +                    break;
   1.289 +                case 5:
   1.290 +                    this.hi32 = (this.hi32 & ~(smask << 16))
   1.291 +                                    | (svalue << 16);
   1.292 +                    break;
   1.293 +            }
   1.294 +        }
   1.295 +
   1.296 +        this.getDigit = function(index, shift) {
   1.297 +            return this.get16((index << 4) - shift);
   1.298 +        }
   1.299 +
   1.300 +        this.getTwoDigits = function(index, shift) {
   1.301 +            return this.get32(((index - 1) << 4) - shift);
   1.302 +        }
   1.303 +
   1.304 +        this.setDigit = function(index, shift, value) {
   1.305 +            this.set16((index << 4) - shift, value);
   1.306 +        }
   1.307 +
   1.308 +        this.countSignificantDigits = function() {
   1.309 +            var sd;
   1.310 +            var remaining;
   1.311 +
   1.312 +            if (this.hi32 === 0) {
   1.313 +                if (this.lo32 === 0) {
   1.314 +                    return 0;
   1.315 +                }
   1.316 +
   1.317 +                sd = 2;
   1.318 +                remaining = this.lo32;
   1.319 +            } else {
   1.320 +                sd = 4;
   1.321 +                remaining = this.hi32;
   1.322 +            }
   1.323 +
   1.324 +            if (remaining < 0) {
   1.325 +                return sd;
   1.326 +            }
   1.327 +
   1.328 +            return (remaining < 65536) ? sd - 1 : sd;
   1.329 +        }
   1.330 +        
   1.331 +        this.toNumber = function() {
   1.332 +            var lo32 = this.lo32;
   1.333 +            if (lo32 < 0) {
   1.334 +                lo32 += 0x100000000;
   1.335 +            }
   1.336 +
   1.337 +            return this.hi32.next32(lo32);
   1.338 +        }
   1.339 +    }
   1.340 +
   1.341 +    function __countLeadingZeroes16(number) {
   1.342 +        var nlz = 0;
   1.343 +
   1.344 +        if (number < 256) {
   1.345 +            nlz += 8;
   1.346 +            number <<= 8;
   1.347 +        }
   1.348 +
   1.349 +        if (number < 4096) {
   1.350 +            nlz += 4;
   1.351 +            number <<= 4;
   1.352 +        }
   1.353 +
   1.354 +        if (number < 16384) {
   1.355 +            nlz += 2;
   1.356 +            number <<= 2;
   1.357 +        }
   1.358 +
   1.359 +        return (number < 32768) ? nlz + 1 : nlz;
   1.360 +    }
   1.361 +    
   1.362 +    // q = u / v; r = u - q * v;
   1.363 +    // v != 0
   1.364 +    function __div64(q, r, u, v) {
   1.365 +        var m = u.countSignificantDigits();
   1.366 +        var n = v.countSignificantDigits();
   1.367 +
   1.368 +        q.hi32 = q.lo32 = 0;
   1.369 +
   1.370 +        if (n === 1) {
   1.371 +            // v has single digit
   1.372 +            var vd = v.getDigit(0, 0);
   1.373 +            var carry = 0;
   1.374 +            for (var i = m - 1; i >= 0; --i) {
   1.375 +                var ui = (carry << 16) | u.getDigit(i, 0);
   1.376 +                if (ui < 0) {
   1.377 +                    ui += 0x100000000;
   1.378 +                }
   1.379 +                var qi = (ui / vd) | 0;
   1.380 +                q.setDigit(i, 0, qi);
   1.381 +                carry = ui - qi * vd;
   1.382 +            }
   1.383 +
   1.384 +            r.hi32 = 0;
   1.385 +            r.lo32 = carry;
   1.386 +            return;
   1.387 +        }
   1.388 +
   1.389 +        r.hi32 = u.hi32;  
   1.390 +        r.lo32 = u.lo32;
   1.391 +
   1.392 +        if (m < n) {
   1.393 +            return;
   1.394 +        }
   1.395 +
   1.396 +        // Normalize
   1.397 +        var nrm = __countLeadingZeroes16(v.getDigit(n - 1, 0));
   1.398 +
   1.399 +        var vd1 = v.getDigit(n - 1, nrm);                
   1.400 +        var vd0 = v.getDigit(n - 2, nrm);
   1.401 +        for (var j = m - n; j >= 0; --j) {
   1.402 +            // Calculate qj estimate
   1.403 +            var ud21 = r.getTwoDigits(j + n, nrm);
   1.404 +            var ud2 = ud21 >>> 16;
   1.405 +            if (ud21 < 0) {
   1.406 +                ud21 += 0x100000000;
   1.407 +            }
   1.408 +
   1.409 +            var qest = (ud2 === vd1) ? 0xFFFF : ((ud21 / vd1) | 0);
   1.410 +            var rest = ud21 - qest * vd1;
   1.411 +
   1.412 +            // 0 <= (qest - qj) <= 2
   1.413 +
   1.414 +            // Refine qj estimate
   1.415 +            var ud0 = r.getDigit(j + n - 2, nrm);
   1.416 +            while ((qest * vd0) > ((rest * 0x10000) + ud0)) {
   1.417 +                --qest;
   1.418 +                rest += vd1;
   1.419 +            }
   1.420 +
   1.421 +            // 0 <= (qest - qj) <= 1
   1.422 +            
   1.423 +            // Multiply and subtract
   1.424 +            var carry = 0;
   1.425 +            for (var i = 0; i < n; ++i) {
   1.426 +                var vi = qest * v.getDigit(i, nrm);
   1.427 +                var ui = r.getDigit(i + j, nrm) - carry - (vi & 0xffff);
   1.428 +                r.setDigit(i + j, nrm, ui);
   1.429 +                carry = (vi >>> 16) - (ui >> 16);
   1.430 +            }
   1.431 +            var uj = ud2 - carry;
   1.432 +
   1.433 +            if (uj < 0) {
   1.434 +                // qest - qj = 1
   1.435 +
   1.436 +                // Add back
   1.437 +                --qest;
   1.438 +                var carry = 0;
   1.439 +                for (var i = 0; i < n; ++i) {
   1.440 +                    var ui = r.getDigit(i + j, nrm) + v.getDigit(i, nrm)
   1.441 +                                 + carry;
   1.442 +                    r.setDigit(i + j, nrm, ui);
   1.443 +                    carry = ui >> 16;
   1.444 +                }
   1.445 +                uj += carry;
   1.446 +            }
   1.447 +
   1.448 +            q.setDigit(j, 0, qest);
   1.449 +            r.setDigit(j + n, nrm, uj);
   1.450 +        }
   1.451 +    }
   1.452 +
   1.453 +    numberPrototype.div32 = function(x) {
   1.454 +        if (x === 0) {
   1.455 +            __handleDivByZero();
   1.456 +        }
   1.457 +
   1.458 +        return (this / x) | 0;
   1.459 +    }
   1.460 +
   1.461 +    numberPrototype.mod32 = function(x) {
   1.462 +        if (x === 0) {
   1.463 +            __handleDivByZero();
   1.464 +        }
   1.465 +
   1.466 +        return (this % x);
   1.467 +    }
   1.468 +
   1.469 +    numberPrototype.div64 = function(x) {
   1.470 +        var negateResult = false;
   1.471 +        var u, v;
   1.472 +
   1.473 +        if ((this.high32() & 0x80000000) != 0) {
   1.474 +            u = this.neg64();
   1.475 +            negateResult = !negateResult;
   1.476 +        } else {
   1.477 +            u = this;        
   1.478 +        }
   1.479 +
   1.480 +        if ((x.high32() & 0x80000000) != 0) {
   1.481 +            v = x.neg64();
   1.482 +            negateResult = !negateResult;
   1.483 +        } else {
   1.484 +            v = x;
   1.485 +        }
   1.486 +
   1.487 +        if ((v === 0) && (v.high32() === 0)) {
   1.488 +            __handleDivByZero();
   1.489 +        }
   1.490 +
   1.491 +        if (u.high32() === 0) {
   1.492 +            if (v.high32() === 0) {
   1.493 +                var result = (u / v) | 0;
   1.494 +                return negateResult ? result.neg64() : result; 
   1.495 +            }
   1.496 +
   1.497 +            return 0;
   1.498 +        }
   1.499 +
   1.500 +        var u64 = new __Int64(u.high32(), u);
   1.501 +        var v64 = new __Int64(v.high32(), v);
   1.502 +        var q64 = new __Int64(0, 0);
   1.503 +        var r64 = new __Int64(0, 0);
   1.504 +
   1.505 +        __div64(q64, r64, u64, v64);
   1.506 +
   1.507 +        var result = q64.toNumber();
   1.508 +        return negateResult ? result.neg64() : result; 
   1.509 +    }
   1.510 +
   1.511 +    numberPrototype.mod64 = function(x) {
   1.512 +        var negateResult = false;
   1.513 +        var u, v;
   1.514 +        
   1.515 +        if ((this.high32() & 0x80000000) != 0) {
   1.516 +            u = this.neg64();
   1.517 +            negateResult = !negateResult;
   1.518 +        } else {
   1.519 +            u = this;        
   1.520 +        }
   1.521 +
   1.522 +        if ((x.high32() & 0x80000000) != 0) {
   1.523 +            v = x.neg64();
   1.524 +        } else {
   1.525 +            v = x;
   1.526 +        }
   1.527 +
   1.528 +        if ((v === 0) && (v.high32() === 0)) {
   1.529 +            __handleDivByZero();
   1.530 +        }
   1.531 +
   1.532 +        if (u.high32() === 0) {
   1.533 +            var result = (v.high32() === 0) ? (u % v) : u;
   1.534 +            return negateResult ? result.neg64() : result; 
   1.535 +        }
   1.536 +
   1.537 +        var u64 = new __Int64(u.high32(), u);
   1.538 +        var v64 = new __Int64(v.high32(), v);
   1.539 +        var q64 = new __Int64(0, 0);
   1.540 +        var r64 = new __Int64(0, 0);
   1.541 +
   1.542 +        __div64(q64, r64, u64, v64);
   1.543 +
   1.544 +        var result = r64.toNumber();
   1.545 +        return negateResult ? result.neg64() : result; 
   1.546 +    }
   1.547 +})(Number.prototype);