diff options
Diffstat (limited to 'apps/plugins/lua/include_lua/math_ex.lua')
| -rw-r--r-- | apps/plugins/lua/include_lua/math_ex.lua | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/apps/plugins/lua/include_lua/math_ex.lua b/apps/plugins/lua/include_lua/math_ex.lua new file mode 100644 index 0000000..c0bf55c --- /dev/null +++ b/apps/plugins/lua/include_lua/math_ex.lua @@ -0,0 +1,158 @@ +--[[ Lua Missing Math functions +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2017 William Wilgus + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +]] + +--[[ Exposed Functions + + _math.clamp + _math.clamp_roll + _math.d_sin + _math.d_cos + _math.d_tan + _math.i_sqrt + +]] + +local _math = {} do + + -- internal constants + local _NIL = nil -- _NIL placeholder + + -- clamps value to >= min and <= max + local function clamp(iVal, iMin, iMax) + if iMin > iMax then + local swap = iMin + iMin, iMax = iMax, swap + end + + if iVal < iMin then + return iMin + elseif iVal < iMax then + return iVal + end + + return iMax + end + + -- clamps value to >= min and <= max rolls over to opposite + local function clamp_roll(iVal, iMin, iMax) + if iMin > iMax then + local swap = iMin + iMin, iMax = iMax, swap + end + + if iVal < iMin then + iVal = iMax + elseif iVal > iMax then + iVal = iMin + end + + return iVal + end + + local function i_sqrt(n) + -- Newtons square root approximation + if n < 2 then return n end + local g = n / 2 + local l = 1 + + for c = 1, 25 do -- if l,g haven't converged after 25 iterations quit + + l = (n / g + g)/ 2 + g = (n / l + l)/ 2 + + if g == l then return g end + end + + -- check for period-two cycle between g and l + if g - l == 1 then + return l + elseif l - g == 1 then + return g + end + + return _NIL + end + + local function d_sin(iDeg, bExtraPrecision) + --[[ values are returned multiplied by 10000 + II | I 180-90 | 90-0 + ---(--)--- -------(--)------- + III | IV 180-270 | 270-360 + + sine is only positive in quadrants I , II => 0 - 180 degrees + sine 180-360 degrees is a reflection of sine 0-180 + Bhaskara I's sine approximation formula isn't overly accurate + but it is close enough for rough image work. + ]] + local sign, x + -- no negative angles -10 degrees = 350 degrees + if iDeg < 0 then + x = 360 + (iDeg % 360) + else --keep rotation in 0-360 range + x = iDeg % 360 + end + + -- reflect II & I onto III & IV + if x > 180 then + sign = -1 + x = x % 180 + else + sign = 1 + end + + local x1 = x * (180 - x) + + if bExtraPrecision then -- ~halves the largest errors + if x <= 22 or x >= 158 then + return sign * 39818 * x1 / (40497 - x1) + elseif (x >= 40 and x <= 56) or (x > 124 and x < 140) then + return sign * 40002 * x1 / (40450 - x1) + elseif (x > 31 and x < 71) or (x > 109 and x < 150) then + return sign * 40009 * x1 / (40470 - x1) + end + end + + --multiplied by 10000 so no decimal in results (RB LUA is integer only) + return sign * 40000 * x1 / (40497 - x1) + end + + local function d_cos(iDeg, bExtraPrecision) + --cos is just sine shifed by 90 degrees CCW + return d_sin(90 - iDeg, bExtraPrecision) + end + + local function d_tan(iDeg, bExtraPrecision) + --tan = sin0 / cos0 + return (d_sin(iDeg, bExtraPrecision) * 10000 / d_sin(90 - iDeg, bExtraPrecision)) + end + + --expose functions to the outside through _math table + _math.clamp = clamp + _math.clamp_roll = clamp_roll + _math.i_sqrt = i_sqrt + _math.d_sin = d_sin + _math.d_cos = d_cos + _math.d_tan = d_tan +end -- missing math functions + +return _math |