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.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
check_z(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
check_q(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
check_f(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
main(int argc,char * argv[])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