[m-rev.] for review: avoid undefined behaviour of int.abs.
Julien Fischer
jfischer at opturion.com
Mon Jan 15 03:56:35 AEDT 2018
For review by anyone.
The following is what was discussed back in Oct. 2016, except that I
haven't added a new exception type specific for overflows (yet).
I will do something similar for ther other signed integer types once
this is reviewed adn committed.
-----------------------
Avoid undefined behaviour of int.abs.
library.m:
Make int.abs throw an exception for int.min_int.
Add the new function unchecked_abs/1, whose behaviour is
undefined for int.min_int.
Add the new function nabs/1 which computes the negative
absolute value of an int Unlike abs, this is defined for
all ints.
NEWS:
Announce the above.
Unrelated change: list int64 and uint64 as reserved type names.
Julien.
diff --git a/NEWS b/NEWS
index 05be405..2e96a9a 100644
--- a/NEWS
+++ b/NEWS
@@ -44,9 +44,9 @@ Changes that may break compatibility:
type names are:
int
- int{8,16,32}
+ int{8,16,32,64}
uint
- uint{8,16,32}
+ uint{8,16,32,64}
float
character
string
@@ -113,6 +113,10 @@ Changes that may break compatibility:
int.legacy_left_shift/2 and int.legacy_right_shift/2. These functions
will be deleted in a future release.
+* We have changed the semantics of int.abs/1 so that it throws an exception
+ if its argument is equal to int.min_int. The old behaviour of this function
+ is provided by the the new function int.unchecked_abs/1.
+
Changes to the Mercury language:
* We have added a new primitive type, uint, which is an unsigned integer type
@@ -386,9 +390,10 @@ Changes to the Mercury standard library:
queue ADT. This is a blend between a priority queue and a map. This was
contributed by Matthias Güdemann.
-* We have added the following predicate to the int module:
+* The following predicates and functions have been added to the int module:
- all_true_in_range/3
+ - nabs/1
* We have added a predicate named is_dummy_context to the term module.
diff --git a/library/int.m b/library/int.m
index 4dad325..e0b7cd6 100644
--- a/library/int.m
+++ b/library/int.m
@@ -1,7 +1,8 @@
%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
-% Copyright (C) 1994-2011 The University of Melbourne.
+% Copyright (C) 1994-2012 The University of Melbourne.
+% Copyright (C) 2013-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.
%---------------------------------------------------------------------------%
@@ -52,11 +53,24 @@
%---------------------------------------------------------------------------%
- % Absolute value.
+ % abs(X) returns the absolute value of X.
+ % Throws an exception if X = int.min_int.
%
:- func abs(int) = int.
:- pred abs(int::in, int::out) is det.
+ % unchecked(X) returns the absolute value of X, except that the result is
+ % undefined if X = int.min_int.
+ %
+:- func unchecked_abs(int) = int.
+
+ % nabs(X) returns the negative absolute value of X.
+ % Unlike abs/1 this function is defined for X = int.min_int.
+ %
+:- func nabs(int) = int.
+
+%---------------------------------------------------------------------------%
+
% Maximum.
%
:- func max(int, int) = int.
@@ -584,12 +598,28 @@ abs(Num) = Abs :-
abs(Num, Abs).
abs(Num, Abs) :-
+ ( if Num = int.min_int then
+ throw(software_error("int.abs: abs(min_int) would overflow"))
+ else
+ Abs = unchecked_abs(Num)
+ ).
+
+unchecked_abs(Num) =
( if Num < 0 then
- Abs = 0 - Num
+ 0 - Num
else
- Abs = Num
+ Num
).
+nabs(Num) =
+ ( if Num > 0 then
+ -Num
+ else
+ Num
+ ).
+
+%---------------------------------------------------------------------------%
+
max(X, Y) = Max :-
max(X, Y, Max).
More information about the reviews
mailing list