3

I have a C module that I am testing with Ruby test by extending ruby with this piece of C code. Any number above 2 ** 24 -1 is being modified. I need to pass 64-bit values back and forth between Ruby and C and it should be bit-precise. Any thoughts would be appreciated.

in c extension:
long int sig_val;
sig_val = NUM2LL(sig) // sig is type VALUE and is ruby number to be passed on to C

. . . Few example of data I passed:

  • (2^34 -1) * 16 ==> C receives (2^34) * 16
  • (2^34 +1) * 16 ==> C receives (2^34) * 16
  • (2^24 +1) * 16 ==> C receives (2^24) * 16
  • (2^25 -1) ==> C receives (2^25)
  • (2^24 -1) ==> C receives (2^24 -1) (Correct)

Any number below is also correct.

Thank you!

aalavi
  • 63
  • 5
  • 1
    Ruby uses some of the higher bits as flags (an optimization which allows commonly used smaller integers to be themselves rather than forcing them to be wrapped in a layer of indirection), sounds like you're running into those flag bits somewhere. – mu is too short May 02 '13 at 22:21
  • How are you testing what the C is receiving? It is possible one or more reverse conversions are also affected, making the problem seem more complicated. Also, are you compiling to 64-bit or 32-bit in your tests? If the former you may not need a `long long` – Neil Slater May 03 '13 at 05:39
  • Thanks for your time... I print out the data right at the entry point of the C function I am wrapping. Also, I used sizeof() and long int is 8 bytes and int is 4. I am now thinking of sending the ruby number as array of 8 bytes (char) and add them up accordingly in wrapping extension layer before sending them into the C routine. – aalavi May 03 '13 at 06:26
  • mu is too short, I agree... I actually realized that no matter what size of the number is, it maintains only 24 bits and rounds things up such that with 24 bits and bunch of trivial zeros, it can represent the number (or close approximate of) – aalavi May 03 '13 at 06:30
  • 2
    I just realized that in the code, there is a typecast to float that causes ruby to limit number of bits to 24 (as per single point IEEE754 I guess). Now I can pass 64-bit wide numbers using NUM2LL and LL2NUM. Thank you – aalavi May 03 '13 at 19:41
  • @aalavi - If you're game to recap the solution as your own answer, I'll delete my answer. (See http://meta.stackexchange.com/questions/90263/unanswered-question-answered-in-comments for elaboration of why this is helpful.) Thanks! – DreadPirateShawn Oct 10 '13 at 06:18

1 Answers1

0

Copying the answer from the comments in order to remove this question from the "Unanswered" filter:

I just realized that in the code, there is a typecast to float that causes ruby to limit number of bits to 24 (as per single point IEEE754 I guess). Now I can pass 64-bit wide numbers using NUM2LL and LL2NUM. Thank you

~ answer per aalavi

Community
  • 1
  • 1
DreadPirateShawn
  • 8,164
  • 4
  • 49
  • 71