#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <nlopt.h>
#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: <<EOT
const char * T_PTROBJ
const double * T_PTROBJ
double * T_PTROBJ
int * T_PTROBJ
# enums
nlopt_algorithm T_ENUM
nlopt_result T_ENUM
validated_result T_VALIDATED_RESULT
# object pointer
NLopt T_NLopt
# convert from our object directly to nlopt_opt
nlopt_opt T_nlopt_opt
# pointers to functions; they are passed a void* user data
# which the proxy functions use to associate a particular
# perl sub instance.
nlopt_func T_PTROBJ
nlopt_mfunc T_PTROBJ
nlopt_precond T_PTROBJ
INPUT
T_nlopt_opt
if (sv_isa($arg, \"$Package\")) {
$var = ((ProxyNLopt*) SvPVX( SvRV($arg) ))->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