]> git.eshelyaron.com Git - emacs.git/commitdiff
Clarify rounding mode when converting to struct timespec.
authorPhilipp Stephani <phst@google.com>
Wed, 24 Apr 2019 11:41:05 +0000 (13:41 +0200)
committerPhilipp Stephani <phst@google.com>
Wed, 24 Apr 2019 11:41:05 +0000 (13:41 +0200)
* doc/lispref/internals.texi (Module Values): Clarify that the
truncation is towards negative infinity.

* test/data/emacs-module/mod-test.c (Fmod_test_nanoseconds): Add test
function.
(emacs_module_init): Define it.

* test/src/emacs-module-tests.el (mod-test-nanoseconds): New unit test.

doc/lispref/internals.texi
test/data/emacs-module/mod-test.c
test/src/emacs-module-tests.el

index 10f49c569faf9a6be81206d06376f77ad6bfe46a..3e6488a5ccf002f38ad5e199b4bf0519ccab58d1 100644 (file)
@@ -1406,12 +1406,12 @@ billion.
 @xref{Elapsed Time,,,libc}.
 
 If @var{time} has higher precision than nanoseconds, then this
-function truncates it to nanosecond precision.  This function signals
-an error if @var{time} (truncated to nanoseconds) cannot be
-represented by @code{struct timespec}.  For example, if @code{time_t}
-is a 32-bit integral type, then a @var{time} value of ten billion
-seconds would signal an error, but a @var{time} value of 600
-picoseconds would get truncated to zero.
+function truncates it to nanosecond precision towards negative
+infinity.  This function signals an error if @var{time} (truncated to
+nanoseconds) cannot be represented by @code{struct timespec}.  For
+example, if @code{time_t} is a 32-bit integral type, then a @var{time}
+value of ten billion seconds would signal an error, but a @var{time}
+value of 600 picoseconds would get truncated to zero.
 
 If you need to deal with time values that are not representable by
 @code{struct timespec}, or if you want higher precision, call the Lisp
index 85a7f28e50d094489b3831046f4fc0f583beddde..8ac08f71534b7cac8b757286a2045851b287c288 100644 (file)
@@ -381,6 +381,22 @@ Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
   return env->make_time (env, time);
 }
 
+static emacs_value
+Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
+  assert (nargs == 1);
+  struct timespec time = env->extract_time (env, args[0]);
+  struct emacs_mpz nanoseconds;
+  assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX);
+  mpz_init_set_si (nanoseconds.value, time.tv_sec);
+  static_assert (1000000000 <= ULONG_MAX, "unsupported architecture");
+  mpz_mul_ui (nanoseconds.value, nanoseconds.value, 1000000000);
+  assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX);
+  mpz_add_ui (nanoseconds.value, nanoseconds.value, time.tv_nsec);
+  emacs_value result = env->make_big_integer (env, &nanoseconds);
+  mpz_clear (nanoseconds.value);
+  return result;
+}
+
 static emacs_value
 Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
                   void *data)
@@ -465,6 +481,7 @@ emacs_module_init (struct emacs_runtime *ert)
          NULL, NULL);
   DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
   DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, NULL);
+  DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
   DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
 
 #undef DEFUN
index 9eb38cd454876feb4b4606840c762f9796842287..173b63670fce60ffd5ee78948de2eec37383b803 100644 (file)
@@ -342,6 +342,25 @@ Interactively, you can try hitting \\[keyboard-quit] to quit."
     (ert-info ((format "input: %s" input))
       (should-error (mod-test-add-nanosecond input)))))
 
+(ert-deftest mod-test-nanoseconds ()
+  "Test truncation when converting to `struct timespec'."
+  (dolist (test-case '((0 . 0)
+                       (-1 . -1000000000)
+                       ((1 . 1000000000) . 1)
+                       ((-1 . 1000000000) . -1)
+                       ((1 . 1000000000000) . 0)
+                       ((-1 . 1000000000000) . -1)
+                       ((999 . 1000000000000) . 0)
+                       ((-999 . 1000000000000) . -1)
+                       ((1000 . 1000000000000) . 1)
+                       ((-1000 . 1000000000000) . -1)
+                       ((0 0 0 1) . 0)
+                       ((0 0 0 -1) . -1)))
+    (let ((input (car test-case))
+          (expected (cdr test-case)))
+      (ert-info ((format "input: %S, expected result: %d" input expected))
+        (should (eq (mod-test-nanoseconds input) expected))))))
+
 (ert-deftest mod-test-double ()
   (dolist (input (list 0 1 2 -1 42 12345678901234567890
                        most-positive-fixnum (1+ most-positive-fixnum)