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

num/fraction.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 fraction
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# fraction
#
#
# fraction provides fraction numbers based on an integer type to represent the
# numerator and the denominator.
#
# basic numeric operations +, -, * and comparison are supported. numerator and
# denominator are reduced after each operation.
#
# there are currently no checks or preconditions for overflows in the numerator
# or the denominator.
#
public fraction(
         public B type : integer,
         public numerator,
                denominator B
        ) : numeric
  pre
    safety: denominator.sign > 0 # denominator must be positive
is

  # just for brevity
  a => fraction numerator denominator


  # reduce numerator and denominator by their gcd:
  public reduce fraction B =>
    gcd := numerator.abs.gcd denominator
    if gcd = B.one
      a
    else
      fraction (numerator / gcd) (denominator / gcd)


  # basic operations
  public fixed redef prefix + fraction B => a
  public fixed redef prefix - fraction B => fraction -a.numerator a.denominator
  public fixed redef infix + (b fraction B) fraction B => (fraction (numerator * b.denominator + b.numerator * denominator) (denominator * b.denominator)).reduce
  public fixed redef infix - (b fraction B) fraction B => (fraction (numerator * b.denominator - b.numerator * denominator) (denominator * b.denominator)).reduce
  public fixed redef infix * (b fraction B) fraction B => (fraction (numerator * b.numerator                              ) (denominator * b.denominator)).reduce
  public fixed redef infix / (b fraction B) fraction B => (fraction (numerator * b.denominator) (denominator * b.numerator)).reduce


  public redef as_string String => "{numerator}?{denominator}"


  # -----------------------------------------------------------------------
  #
  # type features:


  # identity element for 'infix +'
  #
  public fixed redef type.zero num.fraction B => B.zero ? B.one


  # identity element for 'infix *'
  #
  public fixed redef type.one num.fraction B => B.one ? B.one


  # equality
  #
  public fixed redef type.equality(a, b num.fraction B) bool =>
    (a - b).numerator.is_zero


  # total order
  #
  public fixed redef type.lteq(a, b num.fraction B) bool =>
    (a - b).numerator.sign ? 0

last changed: 2026-03-09