[m-rev.] diff: implement from_bytes_{le,be} for 64-bit integers

Julien Fischer jfischer at opturion.com
Thu Feb 8 17:02:39 AEDT 2018


Implement from_bytes_{le,be} for 64-bit integers.

library/int64.m:
library/uint64.m:
     As above.

tests/hard_coded/Mmakefile:
tests/hard_coded/{int6,uint64}_from-bytes.{m,exp}:
     Add tests of the new functions.

Julien.

diff --git a/library/int64.m b/library/int64.m
index fabfae4..124aaa2 100644
--- a/library/int64.m
+++ b/library/int64.m
@@ -30,6 +30,22 @@

  :- func cast_from_uint64(uint64) = int64.

+    % from_bytes_le(Byte0, Byte1, ..., Byte7) = I64:
+    % I64 is the int64 whose bytes are given in little-endian order by the
+    % arguments from left-to-right (i.e. Byte0 is the least significant byte
+    % and Byte7 is the most significant byte).
+    %
+:- func from_bytes_le(uint8, uint8, uint8, uint8, uint8, uint8, uint8,
+    uint8) = int64.
+
+    % from_bytes_be(Byte0, Byte1, ..., Byte7) = I64:
+    % I64 is the int64 whose bytes are given in big-endian order by the
+    % arguments in left-to-right order (i.e. Byte0 is the most significant
+    % byte and Byte7 is the least significant byte).
+    %
+:- func from_bytes_be(uint8, uint8, uint8, uint8, uint8, uint8, uint8,
+    uint8) = int64.
+
  %---------------------------------------------------------------------------%

      % Less than.
@@ -307,6 +323,74 @@ cast_from_uint64(_) = _ :-

  %---------------------------------------------------------------------------%

+:- pragma foreign_proc("C",
+    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
+        Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (I64::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    unsigned char *int64_bytes = (unsigned char *) &I64;
+#if defined(MR_BIG_ENDIAN)
+    int64_bytes[0] = Byte7;
+    int64_bytes[1] = Byte6;
+    int64_bytes[2] = Byte5;
+    int64_bytes[3] = Byte4;
+    int64_bytes[4] = Byte3;
+    int64_bytes[5] = Byte2;
+    int64_bytes[6] = Byte1;
+    int64_bytes[7] = Byte0;
+#else
+    int64_bytes[0] = Byte0;
+    int64_bytes[1] = Byte1;
+    int64_bytes[2] = Byte2;
+    int64_bytes[3] = Byte3;
+    int64_bytes[4] = Byte4;
+    int64_bytes[5] = Byte5;
+    int64_bytes[6] = Byte6;
+    int64_bytes[7] = Byte7;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
+        Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (I64::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I64 = (long)(Byte7 & 0xff) << 56 |
+          (long)(Byte6 & 0xff) << 48 |
+          (long)(Byte5 & 0xff) << 40 |
+          (long)(Byte4 & 0xff) << 32 |
+          (long)(Byte3 & 0xff) << 24 |
+          (long)(Byte2 & 0xff) << 16 |
+          (long)(Byte1 & 0xff) << 8  |
+          (long)(Byte0 & 0xff);
+").
+
+:- pragma foreign_proc("C#",
+    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
+        Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (I64::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    I64 = (long) (
+        (ulong)Byte7 << 56 |
+        (ulong)Byte6 << 48 |
+        (ulong)Byte5 << 40 |
+        (ulong)Byte4 << 32 |
+        (ulong)Byte3 << 24 |
+        (ulong)Byte2 << 16 |
+        (ulong)Byte1 << 8  |
+        (ulong)Byte0);
+").
+
+from_bytes_le(_, _, _, _, _, _, _, _) = _ :-
+    sorry($module, "int64.from_bytes_le/8 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+from_bytes_be(Byte7, Byte6, Byte5,Byte4, Byte3, Byte2, Byte1, Byte0) =
+    from_bytes_le(Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7).
+
+%---------------------------------------------------------------------------%
+
  abs(Num) = Abs :-
      ( if Num = int64.min_int64 then
          throw(software_error("int64.abs: abs(min_int64) would overflow"))
diff --git a/library/uint64.m b/library/uint64.m
index 88bef0e..6e1269c 100644
--- a/library/uint64.m
+++ b/library/uint64.m
@@ -33,6 +33,22 @@

  :- func cast_to_int(uint64) = int.

+    % from_bytes_le(Byte0, Byte1, ..., Byte7) = U64:
+    % U64 is the uint64 whose bytes are given in little-endian order by the
+    % arguments from left-to-right (i.e. Byte0 is the least significant byte
+    % and Byte7 is the most significant byte).
+    %
+:- func from_bytes_le(uint8, uint8, uint8, uint8, uint8, uint8, uint8,
+    uint8) = uint64.
+
+    % from_bytes_be(Byte0, Byte1, ..., Byte7) = U64:
+    % U64 is the uint64 whose bytes are given in big-endian order by the
+    % arguments in left-to-right order (i.e. Byte0 is the most significant
+    % byte and Byte7 is the least significant byte).
+    %
+:- func from_bytes_be(uint8, uint8, uint8, uint8, uint8, uint8, uint8,
+    uint8) = uint64.
+
  %---------------------------------------------------------------------------%

      % Less than.
@@ -293,6 +309,74 @@ cast_to_int(_) = _ :-

  %---------------------------------------------------------------------------%

+:- pragma foreign_proc("C",
+    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
+        Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (U64::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+"
+    unsigned char *uint64_bytes = (unsigned char *) &U64;
+#if defined(MR_BIG_ENDIAN)
+    uint64_bytes[0] = Byte7;
+    uint64_bytes[1] = Byte6;
+    uint64_bytes[2] = Byte5;
+    uint64_bytes[3] = Byte4;
+    uint64_bytes[4] = Byte3;
+    uint64_bytes[5] = Byte2;
+    uint64_bytes[6] = Byte1;
+    uint64_bytes[7] = Byte0;
+#else
+    uint64_bytes[0] = Byte0;
+    uint64_bytes[1] = Byte1;
+    uint64_bytes[2] = Byte2;
+    uint64_bytes[3] = Byte3;
+    uint64_bytes[4] = Byte4;
+    uint64_bytes[5] = Byte5;
+    uint64_bytes[6] = Byte6;
+    uint64_bytes[7] = Byte7;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
+        Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (U64::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U64 = (long)(Byte7 & 0xff) << 56 |
+          (long)(Byte6 & 0xff) << 48 |
+          (long)(Byte5 & 0xff) << 40 |
+          (long)(Byte4 & 0xff) << 32 |
+          (long)(Byte3 & 0xff) << 24 |
+          (long)(Byte2 & 0xff) << 16 |
+          (long)(Byte1 & 0xff) << 8  |
+          (long)(Byte0 & 0xff);
+").
+
+:- pragma foreign_proc("C#",
+    from_bytes_le(Byte0::in, Byte1::in, Byte2::in, Byte3::in,
+        Byte4::in, Byte5::in, Byte6::in, Byte7::in) = (U64::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    U64 = (ulong) (
+        (ulong)Byte7 << 56 |
+        (ulong)Byte6 << 48 |
+        (ulong)Byte5 << 40 |
+        (ulong)Byte4 << 32 |
+        (ulong)Byte3 << 24 |
+        (ulong)Byte2 << 16 |
+        (ulong)Byte1 << 8  |
+        (ulong)Byte0);
+").
+
+from_bytes_le(_, _, _, _, _, _, _, _) = _ :-
+    sorry($module, "uint64.from_bytes_le/8 NYI for Erlang").
+
+%---------------------------------------------------------------------------%
+
+from_bytes_be(Byte7, Byte6, Byte5,Byte4, Byte3, Byte2, Byte1, Byte0) =
+    from_bytes_le(Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7).
+
+%---------------------------------------------------------------------------%
+
  X div Y = X // Y.

  :- pragma inline('//'/2).
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 81df85a..f00aea8 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -175,6 +175,7 @@ ORDINARY_PROGS =	\
  	int_range_ops \
  	int16_from_bytes \
  	int32_from_bytes \
+	int64_from_bytes \
  	integer_int16_conv \
  	integer_int32_conv \
  	integer_int64_conv \
@@ -382,6 +383,7 @@ ORDINARY_PROGS =	\
  	uint16_switch_test \
  	uint32_from_bytes \
  	uint32_switch_test \
+	uint64_from_bytes \
  	uint8_switch_test \
  	uint_switch_test \
  	unicode_test \
diff --git a/tests/hard_coded/int64_from_bytes.exp b/tests/hard_coded/int64_from_bytes.exp
new file mode 100644
index 0000000..32314f2
--- /dev/null
+++ b/tests/hard_coded/int64_from_bytes.exp
@@ -0,0 +1,16 @@
+-72057594037927936i64
+71776119061217280i64
+280375465082880i64
+1095216660480i64
+4278190080i64
+16711680i64
+65280i64
+255i64
+255i64
+65280i64
+16711680i64
+4278190080i64
+1095216660480i64
+280375465082880i64
+71776119061217280i64
+-72057594037927936i64
diff --git a/tests/hard_coded/int64_from_bytes.m b/tests/hard_coded/int64_from_bytes.m
new file mode 100644
index 0000000..b0ec95b
--- /dev/null
+++ b/tests/hard_coded/int64_from_bytes.m
@@ -0,0 +1,45 @@
+:- module int64_from_bytes.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int64.
+
+main(!IO) :-
+     Test1 = int64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8),
+     io.write_line(Test1, !IO),
+     Test2 = int64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8),
+     io.write_line(Test2, !IO),
+     Test3 = int64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8),
+     io.write_line(Test3, !IO),
+     Test4 = int64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test4, !IO),
+     Test5 = int64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test5, !IO),
+     Test6 = int64.from_bytes_le(0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test6, !IO),
+     Test7 = int64.from_bytes_le(0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test7, !IO),
+     Test8 = int64.from_bytes_le(0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test8, !IO),
+
+     Test9 = int64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8),
+     io.write_line(Test9, !IO),
+     Test10 = int64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8),
+     io.write_line(Test10, !IO),
+     Test11 = int64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8),
+     io.write_line(Test11, !IO),
+     Test12 = int64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test12, !IO),
+     Test13 = int64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test13, !IO),
+     Test14 = int64.from_bytes_be(0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test14, !IO),
+     Test15 = int64.from_bytes_be(0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test15, !IO),
+     Test16 = int64.from_bytes_be(0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test16, !IO).
diff --git a/tests/hard_coded/uint64_from_bytes.exp b/tests/hard_coded/uint64_from_bytes.exp
new file mode 100644
index 0000000..cfd90df
--- /dev/null
+++ b/tests/hard_coded/uint64_from_bytes.exp
@@ -0,0 +1,16 @@
+18374686479671623680u64
+71776119061217280u64
+280375465082880u64
+1095216660480u64
+4278190080u64
+16711680u64
+65280u64
+255u64
+255u64
+65280u64
+16711680u64
+4278190080u64
+1095216660480u64
+280375465082880u64
+71776119061217280u64
+18374686479671623680u64
diff --git a/tests/hard_coded/uint64_from_bytes.m b/tests/hard_coded/uint64_from_bytes.m
new file mode 100644
index 0000000..3b1d9a8
--- /dev/null
+++ b/tests/hard_coded/uint64_from_bytes.m
@@ -0,0 +1,45 @@
+:- module uint64_from_bytes.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module uint64.
+
+main(!IO) :-
+     Test1 = uint64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8),
+     io.write_line(Test1, !IO),
+     Test2 = uint64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8),
+     io.write_line(Test2, !IO),
+     Test3 = uint64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8),
+     io.write_line(Test3, !IO),
+     Test4 = uint64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test4, !IO),
+     Test5 = uint64.from_bytes_le(0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test5, !IO),
+     Test6 = uint64.from_bytes_le(0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test6, !IO),
+     Test7 = uint64.from_bytes_le(0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test7, !IO),
+     Test8 = uint64.from_bytes_le(0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test8, !IO),
+
+     Test9 = uint64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8),
+     io.write_line(Test9, !IO),
+     Test10 = uint64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8),
+     io.write_line(Test10, !IO),
+     Test11 = uint64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8),
+     io.write_line(Test11, !IO),
+     Test12 = uint64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test12, !IO),
+     Test13 = uint64.from_bytes_be(0x00u8, 0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test13, !IO),
+     Test14 = uint64.from_bytes_be(0x00u8, 0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test14, !IO),
+     Test15 = uint64.from_bytes_be(0x00u8, 0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test15, !IO),
+     Test16 = uint64.from_bytes_be(0xffu8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8),
+     io.write_line(Test16, !IO).



More information about the reviews mailing list