├── .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 |
--------------------------------------------------------------------------------