Fuzion Logo
flang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

numeric.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature numeric
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# numeric -- parent of all numeric features
#
numeric<T : numeric<T>> : hasHash<T>, ordered<T>, numerics<T> is

  # get numeric.this value of type T.  This is used for a generic implemention
  # of some features (e.g. prefix -, abs
  thiz T is abstract

  isZero => numeric.this == zero
  isOne  => numeric.this == one

  # basic operations: 'prefix +' (identity)
  prefix + T
    pre
      safety: +!thiz
  is thiz

  # basic operations: 'prefix -' (negation)
  prefix - T
    pre
      safety: -!thiz
  is zero - thiz

  # basic operations: 'infix +' (addition)
  infix +  (other T) T
    pre
      safety: thiz +! other
  is abstract

  # basic operations: 'infix -' (substraction)
  infix -  (other T) T
    pre
      safety: thiz -! other
  is abstract

  # basic operations: 'infix *' (multiplication)
  infix *  (other T) T
    pre
      safety: thiz *! other
  is abstract

  # basic operations: 'infix /' (division)
  infix /  (other T) T
    pre
      safety: thiz /! other,
      safety: other != zero
  is abstract

  # basic operations: 'infix %' (division remainder)
  infix %  (other T) T
    pre
      safety: thiz %! other,
      safety: other != zero
  is abstract

  # basic operations: 'infix **' (exponentiation)
  infix ** (other T) T
    pre
      safety: thiz **! other,
      safety: other >= zero
  is abstract


  # preconditions for basic operations: true if the operation's result is
  # representable for the given values
  #
  # This does not check if the operation is defined (i.e, it
  # returns true for '3/!0' or '0**!0'.
  #
  prefix +! bool is true
  prefix -! bool is abstract
  infix +! (other T) bool is abstract
  infix -! (other T) bool is abstract
  infix *! (other T) bool is abstract
  infix /! (other T) bool is abstract
  infix %! (other T) bool is abstract
  infix **!(other T) bool is abstract


  # overflow checking operations
  prefix -? numOption<T> is - thiz
  infix +? (other T) numOption<T> is thiz + other
  infix -? (other T) numOption<T> is thiz - other
  infix *? (other T) numOption<T> is thiz * other
  infix **?(other T) numOption<T> is abstract

  # saturating  operations
  prefix -^  T is - thiz
  infix +^ (other T) T is thiz + other
  infix -^ (other T) T is thiz - other
  infix *^ (other T) T is thiz * other
  infix **^(other T) T is abstract

  # comparison
  infix == (other T) bool is abstract   // NYI: remove, replace by 'infix ='
  redef infix = (other T) bool is thiz == other
  infix != (other T) bool is abstract   // NYI: remove, replace by 'infix /='

  sign => if numeric.this == zero then 0 else if numeric.this > zero then 1 else -1

  abs => if sign >= 0 then thiz else -thiz

  # minimum of numeric.this and other
  #
  min(other T) T is if (numeric.this <= other) thiz else other

  # maximum of numeric.this and other
  #
  max(other T) T is if (numeric.this >= other) thiz else other


  # is this part of given set
  #
  elementOf(s Set<T>) => s.contains thiz
  infix ∈ (s Set<T>) => numeric.this.elementOf s


  # is this not part of given set
  #
  notElementOf(s Set<T>) => !elementOf s
  infix ∉ (s Set<T>) => numeric.this.notElementOf s