PI := 3.14159265358979323 E := 2.718281828459045235360287471352 # abs(x) # x: number # Get the absolute value of a number. If x is negative, the returned # value is positive and equal to `-x`. If x is positive or zero, the # returned value is x. fn absf(x: float) -> float { # if the number is negative if x < 0.0 { # negate it so it's positive return -x } return x } fn absi(n: int) -> int { if n < 0 { -n } else { n } } DERIVE_DX := 0.00000001 fn derive(f: fn(float) -> float, x: float) -> float { return (f(x + DERIVE_DX) - f(x))/DERIVE_DX } NEWTONS_ACC := 0.000000000001 fn newtons(f: fn(float) -> float) -> float { pg := 0.0 g := 1.0 while absf(g - pg) > NEWTONS_ACC { pg = g g = pg - f(pg) / derive(f, pg) } return g } MAX_SQRT_DX := 0.0000001 # sqrt(x) # x: number # Calculate the approximate square root using newton's method until # the accuracy has increased by less than the variable `MAX_SQRT_DX`. fn sqrt(x: float) -> float { ng := x g := 1.0 while absf(g - ng) > MAX_SQRT_DX { g = ng # create new guess ng = (g + x / g) / 2.0 } g } # floor(x) # x: number # Return the whole number part of the number. if x is a whole number, # the returned value is x. If x is not a whole number, the closest # whole number which is less than or equal to x is returned. # ceil(x) # x: number # Return the whole number part of the number. if x is a whole number, # the returned value is x. If x is not a whole number, the closest # whole number which is greater than or equal to x is returned. # round(x) # x: number # Return the closest whole number to the value x. fn round(x: float) -> float { f := floor(x) if x - f > 0.5 { return f + 1.0 } return f } # mod(x, n) # x: number; any number # n: number; the number to divide by # Return the rest from a division of x by n. fn mod(x: float, n: float) -> float { if x == 0.0 { return 0.0 } if x < 0.0 { while x + n <= 0.0 { x = x + n } } else { while x - n >= 0.0 { x = x - n } } return x } # sm_exp(x) # x: number; any number between 0 and 1 # Get an approximate value of e raised to the power of x. # This value is only reasonable if 0 float { p_tot := 0.0 tot := 1.0 n := 1 x_pow := x f := 1.0 while absf(tot - p_tot) > SM_EXP_ACC { p_tot = tot t := x_pow / f tot = tot + t f = f * float(n+1) x_pow = x_pow * x n = n + 1 } return tot } # exp(x) # x: number; any number # Get an approximate value of e raised to the power of x. fn exp(x: float) -> float { n := absf(x) tot := 1.0 while n >= 1.0 { tot = tot * E n = n - 1.0 } if n > 0.0 { tot = tot * sm_exp(n) } if x < 0.0 { 1.0/tot } else { tot } } # ln(x) # x: number; any number # Get the approximate value of the natural logarithm # This function uses newton's method to approximate. LN_ACC := 0.0000000001 fn ln(x: float) -> float { pg := 0.0 g := 1.0 while absf(pg - g) > LN_ACC { pg = g g = pg + x / exp(pg) - 1.0 } return g } # pow(x, p) # x: number; any number. The base # p: number; the value of the exponent # Raise any number to any power (x^p) fn pow(x: float, p: float) -> float { return exp(p*ln(x)) } # log(x, b) # x: number; any number greater than 0 # b: number; any number as the base # Calculate the approximate value of the logarithm # of a with b as base. LOG_ACC := 0.0000001 fn log(a: float, b: float) -> float { ln_b := ln(b) pg := 0.0 g := 1.0 while absf(g - pg) > LOG_ACC { pg = g g = pg - 1.0/ln_b - a/(ln_b*pow(b, pg)) } return g } # sin(x) # x: number; an angle in radians # Get the sine of an angle (in radians). https://en.wikipedia.org/wiki/Sine_and_cosine # TODO: use hashmap with precomputed values and linear interpolation fn sin(x: float) -> float { f := 1.0 x = mod(x, 2.0*PI) if x > PI { x = PI - x f = -1.0 } # compute sine with a taylor series mock function of sine (valid between -pi and +pi) tot := x l := 1.0 i := 1.0 s := -1.0 while i <= 19.0 { i = i + 2.0 l = s * l * x / i / (i-1.0) tot = tot + l s = -s } return tot*f } # cos(x) # x: number; an angle in radians # Get the cosine of an angle (in radians). https://en.wikipedia.org/wiki/Sine_and_cosine fn cos(x: float) -> float { # todo 0.0 } # tan(x) # x: number; an angle in radians # Get the tangent of an angle. https://en.wikipedia.org/wiki/Tangent fn tan(x: float) -> float { # todo 0.0 } (E:, PI:, sqrt:, log:, ln:, exp:, pow:)