1 /* Common part of the Prolog interfaces: variables and non-inline functions.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #include "ppl_prolog_common_defs.hh"
25 #include <exception>
26 #include <stdexcept>
27 #include <sstream>
28 #include <climits>
29 #include <typeinfo>
30 
31 namespace Parma_Polyhedra_Library {
32 
33 namespace Interfaces {
34 
35 namespace Prolog {
36 
37 #if PROLOG_TRACK_ALLOCATION || NOISY_PROLOG_TRACK_ALLOCATION
38 
Allocation_Tracker()39 Allocation_Tracker::Allocation_Tracker() {
40 }
41 
~Allocation_Tracker()42 Allocation_Tracker::~Allocation_Tracker() {
43   Set::size_type n = s.size();
44   if (n > 0)
45     std::cerr
46       << "Interfaces::Prolog::Allocation_Tracker: "
47       << n << " object(s) leaked!"
48       << std::endl;
49 }
50 
51 Allocation_Tracker allocation_tracker;
52 
53 #endif // PROLOG_TRACK_ALLOCATION || NOISY_PROLOG_TRACK_ALLOCATION
54 
55 
56 
57 // For the out-of-memory exception.
58 Prolog_atom out_of_memory_exception_atom;
59 
60 // For variables.
61 Prolog_atom a_dollar_VAR;
62 
63 // For linear expressions.
64 Prolog_atom a_plus;
65 Prolog_atom a_minus;
66 Prolog_atom a_asterisk;
67 
68 // To represent rational numbers as fractions.
69 Prolog_atom a_slash;
70 
71 // For constraints.
72 Prolog_atom a_less_than;
73 Prolog_atom a_equal_less_than;
74 Prolog_atom a_equal;
75 Prolog_atom a_greater_than_equal;
76 Prolog_atom a_greater_than;
77 
78 // For congruences.
79 Prolog_atom a_is_congruent_to;
80 Prolog_atom a_modulo;
81 
82 // For generators.
83 Prolog_atom a_line;
84 Prolog_atom a_ray;
85 Prolog_atom a_point;
86 Prolog_atom a_closure_point;
87 
88 // For grid_generators.
89 Prolog_atom a_grid_line;
90 Prolog_atom a_parameter;
91 Prolog_atom a_grid_point;
92 
93 // For artificial_parameters.
94 Prolog_atom a_divided_by;
95 
96 // For the relation between a polyhedron and a constraint.
97 Prolog_atom a_is_disjoint;
98 Prolog_atom a_strictly_intersects;
99 Prolog_atom a_is_included;
100 Prolog_atom a_saturates;
101 
102 // For the relation between a polyhedron and a generator.
103 Prolog_atom a_subsumes;
104 
105 // Denotes a closed interval boundary.
106 Prolog_atom a_c;
107 
108 // Denotes the empty set such as the empty interval or polyhedron.
109 Prolog_atom a_empty;
110 
111 // Denotes the universe polyhedron.
112 Prolog_atom a_universe;
113 
114 // Denotes the maximization mode for optimization problems.
115 Prolog_atom a_max;
116 
117 // Denotes the minimization mode for optimization problems.
118 Prolog_atom a_min;
119 
120 // Denote possible widths of bounded integer types.
121 Prolog_atom a_bits_8;
122 Prolog_atom a_bits_16;
123 Prolog_atom a_bits_32;
124 Prolog_atom a_bits_64;
125 Prolog_atom a_bits_128;
126 
127 // Denote possible representations of bounded integer types.
128 Prolog_atom a_unsigned;
129 Prolog_atom a_signed_2_complement;
130 
131 // Denote possible overflow behavior of bounded integer types.
132 Prolog_atom a_overflow_wraps;
133 Prolog_atom a_overflow_undefined;
134 Prolog_atom a_overflow_impossible;
135 
136 // Denote possible outcomes of MIP and PIP problems solution attempts.
137 Prolog_atom a_unfeasible;
138 Prolog_atom a_unbounded;
139 Prolog_atom a_optimized;
140 
141 // Denotes an open interval boundary.
142 Prolog_atom a_o;
143 
144 // Denotes the constructor that turns two boundaries into a proper interval.
145 Prolog_atom a_i;
146 
147 // Denote the -infinity and +infinity interval boundaries.
148 Prolog_atom a_minf;
149 Prolog_atom a_pinf;
150 
151 // Denote complexity classes.
152 Prolog_atom a_polynomial;
153 Prolog_atom a_simplex;
154 Prolog_atom a_any;
155 
156 // Denote control_parameters.
157 Prolog_atom a_pricing;
158 Prolog_atom a_pricing_steepest_edge_float;
159 Prolog_atom a_pricing_steepest_edge_exact;
160 Prolog_atom a_pricing_textbook;
161 
162 Prolog_atom a_cutting_strategy;
163 Prolog_atom a_cutting_strategy_first;
164 Prolog_atom a_cutting_strategy_deepest;
165 Prolog_atom a_cutting_strategy_all;
166 
167 Prolog_atom a_pivot_row_strategy;
168 Prolog_atom a_pivot_row_strategy_first;
169 Prolog_atom a_pivot_row_strategy_max_column;
170 
171 // Default timeout exception atom.
172 Prolog_atom a_time_out;
173 
174 // "Out of memory" exception atom.
175 Prolog_atom a_out_of_memory;
176 
177 // Boolean constants.
178 Prolog_atom a_true;
179 Prolog_atom a_false;
180 
181 // To build exception terms.
182 Prolog_atom a_ppl_overflow_error;
183 Prolog_atom a_ppl_domain_error;
184 Prolog_atom a_ppl_length_error;
185 Prolog_atom a_ppl_invalid_argument;
186 Prolog_atom a_ppl_logic_error;
187 Prolog_atom a_ppl_representation_error;
188 Prolog_atom a_expected;
189 Prolog_atom a_found;
190 Prolog_atom a_where;
191 
192 const Prolog_Interface_Atom prolog_interface_atoms[] = {
193   { &a_dollar_VAR,               "$VAR" },
194 
195   { &a_plus,                     "+" },
196   { &a_minus,                    "-" },
197   { &a_asterisk,                 "*" },
198 
199   { &a_slash,                    "/" },
200 
201   { &a_equal,                    "=" },
202   { &a_greater_than_equal,       ">=" },
203   { &a_equal_less_than,          "=<" },
204   { &a_greater_than,             ">" },
205   { &a_less_than,                "<" },
206 
207   { &a_is_congruent_to,          "=:=" },
208   { &a_modulo,                   "/" },
209 
210   { &a_divided_by,               "/" },
211 
212   { &a_line,                     "line" },
213   { &a_ray,                      "ray" },
214   { &a_point,                    "point" },
215   { &a_closure_point,            "closure_point" },
216 
217   { &a_grid_line,                "grid_line" },
218   { &a_parameter,                "parameter" },
219   { &a_grid_point,               "grid_point" },
220 
221   { &a_is_disjoint,              "is_disjoint" },
222   { &a_strictly_intersects,      "strictly_intersects" },
223   { &a_is_included,              "is_included" },
224   { &a_saturates,                "saturates" },
225 
226   { &a_subsumes,                 "subsumes" },
227 
228   { &a_c,                        "c" },
229 
230   { &a_empty,                    "empty" },
231   { &a_universe,                 "universe" },
232 
233   { &a_max,                      "max" },
234   { &a_min,                      "min" },
235 
236   { &a_bits_8,                   "bits_8" },
237   { &a_bits_16,                  "bits_16" },
238   { &a_bits_32,                  "bits_32" },
239   { &a_bits_64,                  "bits_64" },
240   { &a_bits_128,                 "bits_128" },
241 
242   { &a_unsigned,                 "unsigned" },
243   { &a_signed_2_complement,      "signed_2_complement" },
244 
245   { &a_overflow_wraps,           "overflow_wraps" },
246   { &a_overflow_undefined,       "overflow_undefined" },
247   { &a_overflow_impossible,      "overflow_impossible" },
248 
249   { &a_unfeasible,               "unfeasible" },
250   { &a_unbounded,                "unbounded" },
251   { &a_optimized,                "optimized" },
252 
253   { &a_o,                        "o" },
254   { &a_i,                        "i" },
255 
256   { &a_minf,                     "minf" },
257   { &a_pinf,                     "pinf" },
258 
259   { &a_polynomial,               "polynomial" },
260   { &a_simplex,                  "simplex" },
261   { &a_any,                      "any" },
262 
263   { &a_pricing,                  "pricing" },
264   { &a_pricing_steepest_edge_float,
265                                  "pricing_steepest_edge_float" },
266   { &a_pricing_steepest_edge_exact,
267                                  "pricing_steepest_edge_exact" },
268   { &a_pricing_textbook,         "pricing_textbook" },
269 
270   { &a_cutting_strategy,         "cutting_strategy" },
271   { &a_cutting_strategy_first,   "cutting_strategy_first" },
272   { &a_cutting_strategy_deepest, "cutting_strategy_deepest" },
273   { &a_cutting_strategy_all,     "cutting_strategy_all" },
274 
275   { &a_pivot_row_strategy,       "pivot_row_strategy" },
276   { &a_pivot_row_strategy_first, "pivot_row_strategy_first" },
277   { &a_pivot_row_strategy_max_column,
278                                  "pivot_row_strategy_max_column" },
279 
280   { &a_time_out,                 "time_out" },
281   { &a_out_of_memory,            "out_of_memory" },
282 
283   { &a_true,                     "true" },
284   { &a_false,                    "false" },
285 
286   { &a_ppl_invalid_argument,     "ppl_invalid_argument" },
287   { &a_ppl_overflow_error,       "ppl_overflow_error" },
288   { &a_ppl_domain_error,         "ppl_domain_error" },
289   { &a_ppl_length_error,         "ppl_length_error" },
290   { &a_ppl_invalid_argument,     "ppl_invalid_argument" },
291   { &a_ppl_logic_error,          "ppl_logic_error" },
292   { &a_ppl_representation_error, "ppl_representation_error" },
293   { &a_expected,                 "expected" },
294   { &a_found,                    "found" },
295   { &a_where,                    "where" },
296   { 0,                           0 }
297 };
298 
299 Prolog_term_ref
Prolog_atom_term_from_string(const char * s)300 Prolog_atom_term_from_string(const char* s) {
301   Prolog_term_ref t = Prolog_new_term_ref();
302   Prolog_put_atom(t, Prolog_atom_from_string(s));
303   return t;
304 }
305 
306 void
handle_exception(const Prolog_unsigned_out_of_range & e)307 handle_exception(const Prolog_unsigned_out_of_range& e) {
308   Prolog_term_ref found = Prolog_new_term_ref();
309   Prolog_construct_compound(found, a_found, e.term());
310 
311   Prolog_term_ref max = Prolog_new_term_ref();
312   Prolog_put_ulong(max, e.max());
313   Prolog_construct_compound(max,
314                             Prolog_atom_from_string("unsigned_integer"
315                                                     "_less_or_equal"),
316                             max);
317   Prolog_term_ref expected = Prolog_new_term_ref();
318   Prolog_construct_compound(expected, a_expected, max);
319 
320   Prolog_term_ref where = Prolog_new_term_ref();
321   Prolog_construct_compound(where, a_where,
322                             Prolog_atom_term_from_string(e.where()));
323 
324   Prolog_term_ref exception_term = Prolog_new_term_ref();
325   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
326                             found, expected, where);
327   Prolog_raise_exception(exception_term);
328 }
329 
330 void
handle_exception(const not_unsigned_integer & e)331 handle_exception(const not_unsigned_integer& e) {
332   Prolog_term_ref found = Prolog_new_term_ref();
333   Prolog_construct_compound(found, a_found, e.term());
334 
335   Prolog_term_ref expected = Prolog_new_term_ref();
336   Prolog_construct_compound(expected, a_expected,
337                             Prolog_atom_term_from_string("unsigned_integer"));
338 
339   Prolog_term_ref where = Prolog_new_term_ref();
340   Prolog_construct_compound(where, a_where,
341                             Prolog_atom_term_from_string(e.where()));
342 
343   Prolog_term_ref exception_term = Prolog_new_term_ref();
344   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
345                             found, expected, where);
346   Prolog_raise_exception(exception_term);
347 }
348 
349 void
handle_exception(const non_linear & e)350 handle_exception(const non_linear& e) {
351   Prolog_term_ref found = Prolog_new_term_ref();
352   Prolog_construct_compound(found, a_found, e.term());
353 
354   Prolog_term_ref expected = Prolog_new_term_ref();
355   Prolog_construct_compound(expected, a_expected,
356                             Prolog_atom_term_from_string
357                             ("linear_expression_or_constraint"));
358 
359   Prolog_term_ref where = Prolog_new_term_ref();
360   Prolog_construct_compound(where, a_where,
361                             Prolog_atom_term_from_string(e.where()));
362 
363   Prolog_term_ref exception_term = Prolog_new_term_ref();
364   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
365                             found, expected, where);
366   Prolog_raise_exception(exception_term);
367 }
368 
369 void
handle_exception(const not_a_variable & e)370 handle_exception(const not_a_variable& e) {
371   Prolog_term_ref found = Prolog_new_term_ref();
372   Prolog_construct_compound(found, a_found,
373                             e.term());
374 
375   Prolog_term_ref expected = Prolog_new_term_ref();
376   Prolog_construct_compound(expected, a_expected,
377                             Prolog_atom_term_from_string
378                             ("$VAR(unsigned_integer)"));
379 
380   Prolog_term_ref where = Prolog_new_term_ref();
381   Prolog_construct_compound(where, a_where,
382                             Prolog_atom_term_from_string(e.where()));
383 
384   Prolog_term_ref exception_term = Prolog_new_term_ref();
385   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
386                             found, expected, where);
387   Prolog_raise_exception(exception_term);
388 }
389 
390 void
handle_exception(const not_an_integer & e)391 handle_exception(const not_an_integer& e) {
392   Prolog_term_ref found = Prolog_new_term_ref();
393   Prolog_construct_compound(found, a_found, e.term());
394 
395   Prolog_term_ref expected = Prolog_new_term_ref();
396   Prolog_construct_compound(expected, a_expected,
397                             Prolog_atom_term_from_string("integer"));
398 
399   Prolog_term_ref where = Prolog_new_term_ref();
400   Prolog_construct_compound(where, a_where,
401                             Prolog_atom_term_from_string(e.where()));
402 
403   Prolog_term_ref exception_term = Prolog_new_term_ref();
404   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
405                             found, expected, where);
406   Prolog_raise_exception(exception_term);
407 }
408 
409 void
handle_exception(const ppl_handle_mismatch & e)410 handle_exception(const ppl_handle_mismatch& e) {
411   Prolog_term_ref found = Prolog_new_term_ref();
412   Prolog_construct_compound(found, a_found, e.term());
413 
414   Prolog_term_ref expected = Prolog_new_term_ref();
415   Prolog_construct_compound(expected, a_expected,
416                             Prolog_atom_term_from_string("handle"));
417 
418   Prolog_term_ref where = Prolog_new_term_ref();
419   Prolog_construct_compound(where, a_where,
420                             Prolog_atom_term_from_string(e.where()));
421 
422   Prolog_term_ref exception_term = Prolog_new_term_ref();
423   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
424                             found, expected, where);
425   Prolog_raise_exception(exception_term);
426 }
427 
428 void
handle_exception(const not_an_optimization_mode & e)429 handle_exception(const not_an_optimization_mode& e) {
430   Prolog_term_ref found = Prolog_new_term_ref();
431   Prolog_construct_compound(found, a_found, e.term());
432 
433   Prolog_term_ref expected = Prolog_new_term_ref();
434   Prolog_put_nil(expected);
435   Prolog_construct_cons(expected,
436                         Prolog_atom_term_from_string("max"), expected);
437   Prolog_construct_cons(expected,
438                         Prolog_atom_term_from_string("min"), expected);
439   Prolog_construct_compound(expected, a_expected, expected);
440 
441   Prolog_term_ref where = Prolog_new_term_ref();
442   Prolog_construct_compound(where, a_where,
443                             Prolog_atom_term_from_string(e.where()));
444   Prolog_term_ref exception_term = Prolog_new_term_ref();
445   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
446                             found, expected, where);
447   Prolog_raise_exception(exception_term);
448 }
449 
450 void
handle_exception(const not_a_complexity_class & e)451 handle_exception(const not_a_complexity_class& e) {
452   Prolog_term_ref found = Prolog_new_term_ref();
453   Prolog_construct_compound(found, a_found, e.term());
454 
455   Prolog_term_ref expected = Prolog_new_term_ref();
456   Prolog_put_nil(expected);
457   Prolog_construct_cons(expected,
458                         Prolog_atom_term_from_string("polynomial"), expected);
459   Prolog_construct_cons(expected,
460                         Prolog_atom_term_from_string("simplex"), expected);
461   Prolog_construct_cons(expected,
462                         Prolog_atom_term_from_string("any"), expected);
463   Prolog_construct_compound(expected, a_expected, expected);
464 
465   Prolog_term_ref where = Prolog_new_term_ref();
466   Prolog_construct_compound(where, a_where,
467                             Prolog_atom_term_from_string(e.where()));
468   Prolog_term_ref exception_term = Prolog_new_term_ref();
469   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
470                             found, expected, where);
471   Prolog_raise_exception(exception_term);
472 }
473 
474 void
handle_exception(const not_a_control_parameter_name & e)475   handle_exception(const not_a_control_parameter_name& e) {
476   Prolog_term_ref found = Prolog_new_term_ref();
477   Prolog_construct_compound(found, a_found, e.term());
478 
479   Prolog_term_ref expected = Prolog_new_term_ref();
480   Prolog_put_nil(expected);
481   Prolog_construct_cons(expected,
482                         Prolog_atom_term_from_string("pricing"), expected);
483 
484   Prolog_term_ref where = Prolog_new_term_ref();
485   Prolog_construct_compound(where, a_where,
486                             Prolog_atom_term_from_string(e.where()));
487   Prolog_term_ref exception_term = Prolog_new_term_ref();
488   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
489                             found, expected, where);
490   Prolog_raise_exception(exception_term);
491 }
492 
493 void
handle_exception(const not_a_control_parameter_value & e)494   handle_exception(const not_a_control_parameter_value& e) {
495   Prolog_term_ref found = Prolog_new_term_ref();
496   Prolog_construct_compound(found, a_found, e.term());
497 
498   Prolog_term_ref expected = Prolog_new_term_ref();
499   Prolog_put_nil(expected);
500   Prolog_construct_cons(expected,
501                         Prolog_atom_term_from_string("pricing_steepest_edge_float"),
502                         expected);
503   Prolog_construct_cons(expected,
504                         Prolog_atom_term_from_string("pricing_steepest_edge_exact"),
505                         expected);
506   Prolog_construct_cons(expected,
507                         Prolog_atom_term_from_string("pricing_textbook"),
508                         expected);
509 
510   Prolog_term_ref where = Prolog_new_term_ref();
511   Prolog_construct_compound(where, a_where,
512                             Prolog_atom_term_from_string(e.where()));
513   Prolog_term_ref exception_term = Prolog_new_term_ref();
514   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
515                             found, expected, where);
516   Prolog_raise_exception(exception_term);
517 }
518 
519 void
handle_exception(const not_a_pip_problem_control_parameter_name & e)520   handle_exception(const not_a_pip_problem_control_parameter_name& e) {
521   Prolog_term_ref found = Prolog_new_term_ref();
522   Prolog_construct_compound(found, a_found, e.term());
523 
524   Prolog_term_ref expected = Prolog_new_term_ref();
525   Prolog_put_nil(expected);
526   Prolog_construct_cons(expected,
527                         Prolog_atom_term_from_string("cutting_strategy"),
528                         expected);
529   Prolog_construct_cons(expected,
530                         Prolog_atom_term_from_string("pivot_row_strategy"),
531                         expected);
532 
533   Prolog_term_ref where = Prolog_new_term_ref();
534   Prolog_construct_compound(where, a_where,
535                             Prolog_atom_term_from_string(e.where()));
536   Prolog_term_ref exception_term = Prolog_new_term_ref();
537   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
538                             found, expected, where);
539   Prolog_raise_exception(exception_term);
540 }
541 
542 void
handle_exception(const not_a_pip_problem_control_parameter_value & e)543   handle_exception(const not_a_pip_problem_control_parameter_value& e) {
544   Prolog_term_ref found = Prolog_new_term_ref();
545   Prolog_construct_compound(found, a_found, e.term());
546 
547   Prolog_term_ref expected = Prolog_new_term_ref();
548   Prolog_put_nil(expected);
549   Prolog_construct_cons(expected,
550                         Prolog_atom_term_from_string("cutting_strategy_first"),
551                         expected);
552   Prolog_construct_cons(expected,
553                         Prolog_atom_term_from_string("cutting_strategy_deepest"),
554                         expected);
555    Prolog_construct_cons(expected,
556                         Prolog_atom_term_from_string("cutting_strategy_all"),
557                         expected);
558    Prolog_construct_cons(expected,
559                         Prolog_atom_term_from_string("pivot_row_strategy_first"),
560                         expected);
561     Prolog_construct_cons(expected,
562                         Prolog_atom_term_from_string("pivot_row_strategy_max_column"),
563                         expected);
564  Prolog_term_ref where = Prolog_new_term_ref();
565   Prolog_construct_compound(where, a_where,
566                             Prolog_atom_term_from_string(e.where()));
567   Prolog_term_ref exception_term = Prolog_new_term_ref();
568   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
569                             found, expected, where);
570   Prolog_raise_exception(exception_term);
571 }
572 
573 void
handle_exception(const not_universe_or_empty & e)574 handle_exception(const not_universe_or_empty& e) {
575   Prolog_term_ref found = Prolog_new_term_ref();
576   Prolog_construct_compound(found, a_found, e.term());
577 
578   Prolog_term_ref expected = Prolog_new_term_ref();
579   Prolog_put_nil(expected);
580   Prolog_construct_cons(expected,
581                         Prolog_atom_term_from_string("universe"), expected);
582   Prolog_construct_cons(expected,
583                         Prolog_atom_term_from_string("empty"), expected);
584   Prolog_construct_compound(expected, a_expected, expected);
585 
586   Prolog_term_ref where = Prolog_new_term_ref();
587   Prolog_construct_compound(where, a_where,
588                             Prolog_atom_term_from_string(e.where()));
589   Prolog_term_ref exception_term = Prolog_new_term_ref();
590   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
591                             found, expected, where);
592   Prolog_raise_exception(exception_term);
593 }
594 
595 void
handle_exception(const not_a_boolean & e)596 handle_exception(const not_a_boolean& e) {
597   Prolog_term_ref found = Prolog_new_term_ref();
598   Prolog_construct_compound(found, a_found, e.term());
599 
600   Prolog_term_ref expected = Prolog_new_term_ref();
601   Prolog_put_nil(expected);
602   Prolog_construct_cons(expected,
603                         Prolog_atom_term_from_string("true"), expected);
604   Prolog_construct_cons(expected,
605                         Prolog_atom_term_from_string("false"), expected);
606   Prolog_construct_compound(expected, a_expected, expected);
607 
608   Prolog_term_ref where = Prolog_new_term_ref();
609   Prolog_construct_compound(where, a_where,
610                             Prolog_atom_term_from_string(e.where()));
611   Prolog_term_ref exception_term = Prolog_new_term_ref();
612   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
613                             found, expected, where);
614   Prolog_raise_exception(exception_term);
615 }
616 
617 void
handle_exception(const not_a_bounded_integer_type_width & e)618 handle_exception(const not_a_bounded_integer_type_width& e) {
619   Prolog_term_ref found = Prolog_new_term_ref();
620   Prolog_construct_compound(found, a_found, e.term());
621 
622   Prolog_term_ref expected = Prolog_new_term_ref();
623   Prolog_put_nil(expected);
624   Prolog_construct_cons(expected,
625                         Prolog_atom_term_from_string("bits_8"), expected);
626   Prolog_construct_cons(expected,
627                         Prolog_atom_term_from_string("bits_16"), expected);
628   Prolog_construct_cons(expected,
629                         Prolog_atom_term_from_string("bits_32"), expected);
630   Prolog_construct_cons(expected,
631                         Prolog_atom_term_from_string("bits_64"), expected);
632   Prolog_construct_cons(expected,
633                         Prolog_atom_term_from_string("bits_128"), expected);
634   Prolog_construct_compound(expected, a_expected, expected);
635 
636   Prolog_term_ref where = Prolog_new_term_ref();
637   Prolog_construct_compound(where, a_where,
638                             Prolog_atom_term_from_string(e.where()));
639   Prolog_term_ref exception_term = Prolog_new_term_ref();
640   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
641                             found, expected, where);
642   Prolog_raise_exception(exception_term);
643 }
644 
645 void
handle_exception(const not_a_bounded_integer_type_representation & e)646 handle_exception(const not_a_bounded_integer_type_representation& e) {
647   Prolog_term_ref found = Prolog_new_term_ref();
648   Prolog_construct_compound(found, a_found, e.term());
649 
650   Prolog_term_ref expected = Prolog_new_term_ref();
651   Prolog_put_nil(expected);
652   Prolog_construct_cons(expected,
653                         Prolog_atom_term_from_string("unsigned"), expected);
654   Prolog_construct_cons(expected,
655                         Prolog_atom_term_from_string("signed_2_complement"),
656                         expected);
657   Prolog_construct_compound(expected, a_expected, expected);
658 
659   Prolog_term_ref where = Prolog_new_term_ref();
660   Prolog_construct_compound(where, a_where,
661                             Prolog_atom_term_from_string(e.where()));
662   Prolog_term_ref exception_term = Prolog_new_term_ref();
663   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
664                             found, expected, where);
665   Prolog_raise_exception(exception_term);
666 }
667 
668 void
handle_exception(const not_a_bounded_integer_type_overflow & e)669 handle_exception(const not_a_bounded_integer_type_overflow& e) {
670   Prolog_term_ref found = Prolog_new_term_ref();
671   Prolog_construct_compound(found, a_found, e.term());
672 
673   Prolog_term_ref expected = Prolog_new_term_ref();
674   Prolog_put_nil(expected);
675   Prolog_construct_cons(expected,
676                         Prolog_atom_term_from_string("overflow_wraps"),
677                         expected);
678   Prolog_construct_cons(expected,
679                         Prolog_atom_term_from_string("overflow_undefined"),
680                         expected);
681   Prolog_construct_cons(expected,
682                         Prolog_atom_term_from_string("overflow_impossible"),
683                         expected);
684   Prolog_construct_compound(expected, a_expected, expected);
685 
686   Prolog_term_ref where = Prolog_new_term_ref();
687   Prolog_construct_compound(where, a_where,
688                             Prolog_atom_term_from_string(e.where()));
689   Prolog_term_ref exception_term = Prolog_new_term_ref();
690   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
691                             found, expected, where);
692   Prolog_raise_exception(exception_term);
693 }
694 
695 void
handle_exception(const not_a_relation & e)696 handle_exception(const not_a_relation& e) {
697   Prolog_term_ref found = Prolog_new_term_ref();
698   Prolog_construct_compound(found, a_found, e.term());
699 
700   Prolog_term_ref expected = Prolog_new_term_ref();
701   Prolog_put_nil(expected);
702   Prolog_construct_cons(expected,
703                         Prolog_atom_term_from_string("="), expected);
704   Prolog_construct_cons(expected,
705                         Prolog_atom_term_from_string(">="), expected);
706   Prolog_construct_cons(expected,
707                         Prolog_atom_term_from_string("=<"), expected);
708   Prolog_construct_cons(expected,
709                         Prolog_atom_term_from_string(">"), expected);
710   Prolog_construct_cons(expected,
711                         Prolog_atom_term_from_string("<"), expected);
712   Prolog_construct_compound(expected, a_expected, expected);
713 
714   Prolog_term_ref where = Prolog_new_term_ref();
715   Prolog_construct_compound(where, a_where,
716                             Prolog_atom_term_from_string(e.where()));
717   Prolog_term_ref exception_term = Prolog_new_term_ref();
718   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
719                             found, expected, where);
720   Prolog_raise_exception(exception_term);
721 }
722 
723 void
handle_exception(const not_a_nil_terminated_list & e)724 handle_exception(const not_a_nil_terminated_list& e) {
725   Prolog_term_ref found = Prolog_new_term_ref();
726   Prolog_construct_compound(found, a_found, e.term());
727 
728   Prolog_term_ref expected = Prolog_new_term_ref();
729   Prolog_put_nil(expected);
730   Prolog_construct_cons(expected,
731                         Prolog_atom_term_from_string
732                         ("Prolog_list"), expected);
733   Prolog_construct_compound(expected, a_expected, expected);
734 
735   Prolog_term_ref where = Prolog_new_term_ref();
736   Prolog_construct_compound(where, a_where,
737                             Prolog_atom_term_from_string(e.where()));
738   Prolog_term_ref exception_term = Prolog_new_term_ref();
739   Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
740                             found, expected, where);
741   Prolog_raise_exception(exception_term);
742 }
743 
744 void
handle_exception(const PPL_integer_out_of_range & e)745 handle_exception(const PPL_integer_out_of_range& e) {
746   Prolog_term_ref where = Prolog_new_term_ref();
747   Prolog_construct_compound(where, a_where,
748                             Prolog_atom_term_from_string("Coefficient_to_integer_term"));
749 
750   Prolog_term_ref exception_term = Prolog_new_term_ref();
751   std::ostringstream s;
752   s << e.value();
753   std::string str = s.str();
754   Prolog_construct_compound(exception_term, a_ppl_representation_error,
755                             Prolog_atom_term_from_string(str.c_str()),
756                             where);
757   Prolog_raise_exception(exception_term);
758 }
759 
760 void
handle_exception(const unknown_interface_error & e)761 handle_exception(const unknown_interface_error& e) {
762   Prolog_term_ref et = Prolog_new_term_ref();
763   Prolog_put_atom_chars(et, e.where());
764   Prolog_raise_exception(et);
765 }
766 
767 void
handle_exception(const std::overflow_error & e)768 handle_exception(const std::overflow_error& e) {
769   Prolog_term_ref et = Prolog_new_term_ref();
770   Prolog_construct_compound(et, a_ppl_overflow_error,
771                             Prolog_atom_term_from_string(e.what()));
772   Prolog_raise_exception(et);
773 }
774 
775 void
handle_exception(const std::domain_error & e)776 handle_exception(const std::domain_error& e) {
777   Prolog_term_ref et = Prolog_new_term_ref();
778   Prolog_construct_compound(et, a_ppl_domain_error,
779                             Prolog_atom_term_from_string(e.what()));
780   Prolog_raise_exception(et);
781 }
782 
783 void
handle_exception(const std::length_error & e)784 handle_exception(const std::length_error& e) {
785   Prolog_term_ref et = Prolog_new_term_ref();
786   Prolog_construct_compound(et, a_ppl_length_error,
787                             Prolog_atom_term_from_string(e.what()));
788   Prolog_raise_exception(et);
789 }
790 
791 void
handle_exception(const std::invalid_argument & e)792 handle_exception(const std::invalid_argument& e) {
793   Prolog_term_ref et = Prolog_new_term_ref();
794   Prolog_construct_compound(et, a_ppl_invalid_argument,
795                             Prolog_atom_term_from_string(e.what()));
796   Prolog_raise_exception(et);
797 }
798 
799 void
handle_exception(const std::logic_error & e)800 handle_exception(const std::logic_error& e) {
801   Prolog_term_ref et = Prolog_new_term_ref();
802   Prolog_construct_compound(et, a_ppl_logic_error,
803                             Prolog_atom_term_from_string(e.what()));
804   Prolog_raise_exception(et);
805 }
806 
807 void
handle_exception(const std::bad_alloc &)808 handle_exception(const std::bad_alloc&) {
809   Prolog_term_ref et = Prolog_new_term_ref();
810   Prolog_put_atom(et, out_of_memory_exception_atom);
811   Prolog_raise_exception(et);
812 }
813 
814 void
handle_exception(const std::exception & e)815 handle_exception(const std::exception& e) {
816   Prolog_term_ref et = Prolog_new_term_ref();
817   Prolog_put_atom_chars(et, e.what());
818   Prolog_raise_exception(et);
819 }
820 
821 void
handle_exception()822 handle_exception() {
823   Prolog_term_ref et = Prolog_new_term_ref();
824   Prolog_put_atom_chars(et, "PPL bug: unknown exception raised");
825   Prolog_raise_exception(et);
826 }
827 
828 Parma_Polyhedra_Library::Watchdog* p_timeout_object = 0;
829 
830 typedef
831 Parma_Polyhedra_Library::Threshold_Watcher
832 <Parma_Polyhedra_Library::Weightwatch_Traits> Weightwatch;
833 
834 Weightwatch* p_deterministic_timeout_object = 0;
835 
836 void
reset_timeout()837 reset_timeout() {
838   if (p_timeout_object) {
839     delete p_timeout_object;
840     p_timeout_object = 0;
841     abandon_expensive_computations = 0;
842   }
843 }
844 
845 void
reset_deterministic_timeout()846 reset_deterministic_timeout() {
847   if (p_deterministic_timeout_object) {
848     delete p_deterministic_timeout_object;
849     p_deterministic_timeout_object = 0;
850     abandon_expensive_computations = 0;
851   }
852 }
853 
854 Prolog_atom timeout_exception_atom;
855 
856 void
handle_exception(const timeout_exception &)857 handle_exception(const timeout_exception&) {
858   assert(p_timeout_object);
859   reset_timeout();
860   Prolog_term_ref et = Prolog_new_term_ref();
861   Prolog_put_atom(et, timeout_exception_atom);
862   Prolog_raise_exception(et);
863 }
864 
865 void
handle_exception(const deterministic_timeout_exception &)866 handle_exception(const deterministic_timeout_exception&) {
867   assert(p_deterministic_timeout_object);
868   reset_deterministic_timeout();
869   Prolog_term_ref et = Prolog_new_term_ref();
870   Prolog_put_atom(et, timeout_exception_atom);
871   Prolog_raise_exception(et);
872 }
873 
874 Prolog_term_ref
variable_term(dimension_type varid)875 variable_term(dimension_type varid) {
876   Prolog_term_ref v = Prolog_new_term_ref();
877   Prolog_put_ulong(v, varid);
878   Prolog_term_ref t = Prolog_new_term_ref();
879   Prolog_construct_compound(t, a_dollar_VAR, v);
880   return t;
881 }
882 
883 Prolog_atom
term_to_boolean(Prolog_term_ref t,const char * where)884 term_to_boolean(Prolog_term_ref t, const char* where) {
885   if (Prolog_is_atom(t)) {
886     Prolog_atom name;
887     if (Prolog_get_atom_name(t, &name)
888         && (name == a_true || name == a_false))
889       return name;
890   }
891   throw not_a_boolean(t, where);
892 }
893 
894 Prolog_atom
term_to_universe_or_empty(Prolog_term_ref t,const char * where)895 term_to_universe_or_empty(Prolog_term_ref t, const char* where) {
896   if (Prolog_is_atom(t)) {
897     Prolog_atom name;
898     if (Prolog_get_atom_name(t, &name)
899         && (name == a_universe || name == a_empty))
900       return name;
901   }
902   throw not_universe_or_empty(t, where);
903 }
904 
905 Coefficient
integer_term_to_Coefficient(Prolog_term_ref t)906 integer_term_to_Coefficient(Prolog_term_ref t) {
907   PPL_DIRTY_TEMP_COEFFICIENT(n);
908   assert(Prolog_is_integer(t));
909   if (!Prolog_get_Coefficient(t, n))
910     abort();
911   return n;
912 }
913 
914 Prolog_term_ref
Coefficient_to_integer_term(const Coefficient & n)915 Coefficient_to_integer_term(const Coefficient& n) {
916   Prolog_term_ref t = Prolog_new_term_ref();
917   if (!Prolog_put_Coefficient(t, n))
918     abort();
919   return t;
920 }
921 
922 bool
unify_long(Prolog_term_ref t,long l)923 unify_long(Prolog_term_ref t, long l) {
924   Prolog_term_ref t_l = Prolog_new_term_ref();
925   return Prolog_put_long(t_l, l) && Prolog_unify(t, t_l);
926 }
927 
928 bool
unify_ulong(Prolog_term_ref t,unsigned long l)929 unify_ulong(Prolog_term_ref t, unsigned long l) {
930   Prolog_term_ref t_l = Prolog_new_term_ref();
931   return Prolog_put_ulong(t_l, l) && Prolog_unify(t, t_l);
932 }
933 
934 Linear_Expression
build_linear_expression(Prolog_term_ref t,const char * where)935 build_linear_expression(Prolog_term_ref t, const char* where) {
936   if (Prolog_is_integer(t))
937     return Linear_Expression(integer_term_to_Coefficient(t));
938   else if (Prolog_is_compound(t)) {
939     Prolog_atom functor;
940     int arity;
941     Prolog_get_compound_name_arity(t, &functor, &arity);
942     switch (arity) {
943     case 1:
944       {
945         Prolog_term_ref arg = Prolog_new_term_ref();
946         Prolog_get_arg(1, t, arg);
947         if (functor == a_minus)
948           // Unary minus.
949           return -build_linear_expression(arg, where);
950         else if (functor == a_dollar_VAR)
951           // Variable.
952           return Variable(term_to_unsigned<dimension_type>(arg, where));
953       }
954       break;
955     case 2:
956       {
957         Prolog_term_ref arg1 = Prolog_new_term_ref();
958         Prolog_term_ref arg2 = Prolog_new_term_ref();
959         Prolog_get_arg(1, t, arg1);
960         Prolog_get_arg(2, t, arg2);
961         if (functor == a_plus)
962           // Plus.
963           if (Prolog_is_integer(arg1))
964             return integer_term_to_Coefficient(arg1)
965               + build_linear_expression(arg2, where);
966           else if (Prolog_is_integer(arg2))
967             return build_linear_expression(arg1, where)
968               + integer_term_to_Coefficient(arg2);
969           else
970             return build_linear_expression(arg1, where)
971               + build_linear_expression(arg2, where);
972         else if (functor == a_minus)
973           // Minus.
974           if (Prolog_is_integer(arg1))
975             return integer_term_to_Coefficient(arg1)
976               - build_linear_expression(arg2, where);
977           else if (Prolog_is_integer(arg2))
978             return build_linear_expression(arg1, where)
979               - integer_term_to_Coefficient(arg2);
980           else
981             return build_linear_expression(arg1, where)
982               - build_linear_expression(arg2, where);
983         else if (functor == a_asterisk) {
984           // Times.
985           if (Prolog_is_integer(arg1))
986             return integer_term_to_Coefficient(arg1)
987               * build_linear_expression(arg2, where);
988           else if (Prolog_is_integer(arg2))
989             return build_linear_expression(arg1, where)
990               * integer_term_to_Coefficient(arg2);
991         }
992       }
993     }
994   }
995   // Invalid.
996   throw non_linear(t, where);
997 }
998 
999 Constraint
build_constraint(Prolog_term_ref t,const char * where)1000 build_constraint(Prolog_term_ref t, const char* where) {
1001   if (Prolog_is_compound(t)) {
1002     Prolog_atom functor;
1003     int arity;
1004     Prolog_get_compound_name_arity(t, &functor, &arity);
1005     if (arity == 2) {
1006       Prolog_term_ref arg1 = Prolog_new_term_ref();
1007       Prolog_term_ref arg2 = Prolog_new_term_ref();
1008       Prolog_get_arg(1, t, arg1);
1009       Prolog_get_arg(2, t, arg2);
1010       if (functor == a_equal)
1011         // =
1012         if (Prolog_is_integer(arg1))
1013           return integer_term_to_Coefficient(arg1)
1014             == build_linear_expression(arg2, where);
1015         else if (Prolog_is_integer(arg2))
1016           return build_linear_expression(arg1, where)
1017             == integer_term_to_Coefficient(arg2);
1018         else
1019           return build_linear_expression(arg1, where)
1020             == build_linear_expression(arg2, where);
1021       else if (functor == a_equal_less_than)
1022         // =<
1023         if (Prolog_is_integer(arg1))
1024           return integer_term_to_Coefficient(arg1)
1025             <= build_linear_expression(arg2, where);
1026         else if (Prolog_is_integer(arg2))
1027           return build_linear_expression(arg1, where)
1028             <= integer_term_to_Coefficient(arg2);
1029         else
1030           return build_linear_expression(arg1, where)
1031             <= build_linear_expression(arg2, where);
1032       else if (functor == a_greater_than_equal)
1033         // >=
1034         if (Prolog_is_integer(arg1))
1035           return integer_term_to_Coefficient(arg1)
1036             >= build_linear_expression(arg2, where);
1037         else if (Prolog_is_integer(arg2))
1038           return build_linear_expression(arg1, where)
1039             >= integer_term_to_Coefficient(arg2);
1040         else
1041           return build_linear_expression(arg1, where)
1042             >= build_linear_expression(arg2, where);
1043       else if (functor == a_less_than)
1044         // <
1045         if (Prolog_is_integer(arg1))
1046           return integer_term_to_Coefficient(arg1)
1047             < build_linear_expression(arg2, where);
1048         else if (Prolog_is_integer(arg2))
1049           return build_linear_expression(arg1, where)
1050             < integer_term_to_Coefficient(arg2);
1051         else
1052           return build_linear_expression(arg1, where)
1053             < build_linear_expression(arg2, where);
1054       else if (functor == a_greater_than) {
1055         // >
1056         if (Prolog_is_integer(arg1))
1057           return integer_term_to_Coefficient(arg1)
1058             > build_linear_expression(arg2, where);
1059         else if (Prolog_is_integer(arg2))
1060           return build_linear_expression(arg1, where)
1061             > integer_term_to_Coefficient(arg2);
1062         else
1063           return build_linear_expression(arg1, where)
1064             > build_linear_expression(arg2, where);
1065       }
1066     }
1067   }
1068   // Invalid.
1069   throw non_linear(t, where);
1070 }
1071 
1072 Congruence
build_congruence(Prolog_term_ref t,const char * where)1073 build_congruence(Prolog_term_ref t, const char* where) {
1074   if (Prolog_is_compound(t)) {
1075     Prolog_atom functor;
1076     int arity;
1077     Prolog_get_compound_name_arity(t, &functor, &arity);
1078     if (arity == 2) {
1079       Prolog_term_ref arg1 = Prolog_new_term_ref();
1080       Prolog_term_ref arg2 = Prolog_new_term_ref();
1081       Prolog_get_arg(1, t, arg1);
1082       Prolog_get_arg(2, t, arg2);
1083       if (functor == a_modulo) {
1084         // /
1085         if (Prolog_is_integer(arg2)) {
1086           Prolog_atom functor1;
1087           int arity1;
1088           Prolog_get_compound_name_arity(arg1, &functor1, &arity1);
1089           if (arity1 == 2) {
1090             if (functor1 == a_is_congruent_to) {
1091               // =:=
1092               Prolog_term_ref arg11 = Prolog_new_term_ref();
1093               Prolog_term_ref arg12 = Prolog_new_term_ref();
1094               Prolog_get_arg(1, arg1, arg11);
1095               Prolog_get_arg(2, arg1, arg12);
1096               if (Prolog_is_integer(arg12))
1097                 return (build_linear_expression(arg11, where)
1098                         %= integer_term_to_Coefficient(arg12))
1099                   / integer_term_to_Coefficient(arg2);
1100               else
1101                 return (build_linear_expression(arg11, where)
1102                         %= build_linear_expression(arg12, where))
1103                   / integer_term_to_Coefficient(arg2);
1104             }
1105           }
1106         }
1107       }
1108       else
1109         if (functor == a_is_congruent_to)
1110           // =:=
1111           if (Prolog_is_integer(arg2))
1112             return build_linear_expression(arg1, where)
1113               %= integer_term_to_Coefficient(arg2);
1114           else
1115             return build_linear_expression(arg1, where)
1116               %= build_linear_expression(arg2, where);
1117         else
1118           if (functor == a_equal) {
1119             // =
1120             if (Prolog_is_integer(arg1))
1121               return (build_linear_expression(arg2, where)
1122                       %= integer_term_to_Coefficient(arg1)) / 0;
1123             else if (Prolog_is_integer(arg2))
1124               return (build_linear_expression(arg1, where)
1125                       %= integer_term_to_Coefficient(arg2)) / 0;
1126             else
1127               return (build_linear_expression(arg1, where)
1128                       %= build_linear_expression(arg2, where)) / 0;
1129           }
1130     }
1131   }
1132   // Invalid.
1133   throw non_linear(t, where);
1134 }
1135 
1136 Generator
build_generator(Prolog_term_ref t,const char * where)1137 build_generator(Prolog_term_ref t, const char* where) {
1138   if (Prolog_is_compound(t)) {
1139     Prolog_atom functor;
1140     int arity;
1141     Prolog_get_compound_name_arity(t, &functor, &arity);
1142     if (arity == 1) {
1143       Prolog_term_ref arg = Prolog_new_term_ref();
1144       Prolog_get_arg(1, t, arg);
1145       if (functor == a_line)
1146         return Generator::line(build_linear_expression(arg, where));
1147       else if (functor == a_ray)
1148         return Generator::ray(build_linear_expression(arg, where));
1149       else if (functor == a_point)
1150         return Generator::point(build_linear_expression(arg, where));
1151       else if (functor == a_closure_point)
1152         return Generator::closure_point(build_linear_expression(arg, where));
1153     }
1154     else if (arity == 2) {
1155       Prolog_term_ref arg1 = Prolog_new_term_ref();
1156       Prolog_term_ref arg2 = Prolog_new_term_ref();
1157       Prolog_get_arg(1, t, arg1);
1158       Prolog_get_arg(2, t, arg2);
1159       if (Prolog_is_integer(arg2)) {
1160         if (functor == a_point)
1161           return Generator::point(build_linear_expression(arg1, where),
1162                                   integer_term_to_Coefficient(arg2));
1163         else if (functor == a_closure_point)
1164           return Generator::closure_point(build_linear_expression(arg1, where),
1165                                           integer_term_to_Coefficient(arg2));
1166       }
1167     }
1168   }
1169   // Invalid.
1170   throw non_linear(t, where);
1171 }
1172 
1173 Grid_Generator
build_grid_generator(Prolog_term_ref t,const char * where)1174 build_grid_generator(Prolog_term_ref t, const char* where) {
1175   if (Prolog_is_compound(t)) {
1176     Prolog_atom functor;
1177     int arity;
1178     Prolog_get_compound_name_arity(t, &functor, &arity);
1179     if (arity == 1) {
1180       Prolog_term_ref arg = Prolog_new_term_ref();
1181       Prolog_get_arg(1, t, arg);
1182       if (functor == a_grid_line)
1183         return Grid_Generator::grid_line(build_linear_expression(arg, where));
1184       else if (functor == a_parameter)
1185         return Grid_Generator::parameter(build_linear_expression(arg, where));
1186       else if (functor == a_grid_point)
1187         return Grid_Generator::grid_point(build_linear_expression(arg, where));
1188     }
1189     else if (arity == 2) {
1190       Prolog_term_ref arg1 = Prolog_new_term_ref();
1191       Prolog_term_ref arg2 = Prolog_new_term_ref();
1192       Prolog_get_arg(1, t, arg1);
1193       Prolog_get_arg(2, t, arg2);
1194       if (Prolog_is_integer(arg2)) {
1195         if (functor == a_grid_point)
1196           return Grid_Generator::grid_point(build_linear_expression(arg1,
1197                                                                     where),
1198                                             integer_term_to_Coefficient(arg2));
1199         else if (functor == a_parameter)
1200           return Grid_Generator::parameter(build_linear_expression(arg1,
1201                                                                    where),
1202                                           integer_term_to_Coefficient(arg2));
1203       }
1204     }
1205   }
1206   // Invalid.
1207   throw non_linear(t, where);
1208 }
1209 
1210 template <typename R>
1211 Prolog_term_ref
get_homogeneous_expression(const R & r)1212 get_homogeneous_expression(const R& r) {
1213   Prolog_term_ref so_far = Prolog_new_term_ref();
1214   PPL_DIRTY_TEMP_COEFFICIENT(coefficient);
1215   dimension_type varid = 0;
1216   dimension_type space_dimension = r.space_dimension();
1217   while (varid < space_dimension
1218          && (coefficient = r.coefficient(Variable(varid))) == 0)
1219     ++varid;
1220   if (varid >= space_dimension) {
1221     Prolog_put_long(so_far, 0);
1222   }
1223   else {
1224     Prolog_construct_compound(so_far, a_asterisk,
1225                               Coefficient_to_integer_term(coefficient),
1226                               variable_term(varid));
1227     while (true) {
1228       ++varid;
1229       while (varid < space_dimension
1230              && (coefficient = r.coefficient(Variable(varid))) == 0)
1231         ++varid;
1232       if (varid >= space_dimension)
1233         break;
1234       else {
1235         Prolog_term_ref addendum = Prolog_new_term_ref();
1236         Prolog_construct_compound(addendum, a_asterisk,
1237                                   Coefficient_to_integer_term(coefficient),
1238                                   variable_term(varid));
1239         Prolog_term_ref new_so_far = Prolog_new_term_ref();
1240         Prolog_construct_compound(new_so_far, a_plus,
1241                                   so_far, addendum);
1242         so_far = new_so_far;
1243       }
1244     }
1245   }
1246   return so_far;
1247 }
1248 
1249 Prolog_term_ref
get_linear_expression(const Linear_Expression & le)1250 get_linear_expression(const Linear_Expression& le) {
1251   Prolog_term_ref t_homo = get_homogeneous_expression(le);
1252   if (le.inhomogeneous_term() == 0)
1253     return t_homo;
1254   else {
1255     Prolog_term_ref t_in
1256       = Coefficient_to_integer_term(le.inhomogeneous_term());
1257     if (unify_long(t_homo, 0))
1258       return t_in;
1259     else {
1260       Prolog_term_ref t_le = Prolog_new_term_ref();
1261       Prolog_construct_compound(t_le, a_plus, t_homo, t_in);
1262       return t_le;
1263     }
1264   }
1265 }
1266 
1267 Prolog_term_ref
constraint_term(const Constraint & c)1268 constraint_term(const Constraint& c) {
1269   Prolog_atom relation = 0;
1270   switch (c.type()) {
1271   case Constraint::EQUALITY:
1272     relation = a_equal;
1273     break;
1274   case Constraint::NONSTRICT_INEQUALITY:
1275     relation = a_greater_than_equal;
1276     break;
1277   case Constraint::STRICT_INEQUALITY:
1278     relation = a_greater_than;
1279     break;
1280   default:
1281     throw unknown_interface_error("generator_term()");
1282   }
1283   Prolog_term_ref t = Prolog_new_term_ref();
1284   Prolog_construct_compound
1285     (t,
1286      relation,
1287      get_homogeneous_expression(c),
1288      Coefficient_to_integer_term(-c.inhomogeneous_term()));
1289   return t;
1290 }
1291 
1292 Prolog_term_ref
congruence_term(const Congruence & cg)1293 congruence_term(const Congruence& cg) {
1294   Prolog_atom relation1 = a_is_congruent_to;
1295   Prolog_atom relation2 = a_modulo;
1296   Prolog_term_ref t_tmp = Prolog_new_term_ref();
1297   Prolog_term_ref t = Prolog_new_term_ref();
1298   Prolog_construct_compound
1299     (t_tmp,
1300      relation1,
1301      get_homogeneous_expression(cg),
1302      Coefficient_to_integer_term(-cg.inhomogeneous_term()));
1303   Prolog_construct_compound
1304     (t,
1305      relation2,
1306      t_tmp,
1307      Coefficient_to_integer_term(cg.modulus()));
1308   return t;
1309 }
1310 
1311 Prolog_term_ref
generator_term(const Generator & g)1312 generator_term(const Generator& g) {
1313   Prolog_term_ref t = Prolog_new_term_ref();
1314   Prolog_atom constructor = 0;
1315   switch (g.type()) {
1316   case Generator::LINE:
1317     constructor = a_line;
1318     break;
1319   case Generator::RAY:
1320     constructor = a_ray;
1321     break;
1322   case Generator::POINT:
1323     {
1324       constructor = a_point;
1325       const Coefficient& divisor = g.divisor();
1326       if (divisor == 1)
1327         break;
1328       else {
1329         Prolog_construct_compound(t, constructor,
1330                                   get_homogeneous_expression(g),
1331                                   Coefficient_to_integer_term(divisor));
1332         return t;
1333       }
1334     }
1335   case Generator::CLOSURE_POINT:
1336     {
1337       constructor = a_closure_point;
1338       const Coefficient& divisor = g.divisor();
1339       if (divisor == 1)
1340         break;
1341       else {
1342         Prolog_construct_compound(t, constructor,
1343                                   get_homogeneous_expression(g),
1344                                   Coefficient_to_integer_term(divisor));
1345         return t;
1346       }
1347     }
1348   default:
1349     throw unknown_interface_error("generator_term()");
1350   }
1351   Prolog_construct_compound(t, constructor, get_homogeneous_expression(g));
1352   return t;
1353 }
1354 
1355 Prolog_term_ref
grid_generator_term(const Grid_Generator & g)1356 grid_generator_term(const Grid_Generator& g) {
1357   Prolog_term_ref t = Prolog_new_term_ref();
1358   Prolog_atom constructor = 0;
1359   switch (g.type()) {
1360   case Grid_Generator::LINE:
1361     constructor = a_grid_line;
1362     break;
1363   case Grid_Generator::PARAMETER:
1364     {
1365       constructor = a_parameter;
1366       const Coefficient& divisor = g.divisor();
1367       if (divisor == 1)
1368         break;
1369       else {
1370         Prolog_construct_compound(t, constructor,
1371                                   get_homogeneous_expression(g),
1372                                   Coefficient_to_integer_term(divisor));
1373         return t;
1374       }
1375     }
1376   case Grid_Generator::POINT:
1377     {
1378       constructor = a_grid_point;
1379       const Coefficient& divisor = g.divisor();
1380       if (divisor == 1)
1381         break;
1382       else {
1383         Prolog_construct_compound(t, constructor,
1384                                   get_homogeneous_expression(g),
1385                                   Coefficient_to_integer_term(divisor));
1386         return t;
1387       }
1388     }
1389   default:
1390     throw unknown_interface_error("grid_generator_term()");
1391   }
1392   Prolog_construct_compound(t, constructor, get_homogeneous_expression(g));
1393   return t;
1394 }
1395 
1396 Prolog_term_ref
artificial_parameter_term(const PIP_Tree_Node::Artificial_Parameter & art)1397 artificial_parameter_term(const PIP_Tree_Node::Artificial_Parameter& art) {
1398   Prolog_term_ref t = Prolog_new_term_ref();
1399   Prolog_construct_compound(t, a_divided_by,
1400                             get_linear_expression(art),
1401                             Coefficient_to_integer_term(art.denominator()));
1402   return t;
1403 }
1404 
1405 Variable
term_to_Variable(Prolog_term_ref t,const char * where)1406 term_to_Variable(Prolog_term_ref t, const char* where) {
1407   if (Prolog_is_compound(t)) {
1408     Prolog_atom functor;
1409     int arity;
1410     Prolog_get_compound_name_arity(t, &functor, &arity);
1411     if (functor == a_dollar_VAR && arity == 1) {
1412       Prolog_term_ref arg = Prolog_new_term_ref();
1413       Prolog_get_arg(1, t, arg);
1414       return
1415         Variable(term_to_unsigned<dimension_type>(arg, "term_to_Variable"));
1416     }
1417   }
1418   throw not_a_variable(t, where);
1419 }
1420 
1421 Coefficient
term_to_Coefficient(Prolog_term_ref t,const char * where)1422 term_to_Coefficient(Prolog_term_ref t, const char* where) {
1423   if (Prolog_is_integer(t))
1424     return integer_term_to_Coefficient(t);
1425   else
1426     throw not_an_integer(t, where);
1427 }
1428 
1429 Prolog_atom
term_to_bounded_integer_type_width(Prolog_term_ref t,const char * where)1430 term_to_bounded_integer_type_width(Prolog_term_ref t, const char* where) {
1431   if (Prolog_is_atom(t)) {
1432     Prolog_atom name;
1433     if (Prolog_get_atom_name(t, &name)
1434         && (name == a_bits_8 || name == a_bits_16
1435             || name == a_bits_32 || name == a_bits_64
1436             || name == a_bits_128))
1437       return name;
1438   }
1439   throw not_a_bounded_integer_type_width(t, where);
1440 }
1441 
1442 Prolog_atom
term_to_bounded_integer_type_representation(Prolog_term_ref t,const char * where)1443 term_to_bounded_integer_type_representation(Prolog_term_ref t,
1444                                             const char* where) {
1445   if (Prolog_is_atom(t)) {
1446     Prolog_atom name;
1447     if (Prolog_get_atom_name(t, &name)
1448         && (name == a_unsigned || name == a_signed_2_complement))
1449       return name;
1450   }
1451   throw not_a_bounded_integer_type_representation(t, where);
1452 }
1453 
1454 Prolog_atom
term_to_bounded_integer_type_overflow(Prolog_term_ref t,const char * where)1455 term_to_bounded_integer_type_overflow(Prolog_term_ref t,
1456                                       const char* where) {
1457   if (Prolog_is_atom(t)) {
1458     Prolog_atom name;
1459     if (Prolog_get_atom_name(t, &name)
1460         && (name == a_overflow_wraps
1461             || name == a_overflow_undefined
1462             || name == a_overflow_impossible))
1463       return name;
1464   }
1465   throw not_a_bounded_integer_type_overflow(t, where);
1466 }
1467 
1468 Prolog_atom
term_to_optimization_mode(Prolog_term_ref t,const char * where)1469 term_to_optimization_mode(Prolog_term_ref t, const char* where) {
1470   if (Prolog_is_atom(t)) {
1471     Prolog_atom name;
1472     if (Prolog_get_atom_name(t, &name)
1473         && (name == a_max || name == a_min))
1474       return name;
1475   }
1476   throw not_an_optimization_mode(t, where);
1477 }
1478 
1479 Prolog_atom
term_to_control_parameter_name(Prolog_term_ref t,const char * where)1480 term_to_control_parameter_name(Prolog_term_ref t, const char* where) {
1481   if (Prolog_is_atom(t)) {
1482     Prolog_atom name;
1483     if (Prolog_get_atom_name(t, &name)
1484         && (name == a_pricing || name == a_cutting_strategy))
1485       return name;
1486   }
1487   throw not_a_control_parameter_name(t, where);
1488 }
1489 
1490 Prolog_atom
term_to_pip_problem_control_parameter_name(Prolog_term_ref t,const char * where)1491 term_to_pip_problem_control_parameter_name(Prolog_term_ref t, const char* where) {
1492   if (Prolog_is_atom(t)) {
1493     Prolog_atom name;
1494     if (Prolog_get_atom_name(t, &name)
1495         && (name == a_cutting_strategy || name == a_pivot_row_strategy))
1496       return name;
1497   }
1498   throw not_a_pip_problem_control_parameter_name(t, where);
1499 }
1500 
1501 Prolog_atom
term_to_control_parameter_value(Prolog_term_ref t,const char * where)1502 term_to_control_parameter_value(Prolog_term_ref t, const char* where) {
1503   if (Prolog_is_atom(t)) {
1504     Prolog_atom name;
1505     if (Prolog_get_atom_name(t, &name)
1506         && (name == a_pricing_steepest_edge_float
1507             || name == a_pricing_steepest_edge_exact
1508             || name == a_pricing_textbook
1509             || name == a_cutting_strategy_first
1510             || name == a_cutting_strategy_deepest))
1511       return name;
1512   }
1513   throw not_a_control_parameter_value(t, where);
1514 }
1515 
1516 Prolog_atom
term_to_pip_problem_control_parameter_value(Prolog_term_ref t,const char * where)1517 term_to_pip_problem_control_parameter_value(Prolog_term_ref t,
1518                                             const char* where) {
1519   if (Prolog_is_atom(t)) {
1520     Prolog_atom name;
1521     if (Prolog_get_atom_name(t, &name)
1522         && (name == a_cutting_strategy_first
1523             || name == a_cutting_strategy_deepest
1524             || name == a_cutting_strategy_all
1525             || name == a_pivot_row_strategy_first
1526             || name == a_pivot_row_strategy_max_column))
1527       return name;
1528   }
1529   throw not_a_pip_problem_control_parameter_value(t, where);
1530 }
1531 
1532 bool Prolog_interface_initialized = false;
1533 
1534 void
check_nil_terminating(Prolog_term_ref t,const char * where)1535 check_nil_terminating(Prolog_term_ref t, const char* where) {
1536   if (Prolog_get_nil(t))
1537     return;
1538   throw not_a_nil_terminated_list(t, where);
1539 }
1540 
1541 inline dimension_type
max_representable_dimension(dimension_type d)1542 max_representable_dimension(dimension_type d) {
1543   return
1544     Prolog_has_unbounded_integers
1545     ? d
1546     : std::min(d, static_cast<dimension_type>(Prolog_max_integer));
1547 }
1548 
1549 bool
term_to_boundary(Prolog_term_ref t_b,Boundary_Kind kind,bool & finite,bool & closed,Coefficient & n,Coefficient & d)1550 term_to_boundary(Prolog_term_ref t_b, Boundary_Kind kind,
1551                  bool& finite, bool& closed,
1552                  Coefficient& n, Coefficient& d) {
1553   if (!Prolog_is_compound(t_b))
1554     return false;
1555 
1556   Prolog_atom functor;
1557   int arity;
1558 
1559   Prolog_get_compound_name_arity(t_b, &functor, &arity);
1560   // A boundary term is either of the form c(Limit) or o(Limit).
1561   if (arity != 1 || (functor != a_c && functor != a_o))
1562     return false;
1563 
1564   Prolog_atom open_closed_atom = functor;
1565 
1566   Prolog_term_ref t_limit = Prolog_new_term_ref();
1567   Prolog_get_arg(1, t_b, t_limit);
1568   if (Prolog_is_integer(t_limit)) {
1569     // A finite, integral limit.
1570     finite = true;
1571     closed = (open_closed_atom == a_c);
1572     n = integer_term_to_Coefficient(t_limit);
1573     d = 1;
1574   }
1575   else if (Prolog_is_atom(t_limit)) {
1576     Prolog_atom a;
1577     Prolog_get_atom_name(t_limit, &a);
1578     Prolog_atom allowed_infinity = (kind == LOWER_BOUNDARY ? a_minf : a_pinf);
1579     // Only open bounds may be unbounded.
1580     if (a != allowed_infinity || open_closed_atom != a_o)
1581       return false;
1582 
1583     finite = false;
1584   }
1585   else if (Prolog_is_compound(t_limit)) {
1586     Prolog_get_compound_name_arity(t_limit, &functor, &arity);
1587     if (arity != 2 || functor != a_slash)
1588       return false;
1589 
1590     Prolog_term_ref t_n = Prolog_new_term_ref();
1591     Prolog_term_ref t_d = Prolog_new_term_ref();
1592     Prolog_get_arg(1, t_limit, t_n);
1593     Prolog_get_arg(2, t_limit, t_d);
1594 
1595     if (!Prolog_is_integer(t_n) || !Prolog_is_integer(t_d))
1596       return false;
1597     else {
1598       finite = true;
1599       closed = (open_closed_atom == a_c);
1600       n = integer_term_to_Coefficient(t_n);
1601       d = integer_term_to_Coefficient(t_d);
1602       // Catch negative denominators and divisions by zero here.
1603       if (d <= 0)
1604         return false;
1605     }
1606   }
1607   return true;
1608 }
1609 
1610 Prolog_atom
term_to_relation(Prolog_term_ref t,const char * where)1611 term_to_relation(Prolog_term_ref t, const char* where) {
1612   if (Prolog_is_atom(t)) {
1613     Prolog_atom name;
1614     if (Prolog_get_atom_name(t, &name)
1615         && (name == a_equal
1616             || name == a_greater_than_equal
1617             || name == a_equal_less_than
1618             || name == a_greater_than
1619             || name == a_less_than))
1620       return name;
1621   }
1622   throw not_a_relation(t, where);
1623 }
1624 
1625 Relation_Symbol
term_to_relation_symbol(Prolog_term_ref t_r,const char * where)1626 term_to_relation_symbol(Prolog_term_ref t_r, const char* where) {
1627   Prolog_atom ra = term_to_relation(t_r, where);
1628   Relation_Symbol r;
1629   if (ra == a_less_than)
1630     r = LESS_THAN;
1631   else if (ra == a_equal_less_than)
1632     r = LESS_OR_EQUAL;
1633   else if (ra == a_equal)
1634     r = EQUAL;
1635   else if (ra == a_greater_than_equal)
1636     r = GREATER_OR_EQUAL;
1637   else {
1638     assert(ra == a_greater_than);
1639     r = GREATER_THAN;
1640   }
1641   return r;
1642 }
1643 
1644 Prolog_term_ref
rational_term(const Rational_Box::interval_type::boundary_type & q)1645 rational_term(const Rational_Box::interval_type::boundary_type& q) {
1646   Prolog_term_ref t = Prolog_new_term_ref();
1647   PPL_DIRTY_TEMP_COEFFICIENT(numerator);
1648   PPL_DIRTY_TEMP_COEFFICIENT(denominator);
1649   numerator = q.get_num();
1650   denominator = q.get_den();
1651   if (denominator == 1)
1652     Prolog_put_Coefficient(t, numerator);
1653   else
1654     Prolog_construct_compound(t, a_slash,
1655                               Coefficient_to_integer_term(numerator),
1656                               Coefficient_to_integer_term(denominator));
1657   return t;
1658 }
1659 
1660 Prolog_term_ref
interval_term(const Rational_Box::interval_type & i)1661 interval_term(const Rational_Box::interval_type& i) {
1662   Prolog_term_ref t = Prolog_new_term_ref();
1663   if (i.is_empty())
1664     Prolog_put_atom(t, a_empty);
1665   else {
1666     // Lower bound.
1667     const Prolog_atom& l_oc = i.lower_is_open() ? a_o : a_c;
1668     Prolog_term_ref l_b = Prolog_new_term_ref();
1669     if (i.lower_is_boundary_infinity())
1670       Prolog_put_atom(l_b, a_minf);
1671     else
1672       Prolog_put_term(l_b, rational_term(i.lower()));
1673     Prolog_term_ref l_t = Prolog_new_term_ref();
1674     Prolog_construct_compound(l_t, l_oc, l_b);
1675 
1676     // Upper bound.
1677     const Prolog_atom& u_oc = i.upper_is_open() ? a_o : a_c;
1678     Prolog_term_ref u_b = Prolog_new_term_ref();
1679     if (i.upper_is_boundary_infinity())
1680       Prolog_put_atom(u_b, a_pinf);
1681     else
1682       Prolog_put_term(u_b, rational_term(i.upper()));
1683     Prolog_term_ref u_t = Prolog_new_term_ref();
1684     Prolog_construct_compound(u_t, u_oc, u_b);
1685 
1686     Prolog_construct_compound(t, a_i, l_t, u_t);
1687   }
1688   return t;
1689 }
1690 
1691 Prolog_atom
term_to_complexity_class(Prolog_term_ref t,const char * where)1692 term_to_complexity_class(Prolog_term_ref t, const char* where) {
1693   if (Prolog_is_atom(t)) {
1694     Prolog_atom name;
1695     if (Prolog_get_atom_name(t, &name)
1696         && (name == a_polynomial || name == a_simplex || name == a_any))
1697       return name;
1698   }
1699   throw not_a_complexity_class(t, where);
1700 }
1701 
1702 } // namespace Prolog
1703 
1704 } // namespace Interfaces
1705 
1706 } // namespace Parma_Polyhedra_Library
1707 
1708 using namespace Parma_Polyhedra_Library::Interfaces::Prolog;
1709 
1710 extern "C" Prolog_foreign_return_type
ppl_version_major(Prolog_term_ref t_v)1711 ppl_version_major(Prolog_term_ref t_v) {
1712   try {
1713     if (unify_ulong(t_v, version_major()))
1714       return PROLOG_SUCCESS;
1715   }
1716   CATCH_ALL;
1717 }
1718 
1719 extern "C" Prolog_foreign_return_type
ppl_version_minor(Prolog_term_ref t_v)1720 ppl_version_minor(Prolog_term_ref t_v) {
1721   try {
1722     if (unify_ulong(t_v, version_minor()))
1723       return PROLOG_SUCCESS;
1724   }
1725   CATCH_ALL;
1726 }
1727 
1728 extern "C" Prolog_foreign_return_type
ppl_version_revision(Prolog_term_ref t_v)1729 ppl_version_revision(Prolog_term_ref t_v) {
1730   try {
1731     if (unify_ulong(t_v, version_revision()))
1732       return PROLOG_SUCCESS;
1733   }
1734   CATCH_ALL;
1735 }
1736 
1737 extern "C" Prolog_foreign_return_type
ppl_version_beta(Prolog_term_ref t_v)1738 ppl_version_beta(Prolog_term_ref t_v) {
1739   try {
1740     if (unify_ulong(t_v, version_beta()))
1741       return PROLOG_SUCCESS;
1742   }
1743   CATCH_ALL;
1744 }
1745 
1746 extern "C" Prolog_foreign_return_type
ppl_version(Prolog_term_ref t_v)1747 ppl_version(Prolog_term_ref t_v) {
1748   try {
1749     Prolog_term_ref tmp = Prolog_new_term_ref();
1750     Prolog_put_atom_chars(tmp, version());
1751     if (Prolog_unify(t_v, tmp))
1752       return PROLOG_SUCCESS;
1753   }
1754   CATCH_ALL;
1755 }
1756 
1757 extern "C" Prolog_foreign_return_type
ppl_banner(Prolog_term_ref t_b)1758 ppl_banner(Prolog_term_ref t_b) {
1759   try {
1760     Prolog_term_ref tmp = Prolog_new_term_ref();
1761     Prolog_put_atom_chars(tmp, banner());
1762     if (Prolog_unify(t_b, tmp))
1763       return PROLOG_SUCCESS;
1764   }
1765   CATCH_ALL;
1766 }
1767 
1768 extern "C" Prolog_foreign_return_type
ppl_max_space_dimension(Prolog_term_ref t_msd)1769 ppl_max_space_dimension(Prolog_term_ref t_msd) {
1770   try {
1771     if (unify_ulong(t_msd, max_representable_dimension(max_space_dimension())))
1772       return PROLOG_SUCCESS;
1773   }
1774   CATCH_ALL;
1775 }
1776 
1777 extern "C" Prolog_foreign_return_type
ppl_initialize()1778 ppl_initialize() {
1779   try {
1780     if (Prolog_interface_initialized)
1781       return PROLOG_SUCCESS;
1782     // Initialize the core library.
1783     initialize();
1784     for (size_t i = 0; prolog_interface_atoms[i].p_atom != 0; ++i) {
1785       Prolog_atom a = Prolog_atom_from_string(prolog_interface_atoms[i].name);
1786       *prolog_interface_atoms[i].p_atom = a;
1787     }
1788     timeout_exception_atom = a_time_out;
1789     out_of_memory_exception_atom = a_out_of_memory;
1790     ppl_Prolog_sysdep_init();
1791     Prolog_interface_initialized = true;
1792     return PROLOG_SUCCESS;
1793   }
1794   CATCH_ALL;
1795 }
1796 
1797 extern "C" Prolog_foreign_return_type
ppl_finalize()1798 ppl_finalize() {
1799   try {
1800     if (!Prolog_interface_initialized)
1801       return PROLOG_SUCCESS;
1802 
1803     Prolog_interface_initialized = false;
1804     // Finalize the core library.
1805     finalize();
1806     // Release the pending timeout object, if any.
1807     reset_timeout();
1808     ppl_Prolog_sysdep_deinit();
1809     return PROLOG_SUCCESS;
1810   }
1811   CATCH_ALL;
1812 }
1813 
1814 extern "C" Prolog_foreign_return_type
ppl_set_rounding_for_PPL()1815 ppl_set_rounding_for_PPL() {
1816   try {
1817     set_rounding_for_PPL();
1818     return PROLOG_SUCCESS;
1819   }
1820   CATCH_ALL;
1821 }
1822 
1823 extern "C" Prolog_foreign_return_type
ppl_restore_pre_PPL_rounding()1824 ppl_restore_pre_PPL_rounding() {
1825   try {
1826     restore_pre_PPL_rounding();
1827     return PROLOG_SUCCESS;
1828   }
1829   CATCH_ALL;
1830 }
1831 
1832 extern "C" Prolog_foreign_return_type
ppl_irrational_precision(Prolog_term_ref t_p)1833 ppl_irrational_precision(Prolog_term_ref t_p) {
1834   try {
1835     if (unify_ulong(t_p, irrational_precision()))
1836       return PROLOG_SUCCESS;
1837   }
1838   CATCH_ALL;
1839 }
1840 
1841 extern "C" Prolog_foreign_return_type
ppl_set_irrational_precision(Prolog_term_ref t_p)1842 ppl_set_irrational_precision(Prolog_term_ref t_p) {
1843   try {
1844     unsigned p
1845       = term_to_unsigned<unsigned>(t_p, "ppl_set_irrational_precision/1");
1846     set_irrational_precision(p);
1847     return PROLOG_SUCCESS;
1848   }
1849   CATCH_ALL;
1850 }
1851 
1852 extern "C" Prolog_foreign_return_type
ppl_set_timeout_exception_atom(Prolog_term_ref t_tea)1853 ppl_set_timeout_exception_atom(Prolog_term_ref t_tea) {
1854   try {
1855     if (Prolog_is_atom(t_tea)) {
1856       Prolog_atom tea;
1857       if (Prolog_get_atom_name(t_tea, &tea)) {
1858         timeout_exception_atom = tea;
1859         return PROLOG_SUCCESS;
1860       }
1861     }
1862     Prolog_term_ref found = Prolog_new_term_ref();
1863     Prolog_construct_compound(found, a_found, t_tea);
1864 
1865     Prolog_term_ref expected = Prolog_new_term_ref();
1866     Prolog_construct_compound(expected, a_expected,
1867                               Prolog_atom_term_from_string("atom"));
1868 
1869     Prolog_term_ref where = Prolog_new_term_ref();
1870     Prolog_construct_compound(where, a_where,
1871                               Prolog_atom_term_from_string
1872                               ("ppl_set_timeout_exception_atom"));
1873 
1874     Prolog_term_ref exception_term = Prolog_new_term_ref();
1875     Prolog_construct_compound(exception_term, a_ppl_invalid_argument,
1876                               found, expected, where);
1877     Prolog_raise_exception(exception_term);
1878     return PROLOG_FAILURE;
1879   }
1880   CATCH_ALL;
1881 }
1882 
1883 extern "C" Prolog_foreign_return_type
ppl_timeout_exception_atom(Prolog_term_ref t)1884 ppl_timeout_exception_atom(Prolog_term_ref t) {
1885   try {
1886     Prolog_term_ref t_tea = Prolog_new_term_ref();
1887     Prolog_put_atom(t_tea, timeout_exception_atom);
1888     return Prolog_unify(t_tea, t) ? PROLOG_SUCCESS : PROLOG_FAILURE;
1889   }
1890   CATCH_ALL;
1891 }
1892 
1893 extern "C" Prolog_foreign_return_type
ppl_set_timeout(Prolog_term_ref t_csecs)1894 ppl_set_timeout(Prolog_term_ref t_csecs) {
1895   try {
1896     // In case a timeout was already set.
1897     reset_timeout();
1898     static timeout_exception e;
1899     unsigned csecs = term_to_unsigned<unsigned>(t_csecs, "ppl_set_timeout/1");
1900     p_timeout_object =
1901       new Parma_Polyhedra_Library::Watchdog(csecs,
1902                                             abandon_expensive_computations,
1903                                             e);
1904     return PROLOG_SUCCESS;
1905   }
1906   CATCH_ALL;
1907 }
1908 
1909 extern "C" Prolog_foreign_return_type
ppl_reset_timeout()1910 ppl_reset_timeout() {
1911   try {
1912     reset_timeout();
1913     return PROLOG_SUCCESS;
1914   }
1915   CATCH_ALL;
1916 }
1917 
1918 extern "C" Prolog_foreign_return_type
ppl_set_deterministic_timeout(Prolog_term_ref t_unscaled_weight,Prolog_term_ref t_scale)1919 ppl_set_deterministic_timeout(Prolog_term_ref t_unscaled_weight,
1920                               Prolog_term_ref t_scale) {
1921   try {
1922     // In case a deterministic timeout was already set.
1923     reset_deterministic_timeout();
1924     static deterministic_timeout_exception e;
1925     unsigned long unscaled_weight
1926       = term_to_unsigned<unsigned long>(t_unscaled_weight,
1927                                         "ppl_set_deterministic_timeout/2");
1928     unsigned scale
1929       = term_to_unsigned<unsigned>(t_scale, "ppl_set_deterministic_timeout/2");
1930     typedef Parma_Polyhedra_Library::Weightwatch_Traits Traits;
1931     p_deterministic_timeout_object
1932       = new Weightwatch(Traits::compute_delta(unscaled_weight, scale),
1933                         abandon_expensive_computations, e);
1934     return PROLOG_SUCCESS;
1935   }
1936   CATCH_ALL;
1937 }
1938 
1939 extern "C" Prolog_foreign_return_type
ppl_reset_deterministic_timeout()1940 ppl_reset_deterministic_timeout() {
1941   try {
1942     reset_deterministic_timeout();
1943     return PROLOG_SUCCESS;
1944   }
1945   CATCH_ALL;
1946 }
1947 
1948 extern "C" Prolog_foreign_return_type
ppl_Coefficient_bits(Prolog_term_ref t_bits)1949 ppl_Coefficient_bits(Prolog_term_ref t_bits) {
1950   try {
1951     if (unify_ulong(t_bits, PPL_COEFFICIENT_BITS))
1952       return PROLOG_SUCCESS;
1953   }
1954   CATCH_ALL;
1955 }
1956 
1957 extern "C" Prolog_foreign_return_type
ppl_Coefficient_is_bounded()1958 ppl_Coefficient_is_bounded() {
1959   try {
1960     if (std::numeric_limits<Coefficient>::is_bounded)
1961       return PROLOG_SUCCESS;
1962   }
1963   CATCH_ALL;
1964 }
1965 
1966 extern "C" Prolog_foreign_return_type
ppl_Coefficient_min(Prolog_term_ref t_min)1967 ppl_Coefficient_min(Prolog_term_ref t_min) {
1968   try {
1969     if (std::numeric_limits<Coefficient>::is_bounded) {
1970       PPL_DIRTY_TEMP_COEFFICIENT(min);
1971       min = std::numeric_limits<Coefficient>::min();
1972       if (Prolog_has_unbounded_integers
1973           || (min >= Prolog_min_integer && min <= Prolog_min_integer))
1974         return Prolog_unify_Coefficient(t_min, min)
1975           ? PROLOG_SUCCESS : PROLOG_FAILURE;
1976     }
1977   }
1978   CATCH_ALL;
1979 }
1980 
1981 extern "C" Prolog_foreign_return_type
ppl_Coefficient_max(Prolog_term_ref t_max)1982 ppl_Coefficient_max(Prolog_term_ref t_max) {
1983   try {
1984     if (std::numeric_limits<Coefficient>::is_bounded) {
1985       PPL_DIRTY_TEMP_COEFFICIENT(max);
1986       max = std::numeric_limits<Coefficient>::max();
1987       if (Prolog_has_unbounded_integers
1988           || (max >= Prolog_min_integer && max <= Prolog_min_integer))
1989         return Prolog_unify_Coefficient(t_max, max)
1990           ? PROLOG_SUCCESS : PROLOG_FAILURE;
1991     }
1992   }
1993   CATCH_ALL;
1994 }
1995 
1996 extern "C" Prolog_foreign_return_type
ppl_new_MIP_Problem_from_space_dimension(Prolog_term_ref t_nd,Prolog_term_ref t_mip)1997 ppl_new_MIP_Problem_from_space_dimension
1998 (Prolog_term_ref t_nd, Prolog_term_ref t_mip) {
1999   static const char* where = "ppl_MIP_Problem_from_space_dimension/2";
2000   try {
2001     dimension_type d = term_to_unsigned<dimension_type>(t_nd, where);
2002     MIP_Problem* mip = new MIP_Problem(d);
2003     Prolog_term_ref tmp = Prolog_new_term_ref();
2004     Prolog_put_address(tmp, mip);
2005     if (Prolog_unify(t_mip, tmp)) {
2006       PPL_REGISTER(mip);
2007       return PROLOG_SUCCESS;
2008     }
2009     else
2010       delete mip;
2011   }
2012   CATCH_ALL;
2013 }
2014 
2015 extern "C" Prolog_foreign_return_type
ppl_new_MIP_Problem(Prolog_term_ref t_nd,Prolog_term_ref t_clist,Prolog_term_ref t_le_expr,Prolog_term_ref t_opt,Prolog_term_ref t_mip)2016 ppl_new_MIP_Problem(Prolog_term_ref t_nd,
2017                     Prolog_term_ref t_clist,
2018                     Prolog_term_ref t_le_expr,
2019                     Prolog_term_ref t_opt,
2020                     Prolog_term_ref t_mip) {
2021   static const char* where = "ppl_new_MIP_Problem/5";
2022   try {
2023     Constraint_System cs;
2024     Prolog_term_ref c = Prolog_new_term_ref();
2025     while (Prolog_is_cons(t_clist)) {
2026       Prolog_get_cons(t_clist, c, t_clist);
2027       cs.insert(build_constraint(c, where));
2028     }
2029     // Check the list is properly terminated.
2030     check_nil_terminating(t_clist, where);
2031 
2032     const Linear_Expression le = build_linear_expression(t_le_expr, where);
2033     Prolog_atom opt = term_to_optimization_mode(t_opt, where);
2034     Optimization_Mode mode = (opt == a_max) ? MAXIMIZATION : MINIMIZATION;
2035 
2036     MIP_Problem* mip
2037       = new MIP_Problem(term_to_unsigned<dimension_type>(t_nd, where),
2038                         cs, le, mode);
2039     Prolog_term_ref tmp = Prolog_new_term_ref();
2040     Prolog_put_address(tmp, mip);
2041     if (Prolog_unify(t_mip, tmp)) {
2042       PPL_REGISTER(mip);
2043       return PROLOG_SUCCESS;
2044     }
2045     else
2046       delete mip;
2047   }
2048   CATCH_ALL;
2049 }
2050 
2051 extern "C" Prolog_foreign_return_type
ppl_new_MIP_Problem_from_MIP_Problem(Prolog_term_ref t_mip_source,Prolog_term_ref t_mip)2052 ppl_new_MIP_Problem_from_MIP_Problem(Prolog_term_ref t_mip_source,
2053                                      Prolog_term_ref t_mip) {
2054   static const char* where = "ppl_new_MIP_Problem_from_MIP_Problem/2";
2055   try {
2056     const MIP_Problem* mip_source
2057       = static_cast<const MIP_Problem*>
2058       (term_to_handle<MIP_Problem>(t_mip_source, where));
2059     PPL_CHECK(mip_source);
2060     MIP_Problem* mip = new MIP_Problem(*mip_source);
2061     Prolog_term_ref tmp = Prolog_new_term_ref();
2062     Prolog_put_address(tmp, mip);
2063     if (Prolog_unify(t_mip, tmp)) {
2064       PPL_REGISTER(mip);
2065       return PROLOG_SUCCESS;
2066     }
2067     else
2068       delete mip;
2069   }
2070   CATCH_ALL;
2071 }
2072 
2073 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_swap(Prolog_term_ref t_lhs,Prolog_term_ref t_rhs)2074 ppl_MIP_Problem_swap(Prolog_term_ref t_lhs, Prolog_term_ref t_rhs) {
2075   static const char* where = "ppl_MIP_Problem_swap/2";
2076   try {
2077     MIP_Problem* lhs = term_to_handle<MIP_Problem>(t_lhs, where);
2078     MIP_Problem* rhs = term_to_handle<MIP_Problem>(t_rhs, where);
2079     PPL_CHECK(lhs);
2080     PPL_CHECK(rhs);
2081     swap(*lhs, *rhs);
2082     return PROLOG_SUCCESS;
2083   }
2084   CATCH_ALL;
2085 }
2086 
2087 extern "C" Prolog_foreign_return_type
ppl_delete_MIP_Problem(Prolog_term_ref t_mip)2088 ppl_delete_MIP_Problem(Prolog_term_ref t_mip) {
2089   static const char* where = "ppl_delete_MIP_Problem/1";
2090   try {
2091     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2092     PPL_UNREGISTER(mip);
2093     delete mip;
2094     return PROLOG_SUCCESS;
2095   }
2096   CATCH_ALL;
2097 }
2098 
2099 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_space_dimension(Prolog_term_ref t_mip,Prolog_term_ref t_sd)2100 ppl_MIP_Problem_space_dimension(Prolog_term_ref t_mip, Prolog_term_ref t_sd) {
2101   static const char* where = "ppl_MIP_Problem_space_dimension/2";
2102   try {
2103     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2104     PPL_CHECK(mip);
2105     if (unify_ulong(t_sd, mip->space_dimension()))
2106       return PROLOG_SUCCESS;
2107   }
2108   CATCH_ALL;
2109 }
2110 
2111 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_integer_space_dimensions(Prolog_term_ref t_mip,Prolog_term_ref t_vlist)2112 ppl_MIP_Problem_integer_space_dimensions(Prolog_term_ref t_mip,
2113                                          Prolog_term_ref t_vlist) {
2114   static const char* where = "ppl_MIP_Problem_integer_space_dimensions/2";
2115   try {
2116     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2117     PPL_CHECK(mip);
2118 
2119     Prolog_term_ref tail = Prolog_new_term_ref();
2120     Prolog_put_nil(tail);
2121     const Variables_Set& i_vars = mip->integer_space_dimensions();
2122 
2123     for (Variables_Set::const_iterator i = i_vars.begin(),
2124            i_end = i_vars.end(); i != i_end; ++i)
2125       Prolog_construct_cons(tail, variable_term(*i), tail);
2126 
2127     if (Prolog_unify(t_vlist, tail))
2128       return PROLOG_SUCCESS;
2129   }
2130   CATCH_ALL;
2131 }
2132 
2133 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_constraints(Prolog_term_ref t_mip,Prolog_term_ref t_clist)2134 ppl_MIP_Problem_constraints(Prolog_term_ref t_mip,
2135                             Prolog_term_ref t_clist) {
2136   static const char* where = "ppl_MIP_Problem_constraints/2";
2137   try {
2138     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2139     PPL_CHECK(mip);
2140 
2141     Prolog_term_ref tail = Prolog_new_term_ref();
2142     Prolog_put_nil(tail);
2143     for (MIP_Problem::const_iterator i = mip->constraints_begin(),
2144            i_end = mip->constraints_end(); i != i_end; ++i)
2145       Prolog_construct_cons(tail, constraint_term(*i), tail);
2146 
2147     if (Prolog_unify(t_clist, tail))
2148       return PROLOG_SUCCESS;
2149   }
2150   CATCH_ALL;
2151 }
2152 
2153 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_objective_function(Prolog_term_ref t_mip,Prolog_term_ref t_le_expr)2154 ppl_MIP_Problem_objective_function(Prolog_term_ref t_mip,
2155                                    Prolog_term_ref t_le_expr) {
2156   static const char* where = "ppl_MIP_Problem_objective_function/2";
2157   try {
2158     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2159     PPL_CHECK(mip);
2160 
2161     const Linear_Expression& le = mip->objective_function();
2162     Prolog_term_ref t = get_linear_expression(le);
2163 
2164     if (Prolog_unify(t_le_expr, t))
2165       return PROLOG_SUCCESS;
2166   }
2167   CATCH_ALL;
2168 }
2169 
2170 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_optimization_mode(Prolog_term_ref t_mip,Prolog_term_ref t_opt)2171 ppl_MIP_Problem_optimization_mode(Prolog_term_ref t_mip,
2172                                   Prolog_term_ref t_opt) {
2173   static const char* where = "ppl_MIP_Problem_optimization_mode/2";
2174   try {
2175     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2176     PPL_CHECK(mip);
2177 
2178     Optimization_Mode mode = mip->optimization_mode();
2179     Prolog_term_ref t = Prolog_new_term_ref();
2180     Prolog_atom a = (mode == MAXIMIZATION) ? a_max : a_min;
2181     Prolog_put_atom(t, a);
2182     if (Prolog_unify(t_opt, t))
2183       return PROLOG_SUCCESS;
2184   }
2185   CATCH_ALL;
2186 }
2187 
2188 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_clear(Prolog_term_ref t_mip)2189 ppl_MIP_Problem_clear(Prolog_term_ref t_mip) {
2190   static const char* where = "ppl_MIP_Problem_clear/1";
2191   try {
2192     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2193     PPL_CHECK(mip);
2194     mip->clear();
2195     return PROLOG_SUCCESS;
2196   }
2197   CATCH_ALL;
2198 }
2199 
2200 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_add_space_dimensions_and_embed(Prolog_term_ref t_mip,Prolog_term_ref t_nnd)2201 ppl_MIP_Problem_add_space_dimensions_and_embed
2202 (Prolog_term_ref t_mip, Prolog_term_ref t_nnd) {
2203   static const char* where
2204     = "ppl_MIP_Problem_add_space_dimensions_and_embed/2";
2205   try {
2206     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2207     PPL_CHECK(mip);
2208     dimension_type d = term_to_unsigned<dimension_type>(t_nnd, where);
2209     mip->add_space_dimensions_and_embed(d);
2210     return PROLOG_SUCCESS;
2211   }
2212   CATCH_ALL;
2213 }
2214 
2215 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_add_to_integer_space_dimensions(Prolog_term_ref t_mip,Prolog_term_ref t_vlist)2216 ppl_MIP_Problem_add_to_integer_space_dimensions(Prolog_term_ref t_mip,
2217                                                 Prolog_term_ref t_vlist) {
2218   static const char* where
2219     = "ppl_MIP_Problem_add_to_integer_space_dimensions/2";
2220   try {
2221     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2222     PPL_CHECK(mip);
2223     Variables_Set i_vars;
2224     Prolog_term_ref v = Prolog_new_term_ref();
2225 
2226     while (Prolog_is_cons(t_vlist)) {
2227       Prolog_get_cons(t_vlist, v, t_vlist);
2228       i_vars.insert(term_to_Variable(v, where).id());
2229     }
2230 
2231     // Check the list is properly terminated.
2232     check_nil_terminating(t_vlist, where);
2233 
2234     mip->add_to_integer_space_dimensions(i_vars);
2235     return PROLOG_SUCCESS;
2236   }
2237   CATCH_ALL;
2238 }
2239 
2240 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_add_constraint(Prolog_term_ref t_mip,Prolog_term_ref t_c)2241 ppl_MIP_Problem_add_constraint(Prolog_term_ref t_mip, Prolog_term_ref t_c) {
2242   static const char* where = "ppl_MIP_Problem_add_constraint/2";
2243   try {
2244     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2245     PPL_CHECK(mip);
2246     mip->add_constraint(build_constraint(t_c, where));
2247     return PROLOG_SUCCESS;
2248   }
2249   CATCH_ALL;
2250 }
2251 
2252 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_add_constraints(Prolog_term_ref t_mip,Prolog_term_ref t_clist)2253 ppl_MIP_Problem_add_constraints(Prolog_term_ref t_mip,
2254                                 Prolog_term_ref t_clist) {
2255   static const char* where = "ppl_MIP_Problem_add_constraints/2";
2256   try {
2257     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2258     PPL_CHECK(mip);
2259     Constraint_System cs;
2260     Prolog_term_ref c = Prolog_new_term_ref();
2261 
2262     while (Prolog_is_cons(t_clist)) {
2263       Prolog_get_cons(t_clist, c, t_clist);
2264       cs.insert(build_constraint(c, where));
2265     }
2266 
2267     // Check the list is properly terminated.
2268     check_nil_terminating(t_clist, where);
2269 
2270     mip->add_constraints(cs);
2271     return PROLOG_SUCCESS;
2272   }
2273   CATCH_ALL;
2274 }
2275 
2276 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_set_objective_function(Prolog_term_ref t_mip,Prolog_term_ref t_le_expr)2277 ppl_MIP_Problem_set_objective_function(Prolog_term_ref t_mip,
2278                                        Prolog_term_ref t_le_expr) {
2279   static const char* where = "ppl_MIP_Problem_set_objective_function/2";
2280   try {
2281     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2282     PPL_CHECK(mip);
2283     mip->set_objective_function(build_linear_expression(t_le_expr, where));
2284     return PROLOG_SUCCESS;
2285   }
2286   CATCH_ALL;
2287 }
2288 
2289 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_set_optimization_mode(Prolog_term_ref t_mip,Prolog_term_ref t_opt)2290 ppl_MIP_Problem_set_optimization_mode(Prolog_term_ref t_mip,
2291                                       Prolog_term_ref t_opt) {
2292   static const char* where = "ppl_MIP_Problem_set_optimization_mode/2";
2293   try {
2294     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2295     PPL_CHECK(mip);
2296 
2297     Prolog_atom opt = term_to_optimization_mode(t_opt, where);
2298     Optimization_Mode mode = (opt == a_max) ? MAXIMIZATION : MINIMIZATION;
2299     mip->set_optimization_mode(mode);
2300     return PROLOG_SUCCESS;
2301   }
2302   CATCH_ALL;
2303 }
2304 
2305 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_set_control_parameter(Prolog_term_ref t_mip,Prolog_term_ref t_cp_value)2306 ppl_MIP_Problem_set_control_parameter(Prolog_term_ref t_mip,
2307                                       Prolog_term_ref t_cp_value) {
2308   static const char* where = "ppl_MIP_Problem_set_control_parameter/2";
2309   try {
2310     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2311     PPL_CHECK(mip);
2312 
2313     Prolog_atom cp_value = term_to_control_parameter_value(t_cp_value, where);
2314     if (cp_value == a_pricing_steepest_edge_float)
2315       mip->set_control_parameter(MIP_Problem::PRICING_STEEPEST_EDGE_FLOAT);
2316     else if (cp_value == a_pricing_steepest_edge_exact)
2317       mip->set_control_parameter(MIP_Problem::PRICING_STEEPEST_EDGE_EXACT);
2318     else if (cp_value == a_pricing_textbook)
2319       mip->set_control_parameter(MIP_Problem::PRICING_TEXTBOOK);
2320     else
2321       throw unknown_interface_error("ppl_MIP_Problem_get_control_parameter()");
2322     return PROLOG_SUCCESS;
2323   }
2324   CATCH_ALL;
2325 }
2326 
2327 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_get_control_parameter(Prolog_term_ref t_mip,Prolog_term_ref t_cp_name,Prolog_term_ref t_cp_value)2328 ppl_MIP_Problem_get_control_parameter(Prolog_term_ref t_mip,
2329                                       Prolog_term_ref t_cp_name,
2330                                       Prolog_term_ref t_cp_value) {
2331   static const char* where = "ppl_MIP_Problem_get_control_parameter/3";
2332   try {
2333     MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2334     PPL_CHECK(mip);
2335     Prolog_atom cp_name = term_to_control_parameter_name(t_cp_name, where);
2336     MIP_Problem::Control_Parameter_Value ppl_cp_value;
2337     if (cp_name == a_pricing)
2338       ppl_cp_value = mip->get_control_parameter(MIP_Problem::PRICING);
2339     else
2340       throw unknown_interface_error("ppl_MIP_Problem_get_control_parameter()");
2341 
2342     Prolog_term_ref t = Prolog_new_term_ref();
2343     Prolog_atom a;
2344     switch (ppl_cp_value) {
2345     case MIP_Problem::PRICING_STEEPEST_EDGE_FLOAT:
2346       a = a_pricing_steepest_edge_float;
2347       break;
2348     case MIP_Problem::PRICING_STEEPEST_EDGE_EXACT:
2349       a = a_pricing_steepest_edge_exact;
2350       break;
2351     case MIP_Problem::PRICING_TEXTBOOK:
2352       a = a_pricing_textbook;
2353       break;
2354     default:
2355       throw unknown_interface_error("ppl_MIP_Problem_get_control_parameter()");
2356     }
2357     Prolog_put_atom(t, a);
2358     if (Prolog_unify(t_cp_value, t))
2359       return PROLOG_SUCCESS;
2360   }
2361   CATCH_ALL;
2362 }
2363 
2364 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_is_satisfiable(Prolog_term_ref t_mip)2365 ppl_MIP_Problem_is_satisfiable(Prolog_term_ref t_mip) {
2366   static const char* where = "ppl_MIP_Problem_is_satisfiable/1";
2367   try {
2368     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2369     PPL_CHECK(mip);
2370     if (mip->is_satisfiable())
2371       return PROLOG_SUCCESS;
2372   }
2373   CATCH_ALL;
2374 }
2375 
2376 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_solve(Prolog_term_ref t_mip,Prolog_term_ref t_status)2377 ppl_MIP_Problem_solve(Prolog_term_ref t_mip, Prolog_term_ref t_status) {
2378   static const char* where = "ppl_MIP_Problem_solve/2";
2379   try {
2380     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2381     PPL_CHECK(mip);
2382 
2383     Prolog_atom a;
2384     switch (mip->solve()) {
2385     case UNFEASIBLE_MIP_PROBLEM:
2386       a = a_unfeasible;
2387       break;
2388     case UNBOUNDED_MIP_PROBLEM:
2389       a = a_unbounded;
2390       break;
2391     case OPTIMIZED_MIP_PROBLEM:
2392       a = a_optimized;
2393       break;
2394     default:
2395       throw unknown_interface_error("ppl_MIP_Problem_solve()");
2396     }
2397     Prolog_term_ref t = Prolog_new_term_ref();
2398     Prolog_put_atom(t, a);
2399     if (Prolog_unify(t_status, t))
2400       return PROLOG_SUCCESS;
2401   }
2402   CATCH_ALL;
2403 }
2404 
2405 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_feasible_point(Prolog_term_ref t_mip,Prolog_term_ref t_g)2406 ppl_MIP_Problem_feasible_point(Prolog_term_ref t_mip,
2407                                Prolog_term_ref t_g) {
2408   static const char* where = "ppl_MIP_Problem_feasible_point/2";
2409   try {
2410     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2411     PPL_CHECK(mip);
2412     const Generator& g = mip->feasible_point();
2413     if (Prolog_unify(t_g, generator_term(g)))
2414       return PROLOG_SUCCESS;
2415  }
2416  CATCH_ALL;
2417 }
2418 
2419 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_optimizing_point(Prolog_term_ref t_mip,Prolog_term_ref t_g)2420 ppl_MIP_Problem_optimizing_point(Prolog_term_ref t_mip,
2421                                  Prolog_term_ref t_g) {
2422   static const char* where = "ppl_MIP_Problem_optimizing_point/2";
2423   try {
2424     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2425     PPL_CHECK(mip);
2426     const Generator& g = mip->optimizing_point();
2427     if (Prolog_unify(t_g, generator_term(g)))
2428       return PROLOG_SUCCESS;
2429   }
2430   CATCH_ALL;
2431 }
2432 
2433 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_optimal_value(Prolog_term_ref t_mip,Prolog_term_ref t_n,Prolog_term_ref t_d)2434 ppl_MIP_Problem_optimal_value(Prolog_term_ref t_mip,
2435                               Prolog_term_ref t_n,
2436                               Prolog_term_ref t_d) {
2437   static const char* where = "ppl_MIP_Problem_optimal_value/3";
2438   try {
2439     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2440     PPL_CHECK(mip);
2441     PPL_DIRTY_TEMP_COEFFICIENT(n);
2442     PPL_DIRTY_TEMP_COEFFICIENT(d);
2443     mip->optimal_value(n, d);
2444     if (Prolog_unify_Coefficient(t_n, n)
2445         && Prolog_unify_Coefficient(t_d, d))
2446       return PROLOG_SUCCESS;
2447   }
2448   CATCH_ALL;
2449 }
2450 
2451 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_evaluate_objective_function(Prolog_term_ref t_mip,Prolog_term_ref t_g,Prolog_term_ref t_n,Prolog_term_ref t_d)2452 ppl_MIP_Problem_evaluate_objective_function(Prolog_term_ref t_mip,
2453                                             Prolog_term_ref t_g,
2454                                             Prolog_term_ref t_n,
2455                                             Prolog_term_ref t_d) {
2456   static const char* where = "ppl_MIP_Problem_evaluate_objective_function/4";
2457   try {
2458     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2459     PPL_CHECK(mip);
2460     PPL_DIRTY_TEMP_COEFFICIENT(n);
2461     PPL_DIRTY_TEMP_COEFFICIENT(d);
2462     mip->evaluate_objective_function(build_generator(t_g, where), n, d);
2463     if (Prolog_unify_Coefficient(t_n, n)
2464         && Prolog_unify_Coefficient(t_d, d))
2465       return PROLOG_SUCCESS;
2466   }
2467   CATCH_ALL;
2468 }
2469 
2470 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_OK(Prolog_term_ref t_mip)2471 ppl_MIP_Problem_OK(Prolog_term_ref t_mip) {
2472   static const char* where = "ppl_MIP_Problem_OK/1";
2473   try {
2474     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2475     PPL_CHECK(mip);
2476     if (mip->OK())
2477       return PROLOG_SUCCESS;
2478   }
2479   CATCH_ALL;
2480 }
2481 
2482 extern "C" Prolog_foreign_return_type
ppl_MIP_Problem_ascii_dump(Prolog_term_ref t_mip)2483 ppl_MIP_Problem_ascii_dump(Prolog_term_ref t_mip) {
2484   static const char* where = "ppl_MIP_Problem_ascii_dump/1";
2485   try {
2486     const MIP_Problem* mip = term_to_handle<MIP_Problem>(t_mip, where);
2487     PPL_CHECK(mip);
2488     mip->ascii_dump(std::cout);
2489     return PROLOG_SUCCESS;
2490   }
2491   CATCH_ALL;
2492 }
2493 
2494 extern "C" Prolog_foreign_return_type
ppl_new_PIP_Problem_from_space_dimension(Prolog_term_ref t_nd,Prolog_term_ref t_pip)2495 ppl_new_PIP_Problem_from_space_dimension
2496 (Prolog_term_ref t_nd, Prolog_term_ref t_pip) {
2497   static const char* where = "ppl_PIP_Problem_from_space_dimension/2";
2498   try {
2499     dimension_type d = term_to_unsigned<dimension_type>(t_nd, where);
2500     PIP_Problem* pip = new PIP_Problem(d);
2501     Prolog_term_ref tmp = Prolog_new_term_ref();
2502     Prolog_put_address(tmp, pip);
2503     if (Prolog_unify(t_pip, tmp)) {
2504       PPL_REGISTER(pip);
2505       return PROLOG_SUCCESS;
2506     }
2507     else
2508       delete pip;
2509   }
2510   CATCH_ALL;
2511 }
2512 
2513 extern "C" Prolog_foreign_return_type
ppl_new_PIP_Problem(Prolog_term_ref t_dim,Prolog_term_ref t_cs,Prolog_term_ref t_params,Prolog_term_ref t_pip)2514 ppl_new_PIP_Problem(Prolog_term_ref t_dim,
2515                     Prolog_term_ref t_cs,
2516                     Prolog_term_ref t_params,
2517                     Prolog_term_ref t_pip) {
2518   static const char* where = "ppl_new_PIP_Problem/4";
2519   try {
2520     dimension_type dim = term_to_unsigned<dimension_type>(t_dim, where);
2521     Constraint_System cs;
2522     Prolog_term_ref t_c = Prolog_new_term_ref();
2523     while (Prolog_is_cons(t_cs)) {
2524       Prolog_get_cons(t_cs, t_c, t_cs);
2525       cs.insert(build_constraint(t_c, where));
2526     }
2527     // Check the list is properly terminated.
2528     check_nil_terminating(t_cs, where);
2529 
2530     Variables_Set params;
2531     Prolog_term_ref t_par = Prolog_new_term_ref();
2532     while (Prolog_is_cons(t_params)) {
2533       Prolog_get_cons(t_params, t_par, t_params);
2534       params.insert(term_to_Variable(t_par, where).id());
2535     }
2536     // Check the list is properly terminated.
2537     check_nil_terminating(t_params, where);
2538 
2539     PIP_Problem* pip = new PIP_Problem(dim, cs.begin(), cs.end(), params);
2540     Prolog_term_ref tmp = Prolog_new_term_ref();
2541     Prolog_put_address(tmp, pip);
2542     if (Prolog_unify(t_pip, tmp)) {
2543       PPL_REGISTER(pip);
2544       return PROLOG_SUCCESS;
2545     }
2546     else
2547       delete pip;
2548   }
2549   CATCH_ALL;
2550 }
2551 
2552 extern "C" Prolog_foreign_return_type
ppl_new_PIP_Problem_from_PIP_Problem(Prolog_term_ref t_pip_source,Prolog_term_ref t_pip)2553 ppl_new_PIP_Problem_from_PIP_Problem(Prolog_term_ref t_pip_source,
2554                                      Prolog_term_ref t_pip) {
2555   static const char* where = "ppl_new_PIP_Problem_from_PIP_Problem/2";
2556   try {
2557     const PIP_Problem* pip_source
2558       = static_cast<const PIP_Problem*>
2559       (term_to_handle<PIP_Problem>(t_pip_source, where));
2560     PPL_CHECK(pip_source);
2561     PIP_Problem* pip = new PIP_Problem(*pip_source);
2562     Prolog_term_ref tmp = Prolog_new_term_ref();
2563     Prolog_put_address(tmp, pip);
2564     if (Prolog_unify(t_pip, tmp)) {
2565       PPL_REGISTER(pip);
2566       return PROLOG_SUCCESS;
2567     }
2568     else
2569       delete pip;
2570   }
2571   CATCH_ALL;
2572 }
2573 
2574 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_swap(Prolog_term_ref t_lhs,Prolog_term_ref t_rhs)2575 ppl_PIP_Problem_swap(Prolog_term_ref t_lhs, Prolog_term_ref t_rhs) {
2576   static const char* where = "ppl_PIP_Problem_swap/2";
2577   try {
2578     PIP_Problem* lhs = term_to_handle<PIP_Problem>(t_lhs, where);
2579     PIP_Problem* rhs = term_to_handle<PIP_Problem>(t_rhs, where);
2580     PPL_CHECK(lhs);
2581     PPL_CHECK(rhs);
2582     swap(*lhs, *rhs);
2583     return PROLOG_SUCCESS;
2584   }
2585   CATCH_ALL;
2586 }
2587 
2588 extern "C" Prolog_foreign_return_type
ppl_delete_PIP_Problem(Prolog_term_ref t_pip)2589 ppl_delete_PIP_Problem(Prolog_term_ref t_pip) {
2590   static const char* where = "ppl_delete_PIP_Problem/1";
2591   try {
2592     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2593     PPL_UNREGISTER(pip);
2594     delete pip;
2595     return PROLOG_SUCCESS;
2596   }
2597   CATCH_ALL;
2598 }
2599 
2600 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_space_dimension(Prolog_term_ref t_pip,Prolog_term_ref t_sd)2601 ppl_PIP_Problem_space_dimension(Prolog_term_ref t_pip, Prolog_term_ref t_sd) {
2602   static const char* where = "ppl_PIP_Problem_space_dimension/2";
2603   try {
2604     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2605     PPL_CHECK(pip);
2606     if (unify_ulong(t_sd, pip->space_dimension()))
2607       return PROLOG_SUCCESS;
2608   }
2609   CATCH_ALL;
2610 }
2611 
2612 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_parameter_space_dimensions(Prolog_term_ref t_pip,Prolog_term_ref t_vlist)2613 ppl_PIP_Problem_parameter_space_dimensions(Prolog_term_ref t_pip,
2614                                            Prolog_term_ref t_vlist) {
2615   static const char* where = "ppl_PIP_Problem_parameter_space_dimensions/2";
2616   try {
2617     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2618     PPL_CHECK(pip);
2619 
2620     Prolog_term_ref tail = Prolog_new_term_ref();
2621     Prolog_put_nil(tail);
2622     const Variables_Set& params = pip->parameter_space_dimensions();
2623 
2624     for (Variables_Set::const_iterator i = params.begin(),
2625            i_end = params.end(); i != i_end; ++i)
2626       Prolog_construct_cons(tail, variable_term(*i), tail);
2627 
2628     if (Prolog_unify(t_vlist, tail))
2629       return PROLOG_SUCCESS;
2630   }
2631   CATCH_ALL;
2632 }
2633 
2634 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_constraints(Prolog_term_ref t_pip,Prolog_term_ref t_clist)2635 ppl_PIP_Problem_constraints(Prolog_term_ref t_pip,
2636                             Prolog_term_ref t_clist) {
2637   static const char* where = "ppl_PIP_Problem_constraints/2";
2638   try {
2639     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2640     PPL_CHECK(pip);
2641 
2642     Prolog_term_ref tail = Prolog_new_term_ref();
2643     Prolog_put_nil(tail);
2644     for (PIP_Problem::const_iterator i = pip->constraints_begin(),
2645            i_end = pip->constraints_end(); i != i_end; ++i)
2646       Prolog_construct_cons(tail, constraint_term(*i), tail);
2647 
2648     if (Prolog_unify(t_clist, tail))
2649       return PROLOG_SUCCESS;
2650   }
2651   CATCH_ALL;
2652 }
2653 
2654 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_clear(Prolog_term_ref t_pip)2655 ppl_PIP_Problem_clear(Prolog_term_ref t_pip) {
2656   static const char* where = "ppl_PIP_Problem_clear/1";
2657   try {
2658     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2659     PPL_CHECK(pip);
2660     pip->clear();
2661     return PROLOG_SUCCESS;
2662   }
2663   CATCH_ALL;
2664 }
2665 
2666 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_add_space_dimensions_and_embed(Prolog_term_ref t_pip,Prolog_term_ref t_num_vars,Prolog_term_ref t_num_params)2667 ppl_PIP_Problem_add_space_dimensions_and_embed
2668 (Prolog_term_ref t_pip,
2669  Prolog_term_ref t_num_vars,
2670  Prolog_term_ref t_num_params) {
2671   static const char* where
2672     = "ppl_PIP_Problem_add_space_dimensions_and_embed/3";
2673   try {
2674     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2675     PPL_CHECK(pip);
2676     dimension_type nv = term_to_unsigned<dimension_type>(t_num_vars, where);
2677     dimension_type np = term_to_unsigned<dimension_type>(t_num_params, where);
2678     pip->add_space_dimensions_and_embed(nv, np);
2679     return PROLOG_SUCCESS;
2680   }
2681   CATCH_ALL;
2682 }
2683 
2684 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_add_to_parameter_space_dimensions(Prolog_term_ref t_pip,Prolog_term_ref t_vlist)2685 ppl_PIP_Problem_add_to_parameter_space_dimensions(Prolog_term_ref t_pip,
2686                                                   Prolog_term_ref t_vlist) {
2687   static const char* where
2688     = "ppl_PIP_Problem_add_to_parameter_space_dimensions/2";
2689   try {
2690     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2691     PPL_CHECK(pip);
2692     Variables_Set params;
2693     Prolog_term_ref v = Prolog_new_term_ref();
2694 
2695     while (Prolog_is_cons(t_vlist)) {
2696       Prolog_get_cons(t_vlist, v, t_vlist);
2697       params.insert(term_to_Variable(v, where).id());
2698     }
2699 
2700     // Check the list is properly terminated.
2701     check_nil_terminating(t_vlist, where);
2702 
2703     pip->add_to_parameter_space_dimensions(params);
2704     return PROLOG_SUCCESS;
2705   }
2706   CATCH_ALL;
2707 }
2708 
2709 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_add_constraint(Prolog_term_ref t_pip,Prolog_term_ref t_c)2710 ppl_PIP_Problem_add_constraint(Prolog_term_ref t_pip, Prolog_term_ref t_c) {
2711   static const char* where = "ppl_PIP_Problem_add_constraint/2";
2712   try {
2713     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2714     PPL_CHECK(pip);
2715     pip->add_constraint(build_constraint(t_c, where));
2716     return PROLOG_SUCCESS;
2717   }
2718   CATCH_ALL;
2719 }
2720 
2721 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_add_constraints(Prolog_term_ref t_pip,Prolog_term_ref t_clist)2722 ppl_PIP_Problem_add_constraints(Prolog_term_ref t_pip,
2723                                 Prolog_term_ref t_clist) {
2724   static const char* where = "ppl_PIP_Problem_add_constraints/2";
2725   try {
2726     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2727     PPL_CHECK(pip);
2728     Constraint_System cs;
2729     Prolog_term_ref c = Prolog_new_term_ref();
2730 
2731     while (Prolog_is_cons(t_clist)) {
2732       Prolog_get_cons(t_clist, c, t_clist);
2733       cs.insert(build_constraint(c, where));
2734     }
2735 
2736     // Check the list is properly terminated.
2737     check_nil_terminating(t_clist, where);
2738 
2739     pip->add_constraints(cs);
2740     return PROLOG_SUCCESS;
2741   }
2742   CATCH_ALL;
2743 }
2744 
2745 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_get_control_parameter(Prolog_term_ref t_pip,Prolog_term_ref t_cp_name,Prolog_term_ref t_cp_value)2746 ppl_PIP_Problem_get_control_parameter(Prolog_term_ref t_pip,
2747                                       Prolog_term_ref t_cp_name,
2748                                       Prolog_term_ref t_cp_value) {
2749   static const char* where = "ppl_PIP_Problem_get_control_parameter/3";
2750   try {
2751     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2752     PPL_CHECK(pip);
2753     Prolog_atom cp_name = term_to_pip_problem_control_parameter_name(t_cp_name, where);
2754     PIP_Problem::Control_Parameter_Value ppl_cp_value;
2755     Prolog_atom a;
2756     if (cp_name == a_cutting_strategy) {
2757       ppl_cp_value
2758         = pip->get_control_parameter(PIP_Problem::CUTTING_STRATEGY);
2759       switch (ppl_cp_value) {
2760       case PIP_Problem::CUTTING_STRATEGY_FIRST:
2761         a = a_cutting_strategy_first;
2762         break;
2763       case PIP_Problem::CUTTING_STRATEGY_DEEPEST:
2764         a = a_cutting_strategy_deepest;
2765         break;
2766       case PIP_Problem::CUTTING_STRATEGY_ALL:
2767         a = a_cutting_strategy_all;
2768         break;
2769       default:
2770         throw unknown_interface_error(
2771           "ppl_PIP_Problem_get_control_parameter()");
2772       }
2773     }
2774     else if (cp_name == a_pivot_row_strategy) {
2775       ppl_cp_value
2776         = pip->get_control_parameter(PIP_Problem::PIVOT_ROW_STRATEGY);
2777       switch (ppl_cp_value) {
2778       case PIP_Problem::PIVOT_ROW_STRATEGY_FIRST:
2779         a = a_pivot_row_strategy_first;
2780         break;
2781       case PIP_Problem::PIVOT_ROW_STRATEGY_MAX_COLUMN:
2782         a = a_pivot_row_strategy_max_column;
2783         break;
2784       default:
2785         throw unknown_interface_error(
2786           "ppl_PIP_Problem_get_control_parameter()");
2787       }
2788     }
2789     else
2790       throw unknown_interface_error("ppl_PIP_Problem_get_control_parameter()");
2791 
2792     Prolog_term_ref t = Prolog_new_term_ref();
2793     Prolog_put_atom(t, a);
2794     if (Prolog_unify(t_cp_value, t))
2795       return PROLOG_SUCCESS;
2796   }
2797   CATCH_ALL;
2798 }
2799 
2800 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_set_control_parameter(Prolog_term_ref t_pip,Prolog_term_ref t_cp_value)2801 ppl_PIP_Problem_set_control_parameter(Prolog_term_ref t_pip,
2802                                       Prolog_term_ref t_cp_value) {
2803   static const char* where = "ppl_PIP_Problem_set_control_parameter/2";
2804   try {
2805     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2806     PPL_CHECK(pip);
2807 
2808     Prolog_atom cp_value = term_to_pip_problem_control_parameter_value(t_cp_value, where);
2809     if (cp_value == a_cutting_strategy_first)
2810       pip->set_control_parameter(PIP_Problem::CUTTING_STRATEGY_FIRST);
2811     else if (cp_value == a_cutting_strategy_deepest)
2812       pip->set_control_parameter(PIP_Problem::CUTTING_STRATEGY_DEEPEST);
2813     else if (cp_value == a_cutting_strategy_all)
2814       pip->set_control_parameter(PIP_Problem::CUTTING_STRATEGY_ALL);
2815     else if (cp_value == a_pivot_row_strategy_first)
2816       pip->set_control_parameter(PIP_Problem::PIVOT_ROW_STRATEGY_FIRST);
2817     else if (cp_value == a_pivot_row_strategy_max_column)
2818       pip->set_control_parameter(PIP_Problem::PIVOT_ROW_STRATEGY_MAX_COLUMN);
2819     else
2820       throw unknown_interface_error("ppl_PIP_Problem_set_control_parameter()");
2821     return PROLOG_SUCCESS;
2822   }
2823   CATCH_ALL;
2824 }
2825 
2826 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_has_big_parameter_dimension(Prolog_term_ref t_pip,Prolog_term_ref t_d)2827 ppl_PIP_Problem_has_big_parameter_dimension(Prolog_term_ref t_pip,
2828                                             Prolog_term_ref t_d) {
2829   static const char* where = "ppl_PIP_Problem_get_big_parameter_dimension/2";
2830   try {
2831     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2832     PPL_CHECK(pip);
2833     dimension_type dim = pip->get_big_parameter_dimension();
2834     if (dim == not_a_dimension())
2835       return PROLOG_FAILURE;
2836     if (unify_ulong(t_d, dim))
2837       return PROLOG_SUCCESS;
2838   }
2839   CATCH_ALL;
2840 }
2841 
2842 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_set_big_parameter_dimension(Prolog_term_ref t_pip,Prolog_term_ref t_d)2843 ppl_PIP_Problem_set_big_parameter_dimension(Prolog_term_ref t_pip,
2844                                             Prolog_term_ref t_d) {
2845   static const char* where = "ppl_MIP_Problem_set_big_parameter_dimension/2";
2846   try {
2847     PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2848     PPL_CHECK(pip);
2849     dimension_type d = term_to_unsigned<dimension_type>(t_d, where);
2850     pip->set_big_parameter_dimension(d);
2851     return PROLOG_SUCCESS;
2852   }
2853   CATCH_ALL;
2854 }
2855 
2856 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_is_satisfiable(Prolog_term_ref t_pip)2857 ppl_PIP_Problem_is_satisfiable(Prolog_term_ref t_pip) {
2858   static const char* where = "ppl_PIP_Problem_is_satisfiable/1";
2859   try {
2860     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2861     PPL_CHECK(pip);
2862     if (pip->is_satisfiable())
2863       return PROLOG_SUCCESS;
2864   }
2865   CATCH_ALL;
2866 }
2867 
2868 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_solve(Prolog_term_ref t_pip,Prolog_term_ref t_status)2869 ppl_PIP_Problem_solve(Prolog_term_ref t_pip, Prolog_term_ref t_status) {
2870   static const char* where = "ppl_PIP_Problem_solve/2";
2871   try {
2872     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2873     PPL_CHECK(pip);
2874 
2875     Prolog_atom a;
2876     switch (pip->solve()) {
2877     case UNFEASIBLE_PIP_PROBLEM:
2878       a = a_unfeasible;
2879       break;
2880     case OPTIMIZED_PIP_PROBLEM:
2881       a = a_optimized;
2882       break;
2883     default:
2884       throw unknown_interface_error("ppl_PIP_Problem_solve()");
2885     }
2886     Prolog_term_ref t = Prolog_new_term_ref();
2887     Prolog_put_atom(t, a);
2888     if (Prolog_unify(t_status, t))
2889       return PROLOG_SUCCESS;
2890   }
2891   CATCH_ALL;
2892 }
2893 
2894 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_solution(Prolog_term_ref t_pip,Prolog_term_ref t_pip_tree)2895 ppl_PIP_Problem_solution(Prolog_term_ref t_pip,
2896                          Prolog_term_ref t_pip_tree) {
2897   static const char* where = "ppl_PIP_Problem_solution/2";
2898   try {
2899     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2900     PPL_CHECK(pip);
2901     PIP_Tree_Node* sol = const_cast<PIP_Tree_Node*>(pip->solution());
2902     Prolog_term_ref t_sol = Prolog_new_term_ref();
2903     Prolog_put_address(t_sol, sol);
2904     if (Prolog_unify(t_pip_tree, t_sol)) {
2905       PPL_WEAK_REGISTER(sol);
2906       return PROLOG_SUCCESS;
2907     }
2908  }
2909  CATCH_ALL;
2910 }
2911 
2912 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_optimizing_solution(Prolog_term_ref t_pip,Prolog_term_ref t_pip_tree)2913 ppl_PIP_Problem_optimizing_solution(Prolog_term_ref t_pip,
2914                                     Prolog_term_ref t_pip_tree) {
2915   static const char* where = "ppl_PIP_Problem_optimizing_solution/2";
2916   try {
2917     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2918     PPL_CHECK(pip);
2919     PIP_Tree_Node* sol = const_cast<PIP_Tree_Node*>(pip->optimizing_solution());
2920     Prolog_term_ref t_sol = Prolog_new_term_ref();
2921     Prolog_put_address(t_sol, sol);
2922     if (Prolog_unify(t_pip_tree, t_sol)) {
2923       PPL_WEAK_REGISTER(sol);
2924       return PROLOG_SUCCESS;
2925     }
2926  }
2927  CATCH_ALL;
2928 }
2929 
2930 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_OK(Prolog_term_ref t_pip)2931 ppl_PIP_Problem_OK(Prolog_term_ref t_pip) {
2932   static const char* where = "ppl_PIP_Problem_OK/1";
2933   try {
2934     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2935     PPL_CHECK(pip);
2936     if (pip->OK())
2937       return PROLOG_SUCCESS;
2938   }
2939   CATCH_ALL;
2940 }
2941 
2942 extern "C" Prolog_foreign_return_type
ppl_PIP_Problem_ascii_dump(Prolog_term_ref t_pip)2943 ppl_PIP_Problem_ascii_dump(Prolog_term_ref t_pip) {
2944   static const char* where = "ppl_PIP_Problem_ascii_dump/1";
2945   try {
2946     const PIP_Problem* pip = term_to_handle<PIP_Problem>(t_pip, where);
2947     PPL_CHECK(pip);
2948     pip->ascii_dump(std::cout);
2949     return PROLOG_SUCCESS;
2950   }
2951   CATCH_ALL;
2952 }
2953 
2954 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_constraints(Prolog_term_ref t_pip,Prolog_term_ref t_cs)2955 ppl_PIP_Tree_Node_constraints(Prolog_term_ref t_pip,
2956                               Prolog_term_ref t_cs) {
2957   static const char* where = "ppl_PIP_Tree_Node_constraints/2";
2958   try {
2959     const PIP_Tree_Node* pip = term_to_handle<PIP_Tree_Node>(t_pip, where);
2960     PPL_CHECK(pip);
2961 
2962     Prolog_term_ref tail = Prolog_new_term_ref();
2963     Prolog_put_nil(tail);
2964     const Constraint_System& ppl_cs = pip->constraints();
2965     for (Constraint_System::const_iterator i = ppl_cs.begin(),
2966            ppl_cs_end = ppl_cs.end(); i != ppl_cs_end; ++i)
2967       Prolog_construct_cons(tail, constraint_term(*i), tail);
2968 
2969     if (Prolog_unify(t_cs, tail)) {
2970       return PROLOG_SUCCESS;
2971     }
2972   }
2973   CATCH_ALL;
2974 }
2975 
2976 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_is_solution(Prolog_term_ref t_pip)2977 ppl_PIP_Tree_Node_is_solution(Prolog_term_ref t_pip) {
2978   static const char* where = "ppl_PIP_Tree_Node_as_solution/2";
2979   try {
2980     const PIP_Tree_Node* pip = term_to_handle<PIP_Tree_Node>(t_pip, where);
2981     PPL_CHECK(pip);
2982 
2983     if (pip != 0 && pip->as_solution() != 0)
2984       return PROLOG_SUCCESS;
2985     return PROLOG_FAILURE;
2986   }
2987   CATCH_ALL;
2988 }
2989 
2990 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_is_decision(Prolog_term_ref t_pip)2991 ppl_PIP_Tree_Node_is_decision(Prolog_term_ref t_pip) {
2992   static const char* where = "ppl_PIP_Tree_Node_as_decision/2";
2993   try {
2994     const PIP_Tree_Node* pip = term_to_handle<PIP_Tree_Node>(t_pip, where);
2995     PPL_CHECK(pip);
2996 
2997     if (pip != 0 && pip->as_decision() != 0)
2998       return PROLOG_SUCCESS;
2999     return PROLOG_FAILURE;
3000   }
3001   CATCH_ALL;
3002 }
3003 
3004 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_is_bottom(Prolog_term_ref t_pip)3005 ppl_PIP_Tree_Node_is_bottom(Prolog_term_ref t_pip) {
3006   static const char* where = "ppl_PIP_Tree_Node_as_decision/2";
3007   try {
3008     const PIP_Tree_Node* pip = term_to_handle<PIP_Tree_Node>(t_pip, where);
3009     PPL_CHECK(pip);
3010 
3011     if (pip == 0)
3012       return PROLOG_SUCCESS;
3013     return PROLOG_FAILURE;
3014   }
3015   CATCH_ALL;
3016 }
3017 
3018 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_artificials(Prolog_term_ref t_tree_node,Prolog_term_ref t_artlist)3019 ppl_PIP_Tree_Node_artificials(Prolog_term_ref t_tree_node,
3020                               Prolog_term_ref t_artlist) {
3021   static const char* where = "ppl_PIP_Tree_Node_artificials/2";
3022   try {
3023     const PIP_Tree_Node* node
3024       = term_to_handle<PIP_Tree_Node>(t_tree_node, where);
3025     PPL_CHECK(node);
3026 
3027     Prolog_term_ref tail = Prolog_new_term_ref();
3028     Prolog_put_nil(tail);
3029     for (PIP_Tree_Node::Artificial_Parameter_Sequence::const_iterator
3030            i = node->art_parameter_begin(),
3031            arts_end = node->art_parameter_end(); i != arts_end; ++i)
3032       Prolog_construct_cons(tail, artificial_parameter_term(*i), tail);
3033 
3034     if (Prolog_unify(t_artlist, tail))
3035       return PROLOG_SUCCESS;
3036   }
3037   CATCH_ALL;
3038 }
3039 
3040 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_parametric_values(Prolog_term_ref t_pip,Prolog_term_ref t_var,Prolog_term_ref t_le)3041 ppl_PIP_Tree_Node_parametric_values(Prolog_term_ref t_pip,
3042                                             Prolog_term_ref t_var,
3043                                             Prolog_term_ref t_le) {
3044   static const char* where = "ppl_PIP_Solution_Node_get_parametric_values/3";
3045   try {
3046     const PIP_Solution_Node* pip
3047       = term_to_handle<PIP_Solution_Node>(t_pip, where);
3048     PPL_CHECK(pip);
3049     Variable var = term_to_Variable(t_var, where);
3050     if (Prolog_unify(t_le, get_linear_expression(pip->parametric_values(var))))
3051       return PROLOG_SUCCESS;
3052   }
3053   CATCH_ALL;
3054 }
3055 
3056 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_true_child(Prolog_term_ref t_pip,Prolog_term_ref t_ptree)3057 ppl_PIP_Tree_Node_true_child(Prolog_term_ref t_pip,
3058                                      Prolog_term_ref t_ptree) {
3059   static const char* where = "ppl_PIP_Decision_Node_get_true_child/2";
3060   try {
3061     const PIP_Decision_Node* pip
3062       = term_to_handle<PIP_Decision_Node>(t_pip, where);
3063     PPL_CHECK(pip);
3064     bool b = true;
3065     PIP_Tree_Node* ppl_ptree = const_cast<PIP_Tree_Node*>(pip->child_node(b));
3066     Prolog_term_ref t_ppl_ptree = Prolog_new_term_ref();
3067     Prolog_put_address(t_ppl_ptree, ppl_ptree);
3068     if (Prolog_unify(t_ptree, t_ppl_ptree)) {
3069       PPL_WEAK_REGISTER(ppl_ptree);
3070       return PROLOG_SUCCESS;
3071     }
3072   }
3073   CATCH_ALL;
3074 }
3075 
3076 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_false_child(Prolog_term_ref t_pip,Prolog_term_ref t_ptree)3077 ppl_PIP_Tree_Node_false_child(Prolog_term_ref t_pip,
3078                                       Prolog_term_ref t_ptree) {
3079   static const char* where = "ppl_PIP_Decision_Node_get_false_child/2";
3080   try {
3081     const PIP_Decision_Node* pip
3082       = term_to_handle<PIP_Decision_Node>(t_pip, where);
3083     PPL_CHECK(pip);
3084     bool b = false;
3085     PIP_Tree_Node* ppl_ptree = const_cast<PIP_Tree_Node*>(pip->child_node(b));
3086     Prolog_term_ref t_ppl_ptree = Prolog_new_term_ref();
3087     Prolog_put_address(t_ppl_ptree, ppl_ptree);
3088     if (Prolog_unify(t_ptree, t_ppl_ptree)) {
3089       PPL_WEAK_REGISTER(ppl_ptree);
3090       return PROLOG_SUCCESS;
3091     }
3092   }
3093   CATCH_ALL;
3094 }
3095 
3096 extern "C" Prolog_foreign_return_type
ppl_PIP_Tree_Node_OK(Prolog_term_ref t_pip)3097 ppl_PIP_Tree_Node_OK(Prolog_term_ref t_pip) {
3098   static const char* where = "ppl_PIP_Tree_Node_OK/1";
3099   try {
3100     const PIP_Tree_Node* pip = term_to_handle<PIP_Tree_Node>(t_pip, where);
3101     PPL_CHECK(pip);
3102     if (pip->OK())
3103       return PROLOG_SUCCESS;
3104   }
3105   CATCH_ALL;
3106 }
3107