    "Abstraction of [[numeric|Numeric]] types with a natural
     [[total order|Comparable]], including the built-in numeric
     types [[Integer]] and [[Float]].

     A `Number` has a well-defined [[magnitude]] together with a
     [[sign]] of type [[Integer]], defined for any instance `x`
     as follows:

     - if `x==0` then `x.sign==0` and `x.magnitude==0`,
     - if `x>0` then `x.sign==1` and `x.magnitude==x`, or
     - if `x<0` then `x.sign==-1` and `x.magnitude==-x`,

     where `0` is the additive identity of the numeric type.

     Not every value commonly considered to be a \"number\" is
     a `Number`. For example, complex numbers aren't `Number`s
     since they don't have a total order."
    see (`class Integer`, `class Float`)
    by ("Gavin")
    tagged("Numbers")
    shared interface Number<Other> of Other
            satisfies Numeric<Other> &
                      Comparable<Other>
            given Other satisfies Number<Other> {

        "The magnitude of this number, defined for any instance
         `x` as:

         - `-x` if `x<0`, or
         - `x` otherwise,

         where `0` is the additive identity. Hence:

         - `x.magnitude >= 0` for any `x`, and
         - `x.magnitude == 0` if and only if `x==0`."
        aliased("absolute")
        shared default Other magnitude
                => negative
                then negated
                else this of Other;

        "The sign of this number:

         - `1` if the number is [[positive]],
         - `-1` if it is [[negative]], or
         - `0` if it is the additive identity.

         Must satisfy:

             x.magnitude.timesInteger(x.sign) == x"
        shared default Integer sign
                => if (positive) then 1
              else if (negative) then -1
              else 0;

        "Determine if the number is strictly positive, that is,
         if `this>0`, where `0` is the additive identity."
        shared formal Boolean positive;

        "Determine if the number is strictly negative, that is,
         if `this<0`, where `0` is the additive identity."
        shared formal Boolean negative;

        "The fractional part of this number, after truncation of
         the integral part. For [[Integral]] numeric types, the
         fractional part is always zero."
        shared formal Other fractionalPart;

        "The integral value of the number after truncation of
         the fractional part. For [[Integral]] numeric types,
         the integral value of a number is the number itself."
        shared formal Other wholePart;

        "The result of multiplying this number by the given
         [[Integer]]."
        since("1.1.0")
        shared formal Other timesInteger(Integer integer);

        "The result of adding this number to the given
         [[Integer]]."
        since("1.1.0")
        shared formal Other plusInteger(Integer integer);

        "The result of raising this number to the given
         non-negative [[Integer]] power. For a negative power,
         the behavior is implementation-dependent."
        throws (`class AssertionError`,
                "if the exponent is a negative power and this is
                 an integral numeric type")
        since("1.1.0")
        shared formal Other powerOfInteger(Integer integer);

        "Compares this number with the given number, returning:

         - [[larger]], if the [[difference|minus]] `this-other`
           between the numbers is [[positive]],
         - [[smaller]], if the difference `this-other` between
           the numbers is [[negative]], or
         - [[equal]] otherwise."
        shared actual default Comparison compare(Other other)
                => let (diff = this - other)
                    if (diff.positive) then larger
               else if (diff.negative) then smaller
               else equal;

    }