PPL Java Language Interface  1.2
ppl_java_common.cc
Go to the documentation of this file.
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 
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;
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;
65  Linear_Expression_Sum = NULL;
69  MIP_Problem_Status = NULL;
70  Optimization_Mode = NULL;
71  Pair = 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
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
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.
108  "parma_polyhedra_library/Artificial_Parameter");
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");
122  "parma_polyhedra_library/Grid_Generator_Type");
124  "parma_polyhedra_library/Constraint_System");
126  "parma_polyhedra_library/Congruence_System");
128  "parma_polyhedra_library/Generator_System");
130  "parma_polyhedra_library/Grid_Generator_System");
132  "parma_polyhedra_library/Linear_Expression");
134  "parma_polyhedra_library/Linear_Expression_Coefficient");
136  "parma_polyhedra_library/Linear_Expression_Difference");
138  "parma_polyhedra_library/Linear_Expression_Sum");
140  "parma_polyhedra_library/Linear_Expression_Times");
142  "parma_polyhedra_library/Linear_Expression_Unary_Minus");
144  "parma_polyhedra_library/Linear_Expression_Variable");
146  "parma_polyhedra_library/MIP_Problem_Status");
148  "parma_polyhedra_library/Optimization_Mode");
149  init_cache(env, Pair, "parma_polyhedra_library/Pair");
151  "parma_polyhedra_library/PIP_Problem_Control_Parameter_Name");
153  "parma_polyhedra_library/PIP_Problem_Control_Parameter_Value");
155  "parma_polyhedra_library/PIP_Problem_Status");
157  "parma_polyhedra_library/Poly_Con_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
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
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.
194  clear_cache(env, Coefficient);
195  clear_cache(env, Congruence);
196  clear_cache(env, Constraint);
197  clear_cache(env, Generator);
215  clear_cache(env, Pair);
218  clear_cache(env, PPL_Object);
220  clear_cache(env, Variable);
223 }
224 
225 void
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
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
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
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
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
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
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
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
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
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
320 reset_timeout() {
321  if (p_timeout_object) {
322  delete p_timeout_object;
323  p_timeout_object = 0;
325  }
326 }
327 
328 void
329 reset_deterministic_timeout() {
330  if (p_deterministic_timeout_object) {
331  delete p_deterministic_timeout_object;
332  p_deterministic_timeout_object = 0;
334  }
335 }
336 
337 jobject
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
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;
360  }
361  else if (r.implies(Poly_Con_Relation::strictly_intersects())) {
362  j_value += 2;
364  }
365  else if (r.implies(Poly_Con_Relation::is_included())) {
366  j_value += 4;
368  }
369  else if (r.implies(Poly_Con_Relation::saturates())) {
370  j_value += 8;
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
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
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);
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
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));
418  return ret;
419 }
420 
421 jobject
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);
427  return ret;
428 }
429 
430 jlong
431 j_long_class_to_j_long(JNIEnv* env, jobject j_long) {
432  jlong ret = env->CallLongMethod(j_long, cached_FMIDs.Long_longValue_ID);
434  return ret;
435 }
436 
437 jobject
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);
443  return ret;
444 }
445 
446 jint
447 j_integer_to_j_int(JNIEnv* env, jobject j_integer) {
448  jint ret = env->CallIntMethod(j_integer, cached_FMIDs.Integer_intValue_ID);
450  return ret;
451 }
452 
453 Variables_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);
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);
469  v_set.insert(build_cxx_variable(env, j_variable));
470  has_next_value = env->CallBooleanMethod(j_iter, has_next_ID);
472  }
473  return v_set;
474 }
475 
476 jobject
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);
489  }
490  return j_vs;
491 }
492 
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);
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:
507  }
508 }
509 
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);
515  switch (bounded_rep) {
516  case 0:
517  return UNSIGNED;
518  case 1:
519  return SIGNED_2_COMPLEMENT;
520  default:
522  }
523 }
524 
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);
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:
543  }
544 }
545 
547 build_cxx_relsym(JNIEnv* env, jobject j_relsym) {
548  jint rel_sym
549  = env->CallIntMethod(j_relsym, cached_FMIDs.Relation_Symbol_ordinal_ID);
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:
566  }
567 }
568 
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);
574  switch (opt_mode) {
575  case 0:
576  return MINIMIZATION;
577  case 1:
578  return MAXIMIZATION;
579  default:
581  }
582 }
583 
584 jobject
585 build_java_mip_status(JNIEnv* env, const MIP_Problem_Status& mip_status) {
586  jfieldID fID;
587  switch (mip_status) {
589  fID = cached_FMIDs.MIP_Problem_Status_UNFEASIBLE_MIP_PROBLEM_ID;
590  break;
592  fID = cached_FMIDs.MIP_Problem_Status_UNBOUNDED_MIP_PROBLEM_ID;
593  break;
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
604 build_java_pip_status(JNIEnv* env, const PIP_Problem_Status& pip_status) {
605  jfieldID fID;
606  switch (pip_status) {
608  fID = cached_FMIDs.PIP_Problem_Status_UNFEASIBLE_PIP_PROBLEM_ID;
609  break;
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
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 
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);
644  if (cp_name == 0)
645  return MIP_Problem::PRICING;
646  else
648 }
649 
650 jobject
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 
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);
676  switch (cp_value) {
677  case 0:
679  case 1:
681  case 2:
683  default:
685  }
686 }
687 
688 jobject
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) {
697  field_name = "PRICING_STEEPEST_EDGE_FLOAT";
698  break;
700  field_name = "PRICING_STEEPEST_EDGE_EXACT";
701  break;
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 
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);
723  switch (cp_name) {
724  case 0:
726  case 1:
728  default:
730  }
731 }
732 
733 jobject
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) {
749  return env->GetStaticObjectField(j_cp_name_class,
750  cp_name_cutting_strategy_get_id);
752  return env->GetStaticObjectField(j_cp_name_class,
753  cp_name_pivot_row_strategy_get_id);
754  default:
755  PPL_UNREACHABLE;
756  }
757 }
758 
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);
768  switch (cp_value) {
769  case 0:
771  case 1:
773  case 2:
775  case 3:
777  case 4:
779  default:
781  }
782 }
783 
784 jobject
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) {
793  field_name = "CUTTING_STRATEGY_FIRST";
794  break;
796  field_name = "CUTTING_STRATEGY_DEEPEST";
797  break;
799  field_name = "CUTTING_STRATEGY_ALL";
800  break;
802  field_name = "PIVOT_ROW_STRATEGY_FIRST";
803  break;
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
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);
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:
842  }
843 }
844 
845 Linear_Expression
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.
902 }
903 
904 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);
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:
935  }
936 }
937 
938 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);
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:
967  }
968 }
969 
970 jobject
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
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
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:
1002  }
1003 }
1004 
1005 jobject
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:
1014  }
1015 }
1016 
1017 jobject
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;
1028  fID = cached_FMIDs.Relation_Symbol_GREATER_OR_EQUAL_ID;
1029  break;
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
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
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  }
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
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;
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
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
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
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
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
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
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);
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
static Poly_Con_Relation is_disjoint()
static Poly_Gen_Relation subsumes()
#define CHECK_RESULT_ASSERT(env, cond)
#define CHECK_RESULT_THROW(env, cond)
value
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
#define PPL_JAVA_UNEXPECTED
#define CHECK_EXCEPTION_THROW(env)
static Poly_Con_Relation is_included()
static Poly_Con_Relation saturates()
PPL_COEFFICIENT_TYPE Coefficient
#define CHECK_RESULT_ABORT(env, cond)
void clear_cache(JNIEnv *env)
Resets all fields to NULL.
Generator_System_const_iterator const_iterator
#define CHECK_EXCEPTION_ASSERT(env)
void init_cache(JNIEnv *env)
Initializes all cache fields.
const Throwable *volatile abandon_expensive_computations
static Poly_Con_Relation nothing()
static Poly_Con_Relation strictly_intersects()
static Poly_Gen_Relation nothing()
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
Constraint_System_const_iterator const_iterator