#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include #include "const-c.inc" #if INTSIZE == Size_t_size #define FMT_SIZE_T "%d" #else #define FMT_SIZE_T "%ld" #endif #define EXCEPTION "Math::NLopt::Exception" /* copy a C double array (in) into an AV (out). 'out' may be NULL, an AV* or an RV pointing to an AV if 'out' is NULL, a newly allocated AV is returned. */ static SV* double_to_AV( pTHX_ unsigned n, const double *in, SV* out ) { AV* arr; SSize_t i; if ( NULL == out ) { arr = newAV(); av_extend(arr, n ); for ( i = 0 ; i < n ; i++ ) { av_store(arr, i, newSVnv(in[i]) ); } out = (SV*) arr; } else { if ( SvROK( out ) && SvTYPE(SvRV(out)) == SVt_PVAV ) { arr = (AV*) SvRV(out); } else if ( SvTYPE(out) == SVt_PVAV ) { arr = (AV*) out; } else { croak( "internal error: unknown SV passed to double_to_AV" ); } if ( n != av_count(arr) ) croak( "double_to_AV: inconsistent output Perl arr length: expected %d, got " FMT_SIZE_T, n, av_count(arr) ); /* possibly cheaper to call AvARR and get a direct pointer to the SV* arr, but av_fetch ensures the location is populated with an SV, and I don't trust callers not to muck about with things in the AV */ for (i = 0; i < n ; i++ ) { SV** svp = av_fetch( arr, i, 1 ); sv_setnv( *svp, in[i] ); } } return out; } /* copy an AV (in) into a C double array (out). 'in' must have at n slots which must be populated with SV's. it may either by an actual AV or a reference to one if 'out' is NULL, a mortal SVPV is created which will hold the C array. */ static double* AV_to_double( pTHX_ unsigned n, SV* in, double *out ) { AV* arr; SSize_t i; if ( SvROK( in ) && SvTYPE(SvRV(in)) == SVt_PVAV ) { arr = (AV*) SvRV(in); } else if ( SvTYPE(in) == SVt_PVAV ) { arr = (AV*) in; } else { croak( "internal error: unknown SV passed to AV_to_double" ); } SSize_t len = av_count( arr ); if ( len != n ) croak( "AV_to_double: inconsistent input Perl array length: expected %d, got " FMT_SIZE_T, n, len ); if ( NULL == out ) out = (double*) SvPVX( sv_2mortal(newSV(n * sizeof(double))) ); /* possibly cheaper to call AvARRAY and get a direct poarrter to the SV* array, but av_fetch ensures the location is populated with an SV, and I don't trust callers not to muck about with tharrgs arr the AV */ for (i = 0; i < n ; i++ ) { SV** svp = av_fetch( arr, i, 1 ); out[i] = SvNVx( *svp ); } return out; } static AV* populate_array ( pTHX_ AV* array, SSize_t n ) { SSize_t i; av_extend( array, n ); for ( i = 0 ; i < n ; i ++ ) av_store( array, i, newSVnv(0) ); return array; } /* create a Perl array filled with zeroes. returns an RV to the array if n == 0, doesn't extend it or populate it. */ static SV* new_array ( pTHX_ SSize_t n ) { AV* arr = newAV(); SV* rv = newRV_noinc((SV*) arr ); if ( n > 0 ) populate_array( aTHX_ arr, n ); return rv; } /* keep track of all of our goodies */ typedef struct { nlopt_opt self; unsigned int dimension; int throw_on_error; nlopt_result result; nlopt_result optimize_result; double optimum_value; AV* proxies; /* store proxy structures in AV; will be GC'd in DESTROY */ } ProxyNLopt; typedef ProxyNLopt* NLopt; SV* new_ProxyNLopt( pTHX_ nlopt_opt self ) { SV* sv_proxy = newSV(sizeof(ProxyNLopt)); ProxyNLopt * proxy = (ProxyNLopt*) SvPVX( sv_proxy ); proxy->self = self; proxy->dimension = nlopt_get_dimension( self ); proxy->proxies = newAV(); proxy->throw_on_error = 1; return sv_proxy; } static void my_throw( pTHX_ const char * pclass, const char* message ) { SV* object; int count; dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP,2); mPUSHs(newSVpv(pclass, 0 )); mPUSHs(newSVpv(message, 0 )); PUTBACK; count = call_method( "new", G_SCALAR ); SPAGAIN; if (count != 1) croak("Big Trouble\n" ); object = POPs; /* increment ref count otherwise the LEAVE below destroys it */ SvREFCNT_inc_simple_void_NN(object); PUTBACK; FREETMPS; LEAVE; croak_sv( object ); } static void throw_nlopt( pTHX_ int iclass, const char* message ) { SV* object; const char * pclass; int count; switch( iclass ) { case NLOPT_FAILURE: pclass = "Math::NLopt::Exception::Failure"; if ( NULL == message ) message = "failure"; break; case NLOPT_OUT_OF_MEMORY: pclass = "Math::NLopt::Exception::OutOfMemory"; if ( NULL == message ) message = "out of memory"; break; case NLOPT_INVALID_ARGS: pclass = "Math::NLopt::Exception::InvalidArgs"; if ( NULL == message ) message = "invalid argument"; break; case NLOPT_ROUNDOFF_LIMITED: pclass = "Math::NLopt::Exception::RoundoffLimited"; if ( NULL == message ) message = "roundoff limited"; break; case NLOPT_FORCED_STOP: pclass = "Math::NLopt::Exception::ForcedStop"; if ( NULL == message ) message = "forced stop"; break; default: pclass = "Math::NLopt::Exception"; break; } my_throw( aTHX_ pclass, message ); } nlopt_result validate_result ( pTHX_ NLopt opt, nlopt_result result ) { opt->result = result; if ( ! opt->throw_on_error || result >= NLOPT_SUCCESS) return result; const char *errmsg = nlopt_get_errmsg( opt->self ); throw_nlopt( aTHX_ result, errmsg ); /* shouldn't get here */ return result; } static SV* dup_subref( pTHX_ SV* sub ) { SV*copy; if ( ! ( SvTYPE(sub) == SVt_PV || (SvROK(sub) && SvTYPE(SvRV(sub)) == SVt_PVCV ) ) ) croak( "subroutine must either be a codref or string" ); copy = newSV(0); SvSetSV(copy, sub); return copy; } typedef struct { const char *label = "proxyfunc"; SV* perl_sub; /* PV or SV to CV */ SV* x; /* RV to AV */ SV* gradient; /* RV to AV */ SV* data; SV* precond; /* PV containiing possible ProxyPreCondFunc; only used when this is a subsidiary func of that */ } ProxyFunc; static SV* new_ProxyFunc( pTHX_ NLopt opt, SV* sub, unsigned n, SV* data ) { AV* arr; SV* sv_proxy = newSV(sizeof(ProxyFunc)); av_push( opt->proxies, sv_proxy ); ProxyFunc* proxy = (ProxyFunc*) SvPVX( sv_proxy ); proxy->perl_sub = dup_subref( aTHX_ sub); av_push(opt->proxies, proxy->perl_sub ); if ( NULL == data ) { proxy->data = &PL_sv_undef; } else { proxy->data = data; av_push( opt->proxies, SvREFCNT_inc_simple_NN(data) ); } proxy->x = new_array( aTHX_ n ); av_push( opt->proxies, proxy->x ); proxy->gradient = new_array( aTHX_ 0 ); av_push( opt->proxies, proxy->gradient ); return sv_proxy; } /* proxy passed to NLopt for arguments of type nlopt_func */ static double proxy_func ( unsigned n, const double *x, double *gradient, void *data ) { int count; double retval; ProxyFunc *proxy = (ProxyFunc *) SvPVX( (SV*) data); dTHX; /* this is called from C, not from a perl routine, so can't put it in the argument list */ dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP,2); double_to_AV( aTHX_ n, x, proxy->x ); PUSHs( proxy->x ); if ( NULL == gradient ) PUSHs(&PL_sv_undef); else { AV* array = (AV*) SvRV( proxy->gradient ); /* populate if not already done so */ if ( av_count( array ) == 0 ) populate_array( aTHX_ array, n ); PUSHs( proxy->gradient ); } PUSHs(proxy->data); PUTBACK; count = call_sv( proxy->perl_sub, G_SCALAR); SPAGAIN; if (count != 1) croak("Big Trouble\n" ); retval = POPn; if ( NULL != gradient ) AV_to_double( aTHX_ n, proxy->gradient, gradient ); PUTBACK; FREETMPS; LEAVE; return retval; } typedef struct { SV* perl_sub; SV* x; /* RV to AV */ SV* gradient; /* RV to AV */ SV* result; /* RV to AV */ SV* data; } ProxyMFunc; static SV* new_ProxyMFunc( pTHX_ NLopt opt, SV* sub, unsigned n, unsigned m, SV* data ) { SV* sv_proxy = newSV(sizeof(ProxyMFunc)); av_push( opt->proxies, sv_proxy ); ProxyMFunc * proxy = (ProxyMFunc*) SvPVX( sv_proxy ); proxy->perl_sub = dup_subref( aTHX_ sub); av_push(opt->proxies, proxy->perl_sub ); if ( NULL == data ) { proxy->data = &PL_sv_undef; } else { proxy->data = data; av_push( opt->proxies, SvREFCNT_inc_simple_NN(data) ); } proxy->x = new_array( aTHX_ n ); av_push( opt->proxies, proxy->x ); proxy->gradient = new_array( aTHX_ 0 ); av_push( opt->proxies, proxy->gradient ); proxy->result = new_array (aTHX_ n ); av_push( opt->proxies, proxy->result ); return sv_proxy; } static void proxy_mfunc( unsigned m, double *result, unsigned n, const double* x, double* gradient, void *data) { int count; ProxyMFunc *proxy = (ProxyMFunc *) SvPVX( (SV*) data); dTHX; /* this is called from C, not from a perl routine, so can't put it in the argument list */ dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP,4); PUSHs( proxy->result); PUSHs( double_to_AV( aTHX_ n, x, proxy->x ) ); if ( NULL == gradient ) PUSHs(&PL_sv_undef); else { AV* array = (AV*) SvRV( proxy->gradient ); /* populate if not already done so */ if ( av_count( array ) == 0 ) populate_array( aTHX_ array, n * m ); PUSHs( proxy->gradient ); } PUSHs(proxy->data); PUTBACK; count = call_sv( proxy->perl_sub, G_VOID); SPAGAIN; if (count != 1) croak("Big Trouble\n" ); AV_to_double( aTHX_ m, proxy->result, result ); if ( NULL != gradient ) AV_to_double( aTHX_ n * m, proxy->gradient, gradient ); PUTBACK; FREETMPS; LEAVE; } typedef struct { SV* perl_sub; SV* x; /* RV to AV */ SV* v; /* RV to AV */ SV* vpre; /* RV to AV */ SV* data; } ProxyPreCondFunc; static SV* new_ProxyPreCondFunc( pTHX_ NLopt opt, SV* sub, unsigned n, SV* data ) { SV* sv_proxy = newSV(sizeof(ProxyPreCondFunc)); av_push( opt->proxies, sv_proxy ); ProxyPreCondFunc * proxy = (ProxyPreCondFunc*) SvPVX( sv_proxy ); proxy->perl_sub = dup_subref( aTHX_ sub); if ( NULL == data ) { proxy->data = &PL_sv_undef; } else { proxy->data = data; av_push( opt->proxies, SvREFCNT_inc_simple_NN(data) ); } proxy->x = new_array( aTHX_ n ); av_push( opt->proxies, proxy->x ); proxy->v = new_array( aTHX_ n ); av_push( opt->proxies, proxy->v ); proxy->vpre = new_array( aTHX_ n ); av_push( opt->proxies, proxy->vpre ); return sv_proxy; } static void proxy_precond( unsigned n, const double *x, const double *v, double *vpre, void *f_data) { int count; /* there's only one user data available when using preconditioners, but two functions, so we piggy back on the user data for the main objective function */ ProxyPreCondFunc *proxy; dTHX; /* this is called from C, not from a perl routine, so can't put it in the argument list */ proxy = (ProxyPreCondFunc*) SvPVX( ((ProxyFunc *) SvPVX( (SV*) f_data))->precond ); dSP; ENTER; SAVETMPS; PUSHMARK(SP); EXTEND(SP,4); PUSHs( double_to_AV( aTHX_ n, x, proxy->x ) ); PUSHs( double_to_AV( aTHX_ n, v, proxy->v ) ); PUSHs( proxy->vpre ); PUSHs(proxy->data); PUTBACK; count = call_sv( proxy->perl_sub, G_VOID); SPAGAIN; if (count != 1) croak("Big Trouble\n" ); AV_to_double( aTHX_ n, proxy->vpre, vpre ); PUTBACK; FREETMPS; LEAVE; } typedef nlopt_result validated_result; MODULE = Math::NLopt PACKAGE = Math::NLopt PREFIX = nlopt_ TYPEMAP: <self; } else { const char* refstr = SvROK($arg) ? \"\" : SvOK($arg) ? \"scalar \" : \"undef\"; Perl_croak_nocontext(\"%s: Expected %s to be of type %s; got %s%\" SVf \" instead\", ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]}, \"$var\", \"Math::NLopt\", refstr, $arg ); } T_NLopt if (sv_isa($arg, \"$Package\")) { $var = (ProxyNLopt*) SvPVX( SvRV($arg) ); } else { const char* refstr = SvROK($arg) ? \"\" : SvOK($arg) ? \"scalar \" : \"undef\"; Perl_croak_nocontext(\"%s: Expected %s to be of type %s; got %s%\" SVf \" instead\", ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]}, \"$var\", \"$Package\", refstr, $arg ); } OUTPUT # this mess assumes that the first argument, ST(0), is an NLopt . it's equivalent to validate_result( opt, RETVAL) T_VALIDATED_RESULT ${ "$var" eq "RETVAL" ? \"$arg = newSViv(validate_result(aTHX_ (ProxyNLopt*) SvPVX( SvRV(ST(0))),$var));" : croak('INTERNAL ERROR VALIDATED_RESULT ONLY USES RETVAL'); } # vendored fix from 5.15.4 TYPEMAP AV* T_MY_AVREF_REFCOUNT_FIXED INPUT T_MY_AVREF_REFCOUNT_FIXED STMT_START { SV* const xsub_tmp_sv = $arg; SvGETMAGIC(xsub_tmp_sv); if (SvROK(xsub_tmp_sv) && SvTYPE(SvRV(xsub_tmp_sv)) == SVt_PVAV){ $var = (AV*)SvRV(xsub_tmp_sv); } else{ Perl_croak_nocontext(\"%s: %s is not an ARRAY reference\", ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]}, \"$var\"); } } STMT_END OUTPUT # Copy T_MY_AVREF_REFCOUNT_FIXED ${ "$var" eq "RETVAL" ? \"$arg = newRV_noinc((SV*)$var);" : \"sv_setrv_noinc($arg, (SV*)$var);" } EOT PROTOTYPES: DISABLE INCLUDE: const-xs.inc validated_result nlopt_add_equality_constraint(opt, h, ... ) NLopt opt SV* h PREINIT: SV* func; SV* h_data; double tol; CODE: if (items > 4) croak_xs_usage(cv, "too many arguments" ); h_data = items > 2 ? ST(2) : &PL_sv_undef; tol = items > 3 ? (double) SvNV(ST(3)) : 0; func = new_ProxyFunc( aTHX_ opt, h, opt->dimension, h_data ); RETVAL = nlopt_add_equality_constraint( opt->self, &proxy_func, (void*) func, tol); OUTPUT: RETVAL validated_result nlopt_add_inequality_constraint(opt, fc, ... ) NLopt opt SV* fc PREINIT: SV* func; SV* fc_data; double tol; CODE: if (items > 4) croak_xs_usage(cv, "too many arguments" ); fc_data = items > 2 ? ST(2) : &PL_sv_undef; tol = items > 3 ? (double) SvNV(ST(3)) : 0; func = new_ProxyFunc( aTHX_ opt, fc, opt->dimension, fc_data ); RETVAL = nlopt_add_inequality_constraint( opt->self, &proxy_func, (void*) func, tol); OUTPUT: RETVAL validated_result nlopt_add_equality_mconstraint(opt, m, h, ... ) NLopt opt unsigned m SV* h PREINIT: SV* func; SV* h_data; SV* tol; double *c_tol = NULL; CODE: if (items > 5) croak_xs_usage(cv, "too many arguments" ); h_data = items > 3 ? ST(3) : &PL_sv_undef; tol = items > 4 ? ST(4) : &PL_sv_undef; func = new_ProxyMFunc( aTHX_ opt, h, opt->dimension, m, h_data ); if ( tol != &PL_sv_undef ) c_tol = AV_to_double( aTHX_ m, tol, NULL ); RETVAL = nlopt_add_equality_mconstraint( opt->self, m, &proxy_mfunc, (void*) func, c_tol); OUTPUT: RETVAL validated_result nlopt_add_inequality_mconstraint(opt, m, fc, ... ) NLopt opt unsigned m SV* fc PREINIT: SV* func; SV* fc_data; SV* tol; double *c_tol = NULL; CODE: if (items > 5) croak_xs_usage(cv, "too many arguments" ); fc_data = items > 3 ? ST(3) : &PL_sv_undef; tol = items > 4 ? ST(4) : &PL_sv_undef; func = new_ProxyMFunc( aTHX_ opt, fc, opt->dimension, m, fc_data ); if ( tol != &PL_sv_undef ) c_tol = AV_to_double( aTHX_ m, tol, NULL); RETVAL = nlopt_add_inequality_mconstraint( opt->self, m, &proxy_mfunc, (void*) func, c_tol); OUTPUT: RETVAL nlopt_algorithm nlopt_algorithm_from_string(name) const char * name const char * nlopt_algorithm_name(a) nlopt_algorithm a const char * nlopt_algorithm_to_string(algorithm) nlopt_algorithm algorithm # NLopt # nlopt_copy(opt) # NLopt opt SV* new(classname, algorithm, n) SV* classname nlopt_algorithm algorithm unsigned n PREINIT: SV* rv; CODE: rv = newRV( new_ProxyNLopt( aTHX_ nlopt_create( algorithm, n ) ) ); sv_bless( rv, gv_stashsv( classname, GV_NOADD_NOINIT ) ); RETVAL = rv; OUTPUT: RETVAL SV* nlopt_create(algorithm, n) nlopt_algorithm algorithm unsigned n PREINIT: SV* rv; HV* stash; CODE: rv = newRV( new_ProxyNLopt( aTHX_ nlopt_create( algorithm, n ) )); stash = gv_stashpvs( "Math::NLopt", GV_NOADD_NOINIT ); sv_bless( rv, stash ); RETVAL = rv; OUTPUT: RETVAL void DESTROY(opt) NLopt opt CODE: /* all of the proxy SV's should be in the proxies AV in opt; drop its refcount and that should delete them all */ nlopt_destroy(opt->self); SvREFCNT_dec( opt->proxies ); validated_result nlopt_force_stop(opt) nlopt_opt opt nlopt_algorithm nlopt_get_algorithm(opt) nlopt_opt opt unsigned nlopt_get_dimension(opt) NLopt opt CODE: RETVAL = opt->dimension; OUTPUT: RETVAL const char * nlopt_get_errmsg(opt) nlopt_opt opt int nlopt_get_force_stop(opt) nlopt_opt opt double nlopt_get_ftol_abs(opt) nlopt_opt opt double nlopt_get_ftol_rel(opt) nlopt_opt opt AV* nlopt_get_initial_step(opt, x) NLopt opt AV* x PREINIT: unsigned n; double* c_x; double* c_dx; CODE: n = opt->dimension; c_x = AV_to_double( aTHX_ n, (SV*) x, NULL); c_dx = (double*) SvPVX( sv_2mortal(newSV(n * sizeof(double))) ); validate_result( aTHX_ opt, nlopt_get_initial_step( opt->self, c_x, c_dx ) ); RETVAL = (AV*) double_to_AV( aTHX_ n, c_dx, NULL ); OUTPUT: RETVAL AV* nlopt_get_lower_bounds(opt) NLopt opt PREINIT: unsigned n; double* c_lb; CODE: n = opt->dimension; c_lb = (double*) SvPVX( sv_2mortal(newSV(n * sizeof(double))) ); validate_result( aTHX_ opt, nlopt_get_lower_bounds(opt->self, c_lb ) ); RETVAL = (AV*) double_to_AV( aTHX_ n, c_lb, NULL ); OUTPUT: RETVAL int nlopt_get_maxeval(opt) nlopt_opt opt double nlopt_get_maxtime(opt) nlopt_opt opt int nlopt_get_numevals(opt) nlopt_opt opt double nlopt_get_param(opt, name, defaultval) nlopt_opt opt const char * name double defaultval unsigned nlopt_get_population(opt) nlopt_opt opt double nlopt_get_stopval(opt) nlopt_opt opt AV* nlopt_get_upper_bounds(opt) NLopt opt PREINIT: unsigned n; double* c_ub; CODE: n = opt->dimension; c_ub = (double*) SvPVX( sv_2mortal(newSV(n * sizeof(double))) ); validate_result( aTHX_ opt, nlopt_get_upper_bounds( opt->self, c_ub ) ); RETVAL = (AV*) double_to_AV( aTHX_ n, c_ub, NULL ); OUTPUT: RETVAL unsigned nlopt_get_vector_storage(opt) nlopt_opt opt AV* nlopt_get_x_weights(opt) NLopt opt PREINIT: unsigned n; double* c_w; CODE: n = opt->dimension; c_w = (double*) SvPVX( sv_2mortal(newSV(n * sizeof(double))) ); validate_result( aTHX_ opt, nlopt_get_x_weights( opt->self, c_w ) ); RETVAL = (AV*) double_to_AV( aTHX_ n, c_w, NULL ); OUTPUT: RETVAL AV* nlopt_get_xtol_abs(opt) NLopt opt PREINIT: unsigned n; double* c_tol; CODE: n = opt->dimension; c_tol = (double*) SvPVX( sv_2mortal(newSV(n * sizeof(double))) ); validate_result( aTHX_ opt, nlopt_get_xtol_abs( opt->self, c_tol ) ); RETVAL = (AV*) double_to_AV( aTHX_ n, c_tol, NULL ); OUTPUT: RETVAL double nlopt_get_xtol_rel(opt) nlopt_opt opt int nlopt_has_param(opt, name) nlopt_opt opt const char * name const char * nlopt_nth_param(opt, n) nlopt_opt opt unsigned n unsigned nlopt_num_params(opt) nlopt_opt opt nlopt_result last_optimize_result ( opt ) NLopt opt CODE: RETVAL = opt->optimize_result; OUTPUT: RETVAL double last_optimum_value ( opt ) NLopt opt CODE: RETVAL = opt->optimum_value; OUTPUT: RETVAL AV* nlopt_optimize(opt, x) NLopt opt AV* x PREINIT: unsigned n; double* c_x; CODE: n = opt->dimension; c_x = AV_to_double( aTHX_ n, (SV*) x, NULL ); /* store result first, then validate it, so that if validate_result throws the result is available via last_optimize_result */ opt->optimize_result = nlopt_optimize( opt->self, c_x, &(opt->optimum_value) ); validate_result( aTHX_ opt, opt->optimize_result ); RETVAL = (AV*) double_to_AV( aTHX_ n, c_x, NULL ); OUTPUT: RETVAL validated_result nlopt_remove_equality_constraints(opt) nlopt_opt opt validated_result nlopt_remove_inequality_constraints(opt) nlopt_opt opt nlopt_result nlopt_result_from_string(name) const char * name const char * nlopt_result_to_string(algorithm) nlopt_result algorithm validated_result nlopt_set_force_stop(opt, val) nlopt_opt opt int val validated_result nlopt_set_ftol_abs(opt, tol) nlopt_opt opt double tol validated_result nlopt_set_ftol_rel(opt, tol) nlopt_opt opt double tol validated_result nlopt_set_initial_step(opt, dx) NLopt opt AV* dx PREINIT: double *c_dx = NULL; CODE: c_dx = AV_to_double( aTHX_ opt->dimension, (SV*) dx, NULL); RETVAL = nlopt_set_initial_step( opt->self, c_dx ); OUTPUT: RETVAL validated_result nlopt_set_initial_step1(opt, dx) nlopt_opt opt double dx validated_result nlopt_set_local_optimizer(opt, local_opt) nlopt_opt opt nlopt_opt local_opt validated_result nlopt_set_lower_bound(opt, i, lb) nlopt_opt opt int i double lb validated_result nlopt_set_lower_bounds(opt, lb) NLopt opt AV* lb PREINIT: double* c_lb; CODE: /* NLopt makes a copy of c_lb, so don't need to keep it around */ c_lb = AV_to_double( aTHX_ opt->dimension, (SV*) lb, NULL ); RETVAL = nlopt_set_lower_bounds( opt->self, c_lb); OUTPUT: RETVAL validated_result nlopt_set_lower_bounds1(opt, lb) nlopt_opt opt double lb validated_result nlopt_set_max_objective(opt, f, ...) NLopt opt SV* f PREINIT: SV* func; SV * f_data; CODE: if (items > 4) croak_xs_usage(cv, "too many arguments" ); f_data = items > 3 ? ST(3) : &PL_sv_undef; func = new_ProxyFunc( aTHX_ opt, f, opt->dimension, f_data ); RETVAL = nlopt_set_max_objective( opt->self, &proxy_func, (void*) func ); OUTPUT: RETVAL validated_result nlopt_set_maxeval(opt, maxeval) nlopt_opt opt int maxeval validated_result nlopt_set_maxtime(opt, maxtime) nlopt_opt opt double maxtime validated_result nlopt_set_min_objective(opt, f, ... ) NLopt opt SV* f PREINIT: SV * func; SV * f_data; CODE: if (items > 3) croak_xs_usage(cv, "too many arguments" ); f_data = items > 2 ? ST(2) : &PL_sv_undef; func = new_ProxyFunc( aTHX_ opt, f, opt->dimension, f_data ); RETVAL = nlopt_set_min_objective( opt->self, &proxy_func, (void*) func ); OUTPUT: RETVAL validated_result nlopt_set_param(opt, name, val) nlopt_opt opt const char * name double val validated_result nlopt_set_population(opt, pop) nlopt_opt opt unsigned pop validated_result nlopt_set_precond_max_objective(opt, f, pre, ...) NLopt opt SV* f SV* pre PREINIT: unsigned n; SV* prefunc; SV* func; SV * f_data; CODE: if (items > 4) croak_xs_usage(cv, "too many arguments" ); f_data = items > 3 ? ST(3) : &PL_sv_undef; n = opt->dimension; prefunc = new_ProxyPreCondFunc( aTHX_ opt, f, n, f_data ); func = new_ProxyFunc( aTHX_ opt, f, n, f_data ); ((ProxyFunc*) SvPVX( func ))->precond = prefunc; RETVAL = nlopt_set_precond_max_objective( opt->self, &proxy_func, &proxy_precond, (void*) func ); OUTPUT: RETVAL validated_result nlopt_set_precond_min_objective(opt, f, pre, ...) NLopt opt SV* f SV* pre PREINIT: unsigned n; SV* prefunc; SV* func; SV * f_data; CODE: if (items > 4) croak_xs_usage(cv, "too many arguments" ); f_data = items > 3 ? ST(3) : &PL_sv_undef; n = opt->dimension; prefunc = new_ProxyPreCondFunc( aTHX_ opt, f, n, f_data ); func = new_ProxyFunc( aTHX_ opt, f, n, f_data ); ((ProxyFunc*) SvPVX( func ))->precond = prefunc; RETVAL = nlopt_set_precond_min_objective( opt->self, &proxy_func, &proxy_precond, (void*) func ); OUTPUT: RETVAL validated_result nlopt_set_stopval(opt, stopval) nlopt_opt opt double stopval validated_result nlopt_set_upper_bound(opt, i, ub) nlopt_opt opt int i double ub validated_result nlopt_set_upper_bounds(opt, ub) NLopt opt AV* ub PREINIT: double* c_ub; CODE: /* NLopt makes a copy of c_ub, so don't need to keep it around */ c_ub = AV_to_double( aTHX_ opt->dimension, (SV*) ub, NULL ); RETVAL = nlopt_set_upper_bounds( opt->self, c_ub); OUTPUT: RETVAL validated_result nlopt_set_upper_bounds1(opt, ub) nlopt_opt opt double ub validated_result nlopt_set_vector_storage(opt, dim) nlopt_opt opt unsigned dim validated_result nlopt_set_x_weights(opt, w) NLopt opt AV * w PREINIT: double* c_w; CODE: c_w = AV_to_double( aTHX_ opt->dimension, (SV*) w, NULL ); RETVAL = nlopt_set_x_weights( opt->self, c_w); OUTPUT: RETVAL validated_result nlopt_set_x_weights1(opt, w) nlopt_opt opt double w validated_result nlopt_set_xtol_abs(opt, tol) NLopt opt AV* tol PREINIT: double* c_tol; CODE: c_tol = AV_to_double( aTHX_ opt->dimension, (SV*) tol, NULL ); RETVAL = nlopt_set_xtol_abs( opt->self, c_tol); OUTPUT: RETVAL validated_result nlopt_set_xtol_abs1(opt, tol) nlopt_opt opt double tol validated_result nlopt_set_xtol_rel(opt, tol) nlopt_opt opt double tol void nlopt_srand(seed) unsigned long seed void nlopt_srand_time() void nlopt_version( OUTLIST major, OUTLIST minor, OUTLIST bugfix) int major int minor int bugfix # this is NOT part of the public API nlopt_result _validate_result ( opt, result ) NLopt opt nlopt_result result CODE: RETVAL = validate_result( aTHX_ opt, result ); OUTPUT: RETVAL