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

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

# complex -- complex numbers based on arbitrary numeric type
#
# complex provides complex numbers based on a numeric type (e.g. f64, i32).
# A complex number consists of a real and an imaginary part.
#
public complex (
         public C type : numeric,
         public real,    # real part
                imag C   # imaginary part
         ) : numeric
is


  # enable generic features in ancestors
  public thiz => complex real imag

  # basic operations
  public fixed redef prefix + => thiz
  public fixed redef infix + (b complex.this) => complex real+b.real imag+b.imag
  public fixed redef infix - (b complex.this) => complex real-b.real imag-b.imag
  public fixed redef infix * (b complex.this) => complex real*b.real-imag*b.imag real*b.imag+imag*b.real
  public fixed redef infix / (b complex.this)
  pre
    # NYI: use type features
    # safety: b != zero
    safety: b.real != C.zero || b.imag != C.zero
  =>
    n := b.real*b.real+b.imag*b.imag
    complex (real*b.real+imag*b.imag)/n (imag*b.real-real*b.imag)/n


  # equality
  #
  public fixed type.equality(a, b num.complex C) bool =>
    a.real = b.real && a.imag = b.imag


  # total order ignoring imag
  #
  # NYI: Does this make sense mathematically?
  #
  public fixed type.lteq(a, b num.complex C) bool =>
    a.real ≤ b.real


  public abs² => real*real+imag*imag


  public redef as_string =>
    si :=
      for c in ($imag).as_codepoints
      until !("0123456789.+-".contains c)
        "($imag)"
      else
        $imag
    p := if (si.starts_with "-") then "" else "+"
    "{real}$p{si}i"


  # identity element for 'infix +'
  #
  public fixed type.zero num.complex C =>
    num.complex C.zero C.zero


  # identity element for 'infix *'
  #
  public fixed type.one num.complex C =>
    num.complex C.one C.zero


  # the imaginary unit
  #
  public fixed type.i num.complex C =>
    num.complex C.zero C.one