Hi,
Here's some really ugly/brutal code that seems to do the trick (with
NaN, Inf and -Inf). I've successfully tested on both a big and a small
endian machine. Would be great if you could test it on your
machine/setup. Extract 3 files below or get tiny tarball at:
www.ce.chalmers.se/~feldt/ruby/extensions/floatconsts/floatconsts.tar.gz
Matz: Feel free to rip the code and insert constants into Float (or where
you think they fit)... ;-)
Regards,
Robert
Ps. Please read header comment in floatconsts.c in the tarball if you need
more info...
------------------------floatconsts.c
#include <ruby.h>
#include <math.h>
void Init_floatconsts()
{
static unsigned char nan_small_endian_bytes[8] =
{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static unsigned char inf_small_endian_bytes[8] =
{0x7f, 0xf0, 0, 0, 0, 0, 0, 0};
static unsigned char neginf_small_endian_bytes[8] =
{0xff, 0xf0, 0, 0, 0, 0, 0, 0};
static unsigned char nan_big_endian_bytes[8] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
static unsigned char inf_big_endian_bytes[8] =
{0, 0, 0, 0, 0, 0, 0xf0, 0x7f};
static unsigned char neginf_big_endian_bytes[8] =
{0, 0, 0, 0, 0, 0, 0xf0, 0xff};
double nan, inf, neginf;
static int i = 1;
// Try the IEEE 754 floating point standard ways
nan = 0.0/0.0;
inf = 1.0/0.0;
neginf = -1.0/0.0;
// If at least one didn't work we try the brutal way!
if( !isnan(nan) || !isinf(inf) || !isinf(neginf) ) {
// Test endianness
if( 1 == *((char*)&i) ) {
// Big endian
nan = *((double*)nan_big_endian_bytes);
inf = *((double*)inf_big_endian_bytes);
neginf = *((double*)neginf_big_endian_bytes);
} else {
// Small endian
nan = *((double*)nan_small_endian_bytes);
inf = *((double*)inf_small_endian_bytes);
neginf = *((double*)neginf_small_endian_bytes);
}
}
// If even this failed we return without setting them up
if( !isnan(nan) || !isinf(inf) || !isinf(neginf) ) {
printf("Error: Could not add constants\n");
return;
}
// Set up constants
rb_define_const(rb_cFloat, "NAN", rb_float_new(nan));
rb_define_const(rb_cFloat, "INF", rb_float_new(inf));
rb_define_const(rb_cFloat, "NEGINF", rb_float_new(neginf));
}
-----------------extconf.rb
require "mkmf"
$objs = ["floatconsts.o"]
create_makefile("floatconsts")
-----------------test_floatconsts.rb
require 'floatconsts'
if (Float::NAN != nil) and (Float::NAN.nan?) and
(Float::INF != nil) and (Float::INF.infinite? == 1) and
(Float::NEGINF != nil) and (Float::NEGINF.infinite? == -1)
puts "Test successfull!"
else
puts "ERROR: Test failed!"
end