mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 16:13:05 -04:00
158 lines
4.5 KiB
Lua
158 lines
4.5 KiB
Lua
--[[ Lua Missing Math functions
|
|
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
*
|
|
* 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
|
|
|