[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] pkl,std: add `format_f32' and `format_f64' std functions
From: |
Jose E. Marchesi |
Subject: |
Re: [PATCH] pkl,std: add `format_f32' and `format_f64' std functions |
Date: |
Sun, 08 Jan 2023 00:21:28 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) |
Hi Mohammad.
> This commit adds two new library functions to create string
> representation of single/double-precision floating-point numbers
> from uint<32>/uint<64>.
Wouldn't it be better to add support for %f, %e and %g to `format' and
`printf' instead of having these library functions?
>
> 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);
- [PATCH] pkl,std: add `format_f32' and `format_f64' std functions, Mohammad-Reza Nabipoor, 2023/01/07
- Re: [PATCH] pkl,std: add `format_f32' and `format_f64' std functions,
Jose E. Marchesi <=
- 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