[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] pkl,std: add `format_f32' and `format_f64' std functions
From: |
Mohammad-Reza Nabipoor |
Subject: |
[PATCH] pkl,std: add `format_f32' and `format_f64' std functions |
Date: |
Sat, 7 Jan 2023 20:49:52 +0100 |
This commit adds two new library functions to create string
representation of single/double-precision floating-point numbers
from uint<32>/uint<64>.
2022-01-07 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-insn.def (formatf32): Add new instruction.
(formatf64): Likewise.
* libpoke/pvm.jitter (FORMATF): New macro for formatting
floating-point numbers.
(formatf32): New instruction for formatting floating-point
numbers.
(formatf64): Likewise.
* libpoke/std.pk (format_f32): Add new function for getting the
floating-point representation of a uint<32> number.
(format_f64): Likewise.
* doc/poke.texi (Conversion Functions): Add new section for
`format_f32' and `format_f64' functions.
* testsuite/poke.std/std-test.pk: Add two new entries for testing
`format_f32' and `format_f64' functions.
---
ChangeLog | 17 ++++++++
doc/poke.texi | 42 +++++++++++++++++++
libpoke/pkl-insn.def | 2 +
libpoke/pvm.jitter | 77 ++++++++++++++++++++++++++++++++++
libpoke/std.pk | 38 +++++++++++++++++
testsuite/poke.std/std-test.pk | 31 ++++++++++++++
6 files changed, 207 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index 33cc53cb..2a35968c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2022-01-07 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
+
+ * libpoke/pkl-insn.def (formatf32): Add new instruction.
+ (formatf64): Likewise.
+ * libpoke/pvm.jitter (FORMATF): New macro for formatting
+ floating-point numbers.
+ (formatf32): New instruction for formatting floating-point
+ numbers.
+ (formatf64): Likewise.
+ * libpoke/std.pk (format_f32): Add new function for getting the
+ floating-point representation of a uint<32> number.
+ (format_f64): Likewise.
+ * doc/poke.texi (Conversion Functions): Add new section for
+ `format_f32' and `format_f64' functions.
+ * testsuite/poke.std/std-test.pk: Add two new entries for testing
+ `format_f32' and `format_f64' functions.
+
2022-01-07 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* pickles/pcap.pk (PCAP_Packet): Declare body as a byte array.
diff --git a/doc/poke.texi b/doc/poke.texi
index b8512c91..a6bbbca3 100644
--- a/doc/poke.texi
+++ b/doc/poke.texi
@@ -15122,6 +15122,8 @@ useful conversions.
* stoca:: filling character arrays from strings.
* atoi:: converting strings to integers.
* ltos:: converting integers to strings.
+* format_f32:: string representation of single-precision
floating-points.
+* format_f64:: string representation of double-precision
floating-points.
@end menu
@node catos
@@ -15212,6 +15214,46 @@ fun ltos = (long @var{i}, uint @var{base} = 10) string:
where @var{i} is the number for which to calculate the printed
representation, and @var{base} is a number between 0 and 16.
+@node format_f32
+@subsection @code{format_f32}
+@cindex @code{format_f32}
+
+The @code{format_f32} standard function interpret a given unsigned
+integer as a single-precision floating-point number and then convert
+that number to string. It has the following prototype:
+
+@example
+fun format_f32 = (uint<32> @var{number},
+ uint<8> @var{precision},
+ uint<8> @var{style} = 'f') string:
+@end example
+
+@noindent
+where @var{number} is the floating-point number, @var{precision} is
+exactly like what documented in manual of @code{printf} C library
+function. The @var{style} can be one the following characters:
+@code{'f'}, @code{'e'} and @code{'g'}, which are behave similar to
+@code{"%f"}, @code{"%e"} and @code{"%g"} format specifiers in
+@code{printf} C function,
+
+@node format_f64
+@subsection @code{format_f64}
+@cindex @code{format_f64}
+
+The @code{format_f64} standard function interpret a given unsigned
+integer as a double-precision floating-point number and then convert
+that number to string. It has the following prototype:
+
+@example
+fun format_f64 = (uint<64> @var{number},
+ uint<8> @var{precision},
+ uint<8> @var{style} = 'f') string:
+@end example
+
+@noindent
+which behaves like @code{format_f32} function, except that it accepts
+64-bit wide numbers.
+
@node Array Functions
@section Array Functions
@cindex array functions
diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
index c9cf639b..15ba53a2 100644
--- a/libpoke/pkl-insn.def
+++ b/libpoke/pkl-insn.def
@@ -252,6 +252,8 @@ PKL_DEF_INSN(PKL_INSN_FORMATI,"n","formati")
PKL_DEF_INSN(PKL_INSN_FORMATIU,"n","formatiu")
PKL_DEF_INSN(PKL_INSN_FORMATL,"n","formatl")
PKL_DEF_INSN(PKL_INSN_FORMATLU,"n","formatlu")
+PKL_DEF_INSN(PKL_INSN_FORMATF32,"n","formatf32")
+PKL_DEF_INSN(PKL_INSN_FORMATF64,"n","formatf64")
/* Offset instructions. */
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index cc0f573d..20419edd 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -875,6 +875,27 @@ late-header-c
JITTER_PUSH_STACK (pvm_make_string ((OUT))); \
} while (0)
+#define FORMATF(RESULT,NUM,PREC,STYLE,TYPEF) \
+ do \
+ { \
+ static const char STYLES[] = { 'f', 'e', 'g' }; \
+ TYPEF x; \
+ int n; \
+ char fmt[16]; \
+ \
+ PVM_ASSERT (sizeof (x) == sizeof (NUM)); \
+ PVM_ASSERT ((STYLE) < 3); \
+ \
+ memcpy (&x, &(NUM), sizeof (NUM)); \
+ n = snprintf (fmt, sizeof (fmt), "%%.%u%c", (unsigned)(PREC), \
+ STYLES[(STYLE) % 3]); \
+ if (n == -1) \
+ PVM_RAISE_DFL (PVM_E_CONV); \
+ n = asprintf (&(RESULT), fmt, x); \
+ if (n == -1) \
+ PVM_RAISE_DFL (PVM_E_CONV); \
+ } \
+ while (0)
end
end
@@ -2399,6 +2420,62 @@ instruction formatlu (?n)
end
end
+# Instruction: formatf32
+#
+# Given a UINT (that should be interpreted as a 32-bit floating-point
+# number), and a UINT (as the conversion precision), push the string
+# representation of the floating-point number with specified precision.
+# The formatting style is given by a literal parameters.
+#
+# Style 0 <=> %f in printf
+# Style 1 <=> %e in printf
+# Style 2 <=> %g in printf
+#
+# Stack: ( UINT UINT -- STR )
+
+instruction formatf32 (?n)
+ branching # because of PVM_RAISE_DIRECT
+ code
+ char *result = NULL;
+ uint32_t num = PVM_VAL_UINT (JITTER_TOP_STACK ());
+ unsigned style = (unsigned)JITTER_ARGN0;
+ uint32_t precision = PVM_VAL_UINT (JITTER_UNDER_TOP_STACK ());
+
+ JITTER_DROP_STACK ();
+ FORMATF (result, num, precision, style, float);
+ JITTER_TOP_STACK () = pvm_make_string (result);
+ free (result);
+ end
+end
+
+# Instruction: formatf64
+#
+# Given a ULONG (that should be interpreted as a 64-bit floating-point
+# number), and a UINT (as the conversion precision), push the string
+# representation of the floating-point number with specified precision.
+# The formatting style is given by a literal parameters.
+#
+# Style 0 <=> %f in printf
+# Style 1 <=> %e in printf
+# Style 2 <=> %g in printf
+#
+# Stack: ( ULONG UINT -- STR )
+
+instruction formatf64 (?n)
+ branching # because of PVM_RAISE_DIRECT
+ code
+ char *result = NULL;
+ uint64_t num = PVM_VAL_ULONG (JITTER_TOP_STACK ());
+ unsigned style = (unsigned)JITTER_ARGN0;
+ uint32_t precision = PVM_VAL_UINT (JITTER_UNDER_TOP_STACK ());
+
+ JITTER_DROP_STACK ();
+ FORMATF (result, num, precision, style, double);
+ JITTER_TOP_STACK () = pvm_make_string (result);
+ free (result);
+ end
+end
+
## Main stack manipulation instructions
diff --git a/libpoke/std.pk b/libpoke/std.pk
index ab11160d..2dbc1804 100644
--- a/libpoke/std.pk
+++ b/libpoke/std.pk
@@ -494,3 +494,41 @@ fun with_cur_ios = (int<32> ios,
raise exc;
}
}
+
+/* Create string representation of the single-precision floating-point
+ number given as NUMBER.
+
+ This function supports three style of conversion to floating-points
+ similar to %f, %e and %g format specifiers of C printf library. */
+
+fun format_f32 = (uint<32> number,
+ uint<8> precision = 7,
+ uint<8> style = 'f') string:
+ {
+ assert (style in ['f', 'e', 'g'], "invalid formatting style");
+
+ var prec = precision as uint<32>;
+
+ return style == 'f' ? asm string: ("formatf32 0" : prec, number)
+ : style == 'e' ? asm string: ("formatf32 1" : prec, number)
+ : asm string: ("formatf32 2" : prec, number);
+ }
+
+/* Create string representation of the double-precision floating-point
+ number given as NUMBER.
+
+ This function supports three style of conversion to floating-points
+ similar to %f, %e and %g format specifiers of C printf library. */
+
+fun format_f64 = (uint<64> number,
+ uint<8> precision = 7,
+ uint<8> style = 'f') string:
+ {
+ assert (style in ['f', 'e', 'g'], "invalid formatting style");
+
+ var prec = precision as uint<32>;
+
+ return style == 'f' ? asm string: ("formatf64 0" : prec, number)
+ : style == 'e' ? asm string: ("formatf64 1" : prec, number)
+ : asm string: ("formatf64 2" : prec, number);
+ }
diff --git a/testsuite/poke.std/std-test.pk b/testsuite/poke.std/std-test.pk
index edf44dbf..a531934f 100644
--- a/testsuite/poke.std/std-test.pk
+++ b/testsuite/poke.std/std-test.pk
@@ -295,6 +295,37 @@ var tests = [
qsort ([4,3,2,1], cmpints);
},
},
+ PkTest {
+ name = "format_f32",
+ func = lambda (string name) void:
+ {
+ assert (format_f32 (0x4048f5c3U) == "3.1400001");
+ assert (format_f32 (0x4048f5c3U, 7) == "3.1400001");
+ assert (format_f32 (0x4048f5c3U, 7, 'f') == "3.1400001");
+ assert (format_f32 (0x4048f5c3U, 9) == "3.140000105");
+ assert (format_f32 (0x4048f5c3U, 22) == "3.1400001049041748046875");
+ assert (format_f32 (0x4048f5c3U, 22, 'e')
+ == "3.1400001049041748046875e+00");
+ assert ((format_f32 :number 0x4048f5c3U :style 'g') == "3.14");
+ assert ((format_f32 :number 0x4048f5c3U :style 'g' :precision 8)
+ == "3.1400001");
+ },
+ },
+ PkTest {
+ name = "format_f64",
+ func = lambda (string name) void:
+ {
+ assert (format_f64 (0x40091eb851eb851fU) == "3.1400000");
+ assert (format_f64 (0x40091eb851eb851fU, 7) == "3.1400000");
+ assert (format_f64 (0x40091eb851eb851fU, 7, 'f') == "3.1400000");
+ assert (format_f64 (0x40091eb851eb851fU, 14) == "3.14000000000000");
+ assert (format_f64 (0x40091eb851eb851fU, 15, 'e')
+ == "3.140000000000000e+00");
+ assert (format_f64 (0x40091eb851eb851fU, 15, 'g') == "3.14");
+ assert (format_f64 (0x40091eb851eb851fU, 51)
+ == "3.140000000000000124344978758017532527446746826171875");
+ },
+ },
];
exit (pktest_run (tests) ? 0 : 1);
--
2.39.0
- [PATCH] pkl,std: add `format_f32' and `format_f64' std functions,
Mohammad-Reza Nabipoor <=
- Re: [PATCH] pkl,std: add `format_f32' and `format_f64' std functions, Jose E. Marchesi, 2023/01/07
- Re: [PATCH] pkl,std: add `format_f32' and `format_f64' std functions, Mohammad-Reza Nabipoor, 2023/01/08
- Re: [PATCH] pkl,std: add `format_f32' and `format_f64' std functions, Jose E. Marchesi, 2023/01/08
- [PATCH v2 1/2] pkl, testsuite: add support for printing/formatting floating-points, Mohammad-Reza Nabipoor, 2023/01/08
- [PATCH v2 2/2] pickles: add new pickle for floating-point numbers, Mohammad-Reza Nabipoor, 2023/01/08
- Re: [PATCH v2 2/2] pickles: add new pickle for floating-point numbers, Jose E. Marchesi, 2023/01/08
- Re: [PATCH v2 1/2] pkl,testsuite: add support for printing/formatting floating-points, Jose E. Marchesi, 2023/01/08
- [PATCH v3] pkl, testsuite: add support for printing/formatting floating-points, Mohammad-Reza Nabipoor, 2023/01/10
- Re: [PATCH v3] pkl,testsuite: add support for printing/formatting floating-points, Jose E. Marchesi, 2023/01/10
- Re: [PATCH v3] pkl,testsuite: add support for printing/formatting floating-points, Mohammad-Reza Nabipoor, 2023/01/11