Main Site Documentation

Error using MathEx Class


#1

Hi :
When I am testing the MathEx class, it shows some error.
Any one could help me?
Please see the attached file.
Thank you very much.

Lin


#2

Are you using the emulator?


#3

YES I use the emulator


#4

The MathEx class is implemented in native code on the USBizi chipset, so it wont work on the emulator.


#5

oh so it’s not the version from Elze Kool? I didn’t know that…


#6

No it is not, this is GHI’s implementation. So, it is native and it is very fast :slight_smile:


#7

One thing to remeber though
if you use microsoft math routines some are fixed point math

it threw me the first time I used them


#8

Gus, if this is a GHI implementation, can the team add a few overloads to some of the functions?

For example I need an Abs function that takes doubles, but MathEx takes only ints. Not a bit deal though, Abs is easy to implement. But you guys might wanna take a look at other functions too.


#9

Its just microsoft with fixed point math (namely cos and sin)

GHI MathEx are all floating point…

agreed!! abs isnt one of them…


#10

We omitted several functions. We only included the ones that are necessary and it is bad to do them in managed code.


#11

Thanks, its work.
I am writing a FFT function using the managed code.


#12

I personally really want FFT. You will get a lot of points from me if you do it :wink:


#13

Why not also include an advanced library?


#14

What do you mean? We basically added the ones that you can’t do in managed code or it is bad to do them in managed code. Anything else can be added easily in C#. This way, users can add what fits their needs best instead of us guessing what users needs, especially that each application have different needs.


#15

Below is a FFT class I used in a project. It has been a long time since I used the code, so I can’t answer any questions about it. It is for full .NET so a little change is necessary for the typed list.

Use at your own risk.

using System;
using System.Collections.Generic;
using System.Text;

namespace XXXAlgorithmLibrary
{
    public class FourierTransform
    {
        public class FFT_Datapoint
        {
            public double DB { get; set; }
            public double Real{ get; set; }
            public double Imag { get; set; }
            public double Magnitude { get; private set; }

            public FFT_Datapoint(double db, double real, double imag)
            {
                DB = db;
                Real = real;
                Imag = imag;
                Magnitude = Math.Sqrt((Real * Real) + (Imag * Imag));
            }
        }

        static private int n, nu;

        static private int BitReverse(int j)
        {
            int j2;
            int j1 = j;
            int k = 0;
            for (int i = 1; i <= nu; i++)
            {
                j2 = j1 / 2;
                k = 2 * k + j1 - 2 * j2;
                j1 = j2;
            }
            return k;
        }

        static public void _FFT(double[] x, out double[] xre, out double[] xim)
        {
            // Assume n is a power of 2
            n = x.Length;
            nu = (int)(Math.Log(n) / Math.Log(2));
            int n2 = n / 2;
            int nu1 = nu - 1;
            xre = new double[n];
            xim = new double[n];
            double tr, ti, p, arg, c, s;
            for (int i = 0; i < n; i++)
            {
                xre[i] = x[i];
                xim[i] = 0.0f;
            }
            int k = 0;
            for (int l = 1; l <= nu; l++)
            {
                while (k < n)
                {
                    for (int i = 1; i <= n2; i++)
                    {
                        p = BitReverse(k >> nu1);
                        arg = 2 * (double)Math.PI * p / n;
                        c = (double)Math.Cos(arg);
                        s = (double)Math.Sin(arg);
                        tr = xre[k + n2] * c + xim[k + n2] * s;
                        ti = xim[k + n2] * c - xre[k + n2] * s;
                        xre[k + n2] = xre[k] - tr;
                        xim[k + n2] = xim[k] - ti;
                        xre[k] += tr;
                        xim[k] += ti;
                        k++;
                    }
                    k += n2;
                }
                k = 0;
                nu1--;
                n2 = n2 / 2;
            }
            k = 0;
            int r;
            while (k < n)
            {
                r = BitReverse(k);
                if (r > k)
                {
                    tr = xre[k];
                    ti = xim[k];
                    xre[k] = xre[r];
                    xim[k] = xim[r];
                    xre[r] = tr;
                    xim[r] = ti;
                }
                k++;
            }
        }

        static public double[] FFTDb(double[] x)
        {
            double[] xre = null;
            double[] xim = null;
            int n = x.Length;

            _FFT(x, out xre, out xim);
            double[] decibel = new double[n/2];

            for (int i = 0; i < n / 2; i++)
                decibel[i] = 10.0 * Math.Log10((float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i]))));
            return decibel;
        }

        static public List<FFT_Datapoint> FFT(double[] x)
        {
            List<FFT_Datapoint> rtn = new List<FFT_Datapoint>();
            double[] xre = null;
            double[] xim = null;
            int n = x.Length;

            _FFT(x, out xre, out xim);
            for (int i = 0; i < n / 2; i++)
            {
                double db = 10.0 * Math.Log10((float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i]))));
                rtn.Add(new FFT_Datapoint(db, xre[i], xim[i]));
            }
            return rtn;
        }
    }
}


#16

My idea is to take an ideal FFT code in C# and then move it to native code so it runs faster. But before we do any of that work, I would love to see some FFT working on a FEZ and also an example on how it would be useful to others. I need these few things to be able to convince GHI to add FFT natively to the firmware :wink:


#17

Thanks for Mike’s code, I also find some C# codes, I will also test yours and let you know how it workiing.
To Gus:
You are right. We need tell you why the FFT is important to convince GHI to add FFT natively to the firmware. For example, my research need using the accelerometer to get the acceleration with high sample rate (maybe 200Hz), then send it back by Zigbee. It should be high power consumption for this great amount data. So, if we can transform to frequency domain then send the data with desired frequency range, we can save power. For other application, some application for analyzing the ECG data should have the FFT function. I think DSP Class is useful for many applications. But I can’t find any DSP related .NET MF Class, so we need did it by our self.


#18

I have tested the Mike’s code, It can work on FEZ.


#19

If your wanting to to practical applications of DSP then you need to get this book: http://www.dspguide.com/ , it is also available for free download.


#20

I just ran into this same issue - the MathEx class is not unit testable without the hardware.

If you are moving to more functionality into the firmware, I highly suggest releasing a custom emulator, or at least making interfaces for them. Remember that untestable code is not well designed code, and the .Net framework (full and micro) is full of this. Please do not continue this poor practice.

Much like all the input and output classes, I ended up injecting the math class and created a mock mathEx for my tests. A bit of work, but worth the effort to have testable code.


public interface IMath
    {
        double E { get; }
        double PI { get; }
        
        double Acos(double d);
        double Asin(double d);
        double Atan(double d);
        ........
}

public class MathT : IMath
    {
        public double E
        {
            get { return MathEx.E; }
        }

        public double PI
        {
            get { return MathEx.PI; }
        }

        public double Acos(double d)
        {
            return MathEx.Acos(d);
        }

        ............
}


public class Goertzel
    {
        private IMath _math;

        public Goertzel(int rate, int len, float freq, IMath math)
        {
            _math = math;

 
            double w = ( 2.0 * _math.PI * freq / rate);
            .......
         }
}