Skip to content

Commit

Permalink
Add preserve_rounding parameter in constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
gchabert committed Oct 2, 2020
1 parent e7de9ad commit 1d6d7f5
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 29 deletions.
22 changes: 19 additions & 3 deletions src/Ibex.java.in
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,26 @@ public class Ibex {
*
* prec[i]==-1 => the ith variable is integral.
* prec[i]>=0 => the ith variable is real and the precision is prec[i].
*
*
* @preserve_rounding - Under Linux/MacOS, Ibex (if linked with Gaol) does not use the standard
* rounding mode of the FPU (round-to-nearest) but the upward rounding mode, in order
* to get better performances. If preserve_rounding is true, Ibex will activate the
* upward rounding mode at each function call (contract, etc.) and restore the default
* rounding mode in return, which is transparent from Java but which also mean a loss
* of efficiency. If set to false, the rounding mode is only activated once by the
* construtor. In this case, the rounding mode is also changed on Java side.
*/
public Ibex(double[] prec, boolean preserve_rounding) {
init(prec, preserve_rounding);
}

/**
* Same as previous constructor with preserve_rounding=false.
*
* For backward compatibility.
*/
public Ibex(double[] prec) {
init(prec);
init(prec, false);
}

/**
Expand Down Expand Up @@ -272,7 +288,7 @@ public class Ibex {
*
* This method is automatically called by the constructor.
*/
private native void init(double[] prec);
private native void init(double[] prec, boolean preserve_rounding);

// Internal: do not modify!
// This is a pointer to native c++ data
Expand Down
53 changes: 27 additions & 26 deletions src/ibex_Java.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,19 @@ public:
SmearSumRelative* bis; // bisector for the solver
CellStack* stack; // cell buffer for the solver
Solver* solver; // the solver

Instance(int n, const BitSet& _params, const Vector& prec) : nb_var(n), params(_params), prec(prec), sys(NULL),
ctc(NULL), neg(NULL), bis(NULL), stack(NULL), solver(NULL) {
bool preserve_rounding;

Instance(int n, const BitSet& _params, const Vector& prec, bool preserve_rounding) : nb_var(n), params(_params), prec(prec), sys(NULL),
ctc(NULL), neg(NULL), bis(NULL), stack(NULL), solver(NULL), preserve_rounding(preserve_rounding) {

}

void build() {
//cout << " [ibex] new constraint:" << _syntax << " nb var=" << nb_var << " option=" << option << endl;

if (!preserve_rounding)
ibex_restore(); // do this once for all

stringstream s;
for (size_t i=0; i<ctrs_syntax.size(); i++) {
if (i>0) s << ';';
Expand Down Expand Up @@ -201,8 +205,6 @@ Instance* get_instance(JNIEnv* env, jobject obj) {
// either return BAD_POINT, UNKNOWN_POINT or INFLATE (the latter case also corresponds to the NOT_SIGNIFICANT case)
jint inflate(NumConstraint& ctr, const IntervalVector& xin, IntervalVector& x, jboolean in) {

ibex_restore();

jint result;

Interval yin=ctr.f.eval(xin);
Expand Down Expand Up @@ -235,15 +237,14 @@ jint inflate(NumConstraint& ctr, const IntervalVector& xin, IntervalVector& x, j
}
}

java_restore();
return result;
}

#define EPS_CONTRACT 0.01

}

JNIEXPORT void JNICALL Java_@JAVA_SIGNATURE@_Ibex_init(JNIEnv* env, jobject obj, jdoubleArray _prec) {
JNIEXPORT void JNICALL Java_@JAVA_SIGNATURE@_Ibex_init(JNIEnv* env, jobject obj, jdoubleArray _prec, jboolean preserve_rounding) {
jint size = env->GetArrayLength(_prec);
jdouble* prec = env->GetDoubleArrayElements(_prec, 0);

Expand All @@ -261,7 +262,7 @@ JNIEXPORT void JNICALL Java_@JAVA_SIGNATURE@_Ibex_init(JNIEnv* env, jobject obj,

jclass clazz = env->GetObjectClass(obj);
jfieldID _data = env->GetFieldID(clazz, "data", "J");
env->SetLongField(obj ,_data, (jlong) new Instance(size, b, prec_vec));
env->SetLongField(obj ,_data, (jlong) new Instance(size, b, prec_vec, preserve_rounding));

env->ReleaseDoubleArrayElements(_prec, prec, 0);
}
Expand All @@ -285,19 +286,19 @@ JNIEXPORT jboolean JNICALL Java_@JAVA_SIGNATURE@_Ibex_build(JNIEnv* env, jobject

Instance& inst = *get_instance(env,obj);

ibex_restore(); // required as the parser may perform interval ops
if (inst.preserve_rounding) ibex_restore(); // required as the parser may perform interval ops

if (inst.sys==NULL) {
try {
inst.build();
java_restore();
if (inst.preserve_rounding) java_restore();
return true;
} catch(SyntaxError&) {
java_restore();
if (inst.preserve_rounding) java_restore();
return false;
}
} else {
java_restore();
if (inst.preserve_rounding) java_restore();
return true;
}
}
Expand All @@ -311,15 +312,15 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_contract__I_3DID(JNIEnv* env,
return NOT_BUILT;
}

ibex_restore();
if (inst.preserve_rounding) ibex_restore();

jint result = NOTHING; // by default

jdouble* d = env->GetDoubleArrayElements(_d, 0);
IntervalVector box=inst.read_box(env,d,env->GetArrayLength(_d));
if (box.is_empty()) {
env->ReleaseDoubleArrayElements(_d, d, 0);
java_restore();
if (inst.preserve_rounding) java_restore();
return BAD_DOMAIN;
}

Expand Down Expand Up @@ -384,7 +385,7 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_contract__I_3DID(JNIEnv* env,

env->ReleaseDoubleArrayElements(_d, d, 0);

java_restore();
if (inst.preserve_rounding) java_restore();
return result;
}

Expand All @@ -408,23 +409,23 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_inflate(JNIEnv* env, jobject o
return NOT_BUILT;
}

ibex_restore();
if (inst.preserve_rounding) ibex_restore();

jint result;

jdouble* d = env->GetDoubleArrayElements(_d, 0);
IntervalVector x=inst.read_box(env,d,env->GetArrayLength(_d));
if (x.is_empty()) {
env->ReleaseDoubleArrayElements(_d, d, 0);
java_restore();
if (inst.preserve_rounding) java_restore();
return BAD_DOMAIN;
}

jdouble* din = env->GetDoubleArrayElements(_din, NULL);
if (env->GetArrayLength(_din)!=inst.nb_var) {
env->ReleaseDoubleArrayElements(_d, d, 0);
env->ReleaseDoubleArrayElements(_din, din, 0);
java_restore();
if (inst.preserve_rounding) java_restore();
return BAD_DOMAIN;
}

Expand Down Expand Up @@ -491,7 +492,7 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_inflate(JNIEnv* env, jobject o
env->ReleaseDoubleArrayElements(_d, d, 0);
env->ReleaseDoubleArrayElements(_din, din, 0);

java_restore();
if (inst.preserve_rounding) java_restore();
return result;
}

Expand All @@ -503,20 +504,20 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_start_1solve(JNIEnv* env, jobj
return NOT_BUILT;
}

ibex_restore();
if (inst.preserve_rounding) ibex_restore();

jdouble* d = env->GetDoubleArrayElements(_d, 0);

IntervalVector box=inst.read_box(env,d,env->GetArrayLength(_d));
if (box.is_empty()) {
env->ReleaseDoubleArrayElements(_d, d, 0);
java_restore();
if (inst.preserve_rounding) java_restore();
return BAD_DOMAIN;
}

for (int i=0; i<inst.nb_var; i++) {
if (inst.params[i] && !box[i].is_degenerated()) {
java_restore();
if (inst.preserve_rounding) java_restore();
return DISCRETE_NOT_INSTANCIATED;
}
}
Expand All @@ -525,7 +526,7 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_start_1solve(JNIEnv* env, jobj

env->ReleaseDoubleArrayElements(_d, d, 0);

java_restore();
if (inst.preserve_rounding) java_restore();
return STARTED;
}

Expand All @@ -536,7 +537,7 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_next_1solution(JNIEnv* env, jo
return NOT_BUILT;
}

ibex_restore();
if (inst.preserve_rounding) ibex_restore();

jint result;

Expand All @@ -545,7 +546,7 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_next_1solution(JNIEnv* env, jo
IntervalVector box=inst.read_box(env,d,env->GetArrayLength(_d));
if (box.is_empty()) {
env->ReleaseDoubleArrayElements(_d, d, 0);
java_restore();
if (inst.preserve_rounding) java_restore();
return BAD_DOMAIN;
}

Expand All @@ -564,7 +565,7 @@ JNIEXPORT jint JNICALL Java_@JAVA_SIGNATURE@_Ibex_next_1solution(JNIEnv* env, jo

env->ReleaseDoubleArrayElements(_d, d, 0);

java_restore();
if (inst.preserve_rounding) java_restore();
return result;
}

Expand Down
20 changes: 20 additions & 0 deletions tests/IbexTest.java.in
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,26 @@ public class IbexTest {

}

@Test
public void test_correct_rounding1() {
Ibex ibex = new Ibex(new double[]{1.e-1, 1.e-1, 1.e-4}, false);
ibex.add_ctr("{0}+{1}={2}");
ibex.build();
double domains[] = {0.1, 0.1, 0.2, 0.2, -5.0, 5.0};
int result = ibex.contract(0, domains);
Assert.assertEquals(Ibex.CONTRACT, result);
}

@Test
public void test_correct_rounding2() {
Ibex ibex = new Ibex(new double[]{1.e-1, 1.e-1, 1.e-4}, true);
ibex.add_ctr("{0}+{1}={2}");
ibex.build();
double domains[] = {0.1, 0.1, 0.2, 0.2, -5.0, 5.0};
int result = ibex.contract(0, domains);
Assert.assertEquals(Ibex.CONTRACT, result);
}

public static void main(String args[]) {
org.junit.runner.JUnitCore.main("IbexTest");
}
Expand Down

0 comments on commit 1d6d7f5

Please sign in to comment.