/// <summary> /// Initializes a new instance of the Fourier transformer with the given sign and normalization conventions. /// </summary> /// <param name="size">The series length of the transformer, which must be positive.</param> /// <param name="signConvention">The sign convention of the transformer.</param> /// <param name="normalizationConvention">The normalization convention of the transformer.</param> public Fourier(int size, FourierSign signConvention, FourierNormalization normalizationConvention) { if (size < 1) throw new YAMPArgumentRangeException("size", 0); this.size = size; this.signConvention = signConvention; this.normalizationConvention = normalizationConvention; // pre-compute the Nth complex roots of unity this.roots = Helpers.ComputeRoots(size, +1); // decompose the size into prime factors this.factors = Factors(size); // store a plan for the transform based on the prime factorization plan = new List<Transformlet>(); foreach (Factor factor in factors) { Transformlet t; switch (factor.Value) { // use a radix-specialized transformlet when available case 2: t = new RadixTwoTransformlet(size, roots); break; case 3: t = new RadixThreeTransformlet(size, roots); break; // eventually, we should make an optimized radix-4 transform case 5: t = new RadixFiveTransformlet(size, roots); break; case 7: t = new RadixSevenTransformlet(size, roots); break; case 11: case 13: // the base transformlet is R^2, but when R is small, this can still be faster than the Bluestein algorithm // timing measurements appear to indicate that this is the case for radix 11 and 13 // eventually, we should make optimized Winograd transformlets for these factors t = new Transformlet(factor.Value, size, roots); break; default: // for large factors with no available specialized transformlet, use the Bluestein algorithm t = new BluesteinTransformlet(factor.Value, size, roots); break; } t.Multiplicity = factor.Multiplicity; plan.Add(t); } }
/// <summary> /// Initializes a new instance of the Fourier transformer with the given sign and normalization conventions. /// </summary> /// <param name="size">The series length of the transformer, which must be positive.</param> /// <param name="signConvention">The sign convention of the transformer.</param> /// <param name="normalizationConvention">The normalization convention of the transformer.</param> /// <remarks> /// <para>There are multiple conventions for both the sign of the exponent and the overall normalization of /// Fourier transforms. The default conventions for some widely used software packages are summarized in the following /// table.</para> /// <table> /// <tr><th>Software</th><th>Sign</th><th>Normalization</th></tr> /// <tr><td>Meta.Numerics</td><td><see cref="FourierSign.Negative"/></td><td><see cref="FourierNormalization.None"/></td></tr> /// <tr><td>Matlab</td><td><see cref="FourierSign.Negative"/></td><td><see cref="FourierNormalization.None"/></td></tr> /// <tr><td>Mathmatica</td><td><see cref="FourierSign.Positive"/></td><td><see cref="FourierNormalization.Unitary"/></td></tr> /// <tr><td>Numerical Recipies</td><td><see cref="FourierSign.Positive"/></td><td><see cref="FourierNormalization.None"/></td></tr> /// </table> /// </remarks> public FourierTransformer(int size, FourierSign signConvention, FourierNormalization normalizationConvention) { if (size < 1) { throw new ArgumentOutOfRangeException("size"); } this.size = size; this.signConvention = signConvention; this.normalizationConvention = normalizationConvention; // pre-compute the Nth complex roots of unity this.roots = FourierAlgorithms.ComputeRoots(size, +1); // decompose the size into prime factors this.factors = AdvancedIntegerMath.Factor(size); // store a plan for the transform based on the prime factorization plan = new List <Transformlet>(); foreach (Element factor in factors) { Transformlet t; switch (factor.Value) { // use a radix-specialized transformlet when available case 2: t = new RadixTwoTransformlet(size, roots); break; case 3: t = new RadixThreeTransformlet(size, roots); break; // eventually, we should make an optimized radix-4 transform case 5: t = new RadixFiveTransformlet(size, roots); break; case 7: t = new RadixSevenTransformlet(size, roots); break; case 11: case 13: // the base transformlet is R^2, but when R is small, this can still be faster than the Bluestein algorithm // timing measurements appear to indicate that this is the case for radix 11 and 13 // eventually, we should make optimized Winograd transformlets for these factors t = new Transformlet(factor.Value, size, roots); break; default: // for large factors with no available specialized transformlet, use the Bluestein algorithm t = new BluesteinTransformlet(factor.Value, size, roots); break; } t.Multiplicity = factor.Multiplicity; /* * if ((factor.Value == 2) && (factor.Multiplicity % 2 == 0)) { * t = new RadixFourTransformlet(size, roots); * t.Multiplicity = factor.Multiplicity / 2; * } */ plan.Add(t); } }