1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-26 07:33:47 +00:00

time-equal, and time values of infinity and NaN

* doc/lispref/os.texi (Time Calculations):
Document time-equal, and the behavior on NaNs and infinities of
time-less-p, time-add, time-subtract.
* etc/NEWS: Mention the change.
* src/editfns.c (time_arith): Change last arg from function
to bool.  All callers changed.  Do the right thing with
infinities and NaNs.
(time_cmp): New function, which handlesx infinities and NaNs.
(Ftime_less_p): Use it.
(Ftime_equal): New function.
* test/lisp/emacs-lisp/timer-tests.el (timer-test-multiple-of-time):
Use it.
This commit is contained in:
Paul Eggert 2018-09-27 18:28:27 -07:00
parent 21fc322763
commit 06e2814e1f
4 changed files with 66 additions and 19 deletions

View File

@ -1736,17 +1736,26 @@ integer number stands for the number of seconds since the epoch.
@defun time-less-p t1 t2
This returns @code{t} if time value @var{t1} is less than time value
@var{t2}.
The result is @code{nil} if either argument is a NaN.
@end defun
@defun time-equal t1 t2
This returns @code{t} if @var{t1} and @var{t2} are equal time values.
The result is @code{nil} if either argument is a NaN.
@end defun
@defun time-subtract t1 t2
This returns the time difference @var{t1} @minus{} @var{t2} between
two time values, as a time value. If you need the difference in units
two time values, as a time value. However, the result is a float
if either argument is a float infinity or NaN@.
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.
@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@.
One argument should represent a time difference rather than a point in time,
either as a list or as a single number of elapsed seconds.
Here is how to add a number of seconds to a time value:

View File

@ -951,6 +951,14 @@ like file-attributes that compute file sizes and other attributes,
functions like process-id that compute process IDs, and functions like
user-uid and group-gid that compute user and group IDs.
+++
** 'time-add', 'time-subtract', and 'time-less-p' now accept
infinities and NaNs too, and propagate them or return nil like
floating-point operators do.
+++
** New function 'time-equal' compares time values for equality.
** define-minor-mode automatically documents the meaning of ARG.
+++

View File

@ -1589,13 +1589,21 @@ time_subtract (struct lisp_time ta, struct lisp_time tb)
}
static Lisp_Object
time_arith (Lisp_Object a, Lisp_Object b,
struct lisp_time (*op) (struct lisp_time, struct lisp_time))
time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
{
if (FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
{
double da = XFLOAT_DATA (a);
double db = XFLOAT_DATA (Ffloat_time (b));
return make_float (subtract ? da - db : da + db);
}
if (FLOATP (b) && !isfinite (XFLOAT_DATA (b)))
return subtract ? make_float (-XFLOAT_DATA (b)) : b;
int alen, blen;
struct lisp_time ta = lisp_time_struct (a, &alen);
struct lisp_time tb = lisp_time_struct (b, &blen);
struct lisp_time t = op (ta, tb);
struct lisp_time t = (subtract ? time_subtract : time_add) (ta, tb);
if (FIXNUM_OVERFLOW_P (t.hi))
time_overflow ();
Lisp_Object val = Qnil;
@ -1623,7 +1631,7 @@ A nil value for either argument stands for the current time.
See `current-time-string' for the various forms of a time value. */)
(Lisp_Object a, Lisp_Object b)
{
return time_arith (a, b, time_add);
return time_arith (a, b, false);
}
DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
@ -1633,7 +1641,30 @@ A nil value for either argument stands for the current time.
See `current-time-string' for the various forms of a time value. */)
(Lisp_Object a, Lisp_Object b)
{
return time_arith (a, b, time_subtract);
return time_arith (a, b, true);
}
/* Return negative, 0, positive if a < b, a == b, a > b respectively.
Return positive if either a or b is a NaN; this is good enough
for the current callers. */
static int
time_cmp (Lisp_Object a, Lisp_Object b)
{
if ((FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
|| (FLOATP (b) && !isfinite (XFLOAT_DATA (b))))
{
double da = FLOATP (a) ? XFLOAT_DATA (a) : 0;
double db = FLOATP (b) ? XFLOAT_DATA (b) : 0;
return da < db ? -1 : da != db;
}
int alen, blen;
struct lisp_time ta = lisp_time_struct (a, &alen);
struct lisp_time tb = lisp_time_struct (b, &blen);
return (ta.hi != tb.hi ? (ta.hi < tb.hi ? -1 : 1)
: ta.lo != tb.lo ? (ta.lo < tb.lo ? -1 : 1)
: ta.us != tb.us ? (ta.us < tb.us ? -1 : 1)
: ta.ps < tb.ps ? -1 : ta.ps != tb.ps);
}
DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0,
@ -1642,14 +1673,14 @@ A nil value for either argument stands for the current time.
See `current-time-string' for the various forms of a time value. */)
(Lisp_Object t1, Lisp_Object t2)
{
int t1len, t2len;
struct lisp_time a = lisp_time_struct (t1, &t1len);
struct lisp_time b = lisp_time_struct (t2, &t2len);
return ((a.hi != b.hi ? a.hi < b.hi
: a.lo != b.lo ? a.lo < b.lo
: a.us != b.us ? a.us < b.us
: a.ps < b.ps)
? Qt : Qnil);
return time_cmp (t1, t2) < 0 ? Qt : Qnil;
}
DEFUN ("time-equal", Ftime_equal, Stime_equal, 2, 2, 0,
doc: /* Return non-nil if T1 and T2 are equal time values. */)
(Lisp_Object t1, Lisp_Object t2)
{
return time_cmp (t1, t2) == 0 ? Qt : Qnil;
}
@ -5734,6 +5765,7 @@ it to be non-nil. */);
defsubr (&Scurrent_time);
defsubr (&Stime_add);
defsubr (&Stime_subtract);
defsubr (&Stime_equal);
defsubr (&Stime_less_p);
defsubr (&Sget_internal_run_time);
defsubr (&Sformat_time_string);

View File

@ -40,10 +40,8 @@
(should (debug-timer-check)) t))
(ert-deftest timer-test-multiple-of-time ()
(should (zerop
(float-time
(time-subtract
(timer-next-integral-multiple-of-time '(0 0 0 1) (1+ (ash 1 53)))
(list (ash 1 (- 53 16)) 1))))))
(should (time-equal
(timer-next-integral-multiple-of-time '(0 0 0 1) (1+ (ash 1 53)))
(list (ash 1 (- 53 16)) 1))))
;;; timer-tests.el ends here