diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 07113bd7cf2114553c4e9616eac785940cc626cc..3fa05b507fcd55ec7a56289064e4c46b7ff178ea 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.4 1997/04/17 13:50:34 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.5 1997/05/11 15:11:31 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -558,7 +558,8 @@ abstime_date(AbsoluteTime abstime)
 #if FALSE
 	GetCurrentTime(tm);
 #endif
-	abstime = GetCurrentTransactionStartTime() + CTimeZone;
+	abstime = GetCurrentTransactionStartTime();
+	abstime2tm(abstime, &CTimeZone, tm);
 	date->year = tm->tm_year;
 	date->month = tm->tm_mon;
 	date->day = tm->tm_mday;
diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c
index d700cbd6bd64093de2cddabdd38b397d2bf4e97b..de0ec56854422f49ccd21a5e40db70b287a7a2c6 100644
--- a/src/backend/utils/adt/dt.c
+++ b/src/backend/utils/adt/dt.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.19 1997/04/27 19:20:10 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.20 1997/05/11 15:11:34 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,7 +32,7 @@
 #include "utils/builtins.h"
 
 #define USE_DATE_CACHE 1
-
+#define ROUND_ALL 0
 
 #define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
 
@@ -78,7 +78,8 @@ datetime_in(char *str)
 
     switch (dtype) {
     case DTK_DATE:
-	*result = tm2datetime( tm, fsec, &tz);
+	if (tm2datetime( tm, fsec, &tz, result) != 0)
+	    elog(WARN,"Datetime out of range %s",str);
 
 #ifdef DATEDEBUG
 printf( "datetime_in- date is %f\n", *result);
@@ -123,6 +124,7 @@ datetime_out(DateTime *dt)
     int tz;
     struct tm tt, *tm = &tt;
     double fsec;
+    char *tzn;
     char buf[MAXDATELEN+1];
 
     if (!PointerIsValid(dt))
@@ -131,8 +133,8 @@ datetime_out(DateTime *dt)
     if (DATETIME_IS_RESERVED(*dt)) {
 	EncodeSpecialDateTime(*dt, buf);
 
-    } else if (datetime2tm( *dt, &tz, tm, &fsec) == 0) {
-	EncodeDateTime(tm, fsec, &tz, DateStyle, buf);
+    } else if (datetime2tm( *dt, &tz, tm, &fsec, &tzn) == 0) {
+	EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
 
     } else {
 	EncodeSpecialDateTime(DT_INVALID, buf);
@@ -179,7 +181,7 @@ timespan_in(char *str)
 
     if ((ParseDateTime( str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
       || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
-	elog(WARN,"Bad timespan external representation %s",str);
+	elog(WARN,"Bad timespan external representation '%s'",str);
 
     if (!PointerIsValid(span = PALLOCTYPE(TimeSpan)))
 	elog(WARN,"Memory allocation failed, can't input timespan '%s'",str);
@@ -190,6 +192,7 @@ timespan_in(char *str)
 #if FALSE
 	    TIMESPAN_INVALID(span);
 #endif
+	    elog(WARN,"Bad timespan external representation %s",str);
 	};
 	break;
 
@@ -292,14 +295,14 @@ SetDateTime( DateTime dt) {
 
     if (DATETIME_IS_CURRENT(dt)) {
 	GetCurrentTime(&tt);
-	dt = tm2datetime( &tt, 0, NULL);
+	tm2datetime( &tt, 0, NULL, &dt);
 
 #ifdef DATEDEBUG
 printf( "SetDateTime- current time is %f\n", dt);
 #endif
     } else { /* if (DATETIME_IS_EPOCH(dt1)) */
 	GetEpochTime(&tt);
-	dt = tm2datetime( &tt, 0, NULL);
+	tm2datetime( &tt, 0, NULL, &dt);
 #ifdef DATEDEBUG
 printf( "SetDateTime- epoch time is %f\n", dt);
 #endif
@@ -629,7 +632,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
 	DATETIME_INVALID( result->time);
 
     } else {
-	result->time = (dt1 - dt2);
+	result->time = JROUND(dt1 - dt2);
     };
     result->month = 0;
 
@@ -649,11 +652,6 @@ DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span)
 {
     DateTime *result;
 
-#if FALSE
-    double date, time;
-    int year, mon, mday;
-#endif
-
     if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
 	return NULL;
 
@@ -677,7 +675,7 @@ printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->ti
 	    struct tm tt, *tm = &tt;
 	    double fsec;
 
-	    if (datetime2tm( *result, NULL, tm, &fsec) == 0) {
+	    if (datetime2tm( *result, NULL, tm, &fsec, NULL) == 0) {
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
@@ -702,17 +700,18 @@ printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, t
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
-		*result = tm2datetime( tm, fsec, NULL);
+		tm2datetime( tm, fsec, NULL, result);
 
 	    } else {
 		DATETIME_INVALID(*result);
 	    };
 	};
 
-#if FALSE
+#ifdef ROUND_ALL
 	*result = JROUND(*result + span->time);
-#endif
+#else
 	*result += span->time;
+#endif
     };
 
     return(result);
@@ -1009,6 +1008,7 @@ datetime_part(text *units, DateTime *datetime)
     int i;
     char *up, *lp, lowunits[MAXDATELEN+1];
     double fsec;
+    char *tzn;
     struct tm tt, *tm = &tt;
 
     if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
@@ -1039,7 +1039,7 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
 
 	dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); 
 
-	if (datetime2tm( dt, &tz, tm, &fsec) == 0) {
+	if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
 	    switch (val) {
 	    case DTK_TZ:
 		*result = tz;
@@ -1473,40 +1473,51 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
  * Ref: Explanatory Supplement to the Astronomical Almanac, 1992.
  *  University Science Books, 20 Edgehill Rd. Mill Valley CA 94941.
  *
+ * Use the algorithm by Henry Fliegel, a former NASA/JPL colleague
+ *  now at Aerospace Corp. (hi, Henry!)
+ *
  * These routines will be used by other date/time packages - tgl 97/02/25
  */
 
-#define USE_FLIEGEL 1
+/* Set the minimum year to one greater than the year of the first valid day
+ *  to avoid having to check year and day both. - tgl 97/05/08
+ */
+
+#define UTIME_MINYEAR (1901)
+#define UTIME_MINMONTH (12)
+#define UTIME_MINDAY (14)
+#define UTIME_MAXYEAR (2038)
+#define UTIME_MAXMONTH (01)
+#define UTIME_MAXDAY (18)
+
+#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
+ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
+  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
+ && ((y < UTIME_MAXYEAR) \
+ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
+  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (23)
+
+#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
+ || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
+  || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
 
 int
 date2j(int y, int m, int d)
 {
-#if USE_FLIEGEL
     int m12 = (m-14)/12;
 
     return((1461*(y+4800+m12))/4 + (367*(m-2-12*(m12)))/12
      - (3*((y+4900+m12)/100))/4 + d - 32075);
-
-#else
-    int c, ya;
-
-    if (m > 2) {
-	m -= 3;
-    } else {
-	m += 9;
-	y--;
-    };
-    c = y/100;
-    ya = y - 100*c;
-    return((146097*c)/4+(1461*ya)/4+(153*m+2)/5+d+1721119);
-#endif
 } /* date2j() */
 
 void j2date( int jd, int *year, int *month, int *day)
 {
     int j, y, m, d;
 
-#if USE_FLIEGEL
     int i, l, n;
 
     l = jd + 68569;
@@ -1520,26 +1531,6 @@ void j2date( int jd, int *year, int *month, int *day)
     m = (j+2) - (12*l);
     y = 100*(n-49)+i+l;
 
-#else
-    j = jd - 1721119;
-    y = (4*j-1)/146097;
-    j = 4*j-1-146097*y;
-    d = j/4;
-    j = (4*d+3)/1461;
-    d = 4*d+3-1461*j;
-    d = (d+4)/4;
-    m = (5*d-3)/153;
-    d = 5*d-3-153*m;
-    d = (d+5)/5;
-    y = 100*y+j;
-    if (m < 10) {
-	m += 3;
-    } else {
-	m -= 9;
-	y++;
-    };
-#endif
-
     *year = y;
     *month = m;
     *day = d;
@@ -1560,25 +1551,34 @@ int j2day( int date)
  * Convert datetime data type to POSIX time structure.
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
+ * Returns:
+ *   0 on success
+ *  -1 on out of range
  */
 int
-datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec)
+datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec, char **tzn)
 {
-    double date, time, sec;
+    double date, date0, time, sec;
     time_t utime;
 #ifdef USE_POSIX_TIME
     struct tm *tx;
 #endif
 
+
+    date0 = date2j(2000,1,1);
     time = (modf( dt/86400, &date)*86400);
-    date += date2j(2000,1,1);
+
     if (time < 0) {
 	    time += 86400;
 	    date -= 1;
     };
 
     /* Julian day routine does not work for negative Julian days */
-    if (date < 0) return -1;
+    if (date < -date0)
+	return -1;
+
+    /* add offset to go from J2000 back to standard Julian date */
+    date += date0;
 
 #ifdef DATEDEBUG
 printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time);
@@ -1601,8 +1601,9 @@ printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, t
 
     if (tzp != NULL) {
 	/* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
-	if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
-	    utime = (dt + (date2j(2000,1,1)-date2j(1970,1,1))*86400);
+	if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) {
+	    utime = (dt + (date0-date2j(1970,1,1))*86400);
+
 #ifdef USE_POSIX_TIME
 	    tx = localtime(&utime);
 #ifdef DATEDEBUG
@@ -1617,32 +1618,31 @@ printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n",
 	    tm->tm_min = tx->tm_min;
 	    tm->tm_sec = tx->tm_sec;
 	    tm->tm_isdst = tx->tm_isdst;
+
 #ifdef HAVE_INT_TIMEZONE
 	    *tzp = (tm->tm_isdst? (timezone - 3600): timezone);
+	    if (tzn != NULL) *tzn = tzname[(tm->tm_isdst > 0)];
+
 #else /* !HAVE_INT_TIMEZONE */
 	    *tzp = (tm->tm_isdst? (tm->tm_gmtoff - 3600): tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
+	    if (tzn != NULL) *tzn = tm->tm_zone;
 #endif
+
 #else /* !USE_POSIX_TIME */
 	    *tzp = CTimeZone;	/* V7 conventions; don't know timezone? */
+	    if (tzn != NULL) *tzn = CTZName;
 #endif
 	} else {
 	    *tzp = 0;
 	    tm->tm_isdst = 0;
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-	    tzname[0] = "GMT";
-#else /* !HAVE_INT_TIMEZONE */
-	    tm->tm_zone = "GMT";
-#endif
-#else /* !USE_POSIX_TIME */
-	    strcpy( CTZName, "GMT");
-#endif
+	    if (tzn != NULL) *tzn = NULL;
 	};
 
 	dt = dt2local( dt, *tzp);
 
     } else {
 	tm->tm_isdst = 0;
+	if (tzn != NULL) *tzn = NULL;
     };
 
 #ifdef DATEDEBUG
@@ -1666,26 +1666,25 @@ printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n",
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
  */
-DateTime
-tm2datetime( struct tm *tm, double fsec, int *tzp) {
+int
+tm2datetime( struct tm *tm, double fsec, int *tzp, DateTime *result) {
 
-    DateTime result;
     double date, time;
 
     /* Julian day routines are not correct for negative Julian days */
-    if ((date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)) < 0)
+    if (! IS_VALID_JULIAN( tm->tm_year, tm->tm_mon, tm->tm_mday))
 	return(DT_INVALID);
 
-    date -= date2j(2000,1,1);
+    date = date2j(tm->tm_year,tm->tm_mon,tm->tm_mday) - date2j(2000,1,1);
     time = time2t(tm->tm_hour,tm->tm_min,(tm->tm_sec + fsec));
-    result = (date*86400+time);
+    *result = (date*86400+time);
 #ifdef DATEDEBUG
-printf( "tm2datetime- date is %f (%f %f %d)\n", result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
+printf( "tm2datetime- date is %f (%f %f %d)\n", *result, date, time, (((tm->tm_hour*60)+tm->tm_min)*60+tm->tm_sec));
 printf( "tm2datetime- time is %f %02d:%02d:%02d %f\n", time, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #endif
-    if (tzp != NULL) result = dt2local(result, -(*tzp));
+    if (tzp != NULL) *result = dt2local(*result, -(*tzp));
 
-    return(result);
+    return 0;
 } /* tm2datetime() */
 
 
@@ -1703,10 +1702,11 @@ timespan2tm(TimeSpan span, struct tm *tm, float8 *fsec)
 	tm->tm_mon = 0;
     };
 
-#if FALSE
+#ifdef ROUND_ALL
     time = JROUND(span.time);
-#endif
+#else
     time = span.time;
+#endif
 
     funit = modf( (time / 86400), &iunit);
     tm->tm_mday = iunit;
@@ -1743,7 +1743,7 @@ printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month
  tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #endif
 
-    return 1;
+    return 0;
 } /* tm2timespan() */
 
 
@@ -2092,7 +2092,7 @@ printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
     if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M)
       && (tzp != NULL) && (! (fmask & DTK_M(TZ)))) {
 
-	if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
+	if (IS_VALID_UTIME( tm->tm_year, tm->tm_mon, tm->tm_mday)) {
 #ifdef USE_POSIX_TIME
 	    tm->tm_year -= 1900;
 	    tm->tm_mon -= 1;
@@ -2667,6 +2667,7 @@ printf( "DecodeDateDelta- field[%d] is %s (type %d)\n", i, field[i], ftype[i]);
 #endif
 	switch (ftype[i]) {
 	case DTK_TIME:
+	    /* already read in forward-scan above so return error */
 #if FALSE
 	    if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0) return -1;
 #endif
@@ -2916,47 +2917,27 @@ printf( "EncodeSpecialDateTime- unrecognized date\n");
 /* EncodeDateTime()
  * Encode date and time interpreted as local time.
  */
-int EncodeDateTime(struct tm *tm, double fsec, int *tzp, int style, char *str)
+int EncodeDateTime(struct tm *tm, double fsec, int *tzp, char **tzn, int style, char *str)
 {
     char mabbrev[4], dabbrev[4];
     int day, hour, min;
     double sec;
-#if defined(DATEDEBUG) && FALSE
-    char buf[MAXDATELEN+1];
-#endif
 
     sec = (tm->tm_sec + fsec);
 
-#if FALSE
-    tm->tm_isdst = -1;
-#endif
-
 #ifdef DATEDEBUG
 #ifdef USE_POSIX_TIME
 #ifdef HAVE_INT_TIMEZONE
 printf( "EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n",
- tzname[0], CTZName, *tzp, CTimeZone, tm->tm_isdst, CDayLight);
+ *tzn, tzname[0], *tzp, CTimeZone, tm->tm_isdst, CDayLight);
 #else
 printf( "EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n",
- tm->tm_zone, CTZName, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
+ *tzn, tm->tm_zone, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
 #endif
 #else
-printf( "EncodeDateTime- timezone is %s; offset is %d; daylight is %d\n",
- CTZName, CTimeZone, CDayLight);
-#endif
+printf( "EncodeDateTime- timezone is %s (%s); offset is %d; daylight is %d\n",
+ *tzn, CTZName, CTimeZone, CDayLight);
 #endif
-
-#ifdef USE_POSIX_TIME
-    /* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
-    if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
-	tm->tm_year -= 1900;
-	tm->tm_mon -= 1;
-	mktime(tm);
-	tm->tm_year += 1900;
-	tm->tm_mon += 1;
-    } else {
-	tm->tm_isdst = -1;
-    };
 #endif
 
     day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday);
@@ -2980,7 +2961,7 @@ printf( "EncodeDateTime- day is %d\n", day);
 	      tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
 	    sprintf( (str+17), ((fsec != 0)? "%05.2f": "%02.0f"), sec);
 
-	    if (tm->tm_isdst >= 0) {
+	    if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
 		if (tzp != NULL) {
 		    hour = -(*tzp / 3600);
 		    min = ((abs(*tzp) / 60) % 60);
@@ -3012,16 +2993,9 @@ printf( "EncodeDateTime- day is %d\n", day);
 	    sprintf( (str+5), "/%04d %02d:%02d:%05.2f",
 	      tm->tm_year, tm->tm_hour, tm->tm_min, sec);
 
-	    if (tm->tm_isdst >= 0) {
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-		sprintf( (str+22), " %s", tzname[(tm->tm_isdst > 0)]);
-#else /* !HAVE_INT_TIMEZONE */
-		sprintf( (str+22), " %s", tm->tm_zone);
-#endif
-#else /* !USE_POSIX_TIME */
-		sprintf( (str+22), " %s", CTZName);
-#endif
+	    if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
+		strcpy( (str+22), " ");
+		strcpy( (str+23), *tzn);
 	    };
 
 	} else {
@@ -3041,16 +3015,9 @@ printf( "EncodeDateTime- day is %d\n", day);
 	    sprintf( (str+10), " %02d:%02d:%05.2f %04d",
 	      tm->tm_hour, tm->tm_min, sec, tm->tm_year);
 
-	    if (tm->tm_isdst >= 0) {
-#ifdef USE_POSIX_TIME
-#ifdef HAVE_INT_TIMEZONE
-		sprintf( (str+27), " %s", tzname[(tm->tm_isdst > 0)]);
-#else
-		sprintf( (str+27), " %s", tm->tm_zone);
-#endif
-#else
-		sprintf( (str+27), " %s", CTZName);
-#endif
+	    if ((*tzn != NULL) && (tm->tm_isdst >= 0)) {
+		strcpy( (str+27), " ");
+		strcpy( (str+28), *tzn);
 	    };
 
 	} else {
@@ -3061,13 +3028,6 @@ printf( "EncodeDateTime- day is %d\n", day);
 
 #ifdef DATEDEBUG
 printf( "EncodeDateTime- date result is %s\n", str);
-#endif
-
-#if defined(DATEDEBUG) && FALSE
-    if (tm->tm_year >= 1000) tm->tm_year -= 1900;
-    tm->tm_mon -= 1;
-    strftime( buf, sizeof(buf), "%y.%m.%d %H:%M:%S %Z", tm);
-printf( "EncodeDateTime- strftime result is %s\n", buf);
 #endif
 
     return(TRUE);
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 509ce6ce6d48d884d0d6fc7a74dbb70cf50f2e58..aece1cdc5ba8cf713febde4e5683460c343e7198 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.13 1997/03/12 21:09:11 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.14 1997/05/11 15:11:38 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,7 @@
  *	 float4eq, float4ne, float4lt, float4le, float4gt, float4ge
  *	 float8eq, float8ne, float8lt, float8le, float8gt, float8ge
  *	Conversion routines:
- *	 ftod, dtof
+ *	 ftod, dtof, itod, dtoi, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
  *
  *	Random float8 ops:
  * 	 dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1
@@ -39,6 +39,11 @@
  *	 routines, but then you pay the overhead of converting...)
  *
  * XXX GLUESOME STUFF. FIX IT! -AY '94
+ *
+ *	Added some additional conversion routines and cleaned up
+ *	 a bit of the existing code. Need to change the error checking
+ *	 for calls to pow(), exp() since on some machines (my Linux box
+ *	 included) these routines do not set errno. - tgl 97/05/10
  */
 #include <stdio.h>		/* for sprintf() */
 #include <string.h>
@@ -51,11 +56,21 @@
 #include <math.h>
 
 #include "postgres.h"
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
 #include "fmgr.h"
 #include "utils/builtins.h"	/* for ftod() prototype */
 #include "utils/palloc.h"
 
 
+#ifndef SHRT_MAX
+#define SHRT_MAX 32767
+#endif
+#ifndef SHRT_MIN
+#define SHRT_MIN (-32768)
+#endif
+
 #define FORMAT 		'g'	/* use "g" output format as standard format */
 /* not sure what the following should be, but better to make it over-sufficient */
 #define	MAXFLOATWIDTH 	64
@@ -289,7 +304,7 @@ float32 float4um(float32 arg1)
     if (!arg1)
 	return (float32)NULL;
     
-    val = -(*arg1);
+    val = ((*arg1 != 0) ? -(*arg1): *arg1);
     CheckFloat4Val(val);
 
     result = (float32) palloc(sizeof(float32data));
@@ -360,7 +375,7 @@ float64 float8um(float64 arg1)
     if (!arg1)
 	return (float64)NULL;
     
-    val = -(*arg1);
+    val = ((*arg1 != 0)? -(*arg1): *arg1);
     
     CheckFloat8Val(val);
     result = (float64) palloc(sizeof(float64data));
@@ -585,50 +600,50 @@ float64 float8inc(float64 arg1)
 /*
  *	float4{eq,ne,lt,le,gt,ge}	- float4/float4 comparison operations
  */
-long float4eq(float32 arg1, float32 arg2)
+bool float4eq(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
-    
+	return 0;
+
     return(*arg1 == *arg2);
 }
 
-long float4ne(float32 arg1, float32 arg2)
+bool float4ne(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 != *arg2);
 }
 
-long float4lt(float32 arg1, float32 arg2)
+bool float4lt(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 < *arg2);
 }
 
-long float4le(float32 arg1, float32 arg2)
+bool float4le(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 <= *arg2);
 }
 
-long float4gt(float32 arg1, float32 arg2)
+bool float4gt(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 > *arg2);
 }
 
-long float4ge(float32 arg1, float32 arg2)
+bool float4ge(float32 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 >= *arg2);
 }
@@ -636,50 +651,50 @@ long float4ge(float32 arg1, float32 arg2)
 /*
  *	float8{eq,ne,lt,le,gt,ge}	- float8/float8 comparison operations
  */
-long float8eq(float64 arg1, float64 arg2)
+bool float8eq(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 == *arg2);
 }
 
-long float8ne(float64 arg1, float64 arg2)
+bool float8ne(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 != *arg2);
 }
 
-long float8lt(float64 arg1, float64 arg2)
+bool float8lt(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 < *arg2);
 }
 
-long float8le(float64 arg1, float64 arg2)
+bool float8le(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 <= *arg2);
 }
 
-long float8gt(float64 arg1, float64 arg2)
+bool float8gt(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 > *arg2);
 }
 
-long float8ge(float64 arg1, float64 arg2)
+bool float8ge(float64 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 >= *arg2);
 }
@@ -700,7 +715,7 @@ float64 ftod(float32 num)
     
     if (!num)
 	return (float64)NULL;
-    
+
     result = (float64) palloc(sizeof(float64data));
     
     *result = *num;
@@ -717,10 +732,140 @@ float32 dtof(float64 num)
     
     if (!num)
 	return (float32)NULL;
+
+    CheckFloat4Val(*num);
+
+    result = (float32) palloc(sizeof(float32data));
+
+    *result = *num;
+    return(result);
+}
+
+
+/*
+ *	dtoi		- converts a float8 number to an int4 number
+ */
+int32 dtoi(float64 num)
+{
+    int32	result;
+    
+    if (!num)
+	elog(WARN,"dtoi:  unable to convert null",NULL);
+
+    if ((*num < INT_MIN) || (*num > INT_MAX))
+	elog(WARN,"dtoi:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	dtoi2		- converts a float8 number to an int2 number
+ */
+int16 dtoi2(float64 num)
+{
+    int16	result;
+    
+    if (!num)
+	elog(WARN,"dtoi2:  unable to convert null",NULL);
+
+    if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
+	elog(WARN,"dtoi2:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	itod		- converts an int4 number to a float8 number
+ */
+float64 itod(int32 num)
+{
+    float64	result;
+    
+    result = (float64) palloc(sizeof(float64data));
+    
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *	i2tod		- converts an int2 number to a float8 number
+ */
+float64 i2tod(int16 num)
+{
+    float64	result;
+    
+    result = (float64) palloc(sizeof(float64data));
+    
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *	ftoi		- converts a float8 number to an int4 number
+ */
+int32 ftoi(float32 num)
+{
+    int32	result;
+    
+    if (!num)
+	elog(WARN,"ftoi:  unable to convert null",NULL);
+
+    if ((*num < INT_MIN) || (*num > INT_MAX))
+	elog(WARN,"ftoi:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	ftoi2		- converts a float8 number to an int2 number
+ */
+int16 ftoi2(float32 num)
+{
+    int16	result;
+    
+    if (!num)
+	elog(WARN,"ftoi2:  unable to convert null",NULL);
+
+    if ((*num < SHRT_MIN) || (*num > SHRT_MAX))
+	elog(WARN,"ftoi2:  integer out of range",NULL);
+
+    result = rint(*num);
+    return(result);
+}
+
+
+/*
+ *	itof		- converts an int4 number to a float8 number
+ */
+float32 itof(int32 num)
+{
+    float32	result;
     
     result = (float32) palloc(sizeof(float32data));
     
-    *result = *num;
+    *result = num;
+    return(result);
+}
+
+
+/*
+ *	i2tof		- converts an int2 number to a float8 number
+ */
+float32 i2tof(int16 num)
+{
+    float32	result;
+    
+    result = (float32) palloc(sizeof(float32data));
+    
+    *result = num;
     return(result);
 }
 
@@ -1035,50 +1180,50 @@ float64 float84div(float64 arg1, float32 arg2)
 /*
  *	float48{eq,ne,lt,le,gt,ge}	- float4/float8 comparison operations
  */
-long float48eq(float32 arg1, float64 arg2)
+bool float48eq(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 == (float)*arg2);
 }
 
-long float48ne(float32 arg1, float64 arg2)
+bool float48ne(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 != (float)*arg2);
 }
 
-long float48lt(float32 arg1, float64 arg2)
+bool float48lt(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 < (float)*arg2);
 }
 
-long float48le(float32 arg1, float64 arg2)
+bool float48le(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 <= (float)*arg2);
 }
 
-long float48gt(float32 arg1, float64 arg2)
+bool float48gt(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 > (float)*arg2);
 }
 
-long float48ge(float32 arg1, float64 arg2)
+bool float48ge(float32 arg1, float64 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return(*arg1 >= (float)*arg2);
 }
@@ -1086,50 +1231,50 @@ long float48ge(float32 arg1, float64 arg2)
 /*
  *	float84{eq,ne,lt,le,gt,ge}	- float4/float8 comparison operations
  */
-long float84eq(float64 arg1, float32 arg2)
+bool float84eq(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 == *arg2);
 }
 
-long float84ne(float64 arg1, float32 arg2)
+bool float84ne(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 != *arg2);
 }
 
-long float84lt(float64 arg1, float32 arg2)
+bool float84lt(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 < *arg2);
 }
 
-long float84le(float64 arg1, float32 arg2)
+bool float84le(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 <= *arg2);
 }
 
-long float84gt(float64 arg1, float32 arg2)
+bool float84gt(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 > *arg2);
 }
 
-long float84ge(float64 arg1, float32 arg2)
+bool float84ge(float64 arg1, float32 arg2)
 {
     if (!arg1 || !arg2)
-	return (long)NULL;
+	return 0;
     
     return((float)*arg1 >= *arg2);
 }
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 3489f6cf2b52dfb6a14ab3d4f71999f9492789ec..0b485007ee346896cbe873d09e653cf9447c787c 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.5 1997/05/06 07:27:51 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.6 1997/05/11 15:11:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2639,7 +2639,7 @@ poly_path(POLYGON *poly)
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.5 1997/05/06 07:27:51 thomas Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.6 1997/05/11 15:11:41 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2722,7 +2722,7 @@ CIRCLE *circle_in(char *str)
     if (*s == DELIM) s++;
     while (isspace( *s)) s++;
 
-    if (! single_decode( s, &circle->radius, &s))
+    if ((! single_decode( s, &circle->radius, &s)) || (circle->radius < 0))
       elog (WARN, "Bad circle external representation '%s'",str);
 
     while (depth > 0) {
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index 881206fc59fb070ac6eeb989457ead6f08467cc5..f091932074ea92e5240c37c361452133e3145a32 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.25 1997/04/25 18:40:33 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.26 1997/05/11 15:11:45 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -519,10 +519,10 @@ datetime_abstime(DateTime *datetime)
 
     } else {
 	if (DATETIME_IS_RELATIVE(*datetime)) {
-	    datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec);
+	    datetime2tm( SetDateTime(*datetime), NULL, tm, &fsec, NULL);
 	    result = tm2abstime( tm, 0);
 
-	} else if (datetime2tm( *datetime, NULL, tm, &fsec) == 0) {
+	} else if (datetime2tm( *datetime, NULL, tm, &fsec, NULL) == 0) {
 	    result = tm2abstime( tm, 0);
 
 	} else {
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index d4fb0759644150f814b57ea814a7e763e3159af1..e884f7eb08c667cc035859aa01741a39656c3e25 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -184,7 +184,8 @@ timestamp_datetime(time_t timestamp)
     tm->tm_year += 1900;
     tm->tm_mon += 1;
 
-    *result = tm2datetime(tm, fsec, NULL);
+    if (tm2datetime(tm, fsec, NULL, result) != 0)
+	elog(WARN,"Unable to convert timestamp to datetime",timestamp_out(timestamp));
 
     return(result);
 } /* timestamp_datetime() */