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

container/numeric_sequence.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_sequence
#
#  Author: Michael Lill (michael.lill@tokiwa.software)
#
# -----------------------------------------------------------------------

# numeric_sequence -- a Sequence whose elements inherit from numeric
#
public numeric_sequence(public N type : numeric,
                        redef from Sequence N   ) : searchable_sequence N from,
                                                    property.equatable
is

  # the arithmetic mean of the sequence
  # https://en.wikipedia.org/wiki/Arithmetic_mean
  public average option N =>
    if is_empty
      nil
    else
      cnt := (map N (_ -> N.one)).fold N.sum
      sum := fold N.sum
      sum / cnt


  # the variance of the sequence
  # https://en.wikipedia.org/wiki/Variance
  public variance option N =>
    match average
      nil => nil
      avg N =>
        cnt := (map N (_ -> N.one           )).fold N.sum
        sum := (map N (x -> (x - avg)**N.two)).fold N.sum
        sum / cnt


  # minimum value in the sequence
  public min option N =>
    if is_empty
      nil
    else
      reduce first ((r,t) -> if r ≤ t then r else t)


  # maximum value in the sequence
  public max option N =>
    if is_empty
      nil
    else
      reduce first ((r,t) -> if r ≤ t then t else r)


  # the median of the sequence
  # https://en.wikipedia.org/wiki/Median
  public median option N =>
    if is_empty
      nil
    else
      arr := sorted_array_of numeric_sequence.this
      if arr.length % 2 = 1
        arr[arr.length / 2]
      else
        (arr[(arr.length / 2) - 1] + arr[(arr.length / 2)]) / (N.two)


  # equality check implementation for inherited property.equatable
  #
  public fixed type.equality(a, b container.numeric_sequence N) bool =>
    aa := a.as_array
    ba := b.as_array
    aa.count = ba.count
      && ((0..(a.count - 1)) ∀ (i -> aa[i] = ba[i]))