Semantics of ^^

Jason House jason.james.house at gmail.com
Wed Dec 9 05:26:44 PST 2009


oops, my message was supposed to be in reply to version 3 that included the rewrite rule for -1 ^^ y

Jason House Wrote:

> I think you have a bad corner case:
> 
> enum int ct = -1;
> immutable rt = -1;
> 
> ct ^^ ct // Error (compile time)
> rt ^^ ct // Error (compile time)
> rt ^^ rt // Error (run time)
> ct ^^ rt // Works??? (after rewrite)
> 
> Don Wrote:
> 
> > Based on everyone's comments, this is what I have come up with:
> > 
> > --------------------
> > x ^^ y is right associative, and has a precedence intermediate between 
> > multiplication and unary operators.
> > 
> > * The type of x ^^ y is the same as the type of x * y.
> > * If y == 0,  x ^^ y is 1.
> > * If both x and y are integers, and y > 0,  x^^y is equivalent to
> >     { auto u = x; foreach(i; 1..y) { u *= x; } return u; }
> > * If both x and y are integers, and y < 0, an integer divide error 
> > occurs, regardless of the value of x. This error is detected at compile 
> > time, if possible.
> > * If either x or y are floating-point, the result is pow(x, y).
> > --------------------
> > Rationale:
> > (1) Although the following special cases could be defined...
> >   * If x == 1,  x ^^ y is 1
> >   * If x == -1 and y is even, x^^y == 1
> >   * If x == -1 and y is odd, x^^y == -1
> > ... they are not sufficiently useful to justify the major increase in 
> > complexity which they introduce. In all other cases, a negative exponent 
> > indicates an error; it should be rewritten as (cast(real)x) ^^ y. Making 
> > these cases errors makes everything much simpler, and allows the 
> > compiler to use range propagation on the value of y to detect most 
> > exponentiation errors at compile time. (If those cases are legal, the 
> > compiler can't generate an error on x^^-2, because of the possibility 
> > that x might be 1 or -1).
> > Also note that making it an error leaves open the possibility of 
> > changing it to a non-error later, without breaking code; but going from 
> > non-error to error would be more difficult.
> > 
> > (2) USE OF THE INTEGER DIVIDE ERROR
> > Note that on x86 at least, a hardware "integer divide error", although 
> > commonly referred to as "division by zero", also occurs when the DIV 
> > instruction, which performs uint = ulong/uint, results in a value 
> > greater than uint.max. Raising a number to a negative power does involve 
> > a division, so it seems to me not unreasonable to use it for this case 
> > as well.
> > Note that 0 ^^ -1 is a division by zero.
> > This means that, just as you should check that y!=0 before performing 
> > x/y, you should check that y>=0 before performing x^^y.
> > 
> > (3) OVERFLOW
> > int ^^ int returns an int, not a long. Although a long would allow 
> > representation of larger numbers, even doubling the number of bits 
> > doesn't help much in avoiding overflow, because x^^y is exponential. 
> > Even a floating-point representation can easily overflow:
> > 5000^5000 easily overflows an 80-bit real.
> > So, it's preferable to retain the simplicity that typeof(x^^y) is 
> > typeof(x*y).
> > 
> 




More information about the Digitalmars-d mailing list