Page 1 of 1
for those who need sqrt() funtion
Posted: Sun Nov 21, 2010 1:23 pm
by SilentAngel
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..
Posted: Mon Nov 22, 2010 9:07 pm
by jv_map
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.

Posted: Mon Nov 22, 2010 11:12 pm
by SilentAngel
yep good work!
but why didn't they implemented sqrt function in scripting language? Maybe they preferred let us have fun scripting these all!
