1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
--[[ 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
|