/// <summary>Computes the undual of <paramref name="A"/> with respect to the whole space. The /// space has the dimension specified by the metric <paramref name="M"/>.</summary> /// <param name="M">The metric to be used</param> /// <returns>dual of <param name="A"/></returns> public static Multivector Undual(Multivector A, Metric M) { Multivector I = Multivector.GetPseudoscalar(M.EigenMetric.Length); return ip(A, I, M, BasisBlade.InnerProductType.LEFT_CONTRACTION); }
/// <summary> /// Computes versor inverse of <paramref name="A"/>. /// </summary> /// <param name="A">Multivector to be inverted.</param> /// <param name="M">The metric to be used for the inverse.</param> /// <returns>Inverse of versor <paramref name="A"/></returns> /// <remarks>Computed using the versor inverse method, so <paramref name="A"/>must be a versor or a blade.</remarks> public static Multivector VersorInverse(Multivector A, Metric M) { Multivector R = A.Reverse(); Multivector s = scp(A, R, M); return VersorInverseInternal(R, s); }
/// <summary> /// Computes the scalar product of two multivectors in arbitary non-Euclidean metric. /// </summary> /// <param name="A">input Multivector</param> /// <param name="B">input Multivector</param> /// <param name="M">metric to be used</param> public static Multivector ScalarProduct(Multivector A, Multivector B, Metric M) { return InnerProduct(A, B, M, BasisBlade.InnerProductType.SCALAR_PRODUCT).ScalarPart(); }
/// <summary>Shortcut to ScalarProduct() </summary> public static Multivector scp(Multivector A, Multivector B, Metric M) { return ScalarProduct(A, B, M); }
/// <summary>Shortcut to ScalarProduct() </summary> public static ArrayList scp(BasisBlade A, BasisBlade B, Metric M) { return ScalarProduct(A, B, M); }
/// <summary>Computes the `reverse norm' of this multivector (this.reverse(this)) given a specific metric <paramref name="M"/></paramref>.</summary> /// <param name="M">The metric to be used in the inner product.</param> /// <returns>`reverse norm' of this Multivector in specified metric 'M' (can be negative)</returns> /// <remarks>The reverse norm is s*sqrt(s * this.reverse(this)), where 's' is either +1 or -1, /// such that the square root is always performed on a number >= 0.</remarks> public Multivector Norm_r(Metric M) { //M.IsPositiveDefinite return Norm(Multivector.scp(this, Reverse(), M), M.IsPositiveDefinite()); }
/// <summary> /// Computes the geometric product of two basis blades in arbitary non-Euclidean metric. /// </summary> /// <param name="A">Multivector input (LHS)</param> /// <param name="B">Multivector input (RHS)</param> /// <param name="M">Metric to be used</param> /// <returns>geometric product of <paramref name="A"/> and <paramref name="B"/></returns> public static Multivector GeometricProduct(Multivector A, Multivector B, Metric M) { ArrayList L = new ArrayList(); foreach (BasisBlade a in A.BasisBlades) foreach (BasisBlade b in B.BasisBlades) { L.AddRange(BasisBlade.GeometricProduct(a, b, M)); } return new Multivector(BasisBlade.Simplify(L)); }
/// <summary>Shortcut to InnerProduct() </summary> public static ArrayList ip(BasisBlade A, BasisBlade B, Metric M, InnerProductType type) { return InnerProduct(A, B, M, type); }
/// <summary> /// Computes versor inverse of this. /// </summary> /// <param name="M">The metric to be used for the inverse</param> /// <returns>Inverse of this versor</returns> /// <remarks>Computed using the versor inverse method, so <paramref name="A"/>must be a versor or a blade.</remarks> public Multivector VersorInverse(Metric M) { return VersorInverse(this, M); }
/// <summary>Computes the dual of <paramref name="A"/> with respect to the whole space. The /// space has the dimension specified by the metric <paramref name="M"/>.</summary> /// <param name="M">The metric to be used</param> /// <returns>dual of <param name="A"/></returns> public static Multivector Dual(Multivector A, Metric M) { Multivector Ii = Multivector.GetPseudoscalar(M.EigenMetric.Length).VersorInverse(M); return ip(A, Ii, M, BasisBlade.InnerProductType.LEFT_CONTRACTION); }
/// <summary>Computes unit version of this multivector using Reverse norm.</summary> /// <returns>normalized Multivector, according to specific metric/norm</returns> /// <remarks>Throws exception when norm is 0. /// If the norm is negative, the norm of the returned Multivector will be -1</remarks> public Multivector Unit_r(Metric M) { return Unit(Norm_r(M)); }
/// <summary>Computes the undual of <paramref name="A"/> with respect to the whole space. The /// space has the dimension specified by the metric <paramref name="M"/>.</summary> /// <param name="M">The metric to be used</param> /// <returns>dual of this</returns> public Multivector Undual(Metric M) { return Multivector.Undual(this, M); }
/// <summary>Computes the squared `reverse norm' of this multivector (this.reverse(this)) given a specific metric <paramref name="m"/></paramref>.</summary> /// <param name="M">The metric to be used in the inner product.</param> /// <returns>squared `reverse norm' of this Multivector in specified metric 'm' (can be negative).</returns> public Multivector Norm_r2(Metric M) { return Multivector.scp(this, Reverse(), M); }
/// <summary>Computes the geometric product of two basis blades in arbitary non-Euclidean metric.</summary> /// <param name="_A">Basisblade</param> /// <param name="_B">Basisblade</param> /// <param name="M">Metric to be used</param> /// <returns>An ArrayList, because the result may not be a single BasisBlade anymore. For example, /// <c>no ni = no.ni + no^ni = -1 + no^ni</c>. </returns> public static ArrayList GeometricProduct(BasisBlade _A, BasisBlade _B, Metric M) { // convert arguments to 'eigenbasis' ArrayList A = M.ToEigenbasis(_A); ArrayList B = M.ToEigenbasis(_B); ArrayList result = new ArrayList(); double[] EM = M.EigenMetric; foreach (BasisBlade bA in A) foreach (BasisBlade bB in B) { BasisBlade C = GeometricProduct(bA, bB, EM); if (C.scale != 0.0) result.Add(C); } return M.ToMetricBasis(result); }
/// <summary>Shortcut to GeometricProduct() </summary> public static Multivector gp(Multivector A, Multivector B, Metric M) { return GeometricProduct(A, B, M); }
/// <summary> /// Computes the inner product of two basis blades in Euclidean metric. /// </summary> /// <param name="A">input blade</param> /// <param name="B">input blade</param> /// <param name="M">The Metric to be used.</param> /// <param name="type">inner product type to be used. Use one of the InnerProductType constants: /// LEFT_CONTRACTION, RIGHT_CONTRACTION, HESTENES_INNER_PRODUCT, MODIFIED_HESTENES_INNER_PRODUCT or SCALAR_PRODUCT.</param> /// <returns>Inner product of <paramref name="A"/> and <paramref name="B"/>.</returns> public static ArrayList InnerProduct(BasisBlade A, BasisBlade B, Metric M, InnerProductType type) { return InnerProductFilter(A.Grade(), B.Grade(), GeometricProduct(A, B, M), type); }
/// <summary> /// Computes the inner product of two multivectors in arbitary non-Euclidean metric. /// </summary> /// <param name="A">input Multivector</param> /// <param name="B">input Multivector</param> /// <param name="M">metric to be used</param> /// <param name="type">inner product type to be used</param> /// <returns>Inner product of <paramref name="A"/> and <paramref name="B"/></returns> public static Multivector InnerProduct(Multivector A, Multivector B, Metric M, BasisBlade.InnerProductType type) { ArrayList L = new ArrayList(); foreach (BasisBlade a in A.BasisBlades) foreach (BasisBlade b in B.BasisBlades) { L.AddRange(BasisBlade.InnerProduct(a, b, M, type)); } return new Multivector(BasisBlade.Simplify(L)); }
/// <summary> /// Computes the inner product of two basis blades in arbitary non-Euclidean metric. /// </summary> /// <param name="A">input blade</param> /// <param name="B">input blade</param> /// <param name="M">The Metric to be used</param> /// <returns>Scalar product of <paramref name="A"/> and <paramref name="B"/>.</returns> public static ArrayList ScalarProduct(BasisBlade A, BasisBlade B, Metric M) { InnerProductType type = InnerProductType.SCALAR_PRODUCT; return InnerProductFilter(A.Grade(), B.Grade(), GeometricProduct(A, B, M), type); }
/// <summary>Shortcut to InnerProduct() </summary> public static Multivector ip(Multivector A, Multivector B, Metric M, BasisBlade.InnerProductType type) { return InnerProduct(A, B, M, type); }
static void Main(string[] args) { System.Console.WriteLine("Hello world"); { ArrayList AL = new ArrayList(); AL.Add(new BasisBlade(1, 1.0, "a1")); AL.Add(new BasisBlade(2, 1.0, "a2")); Multivector A = new Multivector(AL); System.Console.WriteLine("A = " + A.ToString()); ArrayList BL = new ArrayList(); BL.Add(new BasisBlade(2, 1.0, "b1")); BL.Add(new BasisBlade(3, 1.0, "b2")); Multivector B = new Multivector(BL); System.Console.WriteLine("B = " + B.ToString()); Multivector AB = Multivector.gp(A, B); System.Console.WriteLine("AB = " + AB.ToString()); Symbolic.HashtableSymbolicEvaluator HSE = new Symbolic.HashtableSymbolicEvaluator(); HSE.Add("a1", 3.0); HSE.Add("a2", -2.0); HSE.Add("b1", 4.0); HSE.Add("b2", 1.0); Multivector ABeval = AB.SymbolicEval(HSE); System.Console.WriteLine("ABeval = " + ABeval.ToString()); return; } Metric M; try { // Conformal metric (no, e1, e2, e3, ni) /* int N = 5; double[] EVM = new double[]{ -0.707107, -0.707107, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, -0.707107, 0.707107, 0, 0, 0}; double[] EV = new double[] { -1.0, 1.0, 1.0, 1.0, 1.0 };*/ /*// Euclidean metric (e1, e2, e3) double[] m = new double[]{ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};*/ // Conformal metric (no, e1, e2, e3, ni) double[] m = new double[]{ 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0}; M = new Metric(m); } catch (Exception E) { System.Console.WriteLine(E.ToString()); return; } /*{ ArrayList AL = new ArrayList(); AL.Add(new BasisBlade(1 << 3)); // e1 Multivector A = new Multivector(AL); ArrayList BL = new ArrayList(); BL.Add(new BasisBlade(1 << 3)); // e1 Multivector B = new Multivector(BL); Multivector V = Multivector.InnerProduct(A, B, M, BasisBlade.InnerProductType.LEFT_CONTRACTION); System.Console.WriteLine("A = " + A.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("B = " + B.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("A . B = " + V.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); }*/ /* ArrayList AL = new ArrayList(); // AL.Add(new BasisBlade(2 + 16, 1.0, "a_e1ni")); // AL.Add(new BasisBlade(4 + 16, 1.0, "a_e2ni")); // AL.Add(new BasisBlade(8 + 16, 1.0, "a_e3ni")); // AL.Add(new BasisBlade(2 + 4, 1.0, "a_e1e2")); // AL.Add(new BasisBlade(4 + 8, 1.0, "a_e2e3")); // AL.Add(new BasisBlade(8 + 2, 1.0, "a_e1e3")); // AL.Add(new BasisBlade(1 + 16, 1.0, "a_noni")); AL.Add(new BasisBlade(2 + 16, 1.0)); AL.Add(new BasisBlade(4 + 16, 2.0)); AL.Add(new BasisBlade(8 + 16, 3.0)); AL.Add(new BasisBlade(2 + 4, 4.0)); AL.Add(new BasisBlade(4 + 8, 5.0)); AL.Add(new BasisBlade(8 + 2, 6.0)); Multivector A = new Multivector(AL); Multivector Aexp = A.Exp(M, false, 0.0); System.Console.WriteLine("A = " + A.ToString(new string[] { "no", "e1", "e2", "e3", "ni" }) + ","); System.Console.WriteLine("expA = " + Aexp.ToString(new string[] { "no", "e1", "e2", "e3", "ni" }) + ",");*/ // Symbolic.HashtableSymbolicEvaluator HSE = new Symbolic.HashtableSymbolicEvaluator(); // HSE.Add("a_e1ni", 1.0); // HSE.Add("a_e2ni", 2.0); // HSE.Add("a_e3ni", 3.0); // HSE.Add("a_e1e2", 4.0); // HSE.Add("a_e2e3", 5.0); // HSE.Add("a_e1e3", 6.0); // HSE.Add("a_noni", 6.0); // System.Console.WriteLine("A = " + A.SymbolicEval(HSE).ToString(new string[] { "no", "e1", "e2", "e3", "ni" }) + ","); // System.Console.WriteLine("expA = " + Aexp.SymbolicEval(HSE).ToString(new string[] { "no", "e1", "e2", "e3", "ni" }) + ","); /* // compute square Multivector A2 = Multivector.gp(A, A, M); System.Console.WriteLine("A2 = " + A2.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); // evaluate with random coords Symbolic.RandomSymbolicEvaluator RSE = new Symbolic.RandomSymbolicEvaluator(-100.0, 100.0); int pos = 0, neg = 0, zero = 0; for (int i = 0; i < 1; i++) { Multivector MV = A2.SymbolicEval(RSE); double val = MV.RealScalarPart(); System.Console.WriteLine("MV = " + MV); System.Console.WriteLine("val = " + val); if (val > 1e-7) pos++; else if (val < -1e-7) neg++; else zero++; RSE.reset(); } System.Console.WriteLine("pos = " + pos); System.Console.WriteLine("neg = " + neg); System.Console.WriteLine("zero = " + zero);*/ /* ArrayList AL = new ArrayList(); AL.Add(new BasisBlade(1 << 0, 1.0, "a_e1")); AL.Add(new BasisBlade(1 << 1, 1.0, "a_e2")); AL.Add(new BasisBlade(1 << 2, 1.0, "a_e3")); Multivector A = new Multivector(AL); ArrayList BL = new ArrayList(); BL.Add(new BasisBlade(1 << 0, 1.0, "b_e1")); BL.Add(new BasisBlade(1 << 1, 1.0, "b_e2")); BL.Add(new BasisBlade(1 << 2, 1.0, "b_e3")); Multivector B = new Multivector(BL); System.Console.WriteLine("A = " + A.ToString()); System.Console.WriteLine("B = " + B.ToString()); System.Console.WriteLine("A B = " + Multivector.gp(A, B).ToString()); */ /* BasisBlade Z = new BasisBlade(1 << 0, 1.0, new Object[][] { new Object[] { "blah", "aaaarg", 3.0, 2.0, 1 }, new Object[] { "bloooey", 'x', "crap", true, false}, new Object[] { "blah", "aaaarg", -10.0, 1 } }); System.Console.WriteLine("Z = " + Z.ToString()); return;*/ // OK: now check for harder objects . . . /* Symbolic.HashtableSymbolicEvaluator HSE = new Symbolic.HashtableSymbolicEvaluator(); HSE.Add("a_e1", 1.0); HSE.Add("a_e2", 2.0); HSE.Add("a_e3", 3.0); //Symbolic.RandomSymbolicEvaluator HSE = new Symbolic.RandomSymbolicEvaluator(-100.0, 100.0); ArrayList AL = new ArrayList(); //AL.Add(new BasisBlade(1 << 0, 1.0, "a_no")); AL.Add(new BasisBlade(1 << 1, 1.0, "a_e1")); AL.Add(new BasisBlade(1 << 2, 1.0, "a_e2")); AL.Add(new BasisBlade(1 << 3, 1.0, "a_e3")); AL.Add(new BasisBlade(1 << 4, 1.0, "a_e1")); Multivector A = new Multivector(AL); A = Multivector.gp(A, Symbolic.ScalarOp.Exp(new Multivector(new BasisBlade(0, 1.0, "a_e2")))); System.Console.WriteLine("A = " + A.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); // todo: check if exp, etc is working, then check why not collapse (by Multivector simplify, basis blade simplify) to single scalar value . . Multivector Ae = A.SymbolicEval(HSE); System.Console.WriteLine("Ae = " + Ae.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); return; ArrayList BL = new ArrayList(); // BL.Add(new BasisBlade(1 << 0, 1.0));//, "b_no")); BL.Add(new BasisBlade(1 << 1, -2.0));//, "b_e1")); BL.Add(new BasisBlade(1 << 2, 3.0));//, "b_e2")); BL.Add(new BasisBlade(1 << 3, -4.0));//, "b_e3")); // BL.Add(new BasisBlade(1 << 4, 1.0));//, "b_ni")); Multivector B = new Multivector(BL); A = Multivector.op(A, B); B = Multivector.gp(A, A); System.Console.WriteLine("A = " + A.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("B = " + B.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); // how to know whether outcome of symbolic computation is positive, negative or zero??? // simply fill in values for random variables? //Multivector unitA = A.Unit_r(M); //System.Console.WriteLine("unitA = " + unitA.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); */ /* Multivector ApAgB = Multivector.Add(Multivector.Add(A, Multivector.gp(A, B, M)), Multivector.gp(Multivector.GetPseudoscalar(4), 0.01)); // still testing . . . System.Console.WriteLine("ApAgB = " + ApAgB.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); int g = ApAgB.LargestGradePartIndex(); System.Console.WriteLine("Largest grade part = " + g); System.Console.WriteLine("Largest grade part = " + ApAgB.ExtractGrade(g).ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("Top grade part = " + ApAgB.TopGradePartIndex(0.02));*/ /* BasisBlade se1 = new BasisBlade(1 << 1, 1.0, "ae1"); BasisBlade se2 = new BasisBlade(1 << 2, 1.0, "ae2"); BasisBlade X = BasisBlade.op(se1, se2); System.Console.WriteLine("se1 = " + se1); System.Console.WriteLine("se2 = " + se2); System.Console.WriteLine("X = " + X); */ /* Multivector no = new Multivector(new BasisBlade(1, 1.0)); Multivector ni = new Multivector(new BasisBlade(1 << 4, 1.0)); Multivector noni = Multivector.GeometricProduct(no, ni, M); System.Console.WriteLine("no = " + no.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("ni = " + ni.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("noni = " + noni.ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("noni2 = " + noni.ExtractGrade(2).ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("dual(noni) = " + noni.Dual(M).ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); System.Console.WriteLine("dual(I) = " + Multivector.GetPseudoscalar(5).Dual(M).ToString(new string[] { "no", "e1", "e2", "e3", "ni" })); */ /*BasisBlade no = new BasisBlade(1); BasisBlade ni = new BasisBlade(1 << 4); System.Console.WriteLine("no = " + no); System.Console.WriteLine("ni = " + ni); System.Collections.ArrayList L = BasisBlade.GeometricProduct(ni, no, M); System.Console.WriteLine("L = " + BasisBlade.ToString(L, new string[] {"no", "e1", "e2", "e3", "ni"})); */ /* BasisBlade A = new BasisBlade(1 | 4, 2.0); BasisBlade B = new BasisBlade(2, 2.0); BasisBlade C = new BasisBlade(1 | 4, 3.0); BasisBlade D =new BasisBlade(1, 1.0); System.Collections.ArrayList L = new System.Collections.ArrayList(); L.Add(A); L.Add(B); L.Add(C); L.Add(D); L.Add(new BasisBlade(2 | 4, 2.0)); System.Console.WriteLine("Before: "); foreach (BasisBlade BB in L) { System.Console.WriteLine(BB.ToString()); } L = BasisBlade.Simplify(L); System.Console.WriteLine("After: "); foreach (BasisBlade BB in L) { System.Console.WriteLine(BB.ToString()); } */ // System.Console.WriteLine("A = " + A); // System.Console.WriteLine("B = " + B); // .ToString(new string[] { "no", "e1", "ni" }) // System.Console.WriteLine("A ^ B = " + (A ^ B)); /* try { double[][] MA = new double[][]{ new double[]{0.0, 0.0, 0.0, 0.0, -1.0}, new double[]{0.0, 1.0, 0.0, 0.0, 0.0}, new double[]{0.0, 0.0, 1.0, 0.0, 0.0}, new double[]{0.0, 0.0, 0.0, 1.0, 0.0}, new double[]{-1.0, 0.0, 0.0, 0.0, 0.0}}; new Metric(MA); } catch (Exception E) { System.Console.WriteLine(E.ToString()); }*/ /* double[] A = new double[]{ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; int nbRows = 3; int nbColumns = 3; bool columnWise = false; dnAnalytics.LinearAlgebra.Matrix M = dnAnalytics.LinearAlgebra.MatrixBuilder.CreateMatrix(A, nbRows, nbColumns, columnWise); System.Console.WriteLine("Hi hoi!" + M); */ }
/// <summary>Computes the dual of <paramref name="A"/> with respect to the whole space. The /// space has the dimension specified by the metric <paramref name="M"/>.</summary> /// <param name="M">The metric to be used</param> /// <returns>dual of this</returns> public Multivector Dual(Metric M) { return Multivector.Dual(this, M); }