Subject: square root
From: johnl@informix.com (Jonathan Leffler)
Newsgroups: comp.databases.informix
Date: 9 Oct 1996 10:03:20 -0400

For SQRT, you could use the i4gl_sqrt() function and the underlying
decsqrt() function in the attached shell archive.  Note that this
code uses DECIMAL types throughout and is therefore accurate up to
32 digits.

For general trig, you could consider using the functions in the SELECT
statement:

SELECT SIN(3.1415) FROM SysTables WHERE Tabid = 1;

but (a) that is a ludicrously slow way to do it, and (b) it almost
certainly uses the C math library functions, rather than any more precise
DECIMAL code, so the accuracy will not exceed about 14 digits.  You can get
those functions to exececute more quickly by using simple interface
functions like i4gl_sin():

#include <math.h>
#include <fglsys.h>

int i4gl_sin(int n)
{
	double	x;

	if (n != 1)
		fgl_fatal("i4gl_sin()", 1, -1318);
	popdub(&x);
	retdub(sin(x));
	return(1);
}

If you are using an old version of I4GL, you may not have fglsys.h to declare
the functions like popdub() and retdub() -- it is then simplest to omit the
#include <fglsys.h> line.

Yours,
Jonathan Leffler (johnl@informix.com) #include <disclaimer.h>

>Does anyone know how to compute square root on 4GL?  Also how to compute
>logarithmic and trig functions?

:	"@(#)shar.sh	1.9"
#! /bin/sh
#
#	This is a shell archive.
#	Remove everything above this line and run sh on the resulting file.
#	If this archive is complete, you will see this message at the end:
#	"All files extracted"
#
#	Created: Wed Oct  9 06:04:47 PDT 1996 by johnl at Informix Software Ltd.
#	Files archived in this archive:
#	decsqrt.c
#	i4glsqrt.c
#
#--------------------
if [ -f decsqrt.c -a "$1" != "-c" ]
then echo shar: decsqrt.c already exists
else
echo 'x - decsqrt.c (2362 characters)'
sed -e 's/^X//' >decsqrt.c <<'SHAR-EOF'
X/*
X@(#)File:            decsqrt.c
X@(#)Version:         1.2
X@(#)Last changed:    95/05/26
X@(#)Purpose:         Square root of DECIMAL value
X@(#)Author:          J Leffler
X@(#)Copyright:       (C) JLSS 1992
X@(#)Product:         :PRODUCT:
X*/
X
X/*TABSTOP=4*/
X/*LINTLIBRARY*/
X
X#include <decimal.h>
X#include <math.h>
X#include <errno.h>
X
X#ifdef TEST
X#define PRINTLEN    32
X#define MAXITER		5
X#define	ITERATIONS	iter
Xstatic int		iter;
X#else
X#define ITERATIONS	2		/* Empirically, one would suffice! */
X#endif	/* TEST */
X
X#ifndef lint
Xstatic char     sccs[] = "@(#)decsqrt.c	1.2 95/05/26";
X#endif
X
Xdecsqrt(x, r1)
Xdec_t	*x;
Xdec_t	*r1;
X{
X	int		s;
X	dec_t	r;
X	dec_t	t;
X	dec_t	two;
X	double	d;
X	int		e;
X	int     i;
X
X	/* Check for zero and negative numbers */
X	deccvdbl(0.0, &t);
X	if ((s = deccmp(x, &t)) <= 0)
X	{
X		*r1 = t;
X		return((s == 0) ? 0 : -EDOM);
X	}
X
X	/* Deduce initial guess */
X	r = *x;
X	e = r.dec_exp;
X	r.dec_exp &= 0x01;
X	dectodbl(&r, &d);
X	d = sqrt(d);
X	deccvdbl(d, &r);
X	r.dec_exp = (e + 1) / 2;
X
X	deccvdbl(2.0, &two);
X
X	for (i = 0; i < ITERATIONS; i++)
X	{
X		if ((s = decdiv(x, &r, &t)) != 0)
X			return(s);
X		if ((s = decadd(&r, &t, &t)) != 0)
X			return(s);
X		if ((s = decdiv(&t, &two, &r)) != 0)
X			return(s);
X	}
X	*r1 = r;
X	return(0);
X}
X
X#ifdef TEST
X
X#include <stdio.h>
X
X/*
X#define NO_DECSCI
X*/
X
X#define DIM(x)	(sizeof(x)/sizeof(*(x)))
X
Xchar	*decimals[] =
X{
X	"-1.0",
X	"0.0",
X	"1.0",
X	"2.0",
X	"10.0",
X	"20.0",
X	"200.0",
X	"2000.0",
X	"20000.0",
X	"200000.0",
X	"2e30",
X	"2e31",
X	"2e32",
X	"2e33",
X	"2e-30",
X	"2e-31",
X	"2e-32",
X	"2e-33",
X	"2e120"
X};
X
Xmain()
X{
X	int		i;
X	int		j;
X	int     k;
X	dec_t	num;
X	dec_t	res;
X	char    buffer[40];
X	char    bufnum[40];
X
X	for (j = 0; j < DIM(decimals); j++)
X	{
X		if ((i = deccvasc(decimals[j], strlen(decimals[j]), &num)) != 0)
X		{
X			fprintf(stderr, "error %d from deccvasc processing %s\n",
X					i, decimals[j]);
X			exit(0);
X		}
X
X		for (i = 1; i < MAXITER; i++)
X		{
X			iter = i;
X			k = decsqrt(&num, &res);
X
X#ifdef NO_DECSCI
X			dectoasc(&num, bufnum, sizeof(bufnum)-1, 16);
X			bufnum[sizeof(bufnum)-1] = '\0';
X			dectoasc(&res, buffer, sizeof(buffer)-1, 16);
X			buffer[sizeof(buffer)-1] = '\0';
X#else
X			strcpy(bufnum, decsci(&num, PRINTLEN, 0));
X			strcpy(buffer, decsci(&res, PRINTLEN, 0));
X#endif	/* NO_DECSCI */
X
X			printf("%2d: %5d: SQRT(%s) = %s\n", i, k, bufnum, buffer);
X			num = res;
X		}
X	}
X	return(0);
X}
X
X#endif	/* TEST */
SHAR-EOF
chmod 444 decsqrt.c
if [ `wc -c <decsqrt.c` -ne 2362 ]
then echo shar: decsqrt.c unpacked with wrong size
fi
# end of overwriting check
fi
#--------------------
if [ -f i4glsqrt.c -a "$1" != "-c" ]
then echo shar: i4glsqrt.c already exists
else
echo 'x - i4glsqrt.c (603 characters)'
sed -e 's/^X//' >i4glsqrt.c <<'SHAR-EOF'
X/*
X@(#)File:            i4glsqrt.c
X@(#)Version:         1.1
X@(#)Last changed:    96/10/09
X@(#)Purpose:         I4GL-callable SQRT routine i4gl_sqrt()
X@(#)Author:          J Leffler
X@(#)Copyright:       (C) JLSS 1996
X@(#)Product:         :PRODUCT:
X*/
X
X/*TABSTOP=4*/
X
X#include <decimal.h>
X#include <fglsys.h>
X
X#ifndef lint
Xstatic const char sccs[] = "@(#)i4glsqrt.c	1.1 96/10/09";
X#endif
X
Xint i4gl_sqrt(int n)
X{
X	dec_t	d;
X	dec_t	r;
X	int     s;
X
X	if (n != 1)
X		fgl_fatal("i4gl_sqrt", 1, -1318);
X
X	popdec(&d);
X	s = decsqrt(&d, &r);
X	if (s != 0)
X		fgl_fatal("i4gl_sqrt", 2, s);
X
X	retdec(&r);
X	return(1);
X}
X
X
SHAR-EOF
chmod 444 i4glsqrt.c
if [ `wc -c <i4glsqrt.c` -ne 603 ]
then echo shar: i4glsqrt.c unpacked with wrong size
fi
# end of overwriting check
fi
echo All files extracted
exit 0
