Marcus Downing wrote:
> (i'm about to launch into an unfounded ramble through ideas, which may
> not go anywhere useful. feel free to skip to that much more
> interesting email from your significant other)
To paraphrase Kirk's comment about Spock, "your unfounded ramble is
as good as another man's well-considered reply."
> Intervals do indeed sound cool. Tell me, is there any reason the same
> funkiness couldn't be applied to arrays?
>
> array1 = [3, 5, 7, 11, 13, 17, 23]
> array2 = 4 array1
Actually, multiplying a scalar by an array is quite a bit easier than
doing interval arithmetic. There's no reason I couldn't do that (other
than the fact that implicitly multiplying a named variable by a literal
array looks like a function call)
n [3,5,7]
So it'd just have to be written explicitly:
n * [3,5,7]
The main reason I haven't implemented that yet is that n could
contain an array, and I figured I should do all of n-dimensional matrix
multiplication at the same time. Which means researching the state of
the art so that my algorithms are reasonably efficient.
Here's a few reasons that intervals are more interesting (and harder.)
* The mathematical literature usually treats intervals as "a new type
of number" with its own rules, like complex numbers are a new type of
number. You can't just repeat an operator over and over like you can
with the elements of an array, or the parts of a complex number. It's a
completely different operation.
* When working with intervals, you need to re-order the boundaries so
that they are in proper order. That is, that the lower is smaller than
the upper. (Note that this issue occurs when, say, multiplying by a
negative scalar.)
* When done simplistically, multiplying 2 intervals could involve 8
multiplications (or 16, if you're trying to handle numeric bounds
rigorously.) Doing it smarter involves handling at least 9 different
cases, in which you can limit it to 2 multiplies for most operations.
* You have to make sure that all the values in between the interval
bounds are meaningful. For example:
1 / [-1,1]
is troublesome because at one point in that interval you're dividing
by zero. The interval becomes unbounded and weird.
* As a corollary of the above, how do you take the sine of the
interval [pi/4, 3pi/4]? At both of the endpoints, the value is
sqrt[2]/2, but in that interval, the value ranges up to 1. You have to
find the bounds of the Taylor series expansion of the sin[] function to
make this work. Sigh.
* Under the rules of interval arithmetic, addition and multiplication
are commutative, but no longer always distributive. This means order of
operations is important. For example,
[1,2] * (1-1) = 0
whereas
[1,2]*1 - [1,2]*1 = [-1,1] which is clearly not zero.
Nor is [1,2]-[1,2] equal to zero.
As a data point, Mathematica spells this
RealInterval[{1,2}]
but last I checked, Mathematica's transformation rules totally thrash
interval arithmetic 'cause they assume that the distributive property
always holds. I don't know if that's still the case. Sigh again. Math
is hard.
* I'm making interval boundaries rigorous. This is the biggie. That
means I have to control rounding direction for every mathematical
operation. To vastly over-simplify, when working with floating-point
numbers, I have to round the lower bound down, and the upper bound up so
that the interval's boundaries are guaranteed to include the actual value.
This literally involves changes to every single piece of math within
Frink. It'll be good, though. The rewrites will also allow me much
finer control over the number of digits of working precision and
rounding direction used in any calculation, so I can make
arbitrary-precision calculations that converge well.
And, as you know, Java chose to ignore huge chunks of the IEEE 754
floating-point math standard, so you *can't* control rounding direction
for floats or doubles, nor trap on divide-by-zero nor overflow nor
underflow nor imprecise values nor signaling NaN operations.
It reminds me of the classic Peanuts cartoon:
Charlie Brown: How can you play all of those complex pieces on your
piano when the black keys are just painted on?
Schroeder: You've gotta get the breaks!
> Alternatively, have you thought of pinching perl 6's hyper ops?
>
> array2 = 4 * ^array1
Something like that would be nice, but I've also considered doing it
more along the lispish lines:
array2 = map[multiply, 4, array1]
> In fact, when you start to introduce values which are vectors,
> matrices, complex numbers and so on, you suddenly have a huge variety
> of not-so-real numbers, any pair of which could be fed into any of the
> standard mathematical operators and expected to "just work". Maybe i'm
> being a little unfair - such a thing would be a bitch and a half to
> implement, whatever the syntax.
Well, I'm already partway there. All of Frink's trigonometric
functions are complex-aware, and Frink's operators do the right thing
with any combinations of numerical type (say, multiplying rationals by
complex, etc.) All functions can easily mark themselves as being able
to be applied to an array of values.
But when you add a completely new mathematical type that have their
own rules, (e.g. complex, intervals, rationals, matrices, quaternions,
octonions, etc.) you actually have to implement all of its operations,
and when doing so rigorously, the number of cases you have to implement
tends to square with the number of different numerical types you have.
For a lot of these numerical types, some of the operations are
meaningless. You can't take the sine of a matrix (as far as I know.)
> I don't like the idea of i[3, 5], any more than new Interval[3, 5].
> They both seem somehow ugly, and not just because it interferes with
> normal multiplication by i. The options that seem more pleasing to my
> eye are the ones like [3 something 5], only with a smaller and more
> visible character clump in between. Tell, what would frink currently
> make of the following?
>
> [3 .. 5]
I once tried to use .. for ranges, but unfortunately implied
multiplication causes problems with this and floating-point numbers.
Frink allows you to write "3." and ".5" for floating-point numbers, and
writing 3..5 could be considered a multiplication of these. I'm trying
hard not to make whitespace too significant (as opposed to just
separating tokens,) but if you forced people to enter the whitespace as
above, it would work.
I'd rather not make whitespace overly significant, or I start getting
some of the warts of Ruby like where:
"a +b" is parsed as (the function call) "a(+b)". Remove the space to the
left of "+" or add a space to the right of "+" and it will be parsed as
an addition.
http://www.rubycentral.com/faq/rubyfaq-6.html#ss6.5
Uggggh. This is precisely why I require brackets around function
arguments and lists. If you don't, some things give you ambiguities and
unexpected results. Anyone who has written Perl and elided parentheses
in strange function calls has gotten bitten by this at least once.
> [3 . 5]
That would almost work, but it seems too close to "object.variable"
and would cause confusion/ambiguity if the left-hand-side were a variable.
> [3 ~ 5]
I don't use tilde yet. In Java/C/Perl, it's used for bitwise
negation (which I don't like.) So it's free. A bit hard to type, and
more intended for approximation to my reading, but, it would indeed work.
> [3 -- 5]
Could be mistaken for 3-(-5), unless you require the whitespace.
> [3 _ 5]
Frink allows one to separate the digits of an integer with
underscores for readability (like Ada):
186_282
So this is sorta out, again unless you require the whitespace.
Double-underscore would be okay. I'd consider disallowing the
underscore in integers, but I also sorta like it. It's purely a visual
aid for the programmer, nothing more.
Yes, implicit multiplication forces more parts of the syntax than
you'd ever imagine. But since it's part of 400+ years of standard
mathematical notation, I've decided to grin and bear it, and I wouldn't
give it up. It makes me happy when you can cut-and-paste an equation
into Frink and it just works, units and constants and all.
> But it's probably wrong. Is there a good reason you want to use array
> brackets, not group brackets?
Well, I want to follow standard mathematical notation as closely as
possible. Square brackets are usually used to indicate a closed
interval. At some point, I might implement open and closed intervals
(indicating if the exact boundary could actually be part of the interval
or not.) It's honestly more of an academic point than a practical one,
but it would be nice to track.
> This actually seems like a perfect
> instance where what you're defining is a grouped calculation,
> producing one value rather than a list:
>
> x = (3 _ 5)
> y = (3 _ 4 _ 5)
>
> Returning to my thought earlier, it seems like group brackets might
> have other uses:
>
> complex = (3 + 4i)
> interval = (3 _ 5)
> interval2 = (3 _ 4 _ 5)
> vector = (3, 4)
> matrix = (3, 4; 5, 6)
>
> or somesuch. all of which may be pretty, but will very quickly become
> ambiguous.
These are a good idea, and possibly even good practice to use (some
languages force you to parenthesize complex numbers when you write
them.) However, these do very rapidly become ambiguous in ways you'd
never expect, which is usually found by the parser generator JavaCUP
throwing hundreds of shift/reduce conflicts in the strangest of places
when you try to compile.
> The slightly ugly thought occurs to me of using a keyword
> inside the brackets like this:
>
> complex = (3 + 4i) // this really is just calculated, not constructed
> interval = (interval 3, 5)
> interval2 = (interval 3, 4, 5)
> vector = (vector 3, 4)
> matrix = (matrix 3, 4; 5, 6)
>
> But i'm sure you'll reject that as being a corruption of the currently
> nice and pure group brackets.
Actually, I don't reject these. It'll probably require new reserved
words (which I try to do cautiously) but it may well be a workable
option. I may run some of these through the parser and see what
ambiguities pop up.) Having the reserved word "interval" means that you
couldn't write
interval = (interval 3, 5)
> Anyway. That lot wasn't really an answer. Do i win? Or do i just need
> to go get some sleep?
Sleep is always good, but these are some good options that I hadn't
considered. I'll take a deeper look at them.
P.S. Complex intervals are even more scary, and I haven't studied them
at all. Almost all of the literature confines itself to the real
numbers. One of the few things to address it is the most expensive book
ever written by man,
http://www.amazon.com/exec/obidos/tg/detail/-/3527401342
which is on my Amazon wishlist if some benefactor who sleeps on a bed
of gold wants to buy it for me.
"My bed's stuffed with hay."
--
Alan Eliasen | "It is not enough to do your best;
eliasen@... | you must know what to do and THEN
http://futureboy.homeip.net/ | do your best." -- W. Edwards Deming