[m-rev.] diff: absolute value for fixed size signed integers

Julien Fischer jfischer at opturion.com
Mon Jan 15 11:52:49 AEDT 2018


Absolute value for fixed size signed integers.

library/int8.m:
library/int16.m:
library/int32.m:
     Implement abs/1, unchecked_abs/1 and nabs/1 for int8, in16 and int32.

tests/hard_coded/arith_int{8,16,32}.{m,exp}:
     Extend these tests to cover abs and nabs.

Julien.

diff --git a/library/int16.m b/library/int16.m
index 4ce54cf..9bcbf83 100644
--- a/library/int16.m
+++ b/library/int16.m
@@ -1,7 +1,7 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
  %---------------------------------------------------------------------------%
-% Copyright (C) 2017 The Mercury team.
+% Copyright (C) 2017-2018 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -69,6 +69,23 @@

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

+    % abs(X) returns the absolute value of X.
+    % Throws an exception if X = int16.min_int16.
+    %
+:- func abs(int16) = int16.
+
+    % unchecked_abs(X) returns the absolute value of X, except that the result
+    % is undefined if X = int16.min_int16.
+    %
+:- func unchecked_abs(int16) = int16.
+
+    % nabs(X) returns the negative absolute value of X.
+    % Unlike abs/1 this function is defined for X = int16.min_int16.
+    %
+:- func nabs(int16) = int16.
+
+%---------------------------------------------------------------------------%
+
      % Maximum.
      %
  :- func max(int16, int16) = int16.
@@ -366,6 +383,29 @@ from_bytes_be(MSB, LSB) =

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

+abs(Num) =
+    ( if Num = int16.min_int16 then
+        throw(software_error("int16.abs: abs(min_int16) would overflow"))
+    else
+        unchecked_abs(Num)
+    ).
+
+unchecked_abs(Num) =
+    ( if Num < 0i16 then
+        0i16 - Num
+    else
+        Num
+    ).
+
+nabs(Num) =
+    ( if Num > 0i16 then
+        -Num
+    else
+        Num
+    ).
+
+%---------------------------------------------------------------------------%
+
  max(X, Y) =
      ( if X > Y then X else Y ).

diff --git a/library/int32.m b/library/int32.m
index 57ffb74..2594179 100644
--- a/library/int32.m
+++ b/library/int32.m
@@ -1,7 +1,7 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
  %---------------------------------------------------------------------------%
-% Copyright (C) 2017 The Mercury team.
+% Copyright (C) 2017-2018 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -71,6 +71,33 @@

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

+    % abs(X) returns the absolute value of X.
+    % Throws an exception if X = int32.min_int32.
+    %
+:- func abs(int32) = int32.
+
+    % unchecked_abs(X) returns the absolute value of X, except that the result
+    % is undefined if X = int32.min_int32.
+    %
+:- func unchecked_abs(int32) = int32.
+
+    % nabs(X) returns the negative absolute value of X.
+    % Unlike abs/1 this function is defined for X = int32.min_int32.
+    %
+:- func nabs(int32) = int32.
+
+%---------------------------------------------------------------------------%
+
+    % Maximum.
+    %
+:- func max(int32, int32) = int32.
+
+    % Minimum.
+    %
+:- func min(int32, int32) = int32.
+
+%---------------------------------------------------------------------------%
+
      % Unary plus.
      %
  :- func + (int32::in) = (int32::uo) is det.
@@ -102,14 +129,6 @@
  :- func (int32::in) * (int32::in) = (int32::uo) is det.
  :- func times(int32, int32) = int32.

-    % Maximum.
-    %
-:- func max(int32, int32) = int32.
-
-    % Minimum.
-    %
-:- func min(int32, int32) = int32.
-
      % Flooring integer division.
      % Truncates towards minus infinity, e.g. (-10_i32) div 3_i32 = (-4_i32).
      %
@@ -455,6 +474,29 @@ X >> Y = Result :-

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

+abs(Num) =
+    ( if Num = int32.min_int32 then
+        throw(software_error("int32.abs: abs(min_int32) would overflow"))
+    else
+        unchecked_abs(Num)
+    ).
+
+unchecked_abs(Num) =
+    ( if Num < 0i32 then
+        0i32 - Num
+    else
+        Num
+    ).
+
+nabs(Num) =
+    ( if Num > 0i32 then
+        -Num
+    else
+        Num
+    ).
+
+%---------------------------------------------------------------------------%
+
  max(X, Y) =
      ( if X > Y then X else Y ).

diff --git a/library/int8.m b/library/int8.m
index e2d990e..d48b972 100644
--- a/library/int8.m
+++ b/library/int8.m
@@ -1,7 +1,7 @@
  %---------------------------------------------------------------------------%
  % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
  %---------------------------------------------------------------------------%
-% Copyright (C) 2017 The Mercury team.
+% Copyright (C) 2017-2018 The Mercury team.
  % This file may only be copied under the terms of the GNU Library General
  % Public License - see the file COPYING.LIB in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -56,6 +56,23 @@

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

+    % abs(X) returns the absolute value of X.
+    % Throws an exception if X = int8.min_int8.
+    %
+:- func abs(int8) = int8.
+
+    % unchecked_abs(X) returns the absolute value of X, except that the result
+    % is undefined if X = int8.min_int8.
+    %
+:- func unchecked_abs(int8) = int8.
+
+    % nabs(X) returns the negative absolute value of X.
+    % Unlike abs/1 this function is defined for X = int8.min_int8.
+    %
+:- func nabs(int8) = int8.
+
+%---------------------------------------------------------------------------%
+
      % Maximum.
      %
  :- func max(int8, int8) = int8.
@@ -369,6 +386,29 @@ X >> Y = Result :-

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

+abs(Num) =
+    ( if Num = int8.min_int8 then
+        throw(software_error("int8.abs: abs(min_int8) would overflow"))
+    else
+        unchecked_abs(Num)
+    ).
+
+unchecked_abs(Num) =
+    ( if Num < 0i8 then
+        0i8 - Num
+    else
+        Num
+    ).
+
+nabs(Num) =
+    ( if Num > 0i8 then
+        -Num
+    else
+        Num
+    ).
+
+%---------------------------------------------------------------------------%
+
  max(X, Y) =
      ( if X > Y then X else Y ).

diff --git a/tests/hard_coded/arith_int16.exp b/tests/hard_coded/arith_int16.exp
index aaf6d09..d106efb 100644
--- a/tests/hard_coded/arith_int16.exp
+++ b/tests/hard_coded/arith_int16.exp
@@ -26,6 +26,34 @@
  - 255 = -255
  - 32767 = -32767

+*** Test unary operation 'abs' ***
+
+abs -32768 = <<exception>>
+abs -128 = 128
+abs 0 = 0
+abs 1 = 1
+abs 2 = 2
+abs 8 = 8
+abs 10 = 10
+abs 16 = 16
+abs 127 = 127
+abs 255 = 255
+abs 32767 = 32767
+
+*** Test unary operation 'nabs' ***
+
+nabs -32768 = -32768
+nabs -128 = -128
+nabs 0 = 0
+nabs 1 = -1
+nabs 2 = -2
+nabs 8 = -8
+nabs 10 = -10
+nabs 16 = -16
+nabs 127 = -127
+nabs 255 = -255
+nabs 32767 = -32767
+
  *** Test binary operation '+' ***

  -32768 + -32768 = 0
diff --git a/tests/hard_coded/arith_int16.m b/tests/hard_coded/arith_int16.m
index 5f997ae..139aef1 100644
--- a/tests/hard_coded/arith_int16.m
+++ b/tests/hard_coded/arith_int16.m
@@ -29,8 +29,10 @@ main(!IO) :-
      io.nl(!IO),
      run_unop_test(int16.(-), "-", !IO),
      io.nl(!IO),
-    %run_unop_test(int16.abs, "abs", !IO),
-    %io.nl(!IO),
+    run_unop_test(int16.abs, "abs", !IO),
+    io.nl(!IO),
+    run_unop_test(int16.nabs, "nabs", !IO),
+    io.nl(!IO),
      run_binop_test((func(X, Y) = X + Y), "+", !IO),
      io.nl(!IO),
      run_binop_test((func(X, Y) = X - Y), "-", !IO),
diff --git a/tests/hard_coded/arith_int32.exp b/tests/hard_coded/arith_int32.exp
index 8a46ab2..7ff8966 100644
--- a/tests/hard_coded/arith_int32.exp
+++ b/tests/hard_coded/arith_int32.exp
@@ -28,6 +28,36 @@
  - 32767 = -32767
  - 2147483647 = -2147483647

+*** Test unary operation 'abs' ***
+
+abs -2147483648 = <<exception>>
+abs -32768 = 32768
+abs -128 = 128
+abs 0 = 0
+abs 1 = 1
+abs 2 = 2
+abs 8 = 8
+abs 10 = 10
+abs 16 = 16
+abs 127 = 127
+abs 32767 = 32767
+abs 2147483647 = 2147483647
+
+*** Test unary operation 'nabs' ***
+
+nabs -2147483648 = -2147483648
+nabs -32768 = -32768
+nabs -128 = -128
+nabs 0 = 0
+nabs 1 = -1
+nabs 2 = -2
+nabs 8 = -8
+nabs 10 = -10
+nabs 16 = -16
+nabs 127 = -127
+nabs 32767 = -32767
+nabs 2147483647 = -2147483647
+
  *** Test binary operation '+' ***

  -2147483648 + -2147483648 = 0
diff --git a/tests/hard_coded/arith_int32.m b/tests/hard_coded/arith_int32.m
index b0e87a0..123ae30 100644
--- a/tests/hard_coded/arith_int32.m
+++ b/tests/hard_coded/arith_int32.m
@@ -29,8 +29,10 @@ main(!IO) :-
      io.nl(!IO),
      run_unop_test(int32.(-), "-", !IO),
      io.nl(!IO),
-    %run_unop_test(int32.abs, "abs", !IO),
-    %io.nl(!IO),
+    run_unop_test(int32.abs, "abs", !IO),
+    io.nl(!IO),
+    run_unop_test(int32.nabs, "nabs", !IO),
+    io.nl(!IO),
      run_binop_test((func(X, Y) = X + Y), "+", !IO),
      io.nl(!IO),
      run_binop_test((func(X, Y) = X - Y), "-", !IO),
diff --git a/tests/hard_coded/arith_int8.exp b/tests/hard_coded/arith_int8.exp
index 5bc2a5c..cbfedab 100644
--- a/tests/hard_coded/arith_int8.exp
+++ b/tests/hard_coded/arith_int8.exp
@@ -30,6 +30,38 @@
  - 16 = -16
  - 127 = -127

+*** Test unary operation 'abs' ***
+
+abs -128 = <<exception>>
+abs -16 = 16
+abs -10 = 10
+abs -8 = 8
+abs -2 = 2
+abs -1 = 1
+abs 0 = 0
+abs 1 = 1
+abs 2 = 2
+abs 8 = 8
+abs 10 = 10
+abs 16 = 16
+abs 127 = 127
+
+*** Test unary operation 'nabs' ***
+
+nabs -128 = -128
+nabs -16 = -16
+nabs -10 = -10
+nabs -8 = -8
+nabs -2 = -2
+nabs -1 = -1
+nabs 0 = 0
+nabs 1 = -1
+nabs 2 = -2
+nabs 8 = -8
+nabs 10 = -10
+nabs 16 = -16
+nabs 127 = -127
+
  *** Test binary operation '+' ***

  -128 + -128 = 0
diff --git a/tests/hard_coded/arith_int8.m b/tests/hard_coded/arith_int8.m
index 57540e6..044db15 100644
--- a/tests/hard_coded/arith_int8.m
+++ b/tests/hard_coded/arith_int8.m
@@ -29,9 +29,10 @@ main(!IO) :-
      io.nl(!IO),
      run_unop_test(int8.(-), "-", !IO),
      io.nl(!IO),
-    % int8.abs NYI.
-    %run_unop_test(int8.abs, "abs", !IO),
-    %io.nl(!IO),
+    run_unop_test(int8.abs, "abs", !IO),
+    io.nl(!IO),
+    run_unop_test(int8.nabs, "nabs", !IO),
+    io.nl(!IO),
      run_binop_test((func(X, Y) = X + Y), "+", !IO),
      io.nl(!IO),
      run_binop_test((func(X, Y) = X - Y), "-", !IO),


More information about the reviews mailing list