Re: Smooth numeric upgrades?

2008-12-11 Thread TSa

HaloO,

Darren Duncan wrote:

Michael G Schwern wrote:

TSa (Thomas Sandlaß) wrote:

I want to stress this last point. We have the three types Int,
Rat and Num. What exactly is the purpose of Num? The IEEE formats
will be handled by num64 and the like. Is it just there for
holding properties? Or does it do some more advanced numeric
stuff?


Int, Rat [1] and Num are all human types. They work like
humans were taught numbers work in math class. They have no size
limits. They shouldn't lose accuracy. [2]

As soon as you imply that numbers have a size limit or lose
accuracy you are thinking like a computer. That's why num64 is
not a replacement for Num, conceptually nor is int64 a
replacement for Int. They have limits and lose accuracy.


All agreed.


I also agree. But I want to work out a bit more of the semantics
of Num. Int and Rat are easy insofar as there are arbitrary precision
implementations. This is not the case for irrational numbers. One
route here is to go into symbolic math. But this is at best the task
of add-on modules.

The concept I have in mind is the subtype chain Int : Rat : Num
with automatic upgrades and non-automatic downgrades. That is

my Int $i = 2/3;
my Rat $r = sqrt(2);

are conceptually failures and result in exceptions which can of course
be converted to warnings or automatic conversions by pragmas. I see
the Complex type as a parametric type that replicates the above subtype
chain as Complex[Int] : Complex[Rat] : Complex[Num]. This should be
the general scheme for other types that implement numeric operations.

The Num type is basically an arbitrary precision float as Duncan has
proposed together with an .irrational flag that marks it as non-Rat.
E.g. the Num implementation of sqrt might even flag sqrt(4) as non-Rat
and actually not even achieve 2 numerically. This can be remedied as
follows

   subset SqrInt of Int where { $_ == any(1..* »**» 2) }

   multi sub sqrt (SqrInt $i -- Int)
   {
  # calculate approximate result that will be almost an Int
  # cast is needed to avoid endless dispatch
  return round( sqrt( Num $i ) );
   }

   subset SqrRat of Rat where { .numerator ~~ SqrInt 
.denominator ~~ SqrInt }

   multi sub sqrt (SqrRat $r -- Rat)
   {
  # dispatches to sqrt:(SqrInt -- Int)
  return round( sqrt( $r.numerator ) ) /
 round( sqrt( $r.denominator ) );
   }

The latter implementation has the drawback that it needs to produce
two possibly large Ints as intermediate results. So we could instead
call the approximate sqrt with $r directly with appropriately set
precision demands.

The specced behavior of / for two Ints falls out naturally because it
returns a Num that simply doesn't happen to have the non-Rat flag set
and as such is assignable to a variable with a Rat constraint. It's
also easy to get typesafe assignments of Rats with .denominator == 1
to Int variables. That is we have the conceptual subsets

  subset Rat of Num where { !.irrational }

  subset Int of Rat where { .denominator == 1 }

Functions like sin are not required to flag sin(pi/6) == 1/2
as rational. They might not even achieve the numeric equality
unless some additional definitions are made for the equality
of Nums with some epsilon.



[2] Num should have an optional limit on the number of decimal places
it remembers, like NUMERIC in SQL, but that's a simple truncation.


I disagree.


I disagree as well. But Num should provide an interface to access the
underlying approximations made by functions that operate on Nums. The
default will be a relative error i.e. a ratio between the difference
to the exact value and the exact value---note that this error itself is
approximate. This means that the absolute error can be quite large for
large numbers. This estimation strategy allows an implementation of Num
on top of Rat.

For starters, any limit built into a type definition should be defined 
not as stated above but rather with a simple subtype declaration, eg 
subtype of Rat where ... that tests for example that the Rat is an 
exact multiple of 1/1000.


The interesting thing that occurred to me is that constraints on
variables are known at compile time. If we define that the point
in a computation where the rounding takes place is the moment when
it comes to storing a value in a variable then the parser can
propagate the accuracy of the constraint to all functions called
in the expression tree. This means we need a definition language
how the Num type performs its approximations. This is then used
in the where clause of subset declarations of Num.

This means that we have an extensible set of operators and functions
that do numerics. All these functions have an approximation interface
that the compiler generates input for. If the programmer wishes she
can also use that interface directly, of course.

Second, any truncation should be done at the operator level not at the 
type level; for example, the rational division 

Re: Smooth numeric upgrades?

2008-10-20 Thread Tom Christiansen
On Mon, 06 Oct 2008 at wee small hour of 02:20:22 EDT 
you, Michael G Schwern [EMAIL PROTECTED], wrote:

 Darren Duncan wrote:

 [2] Num should have an optional limit on the number of
 decimal places it remembers, like NUMERIC in SQL, but
 that's a simple truncation.

 I disagree.

 Any numeric operations that would return an irrational number
 in the general case, such as sqrt() and sin(), and the user
 desires the result to be truncated to an exact rational number
 rather than as a symbolic number, then those operators should
 have an extra argument that specifies rounding, eg to an exact
 multiple of 1/1000.

 That seems like scattering a lot of redundant extra arguments
 around.  The nice thing about doing it as part of the type is
 you just specify it once.

 But instead of truncating data in the type, maybe what I want
 is to leave the full accuracy inside and instead override
 string/numification to display only 2 decimal places.

This is currently something of an annoyance with Math::Complex.
It needs a way of specify epsilon.

If you ask for both sqrt()s of 4, you get

(2, -2+2.44929359829471e-16i)

in Cartesian but in Polar:

( [2,0], [2,pi] )

Is the problem that it's working in Polar and the conversion to
Cartesian is off by a wee bit?  I would really like to get
Cartesian answers of (2, -2), not that -2e-16i silliness.

If you ask for both roots of -4, you get

Cartesian:
( 1.22464679914735e-16+2i, -3.67394039744206e-16-2i )
Polar:
( [2,pi/2], [2,-1pi/2] );

But I'd like a Cartesian return of (2i, -2i).  
And a Polar return of ([2,pi/2],[2,-pi/2]).

It's worse still with the 10 roots of 2**10:

The 10 roots of 1024 are:
CRTSN:  1: 2
POLAR:  1: [2,0]
CRTSN:  2: 1.61803398874989+1.17557050458495i
POLAR:  2: [2,pi/5]
CRTSN:  3: 0.618033988749895+1.90211303259031i
POLAR:  3: [2,2pi/5]
CRTSN:  4: -0.618033988749895+1.90211303259031i
POLAR:  4: [2,3pi/5]
CRTSN:  5: -1.61803398874989+1.17557050458495i
POLAR:  5: [2,4pi/5]
CRTSN:  6: -2+2.44929359829471e-16i
POLAR:  6: [2,pi]
CRTSN:  7: -1.61803398874989-1.17557050458495i
POLAR:  7: [2,-4pi/5]
CRTSN:  8: -0.618033988749895-1.90211303259031i
POLAR:  8: [2,-3pi/5]
CRTSN:  9: 0.618033988749894-1.90211303259031i
POLAR:  9: [2,-2pi/5]
CRTSN: 10: 1.61803398874989-1.17557050458495i
POLAR: 10: [2,-1pi/5]

The 10 roots of -1024 are:
CRTSN:  1: 1.90211303259031+0.618033988749895i
POLAR:  1: [2,0.314159265358979]
CRTSN:  2: 1.17557050458495+1.61803398874989i
POLAR:  2: [2,0.942477796076938]
CRTSN:  3: 1.22464679914735e-16+2i
POLAR:  3: [2,pi/2]
CRTSN:  4: -1.17557050458495+1.61803398874989i
POLAR:  4: [2,2.19911485751286]
CRTSN:  5: -1.90211303259031+0.618033988749895i
POLAR:  5: [2,2.82743338823081]
CRTSN:  6: -1.90211303259031-0.618033988749895i
POLAR:  6: [2,-2.82743338823081]
CRTSN:  7: -1.17557050458495-1.61803398874989i
POLAR:  7: [2,-2.19911485751286]
CRTSN:  8: -3.67394039744206e-16-2i
POLAR:  8: [2,-1pi/2]
CRTSN:  9: 1.17557050458495-1.6180339887499i
POLAR:  9: [2,-0.942477796076938]
CRTSN: 10: 1.90211303259031-0.618033988749895i
POLAR: 10: [2,-0.31415926535898]

 Note, a generic numeric rounding operator would also take the
 exact multiple of argument rather than a number of digits
 argument, except when that operator is simply rounding to an
 integer, in which case no such argument is applicable.

 Note, for extra determinism and flexibility, any operation
 rounding/truncating to a rational would also take an optional
 argument specifying the rounding method, eg so users can
 choose between the likes of half-up, to-even, to-zero, etc.
 Then Perl can easily copy any semantics a user desires,
 including when code is ported from other languages and wants
 to maintain exact semantics.

 Yes, this is very important for currency operations.

 Now, as I see it, if Num has any purpose apart from Rat,
 it would be like a whatever numeric type or effectively a
 union of the Int|Rat|that-symbolic-number-type|etc types, for
 people that just want to accept numbers from somewhere and
 don't care about the exact semantics.  The actual underlying
 type used in any given situation would determine the exact
 semantics.  So Int and Rat would be exact and unlimited
 precision, and maybe Symbolic or IRat or something would be
 the symbolic number type, also with exact precision
 components.

 That sounds right.  It's the whatever can conceivably be
 called a number type.

I think you might be surprised by what some people conceive 
of by numbers. :-(

--tom

#!/usr/bin/perl

use strict;
use warnings;

use Math::Complex;

my $STYLE = NORMAL;
# my $STYLE = HACKED;

unless (@ARGV) {
die usage: $0 number rootcount\n;
} 

my ($number, $rootcount) = @ARGV;

$number = cplx($number);  

die $0: $number poor for rooting\n if !$number;
die $0: $rootcount should be 

Re: Smooth numeric upgrades?

2008-10-06 Thread Michael G Schwern
So, the concrete use-case I'm thinking of here is currency.


Darren Duncan wrote:
 [2] Num should have an optional limit on the number of decimal places
 it remembers, like NUMERIC in SQL, but that's a simple truncation.
 
 I disagree.
 
 For starters, any limit built into a type definition should be defined
 not as stated above but rather with a simple subtype declaration, eg
 subtype of Rat where ... that tests for example that the Rat is an
 exact multiple of 1/1000.
 
 Second, any truncation should be done at the operator level not at the
 type level; for example, the rational division operator could have an
 optional extra argument that says the result must be rounded to be an
 exact multiple of 1/1000; without the extra argument, the division
 doesn't truncate anything.
 
 Any numeric operations that would return an irrational number in the
 general case, such as sqrt() and sin(), and the user desires the result
 to be truncated to an exact rational number rather than as a symbolic
 number, then those operators should have an extra argument that
 specifies rounding, eg to an exact multiple of 1/1000.

That seems like scattering a lot of redundant extra arguments around.  The
nice thing about doing it as part of the type is you just specify it once.

But instead of truncating data in the type, maybe what I want is to leave the
full accuracy inside and instead override string/numification to display only
2 decimal places.

But sometimes I want to hang onto fractional pennies and use them in
calculation, just hide them from view.  And sometimes I don't.


 Note, a generic numeric rounding operator would also take the exact
 multiple of argument rather than a number of digits argument, except
 when that operator is simply rounding to an integer, in which case no
 such argument is applicable.
 
 Note, for extra determinism and flexibility, any operation
 rounding/truncating to a rational would also take an optional argument
 specifying the rounding method, eg so users can choose between the likes
 of half-up, to-even, to-zero, etc.  Then Perl can easily copy any
 semantics a user desires, including when code is ported from other
 languages and wants to maintain exact semantics.

Yes, this is very important for currency operations.


 Now, as I see it, if Num has any purpose apart from Rat, it would be
 like a whatever numeric type or effectively a union of the
 Int|Rat|that-symbolic-number-type|etc types, for people that just want
 to accept numbers from somewhere and don't care about the exact
 semantics.  The actual underlying type used in any given situation would
 determine the exact semantics.  So Int and Rat would be exact and
 unlimited precision, and maybe Symbolic or IRat or something would be
 the symbolic number type, also with exact precision components.

That sounds right.  It's the whatever can conceivably be called a number type.



-- 
44. I am not the atheist chaplain.
-- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army
   http://skippyslist.com/list/


Re: Smooth numeric upgrades?

2008-10-05 Thread Darren Duncan

Darren Duncan wrote:

  4.5207196*10**30 - 45207196*10**37


Before anyone nitpicks, I meant to say on that line:

  4.5207196*10**44 - 45207196*10**37

-- Darren Duncan


Re: Smooth numeric upgrades?

2008-10-05 Thread Michael G Schwern
Darren Duncan wrote:
 Patrick R. Michaud wrote:
 Correct.  I suspect that eventually the Rakudo developers will have
 to develop a custom set of PMCs for Perl 6 behaviors rather than
 relying on the Parrot ones.
 
 I think it would be better for things like unlimited-precision integers
 and rationals to be Parrot generic PMCs rather than Perl 6 specific
 ones, since there are other languages that also have unlimited-precision
 numbers (for example Python afaik) and it would be better to have a
 common implementation.  Several popular languages have unlimiteds now,
 and more are coming over time.

+1

The basics of sane numbers should be pushed down into Parrot.
(Of course, my vote counts for bupkis as I'm not going to be the one to
implement it)


-- 
Whip me, beat me, make my code compatible with VMS!


Re: Smooth numeric upgrades?

2008-10-05 Thread TSa (Thomas Sandlaß)
HaloO,

On Sunday, 5. October 2008 04:23:42 Darren Duncan wrote:
 Note that just as integers are naturally radix independent, the unlimited
 rationals should be too, and the latter can compactly represent all
 rationals as a triple of integers corresponding roughly to a (normalized)
 [mantissa, radix, exponent] triple; with that approach you also get 
 unlimited floats for free, so no reason to make floats an exception where
 they aren't unlimited where integers and other rationals are; after all,
 what is a float or scientific notation than just another notation for a
 rational value literal.

I want to stress this last point. We have the three types Int, Rat and Num.
What exactly is the purpose of Num? The IEEE formats will be handled
by num64 and the like. Is it just there for holding properties? Or does
it do some more advanced numeric stuff?

Another matter is how to represent irrationals. With IEEE floats which are
basically non-uniformly spaced integers imprecession is involved anyway.
But sqrt(2) is a ratio of two infinite integers. How is that handled? Here
I see a way for Num to shine as a type that also involves lazy approximations.
But then we need a way for the programmer to specify how these approximations
shall be handled. 


Regards, TSa.
-- 
The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Smooth numeric upgrades?

2008-10-05 Thread Doug McNutt
On Sunday, 5. October 2008 04:23:42 Darren Duncan wrote:
 Note that just as integers are naturally radix independent, the unlimited
 rationals should be too, and the latter can compactly represent all
 rationals as a triple of integers corresponding roughly to a (normalized)
 [mantissa, radix, exponent] triple; with that approach you also get 
 unlimited floats for free, so no reason to make floats an exception where
 they aren't unlimited where integers and other rationals are; after all,
 what is a float or scientific notation than just another notation for a
 rational value literal.

At 18:06 +0200 10/5/08, TSa (Thomas Sandlaß) wrote:
I want to stress this last point. We have the three types Int, Rat and Num.
What exactly is the purpose of Num? The IEEE formats will be handled
by num64 and the like. Is it just there for holding properties? Or does
it do some more advanced numeric stuff?

Another matter is how to represent irrationals. With IEEE floats which are
basically non-uniformly spaced integers imprecession is involved anyway.
But sqrt(2) is a ratio of two infinite integers. How is that handled? Here
I see a way for Num to shine as a type that also involves lazy approximations.
But then we need a way for the programmer to specify how these approximations
shall be handled. 

I'm not so sure that sophisticated numbering is necessary for a practical 
extraction and report language. But. . .

Symbolic algebra packages handle irrationals like sqrt(2) with a root of 
function which can be included in a result before it is deliberately converted 
to an approximation in a later step. Perl should NOT do things like that.

As for unlimited precision in floats I'd rather see a floating point number 
triple that includes, in its structure, an estimate of error, and physical 
units.

Multiplying amperes by volts would then return watts with an appropriately 
calculated estimate of the error. Testing for zero would include the error 
estimate.

When I work with data from the power company expressed in MMBTU I can add to a 
working table of units that MMBTU translates to 10^6 BTU because the M means 
1000 as in millia pasuum. I could also provide a conversion from BTU to joules 
and have it properly handled.

Many arithmetic errors are the result of not keeping the units inside of the 
evaluation. The result is newspaper articles that confuse energy and power as 
they extract from data provided by power company engineers. 1 kW per day is 
meaningless. I wonder if they use perl to extract the data.

And what are those two infinite integers? I wonder if there is a series that 
expresses each one?

-- 

-- A fair tax is one that you pay but I don't --


Re: Smooth numeric upgrades?

2008-10-05 Thread Michael G Schwern
TSa (Thomas Sandlaß) wrote:
 I want to stress this last point. We have the three types Int, Rat and Num.
 What exactly is the purpose of Num? The IEEE formats will be handled
 by num64 and the like. Is it just there for holding properties? Or does
 it do some more advanced numeric stuff?

Int, Rat [1] and Num are all human types.  They work like humans were
taught numbers work in math class.  They have no size limits.  They shouldn't
lose accuracy. [2]

As soon as you imply that numbers have a size limit or lose accuracy you are
thinking like a computer.  That's why num64 is not a replacement for Num,
conceptually nor is int64 a replacement for Int.  They have limits and
lose accuracy.

Making Num just work like humans expect is the more advanced numeric stuff
I suppose. :)


[1] As a name Rat as the type which holds fractions is about as good
as Float to be the type which holds decimal numbers.  Gotta be
something that makes more sense to non CS people.  Like, say, Fraction.

[2] Num should have an optional limit on the number of decimal places
it remembers, like NUMERIC in SQL, but that's a simple truncation.


-- 
184. When operating a military vehicle I may *not* attempt something
 I saw in a cartoon.
-- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army
   http://skippyslist.com/list/


Re: Smooth numeric upgrades?

2008-10-05 Thread Nicholas Clark
On Sat, Oct 04, 2008 at 09:37:29PM -0700, Mark Biggar wrote:

 trivial and vice versa. But promotion (or demotion) between IEEE floats 
 and rationals is really hard and I don't know of a language that even 
 tries.  The major problem is that the demotion from rational to IEEE 
 float is very lossy.  In general, there are many possible distinct 
 rationals that convert into the same IEEE value and converting  IEEE 
 float to the simplest rational out of that set is a very expensive 
 operation..  Once you're in rationals you probably never want to demote 

And I can't see why it's anything other than a heuristic. For example,
0.2 is an infinite binary fraction. So store that as an IEEE float (heck,
in any form of float with a binary mantissa of fixed precision) and 1/5 isn't
the *only* rational that could have got you there. Something like

0b00011001100110011001100110011001100110011001100110011 /
0b1

(900719925474099 / 4503599627370496)

would also result in the same bit pattern in the mantissa.

How does the implementation tell which rational the floating point value
actually came from

 back to IEEE (except possibly at the very end).  Every language that 
 supports rationals, that I know of, leaves it up to the programmer to 
 decide whether they will be doing computations in IEEE float or 
 rationals and do not try to automatically convert back and forth.  I 
 looked at thos and basically gave up when I was writing the perl 5 
 Bigint and Bigrat packages.
 
 Before you discuss implementations, you should define exactly what rules 
 you are going to use for promotion and demotion between the various types.

Studiously ignoring that request to nail down promotion and demotion, I'm
going to jump straight to implementation, and ask:

If one has floating point in the mix [and however much one uses rationals,
and has the parser store all decimal string constants as rationals, floating
point enters the mix as soon as someone wants to use transcendental functions
such as sin(), exp() or sqrt()], I can't see how any implementation that wants
to preserve infinite precision for as long as possible is going to work,
apart from

storing every value as a thunk that holds the sequence of operations that
were used to compute the value, and defer calculation for as long as
possible. (And possibly as a sop to efficiency, cache the floating point
outcome of evaluating the thunk if it gets called)


Nicholas Clark


Re: Smooth numeric upgrades?

2008-10-05 Thread Tom Christiansen
In-Reply-To: Message from Nicholas Clark [EMAIL PROTECTED] 
   of Sun, 05 Oct 2008 22:13:14 BST. [EMAIL PROTECTED] 

 Studiously ignoring that request to nail down promotion and demotion, I'm
 going to jump straight to implementation, and ask:

 If one has floating point in the mix [and however much one uses rationals,
 and has the parser store all decimal string constants as rationals, floating
 point enters the mix as soon as someone wants to use transcendental functions
 such as sin(), exp() or sqrt()], I can't see how any implementation that wants
 to preserve infinite precision for as long as possible is going to work,
 apart from
 
storing every value as a thunk that holds the sequence of operations that
were used to compute the value, and defer calculation for as long as
possible. (And possibly as a sop to efficiency, cache the floating point
outcome of evaluating the thunk if it gets called)

Nicholas Clark

My dear Nicholas, 

You mentioned sin(), exp(), and sqrt() as being transcendental functions,
but this is not true!  Perhaps you meant something more in the way of their
being--um, irrational.  but far be it from me to risk using so loaded a
word in reference to anyone's hypothetical intentions or rationale! :-)

While all transcendentals are indeed irrationals, the opposite relationship
does *not* apply.  It's all really rather simple, provided you look at it 
as a brief, binary decision-tree.

= All reals are also one of either rational or irrational:

 +  Rational numbers are those expressible as the RATIO of I/J, 
where I is any integer and J any non-zero integer. 

 -  Irrationals are all other reals *EXCEPT* the rationals.

= All irrationals are also one of either algebraic or transcendental:

 +  Algebraic numbers are solutions to polynomial equations of a single 
variable and integer coefficients.  When you solve for x in the 
polynomial equation 3*x**2 - 15 == 0, you get an algebraic number.

 -  Transcendentals are all other irrationals *EXCEPT* the algebraics.

Thinking of the sine function and its inverse, I notice that
sin(pi/2) == 1 and asin(1) is pi/2.  Pi is *the* most famous 
of transcendental numbers, and sin() is a transcendental function.

Thinking of the exponential function and its inverse, I notice that
exp(1) == e and log(e) == 1.  And e, Euler's number, is likely the 
#2 most famous transcendental, and exp() is a transcendental function.

However, we come now to a problem.  

If you solved the simple equation I presented above as one whose solution
was by definition *not* a transcendental but rather an algebraic number,
you may have noticed that solution is 5**(1/2), better known as sqrt(5).
So that makes sqrt(5) an algebraic number, and sqrt() is an algebraic
function, which means therefore that it is *not* a transcendental one.

Q.E.D. :-)

Ok, I was teasing a little.  But I'd now like to politely and sincerely
inquire into your assertion that floating point need inevitably enter the
picture just to determine sin(x), exp(x), or sqrt(x).

Your last one, sqrt(), isn't hard at all.  Though I no longer recall the
algorithm, there exists one for solving square roots by hand that is only a
little more complicated than that of solving long division by hand.  Like
division, it is an iterative process, somewhat tedious but quite well-defined
easily implemented even on pen and paper.  Perhaps that has something to do
with sqrt() being an algebraic function. :-) j/k

As for the two transcendental functions, this does ask for more work.  But
it's not as though we do not understand them, nor how to derive them at
need from first principles!  They aren't magic black-ball functions with
secret look-up tables that when poked with a given input, return some
arbitrary answer.

We *know* how to *do* these!  

Sure, many and probably most solutions, at least for the transendentals, do
involve power series, and usually Taylor Series.  But this only means that
you get to joyfully sum up an infinite sequence of figures receding into
infinity (And beyond! quoth Buzz), but where each figure in said series 
tends to be a reasonably simple and straightforward computation.

For example, each term in the Taylor Series for exp(x) is simply x**N / N!,
and the final answer the sum of all suchterms for N going from 0 to infinity.  
Its series is therefore 

 x**0 / 0! # er: that's just 1, of course :-)
  +  x**1 / 1! 
  +  x**2 / 2! 
  +  x**3 / 3! 
  +  x**4 / 4! 
  + 
  + + + + + + + + + + ad infinitum.

For sin(x), it's a bit harder, but not much: the series is a convergent one
of alternating sign, running N from 0 to infinity and producing a series 
that looks like this:

 (x**1 / 1!)# er: that's just x, of course :-)
   - (x**3 / 3!) 
   + (x**5 / 5!) 
   - (x**7 / 7!) 
   + (x**9 / 9!) 
   -
   + - + - + - + - + ad infinitum.

Each term in the sin(x) series is still a comparitively easy one, 
reading much better on paper than on the computer with 

Re: Smooth numeric upgrades?

2008-10-05 Thread Darren Duncan

Michael G Schwern wrote:

TSa (Thomas Sandlaß) wrote:

I want to stress this last point. We have the three types Int, Rat and Num.
What exactly is the purpose of Num? The IEEE formats will be handled
by num64 and the like. Is it just there for holding properties? Or does
it do some more advanced numeric stuff?


Int, Rat [1] and Num are all human types.  They work like humans were
taught numbers work in math class.  They have no size limits.  They shouldn't
lose accuracy. [2]

As soon as you imply that numbers have a size limit or lose accuracy you are
thinking like a computer.  That's why num64 is not a replacement for Num,
conceptually nor is int64 a replacement for Int.  They have limits and
lose accuracy.


All agreed.


[2] Num should have an optional limit on the number of decimal places
it remembers, like NUMERIC in SQL, but that's a simple truncation.


I disagree.

For starters, any limit built into a type definition should be defined not as 
stated above but rather with a simple subtype declaration, eg subtype of Rat 
where ... that tests for example that the Rat is an exact multiple of 1/1000.


Second, any truncation should be done at the operator level not at the type 
level; for example, the rational division operator could have an optional extra 
argument that says the result must be rounded to be an exact multiple of 1/1000; 
without the extra argument, the division doesn't truncate anything.


Any numeric operations that would return an irrational number in the general 
case, such as sqrt() and sin(), and the user desires the result to be truncated 
to an exact rational number rather than as a symbolic number, then those 
operators should have an extra argument that specifies rounding, eg to an exact 
multiple of 1/1000.


Note, a generic numeric rounding operator would also take the exact multiple 
of argument rather than a number of digits argument, except when that 
operator is simply rounding to an integer, in which case no such argument is 
applicable.


Note, for extra determinism and flexibility, any operation rounding/truncating 
to a rational would also take an optional argument specifying the rounding 
method, eg so users can choose between the likes of half-up, to-even, to-zero, 
etc.  Then Perl can easily copy any semantics a user desires, including when 
code is ported from other languages and wants to maintain exact semantics.


Now, as I see it, if Num has any purpose apart from Rat, it would be like a 
whatever numeric type or effectively a union of the 
Int|Rat|that-symbolic-number-type|etc types, for people that just want to accept 
numbers from somewhere and don't care about the exact semantics.  The actual 
underlying type used in any given situation would determine the exact semantics. 
 So Int and Rat would be exact and unlimited precision, and maybe Symbolic or 
IRat or something would be the symbolic number type, also with exact precision 
components.


Come to think of it, isn't whatever how Num is already defined?  If so I think 
that is clearly distinct from Rat.


-- Darren Duncan



Re: Smooth numeric upgrades?

2008-10-05 Thread Darren Duncan

Nicholas Clark wrote:

If one has floating point in the mix [and however much one uses rationals,
and has the parser store all decimal string constants as rationals, floating
point enters the mix as soon as someone wants to use transcendental functions
such as sin(), exp() or sqrt()], I can't see how any implementation that wants
to preserve infinite precision for as long as possible is going to work,
apart from

storing every value as a thunk that holds the sequence of operations that
were used to compute the value, and defer calculation for as long as
possible. (And possibly as a sop to efficiency, cache the floating point
outcome of evaluating the thunk if it gets called)


Floating point has no effect on this.  A float is just a syntax for an exact 
rational.  What you're talking about mostly is how an exact irrational would be 
represented, symbolically.  The result of an exact numeric sin() etc would be a 
symbolic number, and it is only when you separately explicitly convert it to a 
rational does any rounding and loss occur, and it would be the rounding 
operation itself that has extra parameters to control the rounding. 
Alternately, an inexact numeric sin() that results in an exact rational is just 
a wrapper over the last 2 operations combined, and it takes rounding-control 
parameters.  I see no problem here. -- Darren Duncan


Re: Smooth numeric upgrades?

2008-10-04 Thread Michael G Schwern
Larry Wall wrote:
 On Fri, Oct 03, 2008 at 11:57:30PM -0400, Michael G Schwern wrote:
 : What's the status of numeric upgrades in Perl 6?  Is see the docs say Perl 
 6
 : intrinsically supports big integers and rationals through its system of type
 : declarations. Int automatically supports promotion to arbitrary precision 
 but
 : it looks like it's doing the same thing as Perl 5.
 : 
 : $ ./perl6 -e 'say 2**40'
 : 1099511627776
 : 
 : $ ./perl6 -e 'say 2**50'
 : 1.12589990684262e+15
 : 
 : $ ./perl6 -e 'say 2**1100'
 : inf
 
 The status of numeric upgrades in Perl 6 is fine.  It's rakudo that
 doesn't do so well.  :)

 As another datapoint:
 
 $  pugs -e 'say 2**40'
 1099511627776
 $ pugs -e 'say 2**50'
 1125899906842624
 $ pugs -e 'say 2**1100'
 13582985290493858492773514283592667786034938469317445497485196697278130927542418487205392083207560592298578262953847383475038725543234929971155548342800628721885763499406390331782864144164680730766837160526223176512798435772129956553355286032203080380775759732320198985094884004069116123084147875437183658467465148948790552744165376

That's good [1] to hear, thanks.


 I don't think of Int as a type that automatically upgrades.  I think
 of it as an arbritrarily large integer that the implementation can in
 some cases choose to optimize to a smaller or faster representation,

Oh don't worry, I do.  I just got so flustered when I saw Rakudo do the same
thing that Perl 5 does I was worried this got lost somewhere along the line.


[1] We need a polite way to say less bad.


-- 
The mind is a terrible thing,
and it must be stopped.


Re: Smooth numeric upgrades?

2008-10-04 Thread Tom Christiansen
In-Reply-To: Message from Michael G Schwern [EMAIL PROTECTED]
   of Sat, 04 Oct 2008 02:06:18 EDT. [EMAIL PROTECTED]

 Larry Wall wrote:
 The status of numeric upgrades in Perl 6 is fine.  It's rakudo that
 doesn't do so well.  :)

 As another datapoint:

 $  pugs -e 'say 2**40'
 1099511627776
 $ pugs -e 'say 2**50'
 1125899906842624
 $ pugs -e 'say 2**1100'
 1358298529049385849277351428359266778603493846931744549748519669727813SNIP

 That's good [1] to hear, thanks.

 I don't think of Int as a type that automatically upgrades.  I think
 of it as an arbitrarily large integer that the implementation can in
 some cases choose to optimize to a smaller or faster representation,

 Oh don't worry, I do.  I just got so flustered when I saw Rakudo do the
 same thing that Perl 5 does I was worried this got lost somewhere along
 the line.

 [1] We need a polite way to say less bad.

!
ah
fab
yay
good
cool
ayup
d'oh!
helps
tasty
yummy
smooth
cheers
better
yippee!
soothes
pleases
niftier
relieves
mediates
inspires
mollifies
mitigates
clarifies
my mistake
oh, right!
great!
delightful
not to worry
oh be joyful!
'tain't so bad
calms my qualms
less sub-optimal
cheers my spirit
soothes my nerves
dispells my doubts
heartens my resolve
cushions the cudgel
dismisses my dismay
drives out the dread
comforts me to learn
inspires me with hope
restores my confidence
gladdens my good humor
brightens my rainy day
alleviates my concerns
mollifies my misgivings
alleviates my confusion
puts down the false alarm
perks/plucks up my courage
pacifies my preoccupations
banishes my paranoia-demons
felicitates my facilitation
facilitates my felicitation
assuages my misapprehensions
shows I was worrying too much
encourages me; is encouraging
warms the cockles of my heart
offers hope for a better world
trounces my tetchy trepidations
dispells my misplaced anxieties
sure puts a spiffier shine on it 
makes molehills out of mountains
eases up on my nerves a fair bit
not nearly so gnarly as I'd feared
'tis not too late to seek a newer world
way better than I'd half-begun to suspect
patches the potholes in my crumbling wetware
softens the imagined blow that wasn't even there to start with
serenades such sweet sonnets as to nullify nervous nellies' natterings


Re: Smooth numeric upgrades?

2008-10-04 Thread Patrick R. Michaud
On Fri, Oct 03, 2008 at 09:47:38PM -0700, Larry Wall wrote:
 On Fri, Oct 03, 2008 at 11:57:30PM -0400, Michael G Schwern wrote:
 : What's the status of numeric upgrades in Perl 6?  Is see the 
 : docs say Perl 6 intrinsically supports big integers and rationals 
 : through its system of type declarations. Int automatically 
 : supports promotion to arbitrary precision but it looks like it's 
 : doing the same thing as Perl 5.
 
 The status of numeric upgrades in Perl 6 is fine.  It's rakudo that
 doesn't do so well.  :)

Correct.  I suspect that eventually the Rakudo developers will have
to develop a custom set of PMCs for Perl 6 behaviors rather than
relying on the Parrot ones.

In the more general sense, it's sometimes useful to remember that
Parrot is a virtual machine that often takes a Perl 5 approach to
solving problems -- I suspect because in many cases the Perl 6
approach wasn't necessarily well defined at the time.  It's going
to take Rakudo a little time to layer or rebuild the correct 
semantics for its core object types, so in the meantime we see
bits of Parrot peeking out through the interfaces.

Pm


Re: Smooth numeric upgrades?

2008-10-04 Thread Bob Rogers
   From: Patrick R. Michaud [EMAIL PROTECTED]
   Date: Sat, 4 Oct 2008 09:41:22 -0500

   On Fri, Oct 03, 2008 at 09:47:38PM -0700, Larry Wall wrote:
On Fri, Oct 03, 2008 at 11:57:30PM -0400, Michael G Schwern wrote:
: What's the status of numeric upgrades in Perl 6?  Is see the 
: docs say Perl 6 intrinsically supports big integers and rationals 
: through its system of type declarations. Int automatically 
: supports promotion to arbitrary precision but it looks like it's 
: doing the same thing as Perl 5.

The status of numeric upgrades in Perl 6 is fine.  It's rakudo that
doesn't do so well.  :)

   Correct.  I suspect that eventually the Rakudo developers will have
   to develop a custom set of PMCs for Perl 6 behaviors rather than
   relying on the Parrot ones.

The Parrot behavior in this case may be closer than you think.  After
applying the patch below, I get the expected output from Rakudo:

[EMAIL PROTECTED] ./perl6 -e 'say 2**40'
1099511627776
[EMAIL PROTECTED] ./perl6 -e 'say 2**50'
1125899906842624
[EMAIL PROTECTED] ./perl6 -e 'say 2**1100'

13582985290493858492773514283592667786034938469317445497485196697278130927542418487205392083207560592298578262953847383475038725543234929971155548342800628721885763499406390331782864144164680730766837160526223176512798435772129956553355286032203080380775759732320198985094884004069116123084147875437183658467465148948790552744165376
[EMAIL PROTECTED] 

It does produces 300 spectest_regression failures, though, so I don't
claim the patch is right.

   Parrot doesn't currently downgrade BigInt PMCs to Integer when it
should, though.

-- Bob Rogers
   http://rgrjr.dyndns.org/

Make infix:** and infix:* DTRT for Int = BigInt promotion.  May
break other numeric behaviors.

Index: languages/perl6/src/builtins/op.pir
===
--- languages/perl6/src/builtins/op.pir (revision 31592)
+++ languages/perl6/src/builtins/op.pir (working copy)
@@ -59,21 +59,12 @@
 
 ## exponentiation
 .sub 'infix:**' :multi(_,_)
-.param num base
-.param num exp
-$N0 = pow base, exp
-.return ($N0)
+.param pmc base
+.param pmc exp
+$P0 = n_pow base, exp
+.return ($P0)
 .end
 
-
-.sub 'infix:**' :multi(Integer,Integer)
-.param num base
-.param num exp
-$N0 = pow base, exp
-.return '!upgrade_to_num_if_needed'($N0)
-.end
-
-
 ## symbolic unary
 .sub 'prefix:!' :multi(_)
 .param pmc a
@@ -140,21 +131,13 @@
 
 ## multiplicative
 .sub 'infix:*' :multi(_,_)
-.param num a
-.param num b
-$N0 = a * b
-.return ($N0)
+.param pmc a
+.param pmc b
+$P0 = n_mul a, b
+.return ($P0)
 .end
 
 
-.sub 'infix:*' :multi(Integer,Integer)
-.param num a
-.param num b
-$N0 = a * b
-.return '!upgrade_to_num_if_needed'($N0)
-.end
-
-
 .sub 'infix:/' :multi(_,_)
 .param num a
 .param num b


Re: Smooth numeric upgrades?

2008-10-04 Thread Bob Rogers
   From: Bob Rogers [EMAIL PROTECTED]
   Date: Sat, 4 Oct 2008 22:08:10 -0400

  From: Patrick R. Michaud [EMAIL PROTECTED]
  Date: Sat, 4 Oct 2008 18:15:57 -0500

  . . .

  All of the mechanisms I've been able to find in Parrot for 
  converting an arbitrary PMC to a number seem to result in 
  the code for infix:* that we have now.  I'm open for 
  suggestions to improve this, though.

  Pm

   Hmm.  My instinct would be to rely on MMD . . .

   This exposes an MMD bug (it runs forever) . . .

Wrong; Parrot was replacing my Integer with the FixedPMCArray.  (Grr.)
Here is an improvement:

.sub 'infix:*' :multi(Perl6Array,_)
.param pmc a
.param pmc b
$I0 = a
$P0 = new 'Integer'
$P0 = $I0
.return 'infix:*'($P0, b)
.end

.sub 'infix:*' :multi(_,Perl6Array)
.param pmc a
.param pmc b
$I0 = b
$P0 = new 'Integer'
$P0 = $I0
.return 'infix:*'(a, $P0)
.end

It works for some cases:

[EMAIL PROTECTED] ../../perl6 -e 'my @a = abc def ghi; say @a * 
483648;'
1450944
[EMAIL PROTECTED] ../../perl6 -e 'my @a = abc def ghi; say 483648 * 
@a;'
1450944
[EMAIL PROTECTED] ../../perl6 -e 'my @a = abc def ghi; say 483648 * 
483648 * @a;'
701746163712
[EMAIL PROTECTED] ../../perl6 -e 'my @a = abc def ghi; say 483648 * 
483648 * 483648 * @a;'
339398128586981376
[EMAIL PROTECTED]

But not others:

[EMAIL PROTECTED] ../../perl6 -e 'my @a = abc def ghi; say @a * 
2147483648;'
-6442450944
[EMAIL PROTECTED] ../../perl6 -e 'my @a = abc def ghi; say 
2147483648 * @a;'
get_bignum() not implemented in class 'Float'
current instr.: 'infix:*' pc 16030 (src/gen_builtins.pir:10014)
. . .

-- Bob


Smooth numeric upgrades?

2008-10-03 Thread Michael G Schwern
What's the status of numeric upgrades in Perl 6?  Is see the docs say Perl 6
intrinsically supports big integers and rationals through its system of type
declarations. Int automatically supports promotion to arbitrary precision but
it looks like it's doing the same thing as Perl 5.

$ ./perl6 -e 'say 2**40'
1099511627776

$ ./perl6 -e 'say 2**50'
1.12589990684262e+15

$ ./perl6 -e 'say 2**1100'
inf

And...

$ ./perl6 -e 'my Int $foo = 2**32;  say $foo'
Type check failed
current instr.: 'parrot;Perl6Object;infix:=' pc 60 (src/gen_builtins.pir:52)
called from Sub '_block11' pc 98 (EVAL_12:41)
called from Sub 'parrot;PCT::HLLCompiler;eval' pc 806
(src/PCT/HLLCompiler.pir:480)
called from Sub 'parrot;PCT::HLLCompiler;command_line' pc 1298
(src/PCT/HLLCompiler.pir:707)
called from Sub 'parrot;Perl6::Compiler;main' pc 17029 (perl6.pir:172)
perl6(4325) malloc: ***  Deallocation of a pointer not malloced: 0x4157170;
This could be a double free(), or free() called with the middle of an
allocated block; Try setting environment variable MallocHelp to see tools to
help debug
perl6(4325) malloc: ***  Deallocation of a pointer not malloced: 0xda71b; This
could be a double free(), or free() called with the middle of an allocated
block; Try setting environment variable MallocHelp to see tools to help debug
Bus error (core dumped)

though hopefully that's transient.


-- 
Clutter and overload are not an attribute of information,
 they are failures of design
-- Edward Tufte



Re: Smooth numeric upgrades?

2008-10-03 Thread Larry Wall
On Fri, Oct 03, 2008 at 11:57:30PM -0400, Michael G Schwern wrote:
: What's the status of numeric upgrades in Perl 6?  Is see the docs say Perl 6
: intrinsically supports big integers and rationals through its system of type
: declarations. Int automatically supports promotion to arbitrary precision but
: it looks like it's doing the same thing as Perl 5.
: 
: $ ./perl6 -e 'say 2**40'
: 1099511627776
: 
: $ ./perl6 -e 'say 2**50'
: 1.12589990684262e+15
: 
: $ ./perl6 -e 'say 2**1100'
: inf

The status of numeric upgrades in Perl 6 is fine.  It's rakudo that
doesn't do so well.  :)

As another datapoint:

$  pugs -e 'say 2**40'
1099511627776
$ pugs -e 'say 2**50'
1125899906842624
$ pugs -e 'say 2**1100'
13582985290493858492773514283592667786034938469317445497485196697278130927542418487205392083207560592298578262953847383475038725543234929971155548342800628721885763499406390331782864144164680730766837160526223176512798435772129956553355286032203080380775759732320198985094884004069116123084147875437183658467465148948790552744165376

I don't think of Int as a type that automatically upgrades.  I think
of it as an arbritrarily large integer that the implementation can in
some cases choose to optimize to a smaller or faster representation,
but only if that can be transparent to the user (apart from the size
and speed effects).  Certainly this should be the case for anything
declared Int.  A native int is another matter, but that's just
a storage constraint, and probably shouldn't influence intermediate
computations, which are done in Int.  So it shouldn't matter whether 2
and 1100 are stored in Int or int form; the result should be the same
(subject, perhaps to pragmatic control of temp types).

Larry