From efe85e24916c03e2621e168b36a1caf16f0628c2 Mon Sep 17 00:00:00 2001 From: Aleksey Cherepanov Date: Tue, 20 Oct 2015 13:14:34 +0300 Subject: [PATCH] ported to C# 4 Avoiding features: "using static", string interpolations with $ and null-checks with ?. op. String interpolations were replaced with string.Format. null-checks are done use if statement. "using static" is a bit trickier: - ListConstructor was inserted explicitly, - all methods from Symbolism.Constructors and Symbolism.Trigonometric.Constructors were moved into Symbolism.Function and inheritance was used to "import" names. --- Symbolism/Has.cs | 2 +- Symbolism/Symbolism.cs | 349 +++++++++++++++++++++---------------- Symbolism/Trigonometric.cs | 25 ++- Tests/Tests.cs | 214 ++++++++++++----------- 4 files changed, 327 insertions(+), 263 deletions(-) diff --git a/Symbolism/Has.cs b/Symbolism/Has.cs index b8087af..664bafb 100644 --- a/Symbolism/Has.cs +++ b/Symbolism/Has.cs @@ -39,7 +39,7 @@ public static bool Has(this MathObject obj, Func proc) return false; } - public static bool FreeOf(this MathObject obj, MathObject a) => !obj.Has(a); + public static bool FreeOf(this MathObject obj, MathObject a) { return !obj.Has(a); } } } } diff --git a/Symbolism/Symbolism.cs b/Symbolism/Symbolism.cs index 57e9bc1..1216068 100644 --- a/Symbolism/Symbolism.cs +++ b/Symbolism/Symbolism.cs @@ -17,66 +17,68 @@ limitations under the License. */ using System.Linq; using System.Text; -using static Symbolism.ListConstructor; +// using Symbolism.ListConstructor; + +using Symbolism.Trigonometric; namespace Symbolism { public abstract class MathObject { ////////////////////////////////////////////////////////////////////// - public static implicit operator MathObject(int n) => new Integer(n); + public static implicit operator MathObject(int n) { return new Integer(n); } - public static implicit operator MathObject(bool val) => new Bool(val); + public static implicit operator MathObject(bool val) { return new Bool(val); } ////////////////////////////////////////////////////////////////////// #region overloads for 'int' - public static MathObject operator +(MathObject a, int b) => a + new Integer(b); - public static MathObject operator -(MathObject a, int b) => a - new Integer(b); - public static MathObject operator *(MathObject a, int b) => a * new Integer(b); - public static MathObject operator /(MathObject a, int b) => a / new Integer(b); - public static MathObject operator ^(MathObject a, int b) => a ^ new Integer(b); - public static MathObject operator +(int a, MathObject b) => new Integer(a) + b; - public static MathObject operator -(int a, MathObject b) => new Integer(a) - b; - public static MathObject operator *(int a, MathObject b) => new Integer(a) * b; - public static MathObject operator /(int a, MathObject b) => new Integer(a) / b; - public static MathObject operator ^(int a, MathObject b) => new Integer(a) ^ b; + public static MathObject operator +(MathObject a, int b) { return a + new Integer(b); } + public static MathObject operator -(MathObject a, int b) { return a - new Integer(b); } + public static MathObject operator *(MathObject a, int b) { return a * new Integer(b); } + public static MathObject operator /(MathObject a, int b) { return a / new Integer(b); } + public static MathObject operator ^(MathObject a, int b) { return a ^ new Integer(b); } + public static MathObject operator +(int a, MathObject b) { return new Integer(a) + b; } + public static MathObject operator -(int a, MathObject b) { return new Integer(a) - b; } + public static MathObject operator *(int a, MathObject b) { return new Integer(a) * b; } + public static MathObject operator /(int a, MathObject b) { return new Integer(a) / b; } + public static MathObject operator ^(int a, MathObject b) { return new Integer(a) ^ b; } #endregion ////////////////////////////////////////////////////////////////////// #region overloads for 'double' - public static MathObject operator +(MathObject a, double b) => a + new DoubleFloat(b); - public static MathObject operator -(MathObject a, double b) => a - new DoubleFloat(b); - public static MathObject operator *(MathObject a, double b) => a * new DoubleFloat(b); - public static MathObject operator /(MathObject a, double b) => a / new DoubleFloat(b); - public static MathObject operator ^(MathObject a, double b) => a ^ new DoubleFloat(b); - public static MathObject operator +(double a, MathObject b) => new DoubleFloat(a) + b; - public static MathObject operator -(double a, MathObject b) => new DoubleFloat(a) - b; - public static MathObject operator *(double a, MathObject b) => new DoubleFloat(a) * b; - public static MathObject operator /(double a, MathObject b) => new DoubleFloat(a) / b; - public static MathObject operator ^(double a, MathObject b) => new DoubleFloat(a) ^ b; + public static MathObject operator +(MathObject a, double b) { return a + new DoubleFloat(b); } + public static MathObject operator -(MathObject a, double b) { return a - new DoubleFloat(b); } + public static MathObject operator *(MathObject a, double b) { return a * new DoubleFloat(b); } + public static MathObject operator /(MathObject a, double b) { return a / new DoubleFloat(b); } + public static MathObject operator ^(MathObject a, double b) { return a ^ new DoubleFloat(b); } + public static MathObject operator +(double a, MathObject b) { return new DoubleFloat(a) + b; } + public static MathObject operator -(double a, MathObject b) { return new DoubleFloat(a) - b; } + public static MathObject operator *(double a, MathObject b) { return new DoubleFloat(a) * b; } + public static MathObject operator /(double a, MathObject b) { return new DoubleFloat(a) / b; } + public static MathObject operator ^(double a, MathObject b) { return new DoubleFloat(a) ^ b; } #endregion ////////////////////////////////////////////////////////////////////// - public static Equation operator ==(MathObject a, MathObject b) => new Equation(a, b); - public static Equation operator !=(MathObject a, MathObject b) => new Equation(a, b, Equation.Operators.NotEqual); - public static Equation operator <(MathObject a, MathObject b) => new Equation(a, b, Equation.Operators.LessThan); - public static Equation operator >(MathObject a, MathObject b) => new Equation(a, b, Equation.Operators.GreaterThan); + public static Equation operator ==(MathObject a, MathObject b) { return new Equation(a, b); } + public static Equation operator !=(MathObject a, MathObject b) { return new Equation(a, b, Equation.Operators.NotEqual); } + public static Equation operator <(MathObject a, MathObject b) { return new Equation(a, b, Equation.Operators.LessThan); } + public static Equation operator >(MathObject a, MathObject b) { return new Equation(a, b, Equation.Operators.GreaterThan); } - public static Equation operator ==(MathObject a, double b) => new Equation(a, new DoubleFloat(b)); - public static Equation operator ==(double a, MathObject b) => new Equation(new DoubleFloat(a), b); + public static Equation operator ==(MathObject a, double b) { return new Equation(a, new DoubleFloat(b)); } + public static Equation operator ==(double a, MathObject b) { return new Equation(new DoubleFloat(a), b); } - public static Equation operator !=(MathObject a, double b) => new Equation(a, new DoubleFloat(b), Equation.Operators.NotEqual); - public static Equation operator !=(double a, MathObject b) => new Equation(new DoubleFloat(a), b, Equation.Operators.NotEqual); + public static Equation operator !=(MathObject a, double b) { return new Equation(a, new DoubleFloat(b), Equation.Operators.NotEqual); } + public static Equation operator !=(double a, MathObject b) { return new Equation(new DoubleFloat(a), b, Equation.Operators.NotEqual); } - public static Equation operator ==(MathObject a, int b) => new Equation(a, new Integer(b)); - public static Equation operator ==(int a, MathObject b) => new Equation(new Integer(a), b); - public static Equation operator !=(MathObject a, int b) => new Equation(a, new Integer(b), Equation.Operators.NotEqual); - public static Equation operator !=(int a, MathObject b) => new Equation(new Integer(a), b, Equation.Operators.NotEqual); + public static Equation operator ==(MathObject a, int b) { return new Equation(a, new Integer(b)); } + public static Equation operator ==(int a, MathObject b) { return new Equation(new Integer(a), b); } + public static Equation operator !=(MathObject a, int b) { return new Equation(a, new Integer(b), Equation.Operators.NotEqual); } + public static Equation operator !=(int a, MathObject b) { return new Equation(new Integer(a), b, Equation.Operators.NotEqual); } ////////////////////////////////////////////////////////////////////// - public static MathObject operator +(MathObject a, MathObject b) => new Sum(a, b).Simplify(); - public static MathObject operator -(MathObject a, MathObject b) => new Difference(a, b).Simplify(); - public static MathObject operator *(MathObject a, MathObject b) => new Product(a, b).Simplify(); - public static MathObject operator /(MathObject a, MathObject b) => new Quotient(a, b).Simplify(); - public static MathObject operator ^(MathObject a, MathObject b) => new Power(a, b).Simplify(); + public static MathObject operator +(MathObject a, MathObject b) { return new Sum(a, b).Simplify(); } + public static MathObject operator -(MathObject a, MathObject b) { return new Difference(a, b).Simplify(); } + public static MathObject operator *(MathObject a, MathObject b) { return new Product(a, b).Simplify(); } + public static MathObject operator /(MathObject a, MathObject b) { return new Quotient(a, b).Simplify(); } + public static MathObject operator ^(MathObject a, MathObject b) { return new Power(a, b).Simplify(); } public static MathObject operator -(MathObject a) { return new Difference(a).Simplify(); } @@ -107,9 +109,9 @@ public enum ToStringForms { Full, Standard } public static ToStringForms ToStringForm = ToStringForms.Full; - public virtual string FullForm() => base.ToString(); + public virtual string FullForm() { return base.ToString(); } - public virtual string StandardForm() => FullForm(); + public virtual string StandardForm() { return FullForm(); } public override string ToString() { @@ -120,14 +122,14 @@ public override string ToString() throw new Exception(); } - public virtual MathObject Numerator() => this; + public virtual MathObject Numerator() { return this; } - public virtual MathObject Denominator() => 1; + public virtual MathObject Denominator() { return 1; } public override bool Equals(object obj) { throw new Exception("MathObject.Equals called - abstract class"); } - public override int GetHashCode() => base.GetHashCode(); + public override int GetHashCode() { return base.GetHashCode(); } } public class Equation : MathObject @@ -154,12 +156,14 @@ public override string FullForm() throw new Exception(); } - public override bool Equals(object obj) => + public override bool Equals(object obj) { + return obj is Equation && a.Equals((obj as Equation).a) && b.Equals((obj as Equation).b) && Operator == (obj as Equation).Operator; - + } + Boolean ToBoolean() { if (a is Bool && b is Bool) return (a as Bool).Equals(b); @@ -214,7 +218,7 @@ public MathObject Simplify() return this; } - public override int GetHashCode() => new { a, b }.GetHashCode(); + public override int GetHashCode() { return new { a, b }.GetHashCode(); } } @@ -224,11 +228,16 @@ public class Bool : MathObject public Bool(bool b) { val = b; } - public override string FullForm() => val.ToString(); + public override string FullForm() { return val.ToString(); } - public override bool Equals(object obj) => val == (obj as Bool)?.val; - - public override int GetHashCode() => val.GetHashCode(); + public override bool Equals(object obj) { + if ((obj as Bool) != null) { + return val == (obj as Bool).val; + } + return false; + } + + public override int GetHashCode() { return val.GetHashCode(); } } //public class NotEqual @@ -254,13 +263,18 @@ public class Integer : Number public Integer(int n) { val = n; } - public override string FullForm() => val.ToString(); + public override string FullForm() { return val.ToString(); } - public override bool Equals(object obj) => val == (obj as Integer)?.val; + public override bool Equals(object obj) { + if ((obj as Integer) != null) { + return val == (obj as Integer).val; + } + return false; + } - public override int GetHashCode() => val.GetHashCode(); + public override int GetHashCode() { return val.GetHashCode(); } - public override DoubleFloat ToDouble() => new DoubleFloat(val); + public override DoubleFloat ToDouble() { return new DoubleFloat(val); } } public class DoubleFloat : Number @@ -271,7 +285,7 @@ public class DoubleFloat : Number public DoubleFloat(double n) { val = n; } - public override string FullForm() => val.ToString("R"); + public override string FullForm() { return val.ToString("R"); } //public bool EqualWithinTolerance(DoubleFloat obj) //{ @@ -291,9 +305,9 @@ public override bool Equals(object obj) return false; } - public override int GetHashCode() => val.GetHashCode(); + public override int GetHashCode() { return val.GetHashCode(); } - public override DoubleFloat ToDouble() => this; + public override DoubleFloat ToDouble() { return this; } } public class Fraction : Number @@ -304,21 +318,27 @@ public class Fraction : Number public Fraction(Integer a, Integer b) { numerator = a; denominator = b; } - public override string FullForm() => numerator + "/" + denominator; + public override string FullForm() { return numerator + "/" + denominator; } - public override DoubleFloat ToDouble() => new DoubleFloat((double)numerator.val / (double)denominator.val); + public override DoubleFloat ToDouble() { return new DoubleFloat((double)numerator.val / (double)denominator.val); } ////////////////////////////////////////////////////////////////////// - public override bool Equals(object obj) => - numerator == (obj as Fraction)?.numerator - && - denominator == (obj as Fraction)?.denominator; + public override bool Equals(object obj) { + if (obj == null) { + return false; + } else { + return + numerator == (obj as Fraction).numerator + && + denominator == (obj as Fraction).denominator; + } + } - public override int GetHashCode() => new { numerator, denominator }.GetHashCode(); + public override int GetHashCode() { return new { numerator, denominator }.GetHashCode(); } - public override MathObject Numerator() => numerator; + public override MathObject Numerator() { return numerator; } - public override MathObject Denominator() => denominator; + public override MathObject Denominator() { return denominator; } } public static class Rational @@ -555,22 +575,23 @@ public class Symbol : MathObject public Symbol(String str) { name = str; } - public override string FullForm() => name; + public override string FullForm() { return name; } - public override int GetHashCode() => name.GetHashCode(); + public override int GetHashCode() { return name.GetHashCode(); } - public override bool Equals(Object obj) => - obj is Symbol ? name == (obj as Symbol).name : false; + public override bool Equals(Object obj) { + return obj is Symbol ? name == (obj as Symbol).name : false; + } } public static class ListConstructor { - public static List List(params T[] items) => new List(items); + public static List List(params T[] items) { return new List(items); } } public static class ListUtils { - public static bool IsEmpty(this List obj) => obj.Count == 0; + public static bool IsEmpty(this List obj) { return obj.Count == 0; } public static List Cons(this List obj, MathObject elt) { @@ -579,7 +600,7 @@ public static List Cons(this List obj, MathObject elt) return res; } - public static List Cdr(this List obj) => obj.GetRange(1, obj.Count - 1); + public static List Cdr(this List obj) { return obj.GetRange(1, obj.Count - 1); } public static bool equal(List a, List b) { @@ -599,24 +620,39 @@ public class Function : MathObject { public String name; + // Symbolism.Trigonometric.Constructors. + public static MathObject sin(MathObject obj) { return new Sin(obj).Simplify(); } + public static MathObject cos(MathObject obj) { return new Cos(obj).Simplify(); } + public static MathObject tan(MathObject obj) { return new Tan(obj).Simplify(); } + public static MathObject asin(MathObject obj) { return new Asin(obj).Simplify(); } + public static MathObject atan(MathObject obj) { return new Atan(obj).Simplify(); } + + // Symbolism.Constructors + public static MathObject sqrt(MathObject obj) { return obj ^ (new Integer(1) / new Integer(2)); } + public static MathObject and(params MathObject[] ls) { return new And() { args = ls.ToList() }.Simplify(); } + public static MathObject or(params MathObject[] ls) { return new Or() { args = ls.ToList() }.Simplify(); } + + public List args; public delegate MathObject Proc(params MathObject[] ls); public Proc proc; - public override bool Equals(object obj) => + public override bool Equals(object obj) { + return GetType() == obj.GetType() && name == (obj as Function).name && ListUtils.equal(args, ((Function)obj).args); + } + + public MathObject Simplify() { return proc == null ? this : proc(args.ToArray()); } - public MathObject Simplify() => proc == null ? this : proc(args.ToArray()); - - public override string FullForm() => $"{name}({string.Join(", ", args)})"; + public override string FullForm() { return string.Format("{0}({1})", name, string.Join(", ", args)); } - public MathObject Clone() => MemberwiseClone() as MathObject; + public MathObject Clone() { return MemberwiseClone() as MathObject; } - public override int GetHashCode() => new { name, args }.GetHashCode(); + public override int GetHashCode() { return new { name, args }.GetHashCode(); } } public static class FunctionExtensions @@ -725,9 +761,9 @@ public Or(params MathObject[] ls) public static class OrderRelation { - public static MathObject Base(MathObject u) => u is Power ? (u as Power).bas : u; + public static MathObject Base(MathObject u) { return u is Power ? (u as Power).bas : u; } - public static MathObject Exponent(MathObject u) => u is Power ? (u as Power).exp : 1; + public static MathObject Exponent(MathObject u) { return u is Power ? (u as Power).exp : 1; } public static MathObject Term(this MathObject u) { @@ -739,8 +775,10 @@ public static MathObject Term(this MathObject u) return new Product(u); } - public static MathObject Const(this MathObject u) => + public static MathObject Const(this MathObject u) { + return (u is Product && (u as Product).elts[0] is Number) ? (u as Product).elts[0] : 1; + } public static bool O3(List uElts, List vElts) { @@ -867,26 +905,29 @@ public class Power : MathObject public Power(MathObject a, MathObject b) { bas = a; exp = b; } - public override string FullForm() => - string.Format("{0} ^ {1}", - bas.Precedence() < Precedence() ? $"({bas})" : $"{bas}", - exp.Precedence() < Precedence() ? $"({exp})" : $"{exp}"); + public override string FullForm() { + return string.Format("{0} ^ {1}", + string.Format(bas.Precedence() < Precedence() ? "({0})" : "{0}", bas), + string.Format(exp.Precedence() < Precedence() ? "({0})" : "{0}", exp)); + } public override string StandardForm() { // x ^ 1/2 -> sqrt(x) - if (exp == new Integer(1) / new Integer(2)) return $"sqrt({bas})"; + if (exp == new Integer(1) / new Integer(2)) return string.Format("sqrt({0})", bas); return string.Format("{0} ^ {1}", - bas.Precedence() < Precedence() ? $"({bas})" : $"{bas}", - exp.Precedence() < Precedence() ? $"({exp})" : $"{exp}"); + string.Format(bas.Precedence() < Precedence() ? "({0})" : "{0}", bas), + string.Format(exp.Precedence() < Precedence() ? "({0})" : "{0}", exp)); } - public override bool Equals(object obj) => + public override bool Equals(object obj) { + return obj is Power && bas == (obj as Power).bas && exp == (obj as Power).exp; - + } + public MathObject Simplify() { var v = bas; @@ -962,7 +1003,7 @@ public override MathObject Denominator() return 1; } - public override int GetHashCode() => new { bas, exp }.GetHashCode(); + public override int GetHashCode() { return new { bas, exp }.GetHashCode(); } } public class Product : MathObject @@ -972,34 +1013,39 @@ public class Product : MathObject public Product(params MathObject[] ls) { elts = new List(ls); } - public override string FullForm() => - string.Join(" * ", elts.ConvertAll(elt => elt.Precedence() < Precedence() ? $"({elt})" : $"{elt}")); + public override string FullForm() { + return string.Join(" * ", + elts.ConvertAll(elt => string.Format(elt.Precedence() < Precedence() ? "({0})" : "{0}", elt))); + } public override string StandardForm() { if (this.Denominator() == 1) { - if (this.Const() < 0) return $"-{(this * -1)}"; + if (this.Const() < 0) return string.Format("-{0}", (this * -1)); return string.Join(" * ", - elts.ConvertAll(elt => elt.Precedence() < Precedence() || (elt is Power && (elt as Power).exp != new Integer(1) / 2) ? $"({elt})" : $"{elt}")); + elts.ConvertAll(elt => + string.Format(elt.Precedence() < Precedence() || (elt is Power && (elt as Power).exp != new Integer(1) / 2) ? "({0})" : "{0}", elt))); } var expr_a = this.Numerator(); var expr_b = this.Denominator(); - var expr_a_ = expr_a is Sum || (expr_a is Power && (expr_a as Power).exp != new Integer(1) / 2) ? $"({expr_a})" : $"{expr_a}"; + var expr_a_ = string.Format(expr_a is Sum || (expr_a is Power && (expr_a as Power).exp != new Integer(1) / 2) ? "({0})" : "{0}", expr_a); - var expr_b_ = expr_b is Sum || expr_b is Product || (expr_b is Power && (expr_b as Power).exp != new Integer(1) / 2) ? $"({expr_b})" : $"{expr_b}"; + var expr_b_ = string.Format(expr_b is Sum || expr_b is Product || (expr_b is Power && (expr_b as Power).exp != new Integer(1) / 2) ? "({0})" : "{0}", expr_b); - return $"{expr_a_} / {expr_b_}"; + return string.Format("{0} / {1}", expr_a_, expr_b_); } - public override int GetHashCode() => elts.GetHashCode(); + public override int GetHashCode() { return elts.GetHashCode(); } - public override bool Equals(object obj) => + public override bool Equals(object obj) { + return obj is Product && ListUtils.equal(elts, (obj as Product).elts); - + } + static List MergeProducts(List pElts, List qElts) { if (pElts.Count == 0) return qElts; @@ -1011,15 +1057,15 @@ static List MergeProducts(List pElts, List q var q = qElts[0]; var qs = qElts.Cdr(); - var res = RecursiveSimplify(List(p, q)); + var res = RecursiveSimplify(ListConstructor.List(p, q)); if (res.Count == 0) return MergeProducts(ps, qs); if (res.Count == 1) return MergeProducts(ps, qs).Cons(res[0]); - if (ListUtils.equal(res, List(p, q))) return MergeProducts(ps, qElts).Cons(p); + if (ListUtils.equal(res, ListConstructor.List(p, q))) return MergeProducts(ps, qElts).Cons(p); - if (ListUtils.equal(res, List(q, p))) return MergeProducts(pElts, qs).Cons(q); + if (ListUtils.equal(res, ListConstructor.List(q, p))) return MergeProducts(pElts, qs).Cons(q); throw new Exception(); } @@ -1036,7 +1082,7 @@ static List SimplifyDoubleNumberProduct(DoubleFloat a, Number b) if (val == 1.0) return new List() { }; - return List(new DoubleFloat(val)); + return ListConstructor.List(new DoubleFloat(val)); } public static List RecursiveSimplify(List elts) @@ -1048,9 +1094,9 @@ public static List RecursiveSimplify(List elts) ((Product)elts[0]).elts, ((Product)elts[1]).elts); - if (elts[0] is Product) return MergeProducts(((Product)elts[0]).elts, List(elts[1])); + if (elts[0] is Product) return MergeProducts(((Product)elts[0]).elts, ListConstructor.List(elts[1])); - if (elts[1] is Product) return MergeProducts(List(elts[0]), ((Product)elts[1]).elts); + if (elts[1] is Product) return MergeProducts(ListConstructor.List(elts[0]), ((Product)elts[1]).elts); ////////////////////////////////////////////////////////////////////// @@ -1070,11 +1116,11 @@ public static List RecursiveSimplify(List elts) if (P == 1) return new List() { }; - return List(P); + return ListConstructor.List(P); } - if (elts[0] == 1) return List(elts[1]); - if (elts[1] == 1) return List(elts[0]); + if (elts[0] == 1) return ListConstructor.List(elts[1]); + if (elts[1] == 1) return ListConstructor.List(elts[0]); var p = elts[0]; var q = elts[1]; @@ -1085,12 +1131,12 @@ public static List RecursiveSimplify(List elts) if (res == 1) return new List() { }; - return List(res); + return ListConstructor.List(res); } - if (OrderRelation.Compare(q, p)) return List(q, p); + if (OrderRelation.Compare(q, p)) return ListConstructor.List(q, p); - return List(p, q); + return ListConstructor.List(p, q); } if (elts[0] is Product) @@ -1100,7 +1146,7 @@ public static List RecursiveSimplify(List elts) RecursiveSimplify(elts.Cdr())); return MergeProducts( - List(elts[0]), + ListConstructor.List(elts[0]), RecursiveSimplify(elts.Cdr())); throw new Exception(); @@ -1126,23 +1172,31 @@ public MathObject Simplify() return new Product() { elts = res }; } - public override MathObject Numerator() => - new Product() { elts = elts.Select(elt => elt.Numerator()).ToList() }.Simplify(); + public override MathObject Numerator() { + return + new Product() { elts = elts.Select(elt => elt.Numerator()).ToList() }.Simplify(); + } - public override MathObject Denominator() => + public override MathObject Denominator() { + return new Product() { elts = elts.Select(elt => elt.Denominator()).ToList() }.Simplify(); + } } + public class Sum : MathObject { public List elts; public Sum(params MathObject[] ls) { elts = new List(ls); } - public override int GetHashCode() => elts.GetHashCode(); + public override int GetHashCode() { return elts.GetHashCode(); } + + public override bool Equals(object obj) { + return + obj is Sum && ListUtils.equal(elts, (obj as Sum).elts); + } - public override bool Equals(object obj) => - obj is Sum && ListUtils.equal(elts, (obj as Sum).elts); static List MergeSums(List pElts, List qElts) { @@ -1155,15 +1209,15 @@ static List MergeSums(List pElts, List qElts var q = qElts[0]; var qs = qElts.Cdr(); - var res = RecursiveSimplify(List(p, q)); + var res = RecursiveSimplify(ListConstructor.List(p, q)); if (res.Count == 0) return MergeSums(ps, qs); if (res.Count == 1) return MergeSums(ps, qs).Cons(res[0]); - if (ListUtils.equal(res, List(p, q))) return MergeSums(ps, qElts).Cons(p); + if (ListUtils.equal(res, ListConstructor.List(p, q))) return MergeSums(ps, qElts).Cons(p); - if (ListUtils.equal(res, List(q, p))) return MergeSums(pElts, qs).Cons(q); + if (ListUtils.equal(res, ListConstructor.List(q, p))) return MergeSums(pElts, qs).Cons(q); throw new Exception(); } @@ -1195,11 +1249,11 @@ static List RecursiveSimplify(List elts) if (elts[0] is Sum) return MergeSums( ((Sum)elts[0]).elts, - List(elts[1])); + ListConstructor.List(elts[1])); if (elts[1] is Sum) return MergeSums( - List(elts[0]), + ListConstructor.List(elts[0]), ((Sum)elts[1]).elts); ////////////////////////////////////////////////////////////////////// @@ -1220,12 +1274,12 @@ static List RecursiveSimplify(List elts) if (P == 0) return new List() { }; - return List(P); + return ListConstructor.List(P); } - if (elts[0] == 0) return List(elts[1]); + if (elts[0] == 0) return ListConstructor.List(elts[1]); - if (elts[1] == 0) return List(elts[0]); + if (elts[1] == 0) return ListConstructor.List(elts[0]); var p = elts[0]; var q = elts[1]; @@ -1236,12 +1290,12 @@ static List RecursiveSimplify(List elts) if (res == 0) return new List() { }; - return List(res); + return ListConstructor.List(res); } - if (OrderRelation.Compare(q, p)) return List(q, p); + if (OrderRelation.Compare(q, p)) return ListConstructor.List(q, p); - return List(p, q); + return ListConstructor.List(p, q); } if (elts[0] is Sum) @@ -1250,7 +1304,7 @@ static List RecursiveSimplify(List elts) ((Sum)elts[0]).elts, RecursiveSimplify(elts.Cdr())); return MergeSums( - List(elts[0]), RecursiveSimplify(elts.Cdr())); + ListConstructor.List(elts[0]), RecursiveSimplify(elts.Cdr())); } public MathObject Simplify() @@ -1265,8 +1319,11 @@ public MathObject Simplify() return new Sum() { elts = res }; } - public override string FullForm() => - String.Join(" + ", elts.ConvertAll(elt => elt.Precedence() < Precedence() ? $"({elt})" : $"{elt}")); + public override string FullForm() { + return + String.Join(" + ", elts.ConvertAll(elt => + string.Format(elt.Precedence() < Precedence() ? "({0})" : "{0}", elt))); + } public override string StandardForm() { @@ -1276,9 +1333,9 @@ public override string StandardForm() { var elt_ = elt.Const() < 0 ? elt * -1 : elt; - var elt__ = elt.Const() < 0 && elt_ is Sum || (elt is Power && (elt as Power).exp != new Integer(1) / 2) ? $"({elt_})" : $"{elt_}"; + var elt__ = string.Format(elt.Const() < 0 && elt_ is Sum || (elt is Power && (elt as Power).exp != new Integer(1) / 2) ? "({0})" : "{0}", elt_); - return elt.Const() < 0 ? $"- {elt__}" : $"+ {elt__}"; + return string.Format(elt.Const() < 0 ? "- {0}" : "+ {0}", elt__); })); if (result.StartsWith("+ ")) return result.Remove(0, 2); // "+ x + y" -> "x + y" @@ -1313,15 +1370,15 @@ class Quotient : MathObject public Quotient(params MathObject[] ls) { elts = new List(ls); } - public MathObject Simplify() => elts[0] * (elts[1] ^ -1); + public MathObject Simplify() { return elts[0] * (elts[1] ^ -1); } } - public static class Constructors - { - public static MathObject sqrt(MathObject obj) => obj ^ (new Integer(1) / new Integer(2)); + // public static class Constructors + // { + // public static MathObject sqrt(MathObject obj) { return obj ^ (new Integer(1) / new Integer(2)); } - public static MathObject and(params MathObject[] ls) => new And() { args = ls.ToList() }.Simplify(); + // public static MathObject and(params MathObject[] ls) { return new And() { args = ls.ToList() }.Simplify(); } - public static MathObject or(params MathObject[] ls) => new Or() { args = ls.ToList() }.Simplify(); - } + // public static MathObject or(params MathObject[] ls) { return new Or() { args = ls.ToList() }.Simplify(); } + // } } diff --git a/Symbolism/Trigonometric.cs b/Symbolism/Trigonometric.cs index 1630c6b..42113ff 100644 --- a/Symbolism/Trigonometric.cs +++ b/Symbolism/Trigonometric.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Text; -using static Symbolism.ListConstructor; +// using Symbolism.ListConstructor; -using static Symbolism.Trigonometric.Constructors; +// using Symbolism.Trigonometric.Constructors; namespace Symbolism.Trigonometric { @@ -65,7 +65,7 @@ MathObject SinProc(params MathObject[] ls) // n is one of 1 2 3 4 6 if (u is Product && - List(1, 2, 3, 4, 6).Any(elt => + ListConstructor.List(1, 2, 3, 4, 6).Any(elt => elt == (u as Product).elts[0].Denominator()) && (u as Product).elts[0].Numerator() is Integer && (u as Product).elts[1] == Pi) @@ -233,7 +233,7 @@ MathObject CosProc(params MathObject[] ls) if (ls[0] is Product && - List(1, 2, 3, 4, 6) + ListConstructor.List(1, 2, 3, 4, 6) .Any(elt => elt == (ls[0] as Product).elts[0].Denominator()) && (ls[0] as Product).elts[0].Numerator() is Integer && @@ -446,15 +446,14 @@ public Atan2(MathObject a, MathObject b) } } - public static class Constructors - { - public static MathObject sin(MathObject obj) => new Sin(obj).Simplify(); - public static MathObject cos(MathObject obj) => new Cos(obj).Simplify(); - public static MathObject tan(MathObject obj) => new Tan(obj).Simplify(); - - public static MathObject asin(MathObject obj) => new Asin(obj).Simplify(); - public static MathObject atan(MathObject obj) => new Atan(obj).Simplify(); - } + // public static class Constructors + // { + // public static MathObject sin(MathObject obj) { return new Sin(obj).Simplify(); } + // public static MathObject cos(MathObject obj) { return new Cos(obj).Simplify(); } + // public static MathObject tan(MathObject obj) { return new Tan(obj).Simplify(); } + // public static MathObject asin(MathObject obj) { return new Asin(obj).Simplify(); } + // public static MathObject atan(MathObject obj) { return new Atan(obj).Simplify(); } + // } public static class Extensions { diff --git a/Tests/Tests.cs b/Tests/Tests.cs index 9e76769..16e0f5b 100644 --- a/Tests/Tests.cs +++ b/Tests/Tests.cs @@ -38,9 +38,9 @@ limitations under the License. */ using Symbolism.RationalizeExpression; -using static Symbolism.Constructors; +// using static Symbolism.Constructors; -using static Symbolism.Trigonometric.Constructors; +// using static Symbolism.Trigonometric.Constructors; namespace Tests { @@ -115,7 +115,7 @@ public static MathObject AddToBothSides(this MathObject obj, MathObject item) } - public class Obj2 + public class Obj2 : Function { public Symbol ΣFx; public Symbol ΣFy; @@ -130,25 +130,25 @@ public class Obj2 public Obj2(string name) { - ΣFx = new Symbol($"{name}.ΣFx"); - ΣFy = new Symbol($"{name}.ΣFy"); + ΣFx = new Symbol(string.Format("{0}.ΣFx", name)); + ΣFy = new Symbol(string.Format("{0}.ΣFy", name)); - m = new Symbol($"{name}.m"); + m = new Symbol(string.Format("{0}.m", name)); - ax = new Symbol($"{name}.ax"); - ay = new Symbol($"{name}.ay"); + ax = new Symbol(string.Format("{0}.ax", name)); + ay = new Symbol(string.Format("{0}.ay", name)); - F1 = new Symbol($"{name}.F1"); - F2 = new Symbol($"{name}.F2"); + F1 = new Symbol(string.Format("{0}.F1", name)); + F2 = new Symbol(string.Format("{0}.F2", name)); - th1 = new Symbol($"{name}.th1"); - th2 = new Symbol($"{name}.th2"); + th1 = new Symbol(string.Format("{0}.th1", name)); + th2 = new Symbol(string.Format("{0}.th2", name)); - F1x = new Symbol($"{name}.F1x"); - F2x = new Symbol($"{name}.F2x"); + F1x = new Symbol(string.Format("{0}.F1x", name)); + F2x = new Symbol(string.Format("{0}.F2x", name)); - F1y = new Symbol($"{name}.F1y"); - F2y = new Symbol($"{name}.F2y"); + F1y = new Symbol(string.Format("{0}.F1y", name)); + F2y = new Symbol(string.Format("{0}.F2y", name)); } public And Equations() @@ -171,7 +171,7 @@ public And Equations() } } - public class Obj3 + public class Obj3 : Function { public Symbol ΣFx; public Symbol ΣFy; @@ -186,29 +186,29 @@ public class Obj3 public Obj3(string name) { - ΣFx = new Symbol($"{name}.ΣFx"); - ΣFy = new Symbol($"{name}.ΣFy"); + ΣFx = new Symbol(string.Format("{0}.ΣFx", name)); + ΣFy = new Symbol(string.Format("{0}.ΣFy", name)); - m = new Symbol($"{name}.m"); + m = new Symbol(string.Format("{0}.m", name)); - ax = new Symbol($"{name}.ax"); - ay = new Symbol($"{name}.ay"); + ax = new Symbol(string.Format("{0}.ax", name)); + ay = new Symbol(string.Format("{0}.ay", name)); - F1 = new Symbol($"{name}.F1"); - F2 = new Symbol($"{name}.F2"); - F3 = new Symbol($"{name}.F3"); + F1 = new Symbol(string.Format("{0}.F1", name)); + F2 = new Symbol(string.Format("{0}.F2", name)); + F3 = new Symbol(string.Format("{0}.F3", name)); - th1 = new Symbol($"{name}.th1"); - th2 = new Symbol($"{name}.th2"); - th3 = new Symbol($"{name}.th3"); + th1 = new Symbol(string.Format("{0}.th1", name)); + th2 = new Symbol(string.Format("{0}.th2", name)); + th3 = new Symbol(string.Format("{0}.th3", name)); - F1x = new Symbol($"{name}.F1x"); - F2x = new Symbol($"{name}.F2x"); - F3x = new Symbol($"{name}.F3x"); + F1x = new Symbol(string.Format("{0}.F1x", name)); + F2x = new Symbol(string.Format("{0}.F2x", name)); + F3x = new Symbol(string.Format("{0}.F3x", name)); - F1y = new Symbol($"{name}.F1y"); - F2y = new Symbol($"{name}.F2y"); - F3y = new Symbol($"{name}.F3y"); + F1y = new Symbol(string.Format("{0}.F1y", name)); + F2y = new Symbol(string.Format("{0}.F2y", name)); + F3y = new Symbol(string.Format("{0}.F3y", name)); } public And Equations() @@ -234,7 +234,7 @@ public And Equations() } } - public class Obj5 + public class Obj5 : Function { public Symbol ΣFx; public Symbol ΣFy; @@ -249,37 +249,37 @@ public class Obj5 public Obj5(string name) { - ΣFx = new Symbol($"{name}.ΣFx"); - ΣFy = new Symbol($"{name}.ΣFy"); - - m = new Symbol($"{name}.m"); - - ax = new Symbol($"{name}.ax"); - ay = new Symbol($"{name}.ay"); - - F1 = new Symbol($"{name}.F1"); - F2 = new Symbol($"{name}.F2"); - F3 = new Symbol($"{name}.F3"); - F4 = new Symbol($"{name}.F4"); - F5 = new Symbol($"{name}.F5"); - - th1 = new Symbol($"{name}.th1"); - th2 = new Symbol($"{name}.th2"); - th3 = new Symbol($"{name}.th3"); - th4 = new Symbol($"{name}.th4"); - th5 = new Symbol($"{name}.th5"); - - F1x = new Symbol($"{name}.F1x"); - F2x = new Symbol($"{name}.F2x"); - F3x = new Symbol($"{name}.F3x"); - F4x = new Symbol($"{name}.F4x"); - F5x = new Symbol($"{name}.F5x"); - - F1y = new Symbol($"{name}.F1y"); - F2y = new Symbol($"{name}.F2y"); - F3y = new Symbol($"{name}.F3y"); - F4y = new Symbol($"{name}.F4y"); - F5y = new Symbol($"{name}.F5y"); + ΣFx = new Symbol(string.Format("{0}.ΣFx", name)); + ΣFy = new Symbol(string.Format("{0}.ΣFy", name)); + + m = new Symbol(string.Format("{0}.m", name)); + + ax = new Symbol(string.Format("{0}.ax", name)); + ay = new Symbol(string.Format("{0}.ay", name)); + + F1 = new Symbol(string.Format("{0}.F1", name)); + F2 = new Symbol(string.Format("{0}.F2", name)); + F3 = new Symbol(string.Format("{0}.F3", name)); + F4 = new Symbol(string.Format("{0}.F4", name)); + F5 = new Symbol(string.Format("{0}.F5", name)); + + th1 = new Symbol(string.Format("{0}.th1", name)); + th2 = new Symbol(string.Format("{0}.th2", name)); + th3 = new Symbol(string.Format("{0}.th3", name)); + th4 = new Symbol(string.Format("{0}.th4", name)); + th5 = new Symbol(string.Format("{0}.th5", name)); + + F1x = new Symbol(string.Format("{0}.F1x", name)); + F2x = new Symbol(string.Format("{0}.F2x", name)); + F3x = new Symbol(string.Format("{0}.F3x", name)); + F4x = new Symbol(string.Format("{0}.F4x", name)); + F5x = new Symbol(string.Format("{0}.F5x", name)); + + F1y = new Symbol(string.Format("{0}.F1y", name)); + F2y = new Symbol(string.Format("{0}.F2y", name)); + F3y = new Symbol(string.Format("{0}.F3y", name)); + F4y = new Symbol(string.Format("{0}.F4y", name)); + F5y = new Symbol(string.Format("{0}.F5y", name)); } public And Equations() @@ -311,7 +311,7 @@ public And Equations() } } - public class KinematicObjectABC + public class KinematicObjectABC : Function { public Symbol xA, yA, vxA, vyA, vA, thA; public Symbol xB, yB, vxB, vyB, vB, thB; @@ -323,45 +323,45 @@ public class KinematicObjectABC public KinematicObjectABC(string name) { - xA = new Symbol($"{name}.xA"); - yA = new Symbol($"{name}.yA"); + xA = new Symbol(string.Format("{0}.xA", name)); + yA = new Symbol(string.Format("{0}.yA", name)); - vxA = new Symbol($"{name}.vxA"); - vyA = new Symbol($"{name}.vyA"); + vxA = new Symbol(string.Format("{0}.vxA", name)); + vyA = new Symbol(string.Format("{0}.vyA", name)); - vA = new Symbol($"{name}.vA"); - thA = new Symbol($"{name}.thA"); + vA = new Symbol(string.Format("{0}.vA", name)); + thA = new Symbol(string.Format("{0}.thA", name)); - xB = new Symbol($"{name}.xB"); - yB = new Symbol($"{name}.yB"); + xB = new Symbol(string.Format("{0}.xB", name)); + yB = new Symbol(string.Format("{0}.yB", name)); - vxB = new Symbol($"{name}.vxB"); - vyB = new Symbol($"{name}.vyB"); + vxB = new Symbol(string.Format("{0}.vxB", name)); + vyB = new Symbol(string.Format("{0}.vyB", name)); - vB = new Symbol($"{name}.vB"); - thB = new Symbol($"{name}.thB"); + vB = new Symbol(string.Format("{0}.vB", name)); + thB = new Symbol(string.Format("{0}.thB", name)); - xC = new Symbol($"{name}.xC"); - yC = new Symbol($"{name}.yC"); + xC = new Symbol(string.Format("{0}.xC", name)); + yC = new Symbol(string.Format("{0}.yC", name)); - vxC = new Symbol($"{name}.vxC"); - vyC = new Symbol($"{name}.vyC"); + vxC = new Symbol(string.Format("{0}.vxC", name)); + vyC = new Symbol(string.Format("{0}.vyC", name)); - vC = new Symbol($"{name}.vC"); - thC = new Symbol($"{name}.thC"); + vC = new Symbol(string.Format("{0}.vC", name)); + thC = new Symbol(string.Format("{0}.thC", name)); - tAB = new Symbol($"{name}.tAB"); - tBC = new Symbol($"{name}.tBC"); - tAC = new Symbol($"{name}.tAC"); + tAB = new Symbol(string.Format("{0}.tAB", name)); + tBC = new Symbol(string.Format("{0}.tBC", name)); + tAC = new Symbol(string.Format("{0}.tAC", name)); - ax = new Symbol($"{name}.ax"); - ay = new Symbol($"{name}.ay"); + ax = new Symbol(string.Format("{0}.ax", name)); + ay = new Symbol(string.Format("{0}.ay", name)); } - public And EquationsAB() => - + public And EquationsAB() { + return new And( vxB == vxA + ax * tAB, @@ -371,9 +371,10 @@ public And EquationsAB() => yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2 ); + } - public And EquationsBC() => - + public And EquationsBC() { + return new And( vxC == vxB + ax * tBC, @@ -383,9 +384,10 @@ public And EquationsBC() => yC == yB + vyB * tBC + ay * (tBC ^ 2) / 2 ); + } - public And EquationsAC() => - + public And EquationsAC() { + return new And( vxC == vxA + ax * tAC, @@ -395,19 +397,21 @@ public And EquationsAC() => yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2 ); + } - public And TrigEquationsA() => - + public And TrigEquationsA() { + return new And( vxA == vA * cos(thA), vyA == vA * sin(thA) ); + } } - class Program + class Program : Function { static void AssertEqual(DoubleFloat a, DoubleFloat b, double tolerance = 0.00000001) { @@ -426,17 +430,21 @@ static void AssertEqual(MathObject a, Double b, double tolerance = 0.00000001) static void Assert(bool val, string str) { if (!val) Console.WriteLine(str); } - static And Kinematic(Symbol s, Symbol u, Symbol v, Symbol a, Symbol t) => + static And Kinematic(Symbol s, Symbol u, Symbol v, Symbol a, Symbol t) { + return new And( v == u + a * t, s == (u + v) * t / 2 ); + } - static And Kinematic(Symbol sA, Symbol sB, Symbol vA, Symbol vB, Symbol a, Symbol tA, Symbol tB) => + static And Kinematic(Symbol sA, Symbol sB, Symbol vA, Symbol vB, Symbol a, Symbol tA, Symbol tB) { + return new And( vB == vA + a * (tB - tA), sB - sA == (vA + vB) * (tB - tA) / 2); - + } + static void Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; @@ -646,7 +654,7 @@ static void Main(string[] args) Action AssertToStringMatch = - (MathObject obj, string str) => Assert(obj.ToString() == str, $"({str}).ToString()"); + (MathObject obj, string str) => Assert(obj.ToString() == str, string.Format("({0}).ToString()", str)); MathObject.ToStringForm = MathObject.ToStringForms.Full;