[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