using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Azimuth; using Azimuth.Approximation; using Azimuth.Polynomials; using UnitTestSharp; namespace Azimuth.UnitTests.Approximation { public class PadeTests : TestFixture { public class RealTests : TestFixture { public void BookExample() { // From NUMERICAL RECIPES // 5.12 Pade Approximants. // ISBN 978-0-521-88407-5 var coefficients = new DenseVector(new Scalar[] { 2, 1.0/9, 1.0/81, -49.0/8748, 175.0/78732, }); var rational = Pade.Solve(coefficients); Func func = x => Math.Pow(7 + Math.Pow(1 + x, 4.0/3), 1.0/3); CheckEqual(func(0), rational.Evaluate(0)); Check(Scalar.FuzzyEquality(func(1), rational.Evaluate(1), epsilon: 0.0001)); Check(Scalar.FuzzyEquality(func(2), rational.Evaluate(2), epsilon: 0.001)); Check(Scalar.FuzzyEquality(func(3), rational.Evaluate(3), epsilon: 0.002)); Check(Scalar.FuzzyEquality(func(4), rational.Evaluate(4), epsilon: 0.004)); Check(Scalar.FuzzyEquality(func(5), rational.Evaluate(4), epsilon: 0.05)); } public void NoTerms() { CheckThrow(typeof(ArgumentException)); Pade.Solve(new DenseVector(new Scalar[] { })); } public void SingleTerm() { var rational = Pade.Solve(new DenseVector(new Scalar[] { 2, })); CheckEqual(2, rational.Evaluate(2)); } public void TwoTerms() { // A constant divided by a constant is still just a constant. var rational = Pade.Solve(new DenseVector(new Scalar[] { 2, 1.0/9, })); CheckEqual(2, rational.Evaluate(2)); } public void ThreeTerms() { var rational = Pade.Solve(new DenseVector(new Scalar[] { 2, 1.0/9, 1.0/81, })); Check(Scalar.FuzzyEquality(2.24, rational.Evaluate(2), epsilon: 0.1)); } } public class ComplexTests : TestFixture { [IgnoreTest] public void CheckFuzzy(Complex a, Complex b, Scalar epsilon) { CheckLess((double)(a - b).Magnitude(), (double)epsilon); } public void Basic() { // First few terms of the power series of i * exp(z) var coefficients = new ComplexDenseVector(new Complex[] { (0, 1), (0, 1), (0, 1.0/2), (0, 1.0/6), (0, 1.0/24), (0, 1.0/120), (0, 1.0/720), (0, 1.0/5040), }); ComplexRational rational = Pade.Solve(coefficients); CheckEqual((0, 1), rational.Evaluate(0)); CheckFuzzy((0, 1.1051709180756476), rational.Evaluate(0.1), 0.00001); CheckFuzzy((0, 1.2840254166877414), rational.Evaluate(0.25), 0.0001); CheckFuzzy((0, 1.3909681284637802), rational.Evaluate(0.33), 0.0002); CheckFuzzy((-0.0998334166468281, 0.9950041652780257), rational.Evaluate((0, 0.1)), 0.00001); CheckFuzzy((-0.2474039592545229, 0.9689124217106447), rational.Evaluate((0, 0.25)), 0.0001); CheckFuzzy((-0.3240430283948683, 0.9460423435283869), rational.Evaluate((0, 0.33)), 0.0002); } public void NoTerms() { CheckThrow(typeof(ArgumentException)); Pade.Solve(new ComplexDenseVector(new Complex[] { })); } public void SingleTerm() { ComplexRational rational = Pade.Solve(new ComplexDenseVector(new Complex[] { (3, 4), })); CheckEqual((3, 4), rational.Evaluate(2)); } public void TwoTerms() { // A constant divided by a constant is still just a constant. ComplexRational rational = Pade.Solve(new ComplexDenseVector(new Complex[] { (3, 4), (5, -6), })); CheckEqual((3, 4), rational.Evaluate(2)); } public void ThreeTerms() { ComplexRational rational = Pade.Solve(new ComplexDenseVector(new Complex[] { (0, 1), (0, 1), (0, 1.0/2), })); CheckEqual((0, 1.1), rational.Evaluate(0.1)); } } } }