Home | History | Annotate | Line # | Download | only in expr
      1 /* Test expression evaluation (print nothing and exit 0 if successful).
      2 
      3 Copyright 2000-2004 Free Software Foundation, Inc.
      4 
      5 This file is part of the GNU MP Library.
      6 
      7 The GNU MP Library is free software; you can redistribute it and/or modify
      8 it under the terms of either:
      9 
     10   * the GNU Lesser General Public License as published by the Free
     11     Software Foundation; either version 3 of the License, or (at your
     12     option) any later version.
     13 
     14 or
     15 
     16   * the GNU General Public License as published by the Free Software
     17     Foundation; either version 2 of the License, or (at your option) any
     18     later version.
     19 
     20 or both in parallel, as here.
     21 
     22 The GNU MP Library is distributed in the hope that it will be useful, but
     23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     24 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     25 for more details.
     26 
     27 You should have received copies of the GNU General Public License and the
     28 GNU Lesser General Public License along with the GNU MP Library.  If not,
     29 see https://www.gnu.org/licenses/.  */
     30 
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 
     34 #include "gmp-impl.h"
     35 #include "tests.h"
     36 #include "expr-impl.h"
     37 
     38 
     39 int  option_trace = 0;
     40 
     41 
     42 struct data_t {
     43   int         base;
     44   const char  *expr;
     45   const char  *want;
     46 };
     47 
     48 #define numberof(x)  (sizeof (x) / sizeof ((x)[0]))
     49 
     50 
     51 /* These data_xxx[] arrays are tables to be tested with one or more of the
     52    mp?_t types.  z=mpz_t, q=mpz_t, f=mpf_t.  */
     53 
     54 struct data_t  data_zqf[] = {
     55 
     56   /* various deliberately wrong expressions */
     57   { 0, "", NULL },
     58   { 0, "1+", NULL },
     59   { 0, "+2", NULL },
     60   { 0, "1,2", NULL },
     61   { 0, "foo(1,2)", NULL },
     62   { 0, "1+foo", NULL },
     63   { 10, "0fff", NULL },
     64   { 0, "!", NULL },
     65   { 0, "10!", NULL },
     66   { 0, "-10!", NULL },
     67   { 0, "gcd((4,6))", NULL },
     68   { 0, "()", NULL },
     69   { 0, "fac(2**1000)", NULL },
     70   { 0, "$", NULL },
     71   { 0, "$-", NULL },
     72 
     73   /* some basics */
     74   { 10, "123", "123" },
     75   { 10, "-123", "-123" },
     76   { 10, "1+2", "3" },
     77   { 10, "1+2+3", "6" },
     78   { 10, "1+2*3", "7" },
     79   { 10, "3*2+1", "7" },
     80   { 10, "$a", "55" },
     81   { 10, "b", "99" },
     82   { 16, "b", "11" },
     83   { 10, "4**3 * 2 + 1", "129" },
     84   { 10, "1<2", "1" },
     85   { 10, "1>2", "0" },
     86 
     87   { 10, "(123)", "123" },
     88 
     89   { 10, "sgn(-123)", "-1" },
     90   { 10, "5-7", "-2" },
     91 
     92   { 0, "cmp(0,0)", "0" },
     93   { 0, "cmp(1,0)", "1" },
     94   { 0, "cmp(0,1)", "-1" },
     95   { 0, "cmp(-1,0)", "-1" },
     96   { 0, "cmp(0,-1)", "1" },
     97 
     98   { 10, "0 ? 123 : 456", "456" },
     99   { 10, "1 ? 4+5 : 6+7", "9" },
    100 
    101   { 10, "(123)", "123" },
    102   { 10, "(2+3)", "5" },
    103   { 10, "(4+5)*(5+6)", "99" },
    104 
    105   { 0, "1 << 16", "65536" },
    106   { 0, "256 >> 4", "16" },
    107   { 0, "-256 >> 4", "-16" },
    108 
    109   { 0, "!1", "0" },
    110   { 0, "!9", "0" },
    111   { 0, "!0", "1" },
    112 
    113   { 0, "2**2**2", "16" },
    114   { 0, "-2**2**2", "-16" },
    115 
    116   { 0, "0x100", "256" },
    117   { 10, "0x100", NULL },
    118   { 10, "0x 100", NULL },
    119 
    120   { 0, " max ( 1, 2, 3, 4, 5, 6, 7, 8)", "8" },
    121   { 0, " max ( 1, 9, 2, 3, 4, 5, 6, 7, 8)", "9" },
    122   { 0, " min ( 1, 9, 2, 3, 4, 5, 6, 7, 8)", "1" },
    123 
    124   { 10, "abs(123)",  "123" },
    125   { 10, "abs(-123)", "123" },
    126   { 10, "abs(0)",    "0" },
    127 
    128   /* filling data stack */
    129   { 0, "1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1))))))))))))))", "16" },
    130 
    131   /* filling control stack */
    132   { 0, "----------------------------------------------------1", "1" },
    133 };
    134 
    135 
    136 const struct data_t  data_z[] = {
    137   { 0, "divisible_p(333,3)", "1" },
    138   { 0, "congruent_p(7,1,3)", "1" },
    139 
    140   { 0, "cmpabs(0,0)", "0" },
    141   { 0, "cmpabs(1,0)", "1" },
    142   { 0, "cmpabs(0,1)", "-1" },
    143   { 0, "cmpabs(-1,0)", "1" },
    144   { 0, "cmpabs(0,-1)", "-1" },
    145 
    146   { 0, "odd_p(1)", "1" },
    147   { 0, "odd_p(0)", "0" },
    148   { 0, "odd_p(-1)", "1" },
    149 
    150   { 0, "even_p(1)", "0" },
    151   { 0, "even_p(0)", "1" },
    152   { 0, "even_p(-1)", "0" },
    153 
    154   { 0, "fac(0)",  "1" },
    155   { 0, "fac(1)",  "1" },
    156   { 0, "fac(2)",  "2" },
    157   { 0, "fac(3)",  "6" },
    158   { 0, "fac(10)", "3628800" },
    159 
    160   { 10, "root(81,4)", "3" },
    161 
    162   { 10, "gcd(4,6)", "2" },
    163   { 10, "gcd(4,6,9)", "1" },
    164 
    165   { 10, "powm(3,2,9)", "0" },
    166   { 10, "powm(3,2,8)", "1" },
    167 
    168   /* filling data stack */
    169   { 0, "1 ? 1 : 1 || 1 && 1 | 1 ^ 1 & 1 == 1 >= 1 << 1 - 1 * 1 ** 1", "1" },
    170 
    171   /* filling control stack */
    172   { 0, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1", "1" },
    173 
    174   { 0, "fib(10)", "55" },
    175 
    176   { 0, "setbit(0,5)", "32" },
    177   { 0, "clrbit(32,5)", "0" },
    178   { 0, "tstbit(32,5)", "1" },
    179   { 0, "tstbit(32,4)", "0" },
    180   { 0, "scan0(7,0)", "3" },
    181   { 0, "scan1(7,0)", "0" },
    182 };
    183 
    184 const struct data_t  data_zq[] = {
    185   /* expecting failure */
    186   { 0, "1.2", NULL },
    187 };
    188 
    189 const struct data_t  data_q[] = {
    190   { 10,  "(1/2 + 1/3 + 1/4 + 1/5 + 1/6)*20", "29" },
    191   { 0, "num(5/9)", "5" },
    192   { 0, "den(5/9)", "9" },
    193 };
    194 
    195 const struct data_t  data_zf[] = {
    196   { 10, "sqrt ( 49 )", "7" },
    197   { 10, "sqrt ( 49 ) + 1", "8" },
    198   { 10, "sqrt((49))", "7" },
    199   { 10, "sqrt((((((((49))))))))", "7" },
    200 };
    201 
    202 const struct data_t  data_f[] = {
    203   { 0, "1@10",    "10000000000" },
    204   { 0, "1.5@10",  "15000000000" },
    205   { 0, "1000@-1", "100" },
    206   { 0, "10.00@-1", "1" },
    207 
    208   { 0, "1e10",     "10000000000" },
    209   { 0, "1.5e10",   "15000000000" },
    210   { 0, "1000e-1",  "100" },
    211   { 0, "10.00e-1", "1" },
    212 
    213   { 16, "1@9",  "68719476736" },
    214 
    215   { 16,  "1@10", "18446744073709551616" },
    216   { -16, "1@10", "1099511627776" },
    217 
    218   { 0, "ceil(0)",           "0" },
    219   { 0, "ceil(0.25)",        "1" },
    220   { 0, "ceil(0.5)",         "1" },
    221   { 0, "ceil(1.5)",         "2" },
    222   { 0, "ceil(-0.5)",        "0" },
    223   { 0, "ceil(-1.5)",        "-1" },
    224 
    225   /* only simple cases because mpf_eq currently only works on whole limbs */
    226   { 0, "eq(0xFFFFFFFFFFFFFFFF1111111111111111,0xFFFFFFFFFFFFFFFF2222222222222222,64)", "1" },
    227   { 0, "eq(0xFFFFFFFFFFFFFFFF1111111111111111,0xFFFFFFFFFFFFFFFF2222222222222222,128)", "0" },
    228 
    229   { 0, "floor(0)",           "0" },
    230   { 0, "floor(0.25)",        "0" },
    231   { 0, "floor(0.5)",         "0" },
    232   { 0, "floor(1.5)",         "1" },
    233   { 0, "floor(-0.5)",        "-1" },
    234   { 0, "floor(-1.5)",        "-2" },
    235 
    236   { 0, "integer_p(1)",   "1" },
    237   { 0, "integer_p(0.5)", "0" },
    238 
    239   { 0, "trunc(0)",           "0" },
    240   { 0, "trunc(0.25)",        "0" },
    241   { 0, "trunc(0.5)",         "0" },
    242   { 0, "trunc(1.5)",         "1" },
    243   { 0, "trunc(-0.5)",        "0" },
    244   { 0, "trunc(-1.5)",        "-1" },
    245 };
    246 
    247 struct datalist_t {
    248   const struct data_t  *data;
    249   int                  num;
    250 };
    251 
    252 #define DATALIST(data)  { data, numberof (data) }
    253 
    254 struct datalist_t  list_z[] = {
    255   DATALIST (data_z),
    256   DATALIST (data_zq),
    257   DATALIST (data_zf),
    258   DATALIST (data_zqf),
    259 };
    260 
    261 struct datalist_t  list_q[] = {
    262   DATALIST (data_q),
    263   DATALIST (data_zq),
    264   DATALIST (data_zqf),
    265 };
    266 
    267 struct datalist_t  list_f[] = {
    268   DATALIST (data_zf),
    269   DATALIST (data_zqf),
    270   DATALIST (data_f),
    271 };
    272 
    273 
    274 void
    275 check_z (void)
    276 {
    277   const struct data_t  *data;
    278   mpz_t  a, b, got, want;
    279   int    l, i, ret;
    280 
    281   mpz_init (got);
    282   mpz_init (want);
    283   mpz_init_set_ui (a, 55);
    284   mpz_init_set_ui (b, 99);
    285 
    286   for (l = 0; l < numberof (list_z); l++)
    287     {
    288       data = list_z[l].data;
    289 
    290       for (i = 0; i < list_z[l].num; i++)
    291         {
    292           if (option_trace)
    293             printf ("mpz_expr \"%s\"\n", data[i].expr);
    294 
    295           ret = mpz_expr (got, data[i].base, data[i].expr, a, b, NULL);
    296 
    297           if (data[i].want == NULL)
    298             {
    299               /* expect to fail */
    300               if (ret == MPEXPR_RESULT_OK)
    301                 {
    302                   printf ("mpz_expr wrong return value, got %d, expected failure\n", ret);
    303                   goto error;
    304                 }
    305             }
    306           else
    307             {
    308               if (mpz_set_str (want, data[i].want, 0) != 0)
    309                 {
    310                   printf ("Cannot parse wanted value string\n");
    311                   goto error;
    312                 }
    313               if (ret != MPEXPR_RESULT_OK)
    314                 {
    315                   printf ("mpz_expr failed unexpectedly\n");
    316                   printf ("   return value %d\n", ret);
    317                   goto error;
    318                 }
    319               if (mpz_cmp (got, want) != 0)
    320                 {
    321                   printf ("mpz_expr wrong result\n");
    322                   printf ("   got  "); mpz_out_str (stdout, 10, got);
    323                   printf ("\n");
    324                   printf ("   want "); mpz_out_str (stdout, 10, want);
    325                   printf ("\n");
    326                   goto error;
    327                 }
    328             }
    329         }
    330     }
    331   mpz_clear (a);
    332   mpz_clear (b);
    333   mpz_clear (got);
    334   mpz_clear (want);
    335   return;
    336 
    337  error:
    338   printf ("   base %d\n", data[i].base);
    339   printf ("   expr \"%s\"\n", data[i].expr);
    340   if (data[i].want != NULL)
    341     printf ("   want \"%s\"\n", data[i].want);
    342   abort ();
    343 }
    344 
    345 void
    346 check_q (void)
    347 {
    348   const struct data_t  *data;
    349   mpq_t  a, b, got, want;
    350   int    l, i, ret;
    351 
    352   mpq_init (got);
    353   mpq_init (want);
    354   mpq_init (a);
    355   mpq_init (b);
    356 
    357   mpq_set_ui (a, 55, 1);
    358   mpq_set_ui (b, 99, 1);
    359 
    360   for (l = 0; l < numberof (list_q); l++)
    361     {
    362       data = list_q[l].data;
    363 
    364       for (i = 0; i < list_q[l].num; i++)
    365         {
    366           if (option_trace)
    367             printf ("mpq_expr \"%s\"\n", data[i].expr);
    368 
    369           ret = mpq_expr (got, data[i].base, data[i].expr, a, b, NULL);
    370 
    371           if (data[i].want == NULL)
    372             {
    373               /* expect to fail */
    374               if (ret == MPEXPR_RESULT_OK)
    375                 {
    376                   printf ("mpq_expr wrong return value, got %d, expected failure\n", ret);
    377                   goto error;
    378                 }
    379             }
    380           else
    381             {
    382               if (mpz_set_str (mpq_numref(want), data[i].want, 0) != 0)
    383                 {
    384                   printf ("Cannot parse wanted value string\n");
    385                   goto error;
    386                 }
    387               mpz_set_ui (mpq_denref(want), 1);
    388 
    389               if (ret != MPEXPR_RESULT_OK)
    390                 {
    391                   printf ("mpq_expr failed unexpectedly\n");
    392                   printf ("   return value %d\n", ret);
    393                   goto error;
    394                 }
    395               if (mpq_cmp (got, want) != 0)
    396                 {
    397                   printf ("mpq_expr wrong result\n");
    398                   printf ("   got  "); mpq_out_str (stdout, 10, got);
    399                   printf ("\n");
    400                   printf ("   want "); mpq_out_str (stdout, 10, want);
    401                   printf ("\n");
    402                   goto error;
    403                 }
    404             }
    405         }
    406     }
    407   mpq_clear (a);
    408   mpq_clear (b);
    409   mpq_clear (got);
    410   mpq_clear (want);
    411   return;
    412 
    413  error:
    414   printf ("   base %d\n", data[i].base);
    415   printf ("   expr \"%s\"\n", data[i].expr);
    416   if (data[i].want != NULL)
    417     printf ("   want \"%s\"\n", data[i].want);
    418   abort ();
    419 }
    420 
    421 void
    422 check_f (void)
    423 {
    424   const struct data_t  *data;
    425   mpf_t  a, b, got, want;
    426   int    l, i, ret;
    427 
    428   mpf_set_default_prec (200L);
    429 
    430   mpf_init (got);
    431   mpf_init (want);
    432   mpf_init_set_ui (a, 55);
    433   mpf_init_set_ui (b, 99);
    434 
    435   for (l = 0; l < numberof (list_f); l++)
    436     {
    437       data = list_f[l].data;
    438 
    439       for (i = 0; i < list_f[l].num; i++)
    440         {
    441           if (option_trace)
    442             printf ("mpf_expr \"%s\"\n", data[i].expr);
    443 
    444           ret = mpf_expr (got, data[i].base, data[i].expr, a, b, NULL);
    445 
    446           if (data[i].want == NULL)
    447             {
    448               /* expect to fail */
    449               if (ret == MPEXPR_RESULT_OK)
    450                 {
    451                   printf ("mpf_expr wrong return value, got %d, expected failure\n", ret);
    452                   goto error;
    453                 }
    454             }
    455           else
    456             {
    457               if (mpf_set_str (want, data[i].want, 0) != 0)
    458                 {
    459                   printf ("Cannot parse wanted value string\n");
    460                   goto error;
    461                 }
    462 
    463               if (ret != MPEXPR_RESULT_OK)
    464                 {
    465                   printf ("mpf_expr failed unexpectedly\n");
    466                   printf ("   return value %d\n", ret);
    467                   goto error;
    468                 }
    469               if (mpf_cmp (got, want) != 0)
    470                 {
    471                   printf ("mpf_expr wrong result\n");
    472                   printf ("   got  "); mpf_out_str (stdout, 10, 20, got);
    473                   printf ("\n");
    474                   printf ("   want "); mpf_out_str (stdout, 10, 20, want);
    475                   printf ("\n");
    476                   goto error;
    477                 }
    478             }
    479         }
    480     }
    481   mpf_clear (a);
    482   mpf_clear (b);
    483   mpf_clear (got);
    484   mpf_clear (want);
    485   return;
    486 
    487  error:
    488   printf ("   base %d\n", data[i].base);
    489   printf ("   expr \"%s\"\n", data[i].expr);
    490   if (data[i].want != NULL)
    491     printf ("   want \"%s\"\n", data[i].want);
    492   abort ();
    493 }
    494 
    495 
    496 int
    497 main (int argc, char *argv[])
    498 {
    499   tests_start ();
    500 
    501   if (argc >= 2)
    502     option_trace = 1;
    503 
    504   check_z ();
    505   check_q ();
    506   check_f ();
    507 
    508   tests_end ();
    509   exit (0);
    510 }
    511