From: Paul Eggert <eggert@cs.ucla.edu>
To: Michael Albinus <michael.albinus@gmx.de>
Cc: emacs-devel@gnu.org
Subject: Re: master d0c77a1: Remove some assumptions about timestamp format
Date: Thu, 27 Sep 2018 18:50:40 -0700 [thread overview]
Message-ID: <2cfc5ca3-d661-f431-397a-705682ab17eb@cs.ucla.edu> (raw)
In-Reply-To: <87o9ck6270.fsf@gmx.de>
[-- Attachment #1: Type: text/plain, Size: 289 bytes --]
I installed the attached, which should be a win independently of what
Tramp needs as it adds support for time-equal, infinite and NaN time
values. I hope it's enough for Tramp too in that it can use a NaN (or an
infinity) to represent a timestamp that a filesystem can't possibly have.
[-- Attachment #2: 0001-time-equal-and-time-values-of-infinity-and-NaN.patch --]
[-- Type: text/x-patch, Size: 7129 bytes --]
From a588608988b5fe2c27637ad4c1783a945ea639dd Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 27 Sep 2018 18:28:27 -0700
Subject: [PATCH] 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 8481fea806..67b78aea74 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1736,17 +1736,26 @@ Time Calculations
@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:
diff --git a/etc/NEWS b/etc/NEWS
index 2a609e4027..4dd4260b29 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 ec6e8ba98d..acd80bbf31 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 1d3ba757f6..0e40cdf442 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
--
2.17.1
next prev parent reply other threads:[~2018-09-28 1:50 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20180925021527.10418.61555@vcs0.savannah.gnu.org>
[not found] ` <20180925021528.9A119204E8@vcs0.savannah.gnu.org>
2018-09-25 10:09 ` master d0c77a1: Remove some assumptions about timestamp format Michael Albinus
2018-09-26 1:09 ` Paul Eggert
2018-09-26 9:24 ` Michael Albinus
2018-09-26 9:39 ` Eli Zaretskii
2018-09-26 9:43 ` Michael Albinus
2018-09-27 20:46 ` Paul Eggert
2018-09-28 6:32 ` Eli Zaretskii
2018-09-28 10:26 ` Michael Albinus
2018-09-28 17:27 ` Paul Eggert
2018-09-29 13:35 ` Michael Albinus
2018-09-28 14:45 ` Paul Eggert
2018-09-28 14:54 ` Michael Albinus
2018-09-28 1:50 ` Paul Eggert [this message]
2018-09-28 10:35 ` Michael Albinus
2018-09-28 17:39 ` Paul Eggert
2018-09-28 18:06 ` Naming predicates (was: master d0c77a1: Remove some assumptions about timestamp format) Stefan Monnier
2018-09-28 18:28 ` Drew Adams
2018-09-28 19:12 ` Paul Eggert
2018-09-28 19:26 ` Naming predicates Stefan Monnier
2018-09-28 19:40 ` Drew Adams
2018-09-28 19:41 ` Naming predicates (was: master d0c77a1: Remove some assumptions about timestamp format) Drew Adams
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2cfc5ca3-d661-f431-397a-705682ab17eb@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=emacs-devel@gnu.org \
--cc=michael.albinus@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.