1 /* PPL Java interface common routines implementation.
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_java_common_defs.hh"
25 
26 namespace Parma_Polyhedra_Library {
27 
28 namespace Interfaces {
29 
30 namespace Java {
31 
32 // Define class and field/method ID caches.
33 Java_Class_Cache cached_classes;
34 Java_FMID_Cache cached_FMIDs;
35 
Java_Class_Cache()36 Java_Class_Cache::Java_Class_Cache() {
37   // Java Virtual Machine pointer.
38   jvm = NULL;
39   // Non-PPL classes.
40   Boolean = NULL;
41   Integer = NULL;
42   Long = NULL;
43   Iterator = NULL;
44   // PPL classes.
45   Artificial_Parameter = NULL;
46   Artificial_Parameter_Sequence = NULL;
47   Bounded_Integer_Type_Overflow = NULL;
48   Bounded_Integer_Type_Representation = NULL;
49   Bounded_Integer_Type_Width = NULL;
50   By_Reference = NULL;
51   Coefficient = NULL;
52   Congruence = NULL;
53   Constraint = NULL;
54   Generator = NULL;
55   Grid_Generator = NULL;
56   Generator_Type = NULL;
57   Grid_Generator_Type = NULL;
58   Constraint_System = NULL;
59   Congruence_System = NULL;
60   Generator_System = NULL;
61   Grid_Generator_System = NULL;
62   Linear_Expression = NULL;
63   Linear_Expression_Coefficient = NULL;
64   Linear_Expression_Difference = NULL;
65   Linear_Expression_Sum = NULL;
66   Linear_Expression_Times = NULL;
67   Linear_Expression_Unary_Minus = NULL;
68   Linear_Expression_Variable = NULL;
69   MIP_Problem_Status = NULL;
70   Optimization_Mode = NULL;
71   Pair = NULL;
72   PIP_Problem_Control_Parameter_Name = NULL;
73   PIP_Problem_Control_Parameter_Value = NULL;
74   PIP_Problem_Status = NULL;
75   Poly_Con_Relation = NULL;
76   Poly_Gen_Relation = NULL;
77   PPL_Object = NULL;
78   Relation_Symbol = NULL;
79   Variable = NULL;
80   Variable_Stringifier = NULL;
81   Variables_Set = NULL;
82 }
83 
84 void
init_cache(JNIEnv * env,jclass & field,const char * name)85 Java_Class_Cache::init_cache(JNIEnv* env, jclass& field, const char* name) {
86   assert(env != NULL);
87   if (field != NULL) {
88     env->DeleteGlobalRef(field);
89   }
90   jclass jni_class = env->FindClass(name);
91   CHECK_RESULT_ASSERT(env, jni_class);
92   field = (jclass) env->NewGlobalRef(jni_class);
93   CHECK_RESULT_ASSERT(env, field);
94 }
95 
96 void
init_cache(JNIEnv * env)97 Java_Class_Cache::init_cache(JNIEnv* env) {
98   assert(env != NULL);
99   // Java Virtual Machine pointer.
100   env->GetJavaVM(&jvm);
101   // Non-PPL classes.
102   init_cache(env, Boolean, "java/lang/Boolean");
103   init_cache(env, Integer, "java/lang/Integer");
104   init_cache(env, Long, "java/lang/Long");
105   init_cache(env, Iterator, "java/util/Iterator");
106   // PPL classes.
107   init_cache(env, Artificial_Parameter,
108              "parma_polyhedra_library/Artificial_Parameter");
109   init_cache(env, Artificial_Parameter_Sequence,
110              "parma_polyhedra_library/Artificial_Parameter_Sequence");
111   init_cache(env, Bounded_Integer_Type_Overflow, "parma_polyhedra_library/Bounded_Integer_Type_Overflow");
112   init_cache(env, Bounded_Integer_Type_Representation, "parma_polyhedra_library/Bounded_Integer_Type_Representation");
113   init_cache(env, Bounded_Integer_Type_Width, "parma_polyhedra_library/Bounded_Integer_Type_Width");
114   init_cache(env, By_Reference, "parma_polyhedra_library/By_Reference");
115   init_cache(env, Coefficient, "parma_polyhedra_library/Coefficient");
116   init_cache(env, Congruence, "parma_polyhedra_library/Congruence");
117   init_cache(env, Constraint, "parma_polyhedra_library/Constraint");
118   init_cache(env, Generator, "parma_polyhedra_library/Generator");
119   init_cache(env, Grid_Generator, "parma_polyhedra_library/Grid_Generator");
120   init_cache(env, Generator_Type, "parma_polyhedra_library/Generator_Type");
121   init_cache(env, Grid_Generator_Type,
122              "parma_polyhedra_library/Grid_Generator_Type");
123   init_cache(env, Constraint_System,
124              "parma_polyhedra_library/Constraint_System");
125   init_cache(env, Congruence_System,
126              "parma_polyhedra_library/Congruence_System");
127   init_cache(env, Generator_System,
128              "parma_polyhedra_library/Generator_System");
129   init_cache(env, Grid_Generator_System,
130              "parma_polyhedra_library/Grid_Generator_System");
131   init_cache(env, Linear_Expression,
132              "parma_polyhedra_library/Linear_Expression");
133   init_cache(env, Linear_Expression_Coefficient,
134              "parma_polyhedra_library/Linear_Expression_Coefficient");
135   init_cache(env, Linear_Expression_Difference,
136              "parma_polyhedra_library/Linear_Expression_Difference");
137   init_cache(env, Linear_Expression_Sum,
138              "parma_polyhedra_library/Linear_Expression_Sum");
139   init_cache(env, Linear_Expression_Times,
140              "parma_polyhedra_library/Linear_Expression_Times");
141   init_cache(env, Linear_Expression_Unary_Minus,
142              "parma_polyhedra_library/Linear_Expression_Unary_Minus");
143   init_cache(env, Linear_Expression_Variable,
144              "parma_polyhedra_library/Linear_Expression_Variable");
145   init_cache(env, MIP_Problem_Status,
146              "parma_polyhedra_library/MIP_Problem_Status");
147   init_cache(env, Optimization_Mode,
148              "parma_polyhedra_library/Optimization_Mode");
149   init_cache(env, Pair, "parma_polyhedra_library/Pair");
150   init_cache(env, PIP_Problem_Control_Parameter_Name,
151              "parma_polyhedra_library/PIP_Problem_Control_Parameter_Name");
152   init_cache(env, PIP_Problem_Control_Parameter_Value,
153              "parma_polyhedra_library/PIP_Problem_Control_Parameter_Value");
154   init_cache(env, PIP_Problem_Status,
155              "parma_polyhedra_library/PIP_Problem_Status");
156   init_cache(env, Poly_Con_Relation,
157              "parma_polyhedra_library/Poly_Con_Relation");
158   init_cache(env, Poly_Gen_Relation,
159              "parma_polyhedra_library/Poly_Gen_Relation");
160   init_cache(env, PPL_Object, "parma_polyhedra_library/PPL_Object");
161   init_cache(env, Relation_Symbol, "parma_polyhedra_library/Relation_Symbol");
162   init_cache(env, Variable, "parma_polyhedra_library/Variable");
163   // NOTE: initialization of concrete Variable_Stringifier is responsibility
164   // of static (native) method Variable.setStringifier.
165   init_cache(env, Variables_Set, "parma_polyhedra_library/Variables_Set");
166 }
167 
168 void
clear_cache(JNIEnv * env,jclass & field)169 Java_Class_Cache::clear_cache(JNIEnv* env, jclass& field) {
170   assert(env != NULL);
171   if (field != NULL) {
172     env->DeleteGlobalRef(field);
173     field = NULL;
174   }
175 }
176 
177 void
clear_cache(JNIEnv * env)178 Java_Class_Cache::clear_cache(JNIEnv* env) {
179   assert(env != NULL);
180   // Clearing the JVM pointer.
181   jvm = NULL;
182   // Non-PPL classes.
183   clear_cache(env, Boolean);
184   clear_cache(env, Integer);
185   clear_cache(env, Long);
186   clear_cache(env, Iterator);
187   // PPL classes.
188   clear_cache(env, Artificial_Parameter);
189   clear_cache(env, Artificial_Parameter_Sequence);
190   clear_cache(env, Bounded_Integer_Type_Overflow);
191   clear_cache(env, Bounded_Integer_Type_Representation);
192   clear_cache(env, Bounded_Integer_Type_Width);
193   clear_cache(env, By_Reference);
194   clear_cache(env, Coefficient);
195   clear_cache(env, Congruence);
196   clear_cache(env, Constraint);
197   clear_cache(env, Generator);
198   clear_cache(env, Grid_Generator);
199   clear_cache(env, Generator_Type);
200   clear_cache(env, Grid_Generator_Type);
201   clear_cache(env, Constraint_System);
202   clear_cache(env, Congruence_System);
203   clear_cache(env, Generator_System);
204   clear_cache(env, Grid_Generator_System);
205   clear_cache(env, Linear_Expression);
206   clear_cache(env, Linear_Expression_Coefficient);
207   clear_cache(env, Linear_Expression_Difference);
208   clear_cache(env, Linear_Expression_Sum);
209   clear_cache(env, Linear_Expression_Times);
210   clear_cache(env, Linear_Expression_Unary_Minus);
211   clear_cache(env, Linear_Expression_Variable);
212   clear_cache(env, MIP_Problem_Status);
213   clear_cache(env, Optimization_Mode);
214   clear_cache(env, PIP_Problem_Status);
215   clear_cache(env, Pair);
216   clear_cache(env, Poly_Con_Relation);
217   clear_cache(env, Poly_Gen_Relation);
218   clear_cache(env, PPL_Object);
219   clear_cache(env, Relation_Symbol);
220   clear_cache(env, Variable);
221   clear_cache(env, Variable_Stringifier);
222   clear_cache(env, Variables_Set);
223 }
224 
225 void
handle_exception(JNIEnv * env,const std::overflow_error & e)226 handle_exception(JNIEnv* env, const std::overflow_error& e) {
227   jclass newExcCls
228     = env->FindClass("parma_polyhedra_library/Overflow_Error_Exception");
229   CHECK_RESULT_ASSERT(env, newExcCls);
230   jint ret = env->ThrowNew(newExcCls, e.what());
231   CHECK_RESULT_ABORT(env, ret == 0);
232 }
233 
234 void
handle_exception(JNIEnv * env,const std::invalid_argument & e)235 handle_exception(JNIEnv* env, const std::invalid_argument& e) {
236   jclass newExcCls
237     = env->FindClass("parma_polyhedra_library/Invalid_Argument_Exception");
238   CHECK_RESULT_ASSERT(env, newExcCls);
239   jint ret = env->ThrowNew(newExcCls, e.what());
240   CHECK_RESULT_ABORT(env, ret == 0);
241 }
242 
243 void
handle_exception(JNIEnv * env,const std::logic_error & e)244 handle_exception(JNIEnv* env, const std::logic_error& e) {
245   jclass newExcCls
246     = env->FindClass("parma_polyhedra_library/Logic_Error_Exception");
247   CHECK_RESULT_ASSERT(env, newExcCls);
248   jint ret = env->ThrowNew(newExcCls, e.what());
249   CHECK_RESULT_ABORT(env, ret == 0);
250 }
251 
252 void
handle_exception(JNIEnv * env,const std::length_error & e)253 handle_exception(JNIEnv* env, const std::length_error& e) {
254   jclass newExcCls
255     = env->FindClass("parma_polyhedra_library/Length_Error_Exception");
256   CHECK_RESULT_ASSERT(env, newExcCls);
257   jint ret = env->ThrowNew(newExcCls, e.what());
258   CHECK_RESULT_ABORT(env, ret == 0);
259 }
260 
261 void
handle_exception(JNIEnv * env,const std::domain_error & e)262 handle_exception(JNIEnv* env, const std::domain_error& e) {
263   jclass newExcCls
264     = env->FindClass("parma_polyhedra_library/Domain_Error_Exception");
265   CHECK_RESULT_ASSERT(env, newExcCls);
266   jint ret = env->ThrowNew(newExcCls, e.what());
267   CHECK_RESULT_ABORT(env, ret == 0);
268 }
269 
270 void
handle_exception(JNIEnv * env,const std::bad_alloc &)271 handle_exception(JNIEnv* env, const std::bad_alloc&) {
272   jclass newExcCls
273     = env->FindClass("java/lang/RuntimeException");
274   CHECK_RESULT_ASSERT(env, newExcCls);
275   jint ret = env->ThrowNew(newExcCls, "Out of memory");
276   CHECK_RESULT_ABORT(env, ret == 0);
277 }
278 
279 void
handle_exception(JNIEnv * env,const std::exception & e)280 handle_exception(JNIEnv* env, const std::exception& e) {
281   jclass newExcCls = env->FindClass("java/lang/RuntimeException");
282   CHECK_RESULT_ASSERT(env, newExcCls);
283   jint ret = env->ThrowNew(newExcCls, e.what());
284   CHECK_RESULT_ABORT(env, ret == 0);
285 }
286 
287 void
handle_exception(JNIEnv * env,const timeout_exception &)288 handle_exception(JNIEnv* env, const timeout_exception&) {
289   reset_timeout();
290   jclass newExcCls
291     = env->FindClass("parma_polyhedra_library/Timeout_Exception");
292   CHECK_RESULT_ASSERT(env, newExcCls);
293   jint ret = env->ThrowNew(newExcCls, "PPL timeout expired");
294   CHECK_RESULT_ABORT(env, (ret == 0));
295 }
296 
297 void
handle_exception(JNIEnv * env,const deterministic_timeout_exception &)298 handle_exception(JNIEnv* env, const deterministic_timeout_exception&) {
299   reset_deterministic_timeout();
300   jclass newExcCls
301     = env->FindClass("parma_polyhedra_library/Timeout_Exception");
302   CHECK_RESULT_ASSERT(env, newExcCls);
303   jint ret = env->ThrowNew(newExcCls, "PPL deterministic timeout expired");
304   CHECK_RESULT_ABORT(env, (ret == 0));
305 }
306 
307 void
handle_exception(JNIEnv * env)308 handle_exception(JNIEnv* env) {
309   jclass newExcCls = env->FindClass("java/lang/RuntimeException");
310   CHECK_RESULT_ASSERT(env, newExcCls);
311   jint ret = env->ThrowNew(newExcCls, "PPL bug: unknown exception raised");
312   CHECK_RESULT_ABORT(env, ret == 0);
313 }
314 
315 Parma_Polyhedra_Library::Watchdog* p_timeout_object = 0;
316 
317 Weightwatch* p_deterministic_timeout_object = 0;
318 
319 void
reset_timeout()320 reset_timeout() {
321   if (p_timeout_object) {
322     delete p_timeout_object;
323     p_timeout_object = 0;
324     abandon_expensive_computations = 0;
325   }
326 }
327 
328 void
reset_deterministic_timeout()329 reset_deterministic_timeout() {
330   if (p_deterministic_timeout_object) {
331     delete p_deterministic_timeout_object;
332     p_deterministic_timeout_object = 0;
333     abandon_expensive_computations = 0;
334   }
335 }
336 
337 jobject
build_java_poly_gen_relation(JNIEnv * env,Poly_Gen_Relation & r)338 build_java_poly_gen_relation(JNIEnv* env, Poly_Gen_Relation& r) {
339   jint j_value = 0;
340   while (r != Poly_Gen_Relation::nothing()) {
341     if (r.implies(Poly_Gen_Relation::subsumes())) {
342       j_value += 1;
343       r = r - Poly_Gen_Relation::subsumes();
344     }
345   }
346   jobject ret = env->NewObject(cached_classes.Poly_Gen_Relation,
347                                cached_FMIDs.Poly_Gen_Relation_init_ID,
348                                j_value);
349   CHECK_RESULT_THROW(env, ret);
350   return ret;
351 }
352 
353 jobject
build_java_poly_con_relation(JNIEnv * env,Poly_Con_Relation & r)354 build_java_poly_con_relation(JNIEnv* env, Poly_Con_Relation& r) {
355   jint j_value = 0;
356   while (r != Poly_Con_Relation::nothing()) {
357     if (r.implies(Poly_Con_Relation::is_disjoint())) {
358       j_value += 1;
359       r = r - Poly_Con_Relation::is_disjoint();
360     }
361     else if (r.implies(Poly_Con_Relation::strictly_intersects())) {
362       j_value += 2;
363       r = r - Poly_Con_Relation::strictly_intersects();
364     }
365     else if (r.implies(Poly_Con_Relation::is_included())) {
366       j_value += 4;
367       r = r - Poly_Con_Relation::is_included();
368     }
369     else if (r.implies(Poly_Con_Relation::saturates())) {
370       j_value += 8;
371       r = r - Poly_Con_Relation::saturates();
372     }
373   }
374   jobject ret = env->NewObject(cached_classes.Poly_Con_Relation,
375                                cached_FMIDs.Poly_Con_Relation_init_ID,
376                                j_value);
377   CHECK_RESULT_THROW(env, ret);
378   return ret;
379 }
380 
381 
382 Congruence
build_cxx_congruence(JNIEnv * env,jobject j_congruence)383 build_cxx_congruence(JNIEnv* env, jobject j_congruence) {
384   jobject j_mod
385     = env->GetObjectField(j_congruence, cached_FMIDs.Congruence_mod_ID);
386   jobject j_lhs
387     = env->GetObjectField(j_congruence, cached_FMIDs.Congruence_lhs_ID);
388   jobject j_rhs
389     = env->GetObjectField(j_congruence, cached_FMIDs.Congruence_rhs_ID);
390   PPL_DIRTY_TEMP_COEFFICIENT(ppl_modulus);
391   ppl_modulus = build_cxx_coeff(env, j_mod);
392   Linear_Expression lhs = build_cxx_linear_expression(env, j_lhs);
393   Linear_Expression rhs = build_cxx_linear_expression(env, j_rhs);
394   return (lhs %= rhs) / ppl_modulus;
395 }
396 
397 PIP_Tree_Node::Artificial_Parameter
build_cxx_artificial_parameter(JNIEnv * env,jobject j_artificial_parameter)398 build_cxx_artificial_parameter(JNIEnv* env, jobject j_artificial_parameter) {
399   jobject j_le
400     = env->GetObjectField(j_artificial_parameter,
401                           cached_FMIDs.Artificial_Parameter_le_ID);
402   jobject j_den
403     = env->GetObjectField(j_artificial_parameter,
404                           cached_FMIDs.Artificial_Parameter_den_ID);
405   PPL_DIRTY_TEMP_COEFFICIENT(ppl_den);
406   ppl_den = build_cxx_coeff(env, j_den);
407   Linear_Expression le = build_cxx_linear_expression(env, j_le);
408   PIP_Tree_Node::Artificial_Parameter art_param(le, ppl_den);
409   return art_param;
410 }
411 
412 jobject
bool_to_j_boolean_class(JNIEnv * env,const bool value)413 bool_to_j_boolean_class(JNIEnv* env, const bool value) {
414   jobject ret = env->CallStaticObjectMethod(cached_classes.Boolean,
415                                             cached_FMIDs.Boolean_valueOf_ID,
416                                             static_cast<jboolean>(value));
417   CHECK_EXCEPTION_ASSERT(env);
418   return ret;
419 }
420 
421 jobject
j_long_to_j_long_class(JNIEnv * env,jlong jlong_value)422 j_long_to_j_long_class(JNIEnv* env, jlong jlong_value) {
423   jobject ret = env->CallStaticObjectMethod(cached_classes.Long,
424                                             cached_FMIDs.Long_valueOf_ID,
425                                             jlong_value);
426   CHECK_EXCEPTION_THROW(env);
427   return ret;
428 }
429 
430 jlong
j_long_class_to_j_long(JNIEnv * env,jobject j_long)431 j_long_class_to_j_long(JNIEnv* env, jobject j_long) {
432   jlong ret = env->CallLongMethod(j_long, cached_FMIDs.Long_longValue_ID);
433   CHECK_EXCEPTION_ASSERT(env);
434   return ret;
435 }
436 
437 jobject
j_int_to_j_integer(JNIEnv * env,jint jint_value)438 j_int_to_j_integer(JNIEnv* env, jint jint_value) {
439   jobject ret = env->CallStaticObjectMethod(cached_classes.Integer,
440                                             cached_FMIDs.Integer_valueOf_ID,
441                                             jint_value);
442   CHECK_EXCEPTION_THROW(env);
443   return ret;
444 }
445 
446 jint
j_integer_to_j_int(JNIEnv * env,jobject j_integer)447 j_integer_to_j_int(JNIEnv* env, jobject j_integer) {
448   jint ret = env->CallIntMethod(j_integer, cached_FMIDs.Integer_intValue_ID);
449   CHECK_EXCEPTION_ASSERT(env);
450   return ret;
451 }
452 
453 Variables_Set
build_cxx_variables_set(JNIEnv * env,jobject j_v_set)454 build_cxx_variables_set(JNIEnv* env, jobject j_v_set) {
455   // Get the iterator.
456   jobject j_iter
457     = env->CallObjectMethod(j_v_set, cached_FMIDs.Variables_Set_iterator_ID);
458   CHECK_EXCEPTION_THROW(env);
459   // Get method IDs from cache.
460   jmethodID has_next_ID = cached_FMIDs.Variables_Set_Iterator_has_next_ID;
461   jmethodID next_ID = cached_FMIDs.Variables_Set_Iterator_next_ID;
462   // Initialize an empty set of variables.
463   Variables_Set v_set;
464   jobject j_variable;
465   jboolean has_next_value = env->CallBooleanMethod(j_iter, has_next_ID);
466   while (has_next_value) {
467     j_variable = env->CallObjectMethod(j_iter, next_ID);
468     CHECK_EXCEPTION_ASSERT(env);
469     v_set.insert(build_cxx_variable(env, j_variable));
470     has_next_value = env->CallBooleanMethod(j_iter, has_next_ID);
471     CHECK_EXCEPTION_ASSERT(env);
472   }
473   return v_set;
474 }
475 
476 jobject
build_java_variables_set(JNIEnv * env,const Variables_Set & v_set)477 build_java_variables_set(JNIEnv* env, const Variables_Set& v_set) {
478   jobject j_vs = env->NewObject(cached_classes.Variables_Set,
479                                 cached_FMIDs.Variables_Set_init_ID);
480   CHECK_RESULT_THROW(env, j_vs);
481   for (Variables_Set::const_iterator v_begin = v_set.begin(),
482          v_end = v_set.end(); v_begin != v_end; ++v_begin) {
483     Variable var(*v_begin);
484     jobject j_variable = build_java_variable(env, var);
485     env->CallBooleanMethod(j_vs,
486                            cached_FMIDs.Variables_Set_add_ID,
487                            j_variable);
488     CHECK_EXCEPTION_THROW(env);
489   }
490   return j_vs;
491 }
492 
493 Bounded_Integer_Type_Overflow
build_cxx_bounded_overflow(JNIEnv * env,jobject j_bounded_overflow)494 build_cxx_bounded_overflow(JNIEnv* env, jobject j_bounded_overflow) {
495   jint bounded_overflow
496     = env->CallIntMethod(j_bounded_overflow, cached_FMIDs.Bounded_Integer_Type_Overflow_ordinal_ID);
497   CHECK_EXCEPTION_ASSERT(env);
498   switch (bounded_overflow) {
499   case 0:
500     return OVERFLOW_WRAPS;
501   case 1:
502     return OVERFLOW_UNDEFINED;
503   case 2:
504     return OVERFLOW_IMPOSSIBLE;
505   default:
506     PPL_JAVA_UNEXPECTED;
507   }
508 }
509 
510 Bounded_Integer_Type_Representation
build_cxx_bounded_rep(JNIEnv * env,jobject j_bounded_rep)511 build_cxx_bounded_rep(JNIEnv* env, jobject j_bounded_rep) {
512   jint bounded_rep
513     = env->CallIntMethod(j_bounded_rep, cached_FMIDs.Bounded_Integer_Type_Representation_ordinal_ID);
514   CHECK_EXCEPTION_ASSERT(env);
515   switch (bounded_rep) {
516   case 0:
517     return UNSIGNED;
518   case 1:
519     return SIGNED_2_COMPLEMENT;
520   default:
521     PPL_JAVA_UNEXPECTED;
522   }
523 }
524 
525 Bounded_Integer_Type_Width
build_cxx_bounded_width(JNIEnv * env,jobject j_bounded_width)526 build_cxx_bounded_width(JNIEnv* env, jobject j_bounded_width) {
527   jint bounded_width
528     = env->CallIntMethod(j_bounded_width, cached_FMIDs.Bounded_Integer_Type_Width_ordinal_ID);
529   CHECK_EXCEPTION_ASSERT(env);
530   switch (bounded_width) {
531   case 0:
532     return BITS_8;
533   case 1:
534     return BITS_16;
535   case 2:
536     return BITS_32;
537   case 3:
538     return BITS_64;
539   case 4:
540     return BITS_128;
541   default:
542     PPL_JAVA_UNEXPECTED;
543   }
544 }
545 
546 Relation_Symbol
build_cxx_relsym(JNIEnv * env,jobject j_relsym)547 build_cxx_relsym(JNIEnv* env, jobject j_relsym) {
548   jint rel_sym
549     = env->CallIntMethod(j_relsym, cached_FMIDs.Relation_Symbol_ordinal_ID);
550   CHECK_EXCEPTION_ASSERT(env);
551   switch (rel_sym) {
552   case 0:
553     return LESS_THAN;
554   case 1:
555     return LESS_OR_EQUAL;
556   case 2:
557     return EQUAL;
558   case 3:
559     return GREATER_OR_EQUAL;
560   case 4:
561     return GREATER_THAN;
562   case 5:
563     return NOT_EQUAL;
564   default:
565     PPL_JAVA_UNEXPECTED;
566   }
567 }
568 
569 Optimization_Mode
build_cxx_optimization_mode(JNIEnv * env,jobject j_opt_mode)570 build_cxx_optimization_mode(JNIEnv* env, jobject j_opt_mode) {
571   jint opt_mode
572     = env->CallIntMethod(j_opt_mode, cached_FMIDs.Optimization_Mode_ordinal_ID);
573   CHECK_EXCEPTION_ASSERT(env);
574   switch (opt_mode) {
575   case 0:
576     return MINIMIZATION;
577   case 1:
578     return MAXIMIZATION;
579   default:
580     PPL_JAVA_UNEXPECTED;
581   }
582 }
583 
584 jobject
build_java_mip_status(JNIEnv * env,const MIP_Problem_Status & mip_status)585 build_java_mip_status(JNIEnv* env, const MIP_Problem_Status& mip_status) {
586   jfieldID fID;
587   switch (mip_status) {
588   case UNFEASIBLE_MIP_PROBLEM:
589     fID = cached_FMIDs.MIP_Problem_Status_UNFEASIBLE_MIP_PROBLEM_ID;
590     break;
591   case UNBOUNDED_MIP_PROBLEM:
592     fID = cached_FMIDs.MIP_Problem_Status_UNBOUNDED_MIP_PROBLEM_ID;
593     break;
594   case OPTIMIZED_MIP_PROBLEM:
595     fID = cached_FMIDs.MIP_Problem_Status_OPTIMIZED_MIP_PROBLEM_ID;
596     break;
597   default:
598     PPL_UNREACHABLE;
599   }
600   return env->GetStaticObjectField(cached_classes.MIP_Problem_Status, fID);
601 }
602 
603 jobject
build_java_pip_status(JNIEnv * env,const PIP_Problem_Status & pip_status)604 build_java_pip_status(JNIEnv* env, const PIP_Problem_Status& pip_status) {
605   jfieldID fID;
606   switch (pip_status) {
607   case UNFEASIBLE_PIP_PROBLEM:
608     fID = cached_FMIDs.PIP_Problem_Status_UNFEASIBLE_PIP_PROBLEM_ID;
609     break;
610   case OPTIMIZED_PIP_PROBLEM:
611     fID = cached_FMIDs.PIP_Problem_Status_OPTIMIZED_PIP_PROBLEM_ID;
612     break;
613   default:
614     PPL_UNREACHABLE;
615   }
616   return env->GetStaticObjectField(cached_classes.PIP_Problem_Status, fID);
617 }
618 
619 jobject
build_java_optimization_mode(JNIEnv * env,const Optimization_Mode & opt_mode)620 build_java_optimization_mode(JNIEnv* env, const Optimization_Mode& opt_mode) {
621   jfieldID fID;
622   switch (opt_mode) {
623   case MINIMIZATION:
624     fID = cached_FMIDs.Optimization_Mode_MINIMIZATION_ID;
625     break;
626   case MAXIMIZATION:
627     fID = cached_FMIDs.Optimization_Mode_MAXIMIZATION_ID;
628     break;
629   default:
630     PPL_UNREACHABLE;
631   }
632   return env->GetStaticObjectField(cached_classes.Optimization_Mode, fID);
633 }
634 
635 MIP_Problem::Control_Parameter_Name
build_cxx_control_parameter_name(JNIEnv * env,jobject j_cp_name)636 build_cxx_control_parameter_name(JNIEnv* env, jobject j_cp_name) {
637   jclass cp_name_class = env->GetObjectClass(j_cp_name);
638   CHECK_RESULT_ASSERT(env, cp_name_class);
639   jmethodID cp_name_ordinal_id
640     = env->GetMethodID(cp_name_class, "ordinal", "()I");
641   CHECK_RESULT_ASSERT(env, cp_name_ordinal_id);
642   jint cp_name = env->CallIntMethod(j_cp_name, cp_name_ordinal_id);
643   CHECK_EXCEPTION_ASSERT(env);
644   if (cp_name == 0)
645     return MIP_Problem::PRICING;
646   else
647     PPL_JAVA_UNEXPECTED;
648 }
649 
650 jobject
build_java_control_parameter_name(JNIEnv * env,const MIP_Problem::Control_Parameter_Name & cp_name)651 build_java_control_parameter_name
652 (JNIEnv* env,const MIP_Problem::Control_Parameter_Name& cp_name) {
653   jclass j_cp_name_class
654     = env->FindClass("parma_polyhedra_library/Control_Parameter_Name");
655   CHECK_RESULT_ASSERT(env, j_cp_name_class);
656   jfieldID cp_name_pricing_get_id
657     = env->GetStaticFieldID(j_cp_name_class, "PRICING",
658                             "Lparma_polyhedra_library/Control_Parameter_Name;");
659   CHECK_RESULT_ASSERT(env, cp_name_pricing_get_id);
660   if (cp_name == MIP_Problem::PRICING)
661     return env->GetStaticObjectField(j_cp_name_class,
662                                      cp_name_pricing_get_id);
663   else
664     PPL_UNREACHABLE;
665 }
666 
667 MIP_Problem::Control_Parameter_Value
build_cxx_control_parameter_value(JNIEnv * env,jobject j_cp_value)668 build_cxx_control_parameter_value(JNIEnv* env, jobject j_cp_value) {
669   jclass cp_value_class = env->GetObjectClass(j_cp_value);
670   CHECK_RESULT_ASSERT(env, cp_value_class);
671   jmethodID cp_value_ordinal_id
672     = env->GetMethodID(cp_value_class, "ordinal", "()I");
673   CHECK_RESULT_ASSERT(env, cp_value_ordinal_id);
674   jint cp_value = env->CallIntMethod(j_cp_value, cp_value_ordinal_id);
675   CHECK_EXCEPTION_ASSERT(env);
676   switch (cp_value) {
677   case 0:
678     return MIP_Problem::PRICING_STEEPEST_EDGE_FLOAT;
679   case 1:
680     return MIP_Problem::PRICING_STEEPEST_EDGE_EXACT;
681   case 2:
682     return MIP_Problem::PRICING_TEXTBOOK;
683   default:
684     PPL_JAVA_UNEXPECTED;
685   }
686 }
687 
688 jobject
build_java_control_parameter_value(JNIEnv * env,const MIP_Problem::Control_Parameter_Value & cp_value)689 build_java_control_parameter_value
690 (JNIEnv* env, const MIP_Problem::Control_Parameter_Value& cp_value) {
691   jclass j_cp_value_class
692     = env->FindClass("parma_polyhedra_library/Control_Parameter_Value");
693   CHECK_RESULT_ASSERT(env, j_cp_value_class);
694   const char* field_name;
695   switch (cp_value) {
696   case MIP_Problem::PRICING_STEEPEST_EDGE_FLOAT:
697     field_name = "PRICING_STEEPEST_EDGE_FLOAT";
698     break;
699   case MIP_Problem::PRICING_STEEPEST_EDGE_EXACT:
700     field_name = "PRICING_STEEPEST_EDGE_EXACT";
701     break;
702   case MIP_Problem::PRICING_TEXTBOOK:
703     field_name = "PRICING_TEXTBOOK";
704     break;
705   default:
706     PPL_UNREACHABLE;
707   }
708   jfieldID fID = env->GetStaticFieldID(j_cp_value_class, field_name,
709                                        "Lparma_polyhedra_library/Control_Parameter_Value;");
710   CHECK_RESULT_ASSERT(env, fID);
711   return env->GetStaticObjectField(j_cp_value_class, fID);
712 }
713 
714 PIP_Problem::Control_Parameter_Name
build_cxx_pip_problem_control_parameter_name(JNIEnv * env,jobject j_cp_name)715 build_cxx_pip_problem_control_parameter_name(JNIEnv* env, jobject j_cp_name) {
716   jclass cp_name_class = env->GetObjectClass(j_cp_name);
717   CHECK_RESULT_ASSERT(env, cp_name_class);
718   jmethodID cp_name_ordinal_id
719     = env->GetMethodID(cp_name_class, "ordinal", "()I");
720   CHECK_RESULT_ASSERT(env, cp_name_ordinal_id);
721   jint cp_name = env->CallIntMethod(j_cp_name, cp_name_ordinal_id);
722   CHECK_EXCEPTION_ASSERT(env);
723   switch (cp_name) {
724   case 0:
725     return PIP_Problem::CUTTING_STRATEGY;
726   case 1:
727     return PIP_Problem::PIVOT_ROW_STRATEGY;
728   default:
729     PPL_JAVA_UNEXPECTED;
730   }
731 }
732 
733 jobject
build_java_pip_problem_control_parameter_name(JNIEnv * env,const PIP_Problem::Control_Parameter_Name & cp_name)734 build_java_pip_problem_control_parameter_name
735 (JNIEnv* env, const PIP_Problem::Control_Parameter_Name& cp_name) {
736   jclass j_cp_name_class
737     = env->FindClass("parma_polyhedra_library/PIP_Problem_Control_Parameter_Name");
738   CHECK_RESULT_ASSERT(env, j_cp_name_class);
739   jfieldID cp_name_cutting_strategy_get_id
740     = env->GetStaticFieldID(j_cp_name_class, "CUTTING_STRATEGY",
741                             "Lparma_polyhedra_library/PIP_Problem_Control_Parameter_Name;");
742   CHECK_RESULT_ASSERT(env, cp_name_cutting_strategy_get_id);
743   jfieldID cp_name_pivot_row_strategy_get_id
744     = env->GetStaticFieldID(j_cp_name_class, "PIVOT_ROW_STRATEGY",
745                             "Lparma_polyhedra_library/PIP_Problem_Control_Parameter_Name;");
746   CHECK_RESULT_ASSERT(env, cp_name_pivot_row_strategy_get_id);
747   switch (cp_name) {
748   case PIP_Problem::CUTTING_STRATEGY:
749     return env->GetStaticObjectField(j_cp_name_class,
750                                      cp_name_cutting_strategy_get_id);
751   case PIP_Problem::PIVOT_ROW_STRATEGY:
752     return env->GetStaticObjectField(j_cp_name_class,
753                                      cp_name_pivot_row_strategy_get_id);
754   default:
755     PPL_UNREACHABLE;
756   }
757 }
758 
759 PIP_Problem::Control_Parameter_Value
build_cxx_pip_problem_control_parameter_value(JNIEnv * env,jobject j_cp_value)760 build_cxx_pip_problem_control_parameter_value(JNIEnv* env, jobject j_cp_value) {
761   jclass cp_value_class = env->GetObjectClass(j_cp_value);
762   CHECK_RESULT_ASSERT(env, cp_value_class);
763   jmethodID cp_value_ordinal_id
764     = env->GetMethodID(cp_value_class, "ordinal", "()I");
765   CHECK_RESULT_ASSERT(env, cp_value_ordinal_id);
766   jint cp_value = env->CallIntMethod(j_cp_value, cp_value_ordinal_id);
767   CHECK_EXCEPTION_ASSERT(env);
768   switch (cp_value) {
769   case 0:
770     return PIP_Problem::CUTTING_STRATEGY_FIRST;
771   case 1:
772     return PIP_Problem::CUTTING_STRATEGY_DEEPEST;
773   case 2:
774     return PIP_Problem::CUTTING_STRATEGY_ALL;
775   case 3:
776     return PIP_Problem::PIVOT_ROW_STRATEGY_FIRST;
777   case 4:
778     return PIP_Problem::PIVOT_ROW_STRATEGY_MAX_COLUMN;
779   default:
780     PPL_JAVA_UNEXPECTED;
781   }
782 }
783 
784 jobject
build_java_pip_problem_control_parameter_value(JNIEnv * env,const PIP_Problem::Control_Parameter_Value & cp_value)785 build_java_pip_problem_control_parameter_value
786 (JNIEnv* env, const PIP_Problem::Control_Parameter_Value& cp_value) {
787   jclass j_cp_value_class
788     = env->FindClass("parma_polyhedra_library/PIP_Problem_Control_Parameter_Value");
789   CHECK_RESULT_ASSERT(env, j_cp_value_class);
790   const char* field_name;
791   switch (cp_value) {
792   case PIP_Problem::CUTTING_STRATEGY_FIRST:
793     field_name = "CUTTING_STRATEGY_FIRST";
794     break;
795   case PIP_Problem::CUTTING_STRATEGY_DEEPEST:
796     field_name = "CUTTING_STRATEGY_DEEPEST";
797     break;
798   case PIP_Problem::CUTTING_STRATEGY_ALL:
799     field_name = "CUTTING_STRATEGY_ALL";
800     break;
801   case PIP_Problem::PIVOT_ROW_STRATEGY_FIRST:
802     field_name = "PIVOT_ROW_STRATEGY_FIRST";
803     break;
804   case PIP_Problem::PIVOT_ROW_STRATEGY_MAX_COLUMN:
805     field_name = "PIVOT_ROW_STRATEGY_MAX_COLUMN";
806     break;
807   default:
808     PPL_UNREACHABLE;
809   }
810   jfieldID fID = env->GetStaticFieldID(j_cp_value_class, field_name,
811                                        "Lparma_polyhedra_library/PIP_Problem_Control_Parameter_Value;");
812   CHECK_RESULT_ASSERT(env, fID);
813   return env->GetStaticObjectField(j_cp_value_class, fID);
814 }
815 
816 Constraint
build_cxx_constraint(JNIEnv * env,jobject j_constraint)817 build_cxx_constraint(JNIEnv* env, jobject j_constraint) {
818   jobject lhs_value
819     = env->GetObjectField(j_constraint, cached_FMIDs.Constraint_lhs_ID);
820   jobject rhs_value
821     = env->GetObjectField(j_constraint, cached_FMIDs.Constraint_rhs_ID);
822   jobject kind
823     = env->GetObjectField(j_constraint, cached_FMIDs.Constraint_kind_ID);
824   Linear_Expression first_le = build_cxx_linear_expression(env, lhs_value);
825   Linear_Expression second_le = build_cxx_linear_expression(env, rhs_value);
826   jint rel_sym
827     = env->CallIntMethod(kind, cached_FMIDs.Relation_Symbol_ordinal_ID);
828   CHECK_EXCEPTION_ASSERT(env);
829   switch (rel_sym) {
830   case 0:
831     return Constraint(first_le < second_le);
832   case 1:
833     return Constraint(first_le <= second_le);
834   case 2:
835     return Constraint(first_le == second_le);
836   case 3:
837     return Constraint(first_le >= second_le);
838   case 4:
839     return Constraint(first_le > second_le);
840   default:
841     PPL_JAVA_UNEXPECTED;
842   }
843 }
844 
845 Linear_Expression
build_cxx_linear_expression(JNIEnv * env,jobject j_le)846 build_cxx_linear_expression(JNIEnv* env, jobject j_le) {
847   jfieldID fID;
848   jclass current_class = env->GetObjectClass(j_le);
849   // LE_Variable
850   if (env->IsAssignableFrom(current_class,
851                             cached_classes.Linear_Expression_Variable)) {
852     jmethodID mID = cached_FMIDs.Linear_Expression_Variable_var_id_ID;
853     jlong var_id = env->CallLongMethod(j_le, mID);
854     return Linear_Expression(Variable(var_id));
855   }
856   // LE_Coefficient
857   if (env->IsAssignableFrom(current_class,
858                             cached_classes.Linear_Expression_Coefficient)) {
859     fID = cached_FMIDs.Linear_Expression_Coefficient_coeff_ID;
860     jobject ppl_coeff = env->GetObjectField(j_le, fID);
861     return Linear_Expression(build_cxx_coeff(env, ppl_coeff));
862   }
863   // LE_Sum
864   if (env->IsAssignableFrom(current_class,
865                             cached_classes.Linear_Expression_Sum)) {
866     fID = cached_FMIDs.Linear_Expression_Sum_lhs_ID;
867     jobject l_value = env->GetObjectField(j_le, fID);
868     fID = cached_FMIDs.Linear_Expression_Sum_rhs_ID;
869     jobject r_value = env->GetObjectField(j_le, fID);
870     return build_cxx_linear_expression(env, l_value)
871       + build_cxx_linear_expression(env, r_value);
872   }
873   // LE_Times
874   if (env->IsAssignableFrom(current_class,
875                             cached_classes.Linear_Expression_Times)) {
876     fID = cached_FMIDs.Linear_Expression_Times_coeff_ID;
877     jobject coeff_value = env->GetObjectField(j_le, fID);
878     fID = cached_FMIDs.Linear_Expression_Times_lin_expr_ID;
879     jobject le_value = env->GetObjectField(j_le, fID);
880     return build_cxx_coeff(env, coeff_value)
881       * build_cxx_linear_expression(env, le_value);
882   }
883   // LE_Difference
884   if (env->IsAssignableFrom(current_class,
885                             cached_classes.Linear_Expression_Difference)) {
886     fID = cached_FMIDs.Linear_Expression_Difference_lhs_ID;
887     jobject l_value = env->GetObjectField(j_le,fID);
888     fID = cached_FMIDs.Linear_Expression_Difference_rhs_ID;
889     jobject r_value = env->GetObjectField(j_le, fID);
890     return build_cxx_linear_expression(env, l_value)
891       - build_cxx_linear_expression(env, r_value);
892   }
893   // LE_Unary_Minus
894   if (env->IsAssignableFrom(current_class,
895                             cached_classes.Linear_Expression_Unary_Minus)) {
896     fID = cached_FMIDs.Linear_Expression_Unary_Minus_arg_ID;
897     jobject le_value = env->GetObjectField(j_le, fID);
898     return -build_cxx_linear_expression(env, le_value);
899   }
900   // All cases dealt with above.
901   PPL_JAVA_UNEXPECTED;
902 }
903 
904 Generator
build_cxx_generator(JNIEnv * env,jobject j_generator)905 build_cxx_generator(JNIEnv* env, jobject j_generator) {
906   jobject j_le
907     = env->GetObjectField(j_generator, cached_FMIDs.Generator_le_ID);
908   jobject generator_type
909     = env->GetObjectField(j_generator, cached_FMIDs.Generator_gt_ID);
910   jint generator_type_ordinal
911     = env->CallIntMethod(generator_type,
912                          cached_FMIDs.Generator_Type_ordinal_ID);
913   CHECK_EXCEPTION_ASSERT(env);
914   switch (generator_type_ordinal) {
915   case 0:
916     return line(build_cxx_linear_expression(env, j_le));
917   case 1:
918     return ray(build_cxx_linear_expression(env, j_le));
919   case 2:
920     {
921       jobject j_div
922         = env->GetObjectField(j_generator, cached_FMIDs.Generator_div_ID);
923       return point(build_cxx_linear_expression(env, j_le),
924                    build_cxx_coeff(env, j_div));
925     }
926   case 3:
927     {
928       jobject j_div
929         = env->GetObjectField(j_generator, cached_FMIDs.Generator_div_ID);
930       return closure_point(build_cxx_linear_expression(env, j_le),
931                            build_cxx_coeff(env, j_div));
932     }
933   default:
934     PPL_JAVA_UNEXPECTED;
935   }
936 }
937 
938 Grid_Generator
build_cxx_grid_generator(JNIEnv * env,jobject j_grid_generator)939 build_cxx_grid_generator(JNIEnv* env, jobject j_grid_generator) {
940   jobject j_le
941     = env->GetObjectField(j_grid_generator, cached_FMIDs.Grid_Generator_le_ID);
942   jobject grid_generator_type
943     = env->GetObjectField(j_grid_generator, cached_FMIDs.Grid_Generator_gt_ID);
944   jint grid_generator_type_ordinal
945     = env->CallIntMethod(grid_generator_type,
946                          cached_FMIDs.Grid_Generator_Type_ordinal_ID);
947   CHECK_EXCEPTION_ASSERT(env);
948   switch (grid_generator_type_ordinal) {
949   case 0:
950     return grid_line(build_cxx_linear_expression(env, j_le));
951   case 1:
952     {
953       jobject j_div = env->GetObjectField(j_grid_generator,
954                                           cached_FMIDs.Grid_Generator_div_ID);
955       return parameter(build_cxx_linear_expression(env, j_le),
956                        build_cxx_coeff(env, j_div));
957     }
958   case 2:
959     {
960       jobject j_div = env->GetObjectField(j_grid_generator,
961                                           cached_FMIDs.Grid_Generator_div_ID);
962       return grid_point(build_cxx_linear_expression(env, j_le),
963                         build_cxx_coeff(env, j_div));
964     }
965   default:
966     PPL_JAVA_UNEXPECTED;
967   }
968 }
969 
970 jobject
build_java_linear_expression_coefficient(JNIEnv * env,const Coefficient & c)971 build_java_linear_expression_coefficient(JNIEnv* env, const Coefficient& c) {
972   jobject j_coeff = build_java_coeff(env, c);
973   jobject ret
974     = env->NewObject(cached_classes.Linear_Expression_Coefficient,
975                      cached_FMIDs.Linear_Expression_Coefficient_init_ID,
976                      j_coeff);
977   CHECK_RESULT_THROW(env, ret);
978   return ret;
979 }
980 
981 void
set_generator(JNIEnv * env,jobject dst,jobject src)982 set_generator(JNIEnv* env, jobject dst, jobject src) {
983   jobject src_gt = env->GetObjectField(src, cached_FMIDs.Generator_gt_ID);
984   env->SetObjectField(dst, cached_FMIDs.Generator_gt_ID, src_gt);
985   jobject src_le = env->GetObjectField(src, cached_FMIDs.Generator_le_ID);
986   env->SetObjectField(dst, cached_FMIDs.Generator_le_ID, src_le);
987   jobject src_div = env->GetObjectField(src, cached_FMIDs.Generator_div_ID);
988   env->SetObjectField(dst, cached_FMIDs.Generator_div_ID, src_div);
989 }
990 
991 void
set_pair_element(JNIEnv * env,jobject dst_pair,int arg,jobject src)992 set_pair_element(JNIEnv* env, jobject dst_pair, int arg, jobject src) {
993   switch (arg) {
994   case 0:
995     env->SetObjectField(dst_pair, cached_FMIDs.Pair_first_ID, src);
996     break;
997   case 1:
998     env->SetObjectField(dst_pair, cached_FMIDs.Pair_second_ID, src);
999     break;
1000   default:
1001     PPL_JAVA_UNEXPECTED;
1002   }
1003 }
1004 
1005 jobject
get_pair_element(JNIEnv * env,int arg,jobject j_pair)1006 get_pair_element(JNIEnv* env, int arg, jobject j_pair) {
1007   switch (arg) {
1008   case 0:
1009     return env->GetObjectField(j_pair, cached_FMIDs.Pair_first_ID);
1010   case 1:
1011     return env->GetObjectField(j_pair, cached_FMIDs.Pair_second_ID);
1012   default:
1013     PPL_JAVA_UNEXPECTED;
1014   }
1015 }
1016 
1017 jobject
build_java_constraint(JNIEnv * env,const Constraint & c)1018 build_java_constraint(JNIEnv* env, const Constraint& c) {
1019   jobject lhs = build_linear_expression(env, c);
1020   jobject rhs
1021     = build_java_linear_expression_coefficient(env, -c.inhomogeneous_term());
1022   jfieldID fID;
1023   switch (c.type()) {
1024   case Constraint::EQUALITY:
1025     fID = cached_FMIDs.Relation_Symbol_EQUAL_ID;
1026     break;
1027   case Constraint::NONSTRICT_INEQUALITY:
1028     fID = cached_FMIDs.Relation_Symbol_GREATER_OR_EQUAL_ID;
1029     break;
1030   case Constraint::STRICT_INEQUALITY:
1031     fID = cached_FMIDs.Relation_Symbol_GREATER_THAN_ID;
1032     break;
1033   default:
1034     PPL_UNREACHABLE;
1035   }
1036   jobject relation
1037     = env->GetStaticObjectField(cached_classes.Relation_Symbol, fID);
1038   jobject ret = env->NewObject(cached_classes.Constraint,
1039                                cached_FMIDs.Constraint_init_ID,
1040                                lhs, relation, rhs);
1041   CHECK_RESULT_THROW(env, ret);
1042   return ret;
1043 }
1044 
1045 jobject
build_java_congruence(JNIEnv * env,const Congruence & cg)1046 build_java_congruence(JNIEnv* env, const Congruence& cg) {
1047   jobject j_mod = build_java_coeff(env, cg.modulus());
1048   jobject j_lhs = build_linear_expression(env, cg);
1049   jobject j_rhs
1050     = build_java_linear_expression_coefficient(env, -cg.inhomogeneous_term());
1051   jobject ret = env->NewObject(cached_classes.Congruence,
1052                                cached_FMIDs.Congruence_init_ID,
1053                                j_lhs, j_rhs, j_mod);
1054   CHECK_RESULT_THROW(env, ret);
1055   return ret;
1056 }
1057 
1058 jobject
build_java_generator(JNIEnv * env,const Generator & g)1059 build_java_generator(JNIEnv* env, const Generator& g) {
1060   jobject j_g_le = build_linear_expression(env, g);
1061   jobject ret;
1062   switch (g.type()) {
1063   case Generator::LINE:
1064     ret = env->CallStaticObjectMethod(cached_classes.Generator,
1065                                       cached_FMIDs.Generator_line_ID,
1066                                       j_g_le);
1067     break;
1068   case Generator::RAY:
1069     ret = env->CallStaticObjectMethod(cached_classes.Generator,
1070                                       cached_FMIDs.Generator_ray_ID,
1071                                       j_g_le);
1072     break;
1073   case Generator::POINT:
1074     {
1075       const Coefficient& divisor = g.divisor();
1076       jobject j_div = build_java_coeff(env, divisor);
1077       ret = env->CallStaticObjectMethod(cached_classes.Generator,
1078                                         cached_FMIDs.Generator_point_ID,
1079                                         j_g_le, j_div);
1080       break;
1081     }
1082   case Generator::CLOSURE_POINT:
1083     {
1084       const Coefficient& divisor = g.divisor();
1085       jobject j_div = build_java_coeff(env, divisor);
1086       ret = env->CallStaticObjectMethod(cached_classes.Generator,
1087                                         cached_FMIDs.Generator_closure_point_ID,
1088                                         j_g_le, j_div);
1089       break;
1090     }
1091   default:
1092     PPL_UNREACHABLE;
1093   }
1094   CHECK_EXCEPTION_THROW(env);
1095   return ret;
1096 }
1097 
1098 jobject
build_java_grid_generator(JNIEnv * env,const Grid_Generator & g)1099 build_java_grid_generator(JNIEnv* env, const Grid_Generator& g) {
1100   jobject j_g_le = build_linear_expression(env, g);
1101   jobject ret;
1102   switch (g.type()) {
1103   case Grid_Generator::LINE:
1104     ret = env->CallStaticObjectMethod(cached_classes.Grid_Generator,
1105                                       cached_FMIDs.Grid_Generator_grid_line_ID,
1106                                       j_g_le);
1107     break;
1108   case Grid_Generator::PARAMETER:
1109     {
1110       const Coefficient& divisor = g.divisor();
1111       jobject j_div = build_java_coeff(env, divisor);
1112       ret = env->CallStaticObjectMethod(cached_classes.Grid_Generator,
1113                                         cached_FMIDs.Grid_Generator_parameter_ID,
1114                                         j_g_le, j_div);
1115       break;
1116     }
1117   case Grid_Generator::POINT:
1118     {
1119       const Coefficient& divisor = g.divisor();
1120       jobject j_div = build_java_coeff(env, divisor);
1121       ret = env->CallStaticObjectMethod(cached_classes.Grid_Generator,
1122                                         cached_FMIDs.Grid_Generator_grid_point_ID,
1123                                         j_g_le, j_div);
1124       break;
1125     }
1126   default:
1127     PPL_UNREACHABLE;
1128   }
1129   CHECK_EXCEPTION_THROW(env);
1130   return ret;
1131 }
1132 
1133 jobject
build_java_constraint_system(JNIEnv * env,const Constraint_System & cs)1134 build_java_constraint_system(JNIEnv* env, const Constraint_System& cs) {
1135   jobject j_cs = env->NewObject(cached_classes.Constraint_System,
1136                                 cached_FMIDs.Constraint_System_init_ID);
1137   CHECK_RESULT_THROW(env, j_cs);
1138   for (Constraint_System::const_iterator v_begin = cs.begin(),
1139          v_end = cs.end(); v_begin != v_end; ++v_begin) {
1140     jobject j_constraint = build_java_constraint(env, *v_begin);
1141     env->CallBooleanMethod(j_cs,
1142                            cached_FMIDs.Constraint_System_add_ID,
1143                            j_constraint);
1144     CHECK_EXCEPTION_THROW(env);
1145   }
1146   return j_cs;
1147 }
1148 
1149 jobject
build_java_generator_system(JNIEnv * env,const Generator_System & gs)1150 build_java_generator_system(JNIEnv* env, const Generator_System& gs) {
1151   jobject j_gs = env->NewObject(cached_classes.Generator_System,
1152                                 cached_FMIDs.Generator_System_init_ID);
1153   CHECK_RESULT_THROW(env, j_gs);
1154   for (Generator_System::const_iterator v_begin = gs.begin(),
1155          v_end = gs.end(); v_begin != v_end; ++v_begin) {
1156     jobject j_generator = build_java_generator(env, *v_begin);
1157     env->CallBooleanMethod(j_gs,
1158                            cached_FMIDs.Generator_System_add_ID,
1159                            j_generator);
1160     CHECK_EXCEPTION_THROW(env);
1161   }
1162   return j_gs;
1163 }
1164 
1165 jobject
build_java_grid_generator_system(JNIEnv * env,const Grid_Generator_System & gs)1166 build_java_grid_generator_system(JNIEnv* env,
1167                                  const Grid_Generator_System& gs) {
1168   jobject j_gs = env->NewObject(cached_classes.Grid_Generator_System,
1169                                 cached_FMIDs.Grid_Generator_System_init_ID);
1170   CHECK_RESULT_THROW(env, j_gs);
1171   for (Grid_Generator_System::const_iterator v_begin = gs.begin(),
1172          v_end = gs.end(); v_begin != v_end; ++v_begin) {
1173     jobject j_generator = build_java_grid_generator(env, *v_begin);
1174     env->CallBooleanMethod(j_gs,
1175                            cached_FMIDs.Grid_Generator_System_add_ID,
1176                            j_generator);
1177     CHECK_EXCEPTION_THROW(env);
1178   }
1179   return j_gs;
1180 }
1181 
1182 jobject
build_java_congruence_system(JNIEnv * env,const Congruence_System & cgs)1183 build_java_congruence_system(JNIEnv* env, const Congruence_System& cgs) {
1184   jobject j_cgs = env->NewObject(cached_classes.Congruence_System,
1185                                  cached_FMIDs.Congruence_System_init_ID);
1186   CHECK_RESULT_THROW(env, j_cgs);
1187   for (Congruence_System::const_iterator v_begin = cgs.begin(),
1188          v_end = cgs.end(); v_begin != v_end; ++v_begin) {
1189     jobject j_congruence = build_java_congruence(env,*v_begin);
1190     env->CallBooleanMethod(j_cgs,
1191                            cached_FMIDs.Congruence_System_add_ID,
1192                            j_congruence);
1193     CHECK_EXCEPTION_THROW(env);
1194   }
1195   return j_cgs;
1196 }
1197 
1198 jobject
build_java_artificial_parameter(JNIEnv * env,const PIP_Tree_Node::Artificial_Parameter & art)1199 build_java_artificial_parameter
1200 (JNIEnv* env, const PIP_Tree_Node::Artificial_Parameter& art) {
1201   jobject j_le = build_linear_expression(env, art);
1202   jobject j_den = build_java_coeff(env, art.denominator());
1203   jobject ret = env->NewObject(cached_classes.Artificial_Parameter,
1204                                cached_FMIDs.Artificial_Parameter_init_ID,
1205                                j_le, j_den);
1206   CHECK_RESULT_THROW(env, ret);
1207   return ret;
1208 }
1209 
1210 void
Java_Variable_output_function(std::ostream & s,Variable v)1211 Java_Variable_output_function(std::ostream& s, Variable v) {
1212   // Use cached Java Virtual Machine pointer to retrieve JNI env.
1213   JavaVM* jvm = cached_classes.jvm;
1214   JNIEnv *env = 0;
1215   jvm->AttachCurrentThread((void **)&env, NULL);
1216   CHECK_EXCEPTION_ASSERT(env);
1217   // Retrieve stringifier object.
1218   jclass var_class = cached_classes.Variable;
1219   jfieldID fID = cached_FMIDs.Variable_stringifier_ID;
1220   jobject stringifier = env->GetStaticObjectField(var_class, fID);
1221   CHECK_RESULT_THROW(env, stringifier);
1222   // Use it to get the Java string for the variable.
1223   jmethodID mID = cached_FMIDs.Variable_Stringifier_stringify_ID;
1224 #ifndef NDEBUG
1225   {
1226     // Dynamically retrieve stringifier class and use it to compute
1227     // the corresponding method ID, so as to compare it with cached one.
1228     jclass dyn_class = env->GetObjectClass(stringifier);
1229     jmethodID dyn_mID = env->GetMethodID(dyn_class, "stringify",
1230                                          "(J)Ljava/lang/String;");
1231     CHECK_RESULT_ASSERT(env, mID == dyn_mID);
1232   }
1233 #endif // #ifndef NDEBUG
1234   jlong j_var_id = v.id();
1235   jstring bi_string
1236     = (jstring) env->CallObjectMethod(stringifier, mID, j_var_id);
1237   CHECK_EXCEPTION_THROW(env);
1238   // Convert the string and print it on C++ stream.
1239   const char* nativeString = env->GetStringUTFChars(bi_string, 0);
1240   CHECK_RESULT_THROW(env, nativeString);
1241   s << nativeString;
1242   env->ReleaseStringUTFChars(bi_string, nativeString);
1243 }
1244 
1245 } // namespace Java
1246 
1247 } // namespace Interfaces
1248 
1249 } // namespace Parma_Polyhedra_Library
1250