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