[m-rev.] for review: add int32.clamp/3
Julien Fischer
jfischer at opturion.com
Wed Mar 4 12:13:37 AEDT 2026
For review by anyone.
I intend to add the clamp/3 to all of the integer modules. I will add
it for the others
after this change is reviewed.
-----------------------
Add int32.clamp/3.
library/int32.m:
Add the new function.
NEWS.md:
As above.
tests/hard_coded/Mmakefile:
tests/hard_coded/clamp_int32.{m,exp}:
Add a test for the new function.
Julien.
diff --git a/NEWS.md b/NEWS.md
index 02d807d24..277833651 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -458,6 +458,7 @@ Changes to the Mercury standard library
- func `<<u/2`
- func `>>u/2`
+ - func `clamp/3`
- func `unchecked_left_ushift/2`
- func `unchecked_right_ushift/2`
diff --git a/library/int32.m b/library/int32.m
index bc8f526fa..6f4d6b73c 100644
--- a/library/int32.m
+++ b/library/int32.m
@@ -189,6 +189,14 @@
%
:- func min(int32, int32) = int32.
+ % clamp(Min, Max, N):
+ %
+ % Clamp N to the range [Min, Max] (inclusive).
+ % Returns Min if N < Min, Max if N > Max, and N otherwise.
+ % Throws an exception if Max < Min.
+ %
+:- func clamp(int32, int32, int32) = int32.
+
%---------------------------------------------------------------------------%
%
% Absolute values.
@@ -757,6 +765,13 @@ max(X, Y) =
min(X, Y) =
( if X < Y then X else Y ).
+clamp(Min, Max, N) =
+ ( if Max >= Min then
+ max(Min, min(Max, N))
+ else
+ func_error($pred, "Max < Min")
+ ).
+
%---------------------------------------------------------------------------%
abs(Num) =
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 34ae53c32..5e90bda8a 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -789,6 +789,7 @@ ifeq "$(findstring profdeep,$(GRADE))" ""
bitwise_uint64 \
bitwise_uint8 \
char_to_string \
+ clamp_int32 \
cmp_int16 \
cmp_int32 \
cmp_int64 \
diff --git a/tests/hard_coded/clamp_int32.exp b/tests/hard_coded/clamp_int32.exp
new file mode 100644
index 000000000..61377324c
--- /dev/null
+++ b/tests/hard_coded/clamp_int32.exp
@@ -0,0 +1,72 @@
+clamp(-2, 12, -2147483648) = -2
+clamp(-2, 12, -32768) = -2
+clamp(-2, 12, -128) = -2
+clamp(-2, 12, 0) = 0
+clamp(-2, 12, 1) = 1
+clamp(-2, 12, 2) = 2
+clamp(-2, 12, 8) = 8
+clamp(-2, 12, 10) = 10
+clamp(-2, 12, 16) = 12
+clamp(-2, 12, 127) = 12
+clamp(-2, 12, 32767) = 12
+clamp(-2, 12, 2147483647) = 12
+clamp(-10, 5, -2147483648) = -10
+clamp(-10, 5, -32768) = -10
+clamp(-10, 5, -128) = -10
+clamp(-10, 5, 0) = 0
+clamp(-10, 5, 1) = 1
+clamp(-10, 5, 2) = 2
+clamp(-10, 5, 8) = 5
+clamp(-10, 5, 10) = 5
+clamp(-10, 5, 16) = 5
+clamp(-10, 5, 127) = 5
+clamp(-10, 5, 32767) = 5
+clamp(-10, 5, 2147483647) = 5
+clamp(0, 0, -2147483648) = 0
+clamp(0, 0, -32768) = 0
+clamp(0, 0, -128) = 0
+clamp(0, 0, 0) = 0
+clamp(0, 0, 1) = 0
+clamp(0, 0, 2) = 0
+clamp(0, 0, 8) = 0
+clamp(0, 0, 10) = 0
+clamp(0, 0, 16) = 0
+clamp(0, 0, 127) = 0
+clamp(0, 0, 32767) = 0
+clamp(0, 0, 2147483647) = 0
+clamp(-1, 1, -2147483648) = -1
+clamp(-1, 1, -32768) = -1
+clamp(-1, 1, -128) = -1
+clamp(-1, 1, 0) = 0
+clamp(-1, 1, 1) = 1
+clamp(-1, 1, 2) = 1
+clamp(-1, 1, 8) = 1
+clamp(-1, 1, 10) = 1
+clamp(-1, 1, 16) = 1
+clamp(-1, 1, 127) = 1
+clamp(-1, 1, 32767) = 1
+clamp(-1, 1, 2147483647) = 1
+clamp(5, 10, -2147483648) = 5
+clamp(5, 10, -32768) = 5
+clamp(5, 10, -128) = 5
+clamp(5, 10, 0) = 5
+clamp(5, 10, 1) = 5
+clamp(5, 10, 2) = 5
+clamp(5, 10, 8) = 8
+clamp(5, 10, 10) = 10
+clamp(5, 10, 16) = 10
+clamp(5, 10, 127) = 10
+clamp(5, 10, 32767) = 10
+clamp(5, 10, 2147483647) = 10
+clamp(12, 6, -2147483648) = <<exception>>
+clamp(12, 6, -32768) = <<exception>>
+clamp(12, 6, -128) = <<exception>>
+clamp(12, 6, 0) = <<exception>>
+clamp(12, 6, 1) = <<exception>>
+clamp(12, 6, 2) = <<exception>>
+clamp(12, 6, 8) = <<exception>>
+clamp(12, 6, 10) = <<exception>>
+clamp(12, 6, 16) = <<exception>>
+clamp(12, 6, 127) = <<exception>>
+clamp(12, 6, 32767) = <<exception>>
+clamp(12, 6, 2147483647) = <<exception>>
diff --git a/tests/hard_coded/clamp_int32.m b/tests/hard_coded/clamp_int32.m
new file mode 100644
index 000000000..73bb14208
--- /dev/null
+++ b/tests/hard_coded/clamp_int32.m
@@ -0,0 +1,83 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%---------------------------------------------------------------------------%
+
+% Test clamp/3 signed 32-bit integers.
+
+:- module clamp_int32.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module exception.
+:- import_module int32.
+:- import_module list.
+:- import_module pair.
+:- import_module string.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+ list.foldl(run_clamp_test(numbers), ranges, !IO).
+
+:- pred run_clamp_test(list(int32)::in, pair(int32)::in, io::di, io::uo)
+ is cc_multi.
+
+run_clamp_test(Numbers, Range, !IO) :-
+ list.foldl(run_clamp_test_2(Range), Numbers, !IO).
+
+:- pred run_clamp_test_2(pair(int32)::in, int32::in, io::di, io::uo)
+ is cc_multi.
+
+run_clamp_test_2(Range, N, !IO) :-
+ Range = Min - Max,
+ ( try []
+ Result = int32.clamp(Min, Max, N)
+ then
+ ResultStr = int32_to_string(Result)
+ catch_any _ ->
+ ResultStr = "<<exception>>"
+ ),
+ io.format("clamp(%d, %d, %d) = %s\n",
+ [i32(Min), i32(Max), i32(N), s(ResultStr)], !IO).
+
+%---------------------------------------------------------------------------%
+
+:- func numbers = list(int32).
+
+numbers = [
+ -2_147_483_648_i32,
+ -32_768_i32,
+ -128_i32,
+ 0_i32,
+ 1_i32,
+ 2_i32,
+ 8_i32,
+ 10_i32,
+ 16_i32,
+ 127_i32,
+ 32_767_i32,
+ 2_147_483_647_i32
+].
+
+:- func ranges = list(pair(int32)).
+
+ranges = [
+ -2i32 - 12i32,
+ -10i32 - 5i32,
+ 0i32 - 0i32,
+ -1i32 - 1i32,
+ 5i32 - 10i32,
+ 12i32 - 6i32
+].
+
+%---------------------------------------------------------------------------%
+:- end_module clamp_int32.
+%---------------------------------------------------------------------------%
More information about the reviews
mailing list