# HG changeset patch # User Paul (paul.d.anderson@comcast.net) # Date 1269402607 25200 # Node ID b304232c476c6fb4790e1280d4c3b1758b3764d1 # Parent 14badf9104b929a4eff64c1a16c5def35a2cebe7 Coded and tested div and mod. Changed setNumDigits. diff -r 14badf9104b9 -r b304232c476c src/decimal/bcd.d --- a/src/decimal/bcd.d Mon Mar 22 20:20:05 2010 -0700 +++ b/src/decimal/bcd.d Tue Mar 23 20:50:07 2010 -0700 @@ -213,10 +213,18 @@ /** * Adjusts the number of digits in this BCD integer, - * padding or truncating if necessary. + * padding or truncating if necessary. + * If truncating, first leading zeros are stripped away, then + * the remainder is clipped. */ void setNumDigits(uint n) { - digits.length = n; + this = stripLeadingZeros(this); + if (n > digits.length) { + digits.length = n; + } + else { + this = truncate(this, n); + } } unittest { @@ -224,11 +232,9 @@ Bcd a; a = 1234567; a.setNumDigits(5); - writeln("a = ", a); - assert(a == Bcd(34567)); + assert(a == Bcd(12345)); a.setNumDigits(9); - writeln("a = ", a); - assert(a.toString == "000034567"); + assert(a.toString == "000012345"); writeln("passed"); } @@ -267,7 +273,8 @@ unittest { write("digits..."); - Bcd bcd = Bcd(12345678L); + Bcd bcd; + bcd = 12345678; assert(bcd.numDigits() == 8); assert(bcd.firstDigit() == 1); assert(bcd.lastDigit() == 8); @@ -279,8 +286,7 @@ assert(bcd.firstDigit() == 0); assert(bcd.getDigit(5) == 7); bcd.setNumDigits(5); - assert(bcd.getDigit(2) == 6); -// writeln("bcd = ", bcd); + assert(bcd.getDigit(2) == 3); writeln("passed"); } @@ -529,18 +535,68 @@ return this; } -unittest { - write("multiply..."); - Bcd a, b, c; - a = 105, b = -22; - c = a * b; - assert(c == -2310); - c = 45; - c *= 1205; -// writeln("c = ", c); - assert(c == 54225); - writeln("passed"); -} + unittest { + write("multiply..."); + Bcd a, b, c; + a = 105, b = -22; + c = a * b; + assert(c == -2310); + c = 45; + c *= 1205; + // writeln("c = ", c); + assert(c == 54225); + writeln("passed"); + } + + const Bcd opDiv(T:Bcd)(const T b) { + Bcd rem; + return divide(this, b, rem); + } + + unittest { + write("opDiv..."); + Bcd a, b; + a = 7; + b = 3; + assert(a/b == 2); + writeln("passed"); + } + + const Bcd opDiv(T)(const T b) { + Bcd rem; + return divide(this, Bcd(b), rem); + } + + Bcd opDivAssign(T)(const T b) { + this = this / b; + return this; + } + + const Bcd opMod(T:Bcd)(const T b) { + Bcd rem; + divide(this, b, rem); + return rem; + } + + unittest { + write("opMod..."); + Bcd a, b; + a = 7; + b = 3; + assert(a % b == 1); + writeln("passed"); + } + + const Bcd opMod(T)(const T b) { + Bcd rem; + divide(this, Bcd(b), rem); + return rem; + } + + Bcd opModAssign(T)(const T b) { + this = this % b; + return this; + } const Bcd opAnd(const Bcd a) { return and(this, a); @@ -724,6 +780,8 @@ return 0; } + // TODO: does this need a const and a dup? + // should it be public?? private would be okay public Bcd stripLeadingZeros(const Bcd a) { Bcd d = a.dup; if (!a.hasLeadingZeros) return d; @@ -732,7 +790,7 @@ while(i < len-1 && a.getDigit(i) == 0) { i++; } - d.setNumDigits(len - i); + d.digits.length = (len-i); // - 1); if (d.numDigits == 1 && d.firstDigit == 0) { d.sign = false; } @@ -1217,44 +1275,41 @@ assert(pad(a,6).toString == "-008500"); writeln("passed"); } -public Bcd divide(const Bcd a, const Bcd b, out Bcd remainder) { - Bcd quotient; - Bcd dividend = stripLeadingZeros(a); -// writeln("dividend = ", dividend); - Bcd divisor = stripLeadingZeros(b); -// writeln("divisor = ", divisor); - if (divisor == ZERO) throw new Exception("Divide by zero"); - remainder = dividend; - writeln("remainder = ", remainder); - Bcd next = divisor; -// writeln("next = ", next); - Bcd multiple; +public Bcd divide(const Bcd a, const Bcd b, out Bcd r) { + + if (b == ZERO) throw new Exception("Divide by zero"); + if (a == ZERO) return ZERO.dup; + Bcd d = stripLeadingZeros(abs(b)); + r = stripLeadingZeros(abs(a)); + Bcd q; + Bcd p = d; + Bcd m; + + // shift the divisor do { - multiple = next; -// writeln("multiple = ", multiple); - next <<= 1; -// writeln("next = ", next); - } while (next <= remainder && next > multiple); + m = p; + p <<= 1; + } while (p <= r && p > m); - while (multiple >= divisor) { - quotient <<= 1; -// writeln("quotient = ", quotient); - while (multiple <= remainder) { - remainder -= multiple; - writeln("remainder = ", remainder); - quotient++; -// writeln("quotient = ", quotient); + while (m >= d) { + q <<= 1; + // subtract repeatedly + while (m <= r) { + r -= m; + q++; } - multiple >>= 1; -// writeln("multiple = ", multiple); + m >>= 1; } - return quotient; + + // adjust the sign + r.sign = a.sign; + q.sign = a.sign != b.sign; + return q; } unittest { write("divide..."); - writeln(); Bcd a, b, q, r; a = 144; b = 12; @@ -1269,8 +1324,8 @@ a = 142351; b = 12; q = divide(a, b, r); - writeln("q = ", q); - writeln("r = ", r); +// writeln("q = ", q); +// writeln("r = ", r); assert(q == 11862); assert(r == 7); a = 2; @@ -1278,6 +1333,26 @@ q = divide(a, b, r); assert(q == 0); assert(r == 2); + a = 7; + b = 3; + q = divide(a, b, r); + assert(q == 2); + assert(r == 1); + a = 7; + b = -3; + q = divide(a, b, r); + assert(q == -2); + assert(r == 1); + a = -7; + b = 3; + q = divide(a, b, r); + assert(q == -2); + assert(r == -1); + a = -7; + b = -3; + q = divide(a, b, r); + assert(q == 2); + assert(r == -1); writeln("passed"); }