Blame test/mpfrsqrt.awk

Packit Service f629e6
# Date: Sat, 02 Aug 2014 12:27:00 -0400
Packit Service f629e6
# To: bug-gawk@gnu.org
Packit Service f629e6
# From: Katherine Wasserman <katie@wass.net>
Packit Service f629e6
# Message-ID: <E1XDc9F-0007BX-O1@eggs.gnu.org>
Packit Service f629e6
# Subject: [bug-gawk] GAWK 4.1 SQRT() bug
Packit Service f629e6
# 
Packit Service f629e6
# In version 4.1.60 of GAWK the sqrt() function does not work correctly on bignums.
Packit Service f629e6
# Here's a demo of the problem along with, a function that does work correctly.
Packit Service f629e6
# 
Packit Service f629e6
# Running this program (sqrt-bug.awk):
Packit Service f629e6
# --------------------------------------------------------------------
Packit Service f629e6
Packit Service f629e6
@load "intdiv"
Packit Service f629e6
BEGIN {
Packit Service f629e6
a=11111111111111111111111111111111111111111111111111111111111
Packit Service f629e6
print sqrt(a^2)
Packit Service f629e6
#print sq_root(a^2)
Packit Service f629e6
Packit Service f629e6
# ADR: Added for gawk-4.1-stable which doesn't have built-in intdiv() function
Packit Service f629e6
if (PROCINFO["version"] < "4.1.60")
Packit Service f629e6
  print sq_root2(a^2)
Packit Service f629e6
else
Packit Service f629e6
  print sq_root(a^2)
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
function sq_root(x, temp,r,z)
Packit Service f629e6
{  temp=substr(x,1,length(x)/2) + 0 # a good first guess
Packit Service f629e6
   z=0
Packit Service f629e6
   while (abs(z-temp)>1)
Packit Service f629e6
    { z=temp
Packit Service f629e6
      intdiv(x,temp,r)
Packit Service f629e6
      temp=r["quotient"] + temp
Packit Service f629e6
      intdiv(temp,2,r)
Packit Service f629e6
      temp=r["quotient"]
Packit Service f629e6
    }
Packit Service f629e6
   return temp
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
function sq_root2(x, temp,r,z)
Packit Service f629e6
{  temp=substr(x,1,length(x)/2) + 0 # a good first guess
Packit Service f629e6
   z=0
Packit Service f629e6
   while (abs(z-temp)>1)
Packit Service f629e6
    { z=temp
Packit Service f629e6
      awk_div(x,temp,r)
Packit Service f629e6
      temp=r["quotient"] + temp
Packit Service f629e6
      awk_div(temp,2,r)
Packit Service f629e6
      temp=r["quotient"]
Packit Service f629e6
    }
Packit Service f629e6
   return temp
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
function abs(x)
Packit Service f629e6
{ return (x<0 ? -x : x)
Packit Service f629e6
}
Packit Service f629e6
# 
Packit Service f629e6
# --------------------------------------------------------------------
Packit Service f629e6
# gawk -M -f sqrt-bug.awk
Packit Service f629e6
# 
Packit Service f629e6
# results in:
Packit Service f629e6
# 11111111111111111261130863809439559987542611609749437808640
Packit Service f629e6
# 11111111111111111111111111111111111111111111111111111111111
Packit Service f629e6
# 
Packit Service f629e6
# Thanks,
Packit Service f629e6
# Katie
Packit Service f629e6
# 
Packit Service f629e6
Packit Service f629e6
# div --- do integer division
Packit Service f629e6
Packit Service f629e6
function awk_div(numerator, denominator, result,    i, save_PREC)
Packit Service f629e6
{
Packit Service f629e6
	save_PREC = PREC
Packit Service f629e6
	PREC = 400	# good enough for this test
Packit Service f629e6
Packit Service f629e6
	split("", result)
Packit Service f629e6
Packit Service f629e6
	numerator = int(numerator)
Packit Service f629e6
	denominator = int(denominator)
Packit Service f629e6
	result["quotient"] = int(numerator / denominator)
Packit Service f629e6
	result["remainder"] = int(numerator % denominator)
Packit Service f629e6
Packit Service f629e6
	PREC = save_PREC
Packit Service f629e6
	return 0.0
Packit Service f629e6
}