[m-rev.] for post-commit review: add casts to and from int32 and int{8, 16, 64}

Julien Fischer jfischer at opturion.com
Fri Jan 14 14:46:54 AEDT 2022


For post-commit review by anyone.

The only thing that really requires review is the documentation and NEWS
file entry; the implementation is trivial.

-------------------------------------------

Add casts to and from int32 and int{8,16,64}.

library/int32.m:
      Add the above casts.

NEWS:
      Announce the additions.

tests/hard_coded/Mmakefile:
tests/hard_coded/int32_int{8,16,64}.{m,exp}:
      Add tests of the new functions.

Julien.

diff --git a/NEWS b/NEWS
index 3b55efc..f5a842c 100644
--- a/NEWS
+++ b/NEWS
@@ -176,6 +176,17 @@ Changes to the Mercury standard library
      - func `legacy_left_shift/2`    (replacement: `<<`)
      - func `legacy_right_shift/2`   (replacement: `>>`)

+### Changes to the `int32` module
+
+* The following functions have been added:
+
+    - func `cast_to_int8`
+    - func `cast_from_int8`
+    - func `cast_to_int16`
+    - func `cast_from_int16`
+    - func `cast_to_int64`
+    - func `cast_from_int64`
+
  ### Changes to the `integer` module

  * The following obsolete functions have been removed:
diff --git a/library/int32.m b/library/int32.m
index 0e50cb7..6e5a330 100644
--- a/library/int32.m
+++ b/library/int32.m
@@ -1,7 +1,7 @@
  %---------------------------------------------------------------------------%
  % vim: ts=4 sw=4 et ft=mercury
  %---------------------------------------------------------------------------%
-% Copyright (C) 2017-2018 The Mercury team.
+% Copyright (C) 2017-2022 The Mercury team.
  % This file is distributed under the terms specified in COPYING.LIB.
  %---------------------------------------------------------------------------%
  %
@@ -68,6 +68,69 @@

  %---------------------------------------------------------------------------%
  %
+% Conversion to/from int8.
+%
+
+    % cast_to_int8(I32) = I8:
+    %
+    % Convert an int32 to an int8.
+    % Always succeeds, but will yield a result that is mathematically equal
+    % to I32 only if I32 is in [-(2^7), 2^7 - 1].
+    %
+:- func cast_to_int8(int32) = int8.
+
+    % cast_from_int8(I8) = I32:
+    %
+    % Convert an int8 to a int32.
+    % Always succeeds, and yields a result that is mathemtically equal
+    % to I8.
+    %
+:- func cast_from_int8(int8) = int32.
+
+%---------------------------------------------------------------------------%
+%
+% Conversion to/from int16.
+%
+
+    % cast_to_int16(I32) = I16:
+    %
+    % Convert an int32 to an int16.
+    % Always succeeds, but will yield a result that is mathematically equal
+    % to I32 only if I32 is in [-(2^15), 2^15 - 1].
+    %
+:- func cast_to_int16(int32) = int16.
+
+    % cast_from_int16(I16) = I32:
+    %
+    % Convert an int16 to a int32.
+    % Always succeeds, and yields a result that is mathemtically equal
+    % to I16.
+    %
+:- func cast_from_int16(int16) = int32.
+
+%---------------------------------------------------------------------------%
+%
+% Conversion to/from int64.
+%
+
+    % cast_to_int64(I32) = I64:
+    %
+    % Convert an int32 to an int64.
+    % Always succeeds, and always yields a result that is
+    % mathematically equal to I32.
+    %
+:- func cast_to_int64(int32) = int64.
+
+    % cast_from_int64(I64) = I32:
+    %
+    % Convert an int64 to a int32.
+    % Always succeeds, but will yield a result that is mathematically equal
+    % to I only if I is in [0, 2^32 - 1].
+    %
+:- func cast_from_int64(int64) = int32.
+
+%---------------------------------------------------------------------------%
+%
  % Change of signedness.
  %

@@ -476,6 +539,150 @@ det_from_int(I) = I32 :-
  %---------------------------------------------------------------------------%

  :- pragma foreign_proc("C",
+    cast_to_int8(I32::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I8 = (int8_t) I32;
+").
+
+:- pragma foreign_proc("C#",
+    cast_to_int8(I32::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I8 = (sbyte) I32;
+").
+
+:- pragma foreign_proc("Java",
+    cast_to_int8(I32::in) = (I8::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I8 = (byte) I32;
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int8(I8::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I32 = I8;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int8(I8::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = I8;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int8(I8::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = I8;
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_to_int16(I32::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I16 = (int16_t) I32;
+").
+
+:- pragma foreign_proc("C#",
+    cast_to_int16(I32::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) I32;
+").
+
+:- pragma foreign_proc("Java",
+    cast_to_int16(I32::in) = (I16::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I16 = (short) I32;
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int16(I16::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I32 = I16;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int16(I16::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = I16;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int16(I16::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = I16;
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_to_int64(I32::in) = (I64::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I64 = (int64_t) I32;
+").
+
+:- pragma foreign_proc("C#",
+    cast_to_int64(I32::in) = (I64::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I64 = (long) I32;
+").
+
+:- pragma foreign_proc("Java",
+    cast_to_int64(I32::in) = (I64::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I64 = (long) I32;
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
+    cast_from_int64(I64::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        does_not_affect_liveness],
+"
+    I32 = (int32_t) I64;
+").
+
+:- pragma foreign_proc("C#",
+    cast_from_int64(I64::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = (int) I64;
+").
+
+:- pragma foreign_proc("Java",
+    cast_from_int64(I64::in) = (I32::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I32 = (int) I64;
+").
+
+%---------------------------------------------------------------------------%
+
+:- pragma foreign_proc("C",
      cast_from_uint32(U32::in) = (I32::out),
      [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
          does_not_affect_liveness],
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 13c7e85..f3d88b0 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -209,6 +209,8 @@ ORDINARY_PROGS = \
  	inst_alias \
  	int16_from_bytes \
  	int32_from_bytes \
+	int32_int16_casts \
+	int32_int8_casts \
  	int64_from_bytes \
  	int_fold_up_down \
  	int_impl_imports \
diff --git a/tests/hard_coded/int32_int16_casts.exp b/tests/hard_coded/int32_int16_casts.exp
index e69de29..11f2d49 100644
--- a/tests/hard_coded/int32_int16_casts.exp
+++ b/tests/hard_coded/int32_int16_casts.exp
@@ -0,0 +1,38 @@
+cast_from_int16(-32768i16) = -32768i16
+cast_from_int16(-128i16) = -128i16
+cast_from_int16(-64i16) = -64i16
+cast_from_int16(-56i16) = -56i16
+cast_from_int16(-1i16) = -1i16
+cast_from_int16(0i16) = 0i16
+cast_from_int16(1i16) = 1i16
+cast_from_int16(7i16) = 7i16
+cast_from_int16(8i16) = 8i16
+cast_from_int16(15i16) = 15i16
+cast_from_int16(16i16) = 16i16
+cast_from_int16(31i16) = 31i16
+cast_from_int16(32i16) = 32i16
+cast_from_int16(63i16) = 63i16
+cast_from_int16(64i16) = 64i16
+cast_from_int16(127i16) = 127i16
+cast_from_int16(128i16) = 128i16
+cast_from_int16(32767i16) = 32767i16
+
+cast_to_int16(-32896i32) = 32640i16
+cast_to_int16(-64i32) = -64i16
+cast_to_int16(-32i32) = -32i16
+cast_to_int16(-16i32) = -16i16
+cast_to_int16(-8i32) = -8i16
+cast_to_int16(-1i32) = -1i16
+cast_to_int16(0i32) = 0i16
+cast_to_int16(1i32) = 1i16
+cast_to_int16(7i32) = 7i16
+cast_to_int16(8i32) = 8i16
+cast_to_int16(15i32) = 15i16
+cast_to_int16(16i32) = 16i16
+cast_to_int16(31i32) = 31i16
+cast_to_int16(32i32) = 32i16
+cast_to_int16(63i32) = 63i16
+cast_to_int16(64i32) = 64i16
+cast_to_int16(127i32) = 127i16
+cast_to_int16(128i32) = 128i16
+cast_to_int16(32767i32) = 32767i16
diff --git a/tests/hard_coded/int32_int16_casts.m b/tests/hard_coded/int32_int16_casts.m
index e69de29..10a77a8 100644
--- a/tests/hard_coded/int32_int16_casts.m
+++ b/tests/hard_coded/int32_int16_casts.m
@@ -0,0 +1,97 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+%
+% Test casting int32s to/from int16s.
+%
+%---------------------------------------------------------------------------%
+
+:- module int32_int16_casts.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module list.
+:- import_module string.
+:- import_module int32.
+:- import_module int16.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+    list.foldl(do_cast_from_int16_test, int16s, !IO),
+    io.nl(!IO),
+    list.foldl(do_cast_to_int16_test, int32s, !IO).
+
+:- pred do_cast_from_int16_test(int16::in, io::di, io::uo) is det.
+
+do_cast_from_int16_test(I16, !IO) :-
+    io.format("cast_from_int16(%di16) = %di16\n",
+        [i16(I16), i32(cast_from_int16(I16))], !IO).
+
+:- pred do_cast_to_int16_test(int32::in, io::di, io::uo) is det.
+
+do_cast_to_int16_test(I32, !IO) :-
+    io.format("cast_to_int16(%di32) = %di16\n",
+        [i32(I32), i16(cast_to_int16(I32))], !IO).
+
+:- func int16s = list(int16).
+
+int16s = [
+    -32768i16,
+    -128i16,
+    -64i16,
+    -32i16
+    -16i16
+    -8i16,
+    -1i16,
+    0i16,
+    1i16,
+    7i16,
+    8i16,
+    15i16,
+    16i16,
+    31i16,
+    32i16,
+    63i16,
+    64i16,
+    127i16,
+    128i16,
+    32767i16
+].
+
+:- func int32s = list(int32).
+
+int32s = [
+    -32768i32
+    -128i32,
+    -64i32,
+    -32i32,
+    -16i32,
+    -8i32,
+    -1i32,
+    0i32,
+    1i32,
+    7i32,
+    8i32,
+    15i32,
+    16i32,
+    31i32,
+    32i32,
+    63i32,
+    64i32,
+    127i32,
+    128i32,
+    32767i32
+].
+
+%---------------------------------------------------------------------------%
+:- end_module int32_int16_casts.
+%---------------------------------------------------------------------------%
diff --git a/tests/hard_coded/int32_int64_casts.exp b/tests/hard_coded/int32_int64_casts.exp
index e69de29..7432828 100644
--- a/tests/hard_coded/int32_int64_casts.exp
+++ b/tests/hard_coded/int32_int64_casts.exp
@@ -0,0 +1,44 @@
+cast_from_int64(-2147483648i64) = -2147483648i64
+cast_from_int64(-2147483647i64) = -2147483647i64
+cast_from_int64(-32768i64) = -32768i64
+cast_from_int64(-128i64) = -128i64
+cast_from_int64(-64i64) = -64i64
+cast_from_int64(-56i64) = -56i64
+cast_from_int64(-1i64) = -1i64
+cast_from_int64(0i64) = 0i64
+cast_from_int64(1i64) = 1i64
+cast_from_int64(7i64) = 7i64
+cast_from_int64(8i64) = 8i64
+cast_from_int64(15i64) = 15i64
+cast_from_int64(16i64) = 16i64
+cast_from_int64(31i64) = 31i64
+cast_from_int64(32i64) = 32i64
+cast_from_int64(63i64) = 63i64
+cast_from_int64(64i64) = 64i64
+cast_from_int64(127i64) = 127i64
+cast_from_int64(128i64) = 128i64
+cast_from_int64(32767i64) = 32767i64
+cast_from_int64(2147483647i64) = 2147483647i64
+
+cast_to_int64(-2147483648i32) = -2147483648i64
+cast_to_int64(-2147483647i32) = -2147483647i64
+cast_to_int64(-32896i32) = -32896i64
+cast_to_int64(-64i32) = -64i64
+cast_to_int64(-32i32) = -32i64
+cast_to_int64(-16i32) = -16i64
+cast_to_int64(-8i32) = -8i64
+cast_to_int64(-1i32) = -1i64
+cast_to_int64(0i32) = 0i64
+cast_to_int64(1i32) = 1i64
+cast_to_int64(7i32) = 7i64
+cast_to_int64(8i32) = 8i64
+cast_to_int64(15i32) = 15i64
+cast_to_int64(16i32) = 16i64
+cast_to_int64(31i32) = 31i64
+cast_to_int64(32i32) = 32i64
+cast_to_int64(63i32) = 63i64
+cast_to_int64(64i32) = 64i64
+cast_to_int64(127i32) = 127i64
+cast_to_int64(128i32) = 128i64
+cast_to_int64(32767i32) = 32767i64
+cast_to_int64(2147483647i32) = 2147483647i64
diff --git a/tests/hard_coded/int32_int64_casts.m b/tests/hard_coded/int32_int64_casts.m
index e69de29..2b3fb20 100644
--- a/tests/hard_coded/int32_int64_casts.m
+++ b/tests/hard_coded/int32_int64_casts.m
@@ -0,0 +1,103 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+%
+% Test casting int32s to/from int64s.
+%
+%---------------------------------------------------------------------------%
+
+:- module int32_int64_casts.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module list.
+:- import_module string.
+:- import_module int32.
+:- import_module int64.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+    list.foldl(do_cast_from_int64_test, int64s, !IO),
+    io.nl(!IO),
+    list.foldl(do_cast_to_int64_test, int32s, !IO).
+
+:- pred do_cast_from_int64_test(int64::in, io::di, io::uo) is det.
+
+do_cast_from_int64_test(I64, !IO) :-
+    io.format("cast_from_int64(%di64) = %di64\n",
+        [i64(I64), i32(cast_from_int64(I64))], !IO).
+
+:- pred do_cast_to_int64_test(int32::in, io::di, io::uo) is det.
+
+do_cast_to_int64_test(I32, !IO) :-
+    io.format("cast_to_int64(%di32) = %di64\n",
+        [i32(I32), i64(cast_to_int64(I32))], !IO).
+
+:- func int64s = list(int64).
+
+int64s = [
+    -2147483648i64,
+    -2147483647i64,
+    -32768i64,
+    -128i64,
+    -64i64,
+    -32i64
+    -16i64
+    -8i64,
+    -1i64,
+    0i64,
+    1i64,
+    7i64,
+    8i64,
+    15i64,
+    16i64,
+    31i64,
+    32i64,
+    63i64,
+    64i64,
+    127i64,
+    128i64,
+    32767i64,
+    2147483647i64
+].
+
+:- func int32s = list(int32).
+
+int32s = [
+    -2147483648i32,
+    -2147483647i32,
+    -32768i32
+    -128i32,
+    -64i32,
+    -32i32,
+    -16i32,
+    -8i32,
+    -1i32,
+    0i32,
+    1i32,
+    7i32,
+    8i32,
+    15i32,
+    16i32,
+    31i32,
+    32i32,
+    63i32,
+    64i32,
+    127i32,
+    128i32,
+    32767i32,
+    2147483647i32
+].
+
+%---------------------------------------------------------------------------%
+:- end_module int32_int64_casts.
+%---------------------------------------------------------------------------%
diff --git a/tests/hard_coded/int32_int8_casts.exp b/tests/hard_coded/int32_int8_casts.exp
index e69de29..5ec82b1 100644
--- a/tests/hard_coded/int32_int8_casts.exp
+++ b/tests/hard_coded/int32_int8_casts.exp
@@ -0,0 +1,33 @@
+cast_from_int8(-128i8) = -128i8
+cast_from_int8(-64i8) = -64i8
+cast_from_int8(-56i8) = -56i8
+cast_from_int8(-1i8) = -1i8
+cast_from_int8(0i8) = 0i8
+cast_from_int8(1i8) = 1i8
+cast_from_int8(7i8) = 7i8
+cast_from_int8(8i8) = 8i8
+cast_from_int8(15i8) = 15i8
+cast_from_int8(16i8) = 16i8
+cast_from_int8(31i8) = 31i8
+cast_from_int8(32i8) = 32i8
+cast_from_int8(63i8) = 63i8
+cast_from_int8(64i8) = 64i8
+cast_from_int8(127i8) = 127i8
+
+cast_to_int8(-128i32) = -128i8
+cast_to_int8(-64i32) = -64i8
+cast_to_int8(-32i32) = -32i8
+cast_to_int8(-16i32) = -16i8
+cast_to_int8(-8i32) = -8i8
+cast_to_int8(-1i32) = -1i8
+cast_to_int8(0i32) = 0i8
+cast_to_int8(1i32) = 1i8
+cast_to_int8(7i32) = 7i8
+cast_to_int8(8i32) = 8i8
+cast_to_int8(15i32) = 15i8
+cast_to_int8(16i32) = 16i8
+cast_to_int8(31i32) = 31i8
+cast_to_int8(32i32) = 32i8
+cast_to_int8(63i32) = 63i8
+cast_to_int8(64i32) = 64i8
+cast_to_int8(127i32) = 127i8
diff --git a/tests/hard_coded/int32_int8_casts.m b/tests/hard_coded/int32_int8_casts.m
index e69de29..3d9ad6b 100644
--- a/tests/hard_coded/int32_int8_casts.m
+++ b/tests/hard_coded/int32_int8_casts.m
@@ -0,0 +1,91 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%---------------------------------------------------------------------------%
+%
+% Test casting int32s to/from int8s.
+%
+%---------------------------------------------------------------------------%
+
+:- module int32_int8_casts.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%---------------------------------------------------------------------------%
+%---------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module list.
+:- import_module string.
+:- import_module int32.
+:- import_module int8.
+
+%---------------------------------------------------------------------------%
+
+main(!IO) :-
+    list.foldl(do_cast_from_int8_test, int8s, !IO),
+    io.nl(!IO),
+    list.foldl(do_cast_to_int8_test, int32s, !IO).
+
+:- pred do_cast_from_int8_test(int8::in, io::di, io::uo) is det.
+
+do_cast_from_int8_test(I8, !IO) :-
+    io.format("cast_from_int8(%di8) = %di8\n",
+        [i8(I8), i32(cast_from_int8(I8))], !IO).
+
+:- pred do_cast_to_int8_test(int32::in, io::di, io::uo) is det.
+
+do_cast_to_int8_test(I32, !IO) :-
+    io.format("cast_to_int8(%di32) = %di8\n",
+        [i32(I32), i8(cast_to_int8(I32))], !IO).
+
+:- func int8s = list(int8).
+
+int8s = [
+    -128i8,
+    -64i8,
+    -32i8
+    -16i8
+    -8i8,
+    -1i8,
+    0i8,
+    1i8,
+    7i8,
+    8i8,
+    15i8,
+    16i8,
+    31i8,
+    32i8,
+    63i8,
+    64i8,
+    127i8
+].
+
+:- func int32s = list(int32).
+
+int32s = [
+    -128i32,
+    -64i32,
+    -32i32,
+    -16i32,
+    -8i32,
+    -1i32,
+    0i32,
+    1i32,
+    7i32,
+    8i32,
+    15i32,
+    16i32,
+    31i32,
+    32i32,
+    63i32,
+    64i32,
+    127i32
+].
+
+%---------------------------------------------------------------------------%
+:- end_module int32_int8_casts.
+%---------------------------------------------------------------------------%


More information about the reviews mailing list