[E-Lang] Operators #6: Multiplicative operators

Mark S. Miller markm@caplet.com
Sat, 07 Apr 2001 11:57:16 -0700


--=====================_166953944==_.ALT
Content-Type: text/plain; charset="us-ascii"

There are some outstanding controversies about scalar arithmetic, 
specifically divide and modulo.  However, since none of these controversies 
affect the Hydro issues, I simply take E's current scalar arithmetic and 
propose how to transform it so it best fits Python's naming.


    x * y       ->  x op__mul(y)
    x _/ y      ->  x op__floorDiv(y)
    x / y       ->  x op__approxDiv(y)
    x % y       ->  x op__remainder(y)
    x %% y      ->  x op__mod(y)

    x ** y      ->  x op__pow(y)
    x ** y %% z ->  x op__pow(y, z)


Multiplication


There are two general ways to understand multiplication.  When x and y are 
both of type T, then T should have both a zero element (t0) and a one 
element (t1).  Multiplication should have the same kind of closure property 
over T as described by addition, but the identity element is t1 rather than t0:

    x * t1 -> x
    t1 * x -> x

Also, the zero elements should have the familiar property whose name I don't 
remember:

    x * t0 -> t0
    t0 * x -> t0

The other way of understanding multiplication is as repeated addition, when 
there's an integer on the right:

    x * i  ->  x + x + x + ... (i times).

The only case where these two interpretation could conflict of course is on 
integers, and here, of course, they are compatible.


Division, Remainder, and Modulo


Ideally divide is defined in terms of multiply:  
x * y -> z  implies  z / x -> y  and z / y -> x.  
However, ideal divide is not closed over integers, so we introduce two 
approximations:

x _/ y, when x and y are either integers of float64s, evaluates to the 
integer resulting from rounding the quotient towards negative infinity.  
Ie, the largest integer <= the correct quotient.

x / y, when x and y are either integers or float64s, evaluates to the 
floating point number that's the appropriate approximation to the real 
quotient by the IEEE round-to-even rule (the rounding rule governing all 
floating point arithmetic in Java and E.)  When x and y are float64s, "/" 
has the same meaning in E as in Java.

Java's integer divide rounding towards zero, which is really stupid, but can 
be expressed in E as an explicit message:

    x truncDivide(y)

Where there are approximations to divide, there are remainders from this 
approximation.  "%%" is the remainder from "_/", and is therefore a true 
modulo.  "%" is the remainder from truncDivide, and has the same meaning as 
Java's "%".


Exponentiation


x ** y is exponentiation.  x ** y %% z is modular exponentiation.


Datatype specific meanings


Of the core datatypes, all the multiplicative operators are defined only on 
integer and float64, with one possible exception.  Since we did define "+" 
on Strings, we may continue to define

    str * i -> str + str + ... (i repetitions of str)

But probably not.


        Cheers,
        --MarkM

--=====================_166953944==_.ALT
Content-Type: text/html; charset="us-ascii"

There are some outstanding controversies about scalar arithmetic, 
specifically divide and modulo.  However, since none of these controversies
affect the Hydro issues, I simply take E's current scalar arithmetic and
propose how to transform it so it best fits Python's naming.


    x * y       ->  x op__mul(y)
    x _/ y      ->  x op__floorDiv(y)
    x / y       ->  x op__approxDiv(y)
    x % y       ->  x op__remainder(y)
    x %% y      ->  x op__mod(y)

    x ** y      ->  x op__pow(y)
    x ** y %% z ->  x op__pow(y, z)


Multiplication


There are two general ways to understand multiplication.  When x and y are
both of type T, then T should have both a zero element (t0) and a one
element (t1).  Multiplication should have the same kind of closure property
over T as described by addition, but the identity element is t1 rather than t0:

    x * t1 -> x
    t1 * x -> x

Also, the zero elements should have the familiar property whose name I don't
remember:

    x * t0 -> t0
    t0 * x -> t0

The other way of understanding multiplication is as repeated addition, when
there's an integer on the right:

    x * i  ->  x + x + x + ... (i times).

The only case where these two interpretation could conflict of course is on
integers, and here, of course, they are compatible.


Division, Remainder, and Modulo


Ideally divide is defined in terms of multiply: 
x * y -> z  implies  z / x -> y  and z / y -> x. 
However, ideal divide is not closed over integers, so we introduce two
approximations:

x _/ y, when x and y are either integers of float64s, evaluates to the
integer resulting from rounding the quotient towards negative infinity. 
Ie, the largest integer <= the correct quotient.

x / y, when x and y are either integers or float64s, evaluates to the
floating point number that's the appropriate approximation to the real
quotient by the IEEE round-to-even rule (the rounding rule governing all
floating point arithmetic in Java and E.)  When x and y are float64s, "/"
has the same meaning in E as in Java.

Java's integer divide rounding towards zero, which is really stupid, but can
be expressed in E as an explicit message:

    x truncDivide(y)

Where there are approximations to divide, there are remainders from this
approximation.  "%%" is the remainder from "_/", and is therefore a true
modulo.  "%" is the remainder from truncDivide, and has the same meaning as
Java's "%".


Exponentiation


x ** y is exponentiation.  x ** y %% z is modular exponentiation.


Datatype specific meanings


Of the core datatypes, all the multiplicative operators are defined only on
integer and float64, with one possible exception.  Since we did define "+"
on Strings, we may continue to define

    str * i -> str + str + ... (i repetitions of str)

But probably not.


        Cheers,
        --MarkM
--=====================_166953944==_.ALT--