Re: 4GL squareroot function needed
Posted in 1999
Topics: Stored Procedures & SPL, Connectivity: ESQL/C, 4GL & Embedded SQL, Platform-Specific Issues, Third-Party Tools & Monitoring
Hi,
I tested the code Eric posted because I wasn't sure about it, and I don't
like what I found:
$ fglpc sqrttest && fglgo sqrttestfglpc sqrttest && fglgo sqrttest
value = 1e-30, root = 0.00012207, sqr = 0.000000014901
value = 1.0001e-25, root = 0.00012207, sqr = 0.000000014901
value = 1.00020001e-20, root = 0.00012207, sqr = 0.000000014901
value = 1.00030003e-15, root = 0.00012207, sqr = 0.000000014901
value = 0.000000000100, root = 0.00012234, sqr = 0.000000014967
value = 0.000010005, root = 0.003163, sqr = 0.0000100051
value = 1.00, root = 1.00, sqr = 1.00
value = 100070.02, root = 316.34, sqr = 100070.02
[...program hung in infinite loop -- interrupt...]
$
The code works for moderate values (say 1E-5 through 1E+10), but not
outside that range. This is a heads-up for anybody using what Eric posted.
I know Eric said it is based on what other people said, and the algorithm
is the basis of working square root routines (using Newton-Raphson
approximation), but the main problem is the condition which needs to be
normalized by the size of the value you're taking the square root of.
Here is a revised version of the code, embedded in the test program.
It produced the output:
$ fglpc sqrttest3 && fglgo sqrttest3
value = 1e-30, root = 1.00000003e-15, sqr = 1.00000006e-30
value = 1.0001e-25, root = 3.16243577e-13, sqr = 1.0001e-25
value = 1.00020001e-20, root = 0.000000000100, sqr = 1.00020001e-20
value = 1.00030003e-15, root = 0.000000031627, sqr = 1.00030003e-15
value = 0.000000000100, root = 0.000010002, sqr = 0.000000000100
value = 0.000010005, root = 0.003163, sqr = 0.000010005
value = 1.00, root = 1.00, sqr = 1.00
value = 100070.02, root = 316.34, sqr = 100070.02
value = 10008002800.56, root = 100040.01, sqr = 10008002832.05
value = 1.00090036e15, root = 31637009.34, sqr = 1.00090036e15
value = 1.00100045e20, root = 10005001000.12, sqr = 1.00100045e20
value = 1.00110055e25, root = 3164017305647, sqr = 1.001100551e25
$
The code isn't very elegant; a C do-while loop would be better.
You can also code this in C using the decimal routines, and that will be
quicker if you get the numerical analysis right. I was going to supply
that code instead of the fixed I4GL code but I did a bit of extra testing
before sending it and found a problem in it -- you can't have it until I've
worked out how to fix that!
Yours,
Jonathan Leffler (jleffler@informix.com) #include <wish/I/was/skiing.h>
Guardian of DBD::Informix v0.60 (v0.61_02) -- http://www.perl.com/CPAN
Informix IDN for D4GL & Linux -- http://www.informix.com/idn
MAIN
DEFINE d FLOAT
DEFINE r FLOAT
DEFINE s FLOAT
LET d = 1e-30
WHILE d < 1e+30
LET r = sq_root(d)
LET s = r * r
DISPLAY "value = ", d, ", root = ", r, ", sqr = ", s
LET d = d * 1.0001e5
END WHILE
END MAIN
FUNCTION sq_root(x)
DEFINE
x FLOAT,
number FLOAT, # number to find sqrt of
guess FLOAT, # contains answer at end
variance FLOAT # How close are we variable
LET number = x
LET guess = 1 # initial guess
LET variance = (guess * guess) - number # initial variance
IF variance < 0 THEN
LET variance = -variance # make positive
END IF
WHILE variance / number > 0.0000001
IF variance < 0 THEN
LET variance = -variance # make positive
END IF
LET guess = (guess + (number / guess)) / 2
LET variance = (guess * guess) - number
END WHILE
RETURN guess
END FUNCTION
>From: Eric Coleman, Informix Tech Support
>Subject: Re: 4GL squareroot function needed
>Date: Fri, 26 Mar 1999 17:47:15 GMT
>
>You might try something like:
>
>FUNCTION sq_root(x)
>
>define
> x float,
> number float, # number to find sqrt of
> guess float, # contains answer at end
> variance float # How close are we variable
>
>let number = x
>
> let guess = 1 # initial guess
> let variance = 1 # big initial variance
> while variance > .0000001
> let variance = (guess * guess) - number
> if variance < 0 then
> let variance = variance * -1 # make positive
> end if
> let guess = (guess + (number / guess)) / 2
> end while
>
> return guess
>
>END FUNCTION
>
>This is untested by me but was taken from past inquiries into this
>same issue.
>
>Eric
>
>On Fri, 26 Mar 1999 16:49:53 GMT, "jrowland1" <jrowland@sprynet.com>
>wrote:
>>Looking for a function to calculate the square root of a number to
>>use in a 4Gl function. Currently running 4GL version 6.05.
>>Thanks
Uhmmm,
Not to nit pick but....
You are doing an approximation which takes forever on certain numbers.
It would be far more efficient to just write a C function and tie it in.
-Mikey
Jonathan Leffler wrote:
> Hi,
>
> I tested the code Eric posted because I wasn't sure about it, and I don't
> like what I found:
>
> $ fglpc sqrttest && fglgo sqrttest> fglpc sqrttest && fglgo sqrttest
> value = 1e-30, root = 0.00012207, sqr = 0.000000014901
> value = 1.0001e-25, root = 0.00012207, sqr = 0.000000014901
> value = 1.00020001e-20, root = 0.00012207, sqr = 0.000000014901
> value = 1.00030003e-15, root = 0.00012207, sqr = 0.000000014901
> value = 0.000000000100, root = 0.00012234, sqr = 0.000000014967
> value = 0.000010005, root = 0.003163, sqr = 0.0000100051
> value = 1.00, root = 1.00, sqr = 1.00
> value = 100070.02, root = 316.34, sqr = 100070.02
> [...program hung in infinite loop -- interrupt...]
> $
>
> The code works for moderate values (say 1E-5 through 1E+10), but not
> outside that range. This is a heads-up for anybody using what Eric posted.
> I know Eric said it is based on what other people said, and the algorithm
> is the basis of working square root routines (using Newton-Raphson
> approximation), but the main problem is the condition which needs to be
> normalized by the size of the value you're taking the square root of.
>
> Here is a revised version of the code, embedded in the test program.
> It produced the output:
>
> $ fglpc sqrttest3 && fglgo sqrttest3
> value = 1e-30, root = 1.00000003e-15, sqr = 1.00000006e-30
> value = 1.0001e-25, root = 3.16243577e-13, sqr = 1.0001e-25
> value = 1.00020001e-20, root = 0.000000000100, sqr = 1.00020001e-20
> value = 1.00030003e-15, root = 0.000000031627, sqr = 1.00030003e-15
> value = 0.000000000100, root = 0.000010002, sqr = 0.000000000100
> value = 0.000010005, root = 0.003163, sqr = 0.000010005
> value = 1.00, root = 1.00, sqr = 1.00
> value = 100070.02, root = 316.34, sqr = 100070.02
> value = 10008002800.56, root = 100040.01, sqr = 10008002832.05
> value = 1.00090036e15, root = 31637009.34, sqr = 1.00090036e15
> value = 1.00100045e20, root = 10005001000.12, sqr = 1.00100045e20
> value = 1.00110055e25, root = 3164017305647, sqr = 1.001100551e25
> $>
> The code isn't very elegant; a C do-while loop would be better.
>
> You can also code this in C using the decimal routines, and that will be
> quicker if you get the numerical analysis right. I was going to supply
> that code instead of the fixed I4GL code but I did a bit of extra testing
> before sending it and found a problem in it -- you can't have it until I've
> worked out how to fix that!
>
> Yours,
> Jonathan Leffler (jleffler@informix.com) #include <wish/I/was/skiing.h>
> Guardian of DBD::Informix v0.60 (v0.61_02) -- http://www.perl.com/CPAN
> Informix IDN for D4GL & Linux -- http://www.informix.com/idn
>
> MAIN
>
> DEFINE d FLOAT
> DEFINE r FLOAT
> DEFINE s FLOAT
>
> LET d = 1e-30
> WHILE d < 1e+30
> LET r = sq_root(d)
> LET s = r * r
> DISPLAY "value = ", d, ", root = ", r, ", sqr = ", s
> LET d = d * 1.0001e5
> END WHILE
>
> END MAIN
>
> FUNCTION sq_root(x)
>
> DEFINE
> x FLOAT,
> number FLOAT, # number to find sqrt of
> guess FLOAT, # contains answer at end
> variance FLOAT # How close are we variable
>
> LET number = x
>
> LET guess = 1 # initial guess
> LET variance = (guess * guess) - number # initial variance
> IF variance < 0 THEN
> LET variance = -variance # make positive
> END IF
>
> WHILE variance / number > 0.0000001
> IF variance < 0 THEN
> LET variance = -variance # make positive
> END IF
> LET guess = (guess + (number / guess)) / 2
> LET variance = (guess * guess) - number
> END WHILE
>
> RETURN guess
>
> END FUNCTION
>
> >From: Eric Coleman, Informix Tech Support
> >Subject: Re: 4GL squareroot function needed
> >Date: Fri, 26 Mar 1999 17:47:15 GMT
> >
> >You might try something like:
> >
> >FUNCTION sq_root(x)
> >
> >define
> > x float,
> > number float, # number to find sqrt of
> > guess float, # contains answer at end
> > variance float # How close are we variable
> >
> >let number = x
> >
> > let guess = 1 # initial guess
> > let variance = 1 # big initial variance
> > while variance > .0000001
> > let variance = (guess * guess) - number
> > if variance < 0 then
> > let variance = variance * -1 # make positive
> > end if
> > let guess = (guess + (number / guess)) / 2
> > end while
> >
> > return guess
> >
> >END FUNCTION
> >
> >This is untested by me but was taken from past inquiries into this
> >same issue.
> >
> >Eric
> >
> >On Fri, 26 Mar 1999 16:49:53 GMT, "jrowland1" <jrowland@sprynet.com>
> >wrote:
> >>Looking for a function to calculate the square root of a number to
> >>use in a 4Gl function. Currently running 4GL version 6.05.
> >>Thanks
Why write a C function at all? Once you get to C, the 'sqrt' library
function is already out there. You just need to include "math.h" and
add -lm to your linker flags.
Mike Segel wrote in message
<370061C7.1D4608A@KING.OF.MY.DOMAIN.Segel.com>...
>Uhmmm,
>Not to nit pick but....
>
>You are doing an approximation which takes forever on certain numbers.
>It would be far more efficient to just write a C function and tie it in.
>
>-Mikey
>
>
>Jonathan Leffler wrote:
>
>> Hi,
>>
>> I tested the code Eric posted because I wasn't sure about it, and I don't
>> like what I found:
>>
>> $ fglpc sqrttest && fglgo sqrttest>> fglpc sqrttest && fglgo sqrttest
>> value = 1e-30, root = 0.00012207, sqr = 0.000000014901
>> value = 1.0001e-25, root = 0.00012207, sqr = 0.000000014901
>> value = 1.00020001e-20, root = 0.00012207, sqr = 0.000000014901
>> value = 1.00030003e-15, root = 0.00012207, sqr = 0.000000014901
>> value = 0.000000000100, root = 0.00012234, sqr = 0.000000014967
>> value = 0.000010005, root = 0.003163, sqr = 0.0000100051
>> value = 1.00, root = 1.00, sqr = 1.00
>> value = 100070.02, root = 316.34, sqr = 100070.02
>> [...program hung in infinite loop -- interrupt...]
>> $
>>
>> The code works for moderate values (say 1E-5 through 1E+10), but not
>> outside that range. This is a heads-up for anybody using what Eric
posted.
>> I know Eric said it is based on what other people said, and the algorithm
>> is the basis of working square root routines (using Newton-Raphson
>> approximation), but the main problem is the condition which needs to be
>> normalized by the size of the value you're taking the square root of.
>>
>> Here is a revised version of the code, embedded in the test program.
>> It produced the output:
>>
>> $ fglpc sqrttest3 && fglgo sqrttest3
>> value = 1e-30, root = 1.00000003e-15, sqr = 1.00000006e-30
>> value = 1.0001e-25, root = 3.16243577e-13, sqr = 1.0001e-25
>> value = 1.00020001e-20, root = 0.000000000100, sqr = 1.00020001e-20
>> value = 1.00030003e-15, root = 0.000000031627, sqr = 1.00030003e-15
>> value = 0.000000000100, root = 0.000010002, sqr = 0.000000000100
>> value = 0.000010005, root = 0.003163, sqr = 0.000010005
>> value = 1.00, root = 1.00, sqr = 1.00
>> value = 100070.02, root = 316.34, sqr = 100070.02
>> value = 10008002800.56, root = 100040.01, sqr = 10008002832.05
>> value = 1.00090036e15, root = 31637009.34, sqr = 1.00090036e15
>> value = 1.00100045e20, root = 10005001000.12, sqr = 1.00100045e20
>> value = 1.00110055e25, root = 3164017305647, sqr = 1.001100551e25
>> $>>
>> The code isn't very elegant; a C do-while loop would be better.
>>
>> You can also code this in C using the decimal routines, and that will be
>> quicker if you get the numerical analysis right. I was going to supply
>> that code instead of the fixed I4GL code but I did a bit of extra testing
>> before sending it and found a problem in it -- you can't have it until
I've
>> worked out how to fix that!
>>
>> Yours,
>> Jonathan Leffler (jleffler@informix.com) #include <wish/I/was/skiing.h>
>> Guardian of DBD::Informix v0.60 (v0.61_02) -- http://www.perl.com/CPAN
>> Informix IDN for D4GL & Linux -- http://www.informix.com/idn
>>
>> MAIN
>>
>> DEFINE d FLOAT
>> DEFINE r FLOAT
>> DEFINE s FLOAT
>>
>> LET d = 1e-30
>> WHILE d < 1e+30
>> LET r = sq_root(d)
>> LET s = r * r
>> DISPLAY "value = ", d, ", root = ", r, ", sqr = ", s
>> LET d = d * 1.0001e5
>> END WHILE
>>
>> END MAIN
>>
>> FUNCTION sq_root(x)
>>
>> DEFINE
>> x FLOAT,
>> number FLOAT, # number to find sqrt of
>> guess FLOAT, # contains answer at end
>> variance FLOAT # How close are we variable
>>
>> LET number = x
>>
>> LET guess = 1 # initial guess
>> LET variance = (guess * guess) - number # initial variance
>> IF variance < 0 THEN
>> LET variance = -variance # make positive
>> END IF
>>
>> WHILE variance / number > 0.0000001
>> IF variance < 0 THEN
>> LET variance = -variance # make positive
>> END IF
>> LET guess = (guess + (number / guess)) / 2
>> LET variance = (guess * guess) - number
>> END WHILE
>>
>> RETURN guess
>>
>> END FUNCTION
>>
>> >From: Eric Coleman, Informix Tech Support
>> >Subject: Re: 4GL squareroot function needed
>> >Date: Fri, 26 Mar 1999 17:47:15 GMT
>> >
>> >You might try something like:
>> >
>> >FUNCTION sq_root(x)
>> >
>> >define
>> > x float,
>> > number float, # number to find sqrt of
>> > guess float, # contains answer at end
>> > variance float # How close are we variable
>> >
>> >let number = x
>> >
>> > let guess = 1 # initial guess
>> > let variance = 1 # big initial variance
>> > while variance > .0000001
>> > let variance = (guess * guess) - number
>> > if variance < 0 then
>> > let variance = variance * -1 # make positive
>> > end if
>> > let guess = (guess + (number / guess)) / 2
>> > end while
>> >
>> > return guess
>> >
>> >END FUNCTION
>> >
>> >This is untested by me but was taken from past inquiries into this
>> >same issue.
>> >
>> >Eric
>> >
>> >On Fri, 26 Mar 1999 16:49:53 GMT, "jrowland1" <jrowland@sprynet.com>
>> >wrote:
>> >>Looking for a function to calculate the square root of a number to
>> >>use in a 4Gl function. Currently running 4GL version 6.05.
>> >>Thanks
>
Thomas, Pray tell me how you plan on using a C function within 4GL? ;-) You do need to write a 4GL function to call the C function to use the sqrt() function within the math.h library. You have to remember that you need to pop the variables off the stack and to call the sqrt() function within math.h, then push them back on and return. I'm sorry but I thought that was obvious as to what I meant about writing a C function. "Thomas J. Girsch" wrote: > Why write a C function at all? Once you get to C, the 'sqrt' library > function is already out there. You just need to include "math.h" and > add -lm to your linker flags. > > Mike Segel wrote in message > <370061C7.1D4608A@KING.OF.MY.DOMAIN.Segel.com>... > >Uhmmm, > >Not to nit pick but.... > > > >You are doing an approximation which takes forever on certain numbers. > >It would be far more efficient to just write a C function and tie it in. > > > >-Mikey >
I don't have much (read: any) experience with 4GL, but I was once at a site that used it, and if memory serves, it compiled down to C. You basically then hack the C that it generates (naughty, I know) at the appropriate spot in the code. Also, I used to use ISQL a lot, and you could link in C functions from ISQL. I'd be surprised to learn that you can't do this in 4GL... Mike Segel wrote in message <37013D01.9DD01325@KING.OF.MY.DOMAIN.Segel.com>... >Thomas, >Pray tell me how you plan on using a C function within 4GL? ;-) >You do need to write a 4GL function to call the C function to use the sqrt() >function >within the math.h library. You have to remember that you need to pop >the variables off the stack and to call the sqrt() function within math.h, then >push >them back on and return. > >I'm sorry but I thought that was obvious as to what I meant about writing a >C function. > >"Thomas J. Girsch" wrote: > >> Why write a C function at all? Once you get to C, the 'sqrt' library >> function is already out there. You just need to include "math.h" and >> add -lm to your linker flags. >> >> Mike Segel wrote in message >> <370061C7.1D4608A@KING.OF.MY.DOMAIN.Segel.com>... >> >Uhmmm, >> >Not to nit pick but.... >> > >> >You are doing an approximation which takes forever on certain numbers. >> >It would be far more efficient to just write a C function and tie it in. >> > >> >-Mikey >> >