Castle Paradox Forum Index Castle Paradox

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 Gamelist   Review List   Song List   All Journals   Site Stats   Search Gamelist   IRC Chat Room

Math library update.

 
Post new topic   Reply to topic    Castle Paradox Forum Index -> HELP!
View previous topic :: View next topic  
Author Message
TMC
On the Verge of Insanity




Joined: 05 Apr 2003
Posts: 3240
Location: Matakana

PostPosted: Thu Aug 05, 2004 1:38 am    Post subject: Math library update. Reply with quote

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."
Back to top
View user's profile Send private message Send e-mail
junahu
Custom Title: 45 character limit




Joined: 13 Jan 2004
Posts: 369
Location: Hull, England

PostPosted: Thu Aug 05, 2004 5:23 am    Post subject: Reply with quote

You... are... God!

Now everyone can make.... racing games... and triangle coordinates. Very well done! Good use of lookup tables.
_________________
Back to top
View user's profile Send private message Send e-mail
TMC
On the Verge of Insanity




Joined: 05 Apr 2003
Posts: 3240
Location: Matakana

PostPosted: Thu Aug 05, 2004 7:56 pm    Post subject: Reply with quote

Yeah, although I would think that the squareroot script would be the most useful.

I wrote the sin and cos scripts to work out the co-ordinates of a circle (x = cos (angle), y = sin (angle)), but it has a few other uses as well. The only reason tan is in there is because it didn't seem right to leave it out.

The lookup tables were generated by a short program- I'm not about to do all that typing and halving myself. The if trees are designed to be much faster than a long list of ifs, but it increases the amount of memory needed by the scripts : (
_________________
"It is so great it is insanely great."
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    Castle Paradox Forum Index -> HELP! All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group