[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] pickles: add new pickle for floating-point numbers
From: |
Mohammad-Reza Nabipoor |
Subject: |
[PATCH] pickles: add new pickle for floating-point numbers |
Date: |
Sat, 7 Jan 2023 22:30:22 +0100 |
This commit adds a rudimentary pickle for working with
floating-point numbers. The pickle and tests were initially
written by apache2.
2022-01-07 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* pickles/ieee754.pk: New pickle for IEEE 754 floating-point
numbers based on initial code from apache2.
* pickles/Makefile.am (dist_pickles_DATA): Add new pickle.
* testsuite/poke.pickles/ieee754-test.pk: New test.
* testsuite/Makefile.am (EXTRAD_DIST): Update.
---
ChangeLog | 8 ++
pickles/Makefile.am | 2 +-
pickles/ieee754.pk | 70 +++++++++++++++
testsuite/Makefile.am | 1 +
testsuite/poke.pickles/ieee754-test.pk | 120 +++++++++++++++++++++++++
5 files changed, 200 insertions(+), 1 deletion(-)
create mode 100644 pickles/ieee754.pk
create mode 100644 testsuite/poke.pickles/ieee754-test.pk
diff --git a/ChangeLog b/ChangeLog
index 2a35968c..d650a133 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2022-01-07 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
+
+ * pickles/ieee754.pk: New pickle for IEEE 754 floating-point
+ numbers based on initial code from apache2.
+ * pickles/Makefile.am (dist_pickles_DATA): Add new pickle.
+ * testsuite/poke.pickles/ieee754-test.pk: New test.
+ * testsuite/Makefile.am (EXTRA_DIST): Update.
+
2022-01-07 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-insn.def (formatf32): Add new instruction.
diff --git a/pickles/Makefile.am b/pickles/Makefile.am
index f2b6ca50..9de25565 100644
--- a/pickles/Makefile.am
+++ b/pickles/Makefile.am
@@ -26,4 +26,4 @@ dist_pickles_DATA = elf-common.pk elf-64.pk elf-32.pk elf.pk
ctf.pk ctf-dump.pk
openpgp.pk search.pk riscv.pk coff.pk coff-i386.pk
coff-aarch64.pk \
pe.pk pe-amd64.pk pe-arm.pk pe-arm64.pk pe-i386.pk
pe-ia64.pk \
pe-m32r.pk pe-mips.pk pe-ppc.pk pe-sh3.pk pe-riscv.pk
pe-debug.pk \
- uuid.pk redoxfs.pk pcap.pk
+ uuid.pk redoxfs.pk pcap.pk ieee754.pk
diff --git a/pickles/ieee754.pk b/pickles/ieee754.pk
new file mode 100644
index 00000000..9fd65885
--- /dev/null
+++ b/pickles/ieee754.pk
@@ -0,0 +1,70 @@
+/* ieee754.pk - IEEE Standard for Floating-Point Arithmetic. */
+
+/* Copyright (C) 2022-2023 The poke authors. */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+type IEEE754_binary16 =
+ struct int<16>
+ {
+ uint<1> sign;
+ uint<5> exp;
+ uint<10> frac; // aka significand, aka mantissa.
+
+ method is_nan_p = int: { return exp == 0x1f && frac != 0; }
+ method is_snan_p = int: { return exp == 0x1f && (frac & 0x200U); }
+ method is_qnan_p = int: { return exp == 0x1f && !(frac & 0x200U); }
+ method is_inf_p = int: { return exp == 0x1f && frac == 0; }
+ };
+
+type IEEE754_binary32 =
+ struct int<32>
+ {
+ uint<1> sign;
+ uint<8> exp;
+ uint<23> frac; // aka significand, aka mantissa.
+
+ computed string str;
+
+ method get_str = string: { return format_f32 (sign:::exp:::frac); }
+ method set_str = (string s) void: { raise E_inval; }
+
+ method is_nan_p = int: { return exp == 0xff && frac != 0; }
+ method is_snan_p = int: { return exp == 0xff && (frac & 0x400000U); }
+ method is_qnan_p = int: { return exp == 0xff && !(frac & 0x400000U); }
+ method is_inf_p = int: { return exp == 0xff && frac == 0; }
+ };
+
+type IEEE754_binary64 =
+ struct int<64>
+ {
+ uint<1> sign;
+ uint<11> exp;
+ uint<52> frac; // aka significand, aka mantissa.
+
+ computed string str;
+
+ method get_str = string: { return format_f64 (sign:::exp:::frac); }
+ method set_str = (string s) void: { raise E_inval; }
+
+ method is_nan_p = int: { return exp == 0x7ff && frac != 0; }
+ method is_snan_p = int: { return exp == 0x7ff && (frac &
0x4000000000000U); }
+ method is_qnan_p = int: { return exp == 0x7ff && !(frac &
0x4000000000000U); }
+ method is_inf_p = int: { return exp == 0x7ff && frac == 0; }
+ };
+
+type Float16 = IEEE754_binary16;
+type Float32 = IEEE754_binary32;
+type Float64 = IEEE754_binary64;
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 3b90344a..eb361391 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -610,6 +610,7 @@ EXTRA_DIST = \
poke.pickles/uuid-test.pk \
poke.pickles/redoxfs-test.pk \
poke.pickles/pcap-test.pk \
+ poke.pickles/ieee754-test.pk \
poke.pkl/pkl.exp \
poke.pkl/postincr-1.pk \
poke.pkl/postincr-2.pk \
diff --git a/testsuite/poke.pickles/ieee754-test.pk
b/testsuite/poke.pickles/ieee754-test.pk
new file mode 100644
index 00000000..f6f27cae
--- /dev/null
+++ b/testsuite/poke.pickles/ieee754-test.pk
@@ -0,0 +1,120 @@
+/* ieee754-test.pk - Tests for the IEEE 754 pickle. */
+
+/* Copyright (C) 2022-2023 The poke authors. */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+load pktest;
+load ieee754;
+
+var data = open("*data*");
+
+var tests = [
+ PkTest {
+ name = "binary16",
+ func = lambda (string name) void:
+ {
+ var one = 0x3c00 as Float16;
+
+ assert (one.sign == 0);
+ assert (one.exp == 0xf);
+ assert (one.frac == 0);
+ assert (!one.is_inf_p);
+ assert (!one.is_nan_p);
+
+ var minus_two = 0xc000 as Float16;
+
+ assert (minus_two.sign == 1);
+ assert (minus_two.exp == 0x10); // 2^(16-15) = 2^1 = 2
+ assert (minus_two.frac == 0);
+ assert (!minus_two.is_inf_p);
+ assert (!minus_two.is_nan_p);
+
+ var random = 0x5144 as Float16;
+
+ assert (random.sign == 0);
+ assert (random.exp == 0x14); // 42
+ assert (random.frac == 0x144); // .125
+ assert (!random.is_inf_p);
+ assert (!random.is_nan_p);
+
+ var posinf = 0b0111110000000000 as Float16;
+
+ assert (posinf.is_inf_p);
+ assert (!posinf.is_nan_p);
+ },
+ },
+ PkTest {
+ name = "binary32",
+ func = lambda (string name) void:
+ {
+ var one = 0x3f800000 as Float32;
+
+ assert (one.sign == 0);
+ assert (one.exp == 127); // 2^(127-127) == 2^0 == 1
+ assert (one.frac == 0);
+ assert (one.str == "1.0000000");
+
+ var minus_two = 0xc0000000 as Float32;
+
+ assert (minus_two.sign == 1);
+ assert (minus_two.exp == 128); // 2^(128-127) == 2^1 == 1
+ assert (minus_two.frac == 0);
+ assert (minus_two.str == "-2.0000000");
+
+ var random = 0x42288659 as Float32;
+
+ assert (random.sign == 0);
+ assert (random.exp == 0x84);
+ assert (random.frac == 0x288659);
+ assert (random.str == "42.1311989");
+
+ uint<8>[4] @ data : 0#B = [ 0xa4UB, 0x70UB, 0x45UB, 0x41UB];
+
+ type little_32 = struct { little uint<32> f; };
+ var l32 = (little_32 @ data : 0#B).f as Float32;
+
+ assert (l32.sign == 0);
+ assert (l32.exp - 127 == 3);
+ assert (l32.frac == 0x4570a4);
+
+ // Reverse the four bytes:
+ uint<8>[4] @ data : 0#B = [ 0x41UB, 0x45UB, 0x70UB, 0xa4UB];
+
+ type big_32 = struct { big uint<32> f; };
+ var b32 = (big_32 @ data : 0#B).f as Float32;
+
+ assert (b32 == l32);
+ },
+ },
+ PkTest {
+ name = "binary64",
+ func = lambda (string name) void:
+ {
+ var pi = 0x400921fb54442eeaUL as Float64;
+
+ assert (pi.sign == 0);
+ assert (pi.exp == 0b10000000000);
+ assert (pi.frac
+ == 0b1001001000011111101101010100010001000010111011101010U);
+ assert (pi.str == "3.141592653590000");
+ },
+ },
+];
+
+var ok = pktest_run (tests);
+
+close (data);
+exit(ok ? 0 : 1);
--
2.39.0
- [PATCH] pickles: add new pickle for floating-point numbers,
Mohammad-Reza Nabipoor <=