On Thu, 2013-04-25 at 16:31 -0600, Zach wrote:
I am trying to grovel the value of HUGE_VAL from math.h. This: (constant (huge-val "HUGE_VAL") :type double-float) doesn't work, presumably because HUGE_VAL isn't a proper float on my system (but rather some special positive infinity double float). I get this error:
The value NLOPT::INF is not of type REAL.
I need to use HUGE_VAL in the arguments in my NLOpt bindings (hence the package name in NLOPT::INF, though I don't think I even typed INF into the system). I believe that I can't use, say, most-positive-double-float, as there is special behavior when the value HUGE_VAL is used, i.e. it isn't just a large number.
Interestingly, I can grovel HUGE_VAL as an integer with value 18446744073709551615 which, presumably, if I used the ieee-floats system:
(ieee-floats:decode-float64 18446744073709551615) == HUGE_VAL
However, I'm not sure of that and that form naturally produces an overflow error. This is a value that cannot actually be represented as a float, after all. Anyway, I'm not sure that this helps me as I have to pass it to a function that expects a double (actually I pass it as an element in an array of doubles that gets passed to the function): nlopt_result nlopt_set_lower_bounds(nlopt_opt opt, const double* lb); So, I think I need to hold the sizeof(double) bytes in memory (whatever the value of HUGE_VAL is) so that I can write it out to an array later. This is doable, but I am having trouble figuring out the syntax to have the groveler automate the task of getting those sizeof(double) bytes in the first place.
Is there a way to deal with this? Even better, is there a way that CFFI makes this much simpler so I can just pass define whatever holds HUGE_VAL as an opaque object that can be used as a double? Even better yet, the value of HUGE_VAL provided by CFFI already and I am just not seeing it?
Remember that CFFI is untyped, so every (de)reference is an implicit cast. As long as you're careful about the type sizes, you can do something like this:
(with-foreign-object (huge :uint64) (setf (mem-ref huge :uint64) (expt 2 63)) (mem-ref huge :double))
When defining the binding to nlopt_set_lower_bounds, the second argument will be a (generic) pointer and you can pass a pointer to anything.
(constant (+huge-val+ "HUGE_VAL") :type integer)
then
(with-foreign-object (huge-ptr :uint64) (setf (mem-ref huge-ptr :uint64) +huge-val+) (nlopt-set-lower-bound opts huge-ptr))