scratch0-5 / plugins /LargeIntegers.js
soiz1's picture
Upload folder using huggingface_hub
8f3f8db verified
/* Smalltalk from Squeak4.5 with VMMaker 4.13.6 translated as JS source on 3 November 2014 1:52:21 pm */
/* Automatically generated by
JSSmartSyntaxPluginCodeGenerator VMMakerJS-bf.15 uuid: fd4e10f2-3773-4e80-8bb5-c4b471a014e5
from
LargeIntegersPlugin VMMaker-bf.353 uuid: 8ae25e7e-8d2c-451e-8277-598b30e9c002
*/
(function LargeIntegers() {
"use strict";
var VM_PROXY_MAJOR = 1;
var VM_PROXY_MINOR = 11;
/*** Functions ***/
function CLASSOF(obj) { return typeof obj === "number" ? interpreterProxy.classSmallInteger() : obj.sqClass }
function SIZEOF(obj) { return obj.pointers ? obj.pointers.length : obj.words ? obj.words.length : obj.bytes ? obj.bytes.length : 0 }
function BYTESIZEOF(obj) { return obj.bytes ? obj.bytes.length : obj.words ? obj.words.length * 4 : 0 }
function DIV(a, b) { return Math.floor(a / b) | 0; } // integer division
function MOD(a, b) { return a - DIV(a, b) * b | 0; } // signed modulus
function SHL(a, b) { return b > 31 ? 0 : a << b; } // fix JS shift
function SHR(a, b) { return b > 31 ? 0 : a >>> b; } // fix JS shift
function SHIFT(a, b) { return b < 0 ? (b < -31 ? 0 : a >>> (0-b) ) : (b > 31 ? 0 : a << b); }
/*** Variables ***/
var andOpIndex = 0;
var interpreterProxy = null;
var moduleName = "LargeIntegers v1.5 (e)";
var orOpIndex = 1;
var xorOpIndex = 2;
/* Argument has to be aBytesOop! */
/* Tests for any magnitude bits in the interval from start to stopArg. */
function anyBitOfBytesfromto(aBytesOop, start, stopArg) {
var lastByteIx;
var digit;
var magnitude;
var leftShift;
var rightShift;
var firstByteIx;
var stop;
var mask;
var ix;
// missing DebugCode;
if ((start < 1) || (stopArg < 1)) {
return interpreterProxy.primitiveFail();
}
magnitude = aBytesOop;
stop = Math.min(stopArg, highBitOfBytes(magnitude));
if (start > stop) {
return false;
}
firstByteIx = ((start - 1) >> 3) + 1;
lastByteIx = ((stop - 1) >> 3) + 1;
rightShift = MOD((start - 1), 8);
leftShift = 7 - (MOD((stop - 1), 8));
if (firstByteIx === lastByteIx) {
mask = (SHL(255, rightShift)) & (SHR(255, leftShift));
digit = digitOfBytesat(magnitude, firstByteIx);
return (digit & mask) !== 0;
}
if ((SHR(digitOfBytesat(magnitude, firstByteIx), rightShift)) !== 0) {
return true;
}
for (ix = (firstByteIx + 1); ix <= (lastByteIx - 1); ix++) {
if (digitOfBytesat(magnitude, ix) !== 0) {
return true;
}
}
if (((SHL(digitOfBytesat(magnitude, lastByteIx), leftShift)) & 255) !== 0) {
return true;
}
return false;
}
/* Precondition: bytesOop is not anInteger and a bytes object. */
/* Function #byteSizeOf: is used by the interpreter, be careful with name
clashes... */
function byteSizeOfBytes(bytesOop) {
return SIZEOF(bytesOop);
}
/* Attention: this method invalidates all oop's! Only newBytes is valid at return. */
/* Does not normalize. */
function bytesgrowTo(aBytesObject, newLen) {
var oldLen;
var copyLen;
var newBytes;
newBytes = interpreterProxy.instantiateClassindexableSize(CLASSOF(aBytesObject), newLen);
;
oldLen = BYTESIZEOF(aBytesObject);
if (oldLen < newLen) {
copyLen = oldLen;
} else {
copyLen = newLen;
}
cDigitCopyFromtolen(aBytesObject.bytes, newBytes.bytes, copyLen);
return newBytes;
}
/* Attention: this method invalidates all oop's! Only newBytes is valid at return. */
function bytesOrIntgrowTo(oop, len) {
var sq_class;
var val;
var newBytes;
if (typeof oop === "number") {
val = oop;
if (val < 0) {
sq_class = interpreterProxy.classLargeNegativeInteger();
} else {
sq_class = interpreterProxy.classLargePositiveInteger();
}
newBytes = interpreterProxy.instantiateClassindexableSize(sq_class, len);
cCopyIntValtoBytes(val, newBytes);
} else {
newBytes = bytesgrowTo(oop, len);
}
return newBytes;
}
function cCopyIntValtoBytes(val, bytes) {
var pByte;
var ix;
var ixLimiT;
pByte = bytes.bytes;
for (ix = 1, ixLimiT = cDigitLengthOfCSI(val); ix <= ixLimiT; ix++) {
pByte[ix - 1] = cDigitOfCSIat(val, ix);
}
}
/* pByteRes len = longLen; returns over.. */
function cDigitAddlenwithleninto(pByteShort, shortLen, pByteLong, longLen, pByteRes) {
var i;
var limit;
var accum;
accum = 0;
limit = shortLen - 1;
for (i = 0; i <= limit; i++) {
accum = ((accum >>> 8) + pByteShort[i]) + pByteLong[i];
pByteRes[i] = (accum & 255);
}
limit = longLen - 1;
for (i = shortLen; i <= limit; i++) {
accum = (accum >>> 8) + pByteLong[i];
pByteRes[i] = (accum & 255);
}
return accum >>> 8;
}
/* Precondition: pFirst len = pSecond len. */
function cDigitComparewithlen(pFirst, pSecond, len) {
var firstDigit;
var secondDigit;
var ix;
ix = len - 1;
while (ix >= 0) {
if (((secondDigit = pSecond[ix])) !== ((firstDigit = pFirst[ix]))) {
if (secondDigit < firstDigit) {
return 1;
} else {
return -1;
}
}
--ix;
}
return 0;
}
function cDigitCopyFromtolen(pFrom, pTo, len) {
var limit;
var i;
;
limit = len - 1;
for (i = 0; i <= limit; i++) {
pTo[i] = pFrom[i];
}
return 0;
}
function cDigitDivlenremlenquolen(pDiv, divLen, pRem, remLen, pQuo, quoLen) {
var b;
var q;
var a;
var dnh;
var lo;
var hi;
var r3;
var mul;
var cond;
var l;
var k;
var j;
var i;
var dl;
var ql;
var r1r2;
var dh;
var t;
/* Last actual byte of data (ST ix) */
dl = divLen - 1;
ql = quoLen;
dh = pDiv[dl - 1];
if (dl === 1) {
dnh = 0;
} else {
dnh = pDiv[dl - 2];
}
for (k = 1; k <= ql; k++) {
/* maintain quo*arg+rem=self */
/* Estimate rem/div by dividing the leading two digits of rem by dh. */
/* The estimate is q = qhi*16r100+qlo, where qhi and qlo are unsigned char. */
/* r1 := rem digitAt: j. */
j = (remLen + 1) - k;
if (pRem[j - 1] === dh) {
q = 255;
} else {
/* Compute q = (r1,r2)//dh, t = (r1,r2)\\dh. */
/* r2 := (rem digitAt: j - 2). */
r1r2 = pRem[j - 1];
r1r2 = (r1r2 << 8) + pRem[j - 2];
t = MOD(r1r2, dh);
/* Next compute (hi,lo) := q*dnh */
q = DIV(r1r2, dh);
mul = q * dnh;
hi = mul >>> 8;
/* Correct overestimate of q.
Max of 2 iterations through loop -- see Knuth vol. 2 */
lo = mul & 255;
if (j < 3) {
r3 = 0;
} else {
r3 = pRem[j - 3];
}
while (true) {
if ((t < hi) || ((t === hi) && (r3 < lo))) {
/* i.e. (t,r3) < (hi,lo) */
--q;
if (lo < dnh) {
--hi;
lo = (lo + 256) - dnh;
} else {
lo -= dnh;
}
cond = hi >= dh;
} else {
cond = false;
}
if (!(cond)) break;
hi -= dh;
}
}
l = j - dl;
a = 0;
for (i = 1; i <= divLen; i++) {
hi = pDiv[i - 1] * (q >>> 8);
lo = pDiv[i - 1] * (q & 255);
b = (pRem[l - 1] - a) - (lo & 255);
pRem[l - 1] = (b & 255);
/* This is a possible replacement to simulate arithmetic shift (preserving sign of b) */
/* b := b >> 8 bitOr: (0 - (b >> ((interpreterProxy sizeof: b)*8 */
/* CHAR_BIT */
/* -1)) << 8). */
b = b >> 8;
a = (hi + (lo >>> 8)) - b;
++l;
}
if (a > 0) {
/* Add div back into rem, decrease q by 1 */
--q;
l = j - dl;
a = 0;
for (i = 1; i <= divLen; i++) {
a = ((a >>> 8) + pRem[l - 1]) + pDiv[i - 1];
pRem[l - 1] = (a & 255);
++l;
}
}
pQuo[quoLen - k] = q;
}
return 0;
}
/* Answer the index (in bits) of the high order bit of the receiver, or zero if the
receiver is zero. This method is allowed (and needed) for
LargeNegativeIntegers as well, since Squeak's LargeIntegers are
sign/magnitude. */
function cDigitHighBitlen(pByte, len) {
var lastDigit;
var realLength;
realLength = len;
while (((lastDigit = pByte[realLength - 1])) === 0) {
if (((--realLength)) === 0) {
return 0;
}
}
return cHighBit(lastDigit) + (8 * (realLength - 1));
}
/* Answer the number of indexable fields of a CSmallInteger. This value is
the same as the largest legal subscript. */
function cDigitLengthOfCSI(csi) {
if ((csi < 256) && (csi > -256)) {
return 1;
}
if ((csi < 65536) && (csi > -65536)) {
return 2;
}
if ((csi < 16777216) && (csi > -16777216)) {
return 3;
}
return 4;
}
/* C indexed! */
function cDigitLshiftfromlentolen(shiftCount, pFrom, lenFrom, pTo, lenTo) {
var digitShift;
var carry;
var digit;
var i;
var bitShift;
var rshift;
var limit;
digitShift = shiftCount >> 3;
bitShift = MOD(shiftCount, 8);
limit = digitShift - 1;
for (i = 0; i <= limit; i++) {
pTo[i] = 0;
}
if (bitShift === 0) {
/* Fast version for digit-aligned shifts */
/* C indexed! */
return cDigitReplacefromtowithstartingAt(pTo, digitShift, lenTo - 1, pFrom, 0);
}
rshift = 8 - bitShift;
carry = 0;
limit = lenFrom - 1;
for (i = 0; i <= limit; i++) {
digit = pFrom[i];
pTo[i + digitShift] = ((carry | (SHL(digit, bitShift))) & 255);
carry = SHR(digit, rshift);
}
if (carry !== 0) {
pTo[lenTo - 1] = carry;
}
return 0;
}
function cDigitMontgomerylentimeslenmodulolenmInvModBinto(pBytesFirst, firstLen, pBytesSecond, secondLen, pBytesThird, thirdLen, mInv, pBytesRes) {
var k;
var i;
var lastByte;
var limit3;
var limit2;
var limit1;
var u;
var accum;
limit1 = firstLen - 1;
limit2 = secondLen - 1;
limit3 = thirdLen - 1;
lastByte = 0;
for (i = 0; i <= limit1; i++) {
accum = pBytesRes[0] + (pBytesFirst[i] * pBytesSecond[0]);
u = (accum * mInv) & 255;
accum += u * pBytesThird[0];
for (k = 1; k <= limit2; k++) {
accum = (((accum >>> 8) + pBytesRes[k]) + (pBytesFirst[i] * pBytesSecond[k])) + (u * pBytesThird[k]);
pBytesRes[k - 1] = (accum & 255);
}
for (k = secondLen; k <= limit3; k++) {
accum = ((accum >>> 8) + pBytesRes[k]) + (u * pBytesThird[k]);
pBytesRes[k - 1] = (accum & 255);
}
accum = (accum >>> 8) + lastByte;
pBytesRes[limit3] = (accum & 255);
lastByte = accum >>> 8;
}
for (i = firstLen; i <= limit3; i++) {
accum = pBytesRes[0];
u = (accum * mInv) & 255;
accum += u * pBytesThird[0];
for (k = 1; k <= limit3; k++) {
accum = ((accum >>> 8) + pBytesRes[k]) + (u * pBytesThird[k]);
pBytesRes[k - 1] = (accum & 255);
}
accum = (accum >>> 8) + lastByte;
pBytesRes[limit3] = (accum & 255);
lastByte = accum >>> 8;
}
if (!((lastByte === 0) && (cDigitComparewithlen(pBytesThird, pBytesRes, thirdLen) === 1))) {
/* self cDigitSub: pBytesThird len: thirdLen with: pBytesRes len: thirdLen into: pBytesRes */
accum = 0;
for (i = 0; i <= limit3; i++) {
accum = (accum + pBytesRes[i]) - pBytesThird[i];
pBytesRes[i] = (accum & 255);
accum = accum >> 8;
}
}
}
function cDigitMultiplylenwithleninto(pByteShort, shortLen, pByteLong, longLen, pByteRes) {
var ab;
var j;
var digit;
var carry;
var i;
var limitLong;
var k;
var limitShort;
if ((shortLen === 1) && (pByteShort[0] === 0)) {
return 0;
}
if ((longLen === 1) && (pByteLong[0] === 0)) {
return 0;
}
limitShort = shortLen - 1;
limitLong = longLen - 1;
for (i = 0; i <= limitShort; i++) {
if (((digit = pByteShort[i])) !== 0) {
k = i;
/* Loop invariant: 0<=carry<=0377, k=i+j-1 (ST) */
/* -> Loop invariant: 0<=carry<=0377, k=i+j (C) (?) */
carry = 0;
for (j = 0; j <= limitLong; j++) {
ab = pByteLong[j];
ab = ((ab * digit) + carry) + pByteRes[k];
carry = ab >>> 8;
pByteRes[k] = (ab & 255);
++k;
}
pByteRes[k] = carry;
}
}
return 0;
}
/* Answer the value of an indexable field in the receiver.
LargePositiveInteger uses bytes of base two number, and each is a
'digit' base 256. */
/* ST indexed! */
function cDigitOfCSIat(csi, ix) {
if (ix < 1) {
interpreterProxy.primitiveFail();
}
if (ix > 4) {
return 0;
}
if (csi < 0) {
;
return (SHR((0 - csi), ((ix - 1) * 8))) & 255;
} else {
return (SHR(csi, ((ix - 1) * 8))) & 255;
}
}
/* pByteRes len = longLen. */
function cDigitOpshortlenlongleninto(opIndex, pByteShort, shortLen, pByteLong, longLen, pByteRes) {
var i;
var limit;
limit = shortLen - 1;
if (opIndex === andOpIndex) {
for (i = 0; i <= limit; i++) {
pByteRes[i] = (pByteShort[i] & pByteLong[i]);
}
limit = longLen - 1;
for (i = shortLen; i <= limit; i++) {
pByteRes[i] = 0;
}
return 0;
}
if (opIndex === orOpIndex) {
for (i = 0; i <= limit; i++) {
pByteRes[i] = (pByteShort[i] | pByteLong[i]);
}
limit = longLen - 1;
for (i = shortLen; i <= limit; i++) {
pByteRes[i] = pByteLong[i];
}
return 0;
}
if (opIndex === xorOpIndex) {
for (i = 0; i <= limit; i++) {
pByteRes[i] = (pByteShort[i] ^ pByteLong[i]);
}
limit = longLen - 1;
for (i = shortLen; i <= limit; i++) {
pByteRes[i] = pByteLong[i];
}
return 0;
}
return interpreterProxy.primitiveFail();
}
/* C indexed! */
function cDigitReplacefromtowithstartingAt(pTo, start, stop, pFrom, repStart) {
return function() {
// inlining self cDigitCopyFrom: pFrom + repStart to: pTo + start len: stop - start + 1
var len = stop - start + 1;
for (var i = 0; i < len; i++) {
pTo[i + start] = pFrom[i + repStart];
}
return 0;
}();
;
}
function cDigitRshiftfromlentolen(shiftCount, pFrom, fromLen, pTo, toLen) {
var j;
var digitShift;
var carry;
var digit;
var bitShift;
var leftShift;
var limit;
var start;
digitShift = shiftCount >> 3;
bitShift = MOD(shiftCount, 8);
if (bitShift === 0) {
/* Fast version for byte-aligned shifts */
/* C indexed! */
return cDigitReplacefromtowithstartingAt(pTo, 0, toLen - 1, pFrom, digitShift);
}
leftShift = 8 - bitShift;
carry = SHR(pFrom[digitShift], bitShift);
start = digitShift + 1;
limit = fromLen - 1;
for (j = start; j <= limit; j++) {
digit = pFrom[j];
pTo[j - start] = ((carry | (SHL(digit, leftShift))) & 255);
carry = SHR(digit, bitShift);
}
if (carry !== 0) {
pTo[toLen - 1] = carry;
}
return 0;
}
function cDigitSublenwithleninto(pByteSmall, smallLen, pByteLarge, largeLen, pByteRes) {
var i;
var z;
/* Loop invariant is -1<=z<=0 */
z = 0;
for (i = 0; i <= (smallLen - 1); i++) {
z = (z + pByteLarge[i]) - pByteSmall[i];
pByteRes[i] = (z & 255);
z = z >> 8;
}
for (i = smallLen; i <= (largeLen - 1); i++) {
z += pByteLarge[i];
pByteRes[i] = (z & 255);
z = z >> 8;
}
}
/* Answer the index of the high order bit of the argument, or zero if the
argument is zero. */
/* For 64 bit uints there could be added a 32-shift. */
function cHighBit(uint) {
var shifted;
var bitNo;
shifted = uint;
bitNo = 0;
if (!(shifted < (1 << 16))) {
shifted = shifted >>> 16;
bitNo += 16;
}
if (!(shifted < (1 << 8))) {
shifted = shifted >>> 8;
bitNo += 8;
}
if (!(shifted < (1 << 4))) {
shifted = shifted >>> 4;
bitNo += 4;
}
if (!(shifted < (1 << 2))) {
shifted = shifted >>> 2;
bitNo += 2;
}
if (!(shifted < (1 << 1))) {
shifted = shifted >>> 1;
++bitNo;
}
return bitNo + shifted;
}
/* anOop has to be a SmallInteger! */
function createLargeFromSmallInteger(anOop) {
var size;
var res;
var pByte;
var ix;
var sq_class;
var val;
val = anOop;
if (val < 0) {
sq_class = interpreterProxy.classLargeNegativeInteger();
} else {
sq_class = interpreterProxy.classLargePositiveInteger();
}
size = cDigitLengthOfCSI(val);
res = interpreterProxy.instantiateClassindexableSize(sq_class, size);
pByte = res.bytes;
for (ix = 1; ix <= size; ix++) {
pByte[ix - 1] = cDigitOfCSIat(val, ix);
}
return res;
}
/* Attention: this method invalidates all oop's! Only newBytes is valid at return. */
/* Does not normalize. */
function digitLshift(aBytesOop, shiftCount) {
var newLen;
var oldLen;
var newBytes;
var highBit;
oldLen = BYTESIZEOF(aBytesOop);
if (((highBit = cDigitHighBitlen(aBytesOop.bytes, oldLen))) === 0) {
return 0;
}
newLen = ((highBit + shiftCount) + 7) >> 3;
newBytes = interpreterProxy.instantiateClassindexableSize(CLASSOF(aBytesOop), newLen);
;
cDigitLshiftfromlentolen(shiftCount, aBytesOop.bytes, oldLen, newBytes.bytes, newLen);
return newBytes;
}
/* Attention: this method invalidates all oop's! Only newBytes is valid at return. */
/* Shift right shiftCount bits, 0<=shiftCount.
Discard all digits beyond a, and all zeroes at or below a. */
/* Does not normalize. */
function digitRshiftlookfirst(aBytesOop, shiftCount, a) {
var newOop;
var oldDigitLen;
var newByteLen;
var newBitLen;
var oldBitLen;
oldBitLen = cDigitHighBitlen(aBytesOop.bytes, a);
oldDigitLen = (oldBitLen + 7) >> 3;
newBitLen = oldBitLen - shiftCount;
if (newBitLen <= 0) {
/* All bits lost */
return interpreterProxy.instantiateClassindexableSize(CLASSOF(aBytesOop), 0);
}
newByteLen = (newBitLen + 7) >> 3;
newOop = interpreterProxy.instantiateClassindexableSize(CLASSOF(aBytesOop), newByteLen);
;
cDigitRshiftfromlentolen(shiftCount, aBytesOop.bytes, oldDigitLen, newOop.bytes, newByteLen);
return newOop;
}
/* Does not need to normalize! */
function digitAddLargewith(firstInteger, secondInteger) {
var sum;
var shortLen;
var over;
var shortInt;
var resClass;
var newSum;
var longLen;
var firstLen;
var secondLen;
var longInt;
firstLen = BYTESIZEOF(firstInteger);
secondLen = BYTESIZEOF(secondInteger);
resClass = CLASSOF(firstInteger);
if (firstLen <= secondLen) {
shortInt = firstInteger;
shortLen = firstLen;
longInt = secondInteger;
longLen = secondLen;
} else {
shortInt = secondInteger;
shortLen = secondLen;
longInt = firstInteger;
longLen = firstLen;
}
sum = interpreterProxy.instantiateClassindexableSize(resClass, longLen);
;
over = cDigitAddlenwithleninto(shortInt.bytes, shortLen, longInt.bytes, longLen, sum.bytes);
if (over > 0) {
/* sum := sum growby: 1. */
newSum = interpreterProxy.instantiateClassindexableSize(resClass, longLen + 1);
;
cDigitCopyFromtolen(sum.bytes, newSum.bytes, longLen);
/* C index! */
sum = newSum;
sum.bytes[longLen] = over;
}
return sum;
}
/* Bit logic here is only implemented for positive integers or Zero;
if rec or arg is negative, it fails. */
function digitBitLogicwithopIndex(firstInteger, secondInteger, opIx) {
var shortLen;
var shortLarge;
var firstLarge;
var secondLarge;
var longLen;
var longLarge;
var firstLen;
var secondLen;
var result;
if (typeof firstInteger === "number") {
if (firstInteger < 0) {
return interpreterProxy.primitiveFail();
}
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
if (CLASSOF(firstInteger) === interpreterProxy.classLargeNegativeInteger()) {
return interpreterProxy.primitiveFail();
}
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
if (secondInteger < 0) {
return interpreterProxy.primitiveFail();
}
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
if (CLASSOF(secondInteger) === interpreterProxy.classLargeNegativeInteger()) {
return interpreterProxy.primitiveFail();
}
secondLarge = secondInteger;
}
firstLen = BYTESIZEOF(firstLarge);
secondLen = BYTESIZEOF(secondLarge);
if (firstLen < secondLen) {
shortLen = firstLen;
shortLarge = firstLarge;
longLen = secondLen;
longLarge = secondLarge;
} else {
shortLen = secondLen;
shortLarge = secondLarge;
longLen = firstLen;
longLarge = firstLarge;
}
result = interpreterProxy.instantiateClassindexableSize(interpreterProxy.classLargePositiveInteger(), longLen);
;
cDigitOpshortlenlongleninto(opIx, shortLarge.bytes, shortLen, longLarge.bytes, longLen, result.bytes);
if (interpreterProxy.failed()) {
return 0;
}
return normalizePositive(result);
}
/* Compare the magnitude of firstInteger with that of secondInteger.
Return a code of 1, 0, -1 for firstInteger >, = , < secondInteger */
function digitCompareLargewith(firstInteger, secondInteger) {
var secondLen;
var firstLen;
firstLen = BYTESIZEOF(firstInteger);
secondLen = BYTESIZEOF(secondInteger);
if (secondLen !== firstLen) {
if (secondLen > firstLen) {
return -1;
} else {
return 1;
}
}
return cDigitComparewithlen(firstInteger.bytes, secondInteger.bytes, firstLen);
}
/* Does not normalize. */
/* Division by zero has to be checked in caller. */
function digitDivLargewithnegative(firstInteger, secondInteger, neg) {
var resultClass;
var result;
var rem;
var div;
var quo;
var d;
var l;
var secondLen;
var firstLen;
firstLen = BYTESIZEOF(firstInteger);
secondLen = BYTESIZEOF(secondInteger);
if (neg) {
resultClass = interpreterProxy.classLargeNegativeInteger();
} else {
resultClass = interpreterProxy.classLargePositiveInteger();
}
l = (firstLen - secondLen) + 1;
if (l <= 0) {
result = interpreterProxy.instantiateClassindexableSize(interpreterProxy.classArray(), 2);
;
interpreterProxy.stObjectatput(result,1,0);
interpreterProxy.stObjectatput(result,2,firstInteger);
return result;
}
d = 8 - cHighBit(unsafeByteOfat(secondInteger, secondLen));
div = digitLshift(secondInteger, d);
div = bytesOrIntgrowTo(div, digitLength(div) + 1);
;
rem = digitLshift(firstInteger, d);
if (digitLength(rem) === firstLen) {
rem = bytesOrIntgrowTo(rem, firstLen + 1);
}
;
quo = interpreterProxy.instantiateClassindexableSize(resultClass, l);
;
cDigitDivlenremlenquolen(div.bytes, digitLength(div), rem.bytes, digitLength(rem), quo.bytes, digitLength(quo));
rem = digitRshiftlookfirst(rem, d, digitLength(div) - 1);
;
result = interpreterProxy.instantiateClassindexableSize(interpreterProxy.classArray(), 2);
;
interpreterProxy.stObjectatput(result,1,quo);
interpreterProxy.stObjectatput(result,2,rem);
return result;
}
function digitLength(oop) {
if (typeof oop === "number") {
return cDigitLengthOfCSI(oop);
} else {
return BYTESIZEOF(oop);
}
}
function digitMontgomerytimesmodulomInvModB(firstLarge, secondLarge, thirdLarge, mInv) {
var prod;
var thirdLen;
var firstLen;
var secondLen;
firstLen = BYTESIZEOF(firstLarge);
secondLen = BYTESIZEOF(secondLarge);
thirdLen = BYTESIZEOF(thirdLarge);
if (!(firstLen <= thirdLen)) {
return interpreterProxy.primitiveFail();
}
if (!(secondLen <= thirdLen)) {
return interpreterProxy.primitiveFail();
}
if (!((mInv >= 0) && (mInv <= 255))) {
return interpreterProxy.primitiveFail();
}
prod = interpreterProxy.instantiateClassindexableSize(interpreterProxy.classLargePositiveInteger(), thirdLen);
;
cDigitMontgomerylentimeslenmodulolenmInvModBinto(firstLarge.bytes, firstLen, secondLarge.bytes, secondLen, thirdLarge.bytes, thirdLen, mInv, prod.bytes);
return normalizePositive(prod);
}
/* Normalizes. */
function digitMultiplyLargewithnegative(firstInteger, secondInteger, neg) {
var longInt;
var resultClass;
var shortLen;
var shortInt;
var longLen;
var prod;
var secondLen;
var firstLen;
firstLen = BYTESIZEOF(firstInteger);
secondLen = BYTESIZEOF(secondInteger);
if (firstLen <= secondLen) {
shortInt = firstInteger;
shortLen = firstLen;
longInt = secondInteger;
longLen = secondLen;
} else {
shortInt = secondInteger;
shortLen = secondLen;
longInt = firstInteger;
longLen = firstLen;
}
if (neg) {
resultClass = interpreterProxy.classLargeNegativeInteger();
} else {
resultClass = interpreterProxy.classLargePositiveInteger();
}
prod = interpreterProxy.instantiateClassindexableSize(resultClass, longLen + shortLen);
;
cDigitMultiplylenwithleninto(shortInt.bytes, shortLen, longInt.bytes, longLen, prod.bytes);
return normalize(prod);
}
/* Argument has to be aLargeInteger! */
function digitOfBytesat(aBytesOop, ix) {
if (ix > BYTESIZEOF(aBytesOop)) {
return 0;
} else {
return unsafeByteOfat(aBytesOop, ix);
}
}
/* Normalizes. */
function digitSubLargewith(firstInteger, secondInteger) {
var smallerLen;
var larger;
var res;
var smaller;
var resLen;
var largerLen;
var firstNeg;
var firstLen;
var secondLen;
var neg;
firstNeg = CLASSOF(firstInteger) === interpreterProxy.classLargeNegativeInteger();
firstLen = BYTESIZEOF(firstInteger);
secondLen = BYTESIZEOF(secondInteger);
if (firstLen === secondLen) {
while ((firstLen > 1) && (digitOfBytesat(firstInteger, firstLen) === digitOfBytesat(secondInteger, firstLen))) {
--firstLen;
}
secondLen = firstLen;
}
if ((firstLen < secondLen) || ((firstLen === secondLen) && (digitOfBytesat(firstInteger, firstLen) < digitOfBytesat(secondInteger, firstLen)))) {
larger = secondInteger;
largerLen = secondLen;
smaller = firstInteger;
smallerLen = firstLen;
neg = firstNeg === false;
} else {
larger = firstInteger;
largerLen = firstLen;
smaller = secondInteger;
smallerLen = secondLen;
neg = firstNeg;
}
resLen = largerLen;
res = interpreterProxy.instantiateClassindexableSize((neg
? interpreterProxy.classLargeNegativeInteger()
: interpreterProxy.classLargePositiveInteger()), resLen);
;
cDigitSublenwithleninto(smaller.bytes, smallerLen, larger.bytes, largerLen, res.bytes);
return (neg
? normalizeNegative(res)
: normalizePositive(res));
}
/* Note: This is hardcoded so it can be run from Squeak.
The module name is used for validating a module *after*
it is loaded to check if it does really contain the module
we're thinking it contains. This is important! */
function getModuleName() {
return moduleName;
}
function halt() {
;
}
function highBitOfBytes(aBytesOop) {
return cDigitHighBitlen(aBytesOop.bytes, BYTESIZEOF(aBytesOop));
}
function isNormalized(anInteger) {
var ix;
var len;
var sLen;
var minVal;
var maxVal;
if (typeof anInteger === "number") {
return true;
}
len = digitLength(anInteger);
if (len === 0) {
return false;
}
if (unsafeByteOfat(anInteger, len) === 0) {
return false;
}
/* maximal digitLength of aSmallInteger */
sLen = 4;
if (len > sLen) {
return true;
}
if (len < sLen) {
return false;
}
if (CLASSOF(anInteger) === interpreterProxy.classLargePositiveInteger()) {
/* SmallInteger maxVal */
/* all bytes of maxVal but the highest one are just FF's */
maxVal = 1073741823;
return unsafeByteOfat(anInteger, sLen) > cDigitOfCSIat(maxVal, sLen);
} else {
/* SmallInteger minVal */
/* all bytes of minVal but the highest one are just 00's */
minVal = -1073741824;
if (unsafeByteOfat(anInteger, sLen) < cDigitOfCSIat(minVal, sLen)) {
return false;
} else {
/* if just one digit differs, then anInteger < minval (the corresponding digit byte is greater!)
and therefore a LargeNegativeInteger */
for (ix = 1; ix <= sLen; ix++) {
if (unsafeByteOfat(anInteger, ix) !== cDigitOfCSIat(minVal, ix)) {
return true;
}
}
}
}
return false;
}
function msg(s) {
console.log(moduleName + ": " + s);
}
/* Check for leading zeroes and return shortened copy if so. */
function normalize(aLargeInteger) {
// missing DebugCode;
if (CLASSOF(aLargeInteger) === interpreterProxy.classLargePositiveInteger()) {
return normalizePositive(aLargeInteger);
} else {
return normalizeNegative(aLargeInteger);
}
}
/* Check for leading zeroes and return shortened copy if so. */
/* First establish len = significant length. */
function normalizeNegative(aLargeNegativeInteger) {
var i;
var len;
var sLen;
var minVal;
var oldLen;
var val;
len = (oldLen = digitLength(aLargeNegativeInteger));
while ((len !== 0) && (unsafeByteOfat(aLargeNegativeInteger, len) === 0)) {
--len;
}
if (len === 0) {
return 0;
}
/* SmallInteger minVal digitLength */
sLen = 4;
if (len <= sLen) {
/* SmallInteger minVal */
minVal = -1073741824;
if ((len < sLen) || (digitOfBytesat(aLargeNegativeInteger, sLen) < cDigitOfCSIat(minVal, sLen))) {
/* If high digit less, then can be small */
val = 0;
for (i = len; i >= 1; i += -1) {
val = (val * 256) - unsafeByteOfat(aLargeNegativeInteger, i);
}
return val;
}
for (i = 1; i <= sLen; i++) {
/* If all digits same, then = minVal (sr: minVal digits 1 to 3 are
0) */
if (digitOfBytesat(aLargeNegativeInteger, i) !== cDigitOfCSIat(minVal, i)) {
/* Not so; return self shortened */
if (len < oldLen) {
/* ^ self growto: len */
return bytesgrowTo(aLargeNegativeInteger, len);
} else {
return aLargeNegativeInteger;
}
}
}
return minVal;
}
if (len < oldLen) {
/* ^ self growto: len */
return bytesgrowTo(aLargeNegativeInteger, len);
} else {
return aLargeNegativeInteger;
}
}
/* Check for leading zeroes and return shortened copy if so. */
/* First establish len = significant length. */
function normalizePositive(aLargePositiveInteger) {
var i;
var len;
var sLen;
var val;
var oldLen;
len = (oldLen = digitLength(aLargePositiveInteger));
while ((len !== 0) && (unsafeByteOfat(aLargePositiveInteger, len) === 0)) {
--len;
}
if (len === 0) {
return 0;
}
/* SmallInteger maxVal digitLength. */
sLen = 4;
if ((len <= sLen) && (digitOfBytesat(aLargePositiveInteger, sLen) <= cDigitOfCSIat(1073741823, sLen))) {
/* If so, return its SmallInt value */
val = 0;
for (i = len; i >= 1; i += -1) {
val = (val * 256) + unsafeByteOfat(aLargePositiveInteger, i);
}
return val;
}
if (len < oldLen) {
/* ^ self growto: len */
return bytesgrowTo(aLargePositiveInteger, len);
} else {
return aLargePositiveInteger;
}
}
function primAnyBitFromTo() {
var integer;
var large;
var from;
var to;
var _return_value;
from = interpreterProxy.stackIntegerValue(1);
to = interpreterProxy.stackIntegerValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
integer = interpreterProxy.stackValue(2);
if (interpreterProxy.failed()) {
return null;
}
if (typeof integer === "number") {
/* convert it to a not normalized LargeInteger */
large = createLargeFromSmallInteger(integer);
} else {
large = integer;
}
_return_value = (anyBitOfBytesfromto(large, from, to)? interpreterProxy.trueObject() : interpreterProxy.falseObject());
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
/* Converts a SmallInteger into a - non normalized! - LargeInteger;
aLargeInteger will be returned unchanged. */
/* Do not check for forced fail, because we need this conversion to test the
plugin in ST during forced fail, too. */
function primAsLargeInteger() {
var anInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
anInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof anInteger === "number") {
_return_value = createLargeFromSmallInteger(anInteger);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
} else {
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, anInteger);
return null;
}
}
/* If calling this primitive fails, then C module does not exist. Do not check for forced fail, because we want to know if module exists during forced fail, too. */
function primCheckIfCModuleExists() {
var _return_value;
_return_value = (true? interpreterProxy.trueObject() : interpreterProxy.falseObject());
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(1, _return_value);
return null;
}
function _primDigitBitShift() {
var rShift;
var aLarge;
var anInteger;
var shiftCount;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
anInteger = interpreterProxy.stackValue(1);
shiftCount = interpreterProxy.stackIntegerValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof anInteger === "number") {
/* convert it to a not normalized LargeInteger */
aLarge = createLargeFromSmallInteger(anInteger);
} else {
aLarge = anInteger;
}
if (shiftCount >= 0) {
_return_value = digitLshift(aLarge, shiftCount);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
} else {
rShift = 0 - shiftCount;
_return_value = normalize(digitRshiftlookfirst(aLarge, rShift, BYTESIZEOF(aLarge)));
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
}
function primDigitAdd() {
var firstLarge;
var firstInteger;
var secondLarge;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
secondLarge = secondInteger;
}
_return_value = digitAddLargewith(firstLarge, secondLarge);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
function primDigitAddWith() {
var firstLarge;
var secondLarge;
var firstInteger;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
secondLarge = secondInteger;
}
_return_value = digitAddLargewith(firstLarge, secondLarge);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
/* Bit logic here is only implemented for positive integers or Zero; if rec
or arg is negative, it fails. */
function primDigitBitAnd() {
var firstInteger;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
_return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, andOpIndex);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
/* Bit logic here is only implemented for positive integers or Zero; if any arg is negative, it fails. */
function primDigitBitLogicWithOp() {
var firstInteger;
var secondInteger;
var opIndex;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
firstInteger = interpreterProxy.stackValue(2);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
secondInteger = interpreterProxy.stackValue(1);
opIndex = interpreterProxy.stackIntegerValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
_return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, opIndex);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(4, _return_value);
return null;
}
/* Bit logic here is only implemented for positive integers or Zero; if rec
or arg is negative, it fails. */
function primDigitBitOr() {
var firstInteger;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
_return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, orOpIndex);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
function primDigitBitShift() {
var aLarge;
var rShift;
var anInteger;
var shiftCount;
var _return_value;
shiftCount = interpreterProxy.stackIntegerValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
anInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
if (typeof anInteger === "number") {
/* convert it to a not normalized LargeInteger */
aLarge = createLargeFromSmallInteger(anInteger);
} else {
aLarge = anInteger;
}
if (shiftCount >= 0) {
_return_value = digitLshift(aLarge, shiftCount);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
} else {
rShift = 0 - shiftCount;
_return_value = normalize(digitRshiftlookfirst(aLarge, rShift, BYTESIZEOF(aLarge)));
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
}
function primDigitBitShiftMagnitude() {
var aLarge;
var rShift;
var anInteger;
var shiftCount;
var _return_value;
shiftCount = interpreterProxy.stackIntegerValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
anInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
if (typeof anInteger === "number") {
/* convert it to a not normalized LargeInteger */
aLarge = createLargeFromSmallInteger(anInteger);
} else {
aLarge = anInteger;
}
if (shiftCount >= 0) {
_return_value = digitLshift(aLarge, shiftCount);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
} else {
rShift = 0 - shiftCount;
_return_value = normalize(digitRshiftlookfirst(aLarge, rShift, BYTESIZEOF(aLarge)));
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
}
/* Bit logic here is only implemented for positive integers or Zero; if rec
or arg is negative, it fails. */
function primDigitBitXor() {
var firstInteger;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
_return_value = digitBitLogicwithopIndex(firstInteger, secondInteger, xorOpIndex);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
function primDigitCompare() {
var firstVal;
var firstInteger;
var secondVal;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* first */
if (typeof secondInteger === "number") {
/* second */
if (((firstVal = firstInteger)) > ((secondVal = secondInteger))) {
_return_value = 1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
} else {
if (firstVal < secondVal) {
_return_value = -1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
} else {
_return_value = 0;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
}
} else {
/* SECOND */
_return_value = -1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
} else {
/* FIRST */
if (typeof secondInteger === "number") {
/* second */
_return_value = 1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
} else {
/* SECOND */
_return_value = digitCompareLargewith(firstInteger, secondInteger);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
}
}
function primDigitCompareWith() {
var firstVal;
var secondVal;
var firstInteger;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* first */
if (typeof secondInteger === "number") {
/* second */
if (((firstVal = firstInteger)) > ((secondVal = secondInteger))) {
_return_value = 1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
} else {
if (firstVal < secondVal) {
_return_value = -1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
} else {
_return_value = 0;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
}
} else {
/* SECOND */
_return_value = -1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
} else {
/* FIRST */
if (typeof secondInteger === "number") {
/* second */
_return_value = 1;
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
} else {
/* SECOND */
_return_value = digitCompareLargewith(firstInteger, secondInteger);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
}
}
/* Answer the result of dividing firstInteger by secondInteger.
Fail if parameters are not integers, not normalized or secondInteger is
zero. */
function primDigitDivNegative() {
var firstAsLargeInteger;
var firstInteger;
var secondAsLargeInteger;
var secondInteger;
var neg;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
secondInteger = interpreterProxy.stackValue(1);
neg = interpreterProxy.booleanValueOf(interpreterProxy.stackValue(0));
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
firstInteger = interpreterProxy.stackValue(2);
if (interpreterProxy.failed()) {
return null;
}
if (!isNormalized(firstInteger)) {
// missing DebugCode;
interpreterProxy.primitiveFail();
return null;
}
if (!isNormalized(secondInteger)) {
// missing DebugCode;
interpreterProxy.primitiveFail();
return null;
}
if (typeof firstInteger === "number") {
/* convert to LargeInteger */
firstAsLargeInteger = createLargeFromSmallInteger(firstInteger);
;
} else {
firstAsLargeInteger = firstInteger;
}
if (typeof secondInteger === "number") {
/* check for zerodivide and convert to LargeInteger */
if (secondInteger === 0) {
interpreterProxy.primitiveFail();
return null;
}
secondAsLargeInteger = createLargeFromSmallInteger(secondInteger);
;
} else {
secondAsLargeInteger = secondInteger;
}
_return_value = digitDivLargewithnegative(firstAsLargeInteger, secondAsLargeInteger, neg);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
/* Answer the result of dividing firstInteger by secondInteger.
Fail if parameters are not integers or secondInteger is zero. */
function primDigitDivWithNegative() {
var firstAsLargeInteger;
var secondAsLargeInteger;
var firstInteger;
var secondInteger;
var neg;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
firstInteger = interpreterProxy.stackValue(2);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
secondInteger = interpreterProxy.stackValue(1);
neg = interpreterProxy.booleanValueOf(interpreterProxy.stackValue(0));
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert to LargeInteger */
firstAsLargeInteger = createLargeFromSmallInteger(firstInteger);
;
} else {
firstAsLargeInteger = firstInteger;
}
if (typeof secondInteger === "number") {
/* check for zerodivide and convert to LargeInteger */
if (secondInteger === 0) {
interpreterProxy.primitiveFail();
return null;
}
secondAsLargeInteger = createLargeFromSmallInteger(secondInteger);
;
} else {
secondAsLargeInteger = secondInteger;
}
_return_value = digitDivLargewithnegative(firstAsLargeInteger, secondAsLargeInteger, neg);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(4, _return_value);
return null;
}
function primDigitMultiplyNegative() {
var firstLarge;
var firstInteger;
var secondLarge;
var secondInteger;
var neg;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
secondInteger = interpreterProxy.stackValue(1);
neg = interpreterProxy.booleanValueOf(interpreterProxy.stackValue(0));
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
firstInteger = interpreterProxy.stackValue(2);
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
secondLarge = secondInteger;
}
_return_value = digitMultiplyLargewithnegative(firstLarge, secondLarge, neg);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
function primDigitMultiplyWithNegative() {
var firstLarge;
var secondLarge;
var firstInteger;
var secondInteger;
var neg;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
firstInteger = interpreterProxy.stackValue(2);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
secondInteger = interpreterProxy.stackValue(1);
neg = interpreterProxy.booleanValueOf(interpreterProxy.stackValue(0));
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
secondLarge = secondInteger;
}
_return_value = digitMultiplyLargewithnegative(firstLarge, secondLarge, neg);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(4, _return_value);
return null;
}
function primDigitSubtract() {
var firstLarge;
var firstInteger;
var secondLarge;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
secondLarge = secondInteger;
}
_return_value = digitSubLargewith(firstLarge, secondLarge);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
function primDigitSubtractWith() {
var firstLarge;
var secondLarge;
var firstInteger;
var secondInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
firstInteger = interpreterProxy.stackValue(1);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
secondInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondInteger);
;
} else {
secondLarge = secondInteger;
}
_return_value = digitSubLargewith(firstLarge, secondLarge);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(3, _return_value);
return null;
}
/* If calling this primitive fails, then C module does not exist. */
function primGetModuleName() {
var strPtr;
var strLen;
var i;
var strOop;
// missing DebugCode;
strLen = getModuleName().length;
strOop = interpreterProxy.instantiateClassindexableSize(interpreterProxy.classString(), strLen);
strPtr = strOop.bytes;
for (i = 0; i <= (strLen - 1); i++) {
strPtr[i] = getModuleName()[i];
}
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(1, strOop);
return null;
}
function primMontgomeryTimesModulo() {
var firstLarge;
var secondLarge;
var firstInteger;
var thirdLarge;
var secondOperandInteger;
var thirdModuloInteger;
var smallInverseInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(2)));
secondOperandInteger = interpreterProxy.stackValue(2);
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(1)));
thirdModuloInteger = interpreterProxy.stackValue(1);
smallInverseInteger = interpreterProxy.stackIntegerValue(0);
// missing DebugCode;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(3)));
firstInteger = interpreterProxy.stackValue(3);
if (interpreterProxy.failed()) {
return null;
}
if (typeof firstInteger === "number") {
/* convert it to a not normalized LargeInteger */
firstLarge = createLargeFromSmallInteger(firstInteger);
;
} else {
firstLarge = firstInteger;
}
if (typeof secondOperandInteger === "number") {
/* convert it to a not normalized LargeInteger */
secondLarge = createLargeFromSmallInteger(secondOperandInteger);
;
} else {
secondLarge = secondOperandInteger;
}
if (typeof thirdModuloInteger === "number") {
/* convert it to a not normalized LargeInteger */
thirdLarge = createLargeFromSmallInteger(thirdModuloInteger);
;
} else {
thirdLarge = thirdModuloInteger;
}
_return_value = digitMontgomerytimesmodulomInvModB(firstLarge, secondLarge, thirdLarge, smallInverseInteger);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(4, _return_value);
return null;
}
/* Parameter specification #(Integer) doesn't convert! */
function primNormalize() {
var anInteger;
var _return_value;
interpreterProxy.success(interpreterProxy.isKindOfInteger(interpreterProxy.stackValue(0)));
anInteger = interpreterProxy.stackValue(0);
// missing DebugCode;
if (interpreterProxy.failed()) {
return null;
}
if (typeof anInteger === "number") {
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, anInteger);
return null;
}
_return_value = normalize(anInteger);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(2, _return_value);
return null;
}
function primNormalizeNegative() {
var rcvr;
var _return_value;
// missing DebugCode;
interpreterProxy.success(interpreterProxy.stackValue(0).sqClass === interpreterProxy.classLargeNegativeInteger());
rcvr = interpreterProxy.stackValue(0);
if (interpreterProxy.failed()) {
return null;
}
_return_value = normalizeNegative(rcvr);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(1, _return_value);
return null;
}
function primNormalizePositive() {
var rcvr;
var _return_value;
// missing DebugCode;
interpreterProxy.success(interpreterProxy.stackValue(0).sqClass === interpreterProxy.classLargePositiveInteger());
rcvr = interpreterProxy.stackValue(0);
if (interpreterProxy.failed()) {
return null;
}
_return_value = normalizePositive(rcvr);
if (interpreterProxy.failed()) {
return null;
}
interpreterProxy.popthenPush(1, _return_value);
return null;
}
/* Note: This is coded so that is can be run from Squeak. */
function setInterpreter(anInterpreter) {
var ok;
interpreterProxy = anInterpreter;
ok = interpreterProxy.majorVersion() == VM_PROXY_MAJOR;
if (ok === false) {
return false;
}
ok = interpreterProxy.minorVersion() >= VM_PROXY_MINOR;
return ok;
}
/* Argument bytesOop must not be aSmallInteger! */
function unsafeByteOfat(bytesOop, ix) {
var pointer;
return ((pointer = bytesOop.bytes))[ix - 1];
}
function registerPlugin() {
if (typeof Squeak === "object" && Squeak.registerExternalModule) {
Squeak.registerExternalModule("LargeIntegers", {
primDigitAddWith: primDigitAddWith,
primDigitBitShiftMagnitude: primDigitBitShiftMagnitude,
primGetModuleName: primGetModuleName,
primDigitBitLogicWithOp: primDigitBitLogicWithOp,
primCheckIfCModuleExists: primCheckIfCModuleExists,
primDigitCompare: primDigitCompare,
primDigitMultiplyNegative: primDigitMultiplyNegative,
primDigitBitShift: primDigitBitShift,
primNormalizePositive: primNormalizePositive,
primDigitSubtractWith: primDigitSubtractWith,
_primDigitBitShift: _primDigitBitShift,
primDigitMultiplyWithNegative: primDigitMultiplyWithNegative,
primDigitSubtract: primDigitSubtract,
primDigitDivNegative: primDigitDivNegative,
primNormalizeNegative: primNormalizeNegative,
primDigitBitOr: primDigitBitOr,
primMontgomeryTimesModulo: primMontgomeryTimesModulo,
primDigitBitAnd: primDigitBitAnd,
primDigitDivWithNegative: primDigitDivWithNegative,
setInterpreter: setInterpreter,
primNormalize: primNormalize,
primDigitBitXor: primDigitBitXor,
primDigitCompareWith: primDigitCompareWith,
primDigitAdd: primDigitAdd,
getModuleName: getModuleName,
primAsLargeInteger: primAsLargeInteger,
primAnyBitFromTo: primAnyBitFromTo,
});
} else self.setTimeout(registerPlugin, 100);
}
registerPlugin();
})(); // Register module/plugin