Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

r29111 - docs/Perl6/Spec

0 views
Skip to first unread message

pugs-c...@feather.perl6.nl

unread,
Nov 17, 2009, 12:43:13 PM11/17/09
to perl6-l...@perl.org
Author: lwall
Date: 2009-11-17 18:43:12 +0100 (Tue, 17 Nov 2009)
New Revision: 29111

Modified:
docs/Perl6/Spec/S02-bits.pod
Log:
[S02] more Rat and Ratio clarification


Modified: docs/Perl6/Spec/S02-bits.pod
===================================================================
--- docs/Perl6/Spec/S02-bits.pod 2009-11-17 17:28:47 UTC (rev 29110)
+++ docs/Perl6/Spec/S02-bits.pod 2009-11-17 17:43:12 UTC (rev 29111)
@@ -649,12 +649,11 @@
machines that are not natively 2's complement. You must convert to
and from C<Int> to do portable bitops on such ancient hardware.)

-(C<Num> may support arbitrary-precision floating-point arithmetic, but
-is not required to unless we can do so portably and efficiently. C<Num>
-must support the largest native floating point format that runs at full
-speed.)
+C<Num> must support the largest native floating point format that
+runs at full speed. It may be bound to an arbitrary precision type,
+but by default it is the same type as a native C<num>. See below.

-C<Rat> supports arbitrary precision rational arithmetic.
+C<Rat> supports extended precision rational arithmetic.
Dividing two C<Int> objects using C<< infix:</> >> produces a
a C<Rat>, which is generally usable anywhere a C<Num> is usable, but
may also be explicitly cast to C<Num>. (Also, if either side is
@@ -688,8 +687,14 @@
the Big Bang with picosecond precision. Though perhaps not with
picosecond accuracy...)

-For applications that really need arbitrary precision denominators
-as well as numerators, C<Ratio> may be used, which is defined as C<Int/Int>.
+For applications that really need arbitrary precision denominators as
+well as numerators at the cost of performance, C<Ratio> may be used,
+which is stored as C<Int/Int>, that is, as arbitrary precision in
+both parts. There is no literal form for a C<Ratio>, so it must
+be constructed using C<Ratio.new($nu,$de)>. In general, only math
+operators with at least one C<Ratio> argument will return another
+C<Ratio>, to prevent accidental promotion of reasonably fast C<Rat>
+values into arbitrarily slow C<Ratio> values.

=item *

Darren Duncan

unread,
Nov 18, 2009, 3:33:35 AM11/18/09
to perl6-l...@perl.org
Acknowledging that 'FatRat' is current name for above 'Ratio' ...

pugs-c...@feather.perl6.nl wrote:
> -For applications that really need arbitrary precision denominators
> -as well as numerators, C<Ratio> may be used, which is defined as C<Int/Int>.
> +For applications that really need arbitrary precision denominators as
> +well as numerators at the cost of performance, C<Ratio> may be used,
> +which is stored as C<Int/Int>, that is, as arbitrary precision in
> +both parts. There is no literal form for a C<Ratio>, so it must
> +be constructed using C<Ratio.new($nu,$de)>. In general, only math
> +operators with at least one C<Ratio> argument will return another
> +C<Ratio>, to prevent accidental promotion of reasonably fast C<Rat>
> +values into arbitrarily slow C<Ratio> values.

Given the above, if one wants to construct a full-precision rational value in
terms of 3 Int values analogous to a mantissa and radix and exponent, what is
the best way to write it in Perl 6?

For example, say I want the following expression to result in a FatRat because
presumably that's the only type which will represent the result value exactly:

45207196 * 10 ** -37

How should that be spelled out in terms of 3 integers?

And note that a decimal-specific answer isn't what I want, since I want
something that would also work for this:

45207196 * 11 ** -37

Any thoughts?

Basically where I'm coming from here is the idea that any rational can also be
expressed as 3 integers like the above, not just the numerator/denominator pair;
the 3 integers are advantages both for being efficient with common pathological
cases such as very large or very small rationals with a small amount of
precision, such as the above, as well as for exactly reflecting the concept of a
radix-agnostic floating-point number.

Thank you. -- Darren Duncan

Solomon Foster

unread,
Nov 18, 2009, 9:39:56 AM11/18/09
to perl6-l...@perl.org

What's your objection to FatRat.new(45207196, 11 ** 37)?

--
Solomon Foster: col...@gmail.com
HarmonyWare, Inc: http://www.harmonyware.com

Moritz Lenz

unread,
Nov 18, 2009, 3:58:09 AM11/18/09
to perl6-l...@perl.org
On Wed, Nov 18, 2009 at 12:33:35AM -0800, Darren Duncan wrote:
> Acknowledging that 'FatRat' is current name for above 'Ratio' ...
>
> pugs-c...@feather.perl6.nl wrote:
>> -For applications that really need arbitrary precision denominators
>> -as well as numerators, C<Ratio> may be used, which is defined as C<Int/Int>.
>> +For applications that really need arbitrary precision denominators as
>> +well as numerators at the cost of performance, C<Ratio> may be used,
>> +which is stored as C<Int/Int>, that is, as arbitrary precision in
>> +both parts. There is no literal form for a C<Ratio>, so it must
>> +be constructed using C<Ratio.new($nu,$de)>. In general, only math
>> +operators with at least one C<Ratio> argument will return another
>> +C<Ratio>, to prevent accidental promotion of reasonably fast C<Rat>
>> +values into arbitrarily slow C<Ratio> values.
>
> Given the above, if one wants to construct a full-precision rational
> value in terms of 3 Int values analogous to a mantissa and radix and
> exponent, what is the best way to write it in Perl 6?
>
> For example, say I want the following expression to result in a FatRat
> because presumably that's the only type which will represent the result
> value exactly:
>
> 45207196 * 10 ** -37
>
> How should that be spelled out in terms of 3 integers?

why 3?

FatRat.new(45207196, 10**37);

> And note that a decimal-specific answer isn't what I want, since I want
> something that would also work for this:
>
> 45207196 * 11 ** -37

FatRat.new(45207196, 11**37);

> Any thoughts?
>
> Basically where I'm coming from here is the idea that any rational can
> also be expressed as 3 integers like the above, not just the
> numerator/denominator pair; the 3 integers are advantages both for being
> efficient with common pathological cases such as very large or very small
> rationals with a small amount of precision, such as the above, as well as
> for exactly reflecting the concept of a radix-agnostic floating-point
> number.

I think that's an implementation detail. If you care much about it, you'll
have to provide your Rat type.

Cheers,
Moritz

Jon Lang

unread,
Nov 18, 2009, 4:36:04 PM11/18/09
to Moritz Lenz, perl6-l...@perl.org
Moritz Lenz wrote:
>> Given the above, if one wants to construct a full-precision rational
>> value in terms of 3 Int values analogous to a mantissa and radix and
>> exponent, what is the best way to write it in Perl 6?
>>
>> For example, say I want the following expression to result in a FatRat
>> because presumably that's the only type which will represent the result
>> value exactly:
>>
>>   45207196 * 10 ** -37
>>
>> How should that be spelled out in terms of 3 integers?
>
> why 3?

Because three attributes let you define them all as the same kind of
int, instead of one having twice as many bits in it as the other:

has int128 $whole, int128 $numerator, int128 $denominator

vs.

has int256 $numerator, int128 $denominator

This matters when you reach the upper end of the low-level integer
types, such that there is no longer an available integer type that has
twice as many bits as the denominator type. But as you say, this is
an implementation detail. The important thing for the Spec to note is
that user expectations require Rational types to be able to handle a
whole number part that's at least as large as the denominator part.
Right now, the spec is addressing this in terms of implementation
details: it assumes that a Rational will store exactly two numbers,
representing the numerator and the denominator, and that the numerator
must have twice as much storage space reserved for it as the
denominator has. Why twice as much? So that no matter how large the
denominator is, the numerator will be large enough to store a whole
number part that's at least as large. The doubled bits isn't an end
to itself, but merely a means to a more fundamental end.

--
Jonathan "Dataweaver" Lang

Darren Duncan

unread,
Nov 18, 2009, 5:15:12 PM11/18/09
to perl6-l...@perl.org
Moritz Lenz wrote:
> On Wed, Nov 18, 2009 at 12:33:35AM -0800, Darren Duncan wrote:
>> For example, say I want the following expression to result in a FatRat
>> because presumably that's the only type which will represent the result
>> value exactly:
>>
>> 45207196 * 10 ** -37
>>
>> How should that be spelled out in terms of 3 integers?
>
> why 3?

I think Jon Lang gave a good reply to that.

I will also add, because that's conceptually what an IEEE float does, and
technically an IEEE float is still exact precision but it is limited in what
values it can represent so selecting an IEEE float value in the first place may
involve rounding, but once you have, the 3-integer representation of a rational
allows the float to be represented as a rational, tersely, and also radix
agnostically if the 2 or 10 is explicit. And it works with just-as-minimal
memory use when you convert from a 64-bit float like "8.125*2**-4000".

> FatRat.new(45207196, 10**37);
>
>> And note that a decimal-specific answer isn't what I want, since I want
>> something that would also work for this:
>>
>> 45207196 * 11 ** -37
>
> FatRat.new(45207196, 11**37);

Solomon Foster wrote:
> What's your objection to FatRat.new(45207196, 11 ** 37)?

Well, for one thing, that's not the same value. I had a "-37" as the exponent,
designating a small non-integer rational value, whereas the FatRat example had
flipped this around to "37", not the same value.

Now I'm sure the format you showed looks great, but my concern is, does simply
saying this:

11 ** -37

... result in a FatRat and if not then how do I write "11^-37" in Perl 6 such
that the resulting object retains the full precision of the value?

-- Darren Duncan

Darren Duncan

unread,
Nov 20, 2009, 12:34:51 AM11/20/09
to perl6-l...@perl.org
Darren Duncan wrote:

> Moritz Lenz wrote:
>> FatRat.new(45207196, 10**37);
>>
>>> And note that a decimal-specific answer isn't what I want, since I
>>> want something that would also work for this:
>>>
>>> 45207196 * 11 ** -37
>>
>> FatRat.new(45207196, 11**37);
>
> Solomon Foster wrote:
>> What's your objection to FatRat.new(45207196, 11 ** 37)?
>
> Well, for one thing, that's not the same value. I had a "-37" as the
> exponent, designating a small non-integer rational value, whereas the
> FatRat example had flipped this around to "37", not the same value.
>
> Now I'm sure the format you showed looks great, but my concern is, does
> simply saying this:
>
> 11 ** -37
>
> ... result in a FatRat and if not then how do I write "11^-37" in Perl 6
> such that the resulting object retains the full precision of the value?

Actually, I realize now what was going on with that suggestion, and that it
actually was valid for the case I mentioned, being presumably equal to:

45207196 * FatRat.new( 1, 11**37 )

However, the ideal situation would be a format I could use unchanged regardless
of whether the exponent (-37) is positive or negative.

Unless there is one, it would seem I might have to do this in a generic setting,
given 3 integers $mantis, $radix, $exp but $radix is always >= 2:

$exp < 0 ?? FatRat.new( $mantis, $radix**$exp ) !! $mantis * $radix**$exp

What I think might be ideal though is if the FatRat.new() could be a multi that
also has a 3-param variant, so that something like this would work:

FatRat.new( $mantissa, $radix, $exponent )

I would be clear that this 3-param variant would be 3 integers, including the
mantissa, because that guarantees that the new FatRat would be an exact multiple
of $radix**$exponent.

-- Darren Duncan

0 new messages