private static void TestSin(Double a) { String di = System.Math.Sin(a).ToString(); String ni = BigMath.Sin(BigNum.Create(a)).ToString(); Console.WriteLine("Sin({0,6}) = {1,6} : {2,6} -> {3,6}", a, di, ni, di == ni ? "Pass" : "Fail"); }
private static BigNum EvaluateFunction(Function function, BigNum num) { switch (function) { case Function.Sin: return(BigMath.Sin(num)); case Function.Cos: return(BigMath.Cos(num)); case Function.Tan: return(BigMath.Tan(num)); case Function.Csc: return(BigMath.Csc(num)); case Function.Sec: return(BigMath.Sec(num)); case Function.Cot: return(BigMath.Cot(num)); case Function.Abs: return(BigMath.Abs(num)); case Function.Ceil: return(BigMath.Ceiling(num)); case Function.Floor: return(BigMath.Floor(num)); case Function.Fact: return(BigMath.Gamma(num)); default: throw new ExpressionException("Unknown or invalid function"); } }
private static void TestPow(Double a, Double b) { Int32 power = (Int32)System.Math.Round(100 * b); String di = System.Math.Pow(a, power).ToString(); String ni = BigMath.Pow(a, power).ToString(); Console.WriteLine("{0,6} ^ {1,6} = {2,6} : {3,6} -> {4,6}", a, power, di, ni, di == ni ? "Pass" : "Fail"); }
public static BigNum Sin(BigNum theta) { BigNumFactory f = theta.Factory; // calculate sine using the taylor series, the infinite sum of x^r/r! but to n iterations BigNum retVal = f.Zero; // first, reduce this to between 0 and 2Pi if (theta > f.TwoPi || theta < f.Zero) { theta = theta % f.TwoPi; } Boolean subtract = false; // using bignums for sine computation is too heavy. It's faster (and just as accurate) to use Doubles #if DoubleTrig Double thetaDbl = Double.Parse(theta.ToString(), Cult.InvariantCulture); for (Int32 r = 0; r < 20; r++) // 20 iterations is enough, any more just yields inaccurate less-significant digits { Double xPowerR = Math.Pow(thetaDbl, 2 * r + 1); Double factori = BigMath.Factorial((double)(2 * r + 1)); Double element = xPowerR / factori; Double addThis = subtract ? -element : element; BigNum addThisBig = f.Create(addThis); retVal += addThisBig; subtract = !subtract; } #else for (Int32 r = 0; r < _iterations; r++) { BigNum xPowerR = theta.Power(2 * r + 1); BigNum factori = Factorial(2 * r + 1); BigNum element = xPowerR / factori; retVal += subtract ? -element : element; subtract = !subtract; } #endif // TODO: This calculation generates useless and inaccurate trailing digits that must be truncated // so truncate them, when I figure out how many digits can be removed retVal.Truncate(10); return(retVal); }
private static void Normalise(BigInt oldNum, BigInt oldDen, out BigInt newNum, out BigInt newDen) { // TODO: Maybe also ensure that the denominator is positive, only the numerator can be negative // find the GCD of oldNum and oldDen, then apply it to find and return newNum and newDen BigInt gcd = (BigInt)BigMath.Gcd(oldNum, oldDen); newNum = (BigInt)(oldNum / gcd); newDen = (BigInt)(oldDen / gcd); }
private static BigNum Modulo(BigNum x, BigNum y) { // a % b == a - ( b * Floor[a / b] ) if (y == 0) { throw new DivideByZeroException("Divisor y cannot be zero"); } if (x.IsZero) { return(new BigFloat(0)); } BigNum floored = BigMath.Floor(x / y); BigNum multbyb = y * floored; BigNum retval = x - multbyb; return(retval); }
private void Reduce() { BigNum one = _factory.Unity; BigNum zer = _factory.Zero; Operator op = _operatorStack.Peek(); switch (op) { case Operator.Add: // Apply E := E + E EnsureVal(2); BigNum aa = _valueStack.Pop(); BigNum ab = _valueStack.Pop(); _valueStack.Push(aa + ab); break; case Operator.Sub: // Apply E := E - E EnsureVal(2); BigNum sa = _valueStack.Pop(); BigNum sb = _valueStack.Pop(); _valueStack.Push(sb - sa); break; case Operator.Mul: EnsureVal(2); BigNum ma = _valueStack.Pop(); BigNum mb = _valueStack.Pop(); _valueStack.Push(ma * mb); break; case Operator.Div: EnsureVal(2); BigNum da = _valueStack.Pop(); BigNum db = _valueStack.Pop(); _valueStack.Push(db / da); break; case Operator.Neg: EnsureVal(1); BigNum na = _valueStack.Pop(); _valueStack.Push(-na); break; case Operator.Pow: EnsureVal(2); BigNum pa = _valueStack.Pop(); BigNum pb = _valueStack.Pop(); _valueStack.Push(BigMath.Pow(pb, pa)); //Int32 exponent = Int32.Parse( pa.ToString(), N.Integer | N.AllowExponent, Cult.InvariantCulture ); // _valueStack.Push( pb.Power( exponent ) ); break; case Operator.PaR: _operatorStack.Pop(); break; case Operator.CoE: case Operator.CoN: case Operator.CoL: case Operator.CLE: case Operator.CoG: case Operator.CGE: EnsureVal(2); BigNum ea = _valueStack.Pop(); BigNum eb = _valueStack.Pop(); Boolean eq = ea == eb; Boolean lt = eb < ea; Boolean gt = eb > ea; if (op == Operator.CoE) { _valueStack.Push(eq ? one : zer); } else if (op == Operator.CoN) { _valueStack.Push(eq ? zer : one); } else if (op == Operator.CoL) { _valueStack.Push(lt ? one : zer); } else if (op == Operator.CLE) { _valueStack.Push(lt || eq ? one : zer); } else if (op == Operator.CoG) { _valueStack.Push(gt ? one : zer); } else if (op == Operator.CGE) { _valueStack.Push(gt || eq ? one : zer); } break; case Operator.And: case Operator.Or: case Operator.Xor: EnsureVal(2); BigNum binA = _valueStack.Pop(); BigNum binB = _valueStack.Pop(); switch (op) { case Operator.And: Boolean and = binA == one && binB == one; _valueStack.Push(and ? one : zer); break; case Operator.Or: Boolean or = binA == one || binB == one; _valueStack.Push(or ? one : zer); break; case Operator.Xor: Boolean xor = (binA == one && binB != one) || (binA != one && binB == one); _valueStack.Push(xor ? one : zer); break; } break; case Operator.Not: EnsureVal(1); BigNum notA = _valueStack.Pop(); if (notA == one) { notA = zer; } else { notA = one; } _valueStack.Push(notA); break; // Else, ignore it. Do not throw an exception } _operatorStack.Pop(); }