1/* Test expression evaluation (print nothing and exit 0 if successful).
2
3Copyright 2000-2004 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it 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
14or
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
20or both in parallel, as here.
21
22The GNU MP Library is distributed in the hope that it will be useful, but
23WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25for more details.
26
27You should have received copies of the GNU General Public License and the
28GNU Lesser General Public License along with the GNU MP Library.  If not,
29see 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
39int  option_trace = 0;
40
41
42struct 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
54struct 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
136const 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
184const struct data_t  data_zq[] = {
185  /* expecting failure */
186  { 0, "1.2", NULL },
187};
188
189const 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
195const 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
202const 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
247struct datalist_t {
248  const struct data_t  *data;
249  int                  num;
250};
251
252#define DATALIST(data)  { data, numberof (data) }
253
254struct datalist_t  list_z[] = {
255  DATALIST (data_z),
256  DATALIST (data_zq),
257  DATALIST (data_zf),
258  DATALIST (data_zqf),
259};
260
261struct datalist_t  list_q[] = {
262  DATALIST (data_q),
263  DATALIST (data_zq),
264  DATALIST (data_zqf),
265};
266
267struct datalist_t  list_f[] = {
268  DATALIST (data_zf),
269  DATALIST (data_zqf),
270  DATALIST (data_f),
271};
272
273
274void
275check_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
345void
346check_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
421void
422check_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
496int
497main (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