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