[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