poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 1/2] pkl,testsuite: add support for printing/formatting fl


From: Jose E. Marchesi
Subject: Re: [PATCH v2 1/2] pkl,testsuite: add support for printing/formatting floating-points
Date: Mon, 09 Jan 2023 03:23:44 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Hi Mohammad.

Thanks very much for the patch.  This is great to have :)
Please see a few comments below.

> diff --git a/doc/poke.texi b/doc/poke.texi
> index ab0ba0c7..392f5f4c 100644
> --- a/doc/poke.texi
> +++ b/doc/poke.texi
> @@ -14485,6 +14485,19 @@ integers.
>  Same as @code{%i}, but for unsigned integers.
>  @item %c
>  A shorter way to write @code{%u8c}.
> +@item %(f|e|g)@var{bits}d

I would prefer to use this instead:

@item %f@var{bits}[.@var{precision}]d
@itemx %e@var{bits}[.@var{precision}]d
@itemx %g@var{bits}[.@var{precision}]d

and include the documentation for `precision' in the same table entry;
precision needs better documentation as well: how exactly is it
interpreted?

> +Reinterpret the argument as @var{bits}-wide floating-point number
> +and print the floating-point value in base 10 similar to C's
> +@code{printf} library function.  Currently, @var{bits} can only be
> +32 or 64.

I would be more explicit about the fact an integral value is expected,
i.e. something like:

"These tags accept integral values, that are cast to @var{bits} and then
 interpreted as an IEEE 754 floating-point number."

Also, we ought to document %f, %e and %g here: what is the difference
between them?

> +
> +@example
> +(poke) printf ("%f64d\n", 0x40091eb851eb851fUL);
> +3.140000000000000
> +@end example
> +
> +@item %(f|e|g)@var{bits}.@var{precision}d
> +Same as previous item, but with specified @var{precision}.
>  @item %v
>  Print the value printed representation of the argument, which can be
>  of any type including complex types like arrays and structs.  This is
> diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
> index 3b56175d..f652dd52 100644
> --- a/libpoke/pkl-ast.h
> +++ b/libpoke/pkl-ast.h
> @@ -1416,6 +1416,14 @@ pkl_ast_node pkl_ast_make_format (pkl_ast ast, 
> pkl_ast_node fmt,
>     VALUE_P indicates whether the argument shall be printed as a PVM
>     value or not (whether this argument corresponds to a %v or not).
>  
> +   FLOATING_POINT_P indicates whether the argument shall be interpreted
> +   as a floating-point number.
> +
> +   FLOATING_POINT_STYLE specify the floating-point style. This is similar
> +   to C's printf function: %f, %e, %g.

Please document that the field is supposed to store the ascii codes 'f',
'e' or 'g', and the meaning of each.  "similar ot C's printf function"
is too vague.

> +
> +   FLOATING_POINT_PREC specify the precision for the floating-point number.

This comment needs to be expanded: how is the precision interpreted in
the field?

Also, the documentation for FLOATING_POINT_WIDTH is missing.  I
recommend defining PKL_AST_FP_WIDTH_{SINGLE,DOUBLE} in pkl-ast.h for
32-bit and 64-bit respectively, instead of relying on particular
bit-numbers like 32 and 64.

> +
>     FORMAT_MODE and FORMAT_DEPTH specify how the argument shall be
>     printed if VALUE_P is true.  FORMAT_MODE can be one of the
>     PKL_AST_FORMAT_MODE_* constants defined below, while FORMAT_DEPTH can
> @@ -1427,6 +1435,10 @@ pkl_ast_node pkl_ast_make_format (pkl_ast ast, 
> pkl_ast_node fmt,
>  #define PKL_AST_FORMAT_ARG_BEGIN_SC(AST) ((AST)->format_arg.begin_sc)
>  #define PKL_AST_FORMAT_ARG_END_SC(AST) ((AST)->format_arg.end_sc)
>  #define PKL_AST_FORMAT_ARG_VALUE_P(AST) ((AST)->format_arg.value_p)
> +#define PKL_AST_FORMAT_ARG_FLOATING_POINT_P(AST) ((AST)->format_arg.fp_p)
> +#define PKL_AST_FORMAT_ARG_FLOATING_POINT_STYLE(AST) 
> ((AST)->format_arg.fp_style)
> +#define PKL_AST_FORMAT_ARG_FLOATING_POINT_PREC(AST) 
> ((AST)->format_arg.fp_prec)
> +#define PKL_AST_FORMAT_ARG_FLOATING_POINT_WIDTH(AST) 
> ((AST)->format_arg.fp_width)
>  #define PKL_AST_FORMAT_ARG_FORMAT_MODE(AST) ((AST)->format_arg.format_mode)
>  #define PKL_AST_FORMAT_ARG_FORMAT_DEPTH(AST) ((AST)->format_arg.format_depth)
>  
> @@ -1441,6 +1453,10 @@ struct pkl_ast_format_arg
>    char *end_sc;
>    int base;
>    int value_p;
> +  int fp_p;
> +  int fp_style;
> +  unsigned fp_prec;
> +  unsigned fp_width;

Please follow the existing convention to name the fields after the
corresponding part of the macros, i.e. floating_point_p,
floaitng_point_style , floating_point_prec and floating_point_width.

>    int format_mode;
>    int format_depth;
>    char *suffix;
> diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
> index 94b33dd7..27217d88 100644
> --- a/libpoke/pkl-gen.c
> +++ b/libpoke/pkl-gen.c
> @@ -1462,49 +1462,83 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_format)
>        /* Generate code to put the value on the stack.  */
>        PKL_PASS_SUBPASS (exp);
>  
> -      /* Everything except %v.  */
> -      if (!PKL_AST_FORMAT_ARG_VALUE_P (arg))
> +      if (PKL_AST_FORMAT_ARG_VALUE_P (arg))

I am having a hard time understanding the changes in the code generator
handler for `format'.

I understand the addition of the PKL_AST_FORMAT_ARG_FLOATING_POINT_P
(arg) if alternative, but why all the code non concerned with fp
printing being moved around?

>          {
> +          /* Generate code to format the literal value (%v).  */
> +          exp_type = PKL_AST_TYPE (exp);
> +          arg_omode = PKL_AST_FORMAT_ARG_FORMAT_MODE (arg);
> +          arg_odepth = PKL_AST_FORMAT_ARG_FORMAT_DEPTH (arg);
> +
> +          /* Set the argument's own omode and odepth, saving
> +             the VM's own.  */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHOM); /* OMODE */
>            pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> -                        base ? pvm_make_int (base, 32) : PVM_NULL);
> -          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_FORMAT, PKL_AST_TYPE (exp));
> -          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, pvm_make_ulong (nstr++, 
> 64));
> -          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_SWAP);
> -          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_AINS);
> -          goto fmt_suffix;
> -        }
> +                        pvm_make_int (arg_omode, 32)); /* OMODE NOMODE */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM);  /* OMODE */
>  
> -      /* Generate code to format the literal value (%v).  */
> -      exp_type = PKL_AST_TYPE (exp);
> -      arg_omode = PKL_AST_FORMAT_ARG_FORMAT_MODE (arg);
> -      arg_odepth = PKL_AST_FORMAT_ARG_FORMAT_DEPTH (arg);
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHOD); /* OMODE ODEPTH */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                        pvm_make_int (arg_odepth, 32)); /* OMODE ODEPTH 
> NODEPTH */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD);   /* OMODE ODEPTH */
>  
> -      /* Set the argument's own omode and odepth, saving
> -         the VM's own.  */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHOM); /* OMODE */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> -                    pvm_make_int (arg_omode, 32)); /* OMODE NOMODE */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM);  /* OMODE */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_ROT); /* OMODE ODEPTH EXP */
>  
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHOD); /* OMODE ODEPTH */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> -                    pvm_make_int (arg_odepth, 32)); /* OMODE ODEPTH NODEPTH 
> */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD);   /* OMODE ODEPTH */
> +          /* Format the value.  */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                        pvm_make_int (0, 32)); /* OMODE ODEPTH EXP DEPTH */
> +          PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_FORMATER);
> +          PKL_PASS_SUBPASS (exp_type); /* OMODE ODEPTH STR */
> +          PKL_GEN_POP_CONTEXT;
>  
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_ROT); /* OMODE ODEPTH EXP */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_NROT); /* STR OMODE ODEPTH */
>  
> -      /* Format the value.  */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> -                    pvm_make_int (0, 32)); /* OMODE ODEPTH EXP DEPTH */
> -      PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_FORMATER);
> -      PKL_PASS_SUBPASS (exp_type); /* OMODE ODEPTH STR */
> -      PKL_GEN_POP_CONTEXT;
> +          /* Restore the current omode and odepth in the VM.  */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD); /* ARR STR OMODE */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM); /* ARR STR */
> +        }
> +      else if (PKL_AST_FORMAT_ARG_FLOATING_POINT_P (arg))
> +        {
> +          enum pkl_asm_insn insn;
> +          pvm_val prec
> +              = pvm_make_uint (PKL_AST_FORMAT_ARG_FLOATING_POINT_PREC (arg),
> +                               32);
>  
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_NROT); /* STR OMODE ODEPTH */
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, prec); /* ARR EXP PREC */
> +
> +          switch (PKL_AST_FORMAT_ARG_FLOATING_POINT_WIDTH (arg))
> +            {
> +            case 32:
> +              insn = PKL_INSN_FORMATF32;
> +              break;
> +            case 64:
> +              insn = PKL_INSN_FORMATF64;
> +              break;
> +            default:
> +              assert (0 && "unreachable reached");
> +            }
> +          switch (PKL_AST_FORMAT_ARG_FLOATING_POINT_STYLE (arg))
> +            {
> +            case 'f':
> +              pkl_asm_insn (PKL_GEN_ASM, insn, 0);  /* ARR STR */
> +              break;
> +            case 'e':
> +              pkl_asm_insn (PKL_GEN_ASM, insn, 1);  /* ARR STR */
> +              break;
> +            case 'g':
> +              pkl_asm_insn (PKL_GEN_ASM, insn, 2);  /* ARR STR */
> +              break;
> +            default:
> +              assert (0 && "unreachable reached");
> +            }
> +        }
> +      else
> +        {
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                        base ? pvm_make_int (base, 32) : PVM_NULL);
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_FORMAT,
> +                        PKL_AST_TYPE (exp));  /* ARR STR */
> +        }
>  
> -      /* Restore the current omode and odepth in the VM.  */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD); /* ARR STR OMODE */
> -      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM); /* ARR STR */
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
>                      pvm_make_ulong (nstr++, 64)); /* ARR STR IDX */
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_SWAP);  /* ARR IDX STR */
> @@ -1642,6 +1676,41 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_print_stmt)
>                    pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD); /* OMODE */
>                    pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM); /* _ */
>                  }

What follows i what I would expect for the format handler as well: just
the addition of the case to handle floating-point arguments...

> +              else if (PKL_AST_FORMAT_ARG_FLOATING_POINT_P (arg))
> +                {
> +                  enum pkl_asm_insn insn;
> +                  pvm_val prec = pvm_make_uint (
> +                      PKL_AST_FORMAT_ARG_FLOATING_POINT_PREC (arg), 32);
> +
> +                  pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, prec); /* EXP 
> PREC */
> +
> +                  switch (PKL_AST_FORMAT_ARG_FLOATING_POINT_WIDTH (arg))
> +                    {
> +                    case 32:
> +                      insn = PKL_INSN_FORMATF32;
> +                      break;
> +                    case 64:
> +                      insn = PKL_INSN_FORMATF64;
> +                      break;
> +                    default:
> +                      assert (0 && "unreachable reached");
> +                    }
> +                  switch (PKL_AST_FORMAT_ARG_FLOATING_POINT_STYLE (arg))
> +                    {
> +                    case 'f':
> +                      pkl_asm_insn (PKL_GEN_ASM, insn, 0);  /* STR */
> +                      break;
> +                    case 'e':
> +                      pkl_asm_insn (PKL_GEN_ASM, insn, 1);  /* STR */
> +                      break;
> +                    case 'g':
> +                      pkl_asm_insn (PKL_GEN_ASM, insn, 2);  /* STR */
> +                      break;
> +                    default:
> +                      assert (0 && "unreachable reached");
> +                    }
> +                  pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PRINTS);
> +                }
>                else
>                  {
>                    pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
> index cb4d1973..bd764348 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/pkl-trans.c b/libpoke/pkl-trans.c
> index 355c0d49..b7d88976 100644
> --- a/libpoke/pkl-trans.c
> +++ b/libpoke/pkl-trans.c
> @@ -25,6 +25,7 @@
>  #include <string.h>
>  #include <xalloc.h>
>  #include <stdlib.h>
> +#include <errno.h>
>  
>  #include "pk-utils.h"
>  
> @@ -683,8 +684,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_format)
>    pkl_ast_node args = PKL_AST_FORMAT_ARGS (format);
>    pkl_ast_node format_fmt = PKL_AST_FORMAT_FMT (format);
>    char *fmt, *p;
> -  pkl_ast_node t, arg;
> -  int ntag, nargs = 0;
> +  pkl_ast_node arg;
> +  int ntag, nargs = PKL_AST_FORMAT_NARGS (format);
>    pkl_ast_node types = NULL, prev_arg = NULL;
>    const char *msg = NULL;
>    /* XXX this hard limit should go away.  */
> @@ -696,7 +697,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_format)
>    char *new_style_class = NULL;
>  
>    /* Calculate the number of arguments.  */
> -  for (t = args; t; t = PKL_AST_CHAIN (t))
> +  for (pkl_ast_node t = args; t; t = PKL_AST_CHAIN (t))

Why this change?

>      nargs++;
>    PKL_AST_FORMAT_NARGS (format) = nargs;
>  
> @@ -878,6 +879,107 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_format)
>              ntag++;
>              break;
>            }
> +        case 'f':
> +        case 'e':
> +        case 'g':
> +          {
> +            unsigned int bits;
> +
> +            PKL_AST_FORMAT_ARG_FLOATING_POINT_P (arg) = 1;
> +            PKL_AST_FORMAT_ARG_FLOATING_POINT_STYLE (arg) = p[1];
> +
> +            if (p[2] >= '0' && p[2] <= '9')
> +              {
> +                int next_idx;
> +
> +                if (p[3] >= '0' && p[3] <= '9')
> +                  {
> +                    bits = (p[2] - '0') * 10 + (p[3] - '0');
> +                    next_idx = 4;
> +                  }
> +                else
> +                  {
> +                    bits = p[2] - '0';
> +                    next_idx = 3;
> +                  }
> +
> +                if (bits == 0 || !(/*bits == 16 ||*/ bits == 32 || bits == 
> 64))
> +                  {
> +                    msg = _("invalid bit-width for a floating-point number");
> +                    goto invalid_tag;
> +                  }
> +                PKL_AST_FORMAT_ARG_FLOATING_POINT_WIDTH (arg) = bits;
> +
> +                if (p[next_idx] == '.')
> +                  {
> +                    int prec_begin_idx;
> +                    char tmp;
> +                    long prec;
> +
> +                    prec_begin_idx = ++next_idx;
> +                    while (p[next_idx] >= '0' && p[next_idx] <= '9')
> +                      ++next_idx;
> +                    if (next_idx == prec_begin_idx)
> +                      {
> +                        msg = _("expected a precision number after dot");
> +                        goto invalid_tag;
> +                      }
> +                    tmp = p[next_idx];
> +                    p[next_idx] = '\0';
> +                    errno = 0;
> +                    prec = strtol (&p[prec_begin_idx], NULL, 10);
> +                    if (errno != 0)
> +                      {
> +                        msg = _("invalid precision");
> +                        goto invalid_tag;
> +                      }
> +                    PKL_AST_FORMAT_ARG_FLOATING_POINT_PREC (arg)
> +                        = (unsigned)prec;
> +                    p[next_idx] = tmp;
> +                  }
> +                else
> +                  {
> +                    PKL_AST_FORMAT_ARG_FLOATING_POINT_PREC (arg)
> +                        = bits == 32 ? 7 : 15;
> +                  }
> +
> +                switch (p[next_idx])
> +                  {
> +                  case 'b': PKL_AST_FORMAT_ARG_BASE (arg) = 2; break;
> +                  case 'o': PKL_AST_FORMAT_ARG_BASE (arg) = 8; break;
> +                  case 'd': PKL_AST_FORMAT_ARG_BASE (arg) = 10; break;
> +                  case 'x': PKL_AST_FORMAT_ARG_BASE (arg) = 16; break;
> +                  default:
> +                    msg = _("invalid base");
> +                    goto invalid_tag;
> +                  }
> +
> +                if (PKL_AST_FORMAT_ARG_BASE (arg) != 10)
> +                  {
> +                    msg = _("only base 10 is supported for floating-point 
> numbers");
> +                    goto invalid_tag;
> +                  }
> +
> +                atype = pkl_ast_make_integral_type (PKL_PASS_AST,
> +                                                    bits, /*signed_p*/ 0);
> +                types = pkl_ast_chainon (types, atype);
> +
> +                p += ++next_idx;
> +              }
> +            else
> +              {
> +                if (p[1] == 'f')
> +                  msg = _("expected decimal digit after %f");
> +                else if (p[1] == 'e')
> +                  msg = _("expected decimal digit after %e");
> +                else
> +                  msg = _("expected decimal digit after %g");
> +
> +                goto invalid_tag;
> +              }
> +            ntag++;
> +            break;
> +          }
>          case '<':
>            /* Fallthrough.  */
>          case '>':
> diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
> index 35be8504..e8ba8425 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

What are these different styles?

> +#
> +# Stack: ( UINT UINT -- STR )
> +
> +instruction formatf32 (?n)
> +  branching # because of PVM_RAISE_DIRECT
> +  code
> +    char *result = NULL;
> +    uint32_t num = PVM_VAL_UINT (JITTER_UNDER_TOP_STACK ());
> +    unsigned style = (unsigned)JITTER_ARGN0;
> +    uint32_t precision = PVM_VAL_UINT (JITTER_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

What are these different styles?

> +#
> +# Stack: ( ULONG UINT -- STR )
> +
> +instruction formatf64 (?n)
> +  branching # because of PVM_RAISE_DIRECT
> +  code
> +    char *result = NULL;
> +    uint64_t num = PVM_VAL_ULONG (JITTER_UNDER_TOP_STACK ());
> +    unsigned style = (unsigned)JITTER_ARGN0;
> +    uint32_t precision = PVM_VAL_UINT (JITTER_TOP_STACK ());
> +
> +    JITTER_DROP_STACK ();
> +    FORMATF (result, num, precision, style, double);
> +    JITTER_TOP_STACK () = pvm_make_string (result);
> +    free (result);
> +  end
> +end
> +
>  



reply via email to

[Prev in Thread] Current Thread [Next in Thread]