<commit_before>
// nlopt4j
// Provides a JNI wrapper for NLopt (http://ab-initio.mit.edu/wiki/index.php/NLopt)
// LICENSE: See LICENSE file

#include <nlopt.h>
#include <nlopt_jni.h>

#include <algorithm>

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#ifdef __cpluplus
extern "C" {
#endif

    // Cache Java class and method handles for performance reasons
    static JavaVM *jvm;
    static jclass string_class;
    static jclass nlopt_func_class;
    static jmethodID nlopt_func_execute_method;
    static jclass illegal_argument_exception_class;
    static jclass out_of_memory_class;
    static jclass illegal_state_exception_class;

    // Must have same structure as NLopt_data
    struct Constraint_function {
        jobject func;
        nlopt_opt handle;
        Constraint_function *next;
        Constraint_function *unused;
    };

    struct NLopt_data {
        jobject func;
        nlopt_opt handle;
        Constraint_function *first_constraint;
        Constraint_function *last_constraint;
    };

    // We store a reference to the JVM so that we can use it
    // when invoking the callback
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
    {
        jvm = vm;
        return JNI_VERSION_1_6;
    }

    // Wrapper for the Java implementation of the NLopt
    // function callback
    double nlopt_minfunc(unsigned n, const double *x,
        double *gradient, /* NULL if not needed */
        void *func_data)
    {
        NLopt_data *data = (NLopt_data *)func_data;
        // Get JNI environment
        JNIEnv *jni = NULL;
        if (jvm->GetEnv(reinterpret_cast<void **>(&jni), JNI_VERSION_1_6) != JNI_OK) {
            fprintf(stderr, "Error: Unable to obtain JNI environment\n");
            nlopt_force_stop(data->handle);
            return 0.0; // ignored
        }

        if (data->func) {
            jdoubleArray xarray;
            jdoubleArray gradientarray;

            // Create Java arrays
            xarray = jni->NewDoubleArray(n);
            if (!xarray || jni->ExceptionCheck()) {
                nlopt_force_stop(data->handle);
                return 0.0; // ignored
            }
            unsigned gsize = gradient ? n : 0;
            gradientarray = jni->NewDoubleArray(gsize);
            if (!gradientarray || jni->ExceptionCheck()) {
                nlopt_force_stop(data->handle);
                return 0.0; // ignored
            }
            // Copy data into Java arrays
            jni->SetDoubleArrayRegion(xarray, 0, n, x);
            if (gradient) {
                jni->SetDoubleArrayRegion(gradientarray, 0, gsize, gradient);
            }
            // Call Java function
            jdouble result = jni->CallDoubleMethod(data->func, nlopt_func_execute_method, xarray, gradientarray);
            if (jni->ExceptionCheck()) {
                nlopt_force_stop(data->handle);
                return 0.0; // ignored
            }
            if (gradient) {
                // We need to copy data back to C++ land
                jboolean is_copy = false;
                double *xcopy = jni->GetDoubleArrayElements(gradientarray, &is_copy);
                if (!xcopy || jni->ExceptionCheck()) {
                    nlopt_force_stop(data->handle);
                    return 0.0; // ignored
                }
                // Copy data
                std::copy(xcopy, xcopy+gsize, gradient);
                // Release the managed copy
                jni->ReleaseDoubleArrayElements(gradientarray, xcopy, 0);
            }
            return result;
        }
        jni->ThrowNew(illegal_argument_exception_class, "No function set");
        nlopt_force_stop(data->handle);
        return 0.0; // ignored
    }

    JNIEXPORT void JNICALL Java_org_nlopt4j_optimizer_NLopt_init(JNIEnv *jni, jclass myclass)
    {
        // We cache references to objects and fields we need to reference 
        jclass localclass = jni->FindClass("java/lang/String");
        if (jni->ExceptionCheck()) return;
        string_class = (jclass)(jni->NewGlobalRef(localclass));
        jni->DeleteLocalRef(localclass);

        localclass = jni->FindClass("org/nlopt4j/optimizer/NLopt$NLopt_func");<commit_msg>issue #1 release local references to allocated arrays so that the JVM can reclaim memory sooner<commit_after>
// nlopt4j
// Provides a JNI wrapper for NLopt (http://ab-initio.mit.edu/wiki/index.php/NLopt)
// LICENSE: See LICENSE file

#include <nlopt.h>
#include <nlopt_jni.h>

#include <algorithm>

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#ifdef __cpluplus
extern "C" {
#endif

    // Cache Java class and method handles for performance reasons
    static JavaVM *jvm;
    static jclass string_class;
    static jclass nlopt_func_class;
    static jmethodID nlopt_func_execute_method;
    static jclass illegal_argument_exception_class;
    static jclass out_of_memory_class;
    static jclass illegal_state_exception_class;

    // Must have same structure as NLopt_data
    struct Constraint_function {
        jobject func;
        nlopt_opt handle;
        Constraint_function *next;
        Constraint_function *unused;
    };

    struct NLopt_data {
        jobject func;
        nlopt_opt handle;
        Constraint_function *first_constraint;
        Constraint_function *last_constraint;
    };

    // We store a reference to the JVM so that we can use it
    // when invoking the callback
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
    {
        jvm = vm;
        return JNI_VERSION_1_6;
    }

    // Wrapper for the Java implementation of the NLopt
    // function callback
    double nlopt_minfunc(unsigned n, const double *x,
        double *gradient, /* NULL if not needed */
        void *func_data)
    {
        NLopt_data *data = (NLopt_data *)func_data;
        // Get JNI environment
        JNIEnv *jni = NULL;
        if (jvm->GetEnv(reinterpret_cast<void **>(&jni), JNI_VERSION_1_6) != JNI_OK) {
            fprintf(stderr, "Error: Unable to obtain JNI environment\n");
            nlopt_force_stop(data->handle);
            return 0.0; // ignored
        }

        if (data->func) {
            jdoubleArray xarray = NULL;
            jdoubleArray gradientarray = NULL;

            // Create Java arrays
            xarray = jni->NewDoubleArray(n);
            if (!xarray || jni->ExceptionCheck()) {
                nlopt_force_stop(data->handle);
                return 0.0; // ignored
            }
            unsigned gsize = gradient ? n : 0;
            gradientarray = jni->NewDoubleArray(gsize);
            if (!gradientarray || jni->ExceptionCheck()) {
                // avoid holding on to memory - see issue #1
                jni->DeleteLocalRef(xarray);
                nlopt_force_stop(data->handle);
                return 0.0; // ignored
            }
            // Copy data into Java arrays
            jni->SetDoubleArrayRegion(xarray, 0, n, x);
            if (gradient) {
                jni->SetDoubleArrayRegion(gradientarray, 0, gsize, gradient);
            }
            // Call Java function
            jdouble result = jni->CallDoubleMethod(data->func, nlopt_func_execute_method, xarray, gradientarray);
            if (jni->ExceptionCheck()) {
                // avoid holding on to memory - see issue #1
                jni->DeleteLocalRef(xarray);
                jni->DeleteLocalRef(gradientarray);
                nlopt_force_stop(data->handle);
                return 0.0; // ignored
            }
            if (gradient) {
                // We need to copy data back to C++ land
                jboolean is_copy = false;
                double *xcopy = jni->GetDoubleArrayElements(gradientarray, &is_copy);
                if (!xcopy || jni->ExceptionCheck()) {
                    // avoid holding on to memory - see issue #1
                    jni->DeleteLocalRef(xarray);
                    jni->DeleteLocalRef(gradientarray);
                    nlopt_force_stop(data->handle);
                    return 0.0; // ignored
                }
                // Copy data
                std::copy(xcopy, xcopy+gsize, gradient);
                // Release the managed copy
                jni->ReleaseDoubleArrayElements(gradientarray, xcopy, 0);
            }
            // avoid holding on to memory - see issue #1
            jni->DeleteLocalRef(xarray);
            jni->DeleteLocalRef(gradientarray);
            return result;
        }
        jni->ThrowNew(illegal_argument_exception_class, "No function set");
        nlopt_force_stop(data->handle);
        return 0.0; // ignored
    }

    JNIEXPORT void JNICALL Java_org_nlopt4j_optimizer_NLopt_init(JNIEnv *jni, jclass myclass)
    {
        // We cache references to objects and fields we need to reference 
        jclass localclass = jni->FindClass("java/lang/String");
        if (jni->ExceptionCheck()) return;
        string_class = (jclass)(jni->NewGlobalRef(localclass));
        jni->DeleteLocalRef(localclass);

        localclass = jni->FindClass("org/nlopt4j/optimizer/NLopt$NLopt_func");
{'fraction_non_alphanumeric': 0.09458864936207655, 'fraction_numerical': 0.005609326880774307, 'mean_word_length': 1.9852265265922522, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 76, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3920244', 'n_tokens_mistral': 2676, 'n_tokens_neox': 2566, 'n_words': 659}