diff --git a/SharpBag/Math/BigDecimal.cs b/SharpBag/Math/BigDecimal.cs index 9c0609c..ddcaa5d 100644 --- a/SharpBag/Math/BigDecimal.cs +++ b/SharpBag/Math/BigDecimal.cs @@ -370,9 +370,19 @@ public static BigDecimal Parse(string value, int precision) /// -Left public static BigDecimal operator -(BigDecimal value) { return value.Negate(); } + /// + /// Implements the operator %. + /// + /// The left number. + /// The right number. + /// + /// The result of the operator. + /// + public static BigDecimal operator %(BigDecimal left, BigDecimal right) { return BigDecimal.Remainder(left, right); } + private BigDecimal Add(BigDecimal right, bool normalize) { - BigDecimal.Normalize(ref this, ref right); + BigDecimal.Align(ref this, ref right); BigDecimal result = new BigDecimal(this.Mantissa + right.Mantissa, this.Exponent, BigDecimal.PrecisionFor(ref this, ref right), false, this.UsingDefaultPrecision != right.UsingDefaultPrecision || this.UsingDefaultPrecision); if (normalize) @@ -391,7 +401,7 @@ private BigDecimal Add(BigDecimal right) private BigDecimal Subtract(BigDecimal right, bool normalize) { - BigDecimal.Normalize(ref this, ref right); + BigDecimal.Align(ref this, ref right); BigDecimal result = new BigDecimal(this.Mantissa - right.Mantissa, this.Exponent, BigDecimal.PrecisionFor(ref this, ref right), false, this.UsingDefaultPrecision != right.UsingDefaultPrecision || this.UsingDefaultPrecision); if (normalize) @@ -447,6 +457,52 @@ private BigDecimal Divide(BigDecimal right) return new BigDecimal(pos ? mantissa : -mantissa, exponent, precision - BigDecimal.ExtraPrecision - 2, false, this.UsingDefaultPrecision != right.UsingDefaultPrecision || this.UsingDefaultPrecision); } + /// + /// Computes the absolute value of the value. + /// + /// The value. + /// The absolute value. + public static BigDecimal Abs(BigDecimal value) + { + return new BigDecimal(BigInteger.Abs(value.Mantissa), value.Exponent, value.Precision, value.Normalized, value.UsingDefaultPrecision); + } + + /// + /// Computes the left number divided by the right number and the remainder of that divison. + /// + /// The left number. + /// The right number. + /// The remainder. + /// The result of the division. + public static BigDecimal DivRem(BigDecimal left, BigDecimal right, out BigDecimal remainder) + { + BigDecimal.Align(ref left, ref right); + int precision = BigDecimal.PrecisionFor(ref left, ref right); + + bool leftPos = left.Mantissa >= 0, + rightPos = right.Mantissa >= 0, + pos = !(leftPos ^ rightPos); + + BigInteger curRemainder, + mantissa = BigInteger.DivRem(leftPos ? left.Mantissa : -left.Mantissa, rightPos ? right.Mantissa : -right.Mantissa, out curRemainder); + + remainder = new BigDecimal(leftPos ? curRemainder : -curRemainder, left.Exponent, precision, false, false); + return new BigDecimal(pos ? mantissa : -mantissa, 0, precision, false, false); + } + + /// + /// Computes the remainder of the division of the two numbers. + /// + /// The left number. + /// The right number. + /// The remainder. + public static BigDecimal Remainder(BigDecimal left, BigDecimal right) + { + BigDecimal rem; + BigDecimal.DivRem(left, right, out rem); + return rem; + } + /// /// Raise the BigDecimal to the specified power. /// @@ -484,7 +540,7 @@ public static BigDecimal Pow(BigDecimal value, BigDecimal power) if (power < 0) return BigDecimal.Reciprocal(BigDecimal.Pow(value, -power)); if (power == 0) return new BigDecimal(1, 0, value.Precision, true, value.UsingDefaultPrecision); if (power == 1) return new BigDecimal(value); - return BigDecimal.Exp(BigDecimal.Ln(value) * power); + return BigDecimal.Exp(BigDecimal.Log(value) * power); } /// @@ -503,14 +559,13 @@ public static BigDecimal Log10(BigDecimal value) while (digits < precision) { - // m = BigDecimal.Pow(new BigDecimal(m, value.Precision).Divide(BigInteger.Pow(10, a)), 10); m = BigDecimal.Pow(m / BigInteger.Pow(10, a), 10); a = (int)BigInteger.Log10(m.Mantissa) + m.Exponent; mantissa = mantissa * 10 + a; digits++; } - return new BigDecimal(mantissa, -digits, value.Precision, false, value.UsingDefaultPrecision) /*.RoundLastDigit()*/; + return new BigDecimal(mantissa, -digits, value.Precision, false, value.UsingDefaultPrecision); } /// @@ -518,7 +573,7 @@ public static BigDecimal Log10(BigDecimal value) /// /// The value. /// The natural logarithm. - public static BigDecimal Ln(BigDecimal value) + public static BigDecimal Log(BigDecimal value) { return BigDecimal.Log10(value) / Constants.Log10EBig(value.Precision); } @@ -591,6 +646,89 @@ public static BigDecimal Exp(BigDecimal value) return BigDecimal.Round(result, value.Precision + 1); } + /// + /// Computes the sine of the specified value. + /// + /// The value. + /// The sine of the specified value. + public static BigDecimal Sin(BigDecimal value) + { + BigDecimal result = value, + result2 = result * result, + lastResult, + it = BigDecimal.One.WithPrecision(value.Precision), + fact = BigDecimal.One.WithPrecision(value.Precision), + pow = value; + + bool alt = false; + + do + { + lastResult = result; + pow *= result2; + fact *= (it + 1) * (it + 2); + + if (alt) result += pow / fact; + else result -= pow / fact; + alt = !alt; + it += 2; + } + while (result != lastResult); + + if (BigDecimal.Abs(result) > 1) throw new ArgumentOutOfRangeException("value must be between -2pi and 2pi"); + return result; + } + + /// + /// Computes the cosine of the specified value. + /// + /// The value. + /// The cosine of the specified value. + public static BigDecimal Cos(BigDecimal value) + { + BigDecimal result = BigDecimal.One.WithPrecision(value.Precision), + result2 = value * value, + lastResult, + it = BigDecimal.Zero.WithPrecision(value.Precision), + fact = BigDecimal.One.WithPrecision(value.Precision), + pow = result; + + bool alt = false; + + do + { + lastResult = result; + pow *= result2; + fact *= (it + 1) * (it + 2); + + if (alt) result += pow / fact; + else result -= pow / fact; + alt = !alt; + it += 2; + } + while (result != lastResult); + + if (BigDecimal.Abs(result) > 1) throw new ArgumentOutOfRangeException("value must be between -2pi and 2pi"); + return result; + } + + /// + /// Computes the tangent of the specified value. + /// + /// The value. + /// The tangent of the specified value. + public static BigDecimal Tan(BigDecimal value) + { + try + { + return BigDecimal.Sin(value) / BigDecimal.Cos(value); + } + catch (ArgumentOutOfRangeException) + { + throw; + } + } + /// /// Rounds the BigDecimal. /// @@ -668,7 +806,7 @@ public static BigDecimal Round(BigDecimal value, int digits = 0) private bool Equals(BigDecimal other, bool normalize) { - BigDecimal.Normalize(ref this, ref other); + BigDecimal.Align(ref this, ref other); bool eq = this.WithoutExtraPrecision().Mantissa.Equals(other.WithoutExtraPrecision().Mantissa); if (normalize) @@ -710,7 +848,7 @@ public int CompareTo(BigDecimal other) BigDecimal left = this.WithoutExtraPrecision(), right = other.WithoutExtraPrecision(); - BigDecimal.Normalize(ref left, ref right); + BigDecimal.Align(ref left, ref right); return left.Mantissa.CompareTo(right.Mantissa); } @@ -931,7 +1069,7 @@ private void Normalize() } } - private void NormalizeTo(BigDecimal other) + private void AlignWith(BigDecimal other) { if (this.Exponent > other.Exponent) { @@ -940,10 +1078,10 @@ private void NormalizeTo(BigDecimal other) } } - private static void Normalize(ref BigDecimal a, ref BigDecimal b) + private static void Align(ref BigDecimal a, ref BigDecimal b) { - if (a.Exponent > b.Exponent) a.NormalizeTo(b); - else b.NormalizeTo(a); + if (a.Exponent > b.Exponent) a.AlignWith(b); + else b.AlignWith(a); } private static int PrecisionFor(ref BigDecimal a, ref BigDecimal b) diff --git a/SharpBag/bin/Release/CodeContracts/SharpBag.Contracts.dll b/SharpBag/bin/Release/CodeContracts/SharpBag.Contracts.dll index fb13ed4..44e06f7 100644 Binary files a/SharpBag/bin/Release/CodeContracts/SharpBag.Contracts.dll and b/SharpBag/bin/Release/CodeContracts/SharpBag.Contracts.dll differ diff --git a/SharpBag/bin/Release/SharpBag.dll b/SharpBag/bin/Release/SharpBag.dll index e318bec..6ed0e66 100644 Binary files a/SharpBag/bin/Release/SharpBag.dll and b/SharpBag/bin/Release/SharpBag.dll differ diff --git a/SharpBag/bin/Release/SharpBagDocs.xml b/SharpBag/bin/Release/SharpBagDocs.xml index 9be0e8d..fa33510 100644 --- a/SharpBag/bin/Release/SharpBagDocs.xml +++ b/SharpBag/bin/Release/SharpBagDocs.xml @@ -414,6 +414,40 @@ The value. -Left + + + Implements the operator %. + + The left number. + The right number. + + The result of the operator. + + + + + Computes the absolute value of the value. + + The value. + The absolute value. + + + + Computes the left number divided by the right number and the remainder of that divison. + + The left number. + The right number. + The remainder. + The result of the division. + + + + Computes the remainder of the division of the two numbers. + + The left number. + The right number. + The remainder. + Raise the BigDecimal to the specified power. @@ -437,7 +471,7 @@ The BigDecimal. The base-10 logarithm of the BigDecimal. - + Calculates the natural logarithm of the value. @@ -473,6 +507,27 @@ The BigDecimal. e ^ x + + + Computes the sine of the specified value. + + The value. + The sine of the specified value. + + + + Computes the cosine of the specified value. + + The value. + The cosine of the specified value. + + + + Computes the tangent of the specified value. + + The value. + The tangent of the specified value. + Rounds the BigDecimal. @@ -4815,7 +4870,7 @@ - Pi divided by 2. + Pi divided by two. Pi / 2