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 0000000000..c0bf55c1ad --- /dev/null +++ b/apps/plugins/lua/include_lua/math_ex.lua | |||
@@ -0,0 +1,158 @@ | |||
1 | --[[ Lua Missing Math functions | ||
2 | /*************************************************************************** | ||
3 | * __________ __ ___. | ||
4 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | * \/ \/ \/ \/ \/ | ||
9 | * $Id$ | ||
10 | * | ||
11 | * Copyright (C) 2017 William Wilgus | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | ]] | ||
23 | |||
24 | --[[ Exposed Functions | ||
25 | |||
26 | _math.clamp | ||
27 | _math.clamp_roll | ||
28 | _math.d_sin | ||
29 | _math.d_cos | ||
30 | _math.d_tan | ||
31 | _math.i_sqrt | ||
32 | |||
33 | ]] | ||
34 | |||
35 | local _math = {} do | ||
36 | |||
37 | -- internal constants | ||
38 | local _NIL = nil -- _NIL placeholder | ||
39 | |||
40 | -- clamps value to >= min and <= max | ||
41 | local function clamp(iVal, iMin, iMax) | ||
42 | if iMin > iMax then | ||
43 | local swap = iMin | ||
44 | iMin, iMax = iMax, swap | ||
45 | end | ||
46 | |||
47 | if iVal < iMin then | ||
48 | return iMin | ||
49 | elseif iVal < iMax then | ||
50 | return iVal | ||
51 | end | ||
52 | |||
53 | return iMax | ||
54 | end | ||
55 | |||
56 | -- clamps value to >= min and <= max rolls over to opposite | ||
57 | local function clamp_roll(iVal, iMin, iMax) | ||
58 | if iMin > iMax then | ||
59 | local swap = iMin | ||
60 | iMin, iMax = iMax, swap | ||
61 | end | ||
62 | |||
63 | if iVal < iMin then | ||
64 | iVal = iMax | ||
65 | elseif iVal > iMax then | ||
66 | iVal = iMin | ||
67 | end | ||
68 | |||
69 | return iVal | ||
70 | end | ||
71 | |||
72 | local function i_sqrt(n) | ||
73 | -- Newtons square root approximation | ||
74 | if n < 2 then return n end | ||
75 | local g = n / 2 | ||
76 | local l = 1 | ||
77 | |||
78 | for c = 1, 25 do -- if l,g haven't converged after 25 iterations quit | ||
79 | |||
80 | l = (n / g + g)/ 2 | ||
81 | g = (n / l + l)/ 2 | ||
82 | |||
83 | if g == l then return g end | ||
84 | end | ||
85 | |||
86 | -- check for period-two cycle between g and l | ||
87 | if g - l == 1 then | ||
88 | return l | ||
89 | elseif l - g == 1 then | ||
90 | return g | ||
91 | end | ||
92 | |||
93 | return _NIL | ||
94 | end | ||
95 | |||
96 | local function d_sin(iDeg, bExtraPrecision) | ||
97 | --[[ values are returned multiplied by 10000 | ||
98 | II | I 180-90 | 90-0 | ||
99 | ---(--)--- -------(--)------- | ||
100 | III | IV 180-270 | 270-360 | ||
101 | |||
102 | sine is only positive in quadrants I , II => 0 - 180 degrees | ||
103 | sine 180-360 degrees is a reflection of sine 0-180 | ||
104 | Bhaskara I's sine approximation formula isn't overly accurate | ||
105 | but it is close enough for rough image work. | ||
106 | ]] | ||
107 | local sign, x | ||
108 | -- no negative angles -10 degrees = 350 degrees | ||
109 | if iDeg < 0 then | ||
110 | x = 360 + (iDeg % 360) | ||
111 | else --keep rotation in 0-360 range | ||
112 | x = iDeg % 360 | ||
113 | end | ||
114 | |||
115 | -- reflect II & I onto III & IV | ||
116 | if x > 180 then | ||
117 | sign = -1 | ||
118 | x = x % 180 | ||
119 | else | ||
120 | sign = 1 | ||
121 | end | ||
122 | |||
123 | local x1 = x * (180 - x) | ||
124 | |||
125 | if bExtraPrecision then -- ~halves the largest errors | ||
126 | if x <= 22 or x >= 158 then | ||
127 | return sign * 39818 * x1 / (40497 - x1) | ||
128 | elseif (x >= 40 and x <= 56) or (x > 124 and x < 140) then | ||
129 | return sign * 40002 * x1 / (40450 - x1) | ||
130 | elseif (x > 31 and x < 71) or (x > 109 and x < 150) then | ||
131 | return sign * 40009 * x1 / (40470 - x1) | ||
132 | end | ||
133 | end | ||
134 | |||
135 | --multiplied by 10000 so no decimal in results (RB LUA is integer only) | ||
136 | return sign * 40000 * x1 / (40497 - x1) | ||
137 | end | ||
138 | |||
139 | local function d_cos(iDeg, bExtraPrecision) | ||
140 | --cos is just sine shifed by 90 degrees CCW | ||
141 | return d_sin(90 - iDeg, bExtraPrecision) | ||
142 | end | ||
143 | |||
144 | local function d_tan(iDeg, bExtraPrecision) | ||
145 | --tan = sin0 / cos0 | ||
146 | return (d_sin(iDeg, bExtraPrecision) * 10000 / d_sin(90 - iDeg, bExtraPrecision)) | ||
147 | end | ||
148 | |||
149 | --expose functions to the outside through _math table | ||
150 | _math.clamp = clamp | ||
151 | _math.clamp_roll = clamp_roll | ||
152 | _math.i_sqrt = i_sqrt | ||
153 | _math.d_sin = d_sin | ||
154 | _math.d_cos = d_cos | ||
155 | _math.d_tan = d_tan | ||
156 | end -- missing math functions | ||
157 | |||
158 | return _math | ||