@@@ fltfmt wip
[mLib] / utils / t / fltfmt-test.c
index 5b60607..9ed7c68 100644 (file)
@@ -208,7 +208,7 @@ static void test_round(const struct tvec_reg *in, struct tvec_reg *out,
 static const struct tvec_test round_test =
   { "round", round_regs, 0, test_round };
 
-/*----- IEEE format conversion --------------------------------------------*/
+/*----- IEEE format conversion-------------------------------------------*/
 
 #define IEEE_FORMATS(_)                                                        \
   _(mini, 1)                                                           \
@@ -348,7 +348,7 @@ IEEE_FORMATS(DEF_TEST)
 #define DEF_IEEE_TEST(ty, sz) &enc##ty##_test, &dec##ty##_test,
 #define IEEE_TESTS IEEE_FORMATS(DEF_IEEE_TEST)
 
-/*----- Native format conversion ------------------------------------------*/
+/*----- Native format conversion-----------------------------------------*/
 
 #define NATIVE_FORMATS(_)                                              \
   _(flt, float, FLT)                                                   \
@@ -393,64 +393,64 @@ static const struct tvec_flag assume_flags[] = {
 static const struct tvec_flaginfo assume_flaginfo =
   { "assume", assume_flags, &tvrange_uint };
 
-struct nativeenv { struct tvec_env _env; unsigned ntv; };
-struct nativectx { unsigned af, want; };
+struct assumeenv { struct tvec_env _env; unsigned ntv; };
+struct assumectx { unsigned af, want; };
 
-static void setup_native(struct tvec_state *tv, const struct tvec_env *env,
+static void setup_assume(struct tvec_state *tv, const struct tvec_env *env,
                         void *pctx, void *ctx)
 {
-  const struct nativeenv *nenv = (const struct nativeenv *)env;
-  const struct ntvinfo *info = &ntvinfo[nenv->ntv];
-  struct nativectx *nctx = ctx;
+  const struct assumeenv *aenv = (const struct assumeenv *)env;
+  const struct ntvinfo *info = &ntvinfo[aenv->ntv];
+  struct assumectx *actx = ctx;
   double prec;
 
   switch (info->fmt&(FLTFMT_ORGMASK | FLTFMT_TYPEMASK)) {
     case FLTFMT_IEEE_F32:
-      nctx->af = AF_NEGZ | AF_INF | AF_IEEE | AF_PREC24;
+      actx->af = AF_NEGZ | AF_INF | AF_IEEE | AF_PREC24;
       break;
     case FLTFMT_IEEE_F64:
-      nctx->af = AF_NEGZ | AF_INF | AF_IEEE | AF_PREC24 | AF_PREC53;
+      actx->af = AF_NEGZ | AF_INF | AF_IEEE | AF_PREC24 | AF_PREC53;
       break;
     case FLTFMT_IEEE_F128:
-      nctx->af = AF_NEGZ | AF_INF | AF_IEEE |
+      actx->af = AF_NEGZ | AF_INF | AF_IEEE |
                 AF_PREC24 | AF_PREC53 | AF_PREC64 | AF_PREC113;
       break;
     case FLTFMT_INTEL_F80:
-      nctx->af = AF_NEGZ | AF_INF | AF_IEEE |
+      actx->af = AF_NEGZ | AF_INF | AF_IEEE |
                 AF_PREC24 | AF_PREC53 | AF_PREC64;
       break;
     default:
-      nctx->af = 0;
-      if (NEGP(-0.0)) nctx->af |= AF_NEGZ;
+      actx->af = 0;
+      if (NEGP(-0.0)) actx->af |= AF_NEGZ;
 #ifdef INF
-      nctx->af |= AF_INF;
+      actx->af |= AF_INF;
 #endif
 #ifdef NAN
-      nctx->af |= AF_STDCNAN;
+      actx->af |= AF_STDCNAN;
 #endif
       prec = log(FLT_RADIX)/log(2.0)*info->mant_dig;
-      if (prec >= 24) nctx->af |= AF_PREC24;
-      if (prec >= 53) nctx->af |= AF_PREC53;
-      if (prec >= 64) nctx->af |= AF_PREC64;
-      if (prec >= 113) nctx->af |= AF_PREC113;
+      if (prec >= 24) actx->af |= AF_PREC24;
+      if (prec >= 53) actx->af |= AF_PREC53;
+      if (prec >= 64) actx->af |= AF_PREC64;
+      if (prec >= 113) actx->af |= AF_PREC113;
       break;
   }
-  nctx->want = 0;
+  actx->want = 0;
 }
 
-static int setvar_native(struct tvec_state *tv, const char *var,
+static int setvar_assume(struct tvec_state *tv, const char *var,
                         const union tvec_regval *rv, void *ctx)
 {
-  struct nativectx *nctx = ctx;
+  struct assumectx *actx = ctx;
 
-  if (STRCMP(var, ==, "@assume")) nctx->want = rv->u;
+  if (STRCMP(var, ==, "@assume")) actx->want = rv->u;
   else return (tvec_unkregerr(tv, var));
   return (0);
 }
 static const struct tvec_vardef assume_vardef =
-  { sizeof(struct tvec_reg), setvar_native,
+  { sizeof(struct tvec_reg), setvar_assume,
     { "@assume", &tvty_flags, 0, 0, { &assume_flaginfo } }};
-static const struct tvec_vardef *findvar_native
+static const struct tvec_vardef *findvar_assume
   (struct tvec_state *tv, const char *name, void **ctx_out, void *ctx)
 {
   if (STRCMP(name, ==, "@assume"))
@@ -459,11 +459,11 @@ static const struct tvec_vardef *findvar_native
     return (0);
 }
 
-static void before_native(struct tvec_state *tv, void *ctx)
+static void before_assume(struct tvec_state *tv, void *ctx)
 {
-  struct nativectx *nctx = ctx;
+  struct assumectx *actx = ctx;
 
-  if (nctx->want&~nctx->af)
+  if ((tv->f&TVSF_ACTIVE) && (actx->want&~actx->af))
     tvec_skip(tv, "unsatisfied assumption");
   else {
     DEFAULT_REG(RROUND, rv->u = FLTRND_NEAREVEN);
@@ -471,18 +471,18 @@ static void before_native(struct tvec_state *tv, void *ctx)
   }
 }
 
-static void after_native(struct tvec_state *tv, void *ctx)
+static void after_assume(struct tvec_state *tv, void *ctx)
 {
-  struct nativectx *nctx = ctx;
+  struct assumectx *actx = ctx;
 
-  nctx->want = 0;
+  actx->want = 0;
 }
 
 #define DEF_TEST(ty, cty, TY)                                          \
                                                                        \
-  static struct nativeenv ty##_env =                                   \
-    { { sizeof(struct nativectx),                                      \
-       setup_native, findvar_native, before_native, 0, after_native, 0 }, \
+  static struct assumeenv ty##_env =                                   \
+    { { sizeof(struct assumectx),                                      \
+       setup_assume, findvar_assume, before_assume, 0, after_assume, 0 }, \
       NTV_##TY };                                                      \
                                                                        \
   static const struct tvec_regdef enc##ty##_regs[] = {                 \
@@ -538,12 +538,93 @@ NATIVE_FORMATS(DEF_TEST)
 #define DEF_NATIVE_TEST(ty, cty, TY) &enc##ty##_test, &dec##ty##_test,
 #define NATIVE_TESTS NATIVE_FORMATS(DEF_NATIVE_TEST)
 
+/*----- Direct conversions ------------------------------------------------*/
+
+#define DIRECT_CONVERSIONS(_)                                          \
+  _(flt, float, f32)                                                   \
+  _(dbl, double, f64)
+
+#define DEF_TEST1(ty, cty, fty, e)                                     \
+  static void test_##ty##to##fty##e(const struct tvec_reg *in,         \
+                                   struct tvec_reg *out,               \
+                                   void *ctx)                          \
+  {                                                                    \
+    tvec_allocbytes(&out[RZ_OUT].v, OUTSZ_##fty);                      \
+    out[RERR_OUT].v.u = fltfmt_##ty##to##fty##e(out[RZ_OUT].v.bytes.p, \
+                                               in[RX].v.f,             \
+                                               in[RROUND].v.u);        \
+  }                                                                    \
+                                                                       \
+  static const struct tvec_test ty##to##fty##e##_test =                        \
+    { #ty "to" #fty #e, ty##to##fty##_regs, &ty##_env._env,            \
+      test_##ty##to##fty##e };
+
+#define DEF_TEST(ty, cty, fty)                                         \
+  static const struct tvec_regdef ty##to##fty##_regs[] = {             \
+    { "round", &tvty_flags,    RROUND, TVRF_OPT, { &fltrnd_flaginfo } }, \
+    { "x",     &tvty_float,    RX,     0,      { &tvflt_##cty } },     \
+    { "z",     &tvty_bytes,    RZ_OUT, 0,      { &fty##_range } },     \
+    { "err",   &tvty_flags,    RERR_OUT, TVRF_OPT, { &flterr_flaginfo } }, \
+    TVEC_ENDREGS                                                       \
+  };                                                                   \
+                                                                       \
+  DEF_TEST1(ty, cty, fty, l)                                           \
+  DEF_TEST1(ty, cty, fty, b)
+
+DIRECT_CONVERSIONS(DEF_TEST)
+
+#undef DEF_TEST1
+#undef DEF_TEST
+
+#define DEF_TEST1(ty, cty, fty, e)                                     \
+  static void test_##fty##e##to##ty(const struct tvec_reg *in,         \
+                                   struct tvec_reg *out,               \
+                                   void *ctx)                          \
+  {                                                                    \
+    cty z;                                                             \
+                                                                       \
+    out[RERR_OUT].v.u = fltfmt_##fty##e##to##ty(&z, in[RX].v.bytes.p,  \
+                                               in[RROUND].v.u);        \
+    out[RZ_OUT].v.f = z;                                               \
+  }                                                                    \
+                                                                       \
+  static const struct tvec_test fty##e##to##ty##_test =                        \
+    { #fty #e "to" #ty, fty##to##ty##_regs, &ty##_env._env,            \
+      test_##fty##e##to##ty };
+
+#define DEF_TEST(ty, cty, fty)                                         \
+  static const struct tvec_regdef fty##to##ty##_regs[] = {             \
+    { "round", &tvty_flags,    RROUND, TVRF_OPT, { &fltrnd_flaginfo } }, \
+    { "x",     &tvty_bytes,    RX,     0,      { &fty##_range } },     \
+    { "z",     &tvty_float,    RZ_OUT, 0,      { &tvflt_##cty } },     \
+    { "err",   &tvty_flags,    RERR_OUT, TVRF_OPT, { &flterr_flaginfo } }, \
+    TVEC_ENDREGS                                                       \
+  };                                                                   \
+                                                                       \
+  DEF_TEST1(ty, cty, fty, l)                                           \
+  DEF_TEST1(ty, cty, fty, b)
+
+DIRECT_CONVERSIONS(DEF_TEST)
+
+#undef DEF_TEST1
+#undef DEF_TEST
+
+#define DEF_DIRECT_CTOF_TESTS(ty, cty, fty)                            \
+  &ty##to##fty##l_test, &ty##to##fty##b_test,
+#define DEF_DIRECT_FTOC_TESTS(ty, cty, fty)                            \
+  &fty##l##to##ty##_test, &fty##b##to##ty##_test,
+#define DEF_DIRECT_TESTS(ty, cty, fty)                                 \
+  DEF_DIRECT_CTOF_TESTS(ty, cty, fty)                                  \
+  DEF_DIRECT_FTOC_TESTS(ty, cty, fty)
+#define DIRECT_TESTS DIRECT_CONVERSIONS(DEF_DIRECT_TESTS)
+
 /*----- Main code ---------------------------------------------------------*/
 
 static const struct tvec_test *const tests[] = {
   &round_test,
   NATIVE_TESTS
   IEEE_TESTS
+  DIRECT_TESTS
   0
 };