this repo has no description
at develop 118 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3/* 4 * Main authors: 5 * Guido Tack <guido.tack@monash.edu> 6 */ 7 8/* This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 11 12#include <minizinc/ast.hh> 13#include <minizinc/astexception.hh> 14#include <minizinc/astiterator.hh> 15#include <minizinc/builtins.hh> 16#include <minizinc/config.hh> 17#include <minizinc/eval_par.hh> 18#include <minizinc/file_utils.hh> 19#include <minizinc/flat_exp.hh> 20#include <minizinc/flatten_internal.hh> 21#include <minizinc/output.hh> 22#include <minizinc/prettyprinter.hh> 23#include <minizinc/support/regex.hh> 24#include <minizinc/typecheck.hh> 25 26#include <climits> 27#include <cmath> 28#include <iomanip> 29#include <random> 30#include <regex> 31 32namespace MiniZinc { 33 34void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t, 35 FunctionI::builtin_e b, bool fromGlobals = false) { 36 FunctionI* fi = m->matchFn(env, id, t, false); 37 if (fi != nullptr) { 38 fi->builtins.e = b; 39 } else if (!fromGlobals) { 40 std::ostringstream ss; 41 ss << "no definition found for builtin " << id; 42 throw InternalError(ss.str()); 43 } 44} 45void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t, 46 FunctionI::builtin_f b, bool fromGlobals = false) { 47 FunctionI* fi = m->matchFn(env, id, t, false); 48 if (fi != nullptr) { 49 fi->builtins.f = b; 50 } else if (!fromGlobals) { 51 std::ostringstream ss; 52 ss << "no definition found for builtin " << id; 53 throw InternalError(ss.str()); 54 } 55} 56void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t, 57 FunctionI::builtin_i b, bool fromGlobals = false) { 58 FunctionI* fi = m->matchFn(env, id, t, false); 59 if (fi != nullptr) { 60 fi->builtins.i = b; 61 } else if (!fromGlobals) { 62 std::ostringstream ss; 63 ss << "no definition found for builtin " << id; 64 throw InternalError(ss.str()); 65 } 66} 67void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t, 68 FunctionI::builtin_b b, bool fromGlobals = false) { 69 FunctionI* fi = m->matchFn(env, id, t, false); 70 if (fi != nullptr) { 71 fi->builtins.b = b; 72 } else if (!fromGlobals) { 73 std::ostringstream ss; 74 ss << "no definition found for builtin " << id; 75 throw InternalError(ss.str()); 76 } 77} 78void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t, 79 FunctionI::builtin_s b, bool fromGlobals = false) { 80 FunctionI* fi = m->matchFn(env, id, t, false); 81 if (fi != nullptr) { 82 fi->builtins.s = b; 83 } else if (!fromGlobals) { 84 std::ostringstream ss; 85 ss << "no definition found for builtin " << id; 86 throw InternalError(ss.str()); 87 } 88} 89void rb(EnvI& env, Model* m, const ASTString& id, const std::vector<Type>& t, 90 FunctionI::builtin_str b, bool fromGlobals = false) { 91 FunctionI* fi = m->matchFn(env, id, t, false); 92 if (fi != nullptr) { 93 fi->builtins.str = b; 94 } else if (!fromGlobals) { 95 std::ostringstream ss; 96 ss << "no definition found for builtin " << id; 97 throw InternalError(ss.str()); 98 } 99} 100 101IntVal b_int_min(EnvI& env, Call* call) { 102 switch (call->argCount()) { 103 case 1: 104 if (call->arg(0)->type().isSet()) { 105 throw EvalError(env, call->arg(0)->loc(), "sets not supported"); 106 } else { 107 GCLock lock; 108 ArrayLit* al = eval_array_lit(env, call->arg(0)); 109 if (al->size() == 0) { 110 throw ResultUndefinedError(env, al->loc(), "minimum of empty array is undefined"); 111 } 112 IntVal m = eval_int(env, (*al)[0]); 113 for (unsigned int i = 1; i < al->size(); i++) { 114 m = std::min(m, eval_int(env, (*al)[i])); 115 } 116 return m; 117 } 118 case 2: { 119 return std::min(eval_int(env, call->arg(0)), eval_int(env, call->arg(1))); 120 } 121 default: 122 throw EvalError(env, Location(), "dynamic type error"); 123 } 124} 125 126IntVal b_int_max(EnvI& env, Call* call) { 127 switch (call->argCount()) { 128 case 1: 129 if (call->arg(0)->type().isSet()) { 130 throw EvalError(env, call->arg(0)->loc(), "sets not supported"); 131 } else { 132 GCLock lock; 133 ArrayLit* al = eval_array_lit(env, call->arg(0)); 134 if (al->size() == 0) { 135 throw ResultUndefinedError(env, al->loc(), "maximum of empty array is undefined"); 136 } 137 IntVal m = eval_int(env, (*al)[0]); 138 for (unsigned int i = 1; i < al->size(); i++) { 139 m = std::max(m, eval_int(env, (*al)[i])); 140 } 141 return m; 142 } 143 case 2: { 144 return std::max(eval_int(env, call->arg(0)), eval_int(env, call->arg(1))); 145 } 146 default: 147 throw EvalError(env, Location(), "dynamic type error"); 148 } 149} 150 151IntVal b_arg_min_bool(EnvI& env, Call* call) { 152 GCLock lock; 153 ArrayLit* al = eval_array_lit(env, call->arg(0)); 154 if (al->size() == 0) { 155 throw ResultUndefinedError(env, al->loc(), "arg_min of empty array is undefined"); 156 } 157 assert(al->dims() == 1); 158 for (unsigned int i = 0; i < al->size(); i++) { 159 bool val = eval_bool(env, (*al)[i]); 160 if (!val) { 161 return IntVal(i) + al->min(0); 162 } 163 } 164 return al->min(0); 165} 166IntVal b_arg_max_bool(EnvI& env, Call* call) { 167 GCLock lock; 168 ArrayLit* al = eval_array_lit(env, call->arg(0)); 169 if (al->size() == 0) { 170 throw ResultUndefinedError(env, al->loc(), "arg_max of empty array is undefined"); 171 } 172 assert(al->dims() == 1); 173 for (unsigned int i = 0; i < al->size(); i++) { 174 bool val = eval_bool(env, (*al)[i]); 175 if (val) { 176 return IntVal(i) + al->min(0); 177 } 178 } 179 return al->min(0); 180} 181IntVal b_arg_min_int(EnvI& env, Call* call) { 182 GCLock lock; 183 ArrayLit* al = eval_array_lit(env, call->arg(0)); 184 if (al->size() == 0) { 185 throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined"); 186 } 187 assert(al->dims() == 1); 188 IntVal m = eval_int(env, (*al)[0]); 189 unsigned int m_idx = 0; 190 for (unsigned int i = 1; i < al->size(); i++) { 191 IntVal mi = eval_int(env, (*al)[i]); 192 if (mi < m) { 193 m = mi; 194 m_idx = i; 195 } 196 } 197 return IntVal(m_idx) + al->min(0); 198} 199IntVal b_arg_max_int(EnvI& env, Call* call) { 200 GCLock lock; 201 ArrayLit* al = eval_array_lit(env, call->arg(0)); 202 if (al->size() == 0) { 203 throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined"); 204 } 205 assert(al->dims() == 1); 206 IntVal m = eval_int(env, (*al)[0]); 207 unsigned int m_idx = 0; 208 for (unsigned int i = 1; i < al->size(); i++) { 209 IntVal mi = eval_int(env, (*al)[i]); 210 if (mi > m) { 211 m = mi; 212 m_idx = i; 213 } 214 } 215 return IntVal(m_idx) + al->min(0); 216} 217IntVal b_arg_min_float(EnvI& env, Call* call) { 218 GCLock lock; 219 ArrayLit* al = eval_array_lit(env, call->arg(0)); 220 if (al->size() == 0) { 221 throw ResultUndefinedError(env, al->loc(), "argmin of empty array is undefined"); 222 } 223 assert(al->dims() == 1); 224 FloatVal m = eval_float(env, (*al)[0]); 225 unsigned int m_idx = 0; 226 for (unsigned int i = 1; i < al->size(); i++) { 227 FloatVal mi = eval_float(env, (*al)[i]); 228 if (mi < m) { 229 m = mi; 230 m_idx = i; 231 } 232 } 233 return IntVal(m_idx) + al->min(0); 234} 235IntVal b_arg_max_float(EnvI& env, Call* call) { 236 GCLock lock; 237 ArrayLit* al = eval_array_lit(env, call->arg(0)); 238 if (al->size() == 0) { 239 throw ResultUndefinedError(env, al->loc(), "argmax of empty array is undefined"); 240 } 241 assert(al->dims() == 1); 242 FloatVal m = eval_float(env, (*al)[0]); 243 unsigned int m_idx = 0; 244 for (unsigned int i = 1; i < al->size(); i++) { 245 FloatVal mi = eval_float(env, (*al)[i]); 246 if (mi > m) { 247 m = mi; 248 m_idx = i; 249 } 250 } 251 return IntVal(m_idx) + al->min(0); 252} 253 254IntVal b_abs_int(EnvI& env, Call* call) { 255 assert(call->argCount() == 1); 256 return std::abs(eval_int(env, call->arg(0))); 257} 258 259FloatVal b_abs_float(EnvI& env, Call* call) { 260 assert(call->argCount() == 1); 261 return std::abs(eval_float(env, call->arg(0))); 262} 263 264bool b_has_bounds_int(EnvI& env, Call* call) { 265 if (call->argCount() != 1) { 266 throw EvalError(env, Location(), "dynamic type error"); 267 } 268 IntBounds ib = compute_int_bounds(env, call->arg(0)); 269 return ib.valid && ib.l.isFinite() && ib.u.isFinite(); 270} 271bool b_has_bounds_float(EnvI& env, Call* call) { 272 if (call->argCount() != 1) { 273 throw EvalError(env, Location(), "dynamic type error"); 274 } 275 FloatBounds fb = compute_float_bounds(env, call->arg(0)); 276 return fb.valid; 277} 278 279IntVal lb_varoptint(EnvI& env, Expression* e) { 280 IntBounds b = compute_int_bounds(env, e); 281 if (b.valid) { 282 return b.l; 283 } 284 return -IntVal::infinity(); 285} 286IntVal b_lb_varoptint(EnvI& env, Call* call) { 287 if (call->argCount() != 1) { 288 throw EvalError(env, Location(), "dynamic type error"); 289 } 290 return lb_varoptint(env, call->arg(0)); 291} 292 293bool b_occurs(EnvI& env, Call* call) { 294 GCLock lock; 295 return eval_par(env, call->arg(0)) != constants().absent; 296} 297 298IntVal b_deopt_int(EnvI& env, Call* call) { 299 GCLock lock; 300 Expression* e = eval_par(env, call->arg(0)); 301 if (e == constants().absent) { 302 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value"); 303 } 304 return eval_int(env, e); 305} 306 307bool b_deopt_bool(EnvI& env, Call* call) { 308 GCLock lock; 309 Expression* e = eval_par(env, call->arg(0)); 310 if (e == constants().absent) { 311 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value"); 312 } 313 return eval_bool(env, e); 314} 315 316FloatVal b_deopt_float(EnvI& env, Call* call) { 317 GCLock lock; 318 Expression* e = eval_par(env, call->arg(0)); 319 if (e == constants().absent) { 320 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value"); 321 } 322 return eval_float(env, e); 323} 324 325IntSetVal* b_deopt_intset(EnvI& env, Call* call) { 326 GCLock lock; 327 Expression* e = eval_par(env, call->arg(0)); 328 if (e == constants().absent) { 329 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value"); 330 } 331 return eval_intset(env, e); 332} 333 334std::string b_deopt_string(EnvI& env, Call* call) { 335 GCLock lock; 336 Expression* e = eval_par(env, call->arg(0)); 337 if (e == constants().absent) { 338 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value"); 339 } 340 return eval_string(env, e); 341} 342 343Expression* b_deopt_expr(EnvI& env, Call* call) { 344 GCLock lock; 345 Expression* e = eval_par(env, call->arg(0)); 346 if (e == constants().absent) { 347 throw EvalError(env, e->loc(), "cannot evaluate deopt on absent value"); 348 } 349 return e; 350}; 351 352IntVal b_array_lb_int(EnvI& env, Call* call) { 353 assert(call->argCount() == 1); 354 Expression* e = follow_id_to_decl(call->arg(0)); 355 356 bool foundMin = false; 357 IntVal array_lb = -IntVal::infinity(); 358 359 if (auto* vd = e->dynamicCast<VarDecl>()) { 360 if (vd->ti()->domain() != nullptr) { 361 GCLock lock; 362 IntSetVal* isv = eval_intset(env, vd->ti()->domain()); 363 if (isv->size() != 0) { 364 array_lb = isv->min(); 365 foundMin = true; 366 } 367 } 368 e = vd->e(); 369 } 370 371 if (e != nullptr) { 372 GCLock lock; 373 ArrayLit* al = eval_array_lit(env, e); 374 if (al->size() == 0) { 375 throw EvalError(env, Location(), "lower bound of empty array undefined"); 376 } 377 IntVal min = IntVal::infinity(); 378 for (unsigned int i = 0; i < al->size(); i++) { 379 IntBounds ib = compute_int_bounds(env, (*al)[i]); 380 if (!ib.valid) { 381 goto b_array_lb_int_done; 382 } 383 min = std::min(min, ib.l); 384 } 385 if (foundMin) { 386 array_lb = std::max(array_lb, min); 387 } else { 388 array_lb = min; 389 } 390 foundMin = true; 391 } 392b_array_lb_int_done: 393 if (foundMin) { 394 return array_lb; 395 } else { 396 return -IntVal::infinity(); 397 } 398} 399 400IntVal ub_varoptint(EnvI& env, Expression* e) { 401 IntBounds b = compute_int_bounds(env, e); 402 if (b.valid) { 403 return b.u; 404 } 405 return IntVal::infinity(); 406} 407IntVal b_ub_varoptint(EnvI& env, Call* call) { 408 if (call->argCount() != 1) { 409 throw EvalError(env, Location(), "dynamic type error"); 410 } 411 return ub_varoptint(env, call->arg(0)); 412} 413 414IntVal b_array_ub_int(EnvI& env, Call* call) { 415 assert(call->argCount() == 1); 416 Expression* e = follow_id_to_decl(call->arg(0)); 417 418 bool foundMax = false; 419 IntVal array_ub = IntVal::infinity(); 420 421 if (auto* vd = e->dynamicCast<VarDecl>()) { 422 if (vd->ti()->domain() != nullptr) { 423 GCLock lock; 424 IntSetVal* isv = eval_intset(env, vd->ti()->domain()); 425 if (isv->size() != 0) { 426 array_ub = isv->max(); 427 foundMax = true; 428 } 429 } 430 e = vd->e(); 431 } 432 433 if (e != nullptr) { 434 GCLock lock; 435 ArrayLit* al = eval_array_lit(env, e); 436 if (al->size() == 0) { 437 throw EvalError(env, Location(), "upper bound of empty array undefined"); 438 } 439 IntVal max = -IntVal::infinity(); 440 for (unsigned int i = 0; i < al->size(); i++) { 441 IntBounds ib = compute_int_bounds(env, (*al)[i]); 442 if (!ib.valid) { 443 goto b_array_ub_int_done; 444 } 445 max = std::max(max, ib.u); 446 } 447 if (foundMax) { 448 array_ub = std::min(array_ub, max); 449 } else { 450 array_ub = max; 451 } 452 foundMax = true; 453 } 454b_array_ub_int_done: 455 if (foundMax) { 456 return array_ub; 457 } else { 458 return IntVal::infinity(); 459 } 460} 461 462IntVal b_idiv(EnvI& env, Call* call) { 463 assert(call->argCount() == 2); 464 IntVal a = eval_int(env, call->arg(0)); 465 IntVal b = eval_int(env, call->arg(1)); 466 if (b == 0) { 467 throw ResultUndefinedError(env, call->loc(), "division by zero"); 468 } 469 return a / b; 470} 471IntVal b_mod(EnvI& env, Call* call) { 472 assert(call->argCount() == 2); 473 IntVal a = eval_int(env, call->arg(0)); 474 IntVal b = eval_int(env, call->arg(1)); 475 if (b == 0) { 476 throw ResultUndefinedError(env, call->loc(), "division by zero"); 477 } 478 return a % b; 479} 480FloatVal b_fdiv(EnvI& env, Call* call) { 481 assert(call->argCount() == 2); 482 FloatVal a = eval_float(env, call->arg(0)); 483 FloatVal b = eval_float(env, call->arg(1)); 484 if (b == 0.0) { 485 throw ResultUndefinedError(env, call->loc(), "division by zero"); 486 } 487 return a / b; 488} 489IntSetVal* b_dotdot(EnvI& env, Call* call) { 490 assert(call->argCount() == 2); 491 IntVal a = eval_int(env, call->arg(0)); 492 IntVal b = eval_int(env, call->arg(1)); 493 return IntSetVal::a(a, b); 494} 495 496IntVal b_sum_int(EnvI& env, Call* call) { 497 assert(call->argCount() == 1); 498 GCLock lock; 499 ArrayLit* al = eval_array_lit(env, call->arg(0)); 500 if (al->size() == 0) { 501 return 0; 502 } 503 IntVal m = 0; 504 for (unsigned int i = 0; i < al->size(); i++) { 505 m += eval_int(env, (*al)[i]); 506 } 507 return m; 508} 509 510IntVal b_product_int(EnvI& env, Call* call) { 511 assert(call->argCount() == 1); 512 GCLock lock; 513 ArrayLit* al = eval_array_lit(env, call->arg(0)); 514 if (al->size() == 0) { 515 return 1; 516 } 517 IntVal m = 1; 518 for (unsigned int i = 0; i < al->size(); i++) { 519 m *= eval_int(env, (*al)[i]); 520 } 521 return m; 522} 523 524FloatVal b_product_float(EnvI& env, Call* call) { 525 assert(call->argCount() == 1); 526 GCLock lock; 527 ArrayLit* al = eval_array_lit(env, call->arg(0)); 528 if (al->size() == 0) { 529 return 1; 530 } 531 FloatVal m = 1.0; 532 for (unsigned int i = 0; i < al->size(); i++) { 533 m *= eval_float(env, (*al)[i]); 534 } 535 return m; 536} 537 538FloatVal lb_varoptfloat(EnvI& env, Expression* e) { 539 FloatBounds b = compute_float_bounds(env, e); 540 if (b.valid) { 541 return b.l; 542 } 543 throw EvalError(env, e->loc(), "cannot determine bounds"); 544} 545FloatVal ub_varoptfloat(EnvI& env, Expression* e) { 546 FloatBounds b = compute_float_bounds(env, e); 547 if (b.valid) { 548 return b.u; 549 } 550 throw EvalError(env, e->loc(), "cannot determine bounds"); 551} 552 553FloatVal b_lb_varoptfloat(EnvI& env, Call* call) { 554 if (call->argCount() != 1) { 555 throw EvalError(env, Location(), "dynamic type error"); 556 } 557 return lb_varoptfloat(env, call->arg(0)); 558} 559FloatVal b_ub_varoptfloat(EnvI& env, Call* call) { 560 if (call->argCount() != 1) { 561 throw EvalError(env, Location(), "dynamic type error"); 562 } 563 return ub_varoptfloat(env, call->arg(0)); 564} 565 566FloatVal b_array_lb_float(EnvI& env, Call* call) { 567 assert(call->argCount() == 1); 568 Expression* e = follow_id_to_decl(call->arg(0)); 569 570 bool foundMin = false; 571 FloatVal array_lb = 0.0; 572 573 if (auto* vd = e->dynamicCast<VarDecl>()) { 574 if (vd->ti()->domain() != nullptr) { 575 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain()); 576 array_lb = fsv->min(); 577 foundMin = true; 578 } 579 e = vd->e(); 580 } 581 582 if (e != nullptr) { 583 GCLock lock; 584 ArrayLit* al = eval_array_lit(env, e); 585 if (al->size() == 0) { 586 throw EvalError(env, Location(), "lower bound of empty array undefined"); 587 } 588 bool min_valid = false; 589 FloatVal min = 0.0; 590 for (unsigned int i = 0; i < al->size(); i++) { 591 FloatBounds fb = compute_float_bounds(env, (*al)[i]); 592 if (!fb.valid) { 593 goto b_array_lb_float_done; 594 } 595 if (min_valid) { 596 min = std::min(min, fb.l); 597 } else { 598 min_valid = true; 599 min = fb.l; 600 } 601 } 602 assert(min_valid); 603 if (foundMin) { 604 array_lb = std::max(array_lb, min); 605 } else { 606 array_lb = min; 607 } 608 foundMin = true; 609 } 610b_array_lb_float_done: 611 if (foundMin) { 612 return array_lb; 613 } else { 614 throw EvalError(env, e->loc(), "cannot determine lower bound"); 615 } 616} 617 618FloatVal b_array_ub_float(EnvI& env, Call* call) { 619 assert(call->argCount() == 1); 620 Expression* e = follow_id_to_decl(call->arg(0)); 621 622 bool foundMax = false; 623 FloatVal array_ub = 0.0; 624 625 if (auto* vd = e->dynamicCast<VarDecl>()) { 626 if (vd->ti()->domain() != nullptr) { 627 FloatSetVal* fsv = eval_floatset(env, vd->ti()->domain()); 628 array_ub = fsv->max(); 629 foundMax = true; 630 } 631 e = vd->e(); 632 } 633 634 if (e != nullptr) { 635 GCLock lock; 636 ArrayLit* al = eval_array_lit(env, e); 637 if (al->size() == 0) { 638 throw EvalError(env, Location(), "upper bound of empty array undefined"); 639 } 640 bool max_valid = false; 641 FloatVal max = 0.0; 642 for (unsigned int i = 0; i < al->size(); i++) { 643 FloatBounds fb = compute_float_bounds(env, (*al)[i]); 644 if (!fb.valid) { 645 goto b_array_ub_float_done; 646 } 647 if (max_valid) { 648 max = std::max(max, fb.u); 649 } else { 650 max_valid = true; 651 max = fb.u; 652 } 653 } 654 assert(max_valid); 655 if (foundMax) { 656 array_ub = std::min(array_ub, max); 657 } else { 658 array_ub = max; 659 } 660 foundMax = true; 661 } 662b_array_ub_float_done: 663 if (foundMax) { 664 return array_ub; 665 } else { 666 throw EvalError(env, e->loc(), "cannot determine upper bound"); 667 } 668} 669 670FloatVal b_sum_float(EnvI& env, Call* call) { 671 assert(call->argCount() == 1); 672 GCLock lock; 673 ArrayLit* al = eval_array_lit(env, call->arg(0)); 674 if (al->size() == 0) { 675 return 0; 676 } 677 FloatVal m = 0; 678 for (unsigned int i = 0; i < al->size(); i++) { 679 m += eval_float(env, (*al)[i]); 680 } 681 return m; 682} 683 684FloatVal b_float_min(EnvI& env, Call* call) { 685 switch (call->argCount()) { 686 case 1: 687 if (call->arg(0)->type().isSet()) { 688 throw EvalError(env, call->arg(0)->loc(), "sets not supported"); 689 } else { 690 GCLock lock; 691 ArrayLit* al = eval_array_lit(env, call->arg(0)); 692 if (al->size() == 0) { 693 throw EvalError(env, al->loc(), "min on empty array undefined"); 694 } 695 FloatVal m = eval_float(env, (*al)[0]); 696 for (unsigned int i = 1; i < al->size(); i++) { 697 m = std::min(m, eval_float(env, (*al)[i])); 698 } 699 return m; 700 } 701 case 2: { 702 return std::min(eval_float(env, call->arg(0)), eval_float(env, call->arg(1))); 703 } 704 default: 705 throw EvalError(env, Location(), "dynamic type error"); 706 } 707} 708 709FloatVal b_float_max(EnvI& env, Call* call) { 710 switch (call->argCount()) { 711 case 1: 712 if (call->arg(0)->type().isSet()) { 713 throw EvalError(env, call->arg(0)->loc(), "sets not supported"); 714 } else { 715 GCLock lock; 716 ArrayLit* al = eval_array_lit(env, call->arg(0)); 717 if (al->size() == 0) { 718 throw EvalError(env, al->loc(), "max on empty array undefined"); 719 } 720 FloatVal m = eval_float(env, (*al)[0]); 721 for (unsigned int i = 1; i < al->size(); i++) { 722 m = std::max(m, eval_float(env, (*al)[i])); 723 } 724 return m; 725 } 726 case 2: { 727 return std::max(eval_float(env, call->arg(0)), eval_float(env, call->arg(1))); 728 } 729 default: 730 throw EvalError(env, Location(), "dynamic type error"); 731 } 732} 733 734IntSetVal* b_index_set(EnvI& env, Expression* e, int i) { 735 if (e->eid() != Expression::E_ID) { 736 GCLock lock; 737 ArrayLit* al = eval_array_lit(env, e); 738 if (al->dims() < i) { 739 throw EvalError(env, e->loc(), "index_set: wrong dimension"); 740 } 741 return IntSetVal::a(al->min(i - 1), al->max(i - 1)); 742 } 743 Id* id = e->cast<Id>(); 744 if (id->decl() == nullptr) { 745 throw EvalError(env, id->loc(), "undefined identifier"); 746 } 747 if ((id->decl()->ti()->ranges().size() == 1 && 748 id->decl()->ti()->ranges()[0]->domain() != nullptr && 749 id->decl()->ti()->ranges()[0]->domain()->isa<TIId>()) || 750 (static_cast<int>(id->decl()->ti()->ranges().size()) >= i && 751 (id->decl()->ti()->ranges()[i - 1]->domain() == nullptr || 752 id->decl()->ti()->ranges()[i - 1]->domain()->isa<TIId>()))) { 753 GCLock lock; 754 ArrayLit* al = eval_array_lit(env, id); 755 if (al->dims() < i) { 756 throw EvalError(env, id->loc(), "index_set: wrong dimension"); 757 } 758 return IntSetVal::a(al->min(i - 1), al->max(i - 1)); 759 } 760 if (static_cast<int>(id->decl()->ti()->ranges().size()) < i) { 761 throw EvalError(env, id->loc(), "index_set: wrong dimension"); 762 } 763 return eval_intset(env, id->decl()->ti()->ranges()[i - 1]->domain()); 764} 765bool b_index_sets_agree(EnvI& env, Call* call) { 766 if (call->argCount() != 2) { 767 throw EvalError(env, Location(), "index_sets_agree needs exactly two arguments"); 768 } 769 GCLock lock; 770 ArrayLit* al0 = eval_array_lit(env, call->arg(0)); 771 ArrayLit* al1 = eval_array_lit(env, call->arg(1)); 772 if (al0->type().dim() != al1->type().dim()) { 773 return false; 774 } 775 for (int i = 1; i <= al0->type().dim(); i++) { 776 IntSetVal* index0 = b_index_set(env, al0, i); 777 IntSetVal* index1 = b_index_set(env, al1, i); 778 if (!index0->equal(index1)) { 779 return false; 780 } 781 } 782 return true; 783} 784IntSetVal* b_index_set1(EnvI& env, Call* call) { 785 if (call->argCount() != 1) { 786 throw EvalError(env, Location(), "index_set needs exactly one argument"); 787 } 788 return b_index_set(env, call->arg(0), 1); 789} 790IntSetVal* b_index_set2(EnvI& env, Call* call) { 791 if (call->argCount() != 1) { 792 throw EvalError(env, Location(), "index_set needs exactly one argument"); 793 } 794 return b_index_set(env, call->arg(0), 2); 795} 796IntSetVal* b_index_set3(EnvI& env, Call* call) { 797 if (call->argCount() != 1) { 798 throw EvalError(env, Location(), "index_set needs exactly one argument"); 799 } 800 return b_index_set(env, call->arg(0), 3); 801} 802IntSetVal* b_index_set4(EnvI& env, Call* call) { 803 if (call->argCount() != 1) { 804 throw EvalError(env, Location(), "index_set needs exactly one argument"); 805 } 806 return b_index_set(env, call->arg(0), 4); 807} 808IntSetVal* b_index_set5(EnvI& env, Call* call) { 809 if (call->argCount() != 1) { 810 throw EvalError(env, Location(), "index_set needs exactly one argument"); 811 } 812 return b_index_set(env, call->arg(0), 5); 813} 814IntSetVal* b_index_set6(EnvI& env, Call* call) { 815 if (call->argCount() != 1) { 816 throw EvalError(env, Location(), "index_set needs exactly one argument"); 817 } 818 return b_index_set(env, call->arg(0), 6); 819} 820 821IntVal b_min_parsetint(EnvI& env, Call* call) { 822 assert(call->argCount() == 1); 823 IntSetVal* isv = eval_intset(env, call->arg(0)); 824 return isv->min(); 825} 826IntVal b_max_parsetint(EnvI& env, Call* call) { 827 assert(call->argCount() == 1); 828 IntSetVal* isv = eval_intset(env, call->arg(0)); 829 return isv->max(); 830} 831IntSetVal* b_lb_set(EnvI& env, Call* e) { 832 Expression* ee = follow_id_to_value(e->arg(0)); 833 if (ee->type().isPar()) { 834 return eval_intset(env, ee); 835 } 836 return IntSetVal::a(); 837} 838IntSetVal* b_ub_set(EnvI& env, Expression* e) { 839 IntSetVal* isv = compute_intset_bounds(env, e); 840 if (isv != nullptr) { 841 return isv; 842 } 843 throw EvalError(env, e->loc(), "cannot determine bounds of set expression"); 844} 845IntSetVal* b_ub_set(EnvI& env, Call* call) { 846 assert(call->argCount() == 1); 847 return b_ub_set(env, call->arg(0)); 848} 849bool b_has_ub_set(EnvI& env, Call* call) { 850 Expression* e = call->arg(0); 851 for (;;) { 852 switch (e->eid()) { 853 case Expression::E_SETLIT: 854 return true; 855 case Expression::E_ID: { 856 Id* id = e->cast<Id>(); 857 if (id->decl() == nullptr) { 858 throw EvalError(env, id->loc(), "undefined identifier"); 859 } 860 if (id->decl()->e() == nullptr) { 861 return id->decl()->ti()->domain() != nullptr; 862 } 863 e = id->decl()->e(); 864 865 } break; 866 default: 867 throw EvalError(env, e->loc(), "invalid argument to has_ub_set"); 868 } 869 } 870} 871 872IntSetVal* b_array_ub_set(EnvI& env, Call* call) { 873 assert(call->argCount() == 1); 874 GCLock lock; 875 ArrayLit* al = eval_array_lit(env, call->arg(0)); 876 if (al->size() == 0) { 877 throw EvalError(env, Location(), "upper bound of empty array undefined"); 878 } 879 IntSetVal* ub = b_ub_set(env, (*al)[0]); 880 for (unsigned int i = 1; i < al->size(); i++) { 881 IntSetRanges isr(ub); 882 IntSetRanges r(b_ub_set(env, (*al)[i])); 883 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r); 884 ub = IntSetVal::ai(u); 885 } 886 return ub; 887} 888 889IntSetVal* b_dom_varint(EnvI& env, Expression* e) { 890 Id* lastid = nullptr; 891 Expression* cur = e; 892 for (;;) { 893 if (cur == nullptr) { 894 if (lastid == nullptr || lastid->decl()->ti()->domain() == nullptr) { 895 IntBounds b = compute_int_bounds(env, e); 896 if (b.valid) { 897 return IntSetVal::a(b.l, b.u); 898 } 899 return IntSetVal::a(-IntVal::infinity(), IntVal::infinity()); 900 } 901 return eval_intset(env, lastid->decl()->ti()->domain()); 902 } 903 switch (cur->eid()) { 904 case Expression::E_INTLIT: { 905 IntVal v = cur->cast<IntLit>()->v(); 906 return IntSetVal::a(v, v); 907 } 908 case Expression::E_ID: { 909 lastid = cur->cast<Id>(); 910 if (lastid == constants().absent) { 911 return IntSetVal::a(-IntVal::infinity(), IntVal::infinity()); 912 } 913 if (lastid->decl() == nullptr) { 914 throw EvalError(env, lastid->loc(), "undefined identifier"); 915 } 916 cur = lastid->decl()->e(); 917 } break; 918 case Expression::E_ARRAYACCESS: { 919 bool success; 920 cur = eval_arrayaccess(env, cur->cast<ArrayAccess>(), success); 921 if (!success) { 922 cur = nullptr; 923 } 924 } break; 925 default: 926 cur = nullptr; 927 break; 928 } 929 } 930} 931IntSetVal* b_dom_varint(EnvI& env, Call* call) { 932 assert(call->argCount() == 1); 933 return b_dom_varint(env, call->arg(0)); 934} 935 936IntSetVal* b_dom_bounds_array(EnvI& env, Call* call) { 937 assert(call->argCount() == 1); 938 Expression* arg_e = call->arg(0); 939 Expression* e = follow_id_to_decl(arg_e); 940 941 bool foundBounds = false; 942 IntVal array_lb = -IntVal::infinity(); 943 IntVal array_ub = IntVal::infinity(); 944 945 if (auto* vd = e->dynamicCast<VarDecl>()) { 946 if (vd->ti()->domain() != nullptr) { 947 GCLock lock; 948 IntSetVal* isv = eval_intset(env, vd->ti()->domain()); 949 if (isv->size() != 0) { 950 array_lb = isv->min(); 951 array_ub = isv->max(); 952 foundBounds = true; 953 } 954 } 955 e = vd->e(); 956 if (e == nullptr) { 957 e = vd->flat()->e(); 958 } 959 } 960 961 if (foundBounds) { 962 return IntSetVal::a(array_lb, array_ub); 963 } 964 965 if (e != nullptr) { 966 GCLock lock; 967 ArrayLit* al = eval_array_lit(env, e); 968 if (al->size() == 0) { 969 throw EvalError(env, Location(), "lower bound of empty array undefined"); 970 } 971 IntVal min = IntVal::infinity(); 972 IntVal max = -IntVal::infinity(); 973 for (unsigned int i = 0; i < al->size(); i++) { 974 IntBounds ib = compute_int_bounds(env, (*al)[i]); 975 if (!ib.valid) { 976 goto b_array_lb_int_done; 977 } 978 min = std::min(min, ib.l); 979 max = std::max(max, ib.u); 980 } 981 array_lb = std::max(array_lb, min); 982 array_ub = std::min(array_ub, max); 983 foundBounds = true; 984 } 985b_array_lb_int_done: 986 if (foundBounds) { 987 return IntSetVal::a(array_lb, array_ub); 988 } else { 989 throw EvalError(env, e->loc(), "cannot determine lower bound"); 990 } 991} 992 993IntSetVal* b_dom_array(EnvI& env, Call* call) { 994 assert(call->argCount() == 1); 995 Expression* ae = call->arg(0); 996 ArrayLit* al = nullptr; 997 while (al == nullptr) { 998 switch (ae->eid()) { 999 case Expression::E_ARRAYLIT: 1000 al = ae->cast<ArrayLit>(); 1001 break; 1002 case Expression::E_ID: { 1003 Id* id = ae->cast<Id>(); 1004 if (id->decl() == nullptr) { 1005 throw EvalError(env, id->loc(), "undefined identifier"); 1006 } 1007 if (id->decl()->e() == nullptr) { 1008 if (id->decl()->flat() == nullptr) { 1009 throw EvalError(env, id->loc(), "array without initialiser"); 1010 } 1011 if (id->decl()->flat()->e() == nullptr) { 1012 throw EvalError(env, id->loc(), "array without initialiser"); 1013 } 1014 ae = id->decl()->flat()->e(); 1015 1016 } else { 1017 ae = id->decl()->e(); 1018 } 1019 } break; 1020 default: 1021 throw EvalError(env, ae->loc(), "invalid argument to dom"); 1022 } 1023 } 1024 if (al->size() == 0) { 1025 return IntSetVal::a(); 1026 } 1027 IntSetVal* isv = b_dom_varint(env, (*al)[0]); 1028 for (unsigned int i = 1; i < al->size(); i++) { 1029 IntSetRanges isr(isv); 1030 IntSetRanges r(b_dom_varint(env, (*al)[i])); 1031 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r); 1032 isv = IntSetVal::ai(u); 1033 } 1034 return isv; 1035} 1036IntSetVal* b_compute_div_bounds(EnvI& env, Call* call) { 1037 assert(call->argCount() == 2); 1038 IntBounds bx = compute_int_bounds(env, call->arg(0)); 1039 if (!bx.valid) { 1040 throw EvalError(env, call->arg(0)->loc(), "cannot determine bounds"); 1041 } 1042 /// TODO: better bounds if only some input bounds are infinite 1043 if (!bx.l.isFinite() || !bx.u.isFinite()) { 1044 return constants().infinity->isv(); 1045 } 1046 IntBounds by = compute_int_bounds(env, call->arg(1)); 1047 if (!by.valid) { 1048 throw EvalError(env, call->arg(1)->loc(), "cannot determine bounds"); 1049 } 1050 if (!by.l.isFinite() || !by.u.isFinite()) { 1051 return constants().infinity->isv(); 1052 } 1053 Ranges::Const<IntVal> byr(by.l, by.u); 1054 Ranges::Const<IntVal> by0(0, 0); 1055 Ranges::Diff<IntVal, Ranges::Const<IntVal>, Ranges::Const<IntVal>> byr0(byr, by0); 1056 1057 IntVal min = IntVal::maxint(); 1058 IntVal max = IntVal::minint(); 1059 if (byr0()) { 1060 min = std::min(min, bx.l / byr0.min()); 1061 min = std::min(min, bx.l / byr0.max()); 1062 min = std::min(min, bx.u / byr0.min()); 1063 min = std::min(min, bx.u / byr0.max()); 1064 max = std::max(max, bx.l / byr0.min()); 1065 max = std::max(max, bx.l / byr0.max()); 1066 max = std::max(max, bx.u / byr0.min()); 1067 max = std::max(max, bx.u / byr0.max()); 1068 ++byr0; 1069 if (byr0()) { 1070 min = std::min(min, bx.l / byr0.min()); 1071 min = std::min(min, bx.l / byr0.max()); 1072 min = std::min(min, bx.u / byr0.min()); 1073 min = std::min(min, bx.u / byr0.max()); 1074 max = std::max(max, bx.l / byr0.min()); 1075 max = std::max(max, bx.l / byr0.max()); 1076 max = std::max(max, bx.u / byr0.min()); 1077 max = std::max(max, bx.u / byr0.max()); 1078 } 1079 } 1080 return IntSetVal::a(min, max); 1081} 1082 1083// NOLINTNEXTLINE(readability-identifier-naming) 1084ArrayLit* b_arrayXd(EnvI& env, Call* call, int d) { 1085 GCLock lock; 1086 bool check_form = call->ann().contains(constants().ann.array_check_form); 1087 ArrayLit* al = eval_array_lit(env, call->arg(d)); 1088 std::vector<std::pair<int, int>> dims(d); 1089 unsigned int dim1d = 1; 1090 1091 if (check_form && d != al->dims()) { 1092 std::ostringstream ss; 1093 ss << "number of dimensions of original array (" << al->dims() 1094 << ") does not match the given number of index sets (" << d << ")"; 1095 throw EvalError(env, call->loc(), ss.str()); 1096 } 1097 1098 for (int i = 0; i < d; i++) { 1099 IntSetVal* di = eval_intset(env, call->arg(i)); 1100 if (di->size() == 0) { 1101 dims[i] = std::pair<int, int>(1, 0); 1102 dim1d = 0; 1103 } else if (di->size() != 1) { 1104 throw EvalError(env, call->arg(i)->loc(), "arrayXd only defined for ranges"); 1105 } else { 1106 dims[i] = std::pair<int, int>(static_cast<int>(di->min(0).toInt()), 1107 static_cast<int>(di->max(0).toInt())); 1108 dim1d *= dims[i].second - dims[i].first + 1; 1109 if (check_form && dims[i].second - dims[i].first != al->max(i) - al->min(i)) { 1110 std::ostringstream ss; 1111 ss << "index set " << i + 1 << " (" << dims[i].first << ".." << dims[i].second 1112 << ") does not match index set " << i + 1 << " of original array (" << al->min(i) << ".." 1113 << al->max(i) << ")"; 1114 throw EvalError(env, call->arg(i)->loc(), ss.str()); 1115 } 1116 } 1117 } 1118 if (dim1d != al->size()) { 1119 throw EvalError(env, al->loc(), "mismatch in array dimensions"); 1120 } 1121 auto* ret = new ArrayLit(al->loc(), *al, dims); 1122 Type t = al->type(); 1123 t.dim(d); 1124 ret->type(t); 1125 ret->flat(al->flat()); 1126 return ret; 1127} 1128Expression* b_array1d_list(EnvI& env, Call* call) { 1129 GCLock lock; 1130 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1131 if (al->dims() == 1 && al->min(0) == 1) { 1132 return call->arg(0)->isa<Id>() ? call->arg(0) : al; 1133 } 1134 auto* ret = new ArrayLit(al->loc(), *al); 1135 Type t = al->type(); 1136 t.dim(1); 1137 ret->type(t); 1138 ret->flat(al->flat()); 1139 return ret; 1140} 1141Expression* b_array1d(EnvI& env, Call* call) { return b_arrayXd(env, call, 1); } 1142Expression* b_array2d(EnvI& env, Call* call) { return b_arrayXd(env, call, 2); } 1143Expression* b_array3d(EnvI& env, Call* call) { return b_arrayXd(env, call, 3); } 1144Expression* b_array4d(EnvI& env, Call* call) { return b_arrayXd(env, call, 4); } 1145Expression* b_array5d(EnvI& env, Call* call) { return b_arrayXd(env, call, 5); } 1146Expression* b_array6d(EnvI& env, Call* call) { return b_arrayXd(env, call, 6); } 1147 1148// NOLINTNEXTLINE(readability-identifier-naming) 1149Expression* b_arrayXd(EnvI& env, Call* call) { 1150 GCLock lock; 1151 ArrayLit* al0 = eval_array_lit(env, call->arg(0)); 1152 ArrayLit* al1 = eval_array_lit(env, call->arg(1)); 1153 if (al0->dims() == al1->dims()) { 1154 bool sameDims = true; 1155 for (unsigned int i = al0->dims(); (i--) != 0U;) { 1156 if (al0->min(i) != al1->min(i) || al0->max(i) != al1->max(i)) { 1157 sameDims = false; 1158 break; 1159 } 1160 } 1161 if (sameDims) { 1162 return call->arg(1)->isa<Id>() ? call->arg(1) : al1; 1163 } 1164 } 1165 std::vector<std::pair<int, int>> dims(al0->dims()); 1166 for (unsigned int i = al0->dims(); (i--) != 0U;) { 1167 dims[i] = std::make_pair(al0->min(i), al0->max(i)); 1168 } 1169 auto* ret = new ArrayLit(al1->loc(), *al1, dims); 1170 Type t = al1->type(); 1171 t.dim(static_cast<int>(dims.size())); 1172 ret->type(t); 1173 ret->flat(al1->flat()); 1174 return ret; 1175} 1176 1177IntVal b_length(EnvI& env, Call* call) { 1178 GCLock lock; 1179 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1180 return al->size(); 1181} 1182 1183IntVal b_bool2int(EnvI& env, Call* call) { return eval_bool(env, call->arg(0)) ? 1 : 0; } 1184 1185bool b_forall_par(EnvI& env, Call* call) { 1186 if (call->argCount() != 1) { 1187 throw EvalError(env, Location(), "forall needs exactly one argument"); 1188 } 1189 GCLock lock; 1190 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1191 for (unsigned int i = al->size(); (i--) != 0U;) { 1192 if (!eval_bool(env, (*al)[i])) { 1193 return false; 1194 } 1195 } 1196 return true; 1197} 1198bool b_exists_par(EnvI& env, Call* call) { 1199 if (call->argCount() != 1) { 1200 throw EvalError(env, Location(), "exists needs exactly one argument"); 1201 } 1202 GCLock lock; 1203 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1204 for (unsigned int i = al->size(); (i--) != 0U;) { 1205 if (eval_bool(env, (*al)[i])) { 1206 return true; 1207 } 1208 } 1209 return false; 1210} 1211bool b_clause_par(EnvI& env, Call* call) { 1212 if (call->argCount() != 2) { 1213 throw EvalError(env, Location(), "clause needs exactly two arguments"); 1214 } 1215 GCLock lock; 1216 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1217 for (unsigned int i = al->size(); (i--) != 0U;) { 1218 if (eval_bool(env, (*al)[i])) { 1219 return true; 1220 } 1221 } 1222 al = eval_array_lit(env, call->arg(1)); 1223 for (unsigned int i = al->size(); (i--) != 0U;) { 1224 if (!eval_bool(env, (*al)[i])) { 1225 return true; 1226 } 1227 } 1228 return false; 1229} 1230bool b_xorall_par(EnvI& env, Call* call) { 1231 if (call->argCount() != 1) { 1232 throw EvalError(env, Location(), "xorall needs exactly one argument"); 1233 } 1234 GCLock lock; 1235 int count = 0; 1236 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1237 for (unsigned int i = al->size(); (i--) != 0U;) { 1238 count += static_cast<int>(eval_bool(env, (*al)[i])); 1239 } 1240 return count % 2 == 1; 1241} 1242bool b_iffall_par(EnvI& env, Call* call) { 1243 if (call->argCount() != 1) { 1244 throw EvalError(env, Location(), "xorall needs exactly one argument"); 1245 } 1246 GCLock lock; 1247 int count = 0; 1248 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1249 for (unsigned int i = al->size(); (i--) != 0U;) { 1250 count += static_cast<int>(eval_bool(env, (*al)[i])); 1251 } 1252 return count % 2 == 0; 1253} 1254bool b_not_par(EnvI& env, Call* call) { 1255 assert(call->argCount() == 1); 1256 return !eval_bool(env, call->arg(0)); 1257} 1258 1259IntVal b_card(EnvI& env, Call* call) { 1260 if (call->argCount() != 1) { 1261 throw EvalError(env, Location(), "card needs exactly one argument"); 1262 } 1263 IntSetVal* isv = eval_intset(env, call->arg(0)); 1264 IntSetRanges isr(isv); 1265 return Ranges::cardinality(isr); 1266} 1267 1268Expression* exp_is_fixed(EnvI& env, Expression* e) { 1269 GCLock lock; 1270 Expression* cur = e; 1271 for (;;) { 1272 if (cur == nullptr) { 1273 return nullptr; 1274 } 1275 if (cur->type().isPar()) { 1276 return eval_par(env, cur); 1277 } 1278 switch (cur->eid()) { 1279 case Expression::E_ID: 1280 cur = cur->cast<Id>()->decl(); 1281 break; 1282 case Expression::E_VARDECL: 1283 if (cur->type().st() != Type::ST_SET) { 1284 Expression* dom = cur->cast<VarDecl>()->ti()->domain(); 1285 if ((dom != nullptr) && 1286 (dom->isa<IntLit>() || dom->isa<BoolLit>() || dom->isa<FloatLit>())) { 1287 return dom; 1288 } 1289 if ((dom != nullptr) && dom->isa<SetLit>()) { 1290 auto* sl = dom->cast<SetLit>(); 1291 auto* isv = sl->isv(); 1292 if ((isv != nullptr) && isv->min() == isv->max()) { 1293 return IntLit::a(isv->min()); 1294 } 1295 auto* fsv = sl->fsv(); 1296 if ((fsv != nullptr) && fsv->min() == fsv->max()) { 1297 return FloatLit::a(fsv->min()); 1298 } 1299 } 1300 } 1301 cur = cur->cast<VarDecl>()->e(); 1302 break; 1303 default: 1304 return nullptr; 1305 } 1306 } 1307} 1308 1309bool b_is_fixed(EnvI& env, Call* call) { 1310 assert(call->argCount() == 1); 1311 return exp_is_fixed(env, call->arg(0)) != nullptr; 1312} 1313 1314bool b_is_fixed_array(EnvI& env, Call* call) { 1315 assert(call->argCount() == 1); 1316 GCLock lock; 1317 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1318 if (al->size() == 0) { 1319 return true; 1320 } 1321 for (unsigned int i = 0; i < al->size(); i++) { 1322 if (exp_is_fixed(env, (*al)[i]) == nullptr) { 1323 return false; 1324 } 1325 } 1326 return true; 1327} 1328 1329bool b_is_same(EnvI& env, Call* call) { 1330 assert(call->argCount() == 2); 1331 return follow_id_to_decl(call->arg(0)) == follow_id_to_decl(call->arg(1)); 1332} 1333 1334Expression* b_fix(EnvI& env, Call* call) { 1335 assert(call->argCount() == 1); 1336 Expression* ret = exp_is_fixed(env, call->arg(0)); 1337 if (ret == nullptr) { 1338 throw EvalError(env, call->arg(0)->loc(), "expression is not fixed"); 1339 } 1340 return ret; 1341} 1342 1343IntVal b_fix_int(EnvI& env, Call* call) { return eval_int(env, b_fix(env, call)); } 1344bool b_fix_bool(EnvI& env, Call* call) { return eval_bool(env, b_fix(env, call)); } 1345FloatVal b_fix_float(EnvI& env, Call* call) { return eval_float(env, b_fix(env, call)); } 1346IntSetVal* b_fix_set(EnvI& env, Call* call) { return eval_intset(env, b_fix(env, call)); } 1347 1348Expression* b_fix_array(EnvI& env, Call* call) { 1349 assert(call->argCount() == 1); 1350 GCLock lock; 1351 ArrayLit* al = eval_array_lit(env, call->arg(0)); 1352 std::vector<Expression*> fixed(al->size()); 1353 for (unsigned int i = 0; i < fixed.size(); i++) { 1354 fixed[i] = exp_is_fixed(env, (*al)[i]); 1355 if (fixed[i] == nullptr) { 1356 throw EvalError(env, (*al)[i]->loc(), "expression is not fixed"); 1357 } 1358 } 1359 auto* ret = new ArrayLit(Location(), fixed); 1360 Type tt = al->type(); 1361 tt.ti(Type::TI_PAR); 1362 ret->type(tt); 1363 return ret; 1364} 1365 1366bool b_has_ann(EnvI& env, Call* call) { 1367 assert(call->argCount() == 2); 1368 Expression* expr = call->arg(0); 1369 if (!expr->isa<Id>()) { 1370 // Argument is a literal, unable to verify annotations 1371 return false; 1372 } 1373 expr = follow_id_to_decl(expr); 1374 Expression* ann = call->arg(1); 1375 if (ann->isa<Id>()) { 1376 return expr->ann().contains(ann); 1377 } 1378 auto* key = ann->cast<Call>(); 1379 if (Call* c = expr->ann().getCall(key->id())) { 1380 if (c->argCount() != key->argCount()) { 1381 return false; 1382 } 1383 for (int i = 0; i < c->argCount(); ++i) { 1384 if (c->arg(i)->type() != key->arg(i)->type()) { 1385 return false; 1386 } 1387 if (c->arg(i)->type().isPar()) { 1388 GCLock lock; 1389 Expression* check_eq = new BinOp(Location().introduce(), c->arg(i), BOT_EQ, key->arg(i)); 1390 check_eq->type(Type::parbool()); 1391 if (!eval_bool(env, check_eq)) { 1392 return false; 1393 } 1394 } else { 1395 if (c->arg(i)->isa<Id>() && key->arg(i)->isa<Id>()) { 1396 if (follow_id_to_decl(c->arg(i)) != follow_id_to_decl(key->arg(i))) { 1397 return false; 1398 } 1399 } else { 1400 throw EvalError(env, call->loc(), "Unable to determine equality of variable expressions"); 1401 } 1402 } 1403 } 1404 return true; 1405 } 1406 return false; 1407} 1408 1409bool b_annotate(EnvI& env, Call* call) { 1410 assert(call->argCount() == 2); 1411 Expression* expr = call->arg(0); 1412 if (!expr->isa<Id>()) { 1413 // Argument is a literal, unable to annotate 1414 std::ostringstream ss; 1415 ss << "Unable to annotate literal expression `" << *expr << "'."; 1416 env.addWarning(ss.str()); 1417 return true; 1418 } 1419 auto* var_decl = follow_id_to_decl(expr)->cast<VarDecl>(); 1420 // Add annotation 1421 Expression* ann = call->arg(1); 1422 var_decl->ann().add(ann); 1423 // Increase usage count of the annotation 1424 if (auto* ann_decl = follow_id_to_decl(ann)->dynamicCast<VarDecl>()) { 1425 auto var_it = env.varOccurrences.idx.find(var_decl->id()); 1426 assert(var_it != env.varOccurrences.idx.end()); 1427 env.varOccurrences.add(ann_decl, (*env.flat())[var_it->second]); 1428 } 1429 return true; 1430} 1431 1432FloatVal b_int2float(EnvI& env, Call* call) { return eval_int(env, call->arg(0)); } 1433IntVal b_ceil(EnvI& env, Call* call) { 1434 return static_cast<IntVal>(std::ceil(eval_float(env, call->arg(0)))); 1435} 1436IntVal b_floor(EnvI& env, Call* call) { 1437 return static_cast<IntVal>(std::floor(eval_float(env, call->arg(0)))); 1438} 1439IntVal b_round(EnvI& env, Call* call) { 1440 /// Cast to int truncates, so cannot just add 0.5 and cast 1441 return {static_cast<long long>(std::round(eval_float(env, call->arg(0)).toDouble()))}; 1442} 1443FloatVal b_log10(EnvI& env, Call* call) { 1444 return std::log10(eval_float(env, call->arg(0)).toDouble()); 1445} 1446FloatVal b_log2(EnvI& env, Call* call) { 1447 return std::log(eval_float(env, call->arg(0)).toDouble()) / std::log(2.0); 1448} 1449FloatVal b_ln(EnvI& env, Call* call) { return std::log(eval_float(env, call->arg(0)).toDouble()); } 1450FloatVal b_log(EnvI& env, Call* call) { 1451 return std::log(eval_float(env, call->arg(1)).toDouble()) / 1452 std::log(eval_float(env, call->arg(0)).toDouble()); 1453} 1454FloatVal b_exp(EnvI& env, Call* call) { return std::exp(eval_float(env, call->arg(0)).toDouble()); } 1455FloatVal b_pow(EnvI& env, Call* call) { 1456 return std::pow(eval_float(env, call->arg(0)).toDouble(), 1457 eval_float(env, call->arg(1)).toDouble()); 1458} 1459IntVal b_pow_int(EnvI& env, Call* call) { 1460 IntVal p = eval_int(env, call->arg(0)); 1461 IntVal r = 1; 1462 long long int e = eval_int(env, call->arg(1)).toInt(); 1463 if (e < 0) { 1464 throw EvalError(env, call->arg(1)->loc(), "Cannot raise integer to a negative power"); 1465 } 1466 for (long long int i = e; (i--) != 0;) { 1467 r = r * p; 1468 } 1469 return r; 1470} 1471FloatVal b_sqrt(EnvI& env, Call* call) { 1472 return std::sqrt(eval_float(env, call->arg(0)).toDouble()); 1473} 1474 1475bool b_assert_bool(EnvI& env, Call* call) { 1476 assert(call->argCount() == 2); 1477 GCLock lock; 1478 Expression* cond_e; 1479 if (call->arg(0)->type().cv()) { 1480 Ctx ctx; 1481 ctx.b = C_MIX; 1482 cond_e = flat_cv_exp(env, ctx, call->arg(0))(); 1483 } else { 1484 cond_e = call->arg(0); 1485 } 1486 if (eval_bool(env, cond_e)) { 1487 return true; 1488 } 1489 Expression* msg_e; 1490 if (call->arg(1)->type().cv()) { 1491 msg_e = flat_cv_exp(env, Ctx(), call->arg(1))(); 1492 } else { 1493 msg_e = call->arg(1); 1494 } 1495 std::ostringstream ss; 1496 ss << "Assertion failed: " << eval_string(env, msg_e); 1497 throw EvalError(env, call->arg(0)->loc(), ss.str()); 1498} 1499 1500Expression* b_assert(EnvI& env, Call* call) { 1501 assert(call->argCount() == 3); 1502 GCLock lock; 1503 Expression* cond_e; 1504 if (call->arg(0)->type().cv()) { 1505 Ctx ctx; 1506 ctx.b = C_MIX; 1507 cond_e = flat_cv_exp(env, ctx, call->arg(0))(); 1508 } else { 1509 cond_e = call->arg(0); 1510 } 1511 if (eval_bool(env, cond_e)) { 1512 return call->arg(2); 1513 } 1514 Expression* msg_e; 1515 if (call->arg(1)->type().cv()) { 1516 msg_e = flat_cv_exp(env, Ctx(), call->arg(1))(); 1517 } else { 1518 msg_e = call->arg(1); 1519 } 1520 std::ostringstream ss; 1521 ss << "Assertion failed: " << eval_string(env, msg_e); 1522 throw EvalError(env, call->arg(0)->loc(), ss.str()); 1523} 1524 1525Expression* b_mzn_deprecate(EnvI& env, Call* call) { 1526 assert(call->argCount() == 4); 1527 GCLock lock; 1528 std::string fnName = eval_string(env, call->arg(0)); 1529 if (env.deprecationWarnings.find(fnName) == env.deprecationWarnings.end()) { 1530 env.deprecationWarnings.insert(fnName); 1531 env.dumpStack(env.errstream, false); 1532 env.errstream << " The function/predicate `" << fnName; 1533 env.errstream << "' was deprecated in MiniZinc version " << eval_string(env, call->arg(1)); 1534 env.errstream << ".\n More information can be found at " << eval_string(env, call->arg(2)) 1535 << ".\n"; 1536 } 1537 return call->arg(3); 1538} 1539 1540bool b_abort(EnvI& env, Call* call) { 1541 GCLock lock; 1542 Expression* msg_e; 1543 if (call->arg(0)->type().cv()) { 1544 msg_e = flat_cv_exp(env, Ctx(), call->arg(0))(); 1545 } else { 1546 msg_e = call->arg(0); 1547 } 1548 std::ostringstream ss; 1549 ss << "Abort: " << eval_string(env, msg_e); 1550 throw EvalError(env, call->arg(0)->loc(), ss.str()); 1551} 1552 1553Expression* b_mzn_symmetry_breaking_constraint(EnvI& env, Call* call) { 1554 GCLock lock; 1555 Call* check = new Call(Location().introduce(), 1556 ASTString("mzn_check_ignore_symmetry_breaking_constraints"), {}); 1557 check->type(Type::parbool()); 1558 check->decl(env.model->matchFn(env, check, false, true)); 1559 if (eval_bool(env, check)) { 1560 return constants().literalTrue; 1561 } 1562 Call* nc = new Call(call->loc(), ASTString("symmetry_breaking_constraint"), {call->arg(0)}); 1563 nc->type(Type::varbool()); 1564 nc->decl(env.model->matchFn(env, nc, false, true)); 1565 return nc; 1566} 1567 1568Expression* b_mzn_redundant_constraint(EnvI& env, Call* call) { 1569 GCLock lock; 1570 Call* check = 1571 new Call(Location().introduce(), ASTString("mzn_check_ignore_redundant_constraints"), {}); 1572 check->type(Type::parbool()); 1573 check->decl(env.model->matchFn(env, check, false, true)); 1574 if (eval_bool(env, check)) { 1575 return constants().literalTrue; 1576 } 1577 Call* nc = new Call(call->loc(), ASTString("redundant_constraint"), {call->arg(0)}); 1578 nc->type(Type::varbool()); 1579 nc->decl(env.model->matchFn(env, nc, false, true)); 1580 return nc; 1581} 1582 1583Expression* b_trace(EnvI& env, Call* call) { 1584 GCLock lock; 1585 Expression* msg_e; 1586 if (call->arg(0)->type().cv()) { 1587 msg_e = flat_cv_exp(env, Ctx(), call->arg(0))(); 1588 } else { 1589 msg_e = call->arg(0); 1590 } 1591 env.errstream << eval_string(env, msg_e); 1592 return call->argCount() == 1 ? constants().literalTrue : call->arg(1); 1593} 1594 1595Expression* b_trace_stdout(EnvI& env, Call* call) { 1596 GCLock lock; 1597 Expression* msg_e; 1598 if (call->arg(0)->type().cv()) { 1599 msg_e = flat_cv_exp(env, Ctx(), call->arg(0))(); 1600 } else { 1601 msg_e = call->arg(0); 1602 } 1603 env.errstream << eval_string(env, msg_e); 1604 return call->argCount() == 1 ? constants().literalTrue : call->arg(1); 1605} 1606 1607Expression* b_trace_logstream(EnvI& env, Call* call) { 1608 GCLock lock; 1609 StringLit* msg; 1610 if (call->arg(0)->type().cv()) { 1611 msg = flat_cv_exp(env, Ctx(), call->arg(0))()->cast<StringLit>(); 1612 } else { 1613 msg = eval_par(env, call->arg(0))->cast<StringLit>(); 1614 } 1615 env.logstream << msg->v(); 1616 return call->argCount() == 1 ? constants().literalTrue : call->arg(1); 1617} 1618std::string b_logstream(EnvI& env, Call* call) { return env.logstream.str(); } 1619 1620bool b_in_redundant_constraint(EnvI& env, Call* /*call*/) { return env.inRedundantConstraint > 0; } 1621 1622Expression* b_set2array(EnvI& env, Call* call) { 1623 assert(call->argCount() == 1); 1624 GCLock lock; 1625 IntSetVal* isv = eval_intset(env, call->arg(0)); 1626 std::vector<Expression*> elems; 1627 IntSetRanges isr(isv); 1628 for (Ranges::ToValues<IntSetRanges> isr_v(isr); isr_v(); ++isr_v) { 1629 elems.push_back(IntLit::a(isr_v.val())); 1630 } 1631 auto* al = new ArrayLit(call->arg(0)->loc(), elems); 1632 al->type(Type::parint(1)); 1633 return al; 1634} 1635 1636IntVal b_string_length(EnvI& env, Call* call) { 1637 GCLock lock; 1638 std::string s = eval_string(env, call->arg(0)); 1639 return s.size(); 1640} 1641 1642std::string show(EnvI& env, Expression* exp) { 1643 std::ostringstream oss; 1644 GCLock lock; 1645 Printer p(oss, 0, false); 1646 Expression* e = follow_id_to_decl(exp); 1647 if (auto* vd = e->dynamicCast<VarDecl>()) { 1648 if ((vd->e() != nullptr) && !vd->e()->isa<Call>()) { 1649 e = vd->e(); 1650 } else { 1651 e = vd->id(); 1652 } 1653 } 1654 if (e->type().isPar()) { 1655 e = eval_par(env, e); 1656 } 1657 if (e->type().dim() > 0) { 1658 e = eval_array_lit(env, e); 1659 } 1660 if (auto* al = e->dynamicCast<ArrayLit>()) { 1661 oss << "["; 1662 for (unsigned int i = 0; i < al->size(); i++) { 1663 p.print((*al)[i]); 1664 if (i < al->size() - 1) { 1665 oss << ", "; 1666 } 1667 } 1668 oss << "]"; 1669 } else { 1670 p.print(e); 1671 } 1672 return oss.str(); 1673} 1674std::string b_show(EnvI& env, Call* call) { return show(env, call->arg(0)); } 1675std::string b_show_dzn_id(EnvI& env, Call* call) { 1676 GCLock lock; 1677 std::string s = eval_string(env, call->arg(0)); 1678 size_t nonIdChar = 1679 s.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"); 1680 size_t nonIdBegin = s.find_first_of("0123456789_"); 1681 if (nonIdChar != std::string::npos || nonIdBegin == 0) { 1682 s = "'" + s + "'"; 1683 } 1684 return s; 1685} 1686 1687std::string b_show_json_basic(EnvI& env, Expression* e) { 1688 std::ostringstream oss; 1689 Printer p(oss, 0, false); 1690 if (auto* sl = e->dynamicCast<SetLit>()) { 1691 oss << "{ \"set\" : ["; 1692 if (IntSetVal* isv = sl->isv()) { 1693 bool first = true; 1694 for (IntSetRanges isr(isv); isr(); ++isr) { 1695 if (first) { 1696 first = false; 1697 } else { 1698 oss << ","; 1699 } 1700 if (isr.min() == isr.max()) { 1701 oss << isr.min(); 1702 } else { 1703 oss << "[" << isr.min() << "," << isr.max() << "]"; 1704 } 1705 } 1706 } else if (FloatSetVal* fsv = sl->fsv()) { 1707 bool first = true; 1708 for (FloatSetRanges fsr(fsv); fsr(); ++fsr) { 1709 if (first) { 1710 first = false; 1711 } else { 1712 oss << ","; 1713 } 1714 if (fsr.min() == fsr.max()) { 1715 pp_floatval(oss, fsr.min()); 1716 } else { 1717 oss << "["; 1718 pp_floatval(oss, fsr.min()); 1719 oss << ","; 1720 pp_floatval(oss, fsr.max()); 1721 oss << "]"; 1722 } 1723 } 1724 } else { 1725 for (unsigned int i = 0; i < sl->v().size(); i++) { 1726 p.print(sl->v()[i]); 1727 if (i < sl->v().size() - 1) { 1728 oss << ","; 1729 } 1730 } 1731 } 1732 oss << "]}"; 1733 } else if (e == constants().absent) { 1734 oss << "null"; 1735 } else { 1736 p.print(e); 1737 } 1738 return oss.str(); 1739} 1740 1741std::string b_show_json(EnvI& env, Call* call) { 1742 Expression* exp = call->arg(0); 1743 GCLock lock; 1744 Expression* e = eval_par(env, exp); 1745 if (e->type().isvar()) { 1746 std::ostringstream oss; 1747 Printer p(oss, 0, false); 1748 p.print(e); 1749 return oss.str(); 1750 } 1751 if (auto* al = e->dynamicCast<ArrayLit>()) { 1752 std::vector<unsigned int> dims(al->dims() - 1); 1753 if (!dims.empty()) { 1754 dims[0] = al->max(al->dims() - 1) - al->min(al->dims() - 1) + 1; 1755 } 1756 1757 for (int i = 1; i < al->dims() - 1; i++) { 1758 dims[i] = dims[i - 1] * (al->max(al->dims() - 1 - i) - al->min(al->dims() - 1 - i) + 1); 1759 } 1760 1761 std::ostringstream oss; 1762 oss << "["; 1763 for (unsigned int i = 0; i < al->size(); i++) { 1764 for (unsigned int dim : dims) { 1765 if (i % dim == 0) { 1766 oss << "["; 1767 } 1768 } 1769 oss << b_show_json_basic(env, (*al)[i]); 1770 for (unsigned int dim : dims) { 1771 if (i % dim == dim - 1) { 1772 oss << "]"; 1773 } 1774 } 1775 1776 if (i < al->size() - 1) { 1777 oss << ", "; 1778 } 1779 } 1780 oss << "]"; 1781 1782 return oss.str(); 1783 } 1784 return b_show_json_basic(env, e); 1785} 1786 1787Expression* b_output_json(EnvI& env, Call* call) { 1788 return create__json_output(env, false, false, false); 1789} 1790Expression* b_output_json_parameters(EnvI& env, Call* call) { 1791 std::vector<Expression*> outputVars; 1792 outputVars.push_back(new StringLit(Location().introduce(), "{\n")); 1793 1794 class JSONParVisitor : public ItemVisitor { 1795 protected: 1796 EnvI& _e; 1797 std::vector<Expression*>& _outputVars; 1798 bool _firstVar; 1799 1800 public: 1801 JSONParVisitor(EnvI& e, std::vector<Expression*>& outputVars) 1802 : _e(e), _outputVars(outputVars), _firstVar(true) {} 1803 void vVarDeclI(VarDeclI* vdi) { 1804 VarDecl* vd = vdi->e(); 1805 if (vd->ann().contains(constants().ann.rhs_from_assignment)) { 1806 std::ostringstream s; 1807 if (_firstVar) { 1808 _firstVar = false; 1809 } else { 1810 s << ",\n"; 1811 } 1812 s << " \"" << vd->id()->str() << "\"" 1813 << " : "; 1814 auto* sl = new StringLit(Location().introduce(), s.str()); 1815 _outputVars.push_back(sl); 1816 1817 std::vector<Expression*> showArgs(1); 1818 showArgs[0] = vd->id(); 1819 Call* show = new Call(Location().introduce(), "showJSON", showArgs); 1820 show->type(Type::parstring()); 1821 FunctionI* fi = _e.model->matchFn(_e, show, false); 1822 assert(fi); 1823 show->decl(fi); 1824 _outputVars.push_back(show); 1825 } 1826 } 1827 } jsonov(env, outputVars); 1828 1829 iter_items(jsonov, env.model); 1830 outputVars.push_back(new StringLit(Location().introduce(), "\n}\n")); 1831 return new ArrayLit(Location().introduce(), outputVars); 1832} 1833 1834std::string b_format(EnvI& env, Call* call) { 1835 int width = 0; 1836 int prec = -1; 1837 GCLock lock; 1838 Expression* e; 1839 if (call->argCount() > 1) { 1840 width = static_cast<int>(eval_int(env, call->arg(0)).toInt()); 1841 if (call->argCount() == 2) { 1842 e = eval_par(env, call->arg(1)); 1843 } else { 1844 assert(call->argCount() == 3); 1845 prec = static_cast<int>(eval_int(env, call->arg(1)).toInt()); 1846 if (prec < 0) { 1847 throw EvalError(env, call->arg(1)->loc(), "output precision cannot be negative"); 1848 } 1849 e = eval_par(env, call->arg(2)); 1850 } 1851 } else { 1852 e = eval_par(env, call->arg(0)); 1853 } 1854 if (e->type() == Type::parint()) { 1855 long long int i = eval_int(env, e).toInt(); 1856 std::ostringstream formatted; 1857 if (width > 0) { 1858 formatted.width(width); 1859 } else if (width < 0) { 1860 formatted.width(-width); 1861 formatted.flags(std::ios::left); 1862 } 1863 if (prec != -1) { 1864 formatted.precision(prec); 1865 } 1866 formatted << i; 1867 return formatted.str(); 1868 } 1869 if (e->type() == Type::parfloat()) { 1870 FloatVal i = eval_float(env, e); 1871 std::ostringstream formatted; 1872 if (width > 0) { 1873 formatted.width(width); 1874 } else if (width < 0) { 1875 formatted.width(-width); 1876 formatted.flags(std::ios::left); 1877 } 1878 formatted.setf(std::ios::fixed); 1879 formatted.precision(std::numeric_limits<double>::digits10 + 2); 1880 if (prec != -1) { 1881 formatted.precision(prec); 1882 } 1883 formatted << i; 1884 return formatted.str(); 1885 } 1886 std::string s = show(env, e); 1887 if (prec >= 0 && prec < s.size()) { 1888 s = s.substr(0, prec); 1889 } 1890 std::ostringstream oss; 1891 if (s.size() < std::abs(width)) { 1892 int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size())); 1893 if (addLeft < 0) { 1894 addLeft = 0; 1895 } 1896 int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0; 1897 if (addRight < 0) { 1898 addRight = 0; 1899 } 1900 for (int i = addLeft; (i--) != 0;) { 1901 oss << " "; 1902 } 1903 oss << s; 1904 for (int i = addRight; (i--) != 0;) { 1905 oss << " "; 1906 } 1907 return oss.str(); 1908 } 1909 return s; 1910} 1911 1912std::string b_format_justify_string(EnvI& env, Call* call) { 1913 int width = 0; 1914 GCLock lock; 1915 Expression* e; 1916 width = static_cast<int>(eval_int(env, call->arg(0)).toInt()); 1917 e = eval_par(env, call->arg(1)); 1918 std::string s = eval_string(env, e); 1919 std::ostringstream oss; 1920 if (s.size() < std::abs(width)) { 1921 int addLeft = width < 0 ? 0 : (width - static_cast<int>(s.size())); 1922 if (addLeft < 0) { 1923 addLeft = 0; 1924 } 1925 int addRight = width < 0 ? (-width - static_cast<int>(s.size())) : 0; 1926 if (addRight < 0) { 1927 addRight = 0; 1928 } 1929 for (int i = addLeft; (i--) != 0;) { 1930 oss << " "; 1931 } 1932 oss << s; 1933 for (int i = addRight; (i--) != 0;) { 1934 oss << " "; 1935 } 1936 return oss.str(); 1937 } 1938 return s; 1939} 1940 1941std::string b_show_int(EnvI& env, Call* call) { 1942 assert(call->argCount() == 2); 1943 GCLock lock; 1944 Expression* e = eval_par(env, call->arg(1)); 1945 std::ostringstream oss; 1946 if (auto* iv = e->dynamicCast<IntLit>()) { 1947 int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt()); 1948 std::ostringstream oss_length; 1949 oss_length << iv->v(); 1950 int iv_length = static_cast<int>(oss_length.str().size()); 1951 int addLeft = justify < 0 ? 0 : (justify - iv_length); 1952 if (addLeft < 0) { 1953 addLeft = 0; 1954 } 1955 int addRight = justify < 0 ? (-justify - iv_length) : 0; 1956 if (addRight < 0) { 1957 addRight = 0; 1958 } 1959 for (int i = addLeft; (i--) != 0;) { 1960 oss << " "; 1961 } 1962 oss << iv->v(); 1963 for (int i = addRight; (i--) != 0;) { 1964 oss << " "; 1965 } 1966 } else { 1967 Printer p(oss, 0, false); 1968 p.print(e); 1969 } 1970 return oss.str(); 1971} 1972 1973std::string b_show_float(EnvI& env, Call* call) { 1974 assert(call->argCount() == 3); 1975 GCLock lock; 1976 Expression* e = eval_par(env, call->arg(2)); 1977 std::ostringstream oss; 1978 if (auto* fv = e->dynamicCast<FloatLit>()) { 1979 int justify = static_cast<int>(eval_int(env, call->arg(0)).toInt()); 1980 int prec = static_cast<int>(eval_int(env, call->arg(1)).toInt()); 1981 if (prec < 0) { 1982 throw EvalError(env, call->arg(1)->loc(), 1983 "number of digits in show_float cannot be negative"); 1984 } 1985 std::ostringstream oss_length; 1986 oss_length << std::setprecision(prec) << std::fixed << fv->v(); 1987 int fv_length = static_cast<int>(oss_length.str().size()); 1988 int addLeft = justify < 0 ? 0 : (justify - fv_length); 1989 if (addLeft < 0) { 1990 addLeft = 0; 1991 } 1992 int addRight = justify < 0 ? (-justify - fv_length) : 0; 1993 if (addRight < 0) { 1994 addRight = 0; 1995 } 1996 for (int i = addLeft; (i--) != 0;) { 1997 oss << " "; 1998 } 1999 oss << std::setprecision(prec) << std::fixed << fv->v(); 2000 for (int i = addRight; (i--) != 0;) { 2001 oss << " "; 2002 } 2003 } else { 2004 Printer p(oss, 0, false); 2005 p.print(e); 2006 } 2007 return oss.str(); 2008} 2009 2010std::string b_file_path(EnvI& /*env*/, Call* call) { 2011 return FileUtils::file_path( 2012 std::string(call->loc().filename().c_str(), call->loc().filename().size())); 2013} 2014 2015std::string b_concat(EnvI& env, Call* call) { 2016 assert(call->argCount() == 1); 2017 GCLock lock; 2018 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2019 std::ostringstream oss; 2020 for (unsigned int i = 0; i < al->size(); i++) { 2021 oss << eval_string(env, (*al)[i]); 2022 } 2023 return oss.str(); 2024} 2025 2026std::string b_join(EnvI& env, Call* call) { 2027 assert(call->argCount() == 2); 2028 std::string sep = eval_string(env, call->arg(0)); 2029 GCLock lock; 2030 ArrayLit* al = eval_array_lit(env, call->arg(1)); 2031 std::ostringstream oss; 2032 for (unsigned int i = 0; i < al->size(); i++) { 2033 oss << eval_string(env, (*al)[i]); 2034 if (i < al->size() - 1) { 2035 oss << sep; 2036 } 2037 } 2038 return oss.str(); 2039} 2040 2041IntSetVal* b_array_union(EnvI& env, Call* call) { 2042 assert(call->argCount() == 1); 2043 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2044 if (al->size() == 0) { 2045 return IntSetVal::a(); 2046 } 2047 IntSetVal* isv = eval_intset(env, (*al)[0]); 2048 for (unsigned int i = 0; i < al->size(); i++) { 2049 IntSetRanges i0(isv); 2050 IntSetRanges i1(eval_intset(env, (*al)[i])); 2051 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(i0, i1); 2052 isv = IntSetVal::ai(u); 2053 } 2054 return isv; 2055} 2056 2057IntSetVal* b_array_intersect(EnvI& env, Call* call) { 2058 assert(call->argCount() == 1); 2059 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2060 std::vector<IntSetVal::Range> ranges; 2061 if (al->size() > 0) { 2062 IntSetVal* i0 = eval_intset(env, (*al)[0]); 2063 if (i0->size() > 0) { 2064 IntSetRanges i0r(i0); 2065 IntVal min = i0r.min(); 2066 while (i0r()) { 2067 // Initialize with last interval 2068 IntVal max = i0r.max(); 2069 // Intersect with all other intervals 2070 restart: 2071 for (unsigned int j = al->size(); (j--) != 0U;) { 2072 IntSetRanges ij(eval_intset(env, (*al)[j])); 2073 // Skip intervals that are too small 2074 while (ij() && (ij.max() < min)) { 2075 ++ij; 2076 } 2077 if (!ij()) { 2078 goto done; 2079 } 2080 if (ij.min() > max) { 2081 min = ij.min(); 2082 max = ij.max(); 2083 goto restart; 2084 } 2085 // Now the intervals overlap 2086 if (min < ij.min()) { 2087 min = ij.min(); 2088 } 2089 if (max > ij.max()) { 2090 max = ij.max(); 2091 } 2092 } 2093 ranges.emplace_back(min, max); 2094 // The next interval must be at least two elements away 2095 min = max + 2; 2096 } 2097 done: 2098 return IntSetVal::a(ranges); 2099 } else { 2100 return IntSetVal::a(); 2101 } 2102 } else { 2103 return IntSetVal::a(); 2104 } 2105} 2106 2107Expression* b_sort_by_int(EnvI& env, Call* call) { 2108 assert(call->argCount() == 2); 2109 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2110 ArrayLit* order_e = eval_array_lit(env, call->arg(1)); 2111 std::vector<IntVal> order(order_e->size()); 2112 std::vector<int> a(order_e->size()); 2113 for (unsigned int i = 0; i < order.size(); i++) { 2114 a[i] = i; 2115 order[i] = eval_int(env, (*order_e)[i]); 2116 } 2117 struct Ord { 2118 std::vector<IntVal>& order; 2119 Ord(std::vector<IntVal>& order0) : order(order0) {} 2120 bool operator()(int i, int j) { return order[i] < order[j]; } 2121 } _ord(order); 2122 std::stable_sort(a.begin(), a.end(), _ord); 2123 std::vector<Expression*> sorted(a.size()); 2124 for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) { 2125 sorted[i] = (*al)[a[i]]; 2126 } 2127 auto* al_sorted = new ArrayLit(al->loc(), sorted); 2128 al_sorted->type(al->type()); 2129 return al_sorted; 2130} 2131 2132Expression* b_sort_by_float(EnvI& env, Call* call) { 2133 assert(call->argCount() == 2); 2134 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2135 ArrayLit* order_e = eval_array_lit(env, call->arg(1)); 2136 std::vector<FloatVal> order(order_e->size()); 2137 std::vector<int> a(order_e->size()); 2138 for (unsigned int i = 0; i < order.size(); i++) { 2139 a[i] = i; 2140 order[i] = eval_float(env, (*order_e)[i]); 2141 } 2142 struct Ord { 2143 std::vector<FloatVal>& order; 2144 Ord(std::vector<FloatVal>& order0) : order(order0) {} 2145 bool operator()(int i, int j) { return order[i] < order[j]; } 2146 } _ord(order); 2147 std::stable_sort(a.begin(), a.end(), _ord); 2148 std::vector<Expression*> sorted(a.size()); 2149 for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) { 2150 sorted[i] = (*al)[a[i]]; 2151 } 2152 auto* al_sorted = new ArrayLit(al->loc(), sorted); 2153 al_sorted->type(al->type()); 2154 return al_sorted; 2155} 2156 2157Expression* b_sort(EnvI& env, Call* call) { 2158 assert(call->argCount() == 1); 2159 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2160 std::vector<Expression*> sorted(al->size()); 2161 for (auto i = static_cast<unsigned int>(sorted.size()); (i--) != 0U;) { 2162 sorted[i] = (*al)[i]; 2163 } 2164 struct Ord { 2165 EnvI& env; 2166 Ord(EnvI& env0) : env(env0) {} 2167 bool operator()(Expression* e0, Expression* e1) { 2168 switch (e0->type().bt()) { 2169 case Type::BT_INT: 2170 return eval_int(env, e0) < eval_int(env, e1); 2171 case Type::BT_BOOL: 2172 return static_cast<int>(eval_bool(env, e0)) < static_cast<int>(eval_bool(env, e1)); 2173 case Type::BT_FLOAT: 2174 return eval_float(env, e0) < eval_float(env, e1); 2175 default: 2176 throw EvalError(env, e0->loc(), "unsupported type for sorting"); 2177 } 2178 } 2179 } _ord(env); 2180 std::sort(sorted.begin(), sorted.end(), _ord); 2181 auto* al_sorted = new ArrayLit(al->loc(), sorted); 2182 al_sorted->type(al->type()); 2183 return al_sorted; 2184} 2185 2186Expression* b_inverse(EnvI& env, Call* call) { 2187 assert(call->argCount() == 1); 2188 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2189 if (al->size() == 0) { 2190 return al; 2191 } 2192 int min_idx = al->min(0); 2193 2194 std::vector<IntVal> ivs(al->size()); 2195 IntVal minVal = eval_int(env, (*al)[0]); 2196 IntVal maxVal = minVal; 2197 ivs[0] = minVal; 2198 for (unsigned int i = 1; i < al->size(); i++) { 2199 IntVal ii = eval_int(env, (*al)[i]); 2200 ivs[i] = ii; 2201 minVal = std::min(minVal, ii); 2202 maxVal = std::max(maxVal, ii); 2203 } 2204 if (maxVal - minVal + 1 != al->size()) { 2205 throw ResultUndefinedError(env, call->loc(), 2206 "inverse on non-contiguous set of values is undefined"); 2207 } 2208 2209 std::vector<Expression*> inv(al->size()); 2210 std::vector<bool> used(al->size()); 2211 for (unsigned int i = 0; i < ivs.size(); i++) { 2212 used[(ivs[i] - minVal).toInt()] = true; 2213 inv[(ivs[i] - minVal).toInt()] = IntLit::a(i + min_idx); 2214 } 2215 for (bool b : used) { 2216 if (!b) { 2217 throw ResultUndefinedError(env, call->loc(), 2218 "inverse on non-contiguous set of values is undefined"); 2219 } 2220 } 2221 auto* al_inv = new ArrayLit(al->loc(), inv, {{minVal.toInt(), maxVal.toInt()}}); 2222 al_inv->type(al->type()); 2223 return al_inv; 2224} 2225 2226Expression* b_set_to_ranges_int(EnvI& env, Call* call) { 2227 assert(call->argCount() == 1); 2228 IntSetVal* isv = eval_intset(env, call->arg(0)); 2229 std::vector<Expression*> v(isv->size() * 2); 2230 for (unsigned int i = 0; i < isv->size(); i++) { 2231 v[2 * i] = IntLit::a(isv->min(i)); 2232 v[2 * i + 1] = IntLit::a(isv->max(i)); 2233 } 2234 auto* al = new ArrayLit(call->loc().introduce(), v); 2235 al->type(Type::parint(1)); 2236 return al; 2237} 2238 2239Expression* b_set_to_ranges_float(EnvI& env, Call* call) { 2240 assert(call->argCount() == 1); 2241 FloatSetVal* fsv = eval_floatset(env, call->arg(0)); 2242 std::vector<Expression*> v(fsv->size() * 2); 2243 for (unsigned int i = 0; i < fsv->size(); i++) { 2244 v[2 * i] = FloatLit::a(fsv->min(i)); 2245 v[2 * i + 1] = FloatLit::a(fsv->max(i)); 2246 } 2247 auto* al = new ArrayLit(call->loc().introduce(), v); 2248 al->type(Type::parfloat(1)); 2249 return al; 2250} 2251 2252std::default_random_engine& rnd_generator() { 2253 // TODO: initiate with seed if given as annotation/in command line 2254 static std::default_random_engine g; 2255 return g; 2256} 2257 2258FloatVal b_normal_float_float(EnvI& env, Call* call) { 2259 assert(call->argCount() == 2); 2260 const double mean = eval_float(env, call->arg(0)).toDouble(); 2261 const double stdv = eval_float(env, call->arg(1)).toDouble(); 2262 std::normal_distribution<double> distribution(mean, stdv); 2263 // return a sample from the distribution 2264 return distribution(rnd_generator()); 2265} 2266 2267FloatVal b_normal_int_float(EnvI& env, Call* call) { 2268 assert(call->argCount() == 2); 2269 const double mean = double(eval_int(env, call->arg(0)).toInt()); 2270 const double stdv = eval_float(env, call->arg(1)).toDouble(); 2271 std::normal_distribution<double> distribution(mean, stdv); 2272 // return a sample from the distribution 2273 return distribution(rnd_generator()); 2274} 2275 2276FloatVal b_uniform_float(EnvI& env, Call* call) { 2277 assert(call->argCount() == 2); 2278 const double lb = eval_float(env, call->arg(0)).toDouble(); 2279 const double ub = eval_float(env, call->arg(1)).toDouble(); 2280 if (lb > ub) { 2281 std::stringstream ssm; 2282 ssm << "lowerbound of uniform distribution \"" << lb 2283 << "\" is higher than its upperbound: " << ub; 2284 throw EvalError(env, call->arg(0)->loc(), ssm.str()); 2285 } 2286 std::uniform_real_distribution<double> distribution(lb, ub); 2287 // return a sample from the distribution 2288 return distribution(rnd_generator()); 2289} 2290 2291IntVal b_uniform_int(EnvI& env, Call* call) { 2292 assert(call->argCount() == 2); 2293 const long long int lb = eval_int(env, call->arg(0)).toInt(); 2294 const long long int ub = eval_int(env, call->arg(1)).toInt(); 2295 if (lb > ub) { 2296 std::stringstream ssm; 2297 ssm << "lowerbound of uniform distribution \"" << lb 2298 << "\" is higher than its upperbound: " << ub; 2299 throw EvalError(env, call->arg(0)->loc(), ssm.str()); 2300 } 2301 std::uniform_int_distribution<long long int> distribution(lb, ub); 2302 // return a sample from the distribution 2303 return IntVal(distribution(rnd_generator())); 2304} 2305 2306IntVal b_poisson_int(EnvI& env, Call* call) { 2307 assert(call->argCount() == 1); 2308 long long int mean = eval_int(env, call->arg(0)).toInt(); 2309 std::poisson_distribution<long long int> distribution(static_cast<double>(mean)); 2310 // return a sample from the distribution 2311 return IntVal(distribution(rnd_generator())); 2312} 2313 2314IntVal b_poisson_float(EnvI& env, Call* call) { 2315 assert(call->argCount() == 1); 2316 double mean = eval_float(env, call->arg(0)).toDouble(); 2317 std::poisson_distribution<long long int> distribution(mean); 2318 // return a sample from the distribution 2319 return IntVal(distribution(rnd_generator())); 2320} 2321 2322FloatVal b_gamma_float_float(EnvI& env, Call* call) { 2323 assert(call->argCount() == 2); 2324 const double alpha = eval_float(env, call->arg(0)).toDouble(); 2325 const double beta = eval_float(env, call->arg(1)).toDouble(); 2326 std::gamma_distribution<double> distribution(alpha, beta); 2327 // return a sample from the distribution 2328 return distribution(rnd_generator()); 2329} 2330 2331FloatVal b_gamma_int_float(EnvI& env, Call* call) { 2332 assert(call->argCount() == 2); 2333 const double alpha = eval_float(env, call->arg(0)).toDouble(); 2334 const double beta = eval_float(env, call->arg(1)).toDouble(); 2335 std::gamma_distribution<double> distribution(alpha, beta); 2336 // return a sample from the distribution 2337 return distribution(rnd_generator()); 2338} 2339 2340FloatVal b_weibull_int_float(EnvI& env, Call* call) { 2341 assert(call->argCount() == 2); 2342 const double shape = double(eval_int(env, call->arg(0)).toInt()); 2343 if (shape < 0) { 2344 std::stringstream ssm; 2345 ssm << "The shape factor for the weibull distribution \"" << shape 2346 << "\" has to be greater than zero."; 2347 throw EvalError(env, call->arg(0)->loc(), ssm.str()); 2348 } 2349 const double scale = eval_float(env, call->arg(1)).toDouble(); 2350 if (scale < 0) { 2351 std::stringstream ssm; 2352 ssm << "The scale factor for the weibull distribution \"" << scale 2353 << "\" has to be greater than zero."; 2354 throw EvalError(env, call->arg(1)->loc(), ssm.str()); 2355 } 2356 std::weibull_distribution<double> distribution(shape, scale); 2357 // return a sample from the distribution 2358 return distribution(rnd_generator()); 2359} 2360 2361FloatVal b_weibull_float_float(EnvI& env, Call* call) { 2362 assert(call->argCount() == 2); 2363 const double shape = eval_float(env, call->arg(0)).toDouble(); 2364 if (shape < 0) { 2365 std::stringstream ssm; 2366 ssm << "The shape factor for the weibull distribution \"" << shape 2367 << "\" has to be greater than zero."; 2368 throw EvalError(env, call->arg(0)->loc(), ssm.str()); 2369 } 2370 const double scale = eval_float(env, call->arg(1)).toDouble(); 2371 if (scale < 0) { 2372 std::stringstream ssm; 2373 ssm << "The scale factor for the weibull distribution \"" << scale 2374 << "\" has to be greater than zero."; 2375 throw EvalError(env, call->arg(1)->loc(), ssm.str()); 2376 } 2377 std::weibull_distribution<double> distribution(shape, scale); 2378 // return a sample from the distribution 2379 return distribution(rnd_generator()); 2380} 2381 2382FloatVal b_exponential_float(EnvI& env, Call* call) { 2383 assert(call->argCount() == 1); 2384 const double lambda = eval_float(env, call->arg(0)).toDouble(); 2385 if (lambda < 0) { 2386 std::stringstream ssm; 2387 ssm << "The lambda-parameter for the exponential distribution function \"" << lambda 2388 << "\" has to be greater than zero."; 2389 throw EvalError(env, call->arg(0)->loc(), ssm.str()); 2390 } 2391 std::exponential_distribution<double> distribution(lambda); 2392 // return a sample from the distribution 2393 return distribution(rnd_generator()); 2394} 2395 2396FloatVal b_exponential_int(EnvI& env, Call* call) { 2397 assert(call->argCount() == 1); 2398 const double lambda = double(eval_int(env, call->arg(0)).toInt()); 2399 if (lambda < 0) { 2400 std::stringstream ssm; 2401 ssm << "The lambda-parameter for the exponential distribution function \"" << lambda 2402 << "\" has to be greater than zero."; 2403 throw EvalError(env, call->arg(0)->loc(), ssm.str()); 2404 } 2405 std::exponential_distribution<double> distribution(lambda); 2406 // return a sample from the distribution 2407 return distribution(rnd_generator()); 2408} 2409 2410FloatVal b_lognormal_float_float(EnvI& env, Call* call) { 2411 assert(call->argCount() == 2); 2412 const double mean = eval_float(env, call->arg(0)).toDouble(); 2413 const double stdv = eval_float(env, call->arg(1)).toDouble(); 2414 std::lognormal_distribution<double> distribution(mean, stdv); 2415 // return a sample from the distribution 2416 return distribution(rnd_generator()); 2417} 2418 2419FloatVal b_lognormal_int_float(EnvI& env, Call* call) { 2420 assert(call->argCount() == 2); 2421 const double mean = double(eval_int(env, call->arg(0)).toInt()); 2422 const double stdv = eval_float(env, call->arg(1)).toDouble(); 2423 std::lognormal_distribution<double> distribution(mean, stdv); 2424 // return a sample from the distribution 2425 return distribution(rnd_generator()); 2426} 2427 2428FloatVal b_chisquared_float(EnvI& env, Call* call) { 2429 assert(call->argCount() == 1); 2430 const double lambda = eval_float(env, call->arg(0)).toDouble(); 2431 std::exponential_distribution<double> distribution(lambda); 2432 // return a sample from the distribution 2433 return distribution(rnd_generator()); 2434} 2435 2436FloatVal b_chisquared_int(EnvI& env, Call* call) { 2437 assert(call->argCount() == 1); 2438 const double lambda = double(eval_int(env, call->arg(0)).toInt()); 2439 std::exponential_distribution<double> distribution(lambda); 2440 // return a sample from the distribution 2441 return distribution(rnd_generator()); 2442} 2443 2444FloatVal b_cauchy_float_float(EnvI& env, Call* call) { 2445 assert(call->argCount() == 2); 2446 const double mean = eval_float(env, call->arg(0)).toDouble(); 2447 const double scale = eval_float(env, call->arg(1)).toDouble(); 2448 std::cauchy_distribution<double> distribution(mean, scale); 2449 // return a sample from the distribution 2450 return distribution(rnd_generator()); 2451} 2452 2453FloatVal b_cauchy_int_float(EnvI& env, Call* call) { 2454 assert(call->argCount() == 2); 2455 const double mean = double(eval_int(env, call->arg(0)).toInt()); 2456 const double scale = eval_float(env, call->arg(1)).toDouble(); 2457 std::cauchy_distribution<double> distribution(mean, scale); 2458 // return a sample from the distribution 2459 return distribution(rnd_generator()); 2460} 2461 2462FloatVal b_fdistribution_float_float(EnvI& env, Call* call) { 2463 assert(call->argCount() == 2); 2464 const double d1 = eval_float(env, call->arg(0)).toDouble(); 2465 const double d2 = eval_float(env, call->arg(1)).toDouble(); 2466 std::fisher_f_distribution<double> distribution(d1, d2); 2467 // return a sample from the distribution 2468 return distribution(rnd_generator()); 2469} 2470 2471FloatVal b_fdistribution_int_int(EnvI& env, Call* call) { 2472 assert(call->argCount() == 2); 2473 const double d1 = double(eval_int(env, call->arg(0)).toInt()); 2474 const double d2 = double(eval_int(env, call->arg(1)).toInt()); 2475 std::fisher_f_distribution<double> distribution(d1, d2); 2476 // return a sample from the distribution 2477 return distribution(rnd_generator()); 2478} 2479 2480FloatVal b_tdistribution_float(EnvI& env, Call* call) { 2481 assert(call->argCount() == 1); 2482 const double sampleSize = eval_float(env, call->arg(0)).toDouble(); 2483 std::student_t_distribution<double> distribution(sampleSize); 2484 // return a sample from the distribution 2485 return distribution(rnd_generator()); 2486} 2487 2488FloatVal b_tdistribution_int(EnvI& env, Call* call) { 2489 assert(call->argCount() == 1); 2490 const double sampleSize = double(eval_int(env, call->arg(0)).toInt()); 2491 std::student_t_distribution<double> distribution(sampleSize); 2492 // return a sample from the distribution 2493 return distribution(rnd_generator()); 2494} 2495 2496IntVal b_discrete_distribution(EnvI& env, Call* call) { 2497 assert(call->argCount() == 1); 2498 GCLock lock; 2499 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2500 if (al->dims() != 1) { 2501 std::stringstream ssm; 2502 ssm << "expecting 1-dimensional array of weights for discrete distribution instead of: " << *al 2503 << std::endl; 2504 throw EvalError(env, al->loc(), ssm.str()); 2505 } 2506 std::vector<long long int> weights(al->size()); 2507 for (unsigned int i = 0; i < al->size(); i++) { 2508 weights[i] = eval_int(env, (*al)[i]).toInt(); 2509 } 2510#ifdef _MSC_VER 2511 std::size_t i(0); 2512 std::discrete_distribution<long long int> distribution( 2513 weights.size(), 0.0, 1.0, [&weights, &i](double d) { return weights[i++]; }); 2514#else 2515 std::discrete_distribution<long long int> distribution(weights.begin(), weights.end()); 2516#endif 2517 // return a sample from the distribution 2518 IntVal iv = IntVal(distribution(rnd_generator())); 2519 return iv; 2520} 2521 2522bool b_bernoulli(EnvI& env, Call* call) { 2523 assert(call->argCount() == 1); 2524 const double p = eval_float(env, call->arg(0)).toDouble(); 2525 std::bernoulli_distribution distribution(p); 2526 // return a sample from the distribution 2527 return distribution(rnd_generator()); 2528} 2529 2530IntVal b_binomial(EnvI& env, Call* call) { 2531 assert(call->argCount() == 2); 2532 double t = double(eval_int(env, call->arg(0)).toInt()); 2533 double p = eval_float(env, call->arg(1)).toDouble(); 2534 std::binomial_distribution<long long int> distribution(t, p); 2535 // return a sample from the distribution 2536 return IntVal(distribution(rnd_generator())); 2537} 2538 2539FloatVal b_atan(EnvI& env, Call* call) { 2540 assert(call->argCount() == 1); 2541 GCLock lock; 2542 FloatVal f = eval_float(env, call->arg(0)); 2543 return std::atan(f.toDouble()); 2544} 2545 2546FloatVal b_cos(EnvI& env, Call* call) { 2547 assert(call->argCount() == 1); 2548 GCLock lock; 2549 FloatVal f = eval_float(env, call->arg(0)); 2550 return std::cos(f.toDouble()); 2551} 2552 2553FloatVal b_sin(EnvI& env, Call* call) { 2554 assert(call->argCount() == 1); 2555 GCLock lock; 2556 FloatVal f = eval_float(env, call->arg(0)); 2557 return std::sin(f.toDouble()); 2558} 2559 2560FloatVal b_asin(EnvI& env, Call* call) { 2561 assert(call->argCount() == 1); 2562 GCLock lock; 2563 FloatVal f = eval_float(env, call->arg(0)); 2564 return std::asin(f.toDouble()); 2565} 2566 2567FloatVal b_acos(EnvI& env, Call* call) { 2568 assert(call->argCount() == 1); 2569 GCLock lock; 2570 FloatVal f = eval_float(env, call->arg(0)); 2571 return std::acos(f.toDouble()); 2572} 2573 2574FloatVal b_tan(EnvI& env, Call* call) { 2575 assert(call->argCount() == 1); 2576 GCLock lock; 2577 FloatVal f = eval_float(env, call->arg(0)); 2578 return std::tan(f.toDouble()); 2579} 2580 2581IntVal b_to_enum(EnvI& env, Call* call) { 2582 assert(call->argCount() == 2); 2583 IntSetVal* isv = eval_intset(env, call->arg(0)); 2584 IntVal v = eval_int(env, call->arg(1)); 2585 if (!isv->contains(v)) { 2586 throw ResultUndefinedError(env, call->loc(), "value outside of enum range"); 2587 } 2588 return v; 2589} 2590 2591IntVal b_enum_next(EnvI& env, Call* call) { 2592 IntSetVal* isv = eval_intset(env, call->arg(0)); 2593 IntVal v = eval_int(env, call->arg(1)); 2594 if (!isv->contains(v + 1)) { 2595 throw ResultUndefinedError(env, call->loc(), "value outside of enum range"); 2596 } 2597 return v + 1; 2598} 2599 2600IntVal b_enum_prev(EnvI& env, Call* call) { 2601 IntSetVal* isv = eval_intset(env, call->arg(0)); 2602 IntVal v = eval_int(env, call->arg(1)); 2603 if (!isv->contains(v - 1)) { 2604 throw ResultUndefinedError(env, call->loc(), "value outside of enum range"); 2605 } 2606 return v - 1; 2607} 2608 2609IntVal b_mzn_compiler_version(EnvI& /*env*/, Call* /*call*/) { 2610 return atoi(MZN_VERSION_MAJOR) * 10000 + atoi(MZN_VERSION_MINOR) * 1000 + atoi(MZN_VERSION_PATCH); 2611} 2612 2613Expression* b_slice(EnvI& env, Call* call) { 2614 ArrayLit* al = eval_array_lit(env, call->arg(0)); 2615 2616 ArrayLit* slice = eval_array_lit(env, call->arg(1)); 2617 std::vector<std::pair<int, int>> newSlice(slice->size()); 2618 for (unsigned int i = 0; i < slice->size(); i++) { 2619 IntSetVal* isv = eval_intset(env, (*slice)[i]); 2620 if (isv->size() == 0) { 2621 newSlice[i] = std::pair<int, int>(1, 0); 2622 } else { 2623 if (isv->size() > 1) { 2624 throw ResultUndefinedError(env, call->loc(), "array slice must be contiguous"); 2625 } 2626 int sl_min = isv->min().isFinite() ? static_cast<int>(isv->min().toInt()) : al->min(i); 2627 int sl_max = isv->max().isFinite() ? static_cast<int>(isv->max().toInt()) : al->max(i); 2628 if (sl_min < al->min(i) || sl_max > al->max(i)) { 2629 throw ResultUndefinedError(env, call->loc(), "array slice out of bounds"); 2630 } 2631 newSlice[i] = std::pair<int, int>(sl_min, sl_max); 2632 } 2633 } 2634 2635 std::vector<std::pair<int, int>> newDims(call->argCount() - 2); 2636 for (unsigned int i = 0; i < newDims.size(); i++) { 2637 IntSetVal* isv = eval_intset(env, call->arg(2 + i)); 2638 if (isv->size() == 0) { 2639 newDims[i] = std::pair<int, int>(1, 0); 2640 } else { 2641 newDims[i] = std::pair<int, int>(static_cast<int>(isv->min().toInt()), 2642 static_cast<int>(isv->max().toInt())); 2643 } 2644 } 2645 auto* ret = new ArrayLit(al->loc(), al, newDims, newSlice); 2646 ret->type(call->type()); 2647 return ret; 2648} 2649 2650Expression* b_regular_from_string(EnvI& env, Call* call) { 2651#ifdef HAS_GECODE 2652 using namespace Gecode; 2653 ArrayLit* vars = eval_array_lit(env, call->arg(0)); 2654 std::string expr = eval_string(env, call->arg(1)); 2655 2656 IntSetVal* dom; 2657 if (vars->size() == 0) { 2658 dom = IntSetVal::a(); 2659 } else { 2660 dom = b_dom_varint(env, (*vars)[0]); 2661 for (unsigned int i = 1; i < vars->size(); i++) { 2662 IntSetRanges isr(dom); 2663 IntSetRanges r(b_dom_varint(env, (*vars)[i])); 2664 Ranges::Union<IntVal, IntSetRanges, IntSetRanges> u(isr, r); 2665 dom = IntSetVal::ai(u); 2666 } 2667 } 2668 long long int card = dom->max().toInt() - dom->min().toInt() + 1; 2669 int offset = 1 - static_cast<int>(dom->min().toInt()); 2670 2671 // Replace all occurrences of enum constructor calls 2672 std::regex constructor_call( 2673 "([A-Za-z][A-Za-z0-9_]*|'[^'\\xa\\xd\\x0]*')[[:space:]]*\\([[:space:]]*([A-Za-z][A-Za-z0-9_]*" 2674 "|'[^'\\xa\\xd\\x0]*'|([0-9]*))[[:space:]]*\\)", 2675 std::regex_constants::egrep); 2676 while (std::regex_search(expr, constructor_call)) { 2677 std::ostringstream oss; 2678 auto id_re_it = 2679 std::sregex_token_iterator(expr.begin(), expr.end(), constructor_call, {-1, 1, 2, 3}); 2680 for (; id_re_it != std::sregex_token_iterator();) { 2681 std::string rest = *id_re_it; 2682 oss << rest; 2683 ++id_re_it; 2684 if (id_re_it == std::sregex_token_iterator()) { 2685 break; 2686 } 2687 std::string id1 = *id_re_it; 2688 ++id_re_it; 2689 std::string id2 = *id_re_it; 2690 ++id_re_it; 2691 std::string val3 = *id_re_it; 2692 ++id_re_it; 2693 // Enum constructor call, get both items 2694 Expression* arg; 2695 if (val3.empty()) { 2696 auto it = env.reverseEnum.find(id2); 2697 if (it == env.reverseEnum.end()) { 2698 throw std::runtime_error("Unknown identifier: " + id2); 2699 } 2700 auto* id2_vd = it->second->dynamicCast<VarDeclI>(); 2701 if (id2_vd == nullptr) { 2702 throw std::runtime_error("identifier " + id2 + " is not an enum constant"); 2703 } 2704 arg = id2_vd->e()->id(); 2705 } else { 2706 int v = std::stoi(val3); 2707 arg = IntLit::a(v); 2708 } 2709 auto it = env.reverseEnum.find(id1); 2710 if (it == env.reverseEnum.end()) { 2711 throw std::runtime_error("Unknown identifier: " + id2); 2712 } 2713 if (auto* id1_vdi = it->second->dynamicCast<VarDeclI>()) { 2714 // this is not an enum constructor, simply output both values 2715 IntVal result1 = eval_int(env, id1_vdi->e()->id()); 2716 IntVal result2 = eval_int(env, arg); 2717 oss << result1 << "(" << result2 << ")"; 2718 } else { 2719 auto* fi = it->second->cast<FunctionI>(); 2720 Call* c = new Call(Location().introduce(), fi->id(), {arg}); 2721 c->type(fi->rtype(env, {arg->type()}, true)); 2722 c->decl(fi); 2723 2724 IntVal result = eval_int(env, c); 2725 oss << result; 2726 } 2727 } 2728 expr = oss.str(); 2729 } 2730 2731 // Replace all remaining enum identifiers 2732 std::regex enumid("[A-Za-z][A-Za-z0-9_]*|'[^'\\xa\\xd\\x0]*'", std::regex_constants::egrep); 2733 auto id_re_it = std::sregex_token_iterator(expr.begin(), expr.end(), enumid, {-1, 0}); 2734 std::ostringstream oss; 2735 for (; id_re_it != std::sregex_token_iterator();) { 2736 std::string rest = *id_re_it; 2737 oss << rest; 2738 ++id_re_it; 2739 if (id_re_it == std::sregex_token_iterator()) { 2740 break; 2741 } 2742 std::string id1 = *id_re_it; 2743 ++id_re_it; 2744 auto it = env.reverseEnum.find(id1); 2745 if (it == env.reverseEnum.end()) { 2746 throw std::runtime_error("Unknown identifier: " + id1); 2747 } 2748 auto* id1_vd = it->second->dynamicCast<VarDeclI>(); 2749 if (id1_vd == nullptr) { 2750 throw std::runtime_error("identifier " + id1 + " is not an enum constant"); 2751 } 2752 IntVal result1 = eval_int(env, id1_vd->e()->id()); 2753 oss << result1; 2754 } 2755 expr = oss.str(); 2756 2757 std::unique_ptr<REG> regex; 2758 try { 2759 regex = regex_from_string(expr, *dom); 2760 } catch (const std::exception& e) { 2761 throw SyntaxError(call->arg(1)->loc(), e.what()); 2762 } 2763 DFA dfa = DFA(*regex); 2764 2765 std::vector<std::vector<Expression*>> reg_trans( 2766 dfa.n_states(), std::vector<Expression*>(static_cast<size_t>(card), IntLit::a(IntVal(0)))); 2767 2768 DFA::Transitions trans(dfa); 2769 while (trans()) { 2770 // std::cerr << trans.i_state() + 1 << " -- " << trans.symbol() << " --> " << 2771 // trans.o_state() + 1 << "\n"; 2772 if (trans.symbol() >= dom->min().toInt() && trans.symbol() <= dom->max().toInt()) { 2773 reg_trans[trans.i_state()][trans.symbol() + offset - 1] = 2774 IntLit::a(IntVal(trans.o_state() + 1)); 2775 } 2776 ++trans; 2777 } 2778 2779 std::vector<Expression*> args(6); 2780 if (offset == 0) { 2781 args[0] = vars; // x 2782 } else { 2783 std::vector<Expression*> nvars(vars->size()); 2784 IntLit* loffset = IntLit::a(IntVal(offset)); 2785 for (int i = 0; i < nvars.size(); ++i) { 2786 nvars[i] = new BinOp(call->loc().introduce(), (*vars)[i], BOT_PLUS, loffset); 2787 nvars[i]->type(Type::varint()); 2788 } 2789 args[0] = new ArrayLit(call->loc().introduce(), nvars); // x 2790 args[0]->type(Type::varint(1)); 2791 } 2792 args[1] = IntLit::a(IntVal(dfa.n_states())); // Q 2793 args[1]->type(Type::parint()); 2794 args[2] = IntLit::a(IntVal(card)); // S 2795 args[2]->type(Type::parint()); 2796 args[3] = new ArrayLit(call->loc().introduce(), reg_trans); // d 2797 args[3]->type(Type::parint(2)); 2798 args[4] = IntLit::a(IntVal(1)); // q0 2799 args[4]->type(Type::parint()); 2800 args[5] = new SetLit(call->loc().introduce(), 2801 IntSetVal::a(IntVal(dfa.final_fst() + 1), IntVal(dfa.final_lst()))); // F 2802 args[5]->type(Type::parsetint()); 2803 2804 auto* nc = new Call(call->loc().introduce(), "regular", args); 2805 nc->type(Type::varbool()); 2806 2807 return nc; 2808#else 2809 throw FlatteningError( 2810 env, call->loc(), 2811 "MiniZinc was compiled without built-in Gecode, cannot parse regular expression"); 2812#endif 2813} 2814 2815Expression* b_show_checker_output(EnvI& env, Call* call) { 2816 // Get checker output 2817 env.checkerOutput.flush(); 2818 std::string output = env.checkerOutput.str(); 2819 // Reset checker output 2820 env.checkerOutput.str(""); 2821 env.checkerOutput.clear(); 2822 return new StringLit(call->loc().introduce(), output); 2823} 2824 2825void register_builtins(Env& e) { 2826 EnvI& env = e.envi(); 2827 Model* m = env.model; 2828 2829 std::vector<Type> t_intint(2); 2830 t_intint[0] = Type::parint(); 2831 t_intint[1] = Type::parint(); 2832 2833 std::vector<Type> t_intarray(1); 2834 t_intarray[0] = Type::parint(-1); 2835 2836 GCLock lock; 2837 2838 rb(env, m, ASTString("min"), t_intint, b_int_min); 2839 rb(env, m, ASTString("min"), t_intarray, b_int_min); 2840 rb(env, m, ASTString("max"), t_intint, b_int_max); 2841 rb(env, m, ASTString("max"), t_intarray, b_int_max); 2842 rb(env, m, constants().ids.sum, t_intarray, b_sum_int); 2843 rb(env, m, ASTString("product"), t_intarray, b_product_int); 2844 rb(env, m, ASTString("pow"), t_intint, b_pow_int); 2845 2846 rb(env, m, ASTString("'div'"), t_intint, b_idiv); 2847 rb(env, m, ASTString("'mod'"), t_intint, b_mod); 2848 rb(env, m, ASTString("'..'"), t_intint, b_dotdot); 2849 { 2850 std::vector<Type> t({Type::parfloat(), Type::parfloat()}); 2851 rb(env, m, ASTString("'/'"), t, b_fdiv); 2852 } 2853 { 2854 std::vector<Type> t(2); 2855 t[0] = Type::top(-1); 2856 t[1] = Type::top(-1); 2857 rb(env, m, ASTString("index_sets_agree"), t, b_index_sets_agree); 2858 } 2859 { 2860 std::vector<Type> t_anyarray1(1); 2861 t_anyarray1[0] = Type::optvartop(1); 2862 rb(env, m, ASTString("index_set"), t_anyarray1, b_index_set1); 2863 } 2864 { 2865 std::vector<Type> t_anyarray2(1); 2866 t_anyarray2[0] = Type::optvartop(2); 2867 rb(env, m, ASTString("index_set_1of2"), t_anyarray2, b_index_set1); 2868 rb(env, m, ASTString("index_set_2of2"), t_anyarray2, b_index_set2); 2869 } 2870 { 2871 std::vector<Type> t_anyarray3(1); 2872 t_anyarray3[0] = Type::optvartop(3); 2873 rb(env, m, ASTString("index_set_1of3"), t_anyarray3, b_index_set1); 2874 rb(env, m, ASTString("index_set_2of3"), t_anyarray3, b_index_set2); 2875 rb(env, m, ASTString("index_set_3of3"), t_anyarray3, b_index_set3); 2876 } 2877 { 2878 std::vector<Type> t_anyarray4(1); 2879 t_anyarray4[0] = Type::optvartop(4); 2880 rb(env, m, ASTString("index_set_1of4"), t_anyarray4, b_index_set1); 2881 rb(env, m, ASTString("index_set_2of4"), t_anyarray4, b_index_set2); 2882 rb(env, m, ASTString("index_set_3of4"), t_anyarray4, b_index_set3); 2883 rb(env, m, ASTString("index_set_4of4"), t_anyarray4, b_index_set4); 2884 } 2885 { 2886 std::vector<Type> t_anyarray5(1); 2887 t_anyarray5[0] = Type::optvartop(5); 2888 rb(env, m, ASTString("index_set_1of5"), t_anyarray5, b_index_set1); 2889 rb(env, m, ASTString("index_set_2of5"), t_anyarray5, b_index_set2); 2890 rb(env, m, ASTString("index_set_3of5"), t_anyarray5, b_index_set3); 2891 rb(env, m, ASTString("index_set_4of5"), t_anyarray5, b_index_set4); 2892 rb(env, m, ASTString("index_set_5of5"), t_anyarray5, b_index_set5); 2893 } 2894 { 2895 std::vector<Type> t_anyarray6(1); 2896 t_anyarray6[0] = Type::optvartop(6); 2897 rb(env, m, ASTString("index_set_1of6"), t_anyarray6, b_index_set1); 2898 rb(env, m, ASTString("index_set_2of6"), t_anyarray6, b_index_set2); 2899 rb(env, m, ASTString("index_set_3of6"), t_anyarray6, b_index_set3); 2900 rb(env, m, ASTString("index_set_4of6"), t_anyarray6, b_index_set4); 2901 rb(env, m, ASTString("index_set_5of6"), t_anyarray6, b_index_set5); 2902 rb(env, m, ASTString("index_set_6of6"), t_anyarray6, b_index_set6); 2903 } 2904 { 2905 std::vector<Type> t_arrayXd(1); 2906 t_arrayXd[0] = Type::top(-1); 2907 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list); 2908 t_arrayXd[0].ot(Type::OT_OPTIONAL); 2909 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list); 2910 t_arrayXd[0] = Type::vartop(-1); 2911 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list); 2912 t_arrayXd[0] = Type::optvartop(-1); 2913 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d_list); 2914 } 2915 { 2916 std::vector<Type> t_arrayXd(2); 2917 t_arrayXd[0] = Type::parsetint(); 2918 t_arrayXd[1] = Type::top(-1); 2919 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d); 2920 t_arrayXd[1].ot(Type::OT_OPTIONAL); 2921 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d); 2922 t_arrayXd[1] = Type::vartop(-1); 2923 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d); 2924 t_arrayXd[1] = Type::optvartop(-1); 2925 rb(env, m, ASTString("array1d"), t_arrayXd, b_array1d); 2926 } 2927 { 2928 std::vector<Type> t_arrayXd(2); 2929 t_arrayXd[0] = Type::optvartop(-1); 2930 t_arrayXd[1] = Type::top(-1); 2931 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd); 2932 t_arrayXd[1].ot(Type::OT_OPTIONAL); 2933 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd); 2934 t_arrayXd[1] = Type::vartop(-1); 2935 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd); 2936 t_arrayXd[1] = Type::optvartop(-1); 2937 rb(env, m, ASTString("arrayXd"), t_arrayXd, b_arrayXd); 2938 } 2939 { 2940 std::vector<Type> t_arrayXd(3); 2941 t_arrayXd[0] = Type::parsetint(); 2942 t_arrayXd[1] = Type::parsetint(); 2943 t_arrayXd[2] = Type::top(-1); 2944 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d); 2945 t_arrayXd[2].ot(Type::OT_OPTIONAL); 2946 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d); 2947 t_arrayXd[2] = Type::vartop(-1); 2948 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d); 2949 t_arrayXd[2] = Type::optvartop(-1); 2950 rb(env, m, ASTString("array2d"), t_arrayXd, b_array2d); 2951 } 2952 { 2953 std::vector<Type> t_arrayXd(4); 2954 t_arrayXd[0] = Type::parsetint(); 2955 t_arrayXd[1] = Type::parsetint(); 2956 t_arrayXd[2] = Type::parsetint(); 2957 t_arrayXd[3] = Type::top(-1); 2958 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d); 2959 t_arrayXd[3].ot(Type::OT_OPTIONAL); 2960 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d); 2961 t_arrayXd[3] = Type::vartop(-1); 2962 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d); 2963 t_arrayXd[3] = Type::optvartop(-1); 2964 rb(env, m, ASTString("array3d"), t_arrayXd, b_array3d); 2965 } 2966 { 2967 std::vector<Type> t_arrayXd(5); 2968 t_arrayXd[0] = Type::parsetint(); 2969 t_arrayXd[1] = Type::parsetint(); 2970 t_arrayXd[2] = Type::parsetint(); 2971 t_arrayXd[3] = Type::parsetint(); 2972 t_arrayXd[4] = Type::top(-1); 2973 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d); 2974 t_arrayXd[4].ot(Type::OT_OPTIONAL); 2975 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d); 2976 t_arrayXd[4] = Type::vartop(-1); 2977 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d); 2978 t_arrayXd[4] = Type::optvartop(-1); 2979 rb(env, m, ASTString("array4d"), t_arrayXd, b_array4d); 2980 } 2981 { 2982 std::vector<Type> t_arrayXd(6); 2983 t_arrayXd[0] = Type::parsetint(); 2984 t_arrayXd[1] = Type::parsetint(); 2985 t_arrayXd[2] = Type::parsetint(); 2986 t_arrayXd[3] = Type::parsetint(); 2987 t_arrayXd[4] = Type::parsetint(); 2988 t_arrayXd[5] = Type::top(-1); 2989 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d); 2990 t_arrayXd[5].ot(Type::OT_OPTIONAL); 2991 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d); 2992 t_arrayXd[5] = Type::vartop(-1); 2993 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d); 2994 t_arrayXd[5] = Type::optvartop(-1); 2995 rb(env, m, ASTString("array5d"), t_arrayXd, b_array5d); 2996 } 2997 { 2998 std::vector<Type> t_arrayXd(7); 2999 t_arrayXd[0] = Type::parsetint(); 3000 t_arrayXd[1] = Type::parsetint(); 3001 t_arrayXd[2] = Type::parsetint(); 3002 t_arrayXd[3] = Type::parsetint(); 3003 t_arrayXd[4] = Type::parsetint(); 3004 t_arrayXd[5] = Type::parsetint(); 3005 t_arrayXd[6] = Type::top(-1); 3006 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d); 3007 t_arrayXd[6].ot(Type::OT_OPTIONAL); 3008 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d); 3009 t_arrayXd[6] = Type::vartop(-1); 3010 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d); 3011 t_arrayXd[6] = Type::optvartop(-1); 3012 rb(env, m, ASTString("array6d"), t_arrayXd, b_array6d); 3013 } 3014 { 3015 std::vector<Type> stv(3); 3016 stv[0] = Type::partop(-1); 3017 stv[1] = Type::parsetint(1); 3018 stv[2] = Type::parsetint(); 3019 rb(env, m, ASTString("slice_1d"), stv, b_slice); 3020 stv[0] = Type::vartop(-1); 3021 rb(env, m, ASTString("slice_1d"), stv, b_slice); 3022 stv[0] = Type::optvartop(-1); 3023 rb(env, m, ASTString("slice_1d"), stv, b_slice); 3024 stv[0] = Type::optpartop(-1); 3025 rb(env, m, ASTString("slice_1d"), stv, b_slice); 3026 3027 stv.push_back(Type::parsetint()); 3028 stv[0] = Type::partop(-1); 3029 rb(env, m, ASTString("slice_2d"), stv, b_slice); 3030 stv[0] = Type::vartop(-1); 3031 rb(env, m, ASTString("slice_2d"), stv, b_slice); 3032 stv[0] = Type::optvartop(-1); 3033 rb(env, m, ASTString("slice_2d"), stv, b_slice); 3034 stv[0] = Type::optpartop(-1); 3035 rb(env, m, ASTString("slice_2d"), stv, b_slice); 3036 3037 stv.push_back(Type::parsetint()); 3038 stv[0] = Type::partop(-1); 3039 rb(env, m, ASTString("slice_3d"), stv, b_slice); 3040 stv[0] = Type::vartop(-1); 3041 rb(env, m, ASTString("slice_3d"), stv, b_slice); 3042 stv[0] = Type::optvartop(-1); 3043 rb(env, m, ASTString("slice_3d"), stv, b_slice); 3044 stv[0] = Type::optpartop(-1); 3045 rb(env, m, ASTString("slice_3d"), stv, b_slice); 3046 3047 stv.push_back(Type::parsetint()); 3048 stv[0] = Type::partop(-1); 3049 rb(env, m, ASTString("slice_4d"), stv, b_slice); 3050 stv[0] = Type::vartop(-1); 3051 rb(env, m, ASTString("slice_4d"), stv, b_slice); 3052 stv[0] = Type::optvartop(-1); 3053 rb(env, m, ASTString("slice_4d"), stv, b_slice); 3054 stv[0] = Type::optpartop(-1); 3055 rb(env, m, ASTString("slice_4d"), stv, b_slice); 3056 3057 stv.push_back(Type::parsetint()); 3058 stv[0] = Type::partop(-1); 3059 rb(env, m, ASTString("slice_5d"), stv, b_slice); 3060 stv[0] = Type::vartop(-1); 3061 rb(env, m, ASTString("slice_5d"), stv, b_slice); 3062 stv[0] = Type::optvartop(-1); 3063 rb(env, m, ASTString("slice_5d"), stv, b_slice); 3064 stv[0] = Type::optpartop(-1); 3065 rb(env, m, ASTString("slice_5d"), stv, b_slice); 3066 3067 stv.push_back(Type::parsetint()); 3068 stv[0] = Type::partop(-1); 3069 rb(env, m, ASTString("slice_6d"), stv, b_slice); 3070 stv[0] = Type::vartop(-1); 3071 rb(env, m, ASTString("slice_6d"), stv, b_slice); 3072 stv[0] = Type::optvartop(-1); 3073 rb(env, m, ASTString("slice_6d"), stv, b_slice); 3074 stv[0] = Type::optpartop(-1); 3075 rb(env, m, ASTString("slice_6d"), stv, b_slice); 3076 } 3077 { 3078 std::vector<Type> t(2); 3079 t[0] = Type::parbool(); 3080 t[1] = Type::parstring(); 3081 rb(env, m, constants().ids.assert, t, b_assert_bool); 3082 } 3083 { 3084 std::vector<Type> t(3); 3085 t[0] = Type::parbool(); 3086 t[1] = Type::parstring(); 3087 t[2] = Type::top(); 3088 rb(env, m, constants().ids.assert, t, b_assert); 3089 t[2] = Type::optpartop(); 3090 rb(env, m, constants().ids.assert, t, b_assert); 3091 t[2] = Type::vartop(); 3092 rb(env, m, constants().ids.assert, t, b_assert); 3093 t[2] = Type::optvartop(); 3094 rb(env, m, constants().ids.assert, t, b_assert); 3095 t[2] = Type::top(-1); 3096 rb(env, m, constants().ids.assert, t, b_assert); 3097 t[2] = Type::optpartop(-1); 3098 rb(env, m, constants().ids.assert, t, b_assert); 3099 t[2] = Type::vartop(-1); 3100 rb(env, m, constants().ids.assert, t, b_assert); 3101 t[2] = Type::optvartop(-1); 3102 rb(env, m, constants().ids.assert, t, b_assert); 3103 } 3104 { 3105 std::vector<Type> t(4); 3106 t[0] = Type::parstring(); 3107 t[1] = Type::parstring(); 3108 t[2] = Type::parstring(); 3109 t[3] = Type::top(); 3110 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate); 3111 t[3] = Type::vartop(); 3112 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate); 3113 t[3] = Type::optvartop(); 3114 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate); 3115 t[3] = Type::top(-1); 3116 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate); 3117 t[3] = Type::vartop(-1); 3118 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate); 3119 t[3] = Type::optvartop(-1); 3120 rb(env, m, constants().ids.mzn_deprecate, t, b_mzn_deprecate); 3121 } 3122 { 3123 rb(env, m, constants().ids.mzn_symmetry_breaking_constraint, {Type::varbool()}, 3124 b_mzn_symmetry_breaking_constraint); 3125 rb(env, m, constants().ids.mzn_redundant_constraint, {Type::varbool()}, 3126 b_mzn_redundant_constraint); 3127 } 3128 { 3129 std::vector<Type> t(1); 3130 t[0] = Type::parstring(); 3131 rb(env, m, ASTString("abort"), t, b_abort); 3132 rb(env, m, constants().ids.trace, t, b_trace); 3133 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3134 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3135 } 3136 { 3137 std::vector<Type> t; 3138 rb(env, m, ASTString("logstream_to_string"), t, b_logstream); 3139 } 3140 { 3141 std::vector<Type> t(2); 3142 t[0] = Type::parstring(); 3143 t[1] = Type::top(); 3144 rb(env, m, constants().ids.trace, t, b_trace); 3145 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3146 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3147 t[1] = Type::optpartop(); 3148 rb(env, m, constants().ids.trace, t, b_trace); 3149 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3150 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3151 t[1] = Type::vartop(); 3152 rb(env, m, constants().ids.trace, t, b_trace); 3153 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3154 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3155 t[1] = Type::optvartop(); 3156 rb(env, m, constants().ids.trace, t, b_trace); 3157 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3158 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3159 t[1] = Type::top(-1); 3160 rb(env, m, constants().ids.trace, t, b_trace); 3161 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3162 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3163 t[1] = Type::optpartop(-1); 3164 rb(env, m, constants().ids.trace, t, b_trace); 3165 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3166 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3167 t[1] = Type::vartop(-1); 3168 rb(env, m, constants().ids.trace, t, b_trace); 3169 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3170 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3171 t[1] = Type::optvartop(-1); 3172 rb(env, m, constants().ids.trace, t, b_trace); 3173 rb(env, m, ASTString("trace_stdout"), t, b_trace_stdout); 3174 rb(env, m, ASTString("trace_logstream"), t, b_trace_logstream); 3175 } 3176 { 3177 rb(env, m, ASTString("mzn_in_redundant_constraint"), std::vector<Type>(), 3178 b_in_redundant_constraint); 3179 } 3180 { 3181 std::vector<Type> t_length(1); 3182 t_length[0] = Type::optvartop(-1); 3183 rb(env, m, ASTString("length"), t_length, b_length); 3184 } 3185 { 3186 std::vector<Type> t(1); 3187 t[0] = Type::parbool(); 3188 rb(env, m, constants().ids.bool2int, t, b_bool2int); 3189 } 3190 { 3191 std::vector<Type> t(1); 3192 t[0] = Type::parbool(-1); 3193 rb(env, m, constants().ids.forall, t, b_forall_par); 3194 rb(env, m, constants().ids.exists, t, b_exists_par); 3195 rb(env, m, ASTString("xorall"), t, b_xorall_par); 3196 rb(env, m, ASTString("iffall"), t, b_iffall_par); 3197 } 3198 { rb(env, m, constants().ids.bool_not, {Type::parbool()}, b_not_par); } 3199 { 3200 std::vector<Type> t(2); 3201 t[0] = Type::parbool(-1); 3202 t[1] = Type::parbool(-1); 3203 rb(env, m, constants().ids.clause, t, b_clause_par); 3204 } 3205 { 3206 std::vector<Type> t(1); 3207 t[0] = Type::varsetint(); 3208 rb(env, m, ASTString("ub"), t, b_ub_set); 3209 rb(env, m, ASTString("lb"), t, b_lb_set); 3210 } 3211 { 3212 std::vector<Type> t(1); 3213 t[0] = Type::varsetint(1); 3214 rb(env, m, ASTString("ub_array"), t, b_array_ub_set); 3215 } 3216 { 3217 std::vector<Type> t(1); 3218 t[0] = Type::varint(); 3219 rb(env, m, ASTString("dom"), t, b_dom_varint); 3220 t[0].ot(Type::OT_OPTIONAL); 3221 rb(env, m, ASTString("dom"), t, b_dom_varint); 3222 } 3223 { 3224 std::vector<Type> t(1); 3225 t[0] = Type::varint(-1); 3226 rb(env, m, ASTString("dom_array"), t, b_dom_array); 3227 rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array); 3228 t[0].ot(Type::OT_OPTIONAL); 3229 rb(env, m, ASTString("dom_array"), t, b_dom_array); 3230 rb(env, m, ASTString("dom_bounds_array"), t, b_dom_bounds_array); 3231 } 3232 { 3233 std::vector<Type> t(1); 3234 t[0] = Type::parsetint(); 3235 rb(env, m, ASTString("min"), t, b_min_parsetint); 3236 } 3237 { 3238 std::vector<Type> t(1); 3239 t[0] = Type::parsetint(); 3240 rb(env, m, ASTString("max"), t, b_max_parsetint); 3241 } 3242 { 3243 std::vector<Type> t(1); 3244 t[0] = Type::varint(); 3245 t[0].ot(Type::OT_OPTIONAL); 3246 rb(env, m, ASTString("lb"), t, b_lb_varoptint); 3247 } 3248 { 3249 std::vector<Type> t(1); 3250 t[0] = Type::varint(); 3251 t[0].ot(Type::OT_OPTIONAL); 3252 rb(env, m, ASTString("ub"), t, b_ub_varoptint); 3253 } 3254 { 3255 std::vector<Type> t(1); 3256 t[0] = Type::varint(); 3257 rb(env, m, ASTString("lb"), t, b_lb_varoptint); 3258 } 3259 { 3260 std::vector<Type> t(1); 3261 t[0] = Type::varint(); 3262 rb(env, m, ASTString("ub"), t, b_ub_varoptint); 3263 } 3264 { 3265 std::vector<Type> t(1); 3266 t[0] = Type::varint(-1); 3267 t[0].ot(Type::OT_OPTIONAL); 3268 rb(env, m, ASTString("lb_array"), t, b_array_lb_int); 3269 } 3270 { 3271 std::vector<Type> t(1); 3272 t[0] = Type::varint(-1); 3273 t[0].ot(Type::OT_OPTIONAL); 3274 rb(env, m, ASTString("ub_array"), t, b_array_ub_int); 3275 } 3276 { 3277 std::vector<Type> t(1); 3278 t[0] = Type::varfloat(); 3279 t[0].ot(Type::OT_OPTIONAL); 3280 rb(env, m, ASTString("lb"), t, b_lb_varoptfloat); 3281 } 3282 { 3283 std::vector<Type> t(1); 3284 t[0] = Type::varfloat(); 3285 t[0].ot(Type::OT_OPTIONAL); 3286 rb(env, m, ASTString("ub"), t, b_ub_varoptfloat); 3287 } 3288 { 3289 std::vector<Type> t(1); 3290 t[0] = Type::varfloat(); 3291 rb(env, m, ASTString("lb"), t, b_lb_varoptfloat); 3292 } 3293 { 3294 std::vector<Type> t(1); 3295 t[0] = Type::varfloat(); 3296 rb(env, m, ASTString("ub"), t, b_ub_varoptfloat); 3297 } 3298 { 3299 std::vector<Type> t(1); 3300 t[0] = Type::varfloat(-1); 3301 t[0].ot(Type::OT_OPTIONAL); 3302 rb(env, m, ASTString("lb_array"), t, b_array_lb_float); 3303 } 3304 { 3305 std::vector<Type> t(1); 3306 t[0] = Type::varfloat(-1); 3307 t[0].ot(Type::OT_OPTIONAL); 3308 rb(env, m, ASTString("ub_array"), t, b_array_ub_float); 3309 } 3310 { 3311 std::vector<Type> t(1); 3312 t[0] = Type::parsetint(); 3313 rb(env, m, ASTString("card"), t, b_card); 3314 } 3315 { 3316 std::vector<Type> t(1); 3317 t[0] = Type::parsetint(); 3318 rb(env, m, ASTString("set_to_ranges"), t, b_set_to_ranges_int); 3319 t[0] = Type::parsetfloat(); 3320 rb(env, m, ASTString("set_to_ranges"), t, b_set_to_ranges_float); 3321 } 3322 { 3323 std::vector<Type> t(1); 3324 t[0] = Type::parint(); 3325 rb(env, m, ASTString("abs"), t, b_abs_int); 3326 t[0] = Type::parfloat(); 3327 rb(env, m, ASTString("abs"), t, b_abs_float); 3328 } 3329 { 3330 std::vector<Type> t(1); 3331 t[0] = Type::varint(); 3332 rb(env, m, ASTString("has_bounds"), t, b_has_bounds_int); 3333 } 3334 { 3335 std::vector<Type> t(1); 3336 t[0] = Type::varfloat(); 3337 rb(env, m, ASTString("has_bounds"), t, b_has_bounds_float); 3338 } 3339 { 3340 std::vector<Type> t(1); 3341 t[0] = Type::varsetint(); 3342 rb(env, m, ASTString("has_ub_set"), t, b_has_ub_set); 3343 } 3344 { 3345 std::vector<Type> t(1); 3346 t[0] = Type::optvartop(); 3347 rb(env, m, ASTString("is_fixed"), t, b_is_fixed); 3348 t[0] = Type::varsetint(); 3349 rb(env, m, ASTString("is_fixed"), t, b_is_fixed); 3350 Type setoftop; 3351 setoftop.bt(Type::BT_TOP); 3352 setoftop.st(Type::ST_SET); 3353 setoftop.ti(Type::TI_PAR); 3354 setoftop.ot(Type::OT_PRESENT); 3355 t[0] = setoftop; 3356 rb(env, m, ASTString("is_fixed"), t, b_is_fixed); 3357 } 3358 { 3359 std::vector<Type> t(1); 3360 t[0] = Type::optvartop(-1); 3361 rb(env, m, ASTString("is_fixed"), t, b_is_fixed_array); 3362 } 3363 { 3364 std::vector<Type> t(2); 3365 t[0] = t[1] = Type::optvartop(); 3366 rb(env, m, ASTString("is_same"), t, b_is_same); 3367 } 3368 { 3369 std::vector<Type> t(1); 3370 t[0] = Type::optvartop(); 3371 rb(env, m, ASTString("fix"), t, b_fix_bool); 3372 rb(env, m, ASTString("fix"), t, b_fix_int); 3373 rb(env, m, ASTString("fix"), t, b_fix_set); 3374 rb(env, m, ASTString("fix"), t, b_fix_float); 3375 } 3376 { 3377 std::vector<Type> t(1); 3378 t[0] = Type::optvartop(1); 3379 rb(env, m, ASTString("fix"), t, b_fix_array); 3380 } 3381 { 3382 std::vector<Type> t(2); 3383 t[0] = Type::optvartop(); 3384 t[1] = Type::ann(); 3385 rb(env, m, ASTString("has_ann"), t, b_has_ann); 3386 t[0] = Type::varsetint(); 3387 rb(env, m, ASTString("has_ann"), t, b_has_ann); 3388 Type setoftop; 3389 setoftop.bt(Type::BT_TOP); 3390 setoftop.st(Type::ST_SET); 3391 setoftop.ti(Type::TI_PAR); 3392 setoftop.ot(Type::OT_PRESENT); 3393 t[0] = setoftop; 3394 rb(env, m, ASTString("has_ann"), t, b_has_ann); 3395 } 3396 { 3397 std::vector<Type> t(2); 3398 t[0] = Type::optvartop(); 3399 t[1] = Type::ann(); 3400 rb(env, m, ASTString("annotate"), t, b_annotate); 3401 t[0] = Type::varsetint(); 3402 rb(env, m, ASTString("annotate"), t, b_annotate); 3403 Type setoftop; 3404 setoftop.bt(Type::BT_TOP); 3405 setoftop.st(Type::ST_SET); 3406 setoftop.ti(Type::TI_PAR); 3407 setoftop.ot(Type::OT_PRESENT); 3408 t[0] = setoftop; 3409 rb(env, m, ASTString("annotate"), t, b_annotate); 3410 } 3411 { 3412 std::vector<Type> t(1); 3413 t[0] = Type::parint(); 3414 rb(env, m, ASTString("int2float"), t, b_int2float); 3415 } 3416 { 3417 std::vector<Type> t(1); 3418 t[0] = Type::parfloat(); 3419 rb(env, m, ASTString("ceil"), t, b_ceil); 3420 rb(env, m, ASTString("floor"), t, b_floor); 3421 rb(env, m, ASTString("round"), t, b_round); 3422 rb(env, m, ASTString("log10"), t, b_log10); 3423 rb(env, m, ASTString("log2"), t, b_log2); 3424 rb(env, m, ASTString("ln"), t, b_ln); 3425 rb(env, m, ASTString("exp"), t, b_exp); 3426 rb(env, m, ASTString("sqrt"), t, b_sqrt); 3427 t.push_back(Type::parfloat()); 3428 rb(env, m, ASTString("log"), t, b_log); 3429 rb(env, m, ASTString("pow"), t, b_pow); 3430 } 3431 { 3432 std::vector<Type> t(1); 3433 t[0] = Type::parfloat(1); 3434 rb(env, m, constants().ids.sum, t, b_sum_float); 3435 rb(env, m, ASTString("product"), t, b_product_float); 3436 } 3437 { 3438 std::vector<Type> t(1); 3439 t[0] = Type::parfloat(1); 3440 rb(env, m, ASTString("min"), t, b_float_min); 3441 rb(env, m, ASTString("max"), t, b_float_max); 3442 3443 t[0] = Type::parfloat(); 3444 t.push_back(Type::parfloat()); 3445 rb(env, m, ASTString("min"), t, b_float_min); 3446 rb(env, m, ASTString("max"), t, b_float_max); 3447 } 3448 { 3449 std::vector<Type> t(1); 3450 t[0] = Type::parsetint(); 3451 rb(env, m, ASTString("set2array"), t, b_set2array); 3452 } 3453 { 3454 std::vector<Type> t(1); 3455 t[0] = Type::parstring(); 3456 rb(env, m, ASTString("string_length"), t, b_string_length); 3457 } 3458 { rb(env, m, ASTString("file_path"), std::vector<Type>(), b_file_path); } 3459 { 3460 std::vector<Type> t(1); 3461 t[0] = Type::vartop(); 3462 rb(env, m, ASTString("show"), t, b_show); 3463 rb(env, m, ASTString("showJSON"), t, b_show_json); 3464 t[0] = Type::vartop(); 3465 t[0].st(Type::ST_SET); 3466 t[0].ot(Type::OT_OPTIONAL); 3467 rb(env, m, ASTString("show"), t, b_show); 3468 rb(env, m, ASTString("showJSON"), t, b_show_json); 3469 t[0] = Type::vartop(-1); 3470 rb(env, m, ASTString("show"), t, b_show); 3471 rb(env, m, ASTString("showJSON"), t, b_show_json); 3472 } 3473 { 3474 std::vector<Type> t(1); 3475 t[0] = Type::parstring(); 3476 rb(env, m, ASTString("showDznId"), t, b_show_dzn_id); 3477 } 3478 { 3479 std::vector<Type> t(3); 3480 t[0] = t[1] = Type::parint(); 3481 t[2] = Type::vartop(); 3482 rb(env, m, ASTString("format"), t, b_format); 3483 t[2] = Type::vartop(); 3484 t[2].st(Type::ST_SET); 3485 t[2].ot(Type::OT_OPTIONAL); 3486 rb(env, m, ASTString("format"), t, b_format); 3487 t[2] = Type::vartop(-1); 3488 rb(env, m, ASTString("format"), t, b_format); 3489 } 3490 { 3491 std::vector<Type> t(2); 3492 t[0] = Type::parint(); 3493 t[1] = Type::vartop(); 3494 rb(env, m, ASTString("format"), t, b_format); 3495 t[1] = Type::vartop(); 3496 t[1].st(Type::ST_SET); 3497 t[1].ot(Type::OT_OPTIONAL); 3498 rb(env, m, ASTString("format"), t, b_format); 3499 t[1] = Type::vartop(-1); 3500 rb(env, m, ASTString("format"), t, b_format); 3501 t[1] = Type::parstring(); 3502 rb(env, m, ASTString("format_justify_string"), t, b_format_justify_string); 3503 } 3504 { 3505 std::vector<Type> t; 3506 rb(env, m, ASTString("outputJSON"), t, b_output_json); 3507 rb(env, m, ASTString("outputJSONParameters"), t, b_output_json_parameters); 3508 } 3509 { 3510 std::vector<Type> t(2); 3511 t[0] = Type::parint(); 3512 t[1] = Type::varint(); 3513 rb(env, m, ASTString("show_int"), t, b_show_int); 3514 } 3515 { 3516 std::vector<Type> t(3); 3517 t[0] = Type::parint(); 3518 t[1] = Type::parint(); 3519 t[2] = Type::varfloat(); 3520 rb(env, m, ASTString("show_float"), t, b_show_float); 3521 } 3522 { 3523 std::vector<Type> t(1); 3524 t[0] = Type::parstring(1); 3525 rb(env, m, ASTString("concat"), t, b_concat); 3526 } 3527 { 3528 std::vector<Type> t(2); 3529 t[0] = Type::parstring(); 3530 t[1] = Type::parstring(1); 3531 rb(env, m, ASTString("join"), t, b_join); 3532 } 3533 { 3534 std::vector<Type> t(2); 3535 t[0] = Type::varint(); 3536 t[1] = Type::varint(); 3537 rb(env, m, ASTString("compute_div_bounds"), t, b_compute_div_bounds); 3538 } 3539 { 3540 std::vector<Type> t(1); 3541 t[0] = Type::parsetint(1); 3542 rb(env, m, ASTString("array_intersect"), t, b_array_intersect); 3543 rb(env, m, ASTString("array_union"), t, b_array_union); 3544 } 3545 { 3546 std::vector<Type> t(1); 3547 t[0] = Type::parint(); 3548 t[0].ot(Type::OT_OPTIONAL); 3549 t[0].bt(Type::BT_TOP); 3550 rb(env, m, ASTString("occurs"), t, b_occurs); 3551 rb(env, m, ASTString("deopt"), t, b_deopt_expr); 3552 t[0].bt(Type::BT_INT); 3553 rb(env, m, ASTString("deopt"), t, b_deopt_int); 3554 t[0].bt(Type::BT_BOOL); 3555 rb(env, m, ASTString("deopt"), t, b_deopt_bool); 3556 t[0].bt(Type::BT_FLOAT); 3557 rb(env, m, ASTString("deopt"), t, b_deopt_float); 3558 t[0].bt(Type::BT_STRING); 3559 rb(env, m, ASTString("deopt"), t, b_deopt_string); 3560 t[0].bt(Type::BT_INT); 3561 t[0].st(Type::ST_SET); 3562 rb(env, m, ASTString("deopt"), t, b_deopt_intset); 3563 } 3564 { 3565 std::vector<Type> t(2); 3566 t[0] = Type::varbot(1); 3567 t[1] = Type::parint(1); 3568 rb(env, m, ASTString("sort_by"), t, b_sort_by_int); 3569 t[0] = Type::bot(1); 3570 rb(env, m, ASTString("sort_by"), t, b_sort_by_int); 3571 t[0].ot(Type::OT_OPTIONAL); 3572 rb(env, m, ASTString("sort_by"), t, b_sort_by_int); 3573 } 3574 { 3575 std::vector<Type> t(2); 3576 t[0] = Type::varbot(1); 3577 t[1] = Type::parfloat(1); 3578 rb(env, m, ASTString("sort_by"), t, b_sort_by_float); 3579 t[0] = Type::bot(1); 3580 rb(env, m, ASTString("sort_by"), t, b_sort_by_float); 3581 t[0].ot(Type::OT_OPTIONAL); 3582 rb(env, m, ASTString("sort_by"), t, b_sort_by_float); 3583 } 3584 { 3585 std::vector<Type> t(1); 3586 t[0] = Type::parint(1); 3587 rb(env, m, ASTString("sort"), t, b_sort); 3588 rb(env, m, ASTString("arg_min"), t, b_arg_min_int); 3589 rb(env, m, ASTString("arg_max"), t, b_arg_max_int); 3590 t[0] = Type::parbool(1); 3591 rb(env, m, ASTString("sort"), t, b_sort); 3592 rb(env, m, ASTString("arg_min"), t, b_arg_min_bool); 3593 rb(env, m, ASTString("arg_max"), t, b_arg_max_bool); 3594 t[0] = Type::parfloat(1); 3595 rb(env, m, ASTString("sort"), t, b_sort); 3596 rb(env, m, ASTString("arg_min"), t, b_arg_min_float); 3597 rb(env, m, ASTString("arg_max"), t, b_arg_max_float); 3598 } 3599 { 3600 std::vector<Type> t(1); 3601 t[0] = Type::parint(1); 3602 rb(env, m, ASTString("inverse"), t, b_inverse, true); 3603 } 3604 { 3605 std::vector<Type> t(1); 3606 t[0] = Type::parfloat(); 3607 rb(env, m, ASTString("atan"), t, b_atan); 3608 } 3609 { 3610 std::vector<Type> t(1); 3611 t[0] = Type::parfloat(); 3612 rb(env, m, ASTString("cos"), t, b_cos); 3613 } 3614 { 3615 std::vector<Type> t(1); 3616 t[0] = Type::parfloat(); 3617 rb(env, m, ASTString("sin"), t, b_sin); 3618 } 3619 { 3620 std::vector<Type> t(1); 3621 t[0] = Type::parfloat(); 3622 rb(env, m, ASTString("asin"), t, b_asin); 3623 } 3624 { 3625 std::vector<Type> t(1); 3626 t[0] = Type::parfloat(); 3627 rb(env, m, ASTString("acos"), t, b_acos); 3628 } 3629 { 3630 std::vector<Type> t(1); 3631 t[0] = Type::parfloat(); 3632 rb(env, m, ASTString("tan"), t, b_tan); 3633 } 3634 { 3635 std::vector<Type> t(2); 3636 t[0] = Type::parfloat(); 3637 t[1] = Type::parfloat(); 3638 rb(env, m, ASTString("normal"), t, b_normal_float_float); 3639 t[0] = Type::parint(); 3640 rb(env, m, ASTString("normal"), t, b_normal_int_float); 3641 } 3642 { 3643 std::vector<Type> t(2); 3644 t[0] = Type::parfloat(); 3645 t[1] = Type::parfloat(); 3646 rb(env, m, ASTString("uniform"), t, b_uniform_float); 3647 t[0] = Type::parint(); 3648 t[1] = Type::parint(); 3649 rb(env, m, ASTString("uniform"), t, b_uniform_int); 3650 } 3651 { 3652 std::vector<Type> t(1); 3653 t[0] = Type::parfloat(); 3654 rb(env, m, ASTString("poisson"), t, b_poisson_float); 3655 t[0] = Type::parint(); 3656 rb(env, m, ASTString("poisson"), t, b_poisson_int); 3657 } 3658 { 3659 std::vector<Type> t(2); 3660 t[0] = Type::parfloat(); 3661 t[1] = Type::parfloat(); 3662 rb(env, m, ASTString("gamma"), t, b_gamma_float_float); 3663 t[0] = Type::parint(); 3664 rb(env, m, ASTString("gamma"), t, b_gamma_int_float); 3665 } 3666 { 3667 std::vector<Type> t(2); 3668 t[0] = Type::parfloat(); 3669 t[1] = Type::parfloat(); 3670 rb(env, m, ASTString("weibull"), t, b_weibull_float_float); 3671 t[0] = Type::parint(); 3672 rb(env, m, ASTString("weibull"), t, b_weibull_int_float); 3673 } 3674 { 3675 std::vector<Type> t(1); 3676 t[0] = Type::parfloat(); 3677 rb(env, m, ASTString("exponential"), t, b_exponential_float); 3678 t[0] = Type::parint(); 3679 rb(env, m, ASTString("exponential"), t, b_exponential_int); 3680 } 3681 { 3682 std::vector<Type> t(2); 3683 t[0] = Type::parfloat(); 3684 t[1] = Type::parfloat(); 3685 rb(env, m, ASTString("lognormal"), t, b_lognormal_float_float); 3686 t[0] = Type::parint(); 3687 rb(env, m, ASTString("lognormal"), t, b_lognormal_int_float); 3688 } 3689 { 3690 std::vector<Type> t(1); 3691 t[0] = Type::parfloat(); 3692 rb(env, m, ASTString("chisquared"), t, b_chisquared_float); 3693 t[0] = Type::parint(); 3694 rb(env, m, ASTString("chisquared"), t, b_chisquared_int); 3695 } 3696 { 3697 std::vector<Type> t(2); 3698 t[0] = Type::parfloat(); 3699 t[1] = Type::parfloat(); 3700 rb(env, m, ASTString("cauchy"), t, b_cauchy_float_float); 3701 t[0] = Type::parint(); 3702 rb(env, m, ASTString("cauchy"), t, b_cauchy_int_float); 3703 } 3704 { 3705 std::vector<Type> t(2); 3706 t[0] = Type::parfloat(); 3707 t[1] = Type::parfloat(); 3708 rb(env, m, ASTString("fdistribution"), t, b_fdistribution_float_float); 3709 t[0] = Type::parint(); 3710 t[1] = Type::parint(); 3711 rb(env, m, ASTString("fdistribution"), t, b_fdistribution_int_int); 3712 } 3713 { 3714 std::vector<Type> t(1); 3715 t[0] = Type::parfloat(); 3716 rb(env, m, ASTString("tdistribution"), t, b_tdistribution_float); 3717 t[0] = Type::parint(); 3718 rb(env, m, ASTString("tdistribution"), t, b_tdistribution_int); 3719 } 3720 { 3721 std::vector<Type> t(1); 3722 t[0] = Type::parint(1); 3723 rb(env, m, ASTString("discrete_distribution"), t, b_discrete_distribution); 3724 } 3725 { 3726 std::vector<Type> t(1); 3727 t[0] = Type::parint(); 3728 rb(env, m, ASTString("bernoulli"), t, b_bernoulli); 3729 } 3730 { 3731 std::vector<Type> t(2); 3732 t[0] = Type::parint(); 3733 t[1] = Type::parfloat(); 3734 rb(env, m, ASTString("binomial"), t, b_binomial); 3735 } 3736 { 3737 std::vector<Type> t(2); 3738 t[0] = Type::parsetint(); 3739 t[1] = Type::parint(); 3740 rb(env, m, ASTString("to_enum"), t, b_to_enum); 3741 rb(env, m, ASTString("enum_next"), t, b_enum_next); 3742 rb(env, m, ASTString("enum_prev"), t, b_enum_prev); 3743 } 3744 { rb(env, m, ASTString("mzn_compiler_version"), std::vector<Type>(), b_mzn_compiler_version); } 3745 { 3746 std::vector<Type> t(2); 3747 t[0] = Type::varint(1); 3748 t[1] = Type::parstring(); 3749 rb(env, m, ASTString("fzn_regular"), t, b_regular_from_string, true); 3750 } 3751 { rb(env, m, ASTString("showCheckerOutput"), {}, b_show_checker_output); } 3752} 3753 3754} // namespace MiniZinc