TMC On the Verge of Insanity
Joined: 05 Apr 2003 Posts: 3240 Location: Matakana
|
Posted: Thu Aug 05, 2004 1:38 am Post subject: Math library update. |
|
|
Since I originally posted them in Cubes thread above, but he never added them, heres an update to my set of math functions. Feel free to use them in your games (see comment in scripts). The updates will be in the next version of Fyre's ThirdParty.hsi (along with some new non-math scripts I wrote), when Fyre finishes updating the documentation/testing the scripts/what-not. I gave him a head start of a couple of days, you ought to be able to download the full library from the miscfiles page soon.
Basically, in this new version, Sin/Cos/Tan scripts have been rewritten to give a huge boost in performance, and the squareroot script is *slighty* faster. It's still not blazing.
Sqrt (number) : Unchanged from last version, besides slight speed increase, and no longer returns error if you pass a negative number.
Divideround (numerator, divisor) : Unchanged, like divide, except it returns a rounded answer. You can use the 'div' operator like so:
points := distance, div, 5
Digit (number, digit no) : Returns a decimal digit out of a multi-place number. Eg. 'digit (12345, 2)' returns 4. No change from last version. You may discover that this was Cubes script, but I rewrote it to be more capable.
Sine , Cosine, Tan (angle, multiplier) : There are now 90 degrees to a right angle! Incompatible with old version! Both the angle and multiplier can be any number. Tn will no long return error. I have swapped to a lookup table, so accuratcy is much improved (all function should be no more than 1 off most of the time, prehaps 3 off in freak cases) as well as speed. Note that you now pass arguments in the opposite order to the old functions. The default multiplier is 10000.
And you can also use the operators 'times sine', 'times cosine', 'times tan' like this:
variable (angle, x coord, y coord, grad)
angle := 50
x coord := 100, times cosine, angle
y coord := 100, times sine, angle
grad := 10000, times tan, angle
And as for the scripts themselves:
Code: |
#Math functions 2004 The Mad Cacti. email : gwp_@hotmail.com
#Feel free to use in your games. Please give credit to me if you distribute your scripts. Don't steal ownership.
define script, begin
-1, sine, 2, 0, 10000
-1, cosine, 2, 0, 10000
-1, tan, 2, 0, 10000
-1, sina, 1, 0
-1, sinb, 1, 0
-1, sinc, 1, 0
-1, sind, 1, 0
-1, sin wrap, 2, 0, 0
-1, cos wrap, 2, 0, 0
-1, tan wrap, 2, 0, 0
-1, sqrt, 1, 0
-1, digit, 2, 0, 0
-1, divideround, 2, 0, 1
end
define operator, begin #operators for your use, eg '50 + 100, times sine, 50'
25, times sin, sin wrap
25, times cos, cos wrap
25, times tan, tan wrap
30, div, divideround
end
#------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------
script, sine, angle, mult, begin
variable (total, remain, val, sign)
if (angle << 0) then (angle := 0 -- angle, sign := 1) #allow for postive / negative wave nature of graph
sign := (sign + angle / 180), mod, 2
angle := angle, mod, 180 #this part converts the angle to a value between 0 and 90.
if (angle >> 90) then (angle := 180 -- angle)
#lookup table contains 32768*sin(angle)
#so sin(90) can not be stored
if (angle == 90) then (return (mult)) else (
if (angle << 45) then (
if (angle << 22) then (
val := sina (angle)
) else (
val := sinb (angle)
)
) else (
if (angle << 67) then (
val := sinc (angle)
) else (
val := sind (angle)
)
)
#work out result*mult/32768
#boohoho, so much for getting rid of the excess math
variable (multh, multl, valh, vall)
valh := (val / 256) #split val and mult into upper and lower bytes
vall := (val, mod, 256) #so that we can do 32-bit integar math without overflowing
multh := (mult / 256)
multl := (mult, mod, 256)
total := multh * valh * 2 + multh * vall / 128 + multl * valh / 128 + (multl / 2) * (vall / 2) / 8192
remain := (multh * vall), mod, 128 + (multl * valh), mod, 128 #ignore remainder of last part, too minor
increment (total, (remain + 64) / 128) #rounded divide
if (sign) then (return (0 -- total)) else (return (total))
)
end
script, cosine, angle, mult, begin
return (sine (angle + 90, mult))
end
script, tan, angle, mult, begin
variable (hval, divd, sign, val3)
angle := angle, mod, 180
if (angle << 0) then (angle := 0 -- angle, sign := 1)
if (mult << 0) then (mult := 0 -- mult, sign := sign, xor, 1)
if (angle >> 90) then (angle := 180 -- angle, sign := sign, xor, 1)
if (angle == 0) then (return (0)) else (
hval := sine (angle, mult)
val3 := (hval, mod, 2) * 64
hval := hval / 2
angle := 90 -- angle
if (angle << 45) then (
if (angle << 22) then (
divd := sina (angle)
) else (
divd := sinb (angle)
)
) else (
if (angle << 67) then (
divd := sinc (angle)
) else (
divd := sind (angle)
)
)
divd := divd / 2
divh := divd / 128
divl := divd, mod, 128
variable (t1, t2, t3, t4, ans, divh, divl)
if (hval / divd >> 1) then (noop) #result larger than 32767
divh := divd / 128
divl := divd, mod, 128
t1 := hval / divh #base quotient
t2 := (hval, mod, divh) * 128 + val3 #mod of above
t3 := t2 -- divl * t1 #remain
if (t3 << 0) then ( #t1 is too large, figure out by how much
t4 := (0 -- t3) / divd + 1
decrement (t1, t4) #result
increment (t3, divd * t4)#new remain
)
ans := t1 * 128
t1 := t3 / divh
t2 := (t3, mod, divh) * 128
t3 := t2 -- divl * t1
if (t3 << 0) then (
t4 := (0 -- t3) / divd + 1
decrement (t1, t4)
increment (t3, divd * t4)
)
increment (ans, t1)
ans := ans * 2 + (t3 + divd / 2) / divd
if (sign) then (return (0 -- ans)) else (return (ans))
)
end
script, sina, angle, begin
if (angle << 11) then (
if (angle << 5) then (
if (angle << 2) then (
if (angle == 0) then (return (0)) else (return (572))
) else (
if (angle == 2) then (return (1144)) else (
if (angle == 3) then (return (1715)) else (return (2286))
)
)
) else (
if (angle << 8) then (
if (angle == 5) then (return (2856)) else (
if (angle == 6) then (return (3425)) else (return (3993))
)
) else (
if (angle == 8) then (return (4560)) else (
if (angle == 9) then (return (5126)) else (return (5690))
)
)
)
) else (
if (angle << 16) then (
if (angle << 13) then (
if (angle == 11) then (return (6252)) else (return (6813))
) else (
if (angle == 13) then (return (7371)) else (
if (angle == 14) then (return (7927)) else (return (8481))
)
)
) else (
if (angle << 19) then (
if (angle == 16) then (return (9032)) else (
if (angle == 17) then (return (9580)) else (return (10126))
)
) else (
if (angle == 19) then (return (10668)) else (
if (angle == 20) then (return (11207)) else (return (11743))
)
)
)
)
end
script, sinb, angle, begin
if (angle << 33) then (
if (angle << 27) then (
if (angle << 24) then (
if (angle == 22) then (return (12275)) else (return (12803))
) else (
if (angle == 24) then (return (13328)) else (
if (angle == 25) then (return (13848)) else (return (14365))
)
)
) else (
if (angle << 30) then (
if (angle == 27) then (return (14876)) else (
if (angle == 28) then (return (15384)) else (return (15886))
)
) else (
if (angle == 30) then (return (16384)) else (
if (angle == 31) then (return (16877)) else (return (17364))
)
)
)
) else (
if (angle << 39) then (
if (angle << 36) then (
if (angle == 33) then (return (17847)) else (
if (angle == 34) then (return (18324)) else (return (18795))
)
) else (
if (angle == 36) then (return (19261)) else (
if (angle == 37) then (return (19720)) else (return (20174))
)
)
) else (
if (angle << 42) then (
if (angle == 39) then (return (20622)) else (
if (angle == 40) then (return (21063)) else (return (21498))
)
) else (
if (angle == 42) then (return (21926)) else (
if (angle == 43) then (return (22348)) else (return (22763))
)
)
)
)
end
script, sinc, angle, begin
if (angle << 56) then (
if (angle << 50) then (
if (angle << 47) then (
if (angle == 45) then (return (23170)) else (return (23571))
) else (
if (angle == 47) then (return (23965)) else (
if (angle == 48) then (return (24351)) else (return (24730))
)
)
) else (
if (angle << 53) then (
if (angle == 50) then (return (25102)) else (
if (angle == 51) then (return (25466)) else (return (25822))
)
) else (
if (angle == 53) then (return (26170)) else (
if (angle == 54) then (return (26510)) else (return (26842))
)
)
)
) else (
if (angle << 61) then (
if (angle << 58) then (
if (angle == 56) then (return (27166)) else (return (27482))
) else (
if (angle == 58) then (return (27789)) else (
if (angle == 59) then (return (28088)) else (return (28378))
)
)
) else (
if (angle << 64) then (
if (angle == 61) then (return (28660)) else (
if (angle == 62) then (return (28932)) else (return (29197))
)
) else (
if (angle == 64) then (return (29452)) else (
if (angle == 65) then (return (29698)) else (return (29935))
)
)
)
)
end
script, sind, angle, begin
if (angle << 78) then (
if (angle << 72) then (
if (angle << 69) then (
if (angle == 67) then (return (30163)) else (return (30382))
) else (
if (angle == 69) then (return (30592)) else (
if (angle == 70) then (return (30792)) else (return (30983))
)
)
) else (
if (angle << 75) then (
if (angle == 72) then (return (31164)) else (
if (angle == 73) then (return (31336)) else (return (31499))
)
) else (
if (angle == 75) then (return (31651)) else (
if (angle == 76) then (return (31795)) else (return (31928))
)
)
)
) else (
if (angle << 84) then (
if (angle << 81) then (
if (angle == 78) then (return (32052)) else (
if (angle == 79) then (return (32166)) else (return (32270))
)
) else (
if (angle == 81) then (return (32365)) else (
if (angle == 82) then (return (32449)) else (return (32524))
)
)
) else (
if (angle << 87) then (
if (angle == 84) then (return (32588)) else (
if (angle == 85) then (return (32643)) else (return (32688))
)
) else (
if (angle == 87) then (return (32723)) else (
if (angle == 88) then (return (32748)) else (return (32763))
)
)
)
)
end
script, sin wrap, mult, angle (return (sine (angle, mult)))
script, cos wrap, mult, angle (return (cosine (angle, mult)))
script, tan wrap, mult, angle (return (tan (angle, mult)))
script, sqrt, fi, begin
variable (start, divi, approx)
approx := -1
if (fi >= 32581) then (return (181)) else, begin #Prevent overflows
if (fi << 100) then (start := 0, divi := start ^ 2) else (
if (fi >= 22500) then (start := 150) else (
if (fi >= 14400) then (start := 120) else (
if (fi >= 8100) then (start := 90) else (
if (fi >= 4225) then (start := 65) else (
if (fi >= 1600) then (start := 40) else (
if (fi >= 900) then (start := 30) else (
if (fi >= 400) then (start := 20) else (start := 10)
))))))
divi := start ^ 2
if (fi / 3 >> divi / 2) then (start := (start / 5) * 6, divi := start ^ 2)
if (fi / 4 >> divi / 3) then (start := (start / 7) * 8, divi := start ^ 2)
)
while (approx == -1) do, begin
if (divi >= fi) then (approx := start) else (
increment (start)
divi := start ^ 2
)
end
if (divi == fi) then (return (approx)) else, begin
if ((divi -- approx) == fi) then (return (approx -- 1)) else (return (fi / approx + 1))
end
end
end
script, divideround, n, m, begin
return ((n + m / 2) / m)
end
script, digit, value, dgtno, begin
if (dgtno >> 5) then (dgtno := 5)
return ((value / 10 ^ (dgtno -- 1)), mod, 10)
end
|
_________________ "It is so great it is insanely great." |
|