    "An IEEE 754 64-bit [floating point number][]. A `Float` is
     capable of approximately representing numeric values
     between:

     - 2<sup>-1022</sup>, approximately
       1.79769\{#00D7}10<sup>308</sup>, and
     - (2-2<sup>-52</sup>)\{#00D7}2<sup>1023</sup>,
       approximately 5\{#00D7}10<sup>-324</sup>.

     Zero is represented by distinct instances `+0.0`, `-0.0`,
     but these instances are equal. `-0.0` can be distinguished
     from `+0.0` using `f == 0.0 && f.strictlyNegative`.

     In addition, the following special values exist:

     - [[infinity]] and `-infinity`, and
     - [[undefined values|undefined]], denoted [NaN][] by the
       IEEE standard.

     As required by the IEEE standard no undefined value is
     equal to any other value, nor even to itself. Thus, the
     definition of [[equals]] for `Float` violates the general
     contract defined by [[Object.equals]].

     A floating point value with a zero [[fractionalPart]] is
     considered equal to its [[integer]] part.

     Literal floating point values are written with a decimal
     point and, optionally, a magnitude or exponent:

         1.0
         1.0E6
         1.0M
         1.0E-6
         1.0u

     In the case of a fractional magnitude, the decimal point is
     optional. Underscores may be used to group digits into
     groups of three.

     [floating point number]: http://www.validlab.com/goldberg/paper.pdf
     [NaN]: http://en.wikipedia.org/wiki/NaN"
    tagged("Basic types", "Numbers")
    shared native final class Float
            extends Object
            satisfies Number<Float> &
                      Exponentiable<Float,Float> {

        "The sum of all the floating point values in the given
         stream, `0.0` if the stream is empty, or an
         [[undefined]] value if and only if the stream contains
         an undefined value.

         This expression produces the mean of a list of floating
         point values:

             Float.sum(list) / list.size"
        since("1.3.2")
        shared static Float sum({Float*} floats) {
            variable value sum = 0.0;
            for (float in floats) {
                sum += float;
            }
            return sum;
        }

        "The product of all the floating point values in the
         given stream, `1.0` if the stream is empty, or an
         [[undefined]] value if and only if the stream contains
         an undefined value.

         This expression produces the geometric mean of a list
         of floating point values:

             Float.product(list) ^ (1.0/list.size)"
        since("1.3.2")
        shared static Float product({Float*} floats) {
            variable value product = 1.0;
            for (float in floats) {
                product *= float;
            }
            return product;
        }

        "The largest floating point value in the given stream,
         `null` if the stream is empty, or an [[undefined]]
         value if and only if the stream contains an undefined
         value."
        since("1.3.2")
        shared static Float|Absent max<Absent>
                (Iterable<Float,Absent> floats)
                given Absent satisfies Null {
            variable value max = 0.0/0.0;
            for (x in floats) {
                if (x.undefined
                    || x==infinity) {
                    return x;
                }
                if (max.undefined
                    || x > max
                    || x.strictlyPositive
                    && max.strictlyNegative) {
                    max = x;
                }
            }
            if (max.undefined) {
                assert (is Absent null);
                return null;
            }
            else {
                return max;
            }
        }

        "The smallest floating point value in the given stream,
         `null` if the stream is empty, or an [[undefined]]
         value if and only if the stream contains an undefined
         value."
        since("1.3.2")
        shared static Float|Absent min<Absent>
                (Iterable<Float,Absent> floats)
                given Absent satisfies Null {
            variable value min = 0.0/0.0;
            for (x in floats) {
                if (x.undefined
                    || x==-infinity) {
                    return x;
                }
                if (min.undefined
                    || x < min
                    || x.strictlyNegative
                    && min.strictlyPositive) {
                    min = x;
                }
            }
            if (min.undefined) {
                assert (is Absent null);
                return null;
            }
            else {
                return min;
            }
        }

        "The smaller of the two given floating point values, or
         an [[undefined]] value if and only if one of the values
         is undefined."
        since("1.3.2")
        shared static Float smallest(Float x, Float y)
                => if (x.strictlyNegative && y.strictlyPositive)
                    then x
                else if (x.strictlyPositive && y.strictlyNegative)
                    then y
                else if (x.undefined)
                    then x
                else if (y.undefined)
                    then y
                else if (x<y) then x else y;

        "The larger of the two given floating point values, or
         an [[undefined]] value if and only if one of the values
         is undefined."
        since("1.3.2")
        shared static Float largest(Float x, Float y)
                => if (x.strictlyNegative && y.strictlyPositive)
                    then y
                else if (x.strictlyPositive && y.strictlyNegative)
                    then x
                else if (x.undefined)
                    then x
                else if (y.undefined)
                    then y
                else if (x>y) then x else y;

        "The [[Float]] value of the given
         [[string representation|string]] of a decimal floating
         point number, or `null` if the string does not
         represent a decimal floating point number.

         If the given string representation contains more digits
         than can be represented by a `Float`, then the least
         significant digits are ignored.

         The syntax accepted by this method is the same as the
         syntax for a `Float` literal in the Ceylon language
         except that it may optionally begin with a sign
         character (`+` or `-`) and may not contain grouping
         underscore characters. That is, an optional sign
         character, followed by a string of decimal digits,
         followed by an optional decimal point and string of
         decimal digits, followed by an optional decimal
         exponent, for example, `e+10` or `E-5`, or SI magnitude,
         `k`, `M`, `G`, `T`, `P`, `m`, `u`, `n`, `p`, or `f`.

         Float: Sign? Digits ('.' Digits)? (Magnitude|Exponent)
         Sign: '+' | '-'
         Magnitude: 'k' | 'M' | 'G' | 'T' | 'P' | 'm' | 'u' | 'n' | 'p' | 'f'
         Exponent: ('e'|'E') Sign? Digits
         Digits: ('0'..'9')+"
        see (`function format`, `function Integer.parse`)
        tagged("Numbers", "Basic types")
        since("1.3.1")
        shared static Float|ParseException parse(String string)
                => package.parseFloat(string)
                else ParseException("illegal format for Float");

        "The string decimal representation of the given
         [[floating point number|float]]. If the given number is
         [[negative|Float.negative]], the string representation
         will begin with `-`. The [[whole part|Float.wholePart]]
         and [[fractional parts|Float.fractionalPart]] of the
         number are separated by a `.` decimal point. Digits
         consist of decimal digits `0` to `9`.

         The number of decimal places following the decimal
         point is controlled by the parameters
         [[minDecimalPlaces]] and [[maxDecimalPlaces]], which
         default to `1` and `9` respectively, so that by default
         the string representation always contains a decimal
         point, and never contains more than nine decimal places.
         The decimal representation is rounded so that the
         number of decimal places never exceeds the specified
         maximum.

         For example:

         - `Float.format(1234.1234)` is `\"1234.1234\"`
         - `Float.format(0.1234)` is `\"0.1234\"`
         - `Float.format(1234.0)` is `\"1234.0\"`
         - `Float.format(1234.0,0)` is `\"1234\"`
         - `Float.format(1234.1234,6)` is `\"1234.123400\"`
         - `Float.format(1234.1234,0,2)` is `\"1234.12\"`
         - `Float.format(1234.123456,0,5)` is `\"1234.12346\"`
         - `Float.format(0.0001,2,2)` is `\"0.00\"`
         - `Float.format(0.0001,0,2)` is `\"0\"`

         Finally:

         - `Float.format(-0.0)` is `\"0.0\"`,
         - `Float.format(0.0/0)` is `\"NaN\"`,
         - `Float.format(1.0/0)` is `\"Infinity\"`, and
         - `Float.format(-1.0/0)` is `\"-Infinity\".`

         This function never produces a representation involving
         scientific notation."
        tagged("Numbers")
        see (`function parse`, `function Integer.format`)
        since("1.3.1")
        shared static String format(
            "The floating point value to format."
            Float float,
            "The minimum number of allowed decimal places.

             If `minDecimalPlaces<=0`, the result may have no
             decimal point."
            Integer minDecimalPlaces=1,
            "The maximum number of allowed decimal places.

             If `maxDecimalPlaces<=0`, the result always has no
             decimal point."
            Integer maxDecimalPlaces=9,
            "The character to use as the decimal separator.

             `decimalSeparator` may not be '-' or a digit as
             defined by the Unicode general category *Nd*."
            Character decimalSeparator = '.',
            "If not `null`, `thousandsSeparator` will be used to
             separate each group of three digits, starting
             immediately to the left of the decimal separator.

             `thousandsSeparator` may not be equal to the
             decimalSeparator and may not be '-' or a digit as
             defined by the Unicode general category *Nd*."
            Character? thousandsSeparator = null)
                => package.formatFloat(float,
                    minDecimalPlaces, maxDecimalPlaces,
                    decimalSeparator, thousandsSeparator);

        shared new(Float float) extends Object() {}

        "Determines whether this value is undefined. The IEEE
         standard denotes undefined values [NaN][] (an
         abbreviation of Not a Number). Undefined values include:

         - _indeterminate forms_ including `0.0/0.0`,
           `infinity/infinity`, `0.0*infinity`, and
           `infinity-infinity`, along with
         - _complex numbers_ like `sqrt(-1.0)` and `log(-1.0)`.

         An undefined value has the property that it is not
         [[equal|Object.equals]] (`==`) to itself, and as a
         consequence the undefined value cannot sensibly be used
         in most collections.

         If `x` is an undefined `Float`, then:

         - `x==x` evaluates to `false`
         - `x!=x` evaluates to `true`, and
         - `x>x`, `x<x`, `x>=x`, `x<=x` all evaluate to `false`.

         [NaN]: http://en.wikipedia.org/wiki/NaN"
        see (`function compare`)
        aliased("notANumber")
        shared Boolean undefined => this!=this;

        "Determines whether this value is infinite in magnitude.
         Produces `true` for `infinity` and `-infinity`.
         Produces `false` for a finite number, `+0.0`, `-0.0`,
         or undefined."
        see (`value infinity`, `value finite`)
        shared Boolean infinite
                => this==infinity || this==-infinity;

        "Determines whether this value is finite. Produces
         `false` for `infinity`, `-infinity`, and undefined."
        see (`value infinite`, `value infinity`)
        shared Boolean finite
                => this!=infinity && this!=-infinity
                        && !this.undefined;

        "The sign of this value. Produces `1` for a positive
         number or `infinity`. Produces `-1` for a negative
         number or `-infinity`. Produces `0.0` for `+0.0`,
         `-0.0`, or undefined."
        shared actual native Integer sign
                =>   if (this < 0.0) then -1
                else if (this > 0.0) then 1
                else 0;

        "Determines if this value is a positive number or
         `infinity`. Produces `false` for a negative number,
         `+0.0`, `-0.0`, or undefined."
        shared actual native Boolean positive => this > 0.0;

        "Determines if this value is a negative number or
         `-infinity`. Produces `false` for a positive number,
         `+0.0`, `-0.0`, or undefined."
        shared actual native Boolean negative => this < 0.0;

        "Determines if this value is a positive number, `+0.0`,
         or `infinity`. Produces `false` for a negative number,
         `-0.0`, or undefined."
        shared native Boolean strictlyPositive
                => this > 0.0 || 1.0/this > 0.0;

        "Determines if this value is a negative number, `-0.0`,
         or `-infinity`. Produces `false` for a positive number,
         `+0.0`, or undefined."
        shared native Boolean strictlyNegative
                => this < 0.0 || 1.0/this < 0.0;

        "Determines if the given object is equal to this `Float`,
         that is, if:

         - the given object is also a `Float`,
         - neither this value nor the given value is
           [[undefined]], and either
         - both values are [[infinite]] and have the same
           [[sign]], or both represent the same finite floating
           point value as defined by the IEEE specification.

         Or if:

         - the given object is an [[Integer]],
         - this value is neither [[undefined]], nor [[infinite]],
         - the [[fractionalPart]] of this value equals `0.0`,
         - the [[integer]] part of this value equals the given
           integer, and
         - the given integer is between -2<sup>53</sup> and
           2<sup>53</sup> (exclusive)."
        shared actual native Boolean equals(Object that);

        "A platform-dependent hash code for this `Float`."
        shared actual native Integer hash;

        "Compare this value to the given value, where
         [[infinity]] is considered greater than every defined,
         finite value, and `-infinity` is considered smaller
         than every defined, finite value, and [[undefined]]
         values are considered incomparable.

         Note that if `x` is an undefined `Float` and `y` is any
         `Float` that is not undefined, then:

         - `x<=>y` produces an exception when evaluated, but
         - `x>y`, `x<y`, `x>=y`, `x<=y`, and `x==y` all evaluate
           to `false`."
        throws (`class Exception`,
                "if either this value, the given value, or both
                 are [[undefined]]")
        shared actual native Comparison compare(Float other)
                =>   if (this < other) then smaller
                else if (this > other) then larger
                else equal;

        shared actual native Float negated;

        shared actual native Float plus(Float other);
        shared actual native Float minus(Float other);
        shared actual native Float times(Float other);
        shared actual native Float divided(Float other);

        "The result of raising this number to the given floating
         point power, where, following the definition of the
         IEEE `pow()` function, the following indeterminate
         forms all evaluate to `1.0`:

         - `0.0^0.0`,
         - `infinity^0.0` and `(-infinity)^0.0`,
         - `1.0^infinity` and `(-1.0)^infinity`.

         Furthermore:

          - `0.0^infinity` evaluates to `0.0`, and
          - `0.0^(-infinity)` evaluates to `infinity`.

         If this is a [[negative]] number, and the given
         [[power|other]] has a nonzero [[fractionalPart]], the
         result is [[undefined]].

         For any negative power `y<0.0`:

         - `0.0^y` evaluates to `infinity`,
         - `(-0.0)^y` evaluates to `-infinity`, and
         - for any nonzero floating point number `x`, `x^y`
           evaluates to `1.0/x^(-y)`."
        shared actual native Float power(Float other);

        shared actual native Float wholePart;
        shared actual native Float fractionalPart;

        aliased("absolute")
        shared actual native Float magnitude
                => this <= 0.0 then 0.0-this else this;

        "This value, represented as an [[Integer]], after
         truncation of its fractional part, if such a
         representation is possible."
        throws (`class OverflowException`,
            "if the the [[wholePart]] of this value is too large
             or too small to be represented as an `Integer`")
        since("1.1.0")
        shared native Integer integer;

        shared actual native Float timesInteger(Integer integer)
                => times(integer.nearestFloat);

        shared actual native Float plusInteger(Integer integer)
                => plus(integer.nearestFloat);

        "The result of raising this number to the given integer
         power, where the following indeterminate forms evaluate
         to `1.0`:

         - `0.0^0`,
         - `infinity^0` and `(-infinity)^0`.

         For any negative integer power `n<0`:

         - `0.0^n` evaluates to `infinity`,
         - `(-0.0)^n` evaluates to `-infinity`, and
         - for any nonzero floating point number `x`, `x^n`
           evaluates to `1.0/x^(-n)`."
        shared actual native Float powerOfInteger(Integer integer);

        "A string representing this floating point number.

         - `\"NaN\"`, for any [[undefined value|undefined]]
         - `\"Infinity\"`, for [[infinity]],
         - `\"-Infinity\"`, for [[-infinity]], or,
         - a Ceylon floating point literal that evaluates to
           this floating point number, for example, `\"1.0\"`,
           `\"-0.0\"`, or `\"1.5E10\"`."
        see (`function formatFloat`)
        shared actual native String string;

        "Determines if this value is strictly larger than the
         given value, where [[infinity]] is considered greater
         than every defined, finite value, and `-infinity` is
         considered smaller than every defined, finite value.
         Evaluates to `false` if this value, the given value, or
         both are [[undefined]]."
        shared actual native Boolean largerThan(Float other);

        "Determines if this value is strictly smaller than the
         given value, where [[infinity]] is considered greater
         than every defined, finite value, and `-infinity` is
         considered smaller than every defined, finite value.
         Evaluates to `false` if this value, the given value, or
         both are [[undefined]]."
        shared actual native Boolean smallerThan(Float other);

        "Determines if this value is larger than or equal to the
         given value, where [[infinity]] is considered greater
         than every defined, finite value, and `-infinity` is
         considered smaller than every defined, finite value.
         Evaluates to `false` if this value, the given value, or
         both are [[undefined]]."
        shared actual native Boolean notSmallerThan(Float other);

        "Determines if this value is smaller than or equal to the
         given value, where [[infinity]] is considered greater
         than every defined, finite value, and `-infinity` is
         considered smaller than every defined, finite value.
         Evaluates to `false` if this value, the given value, or
         both are [[undefined]]."
        shared actual native Boolean notLargerThan(Float other);
    }