aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/date.c57
-rw-r--r--src/backend/utils/adt/timestamp.c104
2 files changed, 56 insertions, 105 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 3b921258890..b952480f2fe 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.74 2002/11/21 23:31:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.75 2003/01/09 01:06:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -630,12 +630,12 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
};
static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
- INT64CONST(-500000),
- INT64CONST(-50000),
- INT64CONST(-5000),
- INT64CONST(-500),
- INT64CONST(-50),
- INT64CONST(-5),
+ INT64CONST(500000),
+ INT64CONST(50000),
+ INT64CONST(5000),
+ INT64CONST(500),
+ INT64CONST(50),
+ INT64CONST(5),
INT64CONST(0)
};
@@ -649,52 +649,33 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
100000,
1000000
};
-
- static const double TimeOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
- 0.5,
- 0.05,
- 0.005,
- 0.0005,
- 0.00005,
- 0.000005,
- 0.0000005
- };
#endif
if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
{
+ /*
+ * Note: this round-to-nearest code is not completely consistent
+ * about rounding values that are exactly halfway between integral
+ * values. On most platforms, rint() will implement round-to-nearest,
+ * but the integer code always rounds up (away from zero). Is it
+ * worth trying to be consistent?
+ */
#ifdef HAVE_INT64_TIMESTAMP
- /* we have different truncation behavior depending on sign */
if (*time >= INT64CONST(0))
{
- *time = ((*time / TimeScales[typmod])
- * TimeScales[typmod]);
- }
- else
- {
*time = (((*time + TimeOffsets[typmod]) / TimeScales[typmod])
* TimeScales[typmod]);
}
-#else
- /* we have different truncation behavior depending on sign */
- if (*time >= 0)
- {
- *time = (rint(((double) *time) * TimeScales[typmod])
- / TimeScales[typmod]);
- }
else
{
- /*
- * Scale and truncate first, then add to help the rounding
- * behavior
- */
- *time = (rint((((double) *time) * TimeScales[typmod]) + TimeOffsets[typmod])
- / TimeScales[typmod]);
+ *time = - ((((- *time) + TimeOffsets[typmod]) / TimeScales[typmod])
+ * TimeScales[typmod]);
}
+#else
+ *time = (rint(((double) *time) * TimeScales[typmod])
+ / TimeScales[typmod]);
#endif
}
-
- return;
}
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 885d3992fd4..19fb9c11843 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.75 2002/11/12 00:39:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.76 2003/01/09 01:06:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -175,12 +175,12 @@ AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
};
static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
- INT64CONST(-500000),
- INT64CONST(-50000),
- INT64CONST(-5000),
- INT64CONST(-500),
- INT64CONST(-50),
- INT64CONST(-5),
+ INT64CONST(500000),
+ INT64CONST(50000),
+ INT64CONST(5000),
+ INT64CONST(500),
+ INT64CONST(50),
+ INT64CONST(5),
INT64CONST(0)
};
@@ -194,16 +194,6 @@ AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
100000,
1000000
};
-
- static const double TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
- 0.5,
- 0.05,
- 0.005,
- 0.0005,
- 0.00005,
- 0.000005,
- 0.0000005
- };
#endif
if (!TIMESTAMP_NOT_FINITE(*time)
@@ -213,34 +203,27 @@ AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
elog(ERROR, "TIMESTAMP(%d) precision must be between %d and %d",
typmod, 0, MAX_TIMESTAMP_PRECISION);
+ /*
+ * Note: this round-to-nearest code is not completely consistent
+ * about rounding values that are exactly halfway between integral
+ * values. On most platforms, rint() will implement round-to-nearest,
+ * but the integer code always rounds up (away from zero). Is it
+ * worth trying to be consistent?
+ */
#ifdef HAVE_INT64_TIMESTAMP
- /* we have different truncation behavior depending on sign */
if (*time >= INT64CONST(0))
{
- *time = ((*time / TimestampScales[typmod])
- * TimestampScales[typmod]);
- }
- else
- {
*time = (((*time + TimestampOffsets[typmod]) / TimestampScales[typmod])
* TimestampScales[typmod]);
}
-#else
- /* we have different truncation behavior depending on sign */
- if (*time >= 0)
- {
- *time = (rint(((double) *time) * TimestampScales[typmod])
- / TimestampScales[typmod]);
- }
else
{
- /*
- * Scale and truncate first, then add to help the rounding
- * behavior
- */
- *time = (rint((((double) *time) * TimestampScales[typmod]) + TimestampOffsets[typmod])
- / TimestampScales[typmod]);
+ *time = - ((((- *time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
+ * TimestampScales[typmod]);
}
+#else
+ *time = (rint(((double) *time) * TimestampScales[typmod])
+ / TimestampScales[typmod]);
#endif
}
}
@@ -474,12 +457,12 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
};
static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {
- INT64CONST(-500000),
- INT64CONST(-50000),
- INT64CONST(-5000),
- INT64CONST(-500),
- INT64CONST(-50),
- INT64CONST(-5),
+ INT64CONST(500000),
+ INT64CONST(50000),
+ INT64CONST(5000),
+ INT64CONST(500),
+ INT64CONST(50),
+ INT64CONST(5),
INT64CONST(0)
};
@@ -493,16 +476,6 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
100000,
1000000
};
-
- static const double IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {
- 0.5,
- 0.05,
- 0.005,
- 0.0005,
- 0.00005,
- 0.000005,
- 0.0000005
- };
#endif
/*
@@ -701,30 +674,27 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
elog(ERROR, "INTERVAL(%d) precision must be between %d and %d",
precision, 0, MAX_INTERVAL_PRECISION);
+ /*
+ * Note: this round-to-nearest code is not completely consistent
+ * about rounding values that are exactly halfway between integral
+ * values. On most platforms, rint() will implement round-to-nearest,
+ * but the integer code always rounds up (away from zero). Is it
+ * worth trying to be consistent?
+ */
#ifdef HAVE_INT64_TIMESTAMP
- /* we have different truncation behavior depending on sign */
if (interval->time >= INT64CONST(0))
{
- interval->time = ((interval->time / IntervalScales[precision])
- * IntervalScales[precision]);
- }
- else
- {
interval->time = (((interval->time + IntervalOffsets[precision]) / IntervalScales[precision])
* IntervalScales[precision]);
}
-#else
- /* we have different truncation behavior depending on sign */
- if (interval->time >= 0)
- {
- interval->time = (rint(((double) interval->time) * IntervalScales[precision])
- / IntervalScales[precision]);
- }
else
{
- interval->time = (rint((((double) interval->time) + IntervalOffsets[precision])
- * IntervalScales[precision]) / IntervalScales[precision]);
+ interval->time = - (((-interval->time + IntervalOffsets[precision]) / IntervalScales[precision])
+ * IntervalScales[precision]);
}
+#else
+ interval->time = (rint(((double) interval->time) * IntervalScales[precision])
+ / IntervalScales[precision]);
#endif
}
}