In working on an rint() for Win32, I found two --- one in
port/qnx4/rint.c and another in dt_common.c.  The first is very simple,
using fmod, while the second is very complicated.

I would like to pick the best one and move it to /port.  Any idea why
there are two different methods for rint() --- is the second one
complicated because it doesn't use fmod?

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073


Thu, 8 May 2003 22:12:16 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
rint() replacement
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> In working on an rint() for Win32, I found two --- one in
> port/qnx4/rint.c and another in dt_common.c.  The first is very simple,
> using fmod, while the second is very complicated.

Not to mention desperately hardware-specific.  The dt_common.c routine
is a rip from utils/adt/float.c, which has absolutely no business being
where it is --- it might have some claim to live in a Sun-specific
backend/port/ file, but it is not general by any stretch of the
imagination.  (And I think we gave up supporting SunOS awhile back
anyway.)

I can't believe that Windoze does not offer rint(); it's in the C99
standard.  Have you checked?

			regards, tom lane


Thu, 08 May 2003 22:34:28 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: rint() replacement 
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > In working on an rint() for Win32, I found two --- one in
> > port/qnx4/rint.c and another in dt_common.c.  The first is very simple,
> > using fmod, while the second is very complicated.
> 
> Not to mention desperately hardware-specific.  The dt_common.c routine
> is a rip from utils/adt/float.c, which has absolutely no business being
> where it is --- it might have some claim to live in a Sun-specific
> backend/port/ file, but it is not general by any stretch of the
> imagination.  (And I think we gave up supporting SunOS awhile back
> anyway.)

Removed from float.c and ecpg.

> 
> I can't believe that Windoze does not offer rint(); it's in the C99
> standard.  Have you checked?

Both PeerDirect and SRA used rint.c, so they certainly needed it.

Also, there is a special HPUX 9 configure test to look for rint() a
different location.  I am not sure if the new replacement rint() test
has invalidated that code.  Do we still support HPUX 9?  (I added a
comment to the configure script to mention it might now be broken.)

I see a cbrt() in float.c.  Do we actually have platforms that don't
have cbrt()/cube root?  I am inclined to remove it more move it to
/port.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Index: configure
===================================================================
RCS file: /cvsroot/pgsql-server/configure,v
retrieving revision 1.255
diff -c -c -r1.255 configure
*** configure	9 May 2003 01:16:28 -0000	1.255
--- configure	9 May 2003 16:19:09 -0000
***************
*** 11078,11084 ****
  
  
  
! for ac_func in fseeko gethostname getopt_long getrusage inet_aton random srandom strcasecmp strdup strerror strtol strtoul
  do
  as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
  echo "$as_me:$LINENO: checking for $ac_func" >&5
--- 11078,11085 ----
  
  
  
! 
! for ac_func in fseeko gethostname getopt_long getrusage inet_aton random rint srandom strcasecmp strdup strerror strtol strtoul
  do
  as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
  echo "$as_me:$LINENO: checking for $ac_func" >&5
***************
*** 11261,11266 ****
--- 11262,11268 ----
  LIBOBJS="$LIBOBJS opendir.$ac_objext" ;;
  esac
  
+ # Now that rint() is /port, I am not sure this still works, bjm 2003-05-09
  # On HPUX 9, rint() is not in regular libm.a but in /lib/pa1.1/libm.a;
  # this hackery with HPUXMATHLIB allows us to cope.
  HPUXMATHLIB=""
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql-server/configure.in,v
retrieving revision 1.246
diff -c -c -r1.246 configure.in
*** configure.in	9 May 2003 01:16:29 -0000	1.246
--- configure.in	9 May 2003 16:19:10 -0000
***************
*** 839,845 ****
    AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
  fi
  
! AC_REPLACE_FUNCS([fseeko gethostname getopt_long getrusage inet_aton random srandom strcasecmp strdup strerror strtol strtoul])
  
  # system's version of getaddrinfo(), if any, may be used only if we found
  # a definition for struct addrinfo; see notes in src/include/getaddrinfo.h
--- 839,845 ----
    AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
  fi
  
! AC_REPLACE_FUNCS([fseeko gethostname getopt_long getrusage inet_aton random rint srandom strcasecmp strdup strerror strtol strtoul])
  
  # system's version of getaddrinfo(), if any, may be used only if we found
  # a definition for struct addrinfo; see notes in src/include/getaddrinfo.h
***************
*** 867,872 ****
--- 867,873 ----
  AC_LIBOBJ(opendir) ;;
  esac
  
+ # Now that rint() is /port, I am not sure this still works, bjm 2003-05-09
  # On HPUX 9, rint() is not in regular libm.a but in /lib/pa1.1/libm.a;
  # this hackery with HPUXMATHLIB allows us to cope.
  HPUXMATHLIB=""
Index: src/backend/port/qnx4/Makefile
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/port/qnx4/Makefile,v
retrieving revision 1.4
diff -c -c -r1.4 Makefile
*** src/backend/port/qnx4/Makefile	24 Apr 2003 17:16:13 -0000	1.4
--- src/backend/port/qnx4/Makefile	9 May 2003 16:19:12 -0000
***************
*** 12,27 ****
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = isnan.o rint.o sem.o shm.o
  
! all: SUBSYS.o tstrint tstsem tstshm
  
  SUBSYS.o: $(OBJS)
  	$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
  
- tstrint: tstrint.o rint.o
- 	$(CC) -o tstrint rint.o tstrint.o
- 
  tstsem: tstsem.o sem.o
  	$(CC) -o tstsem sem.o tstsem.o
  
--- 12,24 ----
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = isnan.o sem.o shm.o
  
! all: SUBSYS.o tstsem tstshm
  
  SUBSYS.o: $(OBJS)
  	$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
  
  tstsem: tstsem.o sem.o
  	$(CC) -o tstsem sem.o tstsem.o
  
***************
*** 32,38 ****
  	$(CC) -MM $(CFLAGS) *.c >depend
  
  clean: 
! 	rm -f SUBSYS.o $(OBJS) tstrint tstrint.o tstsem tstsem.o tstshm tstshm.o
  
  ifeq (depend,$(wildcard depend))
  include depend
--- 29,35 ----
  	$(CC) -MM $(CFLAGS) *.c >depend
  
  clean: 
! 	rm -f SUBSYS.o $(OBJS) tstsem tstsem.o tstshm tstshm.o
  
  ifeq (depend,$(wildcard depend))
  include depend
Index: src/include/c.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/c.h,v
retrieving revision 1.142
diff -c -c -r1.142 c.h
*** src/include/c.h	9 May 2003 01:16:29 -0000	1.142
--- src/include/c.h	9 May 2003 16:19:14 -0000
***************
*** 811,816 ****
--- 811,820 ----
  extern int gethostname(char *name, int namelen);
  #endif
  
+ #ifndef HAVE_RINT
+ extern double rint(double x);
+ #endif
+ 
  #ifndef HAVE_INET_ATON
  # include <netinet/in.h>
  # include <arpa/inet.h>
Index: src/interfaces/ecpg/pgtypeslib/Makefile
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/pgtypeslib/Makefile,v
retrieving revision 1.5
diff -c -c -r1.5 Makefile
*** src/interfaces/ecpg/pgtypeslib/Makefile	8 Apr 2003 17:06:15 -0000	1.5
--- src/interfaces/ecpg/pgtypeslib/Makefile	9 May 2003 16:19:15 -0000
***************
*** 18,24 ****
  
  override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
  
! OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o
  
  all: all-lib
  
--- 18,25 ----
  
  override CPPFLAGS := -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS)
  
! OBJS= numeric.o datetime.o common.o dt_common.o timestamp.o interval.o \
!       $(filter rint.o, $(LIBOBJS))
  
  all: all-lib
  
Index: src/interfaces/ecpg/pgtypeslib/dt.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/pgtypeslib/dt.h,v
retrieving revision 1.4
diff -c -c -r1.4 dt.h
*** src/interfaces/ecpg/pgtypeslib/dt.h	18 Apr 2003 01:03:42 -0000	1.4
--- src/interfaces/ecpg/pgtypeslib/dt.h	9 May 2003 16:19:15 -0000
***************
*** 299,305 ****
  void j2date(int, int *, int *, int *);
  void GetCurrentDateTime(struct tm*);
  int date2j(int, int, int);
- double rint(double x);
  
  extern char* pgtypes_date_weekdays_short[];
  extern char* pgtypes_date_months[];
--- 299,304 ----
Index: src/interfaces/ecpg/pgtypeslib/dt_common.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/ecpg/pgtypeslib/dt_common.c,v
retrieving revision 1.3
diff -c -c -r1.3 dt_common.c
*** src/interfaces/ecpg/pgtypeslib/dt_common.c	1 Apr 2003 14:37:25 -0000	1.3
--- src/interfaces/ecpg/pgtypeslib/dt_common.c	9 May 2003 16:19:17 -0000
***************
*** 510,617 ****
  
  char* pgtypes_date_months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL};
  
- #ifndef HAVE_RINT
- 
- /* @(#)s_rint.c 5.1 93/09/24 */
- /*
-  * ====================================================
-  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-  *
-  * Developed at SunPro, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice
-  * is preserved.
-  * ====================================================
-  */
- 
- /*
-  * rint(x)
-  * Return x rounded to integral value according to the prevailing
-  * rounding mode.
-  * Method:
-  *		Using floating addition.
-  * Exception:
-  *		Inexact flag raised if x not equal to rint(x).
-  */
- 
- static const double one = 1.0,
- 			TWO52[2] = {
- 	4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- 	-4.50359962737049600000e+15,	/* 0xC3300000, 0x00000000 */
- };
- 
- double
- rint(double x)
- {
- 	int			i0,
- 				n0,
- 				j0,
- 				sx;
- 	unsigned	i,
- 				i1;
- 	double		w,
- 				t;
- 
- 	n0 = (*((int *) &one) >> 29) ^ 1;
- 	i0 = *(n0 + (int *) &x);
- 	sx = (i0 >> 31) & 1;
- 	i1 = *(1 - n0 + (int *) &x);
- 	j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- 	if (j0 < 20)
- 	{
- 		if (j0 < 0)
- 		{
- 			if (((i0 & 0x7fffffff) | i1) == 0)
- 				return x;
- 			i1 |= (i0 & 0x0fffff);
- 			i0 &= 0xfffe0000;
- 			i0 |= ((i1 | -i1) >> 12) & 0x80000;
- 			*(n0 + (int *) &x) = i0;
- 			w = TWO52[sx] + x;
- 			t = w - TWO52[sx];
- 			i0 = *(n0 + (int *) &t);
- 			*(n0 + (int *) &t) = (i0 & 0x7fffffff) | (sx << 31);
- 			return t;
- 		}
- 		else
- 		{
- 			i = (0x000fffff) >> j0;
- 			if (((i0 & i) | i1) == 0)
- 				return x;		/* x is integral */
- 			i >>= 1;
- 			if (((i0 & i) | i1) != 0)
- 			{
- 				if (j0 == 19)
- 					i1 = 0x40000000;
- 				else
- 					i0 = (i0 & (~i)) | ((0x20000) >> j0);
- 			}
- 		}
- 	}
- 	else if (j0 > 51)
- 	{
- 		if (j0 == 0x400)
- 			return x + x;		/* inf or NaN */
- 		else
- 			return x;			/* x is integral */
- 	}
- 	else
- 	{
- 		i = ((unsigned) (0xffffffff)) >> (j0 - 20);
- 		if ((i1 & i) == 0)
- 			return x;			/* x is integral */
- 		i >>= 1;
- 		if ((i1 & i) != 0)
- 			i1 = (i1 & (~i)) | ((0x40000000) >> (j0 - 20));
- 	}
- 	*(n0 + (int *) &x) = i0;
- 	*(1 - n0 + (int *) &x) = i1;
- 	w = TWO52[sx] + x;
- 	return w - TWO52[sx];
- }
- 
- #endif   /* !HAVE_RINT */
- 
  static datetkn *
  datebsearch(char *key, datetkn *base, unsigned int nel)
  {
--- 510,515 ----

Index: src/backend/utils/adt/float.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/float.c,v
retrieving revision 1.85
diff -c -c -r1.85 float.c
*** src/backend/utils/adt/float.c	21 Apr 2003 00:22:24 -0000	1.85
--- src/backend/utils/adt/float.c	9 May 2003 16:30:45 -0000
***************
*** 83,96 ****
  extern double cbrt(double x);
  #endif
  #endif   /* HAVE_CBRT */
- 
- #ifndef HAVE_RINT
- #define rint my_rint
- static double rint(double x);
- 
- #else
- extern double rint(double x);
- #endif   /* HAVE_RINT */
  #endif   /* NeXT check */
  
  
--- 83,88 ----
***************
*** 1936,2044 ****
  }
  
  /* ========== PRIVATE ROUTINES ========== */
- 
- /* From "fdlibm" @ netlib.att.com */
- 
- #ifndef HAVE_RINT
- 
- /* @(#)s_rint.c 5.1 93/09/24 */
- /*
-  * ====================================================
-  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-  *
-  * Developed at SunPro, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice
-  * is preserved.
-  * ====================================================
-  */
- 
- /*
-  * rint(x)
-  * Return x rounded to integral value according to the prevailing
-  * rounding mode.
-  * Method:
-  *		Using floating addition.
-  * Exception:
-  *		Inexact flag raised if x not equal to rint(x).
-  */
- 
- static const double one = 1.0,
- 			TWO52[2] = {
- 	4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- 	-4.50359962737049600000e+15,	/* 0xC3300000, 0x00000000 */
- };
- 
- static double
- rint(double x)
- {
- 	int			i0,
- 				n0,
- 				j0,
- 				sx;
- 	unsigned	i,
- 				i1;
- 	double		w,
- 				t;
- 
- 	n0 = (*((int *) &one) >> 29) ^ 1;
- 	i0 = *(n0 + (int *) &x);
- 	sx = (i0 >> 31) & 1;
- 	i1 = *(1 - n0 + (int *) &x);
- 	j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
- 	if (j0 < 20)
- 	{
- 		if (j0 < 0)
- 		{
- 			if (((i0 & 0x7fffffff) | i1) == 0)
- 				return x;
- 			i1 |= (i0 & 0x0fffff);
- 			i0 &= 0xfffe0000;
- 			i0 |= ((i1 | -i1) >> 12) & 0x80000;
- 			*(n0 + (int *) &x) = i0;
- 			w = TWO52[sx] + x;
- 			t = w - TWO52[sx];
- 			i0 = *(n0 + (int *) &t);
- 			*(n0 + (int *) &t) = (i0 & 0x7fffffff) | (sx << 31);
- 			return t;
- 		}
- 		else
- 		{
- 			i = (0x000fffff) >> j0;
- 			if (((i0 & i) | i1) == 0)
- 				return x;		/* x is integral */
- 			i >>= 1;
- 			if (((i0 & i) | i1) != 0)
- 			{
- 				if (j0 == 19)
- 					i1 = 0x40000000;
- 				else
- 					i0 = (i0 & (~i)) | ((0x20000) >> j0);
- 			}
- 		}
- 	}
- 	else if (j0 > 51)
- 	{
- 		if (j0 == 0x400)
- 			return x + x;		/* inf or NaN */
- 		else
- 			return x;			/* x is integral */
- 	}
- 	else
- 	{
- 		i = ((unsigned) (0xffffffff)) >> (j0 - 20);
- 		if ((i1 & i) == 0)
- 			return x;			/* x is integral */
- 		i >>= 1;
- 		if ((i1 & i) != 0)
- 			i1 = (i1 & (~i)) | ((0x40000000) >> (j0 - 20));
- 	}
- 	*(n0 + (int *) &x) = i0;
- 	*(1 - n0 + (int *) &x) = i1;
- 	w = TWO52[sx] + x;
- 	return w - TWO52[sx];
- }
- #endif   /* !HAVE_RINT */
  
  #ifndef HAVE_CBRT
  
--- 1928,1933 ----
Fri, 9 May 2003 12:34:47 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: rint() replacement

speaking of rint(), I just got this on Linux on a clean get from CVS:

gcc -O2 -Wall -Wmissing-prototypes -Wmissing-declarations -fpic -I../../../.
./src/interfaces/ecpg/include -I../../../../src/include/utils -I../../../../
src/include   -c -o dt_common.o dt_common.c
dt_common.c: In function `dt2time':
dt_common.c:1271: warning: implicit declaration of function `rint'

which I guess is kinda undesirable...

andrew


Fri, 9 May 2003 14:53:44 -0400
"Andrew Dunstan" <andrew@dunslane.net>
Re: rint() replacement
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Also, there is a special HPUX 9 configure test to look for rint() a
> different location.  I am not sure if the new replacement rint() test
> has invalidated that code.  Do we still support HPUX 9?  (I added a
> comment to the configure script to mention it might now be broken.)

HPUX 9 is obsolete (heck, HP is about to obsolete HPUX 10...).  If
there's any beta testers out there still running it, they can find out
for us.  But I'd say that if you are providing a portable rint() in
/port, we could get rid of the HPUXMATHLIB crock and let configure
fall back to using the /port version.

> I see a cbrt() in float.c.  Do we actually have platforms that don't
> have cbrt()/cube root?  I am inclined to remove it more move it to
> /port.

Hardly worth the trouble.  The substitute implementation is small
and portable...

			regards, tom lane


Fri, 09 May 2003 17:03:33 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: rint() replacement 
Andrew Dunstan wrote:
> 
> speaking of rint(), I just got this on Linux on a clean get from CVS:
> 
> gcc -O2 -Wall -Wmissing-prototypes -Wmissing-declarations -fpic -I../../../.
> ./src/interfaces/ecpg/include -I../../../../src/include/utils -I../../../../
> src/include   -c -o dt_common.o dt_common.c
> dt_common.c: In function `dt2time':
> dt_common.c:1271: warning: implicit declaration of function `rint'
> 
> which I guess is kinda undesirable...

OK, fixed.  I added '#include <math.h>'.

However, this illustrates another problem.  dt_common and other ecpg
files test for c.h defines but there is no #include of c.h or
postgres.h, so they never get triggered.  That needs to be fixed.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073


Fri, 9 May 2003 22:07:56 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: rint() replacement
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Also, there is a special HPUX 9 configure test to look for rint() a
> > different location.  I am not sure if the new replacement rint() test
> > has invalidated that code.  Do we still support HPUX 9?  (I added a
> > comment to the configure script to mention it might now be broken.)
> 
> HPUX 9 is obsolete (heck, HP is about to obsolete HPUX 10...).  If
> there's any beta testers out there still running it, they can find out
> for us.  But I'd say that if you are providing a portable rint() in
> /port, we could get rid of the HPUXMATHLIB crock and let configure
> fall back to using the /port version.

OK, removed.

> > I see a cbrt() in float.c.  Do we actually have platforms that don't
> > have cbrt()/cube root?  I am inclined to remove it more move it to
> > /port.
> 
> Hardly worth the trouble.  The substitute implementation is small
> and portable...

Sorry, my paragraph was bad.  Should I remove cbrt or move it to /port?

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073


Fri, 9 May 2003 22:10:51 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: rint() replacement
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Tom Lane wrote:
>> Hardly worth the trouble.  The substitute implementation is small
>> and portable...

> Sorry, my paragraph was bad.  Should I remove cbrt or move it to /port?

I'd leave it sit as-is.  I don't think it's worth fooling with.

			regards, tom lane


Fri, 09 May 2003 22:32:48 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: rint() replacement 