Re: Smooth numeric upgrades?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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