1.1 --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Tue Feb 05 16:32:14 2013 +0100
1.2 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Tue Feb 05 16:40:01 2013 +0100
1.3 @@ -113,15 +113,6 @@
1.4 return hi.next32(low);
1.5 };
1.6
1.7 -Number.prototype.div64 = function(x) {
1.8 - var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough
1.9 - if (low > __m32) {
1.10 - var hi = Math.floor(low / (__m32+1)) | 0;
1.11 - return hi.next32(low % (__m32+1));
1.12 - }
1.13 - return low;
1.14 -};
1.15 -
1.16 Number.prototype.and64 = function(x) {
1.17 var low = this & x;
1.18 low += (low < 0) ? (__m32+1) : 0;
1.19 @@ -213,3 +204,313 @@
1.20 var ret = hi.next32(low);
1.21 return ret.add64(1);
1.22 };
1.23 +
1.24 +function __initDivMod(numberPrototype) {
1.25 + function __Int64(hi32, lo32) {
1.26 + this.hi32 = hi32 | 0;
1.27 + this.lo32 = lo32 | 0;
1.28 +
1.29 + this.get32 = function(bitIndex) {
1.30 + var v0;
1.31 + var v1;
1.32 + bitIndex += 32;
1.33 + var selector = bitIndex >>> 5;
1.34 + switch (selector) {
1.35 + case 0:
1.36 + v0 = 0;
1.37 + v1 = this.lo32;
1.38 + break;
1.39 + case 1:
1.40 + v0 = this.lo32;
1.41 + v1 = this.hi32;
1.42 + break;
1.43 + case 2:
1.44 + v0 = this.hi32;
1.45 + v1 = 0;
1.46 + break
1.47 + default:
1.48 + return 0;
1.49 + }
1.50 +
1.51 + var shift = bitIndex & 31;
1.52 + if (shift === 0) {
1.53 + return v0;
1.54 + }
1.55 +
1.56 + return (v1 << (32 - shift)) | (v0 >>> shift);
1.57 + }
1.58 +
1.59 + this.get16 = function(bitIndex) {
1.60 + return this.get32(bitIndex) & 0xffff;
1.61 + }
1.62 +
1.63 + this.set16 = function(bitIndex, value) {
1.64 + bitIndex += 32;
1.65 + var shift = bitIndex & 15;
1.66 + var svalue = (value & 0xffff) << shift;
1.67 + var smask = 0xffff << shift;
1.68 + var selector = bitIndex >>> 4;
1.69 + switch (selector) {
1.70 + case 0:
1.71 + break;
1.72 + case 1:
1.73 + this.lo32 = (this.lo32 & ~(smask >>> 16))
1.74 + | (svalue >>> 16);
1.75 + break;
1.76 + case 2:
1.77 + this.lo32 = (this.lo32 & ~smask) | svalue;
1.78 + break;
1.79 + case 3:
1.80 + this.lo32 = (this.lo32 & ~(smask << 16))
1.81 + | (svalue << 16);
1.82 + this.hi32 = (this.hi32 & ~(smask >>> 16))
1.83 + | (svalue >>> 16);
1.84 + break;
1.85 + case 4:
1.86 + this.hi32 = (this.hi32 & ~smask) | svalue;
1.87 + break;
1.88 + case 5:
1.89 + this.hi32 = (this.hi32 & ~(smask << 16))
1.90 + | (svalue << 16);
1.91 + break;
1.92 + }
1.93 + }
1.94 +
1.95 + this.getDigit = function(index, shift) {
1.96 + return this.get16((index << 4) - shift);
1.97 + }
1.98 +
1.99 + this.getTwoDigits = function(index, shift) {
1.100 + return this.get32(((index - 1) << 4) - shift);
1.101 + }
1.102 +
1.103 + this.setDigit = function(index, shift, value) {
1.104 + this.set16((index << 4) - shift, value);
1.105 + }
1.106 +
1.107 + this.countSignificantDigits = function() {
1.108 + var sd;
1.109 + var remaining;
1.110 +
1.111 + if (this.hi32 === 0) {
1.112 + if (this.lo32 === 0) {
1.113 + return 0;
1.114 + }
1.115 +
1.116 + sd = 2;
1.117 + remaining = this.lo32;
1.118 + } else {
1.119 + sd = 4;
1.120 + remaining = this.hi32;
1.121 + }
1.122 +
1.123 + if (remaining < 0) {
1.124 + return sd;
1.125 + }
1.126 +
1.127 + return (remaining < 65536) ? sd - 1 : sd;
1.128 + }
1.129 +
1.130 + this.toNumber = function() {
1.131 + var lo32 = this.lo32;
1.132 + if (lo32 < 0) {
1.133 + lo32 += 0x100000000;
1.134 + }
1.135 +
1.136 + return this.hi32.next32(lo32);
1.137 + }
1.138 + }
1.139 +
1.140 + function __countLeadingZeroes16(number) {
1.141 + var nlz = 0;
1.142 +
1.143 + if (number < 256) {
1.144 + nlz += 8;
1.145 + number <<= 8;
1.146 + }
1.147 +
1.148 + if (number < 4096) {
1.149 + nlz += 4;
1.150 + number <<= 4;
1.151 + }
1.152 +
1.153 + if (number < 16384) {
1.154 + nlz += 2;
1.155 + number <<= 2;
1.156 + }
1.157 +
1.158 + return (number < 32768) ? nlz + 1 : nlz;
1.159 + }
1.160 +
1.161 + // q = u / v; r = u - q * v;
1.162 + // v != 0
1.163 + function __div64(q, r, u, v) {
1.164 + var m = u.countSignificantDigits();
1.165 + var n = v.countSignificantDigits();
1.166 +
1.167 + q.hi32 = q.lo32 = 0;
1.168 +
1.169 + if (n === 1) {
1.170 + // v has single digit
1.171 + var vd = v.getDigit(0, 0);
1.172 + var carry = 0;
1.173 + for (var i = m - 1; i >= 0; --i) {
1.174 + var ui = (carry << 16) | u.getDigit(i, 0);
1.175 + if (ui < 0) {
1.176 + ui += 0x100000000;
1.177 + }
1.178 + var qi = (ui / vd) | 0;
1.179 + q.setDigit(i, 0, qi);
1.180 + carry = ui - qi * vd;
1.181 + }
1.182 +
1.183 + r.hi32 = 0;
1.184 + r.lo32 = carry;
1.185 + return;
1.186 + }
1.187 +
1.188 + r.hi32 = u.hi32;
1.189 + r.lo32 = u.lo32;
1.190 +
1.191 + if (m < n) {
1.192 + return;
1.193 + }
1.194 +
1.195 + // Normalize
1.196 + var nrm = __countLeadingZeroes16(v.getDigit(n - 1, 0));
1.197 +
1.198 + var vd1 = v.getDigit(n - 1, nrm);
1.199 + var vd0 = v.getDigit(n - 2, nrm);
1.200 + for (var j = m - n; j >= 0; --j) {
1.201 + // Calculate qj estimate
1.202 + var ud21 = r.getTwoDigits(j + n, nrm);
1.203 + var ud2 = ud21 >>> 16;
1.204 + if (ud21 < 0) {
1.205 + ud21 += 0x100000000;
1.206 + }
1.207 +
1.208 + var qest = (ud2 === vd1) ? 0xFFFF : ((ud21 / vd1) | 0);
1.209 + var rest = ud21 - qest * vd1;
1.210 +
1.211 + // 0 <= (qest - qj) <= 2
1.212 +
1.213 + // Refine qj estimate
1.214 + var ud0 = r.getDigit(j + n - 2, nrm);
1.215 + while ((qest * vd0) > ((rest * 0x10000) + ud0)) {
1.216 + --qest;
1.217 + rest += vd1;
1.218 + }
1.219 +
1.220 + // 0 <= (qest - qj) <= 1
1.221 +
1.222 + // Multiply and subtract
1.223 + var carry = 0;
1.224 + for (var i = 0; i < n; ++i) {
1.225 + var vi = qest * v.getDigit(i, nrm);
1.226 + var ui = r.getDigit(i + j, nrm) - carry - (vi & 0xffff);
1.227 + r.setDigit(i + j, nrm, ui);
1.228 + carry = (vi >>> 16) - (ui >> 16);
1.229 + }
1.230 + var uj = ud2 - carry;
1.231 +
1.232 + if (uj < 0) {
1.233 + // qest - qj = 1
1.234 +
1.235 + // Add back
1.236 + --qest;
1.237 + var carry = 0;
1.238 + for (var i = 0; i < n; ++i) {
1.239 + var ui = r.getDigit(i + j, nrm) + v.getDigit(i, nrm)
1.240 + + carry;
1.241 + r.setDigit(i + j, nrm, ui);
1.242 + carry = ui >> 16;
1.243 + }
1.244 + uj += carry;
1.245 + }
1.246 +
1.247 + q.setDigit(j, 0, qest);
1.248 + r.setDigit(j + n, nrm, uj);
1.249 + }
1.250 + }
1.251 +
1.252 + numberPrototype.div64 = function(x) {
1.253 + var negateResult = false;
1.254 + var u, v;
1.255 +
1.256 + if ((this.high32() & 0x80000000) != 0) {
1.257 + u = this.neg64();
1.258 + negateResult = !negateResult;
1.259 + } else {
1.260 + u = this;
1.261 + }
1.262 +
1.263 + if ((x.high32() & 0x80000000) != 0) {
1.264 + v = x.neg64();
1.265 + negateResult = !negateResult;
1.266 + } else {
1.267 + v = x;
1.268 + }
1.269 +
1.270 + if ((v === 0) && (v.high32() === 0)) {
1.271 + // TODO: throw
1.272 + }
1.273 +
1.274 + if (u.high32() === 0) {
1.275 + if (v.high32() === 0) {
1.276 + var result = (u / v) | 0;
1.277 + return negateResult ? result.neg64() : result;
1.278 + }
1.279 +
1.280 + return 0;
1.281 + }
1.282 +
1.283 + var u64 = new __Int64(u.high32(), u);
1.284 + var v64 = new __Int64(v.high32(), v);
1.285 + var q64 = new __Int64(0, 0);
1.286 + var r64 = new __Int64(0, 0);
1.287 +
1.288 + __div64(q64, r64, u64, v64);
1.289 +
1.290 + var result = q64.toNumber();
1.291 + return negateResult ? result.neg64() : result;
1.292 + }
1.293 +
1.294 + numberPrototype.mod64 = function(x) {
1.295 + var negateResult = false;
1.296 + var u, v;
1.297 +
1.298 + if ((this.high32() & 0x80000000) != 0) {
1.299 + u = this.neg64();
1.300 + negateResult = !negateResult;
1.301 + } else {
1.302 + u = this;
1.303 + }
1.304 +
1.305 + if ((x.high32() & 0x80000000) != 0) {
1.306 + v = x.neg64();
1.307 + } else {
1.308 + v = x;
1.309 + }
1.310 +
1.311 + if ((v === 0) && (v.high32() === 0)) {
1.312 + // TODO: throw
1.313 + }
1.314 +
1.315 + if (u.high32() === 0) {
1.316 + var result = (v.high32() === 0) ? (u % v) : u;
1.317 + return negateResult ? result.neg64() : result;
1.318 + }
1.319 +
1.320 + var u64 = new __Int64(u.high32(), u);
1.321 + var v64 = new __Int64(v.high32(), v);
1.322 + var q64 = new __Int64(0, 0);
1.323 + var r64 = new __Int64(0, 0);
1.324 +
1.325 + __div64(q64, r64, u64, v64);
1.326 +
1.327 + var result = r64.toNumber();
1.328 + return negateResult ? result.neg64() : result;
1.329 + }
1.330 +};
1.331 +
1.332 +__initDivMod(Number.prototype);
2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Feb 05 16:32:14 2013 +0100
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Feb 05 16:40:01 2013 +0100
2.3 @@ -570,7 +570,8 @@
2.4 emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI());
2.5 break;
2.6 case opc_lrem:
2.7 - emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL());
2.8 + emit(out, "@1 = @1.mod64(@2);",
2.9 + smapper.getL(1), smapper.popL());
2.10 break;
2.11 case opc_frem:
2.12 emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Tue Feb 05 16:32:14 2013 +0100
3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Tue Feb 05 16:40:01 2013 +0100
3.3 @@ -168,7 +168,7 @@
3.4 new byte[] { (byte)0x80, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 }
3.5 );
3.6 }
3.7 -
3.8 +
3.9 @Test public void longNegate3() throws Exception {
3.10 final long res = -0xfffffffffffffeddl;
3.11 assertExec("Long negate",
3.12 @@ -178,7 +178,6 @@
3.13 );
3.14 }
3.15
3.16 -
3.17 @Test public void longAddOverflow() throws Exception {
3.18 final long res = Long.MAX_VALUE + 1l;
3.19 assertExec("Addition 1+MAX",
3.20 @@ -278,7 +277,239 @@
3.21 new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e }
3.22 );
3.23 }
3.24 -
3.25 +
3.26 + @Test public void longDivideSmallPositiveNumbers() throws Exception {
3.27 + final long res = 0xabcdef / 0x123;
3.28 + assertExec("Division Small Positive Numbers",
3.29 + Numbers.class, "divL__J_3B_3B",
3.30 + Double.valueOf(res),
3.31 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
3.32 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x23 }
3.33 + );
3.34 + }
3.35 +
3.36 + @Test public void longDivideSmallNegativeNumbers() throws Exception {
3.37 + final long res = -0xabcdef / -0x123;
3.38 + assertExec("Division Small Negative Numbers",
3.39 + Numbers.class, "divL__J_3B_3B",
3.40 + Double.valueOf(res),
3.41 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x11 },
3.42 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
3.43 + );
3.44 + }
3.45 +
3.46 + @Test public void longDivideSmallMixedNumbers() throws Exception {
3.47 + final long res = 0xabcdef / -0x123;
3.48 + assertExec("Division Small Mixed Numbers",
3.49 + Numbers.class, "divL__J_3B_3B",
3.50 + Double.valueOf(res),
3.51 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
3.52 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
3.53 + );
3.54 + }
3.55 +
3.56 + @Test public void longDividePositiveNumbersOneDigitDenom()
3.57 + throws Exception {
3.58 + final long res = 0xabcdef0102ffffL / 0x654;
3.59 + assertExec("Division Positive Numbers One Digit Denom",
3.60 + Numbers.class, "divL__J_3B_3B",
3.61 + Double.valueOf(res),
3.62 + new byte[] { (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x01, (byte)0x02, (byte)0xff, (byte)0xff },
3.63 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
3.64 + );
3.65 + }
3.66 +
3.67 + @Test public void longDivideNegativeNumbersOneDigitDenom()
3.68 + throws Exception {
3.69 + final long res = -0xabcdef0102ffffL / -0x654;
3.70 + assertExec("Division Negative Numbers One Digit Denom",
3.71 + Numbers.class, "divL__J_3B_3B",
3.72 + Double.valueOf(res),
3.73 + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
3.74 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf9, (byte)0xac }
3.75 + );
3.76 + }
3.77 +
3.78 + @Test public void longDivideMixedNumbersOneDigitDenom()
3.79 + throws Exception {
3.80 + final long res = -0xabcdef0102ffffL / 0x654;
3.81 + assertExec("Division Mixed Numbers One Digit Denom",
3.82 + Numbers.class, "divL__J_3B_3B",
3.83 + Double.valueOf(res),
3.84 + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
3.85 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
3.86 + );
3.87 + }
3.88 +
3.89 + @Test public void longDividePositiveNumbersMultiDigitDenom()
3.90 + throws Exception {
3.91 + final long res = 0x7ffefc003322aabbL / 0x89ab1000L;
3.92 + assertExec("Division Positive Numbers Multi Digit Denom",
3.93 + Numbers.class, "divL__J_3B_3B",
3.94 + Double.valueOf(res),
3.95 + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
3.96 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x89, (byte)0xab, (byte)0x10, (byte)0x00 }
3.97 + );
3.98 + }
3.99 +
3.100 + @Test public void longDivideNegativeNumbersMultiDigitDenom()
3.101 + throws Exception {
3.102 + final long res = -0x7ffefc003322aabbL / -0x123489ab1001L;
3.103 + assertExec("Division Negative Numbers Multi Digit Denom",
3.104 + Numbers.class, "divL__J_3B_3B",
3.105 + Double.valueOf(res),
3.106 + new byte[] { (byte)0x80, (byte)0x01, (byte)0x03, (byte)0xff, (byte)0xcc, (byte)0xdd, (byte)0x55, (byte)0x45 },
3.107 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xed, (byte)0xcb, (byte)0x76, (byte)0x54, (byte)0xef, (byte)0xff }
3.108 + );
3.109 + }
3.110 +
3.111 + @Test public void longDivideMixedNumbersMultiDigitDenom()
3.112 + throws Exception {
3.113 + final long res = 0x7ffefc003322aabbL / -0x38f49b0b7574e36L;
3.114 + assertExec("Division Mixed Numbers Multi Digit Denom",
3.115 + Numbers.class, "divL__J_3B_3B",
3.116 + Double.valueOf(res),
3.117 + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
3.118 + new byte[] { (byte)0xfc, (byte)0x70, (byte)0xb6, (byte)0x4f, (byte)0x48, (byte)0xa8, (byte)0xb1, (byte)0xca }
3.119 + );
3.120 + }
3.121 +
3.122 + @Test public void longDivideWithOverflow() throws Exception {
3.123 + final long res = 0x8000fffe0000L / 0x8000ffffL;
3.124 + assertExec("Division With Overflow",
3.125 + Numbers.class, "divL__J_3B_3B",
3.126 + Double.valueOf(res),
3.127 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 },
3.128 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xff }
3.129 + );
3.130 + }
3.131 +
3.132 + @Test public void longDivideWithCorrection() throws Exception {
3.133 + final long res = 0x7fff800000000000L / 0x800000000001L;
3.134 + assertExec("Division With Correction",
3.135 + Numbers.class, "divL__J_3B_3B",
3.136 + Double.valueOf(res),
3.137 + new byte[] { (byte)0x7f, (byte)0xff, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
3.138 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 }
3.139 + );
3.140 + }
3.141 +
3.142 + @Test public void longModuloSmallPositiveNumbers() throws Exception {
3.143 + final long res = 0xabcdef % 0x123;
3.144 + assertExec("Modulo Small Positive Numbers",
3.145 + Numbers.class, "modL__J_3B_3B",
3.146 + Double.valueOf(res),
3.147 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
3.148 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x23 }
3.149 + );
3.150 + }
3.151 +
3.152 + @Test public void longModuloSmallNegativeNumbers() throws Exception {
3.153 + final long res = -0xabcdef % -0x123;
3.154 + assertExec("Modulo Small Negative Numbers",
3.155 + Numbers.class, "modL__J_3B_3B",
3.156 + Double.valueOf(res),
3.157 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x11 },
3.158 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
3.159 + );
3.160 + }
3.161 +
3.162 + @Test public void longModuloSmallMixedNumbers() throws Exception {
3.163 + final long res = 0xabcdef % -0x123;
3.164 + assertExec("Modulo Small Mixed Numbers",
3.165 + Numbers.class, "modL__J_3B_3B",
3.166 + Double.valueOf(res),
3.167 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef },
3.168 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd }
3.169 + );
3.170 + }
3.171 +
3.172 + @Test public void longModuloPositiveNumbersOneDigitDenom()
3.173 + throws Exception {
3.174 + final long res = 0xabcdef0102ffffL % 0x654;
3.175 + assertExec("Modulo Positive Numbers One Digit Denom",
3.176 + Numbers.class, "modL__J_3B_3B",
3.177 + Double.valueOf(res),
3.178 + new byte[] { (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x01, (byte)0x02, (byte)0xff, (byte)0xff },
3.179 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
3.180 + );
3.181 + }
3.182 +
3.183 + @Test public void longModuloNegativeNumbersOneDigitDenom()
3.184 + throws Exception {
3.185 + final long res = -0xabcdef0102ffffL % -0x654;
3.186 + assertExec("Modulo Negative Numbers One Digit Denom",
3.187 + Numbers.class, "modL__J_3B_3B",
3.188 + Double.valueOf(res),
3.189 + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
3.190 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf9, (byte)0xac }
3.191 + );
3.192 + }
3.193 +
3.194 + @Test public void longModuloMixedNumbersOneDigitDenom()
3.195 + throws Exception {
3.196 + final long res = -0xabcdef0102ffffL % 0x654;
3.197 + assertExec("Modulo Mixed Numbers One Digit Denom",
3.198 + Numbers.class, "modL__J_3B_3B",
3.199 + Double.valueOf(res),
3.200 + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 },
3.201 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 }
3.202 + );
3.203 + }
3.204 +
3.205 + @Test public void longModuloPositiveNumbersMultiDigitDenom()
3.206 + throws Exception {
3.207 + final long res = 0x7ffefc003322aabbL % 0x89ab1000L;
3.208 + assertExec("Modulo Positive Numbers Multi Digit Denom",
3.209 + Numbers.class, "modL__J_3B_3B",
3.210 + Double.valueOf(res),
3.211 + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
3.212 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x89, (byte)0xab, (byte)0x10, (byte)0x00 }
3.213 + );
3.214 + }
3.215 +
3.216 + @Test public void longModuloNegativeNumbersMultiDigitDenom()
3.217 + throws Exception {
3.218 + final long res = -0x7ffefc003322aabbL % -0x123489ab1001L;
3.219 + assertExec("Modulo Negative Numbers Multi Digit Denom",
3.220 + Numbers.class, "modL__J_3B_3B",
3.221 + Double.valueOf(res),
3.222 + new byte[] { (byte)0x80, (byte)0x01, (byte)0x03, (byte)0xff, (byte)0xcc, (byte)0xdd, (byte)0x55, (byte)0x45 },
3.223 + new byte[] { (byte)0xff, (byte)0xff, (byte)0xed, (byte)0xcb, (byte)0x76, (byte)0x54, (byte)0xef, (byte)0xff }
3.224 + );
3.225 + }
3.226 +
3.227 + @Test public void longModuloMixedNumbersMultiDigitDenom()
3.228 + throws Exception {
3.229 + final long res = 0x7ffefc003322aabbL % -0x38f49b0b7574e36L;
3.230 + assertExec("Modulo Mixed Numbers Multi Digit Denom",
3.231 + Numbers.class, "modL__J_3B_3B",
3.232 + Double.valueOf(res),
3.233 + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb },
3.234 + new byte[] { (byte)0xfc, (byte)0x70, (byte)0xb6, (byte)0x4f, (byte)0x48, (byte)0xa8, (byte)0xb1, (byte)0xca }
3.235 + );
3.236 + }
3.237 +
3.238 + @Test public void longModuloWithOverflow() throws Exception {
3.239 + final long res = 0x8000fffe0000L % 0x8000ffffL;
3.240 + assertExec("Modulo With Overflow",
3.241 + Numbers.class, "modL__J_3B_3B",
3.242 + Double.valueOf(res),
3.243 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 },
3.244 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xff }
3.245 + );
3.246 + }
3.247 +
3.248 + @Test public void longModuloWithCorrection() throws Exception {
3.249 + final long res = 0x7fff800000000000L % 0x800000000001L;
3.250 + assertExec("Modulo With Correction",
3.251 + Numbers.class, "modL__J_3B_3B",
3.252 + Double.valueOf(res),
3.253 + new byte[] { (byte)0x7f, (byte)0xff, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
3.254 + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 }
3.255 + );
3.256 + }
3.257 +
3.258 @Test public void longShiftL1() throws Exception {
3.259 final long res = 0x00fa37d7763e0ca1l << 5;
3.260 assertExec("Long << 5",
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Tue Feb 05 16:32:14 2013 +0100
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Tue Feb 05 16:40:01 2013 +0100
4.3 @@ -102,12 +102,20 @@
4.4 return (disX.readLong() * disY.readLong());
4.5 }
4.6
4.7 - public static long divL(long x, long y) {
4.8 - return (x / y);
4.9 + public static long divL(byte[] arrX, byte[] arrY) throws IOException {
4.10 + ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
4.11 + DataInputStream disX = new DataInputStream(isX);
4.12 + ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
4.13 + DataInputStream disY = new DataInputStream(isY);
4.14 + return (disX.readLong() / disY.readLong());
4.15 }
4.16
4.17 - public static long modL(long x, long y) {
4.18 - return (x % y);
4.19 + public static long modL(byte[] arrX, byte[] arrY) throws IOException {
4.20 + ByteArrayInputStream isX = new ByteArrayInputStream(arrX);
4.21 + DataInputStream disX = new DataInputStream(isX);
4.22 + ByteArrayInputStream isY = new ByteArrayInputStream(arrY);
4.23 + DataInputStream disY = new DataInputStream(isY);
4.24 + return (disX.readLong() % disY.readLong());
4.25 }
4.26
4.27 public static long shlL(byte[] arrValue, int nBits) throws IOException {