├── .gitignore ├── License.txt ├── lib ├── MathNet.Iridium │ ├── MathNet.Iridium.License.txt │ ├── MathNet.Iridium.dll │ ├── de │ │ └── MathNet.Iridium.resources.dll │ ├── es │ │ └── MathNet.Iridium.resources.dll │ └── fr │ │ └── MathNet.Iridium.resources.dll └── NUnit │ ├── nunit.framework.dll │ └── nunit.framework.extensions.dll └── src ├── MathNet.Palladium.sln ├── app └── MathNet.Palladium │ ├── Arithmeric.cs │ ├── AutoSimplify.cs │ ├── Elementary.cs │ ├── Exponential.cs │ ├── ExpressionBuilder.cs │ ├── MathNet.Palladium.csproj │ ├── Ordering.cs │ ├── Output │ └── MathMLContentMarkupFormatter.cs │ ├── PartialDerivative.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Settings.StyleCop │ ├── Trigonometry.cs │ ├── TypeInference.cs │ └── Visitors │ ├── AlgebraicFold.cs │ ├── AlgebraicFoldLambda.cs │ ├── AlgebraicManipulator.cs │ ├── AlgebraicVisitor.cs │ └── ExpressionManipulator.cs └── test └── MathNet.Palladium.Test ├── DifferentiationTests.cs ├── ExpressionAlgebraElementaryTests.cs ├── ExpressionAlgebraSimplifyTests.cs ├── LinqExpressionTests.cs ├── MathMLContentMarkupFormatterTests.cs ├── MathNet.Palladium.Test.csproj ├── OrderingTests.cs └── Properties └── AssemblyInfo.cs /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | *.Cache 4 | bin 5 | obj 6 | .svn 7 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/License.txt -------------------------------------------------------------------------------- /lib/MathNet.Iridium/MathNet.Iridium.License.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/MathNet.Iridium/MathNet.Iridium.License.txt -------------------------------------------------------------------------------- /lib/MathNet.Iridium/MathNet.Iridium.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/MathNet.Iridium/MathNet.Iridium.dll -------------------------------------------------------------------------------- /lib/MathNet.Iridium/de/MathNet.Iridium.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/MathNet.Iridium/de/MathNet.Iridium.resources.dll -------------------------------------------------------------------------------- /lib/MathNet.Iridium/es/MathNet.Iridium.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/MathNet.Iridium/es/MathNet.Iridium.resources.dll -------------------------------------------------------------------------------- /lib/MathNet.Iridium/fr/MathNet.Iridium.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/MathNet.Iridium/fr/MathNet.Iridium.resources.dll -------------------------------------------------------------------------------- /lib/NUnit/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/NUnit/nunit.framework.dll -------------------------------------------------------------------------------- /lib/NUnit/nunit.framework.extensions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathnet/mathnet-linqalgebra/4f8875a4e272c5c488afee7def115c1480e9eb56/lib/NUnit/nunit.framework.extensions.dll -------------------------------------------------------------------------------- /src/MathNet.Palladium.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MathNet.Palladium", "app\MathNet.Palladium\MathNet.Palladium.csproj", "{96F70E7A-18FD-4A26-B833-797791DC761A}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MathNet.Palladium.Test", "test\MathNet.Palladium.Test\MathNet.Palladium.Test.csproj", "{AD594119-58D0-4BF2-921C-6EC1A5BD67A1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {96F70E7A-18FD-4A26-B833-797791DC761A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {96F70E7A-18FD-4A26-B833-797791DC761A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {96F70E7A-18FD-4A26-B833-797791DC761A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {96F70E7A-18FD-4A26-B833-797791DC761A}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {AD594119-58D0-4BF2-921C-6EC1A5BD67A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {AD594119-58D0-4BF2-921C-6EC1A5BD67A1}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {AD594119-58D0-4BF2-921C-6EC1A5BD67A1}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {AD594119-58D0-4BF2-921C-6EC1A5BD67A1}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Arithmeric.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System.Collections.Generic; 31 | using System.Linq; 32 | using System.Linq.Expressions; 33 | 34 | namespace MathNet.ExpressionAlgebra 35 | { 36 | /// 37 | /// Arithmetic Expression Builder 38 | /// 39 | public static class Arithmeric 40 | { 41 | public static Expression Zero() 42 | { 43 | return ExpressionBuilder.ConstantDouble(0d); 44 | } 45 | 46 | public static Expression One() 47 | { 48 | return ExpressionBuilder.ConstantDouble(1d); 49 | } 50 | 51 | public static Expression MinusOne() 52 | { 53 | return ExpressionBuilder.ConstantDouble(-1d); 54 | } 55 | 56 | public static Expression Add(params Expression[] terms) 57 | { 58 | TypeInference type = new TypeInference(terms); 59 | return type.CastToMaxNumeric() 60 | .Where(x => !Elementary.IsConstantZero(x)) 61 | .Reduce(Expression.Add, Zero()); 62 | } 63 | 64 | public static Expression Subtract(Expression a, Expression b) 65 | { 66 | if(Elementary.IsConstantZero(a)) 67 | { 68 | return Negate(b); 69 | } 70 | 71 | if(Elementary.IsConstantZero(b)) 72 | { 73 | return a; 74 | } 75 | 76 | TypeInference type = new TypeInference(a, b); 77 | List expressions = type.CastToMaxNumericList(); 78 | return Expression.Subtract(expressions[0], expressions[1]); 79 | } 80 | 81 | public static Expression Negate(Expression term) 82 | { 83 | if(Elementary.IsConstantZero(term)) 84 | { 85 | return Arithmeric.Zero(); 86 | } 87 | 88 | if(term.NodeType == ExpressionType.Negate) 89 | { 90 | UnaryExpression unary = (UnaryExpression)term; 91 | return unary.Operand; 92 | } 93 | 94 | return Expression.Negate(term); 95 | } 96 | 97 | public static Expression Multiply(params Expression[] terms) 98 | { 99 | TypeInference type = new TypeInference(terms); 100 | List factors = type.CastToMaxNumeric() 101 | .Where(x => !Elementary.IsConstantOne(x)) 102 | .ToList(); 103 | 104 | if(factors.Exists(Elementary.IsConstantZero)) 105 | { 106 | return Zero(); 107 | } 108 | 109 | return factors.Reduce(Expression.Multiply, One()); 110 | } 111 | 112 | public static Expression Divide(Expression a, Expression b) 113 | { 114 | if(Elementary.IsConstantZero(a)) 115 | { 116 | return Arithmeric.Zero(); 117 | } 118 | 119 | if(Elementary.IsConstantOne(b)) 120 | { 121 | return a; 122 | } 123 | 124 | TypeInference type = new TypeInference(a, b); 125 | List expressions = type.CastToMaxNumericList(); 126 | return Expression.Divide(expressions[0], expressions[1]); 127 | } 128 | 129 | public static Expression Invert(Expression term) 130 | { 131 | if(term.NodeType == ExpressionType.Divide) 132 | { 133 | BinaryExpression binary = (BinaryExpression)term; 134 | return Divide(binary.Right, binary.Left); 135 | } 136 | 137 | return Divide(Expression.Constant(1), term); 138 | } 139 | 140 | public static Expression Power(Expression a, Expression b) 141 | { 142 | // TODO: automatic simplification 143 | TypeInference type = new TypeInference(a, b); 144 | List expressions = type.CastToMaxNumericList(); 145 | return Expression.Power(expressions[0], expressions[1]); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/AutoSimplify.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System.Linq.Expressions; 31 | 32 | namespace MathNet.ExpressionAlgebra 33 | { 34 | /// 35 | /// Automatic Algebraic Expression Simplification. 36 | /// 37 | public static class AutoSimplify 38 | { 39 | /// 40 | /// Automatic factor simplification 41 | /// 42 | /// 43 | /// Ensures that the following rules are met (fixes term if needed): 44 | /// 45 | /// a * b: a is not a product, neither a nor b is a quotient. 46 | /// a / b: neither a nor b are quotients 47 | /// 48 | /// 49 | public static Expression SimplifyFactors(Expression term) 50 | { 51 | switch(term.NodeType) 52 | { 53 | case ExpressionType.Divide: 54 | return SimplifyQuotient((BinaryExpression)term); 55 | case ExpressionType.Multiply: 56 | return SimplifyProduct((BinaryExpression)term); 57 | default: 58 | return term; 59 | } 60 | } 61 | 62 | /// 63 | /// Ensures that for (a / b), neither a nor b are quotients. 64 | /// 65 | static Expression SimplifyQuotient(BinaryExpression quotient) 66 | { 67 | Expression nominator = SimplifyFactors(quotient.Left); 68 | Expression denominator = SimplifyFactors(quotient.Right); 69 | 70 | return SimpleQuotient(nominator, denominator, quotient); 71 | } 72 | 73 | static Expression SimpleQuotient(Expression nominator, Expression denominator, BinaryExpression quotient) 74 | { 75 | // ensure "nominator" is no quotient 76 | if(nominator.NodeType == ExpressionType.Divide) 77 | { 78 | BinaryExpression nominatorQuotient = (BinaryExpression)nominator; 79 | nominator = nominatorQuotient.Left; 80 | denominator = SimpleProduct(denominator, nominatorQuotient.Right, null); 81 | } 82 | 83 | // ensure "denominator" is no quotient 84 | if(denominator.NodeType == ExpressionType.Divide) 85 | { 86 | BinaryExpression denominatorQuotient = (BinaryExpression)denominator; 87 | nominator = SimpleProduct(nominator, denominatorQuotient.Right, null); 88 | denominator = denominatorQuotient.Left; 89 | } 90 | 91 | if((quotient == null) || (nominator != quotient.Left) || (denominator != quotient.Right)) 92 | { 93 | return Expression.Divide(nominator, denominator); 94 | } 95 | 96 | return quotient; 97 | } 98 | 99 | /// 100 | /// Ensures that for (a * b), neither a nor b is a quotient, and b is no product. 101 | /// 102 | static Expression SimplifyProduct(BinaryExpression product) 103 | { 104 | Expression left = SimplifyFactors(product.Left); 105 | Expression right = SimplifyFactors(product.Right); 106 | 107 | return SimpleProduct(left, right, product); 108 | } 109 | 110 | static Expression SimpleProduct(Expression left, Expression right, BinaryExpression product) 111 | { 112 | // ensure "left" is no quotient 113 | if(left.NodeType == ExpressionType.Divide) 114 | { 115 | BinaryExpression leftQuotient = (BinaryExpression)left; 116 | Expression nominator = SimpleProduct(right, leftQuotient.Left, null); 117 | return SimpleQuotient(nominator, leftQuotient.Right, null); 118 | } 119 | 120 | // ensure "right" is no quotient 121 | if(right.NodeType == ExpressionType.Divide) 122 | { 123 | BinaryExpression rightQuotient = (BinaryExpression)right; 124 | Expression nominator = SimpleProduct(left, rightQuotient.Left, null); 125 | return SimpleQuotient(nominator, rightQuotient.Right, null); 126 | } 127 | 128 | // ensure "right" is no product 129 | while(right.NodeType == ExpressionType.Multiply) 130 | { 131 | BinaryExpression rightProduct = (BinaryExpression)right; 132 | left = Expression.Multiply(left, rightProduct.Right); 133 | right = rightProduct.Left; 134 | } 135 | 136 | if((product == null) || (left != product.Left) || (right != product.Right)) 137 | { 138 | return Expression.Multiply(left, right); 139 | } 140 | 141 | return product; 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Elementary.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Linq.Expressions; 33 | 34 | namespace MathNet.ExpressionAlgebra 35 | { 36 | using MathNet.Numerics; 37 | 38 | public static class Elementary 39 | { 40 | public static bool IsConstantAlmost(Expression term, double expected) 41 | { 42 | if(term.NodeType == ExpressionType.Convert) 43 | { 44 | // TODO: do we need 'while' instead of 'if' here? 45 | UnaryExpression conv = (UnaryExpression)term; 46 | term = conv.Operand; 47 | } 48 | 49 | if(term.NodeType != ExpressionType.Constant) 50 | { 51 | return false; 52 | } 53 | 54 | ConstantExpression constExpr = (ConstantExpression)term; 55 | return Number.AlmostEqual(Convert.ToDouble(constExpr.Value), expected); 56 | } 57 | 58 | public static bool IsConstantOne(Expression term) 59 | { 60 | return IsConstantAlmost(term, 1d); 61 | } 62 | 63 | public static bool IsConstantZero(Expression term) 64 | { 65 | return IsConstantAlmost(term, 0d); 66 | } 67 | 68 | public static Expression Numerator(Expression quotient) 69 | { 70 | if(quotient.NodeType != ExpressionType.Divide) 71 | { 72 | return quotient; 73 | } 74 | 75 | BinaryExpression binary = quotient as BinaryExpression; 76 | if(binary == null) 77 | { 78 | ////return quotient; 79 | throw new Exception(String.Format("Expected a BinaryExpression, but was {0} instead.", quotient.Type.Name)); 80 | } 81 | 82 | return binary.Left; 83 | } 84 | 85 | public static Expression Denominator(Expression quotient) 86 | { 87 | if(quotient.NodeType != ExpressionType.Divide) 88 | { 89 | return Expression.Constant(1); 90 | } 91 | 92 | BinaryExpression binary = quotient as BinaryExpression; 93 | if(binary == null) 94 | { 95 | ////return Expression.Constant(1); 96 | throw new Exception(String.Format("Expected a BinaryExpression, but was {0} instead.", quotient.Type.Name)); 97 | } 98 | 99 | return binary.Right; 100 | } 101 | 102 | /// 103 | /// Collect all factors (including inverse factors in case of a quotient) of the provided term. 104 | /// This algorithm does not apply any factorization. 105 | /// 106 | public static List Factors(Expression product) 107 | { 108 | List list = new List(); 109 | CollectFactorsRecursive(product, list, false); 110 | return list; 111 | } 112 | 113 | static void CollectFactorsRecursive(Expression term, List factors, bool denominator) 114 | { 115 | if(term.NodeType == ExpressionType.Multiply) 116 | { 117 | BinaryExpression binary = (BinaryExpression)term; 118 | CollectFactorsRecursive(binary.Left, factors, denominator); 119 | CollectFactorsRecursive(binary.Right, factors, denominator); 120 | return; 121 | } 122 | 123 | if(term.NodeType == ExpressionType.Divide) 124 | { 125 | BinaryExpression binary = (BinaryExpression)term; 126 | CollectFactorsRecursive(binary.Left, factors, denominator); 127 | CollectFactorsRecursive(binary.Right, factors, !denominator); 128 | return; 129 | } 130 | 131 | if(denominator) 132 | { 133 | term = Expression.Divide(Expression.Constant(1d), term); 134 | } 135 | 136 | factors.Add(term); 137 | } 138 | 139 | public static bool DependsOn(Expression term, string parameterName) 140 | { 141 | return Visitors.AlgebraicFoldLambda.Create( 142 | (left, right) => left || right, 143 | parameter => parameter.Name.Equals(parameterName), 144 | constant => false)(term); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Exponential.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Linq.Expressions; 32 | using System.Reflection; 33 | 34 | namespace MathNet.ExpressionAlgebra 35 | { 36 | /// 37 | /// Describing an exponential function. 38 | /// 39 | public enum ExponentialFunction 40 | { 41 | Ln, 42 | Exp 43 | } 44 | 45 | /// 46 | /// Exponential Expression Builder 47 | /// 48 | public static class Exponential 49 | { 50 | static readonly Type _mathType = typeof(Math); 51 | 52 | public static Expression Apply(ExponentialFunction function, Expression argument) 53 | { 54 | switch(function) 55 | { 56 | case ExponentialFunction.Ln: 57 | return Ln(argument); 58 | case ExponentialFunction.Exp: 59 | return Exp(argument); 60 | default: 61 | return ExpressionBuilder.CallDouble(_mathType, function.ToString(), argument); 62 | } 63 | } 64 | 65 | public static bool TryParse(MethodInfo method, out ExponentialFunction function) 66 | { 67 | string name = method.Name; 68 | if(!Enum.IsDefined(typeof(ExponentialFunction), name)) 69 | { 70 | function = (ExponentialFunction)0; 71 | return false; 72 | } 73 | 74 | function = (ExponentialFunction)Enum.Parse(typeof(ExponentialFunction), name); 75 | return true; 76 | } 77 | 78 | /// 79 | /// Natural Logarithm 80 | /// 81 | public static Expression Ln(Expression term) 82 | { 83 | return ExpressionBuilder.CallDouble(_mathType.GetMethod("Log"), term); 84 | } 85 | 86 | /// 87 | /// Exponential 88 | /// 89 | public static Expression Exp(Expression term) 90 | { 91 | return ExpressionBuilder.CallDouble(_mathType.GetMethod("Exp"), term); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/ExpressionBuilder.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Linq.Expressions; 33 | using System.Reflection; 34 | 35 | namespace MathNet.ExpressionAlgebra 36 | { 37 | internal static class ExpressionBuilder 38 | { 39 | static readonly Type[] _oneDouble = new Type[] { typeof(double) }; 40 | static readonly Type[] _twoDoubles = new Type[] { typeof(double), typeof(double) }; 41 | 42 | public static Expression Reduce(this IEnumerable terms, Func map, Expression defaultIfEmpty) 43 | { 44 | Expression sum = null; 45 | foreach(Expression term in terms) 46 | { 47 | sum = (sum == null) ? term : map(sum, term); 48 | } 49 | 50 | return sum ?? defaultIfEmpty; 51 | } 52 | 53 | public static Expression ConstantDouble(double value) 54 | { 55 | return Expression.Constant(value, typeof(double)); 56 | } 57 | 58 | public static Expression ConvertDouble(Expression expression) 59 | { 60 | if(expression.Type != typeof(double)) 61 | { 62 | if(expression.NodeType == ExpressionType.Constant) 63 | { 64 | ConstantExpression constExpr = (ConstantExpression)expression; 65 | return ConstantDouble(Convert.ToDouble(constExpr.Value)); 66 | } 67 | 68 | return Expression.Convert(expression, typeof(double)); 69 | } 70 | 71 | return expression; 72 | } 73 | 74 | public static Expression CallDouble(MethodInfo method, Expression expression) 75 | { 76 | return Expression.Call(method, ConvertDouble(expression)); 77 | } 78 | 79 | public static Expression CallDouble(MethodInfo method, Expression a, Expression b) 80 | { 81 | return Expression.Call(method, ConvertDouble(a), ConvertDouble(b)); 82 | } 83 | 84 | public static Expression CallDouble(Type type, string methodName, Expression expression) 85 | { 86 | return Expression.Call(type.GetMethod(methodName, _oneDouble), ConvertDouble(expression)); 87 | } 88 | 89 | public static Expression CallDouble(Type type, string methodName, Expression a, Expression b) 90 | { 91 | return Expression.Call(type.GetMethod(methodName, _twoDoubles), ConvertDouble(a), ConvertDouble(b)); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/MathNet.Palladium.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {96F70E7A-18FD-4A26-B833-797791DC761A} 9 | Library 10 | Properties 11 | MathNet.ExpressionAlgebra 12 | MathNet.Palladium 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | False 36 | ..\..\..\lib\MathNet.Iridium\MathNet.Iridium.dll 37 | 38 | 39 | 40 | 3.5 41 | 42 | 43 | 3.5 44 | 45 | 46 | 3.5 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Ordering.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Linq.Expressions; 33 | 34 | namespace MathNet.ExpressionAlgebra 35 | { 36 | public class Ordering : IComparer 37 | { 38 | /// 39 | /// Compare two terms for ordering (i.e. "2*x", not "x*2"). 40 | /// 41 | /// 42 | /// Only the top expression node is analyzed, this method is therefore 43 | /// not intended (and can't be used) for comparing two expression trees for equality. 44 | /// 45 | public static int Compare(Expression x, Expression y) 46 | { 47 | // ordering by type 48 | int comparison = Assess(x) - Assess(y); 49 | if(comparison != 0) 50 | { 51 | return comparison; 52 | } 53 | 54 | // if same type, ordering by name (if it has a name) 55 | string nameX = NameOfExpression(x); 56 | string nameY = NameOfExpression(y); 57 | 58 | return string.Compare(nameX, nameY, StringComparison.Ordinal); 59 | } 60 | 61 | /// 62 | /// Returns a simple ordering priority score based on the term type. 63 | /// 64 | static int Assess(Expression term) 65 | { 66 | if(term == null) 67 | { 68 | throw new ArgumentNullException("term"); 69 | } 70 | 71 | ConstantExpression constExpr = term as ConstantExpression; 72 | if(constExpr != null) 73 | { 74 | if((constExpr.Type == typeof(int)) || (constExpr.Type == typeof(long))) 75 | { 76 | return 1; 77 | } 78 | 79 | if((constExpr.Type == typeof(double)) || (constExpr.Type == typeof(float))) 80 | { 81 | return 2; 82 | } 83 | 84 | return 3; 85 | } 86 | 87 | if(term is ParameterExpression) 88 | { 89 | return 10; 90 | } 91 | 92 | if(term is MethodCallExpression) 93 | { 94 | return 200; 95 | } 96 | 97 | BinaryExpression binaryExpr = term as BinaryExpression; 98 | if(binaryExpr != null) 99 | { 100 | switch(binaryExpr.NodeType) 101 | { 102 | case ExpressionType.Multiply: 103 | return 20; 104 | case ExpressionType.Add: 105 | case ExpressionType.Subtract: 106 | return 21; 107 | case ExpressionType.Divide: 108 | return 22; 109 | } 110 | } 111 | 112 | return 100; 113 | } 114 | 115 | /// 116 | /// Tries to find and return the term's name, if it is named (i.e. a parameter or a method call). 117 | /// 118 | static string NameOfExpression(Expression term) 119 | { 120 | ParameterExpression paramExpr = term as ParameterExpression; 121 | if(paramExpr != null) 122 | { 123 | return paramExpr.Name; 124 | } 125 | 126 | MethodCallExpression methodExpr = term as MethodCallExpression; 127 | if(methodExpr != null) 128 | { 129 | return methodExpr.Method.Name; 130 | } 131 | 132 | return null; 133 | } 134 | 135 | int IComparer.Compare(Expression x, Expression y) 136 | { 137 | return Compare(x, y); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Output/MathMLContentMarkupFormatter.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System.Linq.Expressions; 31 | using System.Xml.Linq; 32 | 33 | namespace MathNet.ExpressionAlgebra.Output 34 | { 35 | using MathNet.ExpressionAlgebra.Visitors; 36 | 37 | public class MathMLContentMarkupFormatter : AlgebraicVisitor 38 | { 39 | enum MathMLTrigonometryFunction 40 | { 41 | sin = TrigonometryFunction.Sine, 42 | cos = TrigonometryFunction.Cosine, 43 | tan = TrigonometryFunction.Tangent, 44 | cot = TrigonometryFunction.Cotangent, 45 | sec = TrigonometryFunction.Secant, 46 | csc = TrigonometryFunction.Cosecant, 47 | arcsin = TrigonometryFunction.InverseSine, 48 | arccos = TrigonometryFunction.InverseCosine, 49 | arctan = TrigonometryFunction.InverseTangent, 50 | arccot = TrigonometryFunction.InverseCotangent, 51 | arcsec = TrigonometryFunction.InverseSecant, 52 | arccsc = TrigonometryFunction.InverseCosecant, 53 | sinh = TrigonometryFunction.HyperbolicSine, 54 | cosh = TrigonometryFunction.HyperbolicCosine, 55 | tanh = TrigonometryFunction.HyperbolicTangent, 56 | coth = TrigonometryFunction.HyperbolicCotangent, 57 | sech = TrigonometryFunction.HyperbolicSecant, 58 | csch = TrigonometryFunction.HyperbolicCosecant, 59 | arcsinh = TrigonometryFunction.InverseHyperbolicSine, 60 | arccosh = TrigonometryFunction.InverseHyperbolicCosine, 61 | arctanh = TrigonometryFunction.InverseHyperbolicTangent, 62 | arccoth = TrigonometryFunction.InverseHyperbolicCotangent, 63 | arcsech = TrigonometryFunction.InverseHyperbolicSecant, 64 | arccsch = TrigonometryFunction.InverseHyperbolicCosecant 65 | } 66 | 67 | enum MathMLExponentialFunction 68 | { 69 | exp = ExponentialFunction.Exp, 70 | ln = ExponentialFunction.Ln 71 | } 72 | 73 | public XElement Format(Expression term) 74 | { 75 | return Visit(term); 76 | } 77 | 78 | protected override XElement VisitConstant(ConstantExpression term) 79 | { 80 | return new XElement("cn", term.Value.ToString()); 81 | } 82 | 83 | protected override XElement VisitParameter(ParameterExpression term) 84 | { 85 | return new XElement("ci", term.Name); 86 | } 87 | 88 | protected override XElement VisitAdd(BinaryExpression term) 89 | { 90 | // NOTE: n-ary support 91 | return new XElement( 92 | "apply", 93 | new XElement("plus"), 94 | Visit(term.Left), 95 | Visit(term.Right)); 96 | } 97 | 98 | protected override XElement VisitSubtract(BinaryExpression term) 99 | { 100 | return new XElement( 101 | "apply", 102 | new XElement("minus"), 103 | Visit(term.Left), 104 | Visit(term.Right)); 105 | } 106 | 107 | protected override XElement VisitPlus(UnaryExpression term) 108 | { 109 | return Visit(term.Operand); 110 | } 111 | 112 | protected override XElement VisitMinus(UnaryExpression term) 113 | { 114 | return new XElement( 115 | "apply", 116 | new XElement("minus"), 117 | Visit(term.Operand)); 118 | } 119 | 120 | protected override XElement VisitMultiply(BinaryExpression term) 121 | { 122 | // NOTE: n-ary support 123 | return new XElement( 124 | "apply", 125 | new XElement("times"), 126 | Visit(term.Left), 127 | Visit(term.Right)); 128 | } 129 | 130 | protected override XElement VisitDivide(BinaryExpression term) 131 | { 132 | return new XElement( 133 | "apply", 134 | new XElement("divide"), 135 | Visit(term.Left), 136 | Visit(term.Right)); 137 | } 138 | 139 | protected override XElement VisitPower(BinaryExpression term) 140 | { 141 | return new XElement( 142 | "apply", 143 | new XElement("power"), 144 | Visit(term.Left), 145 | Visit(term.Right)); 146 | } 147 | 148 | protected override XElement VisitTrigonometry(MethodCallExpression term, TrigonometryFunction function) 149 | { 150 | return new XElement( 151 | "apply", 152 | new XElement(((MathMLTrigonometryFunction)function).ToString()), 153 | Visit(term.Arguments[0])); 154 | } 155 | 156 | protected override XElement VisitExponential(MethodCallExpression term, ExponentialFunction function) 157 | { 158 | return new XElement( 159 | "apply", 160 | new XElement(((MathMLExponentialFunction)function).ToString()), 161 | Visit(term.Arguments[0])); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/PartialDerivative.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Linq.Expressions; 32 | 33 | namespace MathNet.ExpressionAlgebra 34 | { 35 | using MathNet.ExpressionAlgebra.Visitors; 36 | 37 | /// 38 | /// This class is stateful and not thread safe, therefore never share an instance 39 | /// between multiple threads (the ThreadStatic attribute might help). 40 | /// 41 | public class PartialDerivative : AlgebraicManipulator 42 | { 43 | string _variableName; 44 | 45 | public Expression Differentiate(Expression term, string variableName) 46 | { 47 | _variableName = variableName; 48 | try 49 | { 50 | return Visit(term); 51 | } 52 | finally 53 | { 54 | _variableName = null; 55 | } 56 | } 57 | 58 | protected override Expression VisitParameter(ParameterExpression p) 59 | { 60 | if(p.Name == _variableName) 61 | { 62 | return Arithmeric.One(); 63 | } 64 | 65 | return Arithmeric.Zero(); 66 | } 67 | 68 | protected override Expression VisitConstant(ConstantExpression c) 69 | { 70 | return Arithmeric.Zero(); 71 | } 72 | 73 | protected override Expression VisitMultiply(BinaryExpression binaryExpression) 74 | { 75 | Expression leftDerivative = Visit(binaryExpression.Left); 76 | Expression rightDerivative = Visit(binaryExpression.Right); 77 | return Arithmeric.Add( 78 | Arithmeric.Multiply(leftDerivative, binaryExpression.Right), 79 | Arithmeric.Multiply(rightDerivative, binaryExpression.Left)); 80 | } 81 | 82 | protected override Expression VisitDivide(BinaryExpression binaryExpression) 83 | { 84 | Expression leftDerivative = Visit(binaryExpression.Left); 85 | Expression rightDerivative = Visit(binaryExpression.Right); 86 | return Arithmeric.Subtract( 87 | Arithmeric.Divide(leftDerivative, binaryExpression.Right), 88 | Arithmeric.Divide( 89 | Arithmeric.Multiply(binaryExpression.Left, rightDerivative), 90 | Arithmeric.Multiply(binaryExpression.Right, binaryExpression.Right))); 91 | } 92 | 93 | protected override Expression VisitPower(BinaryExpression binaryExpression) 94 | { 95 | Expression leftDerivative = Visit(binaryExpression.Left); 96 | Expression rightDerivative = Visit(binaryExpression.Right); 97 | return Arithmeric.Multiply( 98 | binaryExpression, 99 | Arithmeric.Add( 100 | Arithmeric.Multiply( 101 | rightDerivative, 102 | Exponential.Ln(binaryExpression.Left)), 103 | Arithmeric.Divide( 104 | Arithmeric.Multiply(binaryExpression.Right, leftDerivative), 105 | binaryExpression.Left))); 106 | } 107 | 108 | protected override Expression VisitTrigonometry(MethodCallExpression methodCall, TrigonometryFunction function) 109 | { 110 | Expression argument = methodCall.Arguments[0]; 111 | 112 | switch(function) 113 | { 114 | case TrigonometryFunction.Sine: 115 | { 116 | Expression innerDerivative = Visit(argument); 117 | return Arithmeric.Multiply( 118 | innerDerivative, 119 | Trigonometry.Cosine(argument)); 120 | } 121 | 122 | case TrigonometryFunction.Cosine: 123 | { 124 | Expression innerDerivative = Visit(argument); 125 | return Arithmeric.Negate( 126 | Arithmeric.Multiply( 127 | innerDerivative, 128 | Trigonometry.Sine(argument))); 129 | } 130 | 131 | default: 132 | throw new NotSupportedException(String.Format("Trigonometric function {0} is not supported.", function.ToString())); 133 | } 134 | } 135 | 136 | protected override Expression VisitExponential(MethodCallExpression methodCall, ExponentialFunction function) 137 | { 138 | throw new NotSupportedException(String.Format("Exponential function {0} is not supported.", function.ToString())); 139 | } 140 | 141 | protected override Expression VisitOtherMethodCall(MethodCallExpression expression) 142 | { 143 | throw new NotSupportedException(String.Format("Method Call to {0} is not supported.", expression.ToString())); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Math.NET Palladium: Linq Expression Computer Algebra")] 9 | [assembly: AssemblyDescription("http://mathnet.opensourcedotnet.info/")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Math.NET Project")] 12 | [assembly: AssemblyProduct("Math.NET")] 13 | [assembly: AssemblyCopyright("Copyright © 2009, Math.NET Project")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f1b933ff-2a43-4b01-aad8-4bdc7dd2f039")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | False 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | False 38 | 39 | 40 | 41 | 42 | False 43 | 44 | 45 | 46 | 47 | False 48 | 49 | 50 | 51 | 52 | False 53 | 54 | 55 | 56 | 57 | False 58 | 59 | 60 | 61 | 62 | False 63 | 64 | 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | 86 | 87 | False 88 | 89 | 90 | 91 | 92 | False 93 | 94 | 95 | 96 | 97 | False 98 | 99 | 100 | 101 | 102 | False 103 | 104 | 105 | 106 | 107 | False 108 | 109 | 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | False 138 | 139 | 140 | 141 | 142 | False 143 | 144 | 145 | 146 | 147 | False 148 | 149 | 150 | 151 | 152 | False 153 | 154 | 155 | 156 | 157 | False 158 | 159 | 160 | 161 | 162 | False 163 | 164 | 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | False 173 | 174 | 175 | 176 | 177 | False 178 | 179 | 180 | 181 | 182 | False 183 | 184 | 185 | 186 | 187 | False 188 | 189 | 190 | 191 | 192 | False 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | False 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | False 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | False 223 | 224 | 225 | 226 | 227 | False 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | False 238 | 239 | 240 | 241 | 242 | False 243 | 244 | 245 | 246 | 247 | False 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | False 258 | 259 | 260 | 261 | 262 | False 263 | 264 | 265 | 266 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Trigonometry.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Linq.Expressions; 32 | using System.Reflection; 33 | 34 | namespace MathNet.ExpressionAlgebra 35 | { 36 | using MathNet.Numerics; 37 | 38 | /// 39 | /// Describing a trigonometric function. 40 | /// 41 | public enum TrigonometryFunction 42 | { 43 | Sine, 44 | Cosine, 45 | Tangent, 46 | Cotangent, 47 | Secant, 48 | Cosecant, 49 | InverseSine, 50 | InverseCosine, 51 | InverseTangent, 52 | InverseCotangent, 53 | InverseSecant, 54 | InverseCosecant, 55 | HyperbolicSine, 56 | HyperbolicCosine, 57 | HyperbolicTangent, 58 | HyperbolicCotangent, 59 | HyperbolicSecant, 60 | HyperbolicCosecant, 61 | InverseHyperbolicSine, 62 | InverseHyperbolicCosine, 63 | InverseHyperbolicTangent, 64 | InverseHyperbolicCotangent, 65 | InverseHyperbolicSecant, 66 | InverseHyperbolicCosecant 67 | } 68 | 69 | /// 70 | /// Trigonometric Expression Builder 71 | /// 72 | public static class Trigonometry 73 | { 74 | static readonly Type _trigType = typeof(Trig); 75 | 76 | public static Expression Apply(TrigonometryFunction function, Expression argument) 77 | { 78 | return ExpressionBuilder.CallDouble(_trigType, function.ToString(), argument); 79 | } 80 | 81 | public static bool TryParse(MethodInfo method, out TrigonometryFunction function) 82 | { 83 | string name = method.Name; 84 | 85 | if(method.DeclaringType == typeof(System.Math)) 86 | { 87 | // We map System.Math.Sin(double) to Trig for better usability 88 | switch(name) 89 | { 90 | case "Sin": 91 | function = TrigonometryFunction.Sine; 92 | return true; 93 | case "Cos": 94 | function = TrigonometryFunction.Cosine; 95 | return true; 96 | case "Tan": 97 | function = TrigonometryFunction.Tangent; 98 | return true; 99 | case "Sinh": 100 | function = TrigonometryFunction.HyperbolicSine; 101 | return true; 102 | case "Cosh": 103 | function = TrigonometryFunction.HyperbolicCosine; 104 | return true; 105 | case "Tanh": 106 | function = TrigonometryFunction.HyperbolicTangent; 107 | return true; 108 | case "Asin": 109 | function = TrigonometryFunction.InverseSine; 110 | return true; 111 | case "Acos": 112 | function = TrigonometryFunction.InverseCosine; 113 | return true; 114 | case "Atan": 115 | function = TrigonometryFunction.InverseTangent; 116 | return true; 117 | default: 118 | function = (TrigonometryFunction)0; 119 | return false; 120 | } 121 | } 122 | 123 | if(!Enum.IsDefined(typeof(TrigonometryFunction), name)) 124 | { 125 | function = (TrigonometryFunction)0; 126 | return false; 127 | } 128 | 129 | function = (TrigonometryFunction)Enum.Parse(typeof(TrigonometryFunction), name); 130 | return true; 131 | } 132 | 133 | public static Expression Sine(Expression radian) 134 | { 135 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("Sine"), radian); 136 | } 137 | 138 | public static Expression Cosine(Expression radian) 139 | { 140 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("Cosine"), radian); 141 | } 142 | 143 | public static Expression Tangent(Expression radian) 144 | { 145 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("Tangent"), radian); 146 | } 147 | 148 | public static Expression Cotangent(Expression radian) 149 | { 150 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("Cotangent"), radian); 151 | } 152 | 153 | public static Expression Secant(Expression radian) 154 | { 155 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("Secant"), radian); 156 | } 157 | 158 | public static Expression Cosecant(Expression radian) 159 | { 160 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("Cosecant"), radian); 161 | } 162 | 163 | public static Expression InverseSine(Expression real) 164 | { 165 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseSine"), real); 166 | } 167 | 168 | public static Expression InverseCosine(Expression real) 169 | { 170 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseCosine"), real); 171 | } 172 | 173 | public static Expression InverseTangent(Expression real) 174 | { 175 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseTangent"), real); 176 | } 177 | 178 | public static Expression InverseTangentFromRational(Expression nominator, Expression denominator) 179 | { 180 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseTangentFromRational"), nominator, denominator); 181 | } 182 | 183 | public static Expression InverseCotangent(Expression real) 184 | { 185 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseCotangent"), real); 186 | } 187 | 188 | public static Expression InverseSecant(Expression real) 189 | { 190 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseSecant"), real); 191 | } 192 | 193 | public static Expression InverseCosecant(Expression real) 194 | { 195 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseCosecant"), real); 196 | } 197 | 198 | public static Expression HyperbolicSine(Expression radian) 199 | { 200 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("HyperbolicSine"), radian); 201 | } 202 | 203 | public static Expression HyperbolicCosine(Expression radian) 204 | { 205 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("HyperbolicCosine"), radian); 206 | } 207 | 208 | public static Expression HyperbolicTangent(Expression radian) 209 | { 210 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("HyperbolicTangent"), radian); 211 | } 212 | 213 | public static Expression HyperbolicCotangent(Expression radian) 214 | { 215 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("HyperbolicCotangent"), radian); 216 | } 217 | 218 | public static Expression HyperbolicSecant(Expression radian) 219 | { 220 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("HyperbolicSecant"), radian); 221 | } 222 | 223 | public static Expression HyperbolicCosecant(Expression radian) 224 | { 225 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("HyperbolicCosecant"), radian); 226 | } 227 | 228 | public static Expression InverseHyperbolicSine(Expression real) 229 | { 230 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseHyperbolicSine"), real); 231 | } 232 | 233 | public static Expression InverseHyperbolicCosine(Expression real) 234 | { 235 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseHyperbolicCosine"), real); 236 | } 237 | 238 | public static Expression InverseHyperbolicTangent(Expression real) 239 | { 240 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseHyperbolicTangent"), real); 241 | } 242 | 243 | public static Expression InverseHyperbolicCotangent(Expression real) 244 | { 245 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseHyperbolicCotangent"), real); 246 | } 247 | 248 | public static Expression InverseHyperbolicSecant(Expression real) 249 | { 250 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseHyperbolicSecant"), real); 251 | } 252 | 253 | public static Expression InverseHyperbolicCosecant(Expression real) 254 | { 255 | return ExpressionBuilder.CallDouble(_trigType.GetMethod("InverseHyperbolicCosecant"), real); 256 | } 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/TypeInference.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Linq; 33 | using System.Linq.Expressions; 34 | 35 | namespace MathNet.ExpressionAlgebra 36 | { 37 | internal class TypeInference 38 | { 39 | static readonly string[] numericOrder = { "Int16", "Int32", "Int64", "Single", "Double" }; 40 | List _expressions; 41 | 42 | public TypeInference(Expression a, Expression b) 43 | { 44 | _expressions = new List() { a, b }; 45 | } 46 | 47 | public TypeInference(params Expression[] expressions) 48 | { 49 | _expressions = new List(expressions); 50 | } 51 | 52 | public TypeInference(List expressions) 53 | { 54 | _expressions = expressions; 55 | } 56 | 57 | public List CastToMaxNumericList() 58 | { 59 | Type maxType = MaxNumeric(_expressions.Select(x => x.Type)); 60 | return new List(_expressions.Select(x => (x.Type == maxType) ? x : Expression.Convert(x, maxType))); 61 | } 62 | 63 | public IEnumerable CastToMaxNumeric() 64 | { 65 | Type maxType = MaxNumeric(_expressions.Select(x => x.Type)); 66 | return _expressions.Select(x => (x.Type == maxType) ? x : Expression.Convert(x, maxType)); 67 | } 68 | 69 | public static Type MaxNumeric(Type a, Type b) 70 | { 71 | string nameA = a.Name; 72 | string nameB = b.Name; 73 | 74 | if(nameA == nameB) 75 | { 76 | return a; 77 | } 78 | 79 | int indexA = Array.IndexOf(numericOrder, nameA); 80 | int indexB = Array.IndexOf(numericOrder, nameB); 81 | 82 | if(indexA < 0) 83 | { 84 | return b; 85 | } 86 | 87 | if(indexB < 0) 88 | { 89 | return a; 90 | } 91 | 92 | return (indexA > indexB) ? a : b; 93 | } 94 | 95 | public static Type MaxNumeric(IEnumerable types) 96 | { 97 | Type max = typeof(int); 98 | 99 | foreach(Type type in types) 100 | { 101 | max = MaxNumeric(max, type); 102 | } 103 | 104 | return max; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Visitors/AlgebraicFold.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System.Linq; 31 | using System.Linq.Expressions; 32 | 33 | namespace MathNet.ExpressionAlgebra.Visitors 34 | { 35 | /// 36 | /// Alebraic Linq Expression Folding/Reduction Base 37 | /// 38 | public abstract class AlgebraicFold : AlgebraicVisitor 39 | { 40 | protected abstract T Combine(T leftValue, T rightValue); 41 | 42 | protected virtual T Combine(params T[] values) 43 | { 44 | if((values == null) || (values.Length == 0)) 45 | { 46 | return default(T); 47 | } 48 | 49 | if(values.Length == 1) 50 | { 51 | return values[0]; 52 | } 53 | 54 | T fold = Combine(values[0], values[1]); 55 | for(int i = 2; i < values.Length; i++) 56 | { 57 | fold = Combine(fold, values[i]); 58 | } 59 | 60 | return fold; 61 | } 62 | 63 | protected T VisitUnary(UnaryExpression term) 64 | { 65 | return Visit(term.Operand); 66 | } 67 | 68 | protected T VisitBinary(BinaryExpression term) 69 | { 70 | return Combine( 71 | Visit(term.Left), 72 | Visit(term.Right)); 73 | } 74 | 75 | protected T VisitMethodCall(MethodCallExpression term) 76 | { 77 | var visitQuery = term.Arguments.Select(a => Visit(a)); 78 | return Combine(visitQuery.ToArray()); 79 | } 80 | 81 | protected override T VisitAdd(BinaryExpression term) 82 | { 83 | return VisitBinary(term); 84 | } 85 | 86 | protected override T VisitSubtract(BinaryExpression term) 87 | { 88 | return VisitBinary(term); 89 | } 90 | 91 | protected override T VisitPlus(UnaryExpression term) 92 | { 93 | return VisitUnary(term); 94 | } 95 | 96 | protected override T VisitMinus(UnaryExpression term) 97 | { 98 | return VisitUnary(term); 99 | } 100 | 101 | protected override T VisitMultiply(BinaryExpression term) 102 | { 103 | return VisitBinary(term); 104 | } 105 | 106 | protected override T VisitDivide(BinaryExpression term) 107 | { 108 | return VisitBinary(term); 109 | } 110 | 111 | protected override T VisitPower(BinaryExpression term) 112 | { 113 | return VisitBinary(term); 114 | } 115 | 116 | protected override T VisitTrigonometry(MethodCallExpression term, TrigonometryFunction function) 117 | { 118 | return VisitMethodCall(term); 119 | } 120 | 121 | protected override T VisitExponential(MethodCallExpression term, ExponentialFunction function) 122 | { 123 | return VisitMethodCall(term); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Visitors/AlgebraicFoldLambda.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Linq.Expressions; 32 | 33 | namespace MathNet.ExpressionAlgebra.Visitors 34 | { 35 | public class AlgebraicFoldLambda : AlgebraicFold 36 | { 37 | Func _foldLeafParam; 38 | Func _foldLeafConst; 39 | Func _combine; 40 | 41 | public AlgebraicFoldLambda( 42 | Func combine, 43 | Func foldParam, 44 | Func foldConst) 45 | { 46 | _combine = combine; 47 | _foldLeafParam = foldParam; 48 | _foldLeafConst = foldConst; 49 | } 50 | 51 | public static Func Create( 52 | Func combine, 53 | Func foldParam, 54 | Func foldConst) 55 | { 56 | AlgebraicFoldLambda fold = new AlgebraicFoldLambda(combine, foldParam, foldConst); 57 | return fold.Visit; 58 | } 59 | 60 | protected override T Combine(T leftValue, T rightValue) 61 | { 62 | return _combine(leftValue, rightValue); 63 | } 64 | 65 | protected override T VisitConstant(ConstantExpression term) 66 | { 67 | return _foldLeafConst(term); 68 | } 69 | 70 | protected override T VisitParameter(ParameterExpression term) 71 | { 72 | return _foldLeafParam(term); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Visitors/AlgebraicManipulator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Collections.ObjectModel; 32 | using System.Linq.Expressions; 33 | using System.Reflection; 34 | 35 | namespace MathNet.ExpressionAlgebra.Visitors 36 | { 37 | /// 38 | /// Alebraic Linq Expression Manipulator Base 39 | /// 40 | public abstract class AlgebraicManipulator : ExpressionManipulator 41 | { 42 | protected AlgebraicManipulator() 43 | { 44 | } 45 | 46 | protected override Expression VisitUnary(UnaryExpression term) 47 | { 48 | switch(term.NodeType) 49 | { 50 | case ExpressionType.Negate: 51 | case ExpressionType.NegateChecked: 52 | return VisitMinus((UnaryExpression)term); 53 | case ExpressionType.UnaryPlus: 54 | return VisitPlus((UnaryExpression)term); 55 | default: 56 | return base.VisitUnary(term); 57 | } 58 | } 59 | 60 | protected override Expression VisitBinary(BinaryExpression term) 61 | { 62 | switch(term.NodeType) 63 | { 64 | case ExpressionType.Add: 65 | case ExpressionType.AddChecked: 66 | return VisitAdd((BinaryExpression)term); 67 | case ExpressionType.Subtract: 68 | case ExpressionType.SubtractChecked: 69 | return VisitSubtract((BinaryExpression)term); 70 | case ExpressionType.Multiply: 71 | case ExpressionType.MultiplyChecked: 72 | return VisitMultiply((BinaryExpression)term); 73 | case ExpressionType.Divide: 74 | return VisitDivide((BinaryExpression)term); 75 | case ExpressionType.Power: 76 | return VisitPower((BinaryExpression)term); 77 | default: 78 | return base.VisitBinary(term); 79 | } 80 | } 81 | 82 | protected virtual Expression VisitAdd(BinaryExpression term) 83 | { 84 | Expression newLeft = Visit(term.Left); 85 | Expression newRight = Visit(term.Right); 86 | if(newLeft != term.Left || newRight != term.Right) 87 | { 88 | return Arithmeric.Add(newLeft, newRight); 89 | } 90 | 91 | return term; 92 | } 93 | 94 | protected virtual Expression VisitSubtract(BinaryExpression term) 95 | { 96 | Expression newLeft = Visit(term.Left); 97 | Expression newRight = Visit(term.Right); 98 | if(newLeft != term.Left || newRight != term.Right) 99 | { 100 | return Arithmeric.Subtract(newLeft, newRight); 101 | } 102 | 103 | return term; 104 | } 105 | 106 | protected virtual Expression VisitPlus(UnaryExpression term) 107 | { 108 | return base.VisitUnary(term); 109 | } 110 | 111 | protected virtual Expression VisitMinus(UnaryExpression term) 112 | { 113 | return base.VisitUnary(term); 114 | } 115 | 116 | protected virtual Expression VisitMultiply(BinaryExpression term) 117 | { 118 | Expression newLeft = Visit(term.Left); 119 | Expression newRight = Visit(term.Right); 120 | if(newLeft != term.Left || newRight != term.Right) 121 | { 122 | return Arithmeric.Multiply(newLeft, newRight); 123 | } 124 | 125 | return term; 126 | } 127 | 128 | protected virtual Expression VisitDivide(BinaryExpression term) 129 | { 130 | Expression newLeft = Visit(term.Left); 131 | Expression newRight = Visit(term.Right); 132 | if(newLeft != term.Left || newRight != term.Right) 133 | { 134 | return Arithmeric.Divide(newLeft, newRight); 135 | } 136 | 137 | return term; 138 | } 139 | 140 | protected virtual Expression VisitPower(BinaryExpression term) 141 | { 142 | Expression newLeft = Visit(term.Left); 143 | Expression newRight = Visit(term.Right); 144 | if(newLeft != term.Left || newRight != term.Right) 145 | { 146 | return Arithmeric.Power(newLeft, newRight); 147 | } 148 | 149 | return term; 150 | } 151 | 152 | protected override Expression VisitMethodCall(MethodCallExpression term) 153 | { 154 | MethodInfo method = term.Method; 155 | 156 | TrigonometryFunction trigFunction; 157 | if(Trigonometry.TryParse(method, out trigFunction)) 158 | { 159 | return VisitTrigonometry(term, trigFunction); 160 | } 161 | 162 | ExponentialFunction expFunction; 163 | if(Exponential.TryParse(method, out expFunction)) 164 | { 165 | return VisitExponential(term, expFunction); 166 | } 167 | 168 | return VisitOtherMethodCall(term); 169 | } 170 | 171 | protected virtual Expression VisitOtherMethodCall(MethodCallExpression term) 172 | { 173 | return base.VisitMethodCall(term); 174 | } 175 | 176 | protected virtual Expression VisitTrigonometry(MethodCallExpression term, TrigonometryFunction function) 177 | { 178 | ReadOnlyCollection newArguments = VisitExpressionList(term.Arguments); 179 | if(newArguments != term.Arguments) 180 | { 181 | if(newArguments.Count != 1) 182 | { 183 | throw new InvalidOperationException("Single Argument Expected."); 184 | } 185 | 186 | return Trigonometry.Apply(function, newArguments[0]); 187 | } 188 | 189 | return term; 190 | } 191 | 192 | protected virtual Expression VisitExponential(MethodCallExpression term, ExponentialFunction function) 193 | { 194 | ReadOnlyCollection newArguments = VisitExpressionList(term.Arguments); 195 | if(newArguments != term.Arguments) 196 | { 197 | if(newArguments.Count != 1) 198 | { 199 | throw new InvalidOperationException("Single Argument Expected."); 200 | } 201 | 202 | return Exponential.Apply(function, newArguments[0]); 203 | } 204 | 205 | return term; 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Visitors/AlgebraicVisitor.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Linq.Expressions; 32 | using System.Reflection; 33 | 34 | namespace MathNet.ExpressionAlgebra.Visitors 35 | { 36 | /// 37 | /// Linq Expression Generic Algebraic Visitor Base 38 | /// 39 | public abstract class AlgebraicVisitor 40 | { 41 | protected AlgebraicVisitor() 42 | { 43 | } 44 | 45 | protected virtual T Visit(Expression term) 46 | { 47 | if(term == null) 48 | { 49 | return default(T); 50 | } 51 | 52 | switch(term.NodeType) 53 | { 54 | case ExpressionType.Constant: 55 | return VisitConstant((ConstantExpression)term); 56 | 57 | case ExpressionType.Parameter: 58 | return VisitParameter((ParameterExpression)term); 59 | 60 | case ExpressionType.Negate: 61 | case ExpressionType.NegateChecked: 62 | return VisitMinus((UnaryExpression)term); 63 | 64 | case ExpressionType.UnaryPlus: 65 | return VisitPlus((UnaryExpression)term); 66 | 67 | case ExpressionType.Add: 68 | case ExpressionType.AddChecked: 69 | return VisitAdd((BinaryExpression)term); 70 | 71 | case ExpressionType.Subtract: 72 | case ExpressionType.SubtractChecked: 73 | return VisitSubtract((BinaryExpression)term); 74 | 75 | case ExpressionType.Multiply: 76 | case ExpressionType.MultiplyChecked: 77 | return VisitMultiply((BinaryExpression)term); 78 | 79 | case ExpressionType.Divide: 80 | return VisitDivide((BinaryExpression)term); 81 | 82 | case ExpressionType.Power: 83 | return VisitPower((BinaryExpression)term); 84 | 85 | case ExpressionType.Call: 86 | return VisitMethodCallCore((MethodCallExpression)term); 87 | 88 | case ExpressionType.Convert: 89 | case ExpressionType.ConvertChecked: 90 | return VisitConvert((UnaryExpression)term); 91 | 92 | default: 93 | return VisitUnknown(term); 94 | } 95 | } 96 | 97 | protected abstract T VisitConstant(ConstantExpression term); 98 | 99 | protected abstract T VisitParameter(ParameterExpression term); 100 | 101 | protected abstract T VisitAdd(BinaryExpression term); 102 | 103 | protected abstract T VisitSubtract(BinaryExpression term); 104 | 105 | protected abstract T VisitPlus(UnaryExpression term); 106 | 107 | protected abstract T VisitMinus(UnaryExpression term); 108 | 109 | protected abstract T VisitMultiply(BinaryExpression term); 110 | 111 | protected abstract T VisitDivide(BinaryExpression term); 112 | 113 | protected abstract T VisitPower(BinaryExpression term); 114 | 115 | protected abstract T VisitTrigonometry(MethodCallExpression term, TrigonometryFunction function); 116 | 117 | protected abstract T VisitExponential(MethodCallExpression term, ExponentialFunction function); 118 | 119 | protected virtual T VisitOtherMethodCall(MethodCallExpression term) 120 | { 121 | throw new NotSupportedException(string.Format("Unhandled expression method call: '{0}'", term.Method)); 122 | } 123 | 124 | protected virtual T VisitUnknown(Expression term) 125 | { 126 | throw new NotSupportedException(string.Format("Unhandled expression type: '{0}'", term.NodeType)); 127 | } 128 | 129 | protected virtual T VisitConvert(UnaryExpression term) 130 | { 131 | return Visit(term.Operand); 132 | } 133 | 134 | private T VisitMethodCallCore(MethodCallExpression term) 135 | { 136 | MethodInfo method = term.Method; 137 | 138 | TrigonometryFunction trigFunction; 139 | if(Trigonometry.TryParse(method, out trigFunction)) 140 | { 141 | return VisitTrigonometry(term, trigFunction); 142 | } 143 | 144 | ExponentialFunction expFunction; 145 | if(Exponential.TryParse(method, out expFunction)) 146 | { 147 | return VisitExponential(term, expFunction); 148 | } 149 | 150 | return VisitOtherMethodCall(term); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/app/MathNet.Palladium/Visitors/ExpressionManipulator.cs: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2002-2009, Christoph Rüegg. 4 | // All Right Reserved. 5 | // 6 | // 7 | // Christoph Rüegg, http://christoph.ruegg.name 8 | // 9 | // 10 | // Math.NET Palladium, part of the Math.NET Project. 11 | // http://mathnet.opensourcedotnet.info 12 | // 13 | // 14 | // This program is free software; you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as published 16 | // by the Free Software Foundation; either version 2 of the License, or 17 | // any later version. 18 | // 19 | // This program is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | // 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with this program; if not, write to the Free Software 26 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 | // 28 | //----------------------------------------------------------------------- 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | using System.Collections.ObjectModel; 33 | using System.Linq.Expressions; 34 | 35 | namespace MathNet.ExpressionAlgebra.Visitors 36 | { 37 | /// 38 | /// Linq Expression Manipulator Base 39 | /// 40 | public abstract class ExpressionManipulator 41 | { 42 | protected ExpressionManipulator() 43 | { 44 | } 45 | 46 | protected virtual Expression Visit(Expression term) 47 | { 48 | if(term == null) 49 | { 50 | return null; 51 | } 52 | 53 | switch(term.NodeType) 54 | { 55 | case ExpressionType.Negate: 56 | case ExpressionType.NegateChecked: 57 | case ExpressionType.Not: 58 | case ExpressionType.Convert: 59 | case ExpressionType.ConvertChecked: 60 | case ExpressionType.ArrayLength: 61 | case ExpressionType.Quote: 62 | case ExpressionType.TypeAs: 63 | case ExpressionType.UnaryPlus: 64 | return VisitUnary((UnaryExpression)term); 65 | case ExpressionType.Add: 66 | case ExpressionType.AddChecked: 67 | case ExpressionType.Subtract: 68 | case ExpressionType.SubtractChecked: 69 | case ExpressionType.Multiply: 70 | case ExpressionType.MultiplyChecked: 71 | case ExpressionType.Divide: 72 | case ExpressionType.Modulo: 73 | case ExpressionType.And: 74 | case ExpressionType.AndAlso: 75 | case ExpressionType.Or: 76 | case ExpressionType.OrElse: 77 | case ExpressionType.LessThan: 78 | case ExpressionType.LessThanOrEqual: 79 | case ExpressionType.GreaterThan: 80 | case ExpressionType.GreaterThanOrEqual: 81 | case ExpressionType.Equal: 82 | case ExpressionType.NotEqual: 83 | case ExpressionType.Coalesce: 84 | case ExpressionType.ArrayIndex: 85 | case ExpressionType.RightShift: 86 | case ExpressionType.LeftShift: 87 | case ExpressionType.ExclusiveOr: 88 | case ExpressionType.Power: 89 | return VisitBinary((BinaryExpression)term); 90 | case ExpressionType.TypeIs: 91 | return VisitTypeIs((TypeBinaryExpression)term); 92 | case ExpressionType.Conditional: 93 | return VisitConditional((ConditionalExpression)term); 94 | case ExpressionType.Constant: 95 | return VisitConstant((ConstantExpression)term); 96 | case ExpressionType.Parameter: 97 | return VisitParameter((ParameterExpression)term); 98 | case ExpressionType.MemberAccess: 99 | return VisitMemberAccess((MemberExpression)term); 100 | case ExpressionType.Call: 101 | return VisitMethodCall((MethodCallExpression)term); 102 | case ExpressionType.Lambda: 103 | return VisitLambda((LambdaExpression)term); 104 | case ExpressionType.New: 105 | return VisitNew((NewExpression)term); 106 | case ExpressionType.NewArrayInit: 107 | case ExpressionType.NewArrayBounds: 108 | return VisitNewArray((NewArrayExpression)term); 109 | case ExpressionType.Invoke: 110 | return VisitInvocation((InvocationExpression)term); 111 | case ExpressionType.MemberInit: 112 | return VisitMemberInit((MemberInitExpression)term); 113 | case ExpressionType.ListInit: 114 | return VisitListInit((ListInitExpression)term); 115 | default: 116 | return VisitUnknown(term); 117 | } 118 | } 119 | 120 | protected virtual Expression VisitUnknown(Expression expression) 121 | { 122 | throw new Exception(string.Format("Unhandled expression type: '{0}'", expression.NodeType)); 123 | } 124 | 125 | protected virtual MemberBinding VisitBinding(MemberBinding binding) 126 | { 127 | switch(binding.BindingType) 128 | { 129 | case MemberBindingType.Assignment: 130 | return this.VisitMemberAssignment((MemberAssignment)binding); 131 | case MemberBindingType.MemberBinding: 132 | return this.VisitMemberMemberBinding((MemberMemberBinding)binding); 133 | case MemberBindingType.ListBinding: 134 | return this.VisitMemberListBinding((MemberListBinding)binding); 135 | default: 136 | throw new Exception(string.Format("Unhandled binding type '{0}'", binding.BindingType)); 137 | } 138 | } 139 | 140 | protected virtual ElementInit VisitElementInitializer(ElementInit initializer) 141 | { 142 | ReadOnlyCollection arguments = this.VisitExpressionList(initializer.Arguments); 143 | if(arguments != initializer.Arguments) 144 | { 145 | return Expression.ElementInit(initializer.AddMethod, arguments); 146 | } 147 | 148 | return initializer; 149 | } 150 | 151 | protected virtual Expression VisitUnary(UnaryExpression u) 152 | { 153 | Expression operand = this.Visit(u.Operand); 154 | if(operand != u.Operand) 155 | { 156 | return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method); 157 | } 158 | 159 | return u; 160 | } 161 | 162 | protected virtual Expression VisitBinary(BinaryExpression b) 163 | { 164 | Expression left = this.Visit(b.Left); 165 | Expression right = this.Visit(b.Right); 166 | Expression conversion = this.Visit(b.Conversion); 167 | if(left != b.Left || right != b.Right || conversion != b.Conversion) 168 | { 169 | if(b.NodeType == ExpressionType.Coalesce && b.Conversion != null) 170 | { 171 | return Expression.Coalesce(left, right, conversion as LambdaExpression); 172 | } 173 | else 174 | { 175 | return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method); 176 | } 177 | } 178 | 179 | return b; 180 | } 181 | 182 | protected virtual Expression VisitTypeIs(TypeBinaryExpression b) 183 | { 184 | Expression expr = this.Visit(b.Expression); 185 | if(expr != b.Expression) 186 | { 187 | return Expression.TypeIs(expr, b.TypeOperand); 188 | } 189 | 190 | return b; 191 | } 192 | 193 | protected virtual Expression VisitConstant(ConstantExpression constantExpression) 194 | { 195 | return constantExpression; 196 | } 197 | 198 | protected virtual Expression VisitConditional(ConditionalExpression c) 199 | { 200 | Expression test = this.Visit(c.Test); 201 | Expression ifTrue = this.Visit(c.IfTrue); 202 | Expression ifFalse = this.Visit(c.IfFalse); 203 | if(test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse) 204 | { 205 | return Expression.Condition(test, ifTrue, ifFalse); 206 | } 207 | 208 | return c; 209 | } 210 | 211 | protected virtual Expression VisitParameter(ParameterExpression p) 212 | { 213 | return p; 214 | } 215 | 216 | protected virtual Expression VisitMemberAccess(MemberExpression m) 217 | { 218 | Expression exp = this.Visit(m.Expression); 219 | if(exp != m.Expression) 220 | { 221 | return Expression.MakeMemberAccess(exp, m.Member); 222 | } 223 | 224 | return m; 225 | } 226 | 227 | protected virtual Expression VisitMethodCall(MethodCallExpression m) 228 | { 229 | Expression obj = this.Visit(m.Object); 230 | IEnumerable args = this.VisitExpressionList(m.Arguments); 231 | if(obj != m.Object || args != m.Arguments) 232 | { 233 | return Expression.Call(obj, m.Method, args); 234 | } 235 | 236 | return m; 237 | } 238 | 239 | protected virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection original) 240 | { 241 | if(original != null) 242 | { 243 | List list = null; 244 | for(int i = 0, n = original.Count; i < n; i++) 245 | { 246 | Expression p = this.Visit(original[i]); 247 | if(list != null) 248 | { 249 | list.Add(p); 250 | } 251 | else if(p != original[i]) 252 | { 253 | list = new List(n); 254 | for(int j = 0; j < i; j++) 255 | { 256 | list.Add(original[j]); 257 | } 258 | 259 | list.Add(p); 260 | } 261 | } 262 | 263 | if(list != null) 264 | { 265 | return list.AsReadOnly(); 266 | } 267 | } 268 | 269 | return original; 270 | } 271 | 272 | protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) 273 | { 274 | Expression e = this.Visit(assignment.Expression); 275 | if(e != assignment.Expression) 276 | { 277 | return Expression.Bind(assignment.Member, e); 278 | } 279 | 280 | return assignment; 281 | } 282 | 283 | protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) 284 | { 285 | IEnumerable bindings = this.VisitBindingList(binding.Bindings); 286 | if(bindings != binding.Bindings) 287 | { 288 | return Expression.MemberBind(binding.Member, bindings); 289 | } 290 | 291 | return binding; 292 | } 293 | 294 | protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) 295 | { 296 | IEnumerable initializers = this.VisitElementInitializerList(binding.Initializers); 297 | if(initializers != binding.Initializers) 298 | { 299 | return Expression.ListBind(binding.Member, initializers); 300 | } 301 | 302 | return binding; 303 | } 304 | 305 | protected virtual IEnumerable VisitBindingList(ReadOnlyCollection original) 306 | { 307 | List list = null; 308 | for(int i = 0, n = original.Count; i < n; i++) 309 | { 310 | MemberBinding b = this.VisitBinding(original[i]); 311 | if(list != null) 312 | { 313 | list.Add(b); 314 | } 315 | else if(b != original[i]) 316 | { 317 | list = new List(n); 318 | for(int j = 0; j < i; j++) 319 | { 320 | list.Add(original[j]); 321 | } 322 | 323 | list.Add(b); 324 | } 325 | } 326 | 327 | if(list != null) 328 | { 329 | return list; 330 | } 331 | 332 | return original; 333 | } 334 | 335 | protected virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original) 336 | { 337 | List list = null; 338 | for(int i = 0, n = original.Count; i < n; i++) 339 | { 340 | ElementInit init = this.VisitElementInitializer(original[i]); 341 | if(list != null) 342 | { 343 | list.Add(init); 344 | } 345 | else if(init != original[i]) 346 | { 347 | list = new List(n); 348 | for(int j = 0; j < i; j++) 349 | { 350 | list.Add(original[j]); 351 | } 352 | 353 | list.Add(init); 354 | } 355 | } 356 | 357 | if(list != null) 358 | { 359 | return list; 360 | } 361 | 362 | return original; 363 | } 364 | 365 | protected virtual Expression VisitLambda(LambdaExpression lambda) 366 | { 367 | Expression body = this.Visit(lambda.Body); 368 | if(body != lambda.Body) 369 | { 370 | return Expression.Lambda(lambda.Type, body, lambda.Parameters); 371 | } 372 | 373 | return lambda; 374 | } 375 | 376 | protected virtual NewExpression VisitNew(NewExpression nex) 377 | { 378 | IEnumerable args = this.VisitExpressionList(nex.Arguments); 379 | if(args != nex.Arguments) 380 | { 381 | if(nex.Members != null) 382 | { 383 | return Expression.New(nex.Constructor, args, nex.Members); 384 | } 385 | else 386 | { 387 | return Expression.New(nex.Constructor, args); 388 | } 389 | } 390 | 391 | return nex; 392 | } 393 | 394 | protected virtual Expression VisitMemberInit(MemberInitExpression init) 395 | { 396 | NewExpression n = this.VisitNew(init.NewExpression); 397 | IEnumerable bindings = this.VisitBindingList(init.Bindings); 398 | if(n != init.NewExpression || bindings != init.Bindings) 399 | { 400 | return Expression.MemberInit(n, bindings); 401 | } 402 | 403 | return init; 404 | } 405 | 406 | protected virtual Expression VisitListInit(ListInitExpression init) 407 | { 408 | NewExpression n = this.VisitNew(init.NewExpression); 409 | IEnumerable initializers = this.VisitElementInitializerList(init.Initializers); 410 | if(n != init.NewExpression || initializers != init.Initializers) 411 | { 412 | return Expression.ListInit(n, initializers); 413 | } 414 | 415 | return init; 416 | } 417 | 418 | protected virtual Expression VisitNewArray(NewArrayExpression na) 419 | { 420 | IEnumerable exprs = this.VisitExpressionList(na.Expressions); 421 | if(exprs != na.Expressions) 422 | { 423 | if(na.NodeType == ExpressionType.NewArrayInit) 424 | { 425 | return Expression.NewArrayInit(na.Type.GetElementType(), exprs); 426 | } 427 | else 428 | { 429 | return Expression.NewArrayBounds(na.Type.GetElementType(), exprs); 430 | } 431 | } 432 | 433 | return na; 434 | } 435 | 436 | protected virtual Expression VisitInvocation(InvocationExpression iv) 437 | { 438 | IEnumerable args = this.VisitExpressionList(iv.Arguments); 439 | Expression expr = this.Visit(iv.Expression); 440 | if(args != iv.Arguments || expr != iv.Expression) 441 | { 442 | return Expression.Invoke(expr, args); 443 | } 444 | 445 | return iv; 446 | } 447 | } 448 | } 449 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/DifferentiationTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using NUnit.Framework; 4 | 5 | namespace MathNet.Palladium.Test 6 | { 7 | using MathNet.ExpressionAlgebra; 8 | 9 | [TestFixture] 10 | public class DifferentiationTests 11 | { 12 | [Test] 13 | public void TestDeriveConstant() 14 | { 15 | Expression> lambda = x => 5d; 16 | 17 | PartialDerivative pd = new PartialDerivative(); 18 | Expression derivative = pd.Differentiate(lambda.Body, "x"); 19 | Assert.AreEqual(ExpressionType.Constant, derivative.NodeType); 20 | Assert.AreEqual("0", derivative.ToString()); 21 | } 22 | 23 | [Test] 24 | public void TestDeriveVariable() 25 | { 26 | Expression> lambda = x => x; 27 | 28 | PartialDerivative pd = new PartialDerivative(); 29 | Expression derivative = pd.Differentiate(lambda.Body, "x"); 30 | Assert.AreEqual(ExpressionType.Constant, derivative.NodeType); 31 | Assert.AreEqual("1", derivative.ToString()); 32 | } 33 | 34 | [Test] 35 | public void TestDeriveLinear() 36 | { 37 | Expression> lambda = x => 2*x + 5; 38 | 39 | PartialDerivative pd = new PartialDerivative(); 40 | Expression derivative = pd.Differentiate(lambda.Body, "x"); 41 | Assert.AreEqual(ExpressionType.Constant, derivative.NodeType); 42 | Assert.AreEqual("2", derivative.ToString()); 43 | } 44 | 45 | [Test] 46 | public void TestDeriveSine() 47 | { 48 | Expression> lambda = x => Math.Sin(x); 49 | 50 | PartialDerivative pd = new PartialDerivative(); 51 | Expression derivative = pd.Differentiate(lambda.Body, "x"); 52 | Assert.AreEqual(ExpressionType.Call, derivative.NodeType); 53 | Assert.AreEqual("Cosine(x)", derivative.ToString()); 54 | } 55 | 56 | [Test] 57 | public void TestDeriveCosineProduct() 58 | { 59 | Expression> lambda = (x, y) => Math.Cos(x) * Math.Sin(y); 60 | 61 | PartialDerivative pd = new PartialDerivative(); 62 | Expression derivative = pd.Differentiate(lambda.Body, "x"); 63 | Assert.AreEqual(ExpressionType.Multiply, derivative.NodeType); 64 | Assert.AreEqual("(-Sine(x) * Sin(y))", derivative.ToString()); 65 | 66 | /* 67 | NOTE: The reason why the first is named "Sine" while the second uses "Sin" is 68 | that Math.NET Palladium always uses the Math.NET Iridium trigonometric functions 69 | (MathNet.Numerics.Trig.Sine(x)). However, the second instance (System.Math.Sin) 70 | was not touched by Palladium at all and therefore is still using Math.Sin. 71 | */ 72 | } 73 | 74 | [Test] 75 | public void TestDeriveSineInv() 76 | { 77 | Expression> lambda = x => Math.Sin(1d/x); 78 | 79 | PartialDerivative pd = new PartialDerivative(); 80 | Expression derivative = pd.Differentiate(lambda.Body, "x"); 81 | Assert.AreEqual(ExpressionType.Multiply, derivative.NodeType); 82 | Assert.AreEqual("(-(1 / (x * x)) * Cosine((1 / x)))", derivative.ToString()); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/ExpressionAlgebraElementaryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using NUnit.Framework; 5 | 6 | namespace MathNet.Palladium.Test 7 | { 8 | using MathNet.ExpressionAlgebra; 9 | using MathNet.Numerics; 10 | 11 | [TestFixture] 12 | public class ExpressionAlgebraElementaryTests 13 | { 14 | [Test] 15 | public void TestNumeratorDenominatorOfTernaryProduct() 16 | { 17 | Expression> lambda = x => 2 * x * Trig.Cosecant(x); 18 | 19 | Expression nominator = Elementary.Numerator(lambda.Body); 20 | Assert.AreEqual(ExpressionType.Multiply, nominator.NodeType); 21 | Assert.IsInstanceOfType(typeof(BinaryExpression), nominator); 22 | Assert.AreEqual("((2 * x) * Cosecant(x))", nominator.ToString()); 23 | 24 | Expression denominator = Elementary.Denominator(lambda.Body); 25 | Assert.AreEqual(ExpressionType.Constant, denominator.NodeType); 26 | Assert.IsInstanceOfType(typeof(ConstantExpression), denominator); 27 | Assert.AreEqual("1", denominator.ToString()); 28 | } 29 | 30 | [Test] 31 | public void TestNumeratorDenominatorOfBinaryQuotient() 32 | { 33 | Expression> lambda = x => Math.Exp(x) / (2 * x); 34 | 35 | Expression nominator = Elementary.Numerator(lambda.Body); 36 | Assert.AreEqual(ExpressionType.Call, nominator.NodeType); 37 | Assert.IsInstanceOfType(typeof(MethodCallExpression), nominator); 38 | Assert.AreEqual("Exp(x)", nominator.ToString()); 39 | 40 | Expression denominator = Elementary.Denominator(lambda.Body); 41 | Assert.AreEqual(ExpressionType.Multiply, denominator.NodeType); 42 | Assert.IsInstanceOfType(typeof(BinaryExpression), denominator); 43 | Assert.AreEqual("(2 * x)", denominator.ToString()); 44 | } 45 | 46 | [Test] 47 | public void TestNumeratorDenominatorOfTernaryQuotient() 48 | { 49 | Expression> lambda = x => x / 2 / Math.PI; 50 | 51 | Expression nominator = Elementary.Numerator(lambda.Body); 52 | Assert.AreEqual(ExpressionType.Divide, nominator.NodeType); 53 | Assert.IsInstanceOfType(typeof(BinaryExpression), nominator); 54 | Assert.AreEqual("(x / 2)", nominator.ToString()); 55 | 56 | Expression denominator = Elementary.Denominator(lambda.Body); 57 | Assert.AreEqual(ExpressionType.Constant, denominator.NodeType); 58 | Assert.IsInstanceOfType(typeof(ConstantExpression), denominator); 59 | Assert.AreEqual(Math.PI.ToString(), denominator.ToString()); 60 | } 61 | 62 | [Test] 63 | public void TestFactorsOfSum() 64 | { 65 | Expression> lambda = x => 2 + x; 66 | 67 | List factors = Elementary.Factors(lambda.Body); 68 | Assert.AreEqual(1, factors.Count); 69 | Assert.AreEqual(lambda.Body, factors[0]); 70 | } 71 | 72 | [Test] 73 | public void TestFactorsOfProduct() 74 | { 75 | Expression> lambda = x => 2 * x * Math.Sin(x); 76 | 77 | List factors = Elementary.Factors(lambda.Body); 78 | Assert.AreEqual(3, factors.Count); 79 | Assert.AreEqual("2", factors[0].ToString()); 80 | Assert.AreEqual("x", factors[1].ToString()); 81 | Assert.AreEqual("Sin(x)", factors[2].ToString()); 82 | } 83 | 84 | [Test] 85 | public void TestFactorsOfProductWithQuotients() 86 | { 87 | Expression> lambda = x => 2 * (x / Math.Sin(x)) * (1 / (x * Math.Exp(x) * (1 + x))); 88 | 89 | List factors = Elementary.Factors(lambda.Body); 90 | Assert.AreEqual(7, factors.Count); 91 | Assert.AreEqual("2", factors[0].ToString()); 92 | Assert.AreEqual("x", factors[1].ToString()); 93 | Assert.AreEqual("(1 / Sin(x))", factors[2].ToString()); 94 | Assert.AreEqual("1", factors[3].ToString()); 95 | Assert.AreEqual("(1 / x)", factors[4].ToString()); 96 | Assert.AreEqual("(1 / Exp(x))", factors[5].ToString()); 97 | Assert.AreEqual("(1 / (1 + x))", factors[6].ToString()); 98 | } 99 | 100 | [Test] 101 | public void TestFactorsOfNestedQuotients() 102 | { 103 | Expression> lambda = (a, b, c, d) => (a / b / (c * a)) * (c * d / a) / d; 104 | 105 | List factors = Elementary.Factors(lambda.Body); 106 | Assert.AreEqual(8, factors.Count); 107 | Assert.AreEqual("a", factors[0].ToString()); 108 | Assert.AreEqual("(1 / b)", factors[1].ToString()); 109 | Assert.AreEqual("(1 / c)", factors[2].ToString()); 110 | Assert.AreEqual("(1 / a)", factors[3].ToString()); 111 | Assert.AreEqual("c", factors[4].ToString()); 112 | Assert.AreEqual("d", factors[5].ToString()); 113 | Assert.AreEqual("(1 / a)", factors[6].ToString()); 114 | Assert.AreEqual("(1 / d)", factors[7].ToString()); 115 | } 116 | 117 | [Test] 118 | public void TestDependsOn() 119 | { 120 | Expression> f1 = (x, y) => x; 121 | Assert.IsTrue(Elementary.DependsOn(f1.Body, "x")); 122 | Assert.IsFalse(Elementary.DependsOn(f1.Body, "y")); 123 | 124 | Expression> f2 = (x, y) => Math.Sin(2 + y); 125 | Assert.IsFalse(Elementary.DependsOn(f2.Body, "x")); 126 | Assert.IsTrue(Elementary.DependsOn(f2.Body, "y")); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/ExpressionAlgebraSimplifyTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using NUnit.Framework; 4 | 5 | namespace MathNet.Palladium.Test 6 | { 7 | using MathNet.ExpressionAlgebra; 8 | 9 | [TestFixture] 10 | public class ExpressionAlgebraSimplifyTests 11 | { 12 | [Test] 13 | public void TestSimplifyTernaryQuotient() 14 | { 15 | Expression> lambda = x => x / 2 / Math.PI; 16 | Assert.AreEqual(String.Format("((x / 2) / {0})", Math.PI), lambda.Body.ToString()); 17 | 18 | Expression simplified = AutoSimplify.SimplifyFactors(lambda.Body); 19 | Assert.AreEqual(ExpressionType.Divide, simplified.NodeType); 20 | Assert.IsInstanceOfType(typeof(BinaryExpression), simplified); 21 | Assert.AreEqual(String.Format("(x / ({0} * 2))", Math.PI), simplified.ToString()); 22 | } 23 | 24 | [Test] 25 | public void TestSimplifyCrazyFactors() 26 | { 27 | Expression> lambda = (a, b, c, d) => (a / b / (c * a)) * (c * d / a) / d; 28 | Assert.AreEqual("((((a / b) / (c * a)) * ((c * d) / a)) / d)", lambda.Body.ToString()); 29 | 30 | Expression simplified = AutoSimplify.SimplifyFactors(lambda.Body); 31 | Assert.AreEqual(ExpressionType.Divide, simplified.NodeType); 32 | Assert.IsInstanceOfType(typeof(BinaryExpression), simplified); 33 | Assert.AreEqual("(((a * d) * c) / ((((d * a) * b) * a) * c))", simplified.ToString()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/LinqExpressionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using NUnit.Framework; 7 | 8 | namespace MathNet.Palladium.Test 9 | { 10 | using MathNet.Numerics; 11 | 12 | [TestFixture] 13 | public class LinqExpressionTests 14 | { 15 | [Test] 16 | public void LambdaExpressionOperatorDecompositionTest() 17 | { 18 | Expression> add = (x, y) => x + y; 19 | 20 | Assert.AreEqual(ExpressionType.Lambda, add.NodeType); 21 | Assert.IsInstanceOfType(typeof(LambdaExpression), add); 22 | Assert.AreEqual("(x, y) => (x + y)", add.ToString()); 23 | 24 | Expression addBody = add.Body; 25 | Assert.AreEqual(ExpressionType.Add, addBody.NodeType); 26 | Assert.IsInstanceOfType(typeof(BinaryExpression), addBody); 27 | Assert.AreEqual("(x + y)", addBody.ToString()); 28 | 29 | BinaryExpression addBodyBinary = (BinaryExpression)addBody; 30 | Assert.IsNull(addBodyBinary.Method); 31 | } 32 | 33 | [Test] 34 | public void LambdaExpressionFunctionDecompositionTest() 35 | { 36 | Expression> gamma = x => Fn.Gamma(x); 37 | 38 | Assert.AreEqual(ExpressionType.Lambda, gamma.NodeType); 39 | Assert.IsInstanceOfType(typeof(LambdaExpression), gamma); 40 | Assert.AreEqual("x => Gamma(x)", gamma.ToString()); 41 | 42 | Expression gammaBody = gamma.Body; 43 | Assert.AreEqual(ExpressionType.Call, gammaBody.NodeType); 44 | Assert.IsInstanceOfType(typeof(MethodCallExpression), gammaBody); 45 | Assert.AreEqual("Gamma(x)", gammaBody.ToString()); 46 | 47 | MethodCallExpression gammaBodyCall = (MethodCallExpression)gammaBody; 48 | Assert.IsNull(gammaBodyCall.Object); 49 | Assert.IsNotNull(gammaBodyCall.Method); 50 | Assert.AreEqual(typeof(Fn).GetMethod("Gamma"), gammaBodyCall.Method); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/MathMLContentMarkupFormatterTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Xml.Linq; 7 | using NUnit.Framework; 8 | 9 | namespace MathNet.Palladium.Test 10 | { 11 | using MathNet.ExpressionAlgebra.Output; 12 | using MathNet.Numerics; 13 | 14 | [TestFixture] 15 | public class MathMLContentMarkupFormatterTests 16 | { 17 | [Test] 18 | public void TestMMLCFormatterLinear() 19 | { 20 | Expression> lambda = x => 2 * x + 5; 21 | MathMLContentMarkupFormatter formatter = new MathMLContentMarkupFormatter(); 22 | XElement xml = formatter.Format(lambda.Body); 23 | Assert.AreEqual("2x5", xml.ToString(SaveOptions.DisableFormatting)); 24 | Assert.AreEqual("\r\n \r\n \r\n \r\n 2\r\n x\r\n \r\n 5\r\n", xml.ToString()); 25 | } 26 | 27 | [Test] 28 | public void TestMMLCFormatterTrigonometry() 29 | { 30 | Expression> lambda = x => Math.Sin(x) * Trig.HyperbolicCosecant(x); 31 | MathMLContentMarkupFormatter formatter = new MathMLContentMarkupFormatter(); 32 | XElement xml = formatter.Format(lambda.Body); 33 | Assert.AreEqual("xx", xml.ToString(SaveOptions.DisableFormatting)); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/MathNet.Palladium.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {AD594119-58D0-4BF2-921C-6EC1A5BD67A1} 9 | Library 10 | Properties 11 | MathNet.Palladium.Test 12 | MathNet.Palladium.Test 13 | v3.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | False 36 | ..\..\..\lib\MathNet.Iridium\MathNet.Iridium.dll 37 | 38 | 39 | False 40 | ..\..\..\lib\NUnit\nunit.framework.dll 41 | 42 | 43 | False 44 | ..\..\..\lib\NUnit\nunit.framework.extensions.dll 45 | 46 | 47 | 48 | 3.5 49 | 50 | 51 | 3.5 52 | 53 | 54 | 3.5 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {96F70E7A-18FD-4A26-B833-797791DC761A} 71 | MathNet.Palladium 72 | 73 | 74 | 75 | 82 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/OrderingTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NUnit.Framework; 6 | using System.Linq.Expressions; 7 | 8 | namespace MathNet.Palladium.Test 9 | { 10 | using MathNet.ExpressionAlgebra; 11 | using MathNet.Numerics; 12 | 13 | [TestFixture] 14 | public class OrderingTests 15 | { 16 | [Test] 17 | public void TestFrameworkStringCompare() 18 | { 19 | Assert.AreEqual(0, String.Compare("a", "a", StringComparison.Ordinal)); 20 | Assert.AreEqual(-1, String.Compare("a", "b", StringComparison.Ordinal)); 21 | Assert.AreEqual(1, String.Compare("b", "a", StringComparison.Ordinal)); 22 | Assert.AreEqual(32, String.Compare("a", "A", StringComparison.Ordinal)); 23 | Assert.AreEqual(-32, String.Compare("A", "a", StringComparison.Ordinal)); 24 | } 25 | 26 | [Test] 27 | public void TestParameterOrdering() 28 | { 29 | ParameterExpression a = Expression.Parameter(typeof(int), "a"); 30 | ParameterExpression b = Expression.Parameter(typeof(int), "b"); 31 | ParameterExpression c = Expression.Parameter(typeof(int), "c"); 32 | ParameterExpression B = Expression.Parameter(typeof(int), "B"); 33 | ParameterExpression C = Expression.Parameter(typeof(int), "C"); 34 | 35 | Assert.IsTrue(Ordering.Compare(a, b) < 0, "a < b"); 36 | Assert.IsTrue(Ordering.Compare(b, a) > 0, "b > a"); 37 | Assert.IsTrue(Ordering.Compare(a, c) < 0, "a < c"); 38 | Assert.IsTrue(Ordering.Compare(a, a) == 0, "a = a"); 39 | Assert.IsTrue(Ordering.Compare(c, c) == 0, "c = c"); 40 | 41 | Assert.IsTrue(Ordering.Compare(B, C) < 0, "B < C"); 42 | Assert.IsTrue(Ordering.Compare(C, B) > 0, "C > B"); 43 | Assert.IsTrue(Ordering.Compare(C, C) == 0, "C = C"); 44 | 45 | Assert.IsTrue(Ordering.Compare(b, B) > 0, "b > B"); 46 | Assert.IsTrue(Ordering.Compare(c, C) > 0, "c > C"); 47 | Assert.IsTrue(Ordering.Compare(c, B) > 0, "c > B"); 48 | } 49 | 50 | [Test] 51 | public void TestTypeOrdering() 52 | { 53 | ParameterExpression x = Expression.Parameter(typeof(int), "x"); 54 | ConstantExpression c = Expression.Constant(2); 55 | BinaryExpression sum = Expression.Add(x, c); 56 | BinaryExpression product = Expression.Multiply(x, c); 57 | Expression cos = Trigonometry.Cosine(x); 58 | Expression sin = Trigonometry.Sine(x); 59 | 60 | Assert.IsTrue(Ordering.Compare(c, x) < 0, "2 < x"); 61 | Assert.IsTrue(Ordering.Compare(x, c) > 0, "x > 2"); 62 | 63 | Assert.IsTrue(Ordering.Compare(c, sum) < 0, "2 < (2+x)"); 64 | Assert.IsTrue(Ordering.Compare(sum, c) > 0, "(2+x) > 2"); 65 | 66 | Assert.IsTrue(Ordering.Compare(x, sum) < 0, "x < (2+x)"); 67 | Assert.IsTrue(Ordering.Compare(sum, x) > 0, "(2+x) > x"); 68 | 69 | Assert.IsTrue(Ordering.Compare(x, sin) < 0, "x < sin(x)"); 70 | Assert.IsTrue(Ordering.Compare(sin, x) > 0, "sin(x) > x"); 71 | 72 | Assert.IsTrue(Ordering.Compare(product, sum) < 0, "2*x < (2+x)"); 73 | Assert.IsTrue(Ordering.Compare(sum, product) > 0, "(2+x) > 2*x"); 74 | 75 | Assert.IsTrue(Ordering.Compare(sum, sum) == 0, "(2+x) = (2+x)"); 76 | Assert.IsTrue(Ordering.Compare(product, product) == 0, "2*x = 2*x"); 77 | 78 | Assert.IsTrue(Ordering.Compare(product, sin) < 0, "2*x < sin(x)"); 79 | Assert.IsTrue(Ordering.Compare(sin, product) > 0, "sin(x) > 2*x"); 80 | 81 | Assert.IsTrue(Ordering.Compare(cos, sin) < 0, "cos(x) < sin(x)"); 82 | Assert.IsTrue(Ordering.Compare(sin, cos) > 0, "sin(x) > cos(x)"); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/MathNet.Palladium.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Math.NET Palladium Unit Tests")] 9 | [assembly: AssemblyDescription("http://mathnet.opensourcedotnet.info/")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Math.NET Project")] 12 | [assembly: AssemblyProduct("Math.NET")] 13 | [assembly: AssemblyCopyright("Copyright © 2009, Math.NET Project")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("903d64c6-307d-422c-9942-e54c72dcb779")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | --------------------------------------------------------------------------------