+static struct lisp_time
+time_add (struct lisp_time ta, struct lisp_time tb)
+{
+ EMACS_INT hi = ta.hi + tb.hi;
+ int lo = ta.lo + tb.lo;
+ int us = ta.us + tb.us;
+ int ps = ta.ps + tb.ps;
+ us += (1000000 <= ps);
+ ps -= (1000000 <= ps) * 1000000;
+ lo += (1000000 <= us);
+ us -= (1000000 <= us) * 1000000;
+ hi += (1 << LO_TIME_BITS <= lo);
+ lo -= (1 << LO_TIME_BITS <= lo) << LO_TIME_BITS;
+ return (struct lisp_time) { hi, lo, us, ps };
+}
+
+static struct lisp_time
+time_subtract (struct lisp_time ta, struct lisp_time tb)
+{
+ EMACS_INT hi = ta.hi - tb.hi;
+ int lo = ta.lo - tb.lo;
+ int us = ta.us - tb.us;
+ int ps = ta.ps - tb.ps;
+ us -= (ps < 0);
+ ps += (ps < 0) * 1000000;
+ lo -= (us < 0);
+ us += (us < 0) * 1000000;
+ hi -= (lo < 0);
+ lo += (lo < 0) << LO_TIME_BITS;
+ return (struct lisp_time) { hi, lo, us, ps };
+}
+
+static Lisp_Object
+time_arith (Lisp_Object a, Lisp_Object b,
+ struct lisp_time (*op) (struct lisp_time, struct lisp_time))
+{
+ 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);
+ if (! (MOST_NEGATIVE_FIXNUM <= t.hi && t.hi <= MOST_POSITIVE_FIXNUM))
+ time_overflow ();
+ Lisp_Object val = Qnil;
+
+ switch (max (alen, blen))
+ {
+ default:
+ val = Fcons (make_number (t.ps), val);
+ /* Fall through. */
+ case 3:
+ val = Fcons (make_number (t.us), val);
+ /* Fall through. */
+ case 2:
+ val = Fcons (make_number (t.lo), val);
+ val = Fcons (make_number (t.hi), val);
+ break;
+ }
+
+ return val;
+}
+
+DEFUN ("time-add", Ftime_add, Stime_add, 2, 2, 0,
+ doc: /* Return the sum of two time values A and B, as a time value. */)
+ (Lisp_Object a, Lisp_Object b)
+{
+ return time_arith (a, b, time_add);
+}
+
+DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
+ doc: /* Return the difference between two time values A and B, as a time value. */)
+ (Lisp_Object a, Lisp_Object b)
+{
+ return time_arith (a, b, time_subtract);
+}
+
+DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0,
+ doc: /* Return non-nil if time value T1 is earlier than time value T2. */)
+ (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);
+}
+
+