More on semantics of opPow: return type

KennyTM~ kennytm at gmail.com
Mon Dec 7 12:39:36 PST 2009


On Dec 8, 09 03:03, Lars T. Kyllingstad wrote:
> Andrei Alexandrescu wrote:
>> Don wrote:
>>> As has been mentioned in previous posts, a ^^ b should be right
>>> associative and have a precedence between multiplication and unary
>>> operators. That much is clear.
>>>
>>>
>>> Operations involving integers are far less obvious (and are actually
>>> where a major benefit of an operator can come in).
>>>
>>> Using the normal promotion rules, 10^^2 is an integer. The range
>>> checking already present in D2 could be extended so that the compiler
>>> knows it'll even fit in a byte. This gets rid of one of the classic
>>> annoyances of C pow: int x = pow(2, 10); doesn't compile without a cast.
>>>
>>> But the difficult question is, what's the type of 10^^-2 ? Should it
>>> be an error? (since the result, 0.01, is not representable as an
>>> integer). Should it return zero? (just as 1/2 doesn't return 0.5).
>>> For an example of these semantics, see
>>> http://www.tcl.tk/cgi-bin/tct/tip/123.html).
>>> Or should it return a double?
>>> Or should 10^^2 also be a double, but implicitly castable to byte
>>> because of the range checking rules?
>>>
>>> I currently favour making it an error, so that the normal promotion
>>> rules apply. It seems reasonable to me to require a cast to floating
>>> point in there somewhere.
>>> This is analagous to the similar case f ^^ 0.1; where f is known to
>>> be negative. This gives a complex result, creating a run-time error
>>> (returns a NaN). But, there's no standard error and no NaNs for
>>> integer underflow.
>>>
>>> One could also make int ^^ uint defined (returning an int), but not
>>> int ^^ int. Again thanks to range checking, int ^^ uint ^^ uint would
>>> work, because although uint ^^ uint is an int, it's known to be
>>> positive, so would implicitly convert to int. But would making int ^^
>>> int illegal, make it too much of an annoying special case?
>>>
>>> I strongly suspect that x^^y, where x and y are integers, and the
>>> value of y is not known at compile time, is an extremely rare operation.
>>>
>>> Also, should int^^uint generate some kind of overflow error? Although
>>> other arithmeic integer operators don't, it's fantastically easy to
>>> hit an overflow with x^^y. Unless x is 1, y must be tiny (< 64 to
>>> avoid overflowing a ulong).
>>
>> Nice analysis. IMHO this should lead us to reconsider the necessity of
>> "^^" in the first place. It seems to be adding too little real value
>> compared to the complexity of defining it.
>>
>> Andrei
>
>
> It adds a lot of value to the ones that actually use it, even though you
> may not be one of them. Exponentiation is extremely common in numerics.
>
> Here are some statistics for you: A Google code search (see below) for
> FORTRAN code using the power operator **, which until recently didn't
> have a D equivalent, yields roughly 56100 results.
>
> A search for the FORTRAN equivalents of << yield 400 results for ILS()
> and 276 results for LSHIFT(). Yet, left shift apparently deserves a
> place in D.
>
>
> (I've used http://www.google.com/codesearch, with the following search
> strings for **, ILS and LSHIFT, respectively:
>
> [0-9a-zA-Z)]\*\*[0-9a-zA-Z(] lang:fortran
> ils\([0-9a-zA-Z] lang:fortran
> lshift\([0-9a-zA-Z] lang:fortran
>
> As statistics go, this is probably not a prime example, but it is at
> least an indication.)
>
> -Lars

Fortran? I don't think that's D's target audience yet.

And let's also compare with Python: A search of "lang:python 
[\w)]\s*\*\*\s*[\w(]" yields 10,700 results, and the first few actual 
use cases are:

  1: bufferSize = 2**2**2**2
  2: n,x = 89 >> 90 + 6 / 7 % x + z << 6 + 2 ** 8
  3: def cube(n):
       return n ** 3
  4: v1 = stdev(a)**2
     v2 = stdev(b)**2
  5: self.val = self.val ** 2
  6: self._readerLength = self._readerLength * (10**len(m.group(1))) + 
long(m.group(1))
  7: rtn.append((1 - (1 - rgb[index]) ** correction) ** (1 / correction))

I don't find any appeal for cases 1 to 5.

(Also compare with left-shift (lang:python [\w)]\s*<<\s*[\w(]), giving 
9,000 results.)



More information about the Digitalmars-d mailing list