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