From c65bfd22a24f792e92c81b2e6a4b83dcf202a6cc Mon Sep 17 00:00:00 2001 From: Stephen Ierodiaconou Date: Sun, 16 Jan 2011 01:47:14 +0200 Subject: [PATCH] Use native javascript array for mantissa for big performance increase --- Foundation/CPDecimal.j | 122 +++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 60 deletions(-) diff --git a/Foundation/CPDecimal.j b/Foundation/CPDecimal.j index eb5f267cd..58c53f218 100644 --- a/Foundation/CPDecimal.j +++ b/Foundation/CPDecimal.j @@ -146,20 +146,20 @@ function CPDecimalMakeWithString(string, locale) return CPDecimalMakeNaN(); // Representation internally starts at most significant digit - var m = [CPMutableArray array], + var m = [], i = 0; for (; i < (intpart?intpart.length:0); i++) { if (i >= CPDecimalMaxDigits) break; // truncate - [m addObject:parseInt(intpart.charAt(i))]; + Array.prototype.push.call(m, parseInt(intpart.charAt(i))); } var j = 0; for (; j < (decpart?decpart.length:0); j++) { if ((i + j) >= CPDecimalMaxDigits) break; // truncate - [m addObject:parseInt(decpart.charAt(j))]; + Array.prototype.push.call(m, parseInt(decpart.charAt(j))); } var dcm = {_exponent:exponent, _isNegative:isNegative, _isCompact:NO, _isNaN:NO, _mantissa:m}; @@ -177,7 +177,7 @@ function CPDecimalMakeWithString(string, locale) */ function CPDecimalMakeWithParts(mantissa, exponent) { - var m = [CPMutableArray array], + var m = [], isNegative = NO; if (mantissa < 0 ) @@ -187,15 +187,15 @@ function CPDecimalMakeWithParts(mantissa, exponent) } if (mantissa == 0) - [m addObject: 0]; + Array.prototype.push.call(m, 0); if (exponent > CPDecimalMaxExponent || exponent < CPDecimalMinExponent) return CPDecimalMakeNaN(); // remaining digits are disposed of via truncation - while ((mantissa > 0) && ([m count] < CPDecimalMaxDigits)) // count selector here could be optimised away + while ((mantissa > 0) && (m.length < CPDecimalMaxDigits)) // count selector here could be optimised away { - [m insertObject:parseInt(mantissa % 10) atIndex:0]; + Array.prototype.unshift.call(m, parseInt(mantissa % 10)); mantissa = FLOOR(mantissa / 10); } @@ -291,7 +291,7 @@ function CPDecimalIsOne(dcm) // exponent doesnt matter as long as mantissa = 0 if (!dcm._isNaN) { - if (dcm._mantissa && ([dcm._mantissa count] == 1) && (dcm._mantissa[0] == 1)) + if (dcm._mantissa && (dcm._mantissa.length == 1) && (dcm._mantissa[0] == 1)) return YES; } return NO; @@ -305,12 +305,12 @@ function _CPDecimalSet(t,s) t._isNegative = s._isNegative; t._isCompact = s._isCompact; t._isNaN = s._isNaN; - t._mantissa = [s._mantissa copy]; + t._mantissa = Array.prototype.slice.call(s._mantissa, 0); } function _CPDecimalSetZero(result) { - result._mantissa = [CPMutableArray arrayWithObject:0]; + result._mantissa = [0]; result._exponent = 0; result._isNegative = NO; result._isCompact = YES; @@ -319,7 +319,7 @@ function _CPDecimalSetZero(result) function _CPDecimalSetOne(result) { - result._mantissa = [CPMutableArray arrayWithObject:1]; + result._mantissa = [1]; result._exponent = 0; result._isNegative = NO; result._isCompact = YES; @@ -348,7 +348,7 @@ function CPDecimalCopy(dcm) _isNegative:dcm._isNegative, _isCompact:dcm._isCompact, _isNaN:dcm._isNaN, - _mantissa:[dcm._mantissa copy] + _mantissa:Array.prototype.slice.call(dcm._mantissa, 0) }; } @@ -373,8 +373,8 @@ function CPDecimalCompare(leftOperand, rightOperand) return CPOrderedAscending; } - var s1 = leftOperand._exponent + [leftOperand._mantissa count], - s2 = rightOperand._exponent + [rightOperand._mantissa count]; + var s1 = leftOperand._exponent + leftOperand._mantissa.length, + s2 = rightOperand._exponent + rightOperand._mantissa.length; // Sign is the same, quick check size (length + exp) if (s1 < s2) @@ -393,7 +393,7 @@ function CPDecimalCompare(leftOperand, rightOperand) } // Same size, so check mantissa - var l = MIN([leftOperand._mantissa count], [rightOperand._mantissa count]), + var l = MIN(leftOperand._mantissa.length, rightOperand._mantissa.length), i = 0; for (; i < l; i++) @@ -417,14 +417,14 @@ function CPDecimalCompare(leftOperand, rightOperand) } // Same digits, check length - if ([leftOperand._mantissa count] > [rightOperand._mantissa count]) + if (leftOperand._mantissa.length > rightOperand._mantissa.length) { if (rightOperand._isNegative) return CPOrderedAscending; else return CPOrderedDescending; } - if ([leftOperand._mantissa count] < [rightOperand._mantissa count]) + if (leftOperand._mantissa.length < rightOperand._mantissa.length) { if (rightOperand._isNegative) return CPOrderedDescending; @@ -444,8 +444,8 @@ function _SimpleAdd(result, leftOperand, rightOperand, roundingMode, longMode) _CPDecimalSet(result, leftOperand); - var j = [leftOperand._mantissa count] - [rightOperand._mantissa count], - l = [rightOperand._mantissa count], + var j = leftOperand._mantissa.length - rightOperand._mantissa.length, + l = rightOperand._mantissa.length, i = l - 1, carry = 0, error = CPCalculationNoError; @@ -467,7 +467,7 @@ function _SimpleAdd(result, leftOperand, rightOperand, roundingMode, longMode) if (carry) { - for (i = j-1; i >= 0; i--) + for (i = j - 1; i >= 0; i--) { if (result._mantissa[i] != 9) { @@ -480,13 +480,13 @@ function _SimpleAdd(result, leftOperand, rightOperand, roundingMode, longMode) if (carry) { - [result._mantissa insertObject:1 atIndex:0]; + Array.prototype.splice.call(result._mantissa, 0, 0, 1); // The number must be shifted to the right - if ((CPDecimalMaxDigits * factor) == [leftOperand._mantissa count]) + if ((CPDecimalMaxDigits * factor) == leftOperand._mantissa.length) { var scale = - result._exponent - 1; - CPDecimalRound(result, result,scale,roundingMode); + CPDecimalRound(result, result, scale, roundingMode); } if (CPDecimalMaxExponent < result._exponent) @@ -550,8 +550,8 @@ function CPDecimalAdd(result, leftOperand, rightOperand, roundingMode, longMode) // below is equiv of simple compare var comp = 0, - ll = [n1._mantissa count], - lr = [n2._mantissa count]; + ll = n1._mantissa.length, + lr = n2._mantissa.length; if (ll == lr) comp = CPOrderedSame; else if (ll > lr) @@ -605,8 +605,8 @@ function _SimpleSubtract(result, leftOperand, rightOperand, roundingMode) { var error = CPCalculationNoError, borrow = 0, - l = [rightOperand._mantissa count], - j = [leftOperand._mantissa count] - l, + l = rightOperand._mantissa.length, + j = leftOperand._mantissa.length - l, i = l - 1; _CPDecimalSet(result, leftOperand); @@ -628,7 +628,7 @@ function _SimpleSubtract(result, leftOperand, rightOperand, roundingMode) if (borrow) { - for (i = j-1; i >= 0; i--) + for (i = j - 1; i >= 0; i--) { if (result._mantissa[i] != 0) { @@ -759,10 +759,10 @@ function _SimpleDivide(result, leftOperand, rightOperand, roundingMode) _CPDecimalSetZero(result); - n1._mantissa = [CPMutableArray array]; + n1._mantissa = []; - while ((k < [leftOperand._mantissa count]) || ([n1._mantissa count] - && !(([n1._mantissa count] == 1) && (n1._mantissa[0] == 0)))) + while ((k < leftOperand._mantissa.length) || (n1._mantissa.length + && !((n1._mantissa.length == 1) && (n1._mantissa[0] == 0)))) { while (CPOrderedAscending == CPDecimalCompare(n1, rightOperand)) { @@ -771,19 +771,19 @@ function _SimpleDivide(result, leftOperand, rightOperand, roundingMode) if (n1._exponent) { // Put back zeros removed by compacting - [n1._mantissa addObject:0]; + Array.prototype.push.call(n1._mantissa, 0); n1._exponent--; n1._isCompact = NO; } else { - if (used < [leftOperand._mantissa count]) + if (used < leftOperand._mantissa.length) { // Fill up with own digits - if ([n1._mantissa count] || leftOperand._mantissa[used]) + if (n1._mantissa.length || leftOperand._mantissa[used]) { // only add 0 if there is already something - [n1._mantissa addObject:(leftOperand._mantissa[used])]; + Array.prototype.push.call(n1._mantissa, (leftOperand._mantissa[used])); n1._isCompact = NO; } used++; @@ -797,7 +797,7 @@ function _SimpleDivide(result, leftOperand, rightOperand, roundingMode) break; } // Borrow one digit - [n1._mantissa addObject:0]; + Array.prototype.push.call(n1._mantissa, 0); result._exponent--; } @@ -922,11 +922,11 @@ function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerM // Do every digit of the second number var i = 0; - for (; i < [rightOperand._mantissa count]; i++) + for (; i < rightOperand._mantissa.length; i++) { _CPDecimalSetZero(n); - n._exponent = [rightOperand._mantissa count] - i - 1; + n._exponent = rightOperand._mantissa.length - i - 1; carry = 0; d = rightOperand._mantissa[i]; @@ -934,7 +934,7 @@ function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerM continue; var j = 0; - for (j = [leftOperand._mantissa count]-1; j >= 0; j--) + for (j = leftOperand._mantissa.length - 1; j >= 0; j--) { e = leftOperand._mantissa[j] * d + carry; if (e >= 10) @@ -967,11 +967,11 @@ function _SimpleMultiply(result, leftOperand, rightOperand, roundingMode, powerM result._exponent += exp; // perform round to CPDecimalMaxDigits - if ([result._mantissa count] > CPDecimalMaxDigits && !powerMode) + if (result._mantissa.length > CPDecimalMaxDigits && !powerMode) { result._isCompact = NO; - var scale = CPDecimalMaxDigits - ([result._mantissa count] + result._exponent); - CPDecimalRound(result, result, scale ,roundingMode); // calls compact + var scale = CPDecimalMaxDigits - (result._mantissa.length + result._exponent); + CPDecimalRound(result, result, scale, roundingMode); // calls compact error = CPCalculationLossOfPrecision; } @@ -1027,8 +1027,8 @@ function CPDecimalMultiply(result, leftOperand, rightOperand, roundingMode, powe // below is equiv of simple compare var comp = 0, - ll = [n1._mantissa count], - lr = [n2._mantissa count]; + ll = n1._mantissa.length, + lr = n2._mantissa.length; if (ll == lr) comp = CPOrderedSame; else if (ll > lr) @@ -1183,8 +1183,8 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode) e2 = dcm2._exponent; // Add zeros - var l2 = [dcm2._mantissa count], - l1 = [dcm1._mantissa count], + var l2 = dcm2._mantissa.length, + l1 = dcm1._mantissa.length, l = 0; var e = 0; @@ -1202,16 +1202,16 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode) e = e1 - e2; if (e2 > e1) - l = MIN((CPDecimalMaxDigits*factor) - l2, e); //(e2 - e1)); + l = MIN((CPDecimalMaxDigits * factor) - l2, e); //(e2 - e1)); else - l = MIN((CPDecimalMaxDigits*factor) - l1, e); //(e1 - e2)); + l = MIN((CPDecimalMaxDigits * factor) - l1, e); //(e1 - e2)); for (var i = 0; i < l; i++) { if (e2 > e1) - [dcm2._mantissa addObject:0]; //dcm2._mantissa[i + l2] = 0; + Array.prototype.push.call(dcm2._mantissa, 0); //dcm2._mantissa[i + l2] = 0; else - [dcm1._mantissa addObject:0]; + Array.prototype.push.call(dcm1._mantissa, 0); } if (e2 > e1) { @@ -1246,7 +1246,7 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode) // Some zeros where cut of again by compacting if (e2 > e1) { - l1 = [dcm1._mantissa count]; + l1 = dcm1._mantissa.length; l = MIN((CPDecimalMaxDigits * factor) - l1, ABS(dcm1._exponent - dcm2._exponent)); for (var i = 0; i < l; i++) { @@ -1257,7 +1257,7 @@ function CPDecimalNormalize(dcm1, dcm2, roundingMode, longMode) } else { - l2 = [dcm2._mantissa count]; + l2 = dcm2._mantissa.length; l = MIN((CPDecimalMaxDigits * factor) - l2, ABS(dcm2._exponent - dcm1._exponent)); for (var i = 0; i < l; i++) { @@ -1301,7 +1301,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode) _CPDecimalSet(result,dcm); - var mc = [result._mantissa count], + var mc = result._mantissa.length, l = mc + scale + result._exponent; if (mc <= l) @@ -1350,7 +1350,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode) break; } // cut mantissa - result._mantissa = [result._mantissa subarrayWithRange:CPMakeRange(0, l)]; + result._mantissa = Array.prototype.slice.call(result._mantissa, 0, l); if (up) { @@ -1373,7 +1373,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode) // Overflow in rounding. // Add one zero add the end. There must be space as // we just cut off some digits. - [result._mantissa addObject:0]; + Array.prototype.push.call(result._mantissa, 0); } else result._exponent++; @@ -1392,7 +1392,7 @@ function CPDecimalRound(result, dcm, scale ,roundingMode) function CPDecimalCompact(dcm) { // if positive or zero exp leading zeros simply delete, trailing ones u need to increment exponent - if (!dcm || [dcm._mantissa count] == 0 || CPDecimalIsNotANumber(dcm) ) + if (!dcm || dcm._mantissa.length == 0 || CPDecimalIsNotANumber(dcm) ) return; @@ -1406,12 +1406,12 @@ function CPDecimalCompact(dcm) // if exp is zero does it make sense to have them? dont think so so delete them while (dcm._mantissa[0] === 0) { - [dcm._mantissa removeObjectAtIndex:0]; + Array.prototype.shift.call(dcm._mantissa); } // trailing zeros, strip them - while ([dcm._mantissa lastObject] === 0) + while (dcm._mantissa[dcm._mantissa.length - 1] === 0) { - [dcm._mantissa removeLastObject]; + Array.prototype.pop.call(dcm._mantissa); dcm._exponent++; if (dcm._exponent + 1 > CPDecimalMaxExponent) { @@ -1443,8 +1443,10 @@ function CPDecimalString(dcm, locale) if (dcm._isNegative) string += "-"; - var k = [dcm._mantissa count], + + var k = dcm._mantissa.length, l = ((dcm._exponent < 0) ? dcm._exponent : 0) + k; + if (l < 0) { // add leading zeros