[m-rev.] for review: document how "next integer" operations handle infinite values

Julien Fischer jfischer at opturion.com
Tue Sep 4 17:00:40 AEST 2018


For review by anyone.

----------

Document how "next integer" operations handle infinite values.

Fix a test case failure in spf grades.

library/math.m:
      Document how the "next integer" operations handle arguments of infinite
      magnitude.

tests/general/float_test.m:
     s/ceil/ceiling/ in a spot.

     Test next integer operations with +/-infinity (and zero).

     In the erlang grades, avoid running parts of these tests that
     rely on library functionality that is NYI.

     Document what the expected outputs correspond to.

tests/general/float_test.exp:
     Update this expected output.

tests/general/float_test.exp2:
     Replace the contents of this file: previously it contained output for
     some ancient version of MSVC; it now contains the spf version of the
     output.

tests/general/float_test.exp3:
     A new expected output for the erlang grades.

Julien.

diff --git a/library/math.m b/library/math.m
index bda39b2..74cf915 100644
--- a/library/math.m
+++ b/library/math.m
@@ -56,21 +56,25 @@

      % ceiling(X) = Ceil is true if Ceil is the smallest integer
      % not less than X.
+    % If X is of infinite magnitude then Ceil = X.
      %
  :- func ceiling(float) = float.

      % floor(X) = Floor is true if Floor is the largest integer
      % not greater than X.
+    % If X is of infinite magnitude then Floor = X.
      %
  :- func floor(float) = float.

      % round(X) = Round is true if Round is the integer closest to X.
      % If X has a fractional value of 0.5, it is rounded up.
+    % If X is of infinite magnitude then Round = X.
      %
  :- func round(float) = float.

      % truncate(X) = Trunc is true if Trunc is the integer closest to X
      % such that |Trunc| =< |X|.
+    % If X is of infinite magnitude then Trunc = X.
      %
  :- func truncate(float) = float.

diff --git a/tests/general/float_test.exp b/tests/general/float_test.exp
index 134bf26..1aea778 100644
--- a/tests/general/float_test.exp
+++ b/tests/general/float_test.exp
@@ -6,6 +6,7 @@ X * Y:     12
  X - Y:     -1
  X / Y:   0.75
  X ^ Y:     81
+
  X:     41
  Y:     -3
  X + Y:     38
@@ -13,21 +14,44 @@ X * Y:   -123
  X - Y:     44
  X / Y:  -13.7
  X ^ Y: 1.45e-05
+
  Float max: 1.8e+308
  Float min: 2.23e-308
  Float epsilon: 2.22e-16
+
  Pi:   3.14
  e:   2.72
+
+X:      0
+ceiling(X):      0
+floor(X):      0
+round(X):      0
+truncate(X):      0
+
  X:    2.7
-ceil(X):      3
+ceiling(X):      3
  floor(X):      2
  round(X):      3
  truncate(X):      2
+
  X:   -3.6
-ceil(X):     -3
+ceiling(X):     -3
  floor(X):     -4
  round(X):     -4
  truncate(X):     -3
+
+X: infinity
+ceiling(X): infinity
+floor(X): infinity
+round(X): infinity
+truncate(X): infinity
+
+X: -infinity
+ceiling(X): -infinity
+floor(X): -infinity
+round(X): -infinity
+truncate(X): -infinity
+
  X:    2.2
  sqrt(X):   1.48
  ln(X):  0.788
@@ -35,6 +59,7 @@ log2(X):   1.14
  log10(X):  0.342
  log(2.1, X):   1.06
  exp(X):   9.03
+
  X:    0.5
  sin(X):  0.479
  cos(X):  0.878
@@ -43,7 +68,9 @@ sinh(X):  0.521
  cosh(X):   1.13
  tanh(X):  0.462
  atan2(sin(X), cos(X)):    0.5
+
  X:    0.6
  asin(X):  0.644
  acos(X):  0.927
  atan(X):   0.54
+
diff --git a/tests/general/float_test.exp2 b/tests/general/float_test.exp2
index fbf3fc1..5fb83b5 100644
--- a/tests/general/float_test.exp2
+++ b/tests/general/float_test.exp2
@@ -1,16 +1,76 @@
-1234.5678: 1.23e+003
+1234.5678: 1.23e+03
  X:      3
  Y:      4
  X + Y:      7
  X * Y:     12
  X - Y:     -1
  X / Y:   0.75
+X ^ Y:     81
+
  X:     41
  Y:     -3
  X + Y:     38
  X * Y:   -123
  X - Y:     44
  X / Y:  -13.7
-Float max: 1.8e+308
-Float min: 2.23e-308
-Float epsilon: 2.22e-016
+X ^ Y: 1.45e-05
+
+Float max: 3.4e+38
+Float min: 1.18e-38
+Float epsilon: 1.19e-07
+
+Pi:   3.14
+e:   2.72
+
+X:      0
+ceiling(X):      0
+floor(X):      0
+round(X):      0
+truncate(X):      0
+
+X:    2.7
+ceiling(X):      3
+floor(X):      2
+round(X):      3
+truncate(X):      2
+
+X:   -3.6
+ceiling(X):     -3
+floor(X):     -4
+round(X):     -4
+truncate(X):     -3
+
+X: infinity
+ceiling(X): infinity
+floor(X): infinity
+round(X): infinity
+truncate(X): infinity
+
+X: -infinity
+ceiling(X): -infinity
+floor(X): -infinity
+round(X): -infinity
+truncate(X): -infinity
+
+X:    2.2
+sqrt(X):   1.48
+ln(X):  0.788
+log2(X):   1.14
+log10(X):  0.342
+log(2.1, X):   1.06
+exp(X):   9.03
+
+X:    0.5
+sin(X):  0.479
+cos(X):  0.878
+tan(X):  0.546
+sinh(X):  0.521
+cosh(X):   1.13
+tanh(X):  0.462
+atan2(sin(X), cos(X)):    0.5
+
+X:    0.6
+asin(X):  0.644
+acos(X):  0.927
+atan(X):   0.54
+
diff --git a/tests/general/float_test.exp3 b/tests/general/float_test.exp3
index e69de29..a699f4b 100644
--- a/tests/general/float_test.exp3
+++ b/tests/general/float_test.exp3
@@ -0,0 +1,64 @@
+1234.5678: 1.23e+03
+X:      3
+Y:      4
+X + Y:      7
+X * Y:     12
+X - Y:     -1
+X / Y:   0.75
+X ^ Y:     81
+
+X:     41
+Y:     -3
+X + Y:     38
+X * Y:   -123
+X - Y:     44
+X / Y:  -13.7
+X ^ Y: 1.45e-05
+
+Float max: 1.8e+308
+Float min: 2.23e-308
+Float epsilon: 2.22e-16
+
+Pi:   3.14
+e:   2.72
+
+X:      0
+ceiling(X):      0
+floor(X):      0
+round(X):      0
+truncate(X):      0
+
+X:    2.7
+ceiling(X):      3
+floor(X):      2
+round(X):      3
+truncate(X):      2
+
+X:   -3.6
+ceiling(X):     -3
+floor(X):     -4
+round(X):     -4
+truncate(X):     -3
+
+X:    2.2
+sqrt(X):   1.48
+ln(X):  0.788
+log2(X):   1.14
+log10(X):  0.342
+log(2.1, X):   1.06
+exp(X):   9.03
+
+X:    0.5
+sin(X):  0.479
+cos(X):  0.878
+tan(X):  0.546
+sinh(X):  0.521
+cosh(X):   1.13
+tanh(X):  0.462
+atan2(sin(X), cos(X)):    0.5
+
+X:    0.6
+asin(X):  0.644
+acos(X):  0.927
+atan(X):   0.54
+
diff --git a/tests/general/float_test.m b/tests/general/float_test.m
index c6602d0..e982d95 100644
--- a/tests/general/float_test.m
+++ b/tests/general/float_test.m
@@ -5,6 +5,10 @@
  % A very basic check of floating point arithmetic and string.to_float.
  % Now tests maths library stuff too.
  %
+% The .exp file is for grades that use double-precision floats.
+% The .exp2 file is for grades that use single-precision floats.
+% The .exp3 file is for the erlang grades (see below).
+%
  %---------------------------------------------------------------------------%

  :- module float_test.
@@ -36,8 +40,16 @@ main(!IO) :-
      test_arithmetic(41.0, -3.0, !IO),
      test_constants(!IO),
      test_math_constants(!IO),
+    test_rounding(0.0, !IO),
      test_rounding(2.7, !IO),
      test_rounding(-3.6, !IO),
+    ( if have_erlang_grade then
+        true
+    else
+        % float.infinity is NYI for Erlang.
+        test_rounding(float.infinity, !IO),
+        test_rounding(-float.infinity, !IO)
+    ),
      test_power(2.2, !IO),
      test_trig(0.5, !IO),
      test_inv_trig(0.6, !IO).
@@ -63,7 +75,8 @@ test_arithmetic(X, Y, !IO) :-
      write_message("X * Y: ", Times, !IO),
      write_message("X - Y: ", Minus, !IO),
      write_message("X / Y: ", Divide, !IO),
-    write_message("X ^ Y: ", Pow, !IO).
+    write_message("X ^ Y: ", Pow, !IO),
+    io.nl(!IO).

  %---------------------------------------------------------------------------%

@@ -72,7 +85,8 @@ test_arithmetic(X, Y, !IO) :-
  test_constants(!IO) :-
      write_message("Float max: ", float.max, !IO),
      write_message("Float min: ", float.min, !IO),
-    write_message("Float epsilon: ", float.epsilon, !IO).
+    write_message("Float epsilon: ", float.epsilon, !IO),
+    io.nl(!IO).

  %---------------------------------------------------------------------------%

@@ -80,7 +94,8 @@ test_constants(!IO) :-

  test_math_constants(!IO) :-
      write_message("Pi: ", math.pi, !IO),
-    write_message("e: ", math.e, !IO).
+    write_message("e: ", math.e, !IO),
+    io.nl(!IO).

  %---------------------------------------------------------------------------%

@@ -88,10 +103,11 @@ test_math_constants(!IO) :-

  test_rounding(X, !IO) :-
      write_message("X: ", X, !IO),
-    write_message("ceil(X): ", math.ceiling(X), !IO),
+    write_message("ceiling(X): ", math.ceiling(X), !IO),
      write_message("floor(X): ", math.floor(X), !IO),
      write_message("round(X): ", math.round(X), !IO),
-    write_message("truncate(X): ", math.truncate(X), !IO).
+    write_message("truncate(X): ", math.truncate(X), !IO),
+    io.nl(!IO).

  %---------------------------------------------------------------------------%

@@ -104,7 +120,8 @@ test_power(X, !IO) :-
      write_message("log2(X): ", math.log2(X), !IO),
      write_message("log10(X): ", math.log10(X), !IO),
      write_message("log(2.1, X): ", math.log(2.1, X), !IO),
-    write_message("exp(X): ", math.exp(X), !IO).
+    write_message("exp(X): ", math.exp(X), !IO),
+    io.nl(!IO).

  %---------------------------------------------------------------------------%

@@ -119,7 +136,8 @@ test_trig(X, !IO) :-
      write_message("cosh(X): ", math.cosh(X), !IO),
      write_message("tanh(X): ", math.tanh(X), !IO),
      write_message("atan2(sin(X), cos(X)): ",
-        math.atan2(math.sin(X), math.cos(X)), !IO).
+        math.atan2(math.sin(X), math.cos(X)), !IO),
+    io.nl(!IO).

  %---------------------------------------------------------------------------%

@@ -129,7 +147,22 @@ test_inv_trig(X, !IO) :-
      write_message("X: ", X, !IO),
      write_message("asin(X): ", math.asin(X), !IO),
      write_message("acos(X): ", math.acos(X), !IO),
-    write_message("atan(X): ", math.atan(X), !IO).
+    write_message("atan(X): ", math.atan(X), !IO),
+    io.nl(!IO).
+
+%---------------------------------------------------------------------------%
+
+:- pred have_erlang_grade is semidet.
+
+:- pragma foreign_proc("Erlang",
+    have_erlang_grade,
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    SUCCESS_INDICATOR = true
+").
+
+have_erlang_grade :-
+    semidet_false.

  %---------------------------------------------------------------------------%
  %---------------------------------------------------------------------------%


More information about the reviews mailing list