How to compute sinh() (hyperbolical sine) or exp() (exponential function) in Monkey C

For a small project which involves computing tile coordinates for OpenStreetMap, I need a Math.sinh(Double) or Math.exp(Double) method to do conversion between Latitude and OSM tile coordinates.

Toolbox.Math does not offer either of these. Also implementing did not look as easy as I hoped, so I am wondering if anyone already solved a similar thing somewhere?

Alternatively I could do a lookup into a table, but this requires an array with a few thousand Double numbers, which quickly blows up memory usage and leads to spurious crashes, so also does not seem to be a viable option.

Any other ideas how to do a lookup-table for 16384 different input-values?

  • You can split the table to smaller portions, using some "hash", and put all of the values belonging to one hash to a smaller table, and store that as a json, and whenever you need a value 1st calculate the hash, then load the relevant json with loadResource().

    The hash could be something like: doubleValue.toString().hashCode() % 100

  • How about this (hopefully I'm not missing something):

    function exp(x as Numeric) as Decimal {
        return Math.pow(Math.E, x);
    }
    
    function sinh(x as Numeric) as Decimal {
        return (1 - exp(-2 * x)) / (2 * exp(-x));
    }

  • I need "x" in exp() to be a decimal, i.e. e^0.34, which seems to be fairly complicated to compute and is not available in Toolbox.Math.

    E.g. in Java it is "double exp(double a)" and "double sinh(double x)", implementation of exp() is in native code there and sinh a bit complicated, but I will try to convert it into Monkey C and see if I get it to work.

  • Thanks for the suggestion, that would be an option, but fairly complicated just for doing a single math computation.

    Currently I use a lookup table for "usual" values for me, i.e. northern hemisphere, and a rough estimation via a sum-formula for others, but accuracy is fairly limited by how many digits Double/Long can hold in Monkey C.

  • Decimal? Do you know how computers and calculations and floating point arithmetic works? You need to separate the math (calculation) part from the visual part. Do the calculations, you'll get a more or less precise result, then display it in whatever format you want: developer.garmin.com/.../Double.html

  • Ah, I mis-read "Numeric" as meaning "Integer-based type", not "Any numeric type including Float, Double, ..".

    Thanks, that makes it rather easy to do via Math.pow() as suggested above!

  • Decimal? Do you know how computers and calculations and floating point arithmetic works? You need to separate the math (calculation) part from the visual part.

    You seem to be assuming that they were referring to a display format when they said “decimal”, but I think they were referring to a number that can be represented as a decimal fraction (as opposed to an integer with no fractional part), which is perfectly valid to me.

    As seen above, even Monkey C uses the Decimal type to denote Float or Double, even though strictly speaking, you could argue it’s not “correct”.

    Even outside of the context of computing, it’s not uncommon to refer to “decimals” (as opposed to integers), when one might more correctly say “real number”. Sure, if we want to be extremely pedantic, we could say that “decimal numeral” refers to a notation (“display format”) as opposed to a type of number.

    Ah, I mis-read "Numeric" as meaning "Integer-based type", not "Any numeric type including Float, Double, ..".

    The type for integers in Monkey C is Integer haha.

    Maybe I should have linked the types before, but my intent was just to provide (hopefully) correct code, not explain every aspect of it. The reason I typed the input as Numeric is because Math.pow() accepts Numeric as input, and because it makes your functions as flexible as possible. 

    [https://developer.garmin.com/connect-iq/api-docs/Toybox/Lang.html]

    (Number is a 32-bit signed int and Long is a 64-bit signed int. Yes, it’s probably pretty unfortunate that Monkey C uses “Number” to refer to an integer type, especially when javascript uses it to refer to a floating-point type.)

    implementation of exp() is in native code there and sinh a bit complicated, but I will try to convert it into Monkey C and see if I get it to work.
    that makes it rather easy to do via Math.pow() as suggested above!

    Not to state what should be obvious now, but the code I posted is literally supposed to be the full Monkey C solution, not pseudocode, starter code or an example. I haven’t tested it, but I have no reason to think it shouldn’t work.