# HG changeset patch # User Lubomir Nerad # Date 1360078801 -3600 # Node ID eecf6077ec4e677086299ca071360827eb4a845f # Parent 7d3da112e2c1e137c247d00bc544c7a193e25bd3 Support for Long division + tests diff -r 7d3da112e2c1 -r eecf6077ec4e emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js --- a/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Tue Feb 05 16:32:14 2013 +0100 +++ b/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Tue Feb 05 16:40:01 2013 +0100 @@ -113,15 +113,6 @@ return hi.next32(low); }; -Number.prototype.div64 = function(x) { - var low = Math.floor(this.toFP() / x.toFP()); // TODO: not exact enough - if (low > __m32) { - var hi = Math.floor(low / (__m32+1)) | 0; - return hi.next32(low % (__m32+1)); - } - return low; -}; - Number.prototype.and64 = function(x) { var low = this & x; low += (low < 0) ? (__m32+1) : 0; @@ -213,3 +204,313 @@ var ret = hi.next32(low); return ret.add64(1); }; + +function __initDivMod(numberPrototype) { + function __Int64(hi32, lo32) { + this.hi32 = hi32 | 0; + this.lo32 = lo32 | 0; + + this.get32 = function(bitIndex) { + var v0; + var v1; + bitIndex += 32; + var selector = bitIndex >>> 5; + switch (selector) { + case 0: + v0 = 0; + v1 = this.lo32; + break; + case 1: + v0 = this.lo32; + v1 = this.hi32; + break; + case 2: + v0 = this.hi32; + v1 = 0; + break + default: + return 0; + } + + var shift = bitIndex & 31; + if (shift === 0) { + return v0; + } + + return (v1 << (32 - shift)) | (v0 >>> shift); + } + + this.get16 = function(bitIndex) { + return this.get32(bitIndex) & 0xffff; + } + + this.set16 = function(bitIndex, value) { + bitIndex += 32; + var shift = bitIndex & 15; + var svalue = (value & 0xffff) << shift; + var smask = 0xffff << shift; + var selector = bitIndex >>> 4; + switch (selector) { + case 0: + break; + case 1: + this.lo32 = (this.lo32 & ~(smask >>> 16)) + | (svalue >>> 16); + break; + case 2: + this.lo32 = (this.lo32 & ~smask) | svalue; + break; + case 3: + this.lo32 = (this.lo32 & ~(smask << 16)) + | (svalue << 16); + this.hi32 = (this.hi32 & ~(smask >>> 16)) + | (svalue >>> 16); + break; + case 4: + this.hi32 = (this.hi32 & ~smask) | svalue; + break; + case 5: + this.hi32 = (this.hi32 & ~(smask << 16)) + | (svalue << 16); + break; + } + } + + this.getDigit = function(index, shift) { + return this.get16((index << 4) - shift); + } + + this.getTwoDigits = function(index, shift) { + return this.get32(((index - 1) << 4) - shift); + } + + this.setDigit = function(index, shift, value) { + this.set16((index << 4) - shift, value); + } + + this.countSignificantDigits = function() { + var sd; + var remaining; + + if (this.hi32 === 0) { + if (this.lo32 === 0) { + return 0; + } + + sd = 2; + remaining = this.lo32; + } else { + sd = 4; + remaining = this.hi32; + } + + if (remaining < 0) { + return sd; + } + + return (remaining < 65536) ? sd - 1 : sd; + } + + this.toNumber = function() { + var lo32 = this.lo32; + if (lo32 < 0) { + lo32 += 0x100000000; + } + + return this.hi32.next32(lo32); + } + } + + function __countLeadingZeroes16(number) { + var nlz = 0; + + if (number < 256) { + nlz += 8; + number <<= 8; + } + + if (number < 4096) { + nlz += 4; + number <<= 4; + } + + if (number < 16384) { + nlz += 2; + number <<= 2; + } + + return (number < 32768) ? nlz + 1 : nlz; + } + + // q = u / v; r = u - q * v; + // v != 0 + function __div64(q, r, u, v) { + var m = u.countSignificantDigits(); + var n = v.countSignificantDigits(); + + q.hi32 = q.lo32 = 0; + + if (n === 1) { + // v has single digit + var vd = v.getDigit(0, 0); + var carry = 0; + for (var i = m - 1; i >= 0; --i) { + var ui = (carry << 16) | u.getDigit(i, 0); + if (ui < 0) { + ui += 0x100000000; + } + var qi = (ui / vd) | 0; + q.setDigit(i, 0, qi); + carry = ui - qi * vd; + } + + r.hi32 = 0; + r.lo32 = carry; + return; + } + + r.hi32 = u.hi32; + r.lo32 = u.lo32; + + if (m < n) { + return; + } + + // Normalize + var nrm = __countLeadingZeroes16(v.getDigit(n - 1, 0)); + + var vd1 = v.getDigit(n - 1, nrm); + var vd0 = v.getDigit(n - 2, nrm); + for (var j = m - n; j >= 0; --j) { + // Calculate qj estimate + var ud21 = r.getTwoDigits(j + n, nrm); + var ud2 = ud21 >>> 16; + if (ud21 < 0) { + ud21 += 0x100000000; + } + + var qest = (ud2 === vd1) ? 0xFFFF : ((ud21 / vd1) | 0); + var rest = ud21 - qest * vd1; + + // 0 <= (qest - qj) <= 2 + + // Refine qj estimate + var ud0 = r.getDigit(j + n - 2, nrm); + while ((qest * vd0) > ((rest * 0x10000) + ud0)) { + --qest; + rest += vd1; + } + + // 0 <= (qest - qj) <= 1 + + // Multiply and subtract + var carry = 0; + for (var i = 0; i < n; ++i) { + var vi = qest * v.getDigit(i, nrm); + var ui = r.getDigit(i + j, nrm) - carry - (vi & 0xffff); + r.setDigit(i + j, nrm, ui); + carry = (vi >>> 16) - (ui >> 16); + } + var uj = ud2 - carry; + + if (uj < 0) { + // qest - qj = 1 + + // Add back + --qest; + var carry = 0; + for (var i = 0; i < n; ++i) { + var ui = r.getDigit(i + j, nrm) + v.getDigit(i, nrm) + + carry; + r.setDigit(i + j, nrm, ui); + carry = ui >> 16; + } + uj += carry; + } + + q.setDigit(j, 0, qest); + r.setDigit(j + n, nrm, uj); + } + } + + numberPrototype.div64 = function(x) { + var negateResult = false; + var u, v; + + if ((this.high32() & 0x80000000) != 0) { + u = this.neg64(); + negateResult = !negateResult; + } else { + u = this; + } + + if ((x.high32() & 0x80000000) != 0) { + v = x.neg64(); + negateResult = !negateResult; + } else { + v = x; + } + + if ((v === 0) && (v.high32() === 0)) { + // TODO: throw + } + + if (u.high32() === 0) { + if (v.high32() === 0) { + var result = (u / v) | 0; + return negateResult ? result.neg64() : result; + } + + return 0; + } + + var u64 = new __Int64(u.high32(), u); + var v64 = new __Int64(v.high32(), v); + var q64 = new __Int64(0, 0); + var r64 = new __Int64(0, 0); + + __div64(q64, r64, u64, v64); + + var result = q64.toNumber(); + return negateResult ? result.neg64() : result; + } + + numberPrototype.mod64 = function(x) { + var negateResult = false; + var u, v; + + if ((this.high32() & 0x80000000) != 0) { + u = this.neg64(); + negateResult = !negateResult; + } else { + u = this; + } + + if ((x.high32() & 0x80000000) != 0) { + v = x.neg64(); + } else { + v = x; + } + + if ((v === 0) && (v.high32() === 0)) { + // TODO: throw + } + + if (u.high32() === 0) { + var result = (v.high32() === 0) ? (u % v) : u; + return negateResult ? result.neg64() : result; + } + + var u64 = new __Int64(u.high32(), u); + var v64 = new __Int64(v.high32(), v); + var q64 = new __Int64(0, 0); + var r64 = new __Int64(0, 0); + + __div64(q64, r64, u64, v64); + + var result = r64.toNumber(); + return negateResult ? result.neg64() : result; + } +}; + +__initDivMod(Number.prototype); diff -r 7d3da112e2c1 -r eecf6077ec4e vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Feb 05 16:32:14 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Feb 05 16:40:01 2013 +0100 @@ -570,7 +570,8 @@ emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI()); break; case opc_lrem: - emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL()); + emit(out, "@1 = @1.mod64(@2);", + smapper.getL(1), smapper.popL()); break; case opc_frem: emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF()); diff -r 7d3da112e2c1 -r eecf6077ec4e vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Tue Feb 05 16:32:14 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Tue Feb 05 16:40:01 2013 +0100 @@ -168,7 +168,7 @@ new byte[] { (byte)0x80, (byte)0xfa, (byte)0x37, (byte)0xd7, (byte)0x76, (byte)0x3e, (byte)0x0c, (byte)0xa1 } ); } - + @Test public void longNegate3() throws Exception { final long res = -0xfffffffffffffeddl; assertExec("Long negate", @@ -178,7 +178,6 @@ ); } - @Test public void longAddOverflow() throws Exception { final long res = Long.MAX_VALUE + 1l; assertExec("Addition 1+MAX", @@ -278,7 +277,239 @@ new byte[] { (byte)0xa7, (byte)0xb3, (byte)0x43, (byte)0x2f, (byte)0xff, (byte)0x00, (byte)0x12, (byte)0x3e } ); } - + + @Test public void longDivideSmallPositiveNumbers() throws Exception { + final long res = 0xabcdef / 0x123; + assertExec("Division Small Positive Numbers", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x23 } + ); + } + + @Test public void longDivideSmallNegativeNumbers() throws Exception { + final long res = -0xabcdef / -0x123; + assertExec("Division Small Negative Numbers", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x11 }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd } + ); + } + + @Test public void longDivideSmallMixedNumbers() throws Exception { + final long res = 0xabcdef / -0x123; + assertExec("Division Small Mixed Numbers", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd } + ); + } + + @Test public void longDividePositiveNumbersOneDigitDenom() + throws Exception { + final long res = 0xabcdef0102ffffL / 0x654; + assertExec("Division Positive Numbers One Digit Denom", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x01, (byte)0x02, (byte)0xff, (byte)0xff }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 } + ); + } + + @Test public void longDivideNegativeNumbersOneDigitDenom() + throws Exception { + final long res = -0xabcdef0102ffffL / -0x654; + assertExec("Division Negative Numbers One Digit Denom", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf9, (byte)0xac } + ); + } + + @Test public void longDivideMixedNumbersOneDigitDenom() + throws Exception { + final long res = -0xabcdef0102ffffL / 0x654; + assertExec("Division Mixed Numbers One Digit Denom", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 } + ); + } + + @Test public void longDividePositiveNumbersMultiDigitDenom() + throws Exception { + final long res = 0x7ffefc003322aabbL / 0x89ab1000L; + assertExec("Division Positive Numbers Multi Digit Denom", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x89, (byte)0xab, (byte)0x10, (byte)0x00 } + ); + } + + @Test public void longDivideNegativeNumbersMultiDigitDenom() + throws Exception { + final long res = -0x7ffefc003322aabbL / -0x123489ab1001L; + assertExec("Division Negative Numbers Multi Digit Denom", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x80, (byte)0x01, (byte)0x03, (byte)0xff, (byte)0xcc, (byte)0xdd, (byte)0x55, (byte)0x45 }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xed, (byte)0xcb, (byte)0x76, (byte)0x54, (byte)0xef, (byte)0xff } + ); + } + + @Test public void longDivideMixedNumbersMultiDigitDenom() + throws Exception { + final long res = 0x7ffefc003322aabbL / -0x38f49b0b7574e36L; + assertExec("Division Mixed Numbers Multi Digit Denom", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb }, + new byte[] { (byte)0xfc, (byte)0x70, (byte)0xb6, (byte)0x4f, (byte)0x48, (byte)0xa8, (byte)0xb1, (byte)0xca } + ); + } + + @Test public void longDivideWithOverflow() throws Exception { + final long res = 0x8000fffe0000L / 0x8000ffffL; + assertExec("Division With Overflow", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xff } + ); + } + + @Test public void longDivideWithCorrection() throws Exception { + final long res = 0x7fff800000000000L / 0x800000000001L; + assertExec("Division With Correction", + Numbers.class, "divL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x7f, (byte)0xff, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 } + ); + } + + @Test public void longModuloSmallPositiveNumbers() throws Exception { + final long res = 0xabcdef % 0x123; + assertExec("Modulo Small Positive Numbers", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x23 } + ); + } + + @Test public void longModuloSmallNegativeNumbers() throws Exception { + final long res = -0xabcdef % -0x123; + assertExec("Modulo Small Negative Numbers", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x11 }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd } + ); + } + + @Test public void longModuloSmallMixedNumbers() throws Exception { + final long res = 0xabcdef % -0x123; + assertExec("Modulo Small Mixed Numbers", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfe, (byte)0xdd } + ); + } + + @Test public void longModuloPositiveNumbersOneDigitDenom() + throws Exception { + final long res = 0xabcdef0102ffffL % 0x654; + assertExec("Modulo Positive Numbers One Digit Denom", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0xab, (byte)0xcd, (byte)0xef, (byte)0x01, (byte)0x02, (byte)0xff, (byte)0xff }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 } + ); + } + + @Test public void longModuloNegativeNumbersOneDigitDenom() + throws Exception { + final long res = -0xabcdef0102ffffL % -0x654; + assertExec("Modulo Negative Numbers One Digit Denom", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf9, (byte)0xac } + ); + } + + @Test public void longModuloMixedNumbersOneDigitDenom() + throws Exception { + final long res = -0xabcdef0102ffffL % 0x654; + assertExec("Modulo Mixed Numbers One Digit Denom", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0xff, (byte)0x54, (byte)0x32, (byte)0x10, (byte)0xfe, (byte)0xfd, (byte)0x00, (byte)0x01 }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x54 } + ); + } + + @Test public void longModuloPositiveNumbersMultiDigitDenom() + throws Exception { + final long res = 0x7ffefc003322aabbL % 0x89ab1000L; + assertExec("Modulo Positive Numbers Multi Digit Denom", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x89, (byte)0xab, (byte)0x10, (byte)0x00 } + ); + } + + @Test public void longModuloNegativeNumbersMultiDigitDenom() + throws Exception { + final long res = -0x7ffefc003322aabbL % -0x123489ab1001L; + assertExec("Modulo Negative Numbers Multi Digit Denom", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x80, (byte)0x01, (byte)0x03, (byte)0xff, (byte)0xcc, (byte)0xdd, (byte)0x55, (byte)0x45 }, + new byte[] { (byte)0xff, (byte)0xff, (byte)0xed, (byte)0xcb, (byte)0x76, (byte)0x54, (byte)0xef, (byte)0xff } + ); + } + + @Test public void longModuloMixedNumbersMultiDigitDenom() + throws Exception { + final long res = 0x7ffefc003322aabbL % -0x38f49b0b7574e36L; + assertExec("Modulo Mixed Numbers Multi Digit Denom", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x7f, (byte)0xfe, (byte)0xfc, (byte)0x00, (byte)0x33, (byte)0x22, (byte)0xaa, (byte)0xbb }, + new byte[] { (byte)0xfc, (byte)0x70, (byte)0xb6, (byte)0x4f, (byte)0x48, (byte)0xa8, (byte)0xb1, (byte)0xca } + ); + } + + @Test public void longModuloWithOverflow() throws Exception { + final long res = 0x8000fffe0000L % 0x8000ffffL; + assertExec("Modulo With Overflow", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0xff, (byte)0xff } + ); + } + + @Test public void longModuloWithCorrection() throws Exception { + final long res = 0x7fff800000000000L % 0x800000000001L; + assertExec("Modulo With Correction", + Numbers.class, "modL__J_3B_3B", + Double.valueOf(res), + new byte[] { (byte)0x7f, (byte)0xff, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }, + new byte[] { (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 } + ); + } + @Test public void longShiftL1() throws Exception { final long res = 0x00fa37d7763e0ca1l << 5; assertExec("Long << 5", diff -r 7d3da112e2c1 -r eecf6077ec4e vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Tue Feb 05 16:32:14 2013 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Tue Feb 05 16:40:01 2013 +0100 @@ -102,12 +102,20 @@ return (disX.readLong() * disY.readLong()); } - public static long divL(long x, long y) { - return (x / y); + public static long divL(byte[] arrX, byte[] arrY) throws IOException { + ByteArrayInputStream isX = new ByteArrayInputStream(arrX); + DataInputStream disX = new DataInputStream(isX); + ByteArrayInputStream isY = new ByteArrayInputStream(arrY); + DataInputStream disY = new DataInputStream(isY); + return (disX.readLong() / disY.readLong()); } - public static long modL(long x, long y) { - return (x % y); + public static long modL(byte[] arrX, byte[] arrY) throws IOException { + ByteArrayInputStream isX = new ByteArrayInputStream(arrX); + DataInputStream disX = new DataInputStream(isX); + ByteArrayInputStream isY = new ByteArrayInputStream(arrY); + DataInputStream disY = new DataInputStream(isY); + return (disX.readLong() % disY.readLong()); } public static long shlL(byte[] arrValue, int nBits) throws IOException {