public static void RegisterTheorems(ILibrary library)
        {
            Analysis.DerivativeTransformation.Provider.Add(
                new Analysis.DerivativeTransformation(_entityId,
                                                      delegate(Port port, SignalSet manipulatedInputs, Signal variable, bool hasManipulatedInputs)
            {
                ReadOnlySignalSet tangents = StdBuilder.Tangent(port.InputSignals);
                SignalSet outputs          = new SignalSet();
                for (int i = 0; i < manipulatedInputs.Count; i++)
                {
                    outputs.Add(Std.Multiply(port.OutputSignals[i], tangents[i], manipulatedInputs[i]));
                }
                return(outputs);
            }));

            MathIdentifier   typeId = new MathIdentifier("TrigonometricSubstitute", "Std");
            ITheoremProvider basicProvider;

            if (!library.TryLookupTheoremType(typeId, out basicProvider))
            {
                basicProvider = Binder.GetInstance <ITransformationTheoremProvider, MathIdentifier>(typeId);
                library.AddTheoremType(basicProvider);
            }
            ((ITransformationTheoremProvider)basicProvider).Add(
                new BasicTransformation(_entityId.DerivePostfix("TrigonometricSubstitute"), typeId,
                                        delegate() { return(new Pattern(new EntityCondition(_entityId))); },
                                        delegate(Port port) { return(ManipulationPlan.DoAlter); },
                                        delegate(Port port, SignalSet transformedInputs, bool hasTransformedInputs)
            {
                return(StdBuilder.Invert(StdBuilder.Cosine(transformedInputs)));
                //Signal[] ret = new Signal[transformedInputs.Length];
                //for(int i = 0; i < ret.Length; i++)
                //    ret[i] = StdBuilder.Invert(StdBuilder.Cosine(port.Context, transformedInputs[i]));
                //return ret;
            }));
        }
        public void StdPolynomial_SingleVariable()
        {
            Signal x = Binder.CreateSignal();

            Signal a0 = IntegerValue.ConstantZero;
            Signal a1 = IntegerValue.ConstantOne;
            Signal a2 = RationalValue.ConstantHalf;
            Signal a3 = IntegerValue.Constant(2);
            Signal a4 = IntegerValue.Constant(3);

            Signal badX  = StdBuilder.Sine(x);
            Signal badA2 = StdBuilder.Tangent(a2);
            Signal badA3 = RealValue.ConstantPI;

            Signal x2 = StdBuilder.Power(x, a3);
            Signal x3 = StdBuilder.Power(x, a4);

            Signal a3x3 = a3 * x3;
            Signal a2x2 = a2 * x2;

            Assert.IsTrue(Polynomial.IsMonomial(x, x), "x: is SVM(x)");
            Assert.IsTrue(Polynomial.IsMonomial(a0, x), "0: is SVM(x)");
            Assert.IsTrue(Polynomial.IsMonomial(a2, x), "1/2: is SVM(x)");
            Assert.IsFalse(Polynomial.IsMonomial(badX, x), "sin(x): is not SVM(x)");
            Assert.IsFalse(Polynomial.IsMonomial(badA2, x), "tan(1/2): is not SVM(x)");
            Assert.IsFalse(Polynomial.IsMonomial(badA3, x), "pi is not SVM(x)");
            Assert.IsTrue(Polynomial.IsMonomial(x3, x), "x^3: is SVM(x)");
            Assert.IsTrue(Polynomial.IsMonomial(a2x2, x), "1/2*x^2: is SVM(x)");

            Assert.AreEqual("Std.Integer(1)", Polynomial.MonomialDegree(x, x).ToString(), "x: SVM deg(x)=1");
            Assert.AreEqual("Std.Integer(0)", Polynomial.MonomialDegree(a2, x).ToString(), "1/2: SVM deg(x)=0");
            Assert.AreEqual("Std.NegativeInfinity", Polynomial.MonomialDegree(a0, x).ToString(), "0: SVM deg(x)=-inf");
            Assert.AreEqual("Std.Integer(3)", Polynomial.MonomialDegree(x3, x).ToString(), "x^3: SVM deg(x)=3");
            Assert.AreEqual("Std.Integer(2)", Polynomial.MonomialDegree(a2x2, x).ToString(), "1/2*x^2: SVM deg(x)=2");

            IValueStructure vs;
            Signal          test = Polynomial.MonomialCoefficient(x, x, out vs);

            Assert.AreEqual("Std.Integer(1)", vs.ToString(), "x: SVM coeff deg=1 ");
            Assert.IsTrue(test.Value.Equals(a1.Value), "x: SVM coeff = 1");

            test = Polynomial.MonomialCoefficient(a2, x, out vs);
            Assert.AreEqual("Std.Integer(0)", vs.ToString(), "1/2: SVM coeff deg=0 ");
            Assert.IsTrue(test.Value.Equals(a2.Value), "1/2: SVM coeff = 1/2");

            test = Polynomial.MonomialCoefficient(a3x3, x, out vs);
            Assert.AreEqual("Std.Integer(3)", vs.ToString(), "2*x^3: SVM coeff deg=3 ");
            Assert.IsTrue(test.Value.Equals(a3.Value), "2*x^3: SVM coeff = 2");

            Signal a3x3_a2x2_a4 = StdBuilder.Add(a3x3, a2x2, a4);

            Assert.IsFalse(Polynomial.IsMonomial(a3x3_a2x2_a4, x), "2*x^3+1/2*x^2+3: is not SVM(x)");
            Assert.IsTrue(Polynomial.IsPolynomial(a3x3_a2x2_a4, x), "2*x^3+1/2*x^2+3: is SVP(x)");
            Assert.AreEqual("Std.Integer(3)", Polynomial.PolynomialDegree(a3x3_a2x2_a4, x).ToString(), "2*x^3+1/2*x^2+3: SVP deg(x)=3");

            test = Polynomial.PolynomialCoefficient(a3x3_a2x2_a4, x, 1);
            Assert.IsTrue(test.Value.Equals(a0.Value), "2*x^3+1/2*x^2+3: SVP coeff(1) = 0");

            test = Polynomial.PolynomialCoefficient(a3x3_a2x2_a4, x, 2);
            Assert.IsTrue(test.Value.Equals(a2.Value), "2*x^3+1/2*x^2+3: SVP coeff(2) = 1/2");

            Signal[] coefficients = Polynomial.PolynomialCoefficients(a3x3_a2x2_a4, x);
            Assert.AreEqual(4, coefficients.Length, "2*x^3+1/2*x^2+3: SVP coeffs: len(coeffs) = 4 (-> deg=3)");
            Assert.IsTrue(coefficients[0].Value.Equals(a4.Value), "2*x^3+1/2*x^2+3: SVP coeffs: coeffs[0] = 3");
            Assert.IsTrue(coefficients[1].Value.Equals(a0.Value), "2*x^3+1/2*x^2+3: SVP coeffs: coeffs[1] = 0");
            Assert.IsTrue(coefficients[2].Value.Equals(a2.Value), "2*x^3+1/2*x^2+3: SVP coeffs: coeffs[2] = 1/2");
            Assert.IsTrue(coefficients[3].Value.Equals(a3.Value), "2*x^3+1/2*x^2+3: SVP coeffs: coeffs[3] = 2");
        }