// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.core;

/**
 * An integer or floating-point number.
 *
 * It is a compile-time error for any type other than [int] or [double]
 * to attempt to extend or implement num.
 */
abstract class num implements Comparable<num> {
  /**
   * Test whether this value is numerically equal to `other`.
   *
   * If both operands are doubles, they are equal if they have the same
   * representation, except that:
   *   * zero and minus zero (0.0 and -0.0) are considered equal. They
   *     both have the numerical value zero.
   *   * NaN is not equal to anything, including NaN. If either operand is
   *     NaN, the result is always false.
   *
   * If one operand is a double and the other is an int, they are equal if
   * the double has an integer value (finite with no fractional part) and
   * `identical(doubleValue.toInt(), intValue)`.
   *
   * If both operands are integers, they are equal if they have the same value.
   *
   * Returns false if `other` is not a [num].
   *
   * Notice that the behavior for NaN is non-reflexive. This means that
   * equality of double values is not a proper equality relation, as is
   * otherwise required of `operator==`. Using NaN in, e.g., a [HashSet]
   * will fail to work. The behavior is the standard IEEE-754 equality of
   * doubles.
   *
   * If you can avoid NaN values, the remaining doubles do have a proper eqality
   * relation, and can be used safely.
   *
   * Use [compareTo] for a comparison that distinguishes zero and minus zero,
   * and that considers NaN values as equal.
   */
  bool operator==(Object other);

  /**
   * Returns a hash code for a numerical value.
   *
   * The hash code is compatible with equality. It returns the same value
   * for an [int] and a [double] with the same numerical value, and therefore
   * the same value for the doubles zero and minus zero.
   *
   * No guarantees are made about the hash code of NaN.
   */
  int get hashCode;

  /**
   * Compares this to `other`.
   *
   * Returns a negative number if `this` is less than `other`, zero if they are
   * equal, and a positive number if `this` is greater than `other`.
   *
   * The orderding represented by this method is a total ordering of [num]
   * values. All distinct doubles are non-equal, as are all distinct integers,
   * but integers are equal to doubles if they have the same numerical
   * value.
   *
   * For ordering, the double NaN value is considered equal to itself, and
   * greater than any numeric value (unlike its behavior in `operator==`).
   *
   * The double value -0.0 is considered less than 0.0 (and the integer 0), but
   * greater than any non-zero negative value.
   *
   * Positive infinity is greater than any finite value (any value apart from
   * itself and NaN), and negative infinity is less than any other value.
   *
   * All other values are compared using their numeric value.
   */
  int compareTo(num other);

  /** Addition operator. */
  num operator +(num other);

  /** Subtraction operator. */
  num operator -(num other);

  /** Multiplication operator. */
  num operator *(num other);

  /**
   * Euclidean modulo operator.
   *
   * Returns the remainder of the euclidean division. The euclidean division of
   * two integers `a` and `b` yields two integers `q` and `r` such that
   * `a == b * q + r` and `0 <= r < b.abs()`.
   *
   * The euclidean division is only defined for integers, but can be easily
   * extended to work with doubles. In that case `r` may have a non-integer
   * value, but it still verifies `0 <= r < |b|`.
   *
   * The sign of the returned value `r` is always positive.
   *
   * See [remainder] for the remainder of the truncating division.
   */
  num operator %(num other);

  /** Division operator. */
  double operator /(num other);

  /**
   * Truncating division operator.
   *
   * If either operand is a [double] then the result of the truncating division
   * `a ~/ b` is equivalent to `(a / b).truncate().toInt()`.
   *
   * If both operands are [int]s then `a ~/ b` performs the truncating
   * integer division.
   */
  int operator ~/(num other);

  /** Negate operator. */
  num operator -();

 /**
   * Returns the remainder of the truncating division of `this` by [other].
   *
   * The result `r` of this operation satisfies:
   * `this == (this ~/ other) * other + r`.
   * As a consequence the remainder `r` has the same sign as the divider `this`.
   */
  num remainder(num other);

  /** Relational less than operator. */
  bool operator <(num other);

  /** Relational less than or equal operator. */
  bool operator <=(num other);

  /** Relational greater than operator. */
  bool operator >(num other);

  /** Relational greater than or equal operator. */
  bool operator >=(num other);

  /** True if the number is the double Not-a-Number value; otherwise, false. */
  bool get isNaN;

  /**
   * True if the number is negative; otherwise, false.
   *
   * Negative numbers are those less than zero, and the double `-0.0`.
   */
  bool get isNegative;

  /**
   * True if the number is positive infinity or negative infinity; otherwise,
   * false.
   */
  bool get isInfinite;

  /**
   * True if the number is finite; otherwise, false.
   *
   * The only non-finite numbers are NaN, positive infinitity and
   * negative infinity.
   */
  bool get isFinite;

  /** Returns the absolute value of this [num]. */
  num abs();

  /**
   * Returns minus one, zero or plus one depending on the sign and
   * numerical value of the number.
   *
   * Returns minus one if the number is less than zero,
   * plus one if the number is greater than zero,
   * and zero if the number is equal to zero.
   *
   * Returns NaN if the number is the double NaN value.
   *
   * Returns a number of the same type as this number.
   * For doubles, `-0.0.sign == -0.0`.

   * The result satisfies:
   *
   *     n == n.sign * n.abs()
   *
   * for all numbers `n` (except NaN, because NaN isn't `==` to itself).
   */
  num get sign;

  /**
   * Returns the integer closest to `this`.
   *
   * Rounds away from zero when there is no closest integer:
   *  `(3.5).round() == 4` and `(-3.5).round() == -4`.
   *
   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
   */
  int round();

  /**
   * Returns the greatest integer no greater than `this`.
   *
   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
   */
  int floor();

  /**
   * Returns the least integer no smaller than `this`.
   *
   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
   */
  int ceil();

  /**
   * Returns the integer obtained by discarding any fractional
   * digits from `this`.
   *
   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
   */
  int truncate();

  /**
   * Returns the double integer value closest to `this`.
   *
   * Rounds away from zero when there is no closest integer:
   *  `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`.
   *
   * If this is already an integer valued double, including `-0.0`, or it is a
   * non-finite double value, the value is returned unmodified.
   *
   * For the purpose of rounding, `-0.0` is considered to be below `0.0`,
   * and `-0.0` is therefore considered closer to negative numbers than `0.0`.
   * This means that for a value, `d` in the range `-0.5 < d < 0.0`,
   * the result is `-0.0`.
   *
   * The result is always a double.
   * If this is a numerically large integer, the result may be an infinite
   * double.
   */
  double roundToDouble();

  /**
   * Returns the greatest double integer value no greater than `this`.
   *
   * If this is already an integer valued double, including `-0.0`, or it is a
   * non-finite double value, the value is returned unmodified.
   *
   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
   * A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
   *
   * The result is always a double.
   * If this is a numerically large integer, the result may be an infinite
   * double.
   */
  double floorToDouble();

  /**
   * Returns the least double integer value no smaller than `this`.
   *
   * If this is already an integer valued double, including `-0.0`, or it is a
   * non-finite double value, the value is returned unmodified.
   *
   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
   * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
   *
   * The result is always a double.
   * If this is a numerically large integer, the result may be an infinite
   * double.
   */
  double ceilToDouble();

  /**
   * Returns the double integer value obtained by discarding any fractional
   * digits from the double value of `this`.
   *
   * If this is already an integer valued double, including `-0.0`, or it is a
   * non-finite double value, the value is returned unmodified.
   *
   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
   * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
   * in the range `0.0 < d < 1.0` it will return 0.0.
   *
   * The result is always a double.
   * If this is a numerically large integer, the result may be an infinite
   * double.
   */
  double truncateToDouble();

  /**
   * Clamps [this] to be in the range [lowerLimit]-[upperLimit]. The comparison
   * is done using [compareTo] and therefore takes `-0.0` into account.
   * It also implies that [double.NAN] is treated as the maximal double value.
   */
  num clamp(num lowerLimit, num upperLimit);

  /** Truncates this [num] to an integer and returns the result as an [int]. */
  int toInt();

  /**
   * Return this [num] as a [double].
   *
   * If the number is not representable as a [double], an
   * approximation is returned. For numerically large integers, the
   * approximation may be infinite.
   */
  double toDouble();

  /**
   * Returns a decimal-point string-representation of `this`.
   *
   * Converts `this` to a [double] before computing the string representation.
   *
   * If the absolute value of `this` is greater or equal to `10^21` then this
   * methods returns an exponential representation computed by
   * `this.toStringAsExponential()`. Otherwise the result
   * is the closest string representation with exactly [fractionDigits] digits
   * after the decimal point. If [fractionDigits] equals 0 then the decimal
   * point is omitted.
   *
   * The parameter [fractionDigits] must be an integer satisfying:
   * `0 <= fractionDigits <= 20`.
   *
   * Examples:
   *
   *     1.toStringAsFixed(3);  // 1.000
   *     (4321.12345678).toStringAsFixed(3);  // 4321.123
   *     (4321.12345678).toStringAsFixed(5);  // 4321.12346
   *     123456789012345678901.toStringAsFixed(3);  // 123456789012345683968.000
   *     1000000000000000000000.toStringAsFixed(3); // 1e+21
   *     5.25.toStringAsFixed(0); // 5
   */
  String toStringAsFixed(int fractionDigits);

  /**
   * Returns an exponential string-representation of `this`.
   *
   * Converts `this` to a [double] before computing the string representation.
   *
   * If [fractionDigits] is given then it must be an integer satisfying:
   * `0 <= fractionDigits <= 20`. In this case the string contains exactly
   * [fractionDigits] after the decimal point. Otherwise, without the parameter,
   * the returned string uses the shortest number of digits that accurately
   * represent [this].
   *
   * If [fractionDigits] equals 0 then the decimal point is omitted.
   * Examples:
   *
   *     1.toStringAsExponential();       // 1e+0
   *     1.toStringAsExponential(3);      // 1.000e+0
   *     123456.toStringAsExponential();  // 1.23456e+5
   *     123456.toStringAsExponential(3); // 1.235e+5
   *     123.toStringAsExponential(0);    // 1e+2
   */
  String toStringAsExponential([int fractionDigits]);

  /**
   * Converts `this` to a double and returns a string representation with
   * exactly [precision] significant digits.
   *
   * The parameter [precision] must be an integer satisfying:
   * `1 <= precision <= 21`.
   *
   * Examples:
   *
   *     1.toStringAsPrecision(2);       // 1.0
   *     1e15.toStringAsPrecision(3);    // 1.00+15
   *     1234567.toStringAsPrecision(3); // 1.23e+6
   *     1234567.toStringAsPrecision(9); // 1234567.00
   *     12345678901234567890.toStringAsPrecision(20); // 12345678901234567168
   *     12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19
   *     0.00000012345.toPrecision(15); // 1.23450000000000e-7
   *     0.0000012345.toPrecision(15);  // 0.00000123450000000000
   */
  String toStringAsPrecision(int precision);

  /**
   * Returns the shortest string that correctly represent the input number.
   *
   * All [double]s in the range `10^-6` (inclusive) to `10^21` (exclusive)
   * are converted to their decimal representation with at least one digit
   * after the decimal point. For all other doubles,
   * except for special values like `NaN` or `Infinity`, this method returns an
   * exponential representation (see [toStringAsExponential]).
   *
   * Returns `"NaN"` for [double.NAN], `"Infinity"` for [double.INFINITY], and
   * `"-Infinity"` for [double.MINUS_INFINITY].
   *
   * An [int] is converted to a decimal representation with no decimal point.
   *
   * Examples:
   *
   *     (0.000001).toString();  // "0.000001"
   *     (0.0000001).toString(); // "1e-7"
   *     (111111111111111111111.0).toString();  // "111111111111111110000.0"
   *     (100000000000000000000.0).toString();  // "100000000000000000000.0"
   *     (1000000000000000000000.0).toString(); // "1e+21"
   *     (1111111111111111111111.0).toString(); // "1.1111111111111111e+21"
   *     1.toString(); // "1"
   *     111111111111111111111.toString();  // "111111111111111110000"
   *     100000000000000000000.toString();  // "100000000000000000000"
   *     1000000000000000000000.toString(); // "1000000000000000000000"
   *     1111111111111111111111.toString(); // "1111111111111111111111"
   *     1.234e5.toString();   // 123400
   *     1234.5e6.toString();  // 1234500000
   *     12.345e67.toString(); // 1.2345e+68
   *
   * Note: the conversion may round the output if the returned string
   * is accurate enough to uniquely identify the input-number.
   * For example the most precise representation of the [double] `9e59` equals
   * `"899999999999999918767229449717619953810131273674690656206848"`, but
   * this method returns the shorter (but still uniquely identifying) `"9e59"`.
   *
   */
  String toString();

  /**
   * Parses a string containing a number literal into a number.
   *
   * The method first tries to read the [input] as integer (similar to
   * [int.parse] without a radix).
   * If that fails, it tries to parse the [input] as a double (similar to
   * [double.parse]).
   * If that fails, too, it invokes [onError] with [input].
   *
   * If no [onError] is supplied, it defaults to a function that throws a
   * [FormatException].
   *
   * For any number `n`, this function satisfies
   * `identical(n, num.parse(n.toString()))`.
   */
  static num parse(String input, [num onError(String input)]) {
    String source = input.trim();
    // TODO(lrn): Optimize to detect format and result type in one check.
    num result = int.parse(source, onError: _returnNull);
    if (result != null) return result;
    result = double.parse(source, _returnNull);
    if (result != null) return result;
    if (onError == null) throw new FormatException(input);
    return onError(input);
  }

  /** Helper function for [parse]. */
  static _returnNull(_) => null;
}
