Making a math project in unity. Trying to make a derivative function but can't get it right.

I’m trying to make a derivative function for complex numbers (that’s why I’m using Vector2 instead of float), but it always results in a Stack Overflow Exception error. can someone explain what is the problem and how to fix it?

Func<Vector2, Vector2> derivative(Func<Vector2, Vector2> f, int n)
    {
        Func<Vector2, Vector2> currentFunc = f;
        for (int i = 1; i <= n; i++)
        {
            currentFunc = z => (currentFunc(z + new Vector2(Mathf.Epsilon, Mathf.Epsilon)) - currentFunc(z)) / Mathf.Epsilon;
        }
        return currentFunc;
    }

Sounds like perhaps you’re calling yourself recursively, almost certainly on line 6 where you wrap the delegate with a previous delegate, then return it.

Attach the debugger, put a breakpoint in and let 'er rip.

To understand recursion, you must first understand recursion.

2 Likes

and the other one: “once you understand the recursion, it’s recursively understood”

1 Like

Your issue is this part:

currentFunc = z => (currentFunc(

The main issue is that you create a “closure” and closures capture variables, not values. That means the “currentFunc” inside the closure is the same variable as the one you assign your closure to. So you have an infinite recursion as the method / delegate you call inside your closure will be the closure itself. The only way to break this is to create a new variable inside the for loop like this:

 Func<Vector2, Vector2> currentFunc = f;
        for (int i = 1; i <= n; i++)
        {
            Func<Vector2, Vector2> tmp = currentFunc;
            currentFunc = z => (tmp(z + new Vector2(Mathf.Epsilon, Mathf.Epsilon)) - tmp(z)) / Mathf.Epsilon;
        }
        return currentFunc;
4 Likes

Once you solve your recursion issue you will likely face the next problem. I doubt trying to calculate derivative of function by naively using (f(x+epsilon)-f(x))/epsilon will produce meaningful result. As the epsilon approaches zero, result will approach the derivate of function, but only up to a certain point after which you will hit the precision limits of floating point and for any nontrivial calculation you will likely get garbage.

Mathf.Epsilon is smallest (closest to zero not biggest negative) value that floating point numbers can represent. This means that this also smallest step (in the best cases) for changes in function output. If you wanted to calculate derivative for for f(x)=1.5x near zero, you would get either 1 or 2 since floating point can only represent 0 * eps, 1eps and 2eps.
That was the best case scenario. Away from 0, difference between two constitutive floating point numbers is much bigger than Mathf.Epsilon. This means that for most floating point numbers x+eps = x, and I am not speaking abstractly, adding Mathf.Epsilon to a variable will leave it’s bits unchanged. In case of derivative calculations that means you will get 0, since f(x+eps)-f(x)=f(x)-f(x)=0 for all x > 1e-29.

Numbers don’t even have to be very big for this to be a problem. Next floating point number after 1 is 1.00000011921 or ~ 1+1.19e-7. But Mathf.Epsilon is 1.40129846432e-45. That’s already 10^38 times bigger step by just going from 0 to 1.

3 Likes

It’s funny coz it’s true.

Anyway, with so many radically different takes on what’s wrong here, I think OP is a cowboy :slight_smile: (no offense)

2 Likes

As a great man once observed,

“Think of [floating point] as JPEG of numbers.” - orionsyndrome on the Unity3D Forums

:slight_smile:

3 Likes