• I'm using formulas to gernerate a response curve and when I use the following function it gives the wrong answer when I use the compiled keyword. It works fine without being compiled, i was wondering if there was a known issue with the Math library or if there is a simple fix

    function F(x){
    "compiled";
    return 1/(1.13+Math.exp(-8.0*(x-0.54)))+0.14;
    }

    i'm running the code on the original espruino with the latest firmware.

  • Hi - Thanks - I've just reproduced it here. It seems to be something to do with floating point numbers when used as function arguments.

    Even something like this fails:

    function F(x){
      "compiled";
      print (x-0.54);
    }
    
    function G(x){
      print (x-0.54);
    }
    
    for (var i=0;i<10;i++) {
      print("----",i);
      F(i);G(i);
    }
    

    I'll look into this now and see if it's an easy fix

  • Ok - try now!

    Turns out it was two issues :)

    • On nRF52 (which I was using initially) we switched to use the FPU a while back and that messed up how doubles are passed - so code using doubles didn't work reliably. But you wouldn't have hit that (probably the code above would have worked fine on the original Espruino)
    • The type handling of the unary minus (for -8.0) was wrong - and I think that's what hit you

    Running:

    function F(x){
    "compiled";
    return 1/(1.13+Math.exp(-8.0*(x-0.54)))+0.14;
    }
    function G(x){
    return 1/(1.13+Math.exp(-8.0*(x-0.54)))+0.14;
    }
    for (var i=0;i<10;i++) {
      print(F(i),G(i));
    }
    

    Now shows the right values for me

  • we switched to use the FPU a while back and that messed up how doubles are passed

    the -mfloat-abi=softfp was there for a reason so that float could be passed like ints in R0-R4 so that InlineC code could receive float arguments (like this). Is there a reason -mfloat-abi=hard is needed?

    THe -mfloat-abi=softfp -mfpu=fpv4-sp-d16 is a compromise so that both code using softfloats and code with fpu instructions could be linked together.

  • Was talking about this change https://github.com/gfwilliams/EspruinoCompiler/commit/d5534b66ec8e523dfadecc0bdf100716243d06c2 I was thinking espruino itself is build with that convention too?

    Oh just checked and for nrf52 it is not while for stm32 it is!
    https://github.com/espruino/Espruino/search?q=mfpu%3Dfpv4-sp-d16&type=code

    make/family/NRF52.make
    ARCHFLAGS = -mcpu=cortex-m4 -mthumb -mabi=aapcs -mfloat-abi=hard -mfpu=fpv4-sp-d16
    make/family/STM32F4.make
    ARCHFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp

    I'd vote for softfp calling convention as the performance difference is minimal especially when javascript uses doubles and software implementation anyway.

  • so that float could be passed like ints in R0-R4 so that InlineC code could receive float arguments

    Ahh - yes, this makes sense - although since sending floats as function arguments isn't something that's really supported (it has to be done by a bit of a hack) it probably explains why nobody hit this before. I wasn't aware that changing from soft/hard actually changed the argument passing behaviour. nRF52 builds have been like this since at least 2017!!

    Changing from hard -> softfp actually seems to shave a few bytes off the firmware size, so I've committed a change - however it's a tricky one - it doesn't really help anyone on nRF52 who is using the firmware that's out there now. They'll still have the issue using any floating point numbers in code.

    I guess maybe I'll wait until 2v15 gets released and then switch the compiler back to using softfp

  • Changing from hard -> softfp actually seems to shave a few bytes off the firmware size

    yes, thanks for testing, I also made a build and saw that (292300 bytes softfp vs 293468 bytes hardfp on MDBT42Q build) but did not actually test in the device. btw noticed there is also -DFLOAT_ABI_HARD few lines below in the makefile possibly for nordic SDK but keeping it there or removing it did not change the size of build at all so not sure it is doing anything

  • although since sending floats as function arguments isn't something that's really supported (it has to be done by a bit of a hack)

    in inlineC it is definitely a hack as the header clearly says int but code uses float in declaration and it works thanks to softfp calling convention

    var c = E.compiledC(`
    // int fadd(int,int)
    // int fmul(int,int)
    float fadd(float f1,float f2){
    return f1+f2;
    }
    float fmul(float f1,float f2){
    return f1*f2;
    }
    

    so if softfp build will work fine and will stay, it might make sense to allow float keyword also in header comment declaration of InlineC methods

    var c = E.compiledC(`
    // float fadd(float,float)
    

    to make it less hacky

  • Thank you for the quick response, I will try again and see what happens.

  • just tested it extensivly and it works like a charm! thank you.

  • Great! Glad it's all sorted!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

issue with "compliling" code with Math expressions

Posted by Avatar for ioi-655321 @ioi-655321

Actions