From: Robert Feldt Date: 2000-09-27T23:33:57+09:00 Subject: [ruby-talk:5156] Re: Proposal: Add constants to Math 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 #include 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