@emph{Warning}: Since the result is floating point, it may not be
exact. Do not use this function if precise time stamps are required.
+For example, on typical systems @code{(float-time '(1 . 10))} displays
+as @samp{0.1} but is slightly greater than 1/10.
@code{time-to-seconds} is an alias for this function.
@end defun
@defun time-convert time &optional form
This function converts a time value into a Lisp timestamp.
-If the time cannot be represented exactly, it is truncated
-toward minus infinity.
The optional @var{form} argument specifies the timestamp form to be
returned. If @var{form} is the symbol @code{integer}, this function
@code{list}, this is planned to change in a future Emacs version, so
callers requiring list timestamps should pass @code{list} explicitly.
-If @var{time} already has the proper form, this function might yield
-@var{time} rather than a copy.
+If @var{time} is infinite or a NaN, this function signals an error.
+Otherwise, if @var{time} cannot be represented exactly, conversion
+truncates it toward minus infinity. When @var{form} is @code{t},
+conversion is always exact so no truncation occurs, and the returned
+clock resolution is no less than that of @var{time}. By way of
+contrast, @code{float-time} can convert any Lisp time value without
+signaling an error, although the result might not be exact.
+@xref{Time of Day}.
+
+For efficiency this function might return a value that is @code{eq} to
+@var{time}, or that otherwise shares structure with @var{time}.
Although @code{(time-convert nil nil)} is equivalent to
@code{(current-time)}, the latter may be a bit faster.
@defun time-subtract t1 t2
This returns the time difference @var{t1} @minus{} @var{t2} between
-two time values, as a time value. However, the result is a float
-if either argument is a float infinity or NaN@.
+two time values, normally as a Lisp timestamp but as a float
+if either argument is infinite or a NaN@.
+When the result is a timestamp, it is exact and its clock
+resolution is no worse than the worse of its two arguments' resolutions.
If you need the difference in units
-of elapsed seconds, use @code{float-time} (@pxref{Time of Day,
-float-time}) to convert the result into seconds.
+of elapsed seconds, you can convert it with @code{time-convert} or
+@code{float-time}. @xref{Time Conversion}.
@end defun
@defun time-add t1 t2
-This returns the sum of two time values, as a time value.
-However, the result is a float if either argument is a float infinity or NaN@.
+This returns the sum of two time values,
+using the same conversion rules as @code{time-subtract}.
One argument should represent a time difference rather than a point in time,
as a time value that is often just a single number of elapsed seconds.
Here is how to add a number of seconds to a time value:
else
{
int exponent = ilogb (t);
- if (exponent == FP_ILOGBNAN)
- return EINVAL;
-
- /* An enormous or infinite T would make SCALE < 0 which would make
- HZ < 1, which the (TICKS . HZ) representation does not allow. */
- if (DBL_MANT_DIG - 1 < exponent)
- return EOVERFLOW;
-
- /* min so we don't scale tiny numbers as if they were normalized. */
- int scale = min (DBL_MANT_DIG - 1 - exponent, flt_radix_power_size - 1);
+ int scale;
+ if (exponent < DBL_MANT_DIG)
+ {
+ if (exponent < DBL_MIN_EXP - 1)
+ {
+ if (exponent == FP_ILOGBNAN
+ && (FP_ILOGBNAN != FP_ILOGB0 || isnan (t)))
+ return EINVAL;
+ /* T is tiny. SCALE must be less than FLT_RADIX_POWER_SIZE,
+ as otherwise T would be scaled as if it were normalized. */
+ scale = flt_radix_power_size - 1;
+ }
+ else
+ {
+ /* The typical case. */
+ scale = DBL_MANT_DIG - 1 - exponent;
+ }
+ }
+ else if (exponent < INT_MAX)
+ {
+ /* T is finite but so large that HZ would be less than 1 if
+ T's precision were represented exactly. SCALE must be
+ nonnegative, as the (TICKS . HZ) representation requires
+ HZ to be at least 1. So use SCALE = 0, which converts T to
+ (T . 1), which is the exact numeric value with too-large HZ,
+ which is typically better than signaling overflow. */
+ scale = 0;
+ }
+ else
+ return FP_ILOGBNAN == INT_MAX && isnan (t) ? EINVAL : EOVERFLOW;
double scaled = scalbn (t, scale);
eassert (trunc (scaled) == scaled);