aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2018-09-27 18:28:27 -0700
committerPaul Eggert2018-09-27 18:43:54 -0700
commit06e2814e1f3a80d247675319d3c438989592fb06 (patch)
treea9852c5b278bcb85c4f3e0272848f89c2c511d11 /src
parent21fc3227634c720128206980c72080dfc825a3de (diff)
downloademacs-06e2814e1f3a80d247675319d3c438989592fb06.tar.gz
emacs-06e2814e1f3a80d247675319d3c438989592fb06.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/editfns.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/editfns.c b/src/editfns.c
index ec6e8ba98d6..acd80bbf311 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1589,13 +1589,21 @@ time_subtract (struct lisp_time ta, struct lisp_time tb)
1589} 1589}
1590 1590
1591static Lisp_Object 1591static Lisp_Object
1592time_arith (Lisp_Object a, Lisp_Object b, 1592time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1593 struct lisp_time (*op) (struct lisp_time, struct lisp_time))
1594{ 1593{
1594 if (FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
1595 {
1596 double da = XFLOAT_DATA (a);
1597 double db = XFLOAT_DATA (Ffloat_time (b));
1598 return make_float (subtract ? da - db : da + db);
1599 }
1600 if (FLOATP (b) && !isfinite (XFLOAT_DATA (b)))
1601 return subtract ? make_float (-XFLOAT_DATA (b)) : b;
1602
1595 int alen, blen; 1603 int alen, blen;
1596 struct lisp_time ta = lisp_time_struct (a, &alen); 1604 struct lisp_time ta = lisp_time_struct (a, &alen);
1597 struct lisp_time tb = lisp_time_struct (b, &blen); 1605 struct lisp_time tb = lisp_time_struct (b, &blen);
1598 struct lisp_time t = op (ta, tb); 1606 struct lisp_time t = (subtract ? time_subtract : time_add) (ta, tb);
1599 if (FIXNUM_OVERFLOW_P (t.hi)) 1607 if (FIXNUM_OVERFLOW_P (t.hi))
1600 time_overflow (); 1608 time_overflow ();
1601 Lisp_Object val = Qnil; 1609 Lisp_Object val = Qnil;
@@ -1623,7 +1631,7 @@ A nil value for either argument stands for the current time.
1623See `current-time-string' for the various forms of a time value. */) 1631See `current-time-string' for the various forms of a time value. */)
1624 (Lisp_Object a, Lisp_Object b) 1632 (Lisp_Object a, Lisp_Object b)
1625{ 1633{
1626 return time_arith (a, b, time_add); 1634 return time_arith (a, b, false);
1627} 1635}
1628 1636
1629DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0, 1637DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
@@ -1633,7 +1641,30 @@ A nil value for either argument stands for the current time.
1633See `current-time-string' for the various forms of a time value. */) 1641See `current-time-string' for the various forms of a time value. */)
1634 (Lisp_Object a, Lisp_Object b) 1642 (Lisp_Object a, Lisp_Object b)
1635{ 1643{
1636 return time_arith (a, b, time_subtract); 1644 return time_arith (a, b, true);
1645}
1646
1647/* Return negative, 0, positive if a < b, a == b, a > b respectively.
1648 Return positive if either a or b is a NaN; this is good enough
1649 for the current callers. */
1650static int
1651time_cmp (Lisp_Object a, Lisp_Object b)
1652{
1653 if ((FLOATP (a) && !isfinite (XFLOAT_DATA (a)))
1654 || (FLOATP (b) && !isfinite (XFLOAT_DATA (b))))
1655 {
1656 double da = FLOATP (a) ? XFLOAT_DATA (a) : 0;
1657 double db = FLOATP (b) ? XFLOAT_DATA (b) : 0;
1658 return da < db ? -1 : da != db;
1659 }
1660
1661 int alen, blen;
1662 struct lisp_time ta = lisp_time_struct (a, &alen);
1663 struct lisp_time tb = lisp_time_struct (b, &blen);
1664 return (ta.hi != tb.hi ? (ta.hi < tb.hi ? -1 : 1)
1665 : ta.lo != tb.lo ? (ta.lo < tb.lo ? -1 : 1)
1666 : ta.us != tb.us ? (ta.us < tb.us ? -1 : 1)
1667 : ta.ps < tb.ps ? -1 : ta.ps != tb.ps);
1637} 1668}
1638 1669
1639DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0, 1670DEFUN ("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.
1642See `current-time-string' for the various forms of a time value. */) 1673See `current-time-string' for the various forms of a time value. */)
1643 (Lisp_Object t1, Lisp_Object t2) 1674 (Lisp_Object t1, Lisp_Object t2)
1644{ 1675{
1645 int t1len, t2len; 1676 return time_cmp (t1, t2) < 0 ? Qt : Qnil;
1646 struct lisp_time a = lisp_time_struct (t1, &t1len); 1677}
1647 struct lisp_time b = lisp_time_struct (t2, &t2len); 1678
1648 return ((a.hi != b.hi ? a.hi < b.hi 1679DEFUN ("time-equal", Ftime_equal, Stime_equal, 2, 2, 0,
1649 : a.lo != b.lo ? a.lo < b.lo 1680 doc: /* Return non-nil if T1 and T2 are equal time values. */)
1650 : a.us != b.us ? a.us < b.us 1681 (Lisp_Object t1, Lisp_Object t2)
1651 : a.ps < b.ps) 1682{
1652 ? Qt : Qnil); 1683 return time_cmp (t1, t2) == 0 ? Qt : Qnil;
1653} 1684}
1654 1685
1655 1686
@@ -5734,6 +5765,7 @@ it to be non-nil. */);
5734 defsubr (&Scurrent_time); 5765 defsubr (&Scurrent_time);
5735 defsubr (&Stime_add); 5766 defsubr (&Stime_add);
5736 defsubr (&Stime_subtract); 5767 defsubr (&Stime_subtract);
5768 defsubr (&Stime_equal);
5737 defsubr (&Stime_less_p); 5769 defsubr (&Stime_less_p);
5738 defsubr (&Sget_internal_run_time); 5770 defsubr (&Sget_internal_run_time);
5739 defsubr (&Sformat_time_string); 5771 defsubr (&Sformat_time_string);