Use native javascript array for mantissa for big performance increase

This commit is contained in:
Stephen Ierodiaconou
2011-01-16 01:47:14 +02:00
parent e0185a0eff
commit c65bfd22a2
+62 -60
View File
@@ -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