#Inconsistency in derivative calculation

75 messages · Page 1 of 1 (latest)

sand lance
#
//Computes the sum of a series.Which series is it,though...
//tip:don't set both compile time flags,though apparently ChatGPT thinks
//i could use a "mixed partial derivative" or smth...
//derivatives not tested..yet.
double FUNC_NAME(double coeff[], double th, double ph, int level) {
    double cos_th = cos(th), nsin_th = -sin(th);
    double rt2 = 0, zero = 0;
    double cosph[MAX_SH_LEVEL + 1] = { 1 };
    double sinph[MAX_SH_LEVEL + 1] = { 0 };
    double expct[MAX_SH_LEVEL + 1] = { 1 };
    double expox[MAX_SH_LEVEL + 1] = { 1 };
#ifdef DERIVATIVE_TH
    double dexpct[MAX_SH_LEVEL + 1] = { 0 };
    double dexpox[MAX_SH_LEVEL + 1] = { 0 };
#endif
    double preve = 1, prevx = 1;
    for (int m = 1; m <= level; ++m) {
#ifdef DERIVATIVE_PH
        cosph[m] = -m * sin(m * ph);
        sinph[m] = m * cos(m * ph);
#else
        cosph[m] = cos(m * ph);
        sinph[m] = sin(m * ph);
#endif
#ifdef DERIVATIVE_TH
        dexpct[m] = preve * nsin_th * m;
        dexpox[m] = -prevx * cos_th * m;
#endif
        preve = expct[m] = preve * cos_th;
        prevx = expox[m] = prevx * nsin_th;
    }
    double* lpc = lpoly_coeff, * lpn = lpoly_norm, * tc = coeff;
    for (int l = 0; l <= level; l++) {
        double rest = 0;
        for (int i = 0; i < l + 1; i++) {
            rest += *(lpc++) * expct[i];
        }
        zero += *(lpn++) * *tc * rest;
        for (int abs_m = 1; abs_m <= l; abs_m++) {
            rest = 0;
            double E = expox[abs_m];
#ifdef DERIVATIVE_TH
            double dE = dexpox[abs_m];
#endif
            for (int i = 0; i < l + 1; i++) {
#ifdef DERIVATIVE_TH
                rest += *(lpc++) * (expct[i] * dE + dexpct[i] * E);//product rule.annoying here...
#else
                rest += *(lpc++) * expct[i] * E;
#endif
            }
            double nplm = rest * *(lpn++);
            rt2 += nplm * (tc[abs_m] * cosph[abs_m] + tc[-abs_m] * sinph[abs_m]);
        }
        tc += 2 * l + 2;
    }
    return SQRT_2 * rt2 + zero;
}
ionic reefBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

sand lance
#

the derivative functions make completely different results than using numerical methods to compute the derivative

#

like it isn't a problem with the epsilon in the numerical method,it just converges to a different self-consistent value than the derivative function.

#

(don't try to find problems about the non-derivative version of the function not doing what it should,because then the derivative version will too,and it would still be consistent)

haughty ivy
#

So are you saying you made this code or ChatGPT did?

haughty ivy
#

But this code can be improved in a number of ways that will make this a lot more testable:

  • Remove all the prepocessor bollocks and change them for template boolean flags and if constexpr
  • Define the constants inside the scope rather than using global variables, use constants out of <numbers> header
  • Don't use a raw style c-arrays, use a span instead where the extent are with the type and are less prone to buffer overflow
  • Split the inner logic into it's own functions, this will make the code a lot more readable and easier to comprehend.

The will hopefully become more clear during your refactoring, I have an idea of what it is but really, me telling you won't help, and you really need to know exacty what is going on in this function rather than asking chatgpt

sand lance
sand lance
# haughty ivy But this code can be improved in a number of ways that will make this a lot more...
  • yeah,right,thta would be a good method.I didn't know that templates could be used to compile-time modify code when I wrote this.
  • which ones?sqrt_2?
  • the code REALLY needs performance,and BOFs don't happen here because I checked meticulously that all those iterator iteration matches exactly with how I precomputed the arrays,so here it is fine but yeah next time i'll use less error-prone types.
  • the code REALLY needs performance,either I suck at memory management or millions of function calls per 1/60 of asecond costs a lot of time.
#

The main problem is self-inconsistency,where the problem is that the reported derivatives are not actually the derivatives of the function.Since the macros are very simple(and do not involve change of control flow),it should be easy to see if the derivatives would match.

#

The problem is that they don't when they should.I checked the simpler d/dph,and it has nothing wrong with it apart from that it is wrong.

#

The function is also a pure function despite the global coefficient arrays,so there aren't any goofy self-modifying arrays that are actually related to th and ph and so have to be differentiated while I assumed that they are constants.

sand lance
#

alr i did some pen and papering

#
rest = 0;
for (int i = 0; i < l + 1; i++) {
            rest += *(lpc++) * expct[i];
        }

should be

rest = 0;
        for (int i = 0; i < l + 1; i++) {
#ifdef DERIVATIVE_TH
            rest += *(lpc++) * dexpct[i];
#else
            rest += *(lpc++) * expct[i];
#endif
        }

(ignore the indentation

ionic reefBOT
#

@sand lance

It looks like you may have code formatting errors in your message

Note: Make sure to use back-ticks (`) and not quotes (')
Note: Make sure to specify a highlighting language, e.g. `cpp`, after the back-ticks

Markup

```cpp
int main() {}
```

Result
int main() {}
sand lance
#

also zero should hold the value 0 if derivative ph

sand lance
#

yayyy now my code obeys conservation of energy!!

#

(more datapoints not shown)

#

(this is ofc not equal,because i did not count angular kinetic energy)

#

(also every time the failsafe in the collision checking function runs,it teleports the object in a direction that's usually mostly up.this gives it free gravitational potential energy)

twilit galleon
#

use dual numbers

sand lance
#

wait what

#

those numbers that are like "imaginary numbers but square to zero"?

twilit galleon
#

kinda

sand lance
#

ohh automatic differentiation that's where you're going?

twilit galleon
#

yes.

#

its far easier to do it that way

#

derivation is trivial to just hardcode

sand lance
#

ohh so it's like how you use quaternions for rotation

#

binomial expansion of dual numbers(well,not quite,as the actually numbers it would be a "monomial expansion" but)

#

happens to have the same structure as differentiation

#

alr so every type of complex number i know can be represented as a matrix then

#

ig i'll use those numbers next time i need differentiation

#

this time it turned out the two problems were

  1. constant term not differentiated.remember linearity doesn't mean ignore constants,it means ignore constants if they multiply with exactly one(1) non-constant.otherwise you either remove the term or use the product rule properly in its full form.this is also why newton's law sometimes fails btw.
  2. initially i made a mistake opposite to (1) where I neglected to use the product rule.so then i used the product rule,but that requires two things for each expression instead of one,so i undid the part where i substituted the original with a derivative,and so another unrelated part happened to get the original while it didn't need a product rule and so got a derivative.
sand lance
#

like computer function not math function

twilit galleon
sand lance
#

oh yea that's just the product rule

twilit galleon
#

you dont store the formula, you store the values of the function and the derivative

twilit galleon
sand lance
#

and everything else is done by the linearity

sand lance
twilit galleon
#
Dual sin(const Dual& lhs){
  return Dual(sin(y), cos(y));
}
sand lance
#

(i mean to be fair computing models in run time 60 FPS isn't exactly what one usually does)

#

so i had to precompute two kinds of coefficients(one for the normalization the other for the associated legendre polynomials,they are called polynomials so they also need coefficients)

#

and substitute the l poly calculation so i could make optimizations such as not computing (-sin(th)**m was every call to the l poly function and not forgetting trig identities such as sqrt(1-cos2(x))=cos(x) (yes,that is exactly why that array is expox,it stood for Ox which looked like the APL operator for sqrt(1-x*x) iirc)

sand lance
#

idk if they would be optimized as constexpr or smth

#

so kinda worried about a ton of copying and other unnecessary memory operations

twilit galleon
#

c++26 cmath is constexpr

sand lance
#

ohh

twilit galleon
#

gcc's was constexpr before

sand lance
#

turns out my settings didn't support it

#

oh is it still beta?

#

oh ofc it is

#

it's not 2026 yet lol

twilit galleon
#

...

sand lance
#

wait it already is?

twilit galleon
#

or im not sure it is even a thing in standard c++

sand lance
#

nah didn't think so

#

just tested

#

ah numbers::sqrt2_v<double>

twilit galleon
#

i mean im sure i used the macros SQRT_2 but i cant find it on cppref

twilit galleon
twilit galleon
#

nah

sand lance
#

wait you can have non-function templates like that?

twilit galleon
#

yes