emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 06e2814: time-equal, and time values of infinity an


From: Paul Eggert
Subject: [Emacs-diffs] master 06e2814: time-equal, and time values of infinity and NaN
Date: Thu, 27 Sep 2018 21:43:59 -0400 (EDT)

branch: master
commit 06e2814e1f3a80d247675319d3c438989592fb06
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    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.
---
 doc/lispref/os.texi                 | 11 ++++++-
 etc/NEWS                            |  8 +++++
 src/editfns.c                       | 58 ++++++++++++++++++++++++++++---------
 test/lisp/emacs-lisp/timer-tests.el |  8 ++---
 4 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 8481fea..67b78ae 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -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.
address@hidden defun
+
address@hidden 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 address@hidden
+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 
address@hidden
 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:
diff --git a/etc/NEWS b/etc/NEWS
index 2a609e4..4dd4260 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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.
 
 +++
diff --git a/src/editfns.c b/src/editfns.c
index ec6e8ba..acd80bb 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -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);
diff --git a/test/lisp/emacs-lisp/timer-tests.el 
b/test/lisp/emacs-lisp/timer-tests.el
index 1d3ba75..0e40cdf 100644
--- a/test/lisp/emacs-lisp/timer-tests.el
+++ b/test/lisp/emacs-lisp/timer-tests.el
@@ -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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]