[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Best way to create Bignum from C extension

Tom Werner

9/25/2007 5:32:00 PM

I've been hand-translating some Ruby code into C for an extension and
have come across the need to create and return a Bignum from the
extension. I see that there is a macro INT2NUM that will produce a
Bignum from long or long long, but what is the best way to create an
arbitrarily sized Bignum from a byte array packed as:

[a, b, c] -> (a * (256 ** 0)) + (b * (256 ** 1)) + (c * (256 ** 2))

in other words, reversing the array and flatting it would produce the
correct binary representation of the number.

I tried creating a Fixnum with INT2FIX(0) and then using rb_funcalls to
incrementally construct a Bignum, but that approach 1) didn't seem to
work past WORD sized numbers and 2) seems like it would be awfully slow.

--
Tom Preston-Werner

* Libraries:
Chronic (chronic.rubyforge.org)
God (god.rubyforge.org)
Fuzed (fuzed.rubyforge.org)
* Site:
rubyisawesome.com


4 Answers

Tom M

9/26/2007 6:37:00 PM

0

On Sep 25, 1:32 pm, Tom Werner <pub...@rubyisawesome.com> wrote:
> I've been hand-translating some Ruby code into C for an extension and
> have come across the need to create and return a Bignum from the
> extension. I see that there is a macro INT2NUM that will produce a
> Bignum from long or long long, but what is the best way to create an
> arbitrarily sized Bignum from a byte array packed as:
>
> [a, b, c] -> (a * (256 ** 0)) + (b * (256 ** 1)) + (c * (256 ** 2))
>
> in other words, reversing the array and flatting it would produce the
> correct binary representation of the number.
>
> I tried creating a Fixnum with INT2FIX(0) and then using rb_funcalls to
> incrementally construct a Bignum, but that approach 1) didn't seem to
> work past WORD sized numbers and 2) seems like it would be awfully slow.
>
> --
> Tom Preston-Werner
>
> * Libraries:
> Chronic (chronic.rubyforge.org)
> God (god.rubyforge.org)
> Fuzed (fuzed.rubyforge.org)
> * Site:
> rubyisawesome.com

dumb question probably, but could you use scientific notation style
numbers; i.e., 1.076 * 10^10? You'd return a base as a float and an
exponent as a fixnum, and then you could calculate it on the fly...

Tom Werner

9/26/2007 6:49:00 PM

0

Tom M wrote:
> On Sep 25, 1:32 pm, Tom Werner <pub...@rubyisawesome.com> wrote:
>
>> I've been hand-translating some Ruby code into C for an extension and
>> have come across the need to create and return a Bignum from the
>> extension. I see that there is a macro INT2NUM that will produce a
>> Bignum from long or long long, but what is the best way to create an
>> arbitrarily sized Bignum from a byte array packed as:
>>
>> [a, b, c] -> (a * (256 ** 0)) + (b * (256 ** 1)) + (c * (256 ** 2))
>>
>> in other words, reversing the array and flatting it would produce the
>> correct binary representation of the number.
>>
>> I tried creating a Fixnum with INT2FIX(0) and then using rb_funcalls to
>> incrementally construct a Bignum, but that approach 1) didn't seem to
>> work past WORD sized numbers and 2) seems like it would be awfully slow.
>>
>> --
>> Tom Preston-Werner
>>
>> * Libraries:
>> Chronic (chronic.rubyforge.org)
>> God (god.rubyforge.org)
>> Fuzed (fuzed.rubyforge.org)
>> * Site:
>> rubyisawesome.com
>>
>
> dumb question probably, but could you use scientific notation style
> numbers; i.e., 1.076 * 10^10? You'd return a base as a float and an
> exponent as a fixnum, and then you could calculate it on the fly...
>
>
>
>

No, the reason I need to do this is to read in Erlang's packed data
representation. Interestingly enough, that *is* how Erlang transmits floats!

--
Tom Preston-Werner

* Libraries:
Chronic (chronic.rubyforge.org)
God (god.rubyforge.org)
Fuzed (fuzed.rubyforge.org)
* Site:
rubyisawesome.com


Tom M

9/26/2007 7:41:00 PM

0

On Sep 26, 2:49 pm, Tom Werner <pub...@rubyisawesome.com> wrote:
> Tom M wrote:
> > On Sep 25, 1:32 pm, Tom Werner <pub...@rubyisawesome.com> wrote:
>
> >> I've been hand-translating some Ruby code into C for an extension and
> >> have come across the need to create and return a Bignum from the
> >> extension. I see that there is a macro INT2NUM that will produce a
> >> Bignum from long or long long, but what is the best way to create an
> >> arbitrarily sized Bignum from a byte array packed as:
>
> >> [a, b, c] -> (a * (256 ** 0)) + (b * (256 ** 1)) + (c * (256 ** 2))
>
> >> in other words, reversing the array and flatting it would produce the
> >> correct binary representation of the number.
>
> >> I tried creating a Fixnum with INT2FIX(0) and then using rb_funcalls to
> >> incrementally construct a Bignum, but that approach 1) didn't seem to
> >> work past WORD sized numbers and 2) seems like it would be awfully slow.
>
> >> --
> >> Tom Preston-Werner
>
> >> * Libraries:
> >> Chronic (chronic.rubyforge.org)
> >> God (god.rubyforge.org)
> >> Fuzed (fuzed.rubyforge.org)
> >> * Site:
> >> rubyisawesome.com
>
> > dumb question probably, but could you use scientific notation style
> > numbers; i.e., 1.076 * 10^10? You'd return a base as a float and an
> > exponent as a fixnum, and then you could calculate it on the fly...
>
> No, the reason I need to do this is to read in Erlang's packed data
> representation. Interestingly enough, that *is* how Erlang transmits floats!
>
> --
> Tom Preston-Werner
>
> * Libraries:
> Chronic (chronic.rubyforge.org)
> God (god.rubyforge.org)
> Fuzed (fuzed.rubyforge.org)
> * Site:
> rubyisawesome.com

something like breaking up the string into substrings and then calling
unpack on each substring, then reassemling... think 'get_more_digits'
since you're already inclined towards Erlang...

Paul Brannan

9/28/2007 3:04:00 PM

0

On Wed, Sep 26, 2007 at 02:32:08AM +0900, Tom Werner wrote:
> I've been hand-translating some Ruby code into C for an extension and
> have come across the need to create and return a Bignum from the
> extension. I see that there is a macro INT2NUM that will produce a
> Bignum from long or long long, but what is the best way to create an
> arbitrarily sized Bignum from a byte array packed as:
>
> [a, b, c] -> (a * (256 ** 0)) + (b * (256 ** 1)) + (c * (256 ** 2))
>
> in other words, reversing the array and flatting it would produce the
> correct binary representation of the number.
>
> I tried creating a Fixnum with INT2FIX(0) and then using rb_funcalls to
> incrementally construct a Bignum, but that approach 1) didn't seem to
> work past WORD sized numbers and 2) seems like it would be awfully slow.

Take a look at the rb_big_* functions declared in intern.h. I think you
can work something out using them.

Paul