Post your scripting questions / solutions here
Moderator: Moderators
SilentAngel
Captain
Posts: 239 Joined: Wed Mar 12, 2008 8:27 pm
Post
by SilentAngel » Sun Nov 21, 2010 1:23 pm
this is basically the best way I found to return sqrt of a a value..
Code: Select all
//*****************************************************************//
//*This method is used to calculate a fast approximate square root*//
//*****************************************************************//
sqrt local.arg:
if(local.arg == 1)
end 1
local.Xn = float(1)
for(local.i = 1; local.i <= 100; local.i++)
{
local.v1 = float(local.Xn) / float(2)
local.v2 = float(local.arg) / ( float(2) * float(local.Xn) )
local.Xn = local.v1 + local.v2
}
local.return = local.Xn
end local.return
considering that MOH float display only 3 decimals that's pretty accurate..however remember that the more we want it accurate the more we have to increase the number of cycles in the for statement..also if you use really really big numbers ( 1040870 for exemple
) you need more cycles inside for..for exemple you can switch from 100 to 1000..
jv_map
Site Admin
Posts: 6521 Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:
Post
by jv_map » Mon Nov 22, 2010 9:07 pm
Nice
I once wrote this sqrt implementation:
Code: Select all
// fast square-root
// only usuable near x=1
// McLaurin expansion
sqrt1 local.x:
end (1.0 + 0.5 * (local.x - 1.0) - 0.125 * (local.x - 1.0) * (local.x - 1.0))
// square-root
// more accurate than pow^.5
sqrt local.x:
// sqrt(2)
local.SQRT_2 = 1.4142135623730951
// known values, how convenient
if(local.x == 0.0)
{
local.result = 0.0
}
else if(local.x == 1.0)
{
local.result = 1.0
}
else if(local.x == 2.0)
{
local.result = local.SQRT_2
}
else if (local.x < 0.0)
{
// error
println "ERROR[math::sqrt]: sqrt(" local.x ") has no real solution"
local.result = 0.0
}
else
{
// reduce x to [1,2] domain
local.wx = local.x
local.steps = 0
local.dividesteps = 0
// reduce below 2.0
while (local.wx > 2.0)
{
local.wx = 0.5 * local.wx
local.steps++
}
// increase above 1.0
while(local.wx < 1.0)
{
local.wx = 2.0 * local.wx
local.dividesteps++
}
// evaluate in [1,2] domain
if(local.wx == 1.0)
{
local.eval = 1.0
}
else if (local.wx == 2.0)
{
local.eval = local.SQRT_2
}
else
{
// approximation
local.EVALSLOPE = 0.4267766953
local.EVALMOD = 1.224744871 - 1.51 * local.EVALSLOPE
local.eval = local.EVALSLOPE * local.wx + local.EVALMOD
}
// multiply back to original domain
for(local.i = 1; local.i <= local.steps; local.i++)
{
local.eval = local.eval * local.SQRT_2
}
// divide back to original domain
for(local.i = 1; local.i <= local.dividesteps; local.i++)
{
local.eval = local.eval / local.SQRT_2
}
// correct until required accuracy has been reached
local.MAXREFINEMENTSTEPS = 2;
for(local.i = 1; local.i <= local.MAXREFINEMENTSTEPS; local.i++)
{
local.fact = local.eval * local.eval / local.x
local.eval = local.eval / (waitthread sqrt1 local.fact)
}
local.result = local.eval
}
end local.result
It scales the input to the domain [1,2] to keep the cost under control with constant relative error on the entire domain.
SilentAngel
Captain
Posts: 239 Joined: Wed Mar 12, 2008 8:27 pm
Post
by SilentAngel » Mon Nov 22, 2010 11:12 pm
yep good work!
but why didn't they implemented sqrt function in scripting language? Maybe they preferred let us have fun scripting these all!