ExpandCollapse

+ 1 Synopsis.

share/lib/std/algebra/__init__.flx

  include "std/algebra/predicate";        // in logic.html
  include "std/algebra/set";              // in algebra.html
  include "std/algebra/container";        // in algebra.html
  include "std/algebra/equiv";            // in algebra.html
  include "std/algebra/partialorder";     // in algebra.html  
  include "std/algebra/totalorder";       // in algebra.html
  include "std/algebra/sequence";         // in algebra.html
  include "std/algebra/group";            // in algebra.html
  include "std/algebra/ring";             // in algebra.html
  include "std/algebra/bits";             // in algebra.html
  include "std/algebra/integer";          // in algebra.html
  include "std/algebra/trig";             // in algebra.html
  include "std/algebra/real";             // in algebra.html
  include "std/algebra/complex";          // in algebra.html
  include "std/algebra/monad";            // in algebra.html
  

+ 2 Description.

In this section we provide abstract definitions of some basic mathematical stuctures which will be used to specify operations on numeric types.

We use polymorphic classes to do this. A class is introduced by the class keyword followed by its name, then a list of type variables in square brackets. Then the body is presented enclosed in curly braces.

Two kinds of specification are allowed in a polymorphic class: function definitions and assertions.

+ 2.1 Functions.

There are two kinds of function definitions. A function or procedure specified with the adjective virtual may have a specialisation provided in an instance declaration. Virtual functions may have definitions, in which case the definition is merely a default. It can be replaced in a specialising instance. However the definition should be taken as a semantic specification which the specialisation should adhere too.

The set of virtual functions of a polymorphic class is known as the basis of the class.

A non-virtual function can be defined in terms of virtual functions and other non-virtual functions. Non virtual functions cannot be specialised by the programmer. Instead, they are automatically specialised by the system for an instance.

+ 2.2 Assertions

A polymorphic class may also contain assertions. These are function like specifications which specify semantic constraints.

An axiom specifies a basic assertion, it specifies a class property in terms of relations between the class functions. Since Felix only supports first order assertional logic, higher order semantics must be specified in comments.

If a class contains virtual functions with definitions, the definition is also considered as axiomatic.

The set of all axioms, including those in comments, is known as the assertional basis or semantic specification of the class. Additionally some reductions may be or imply an extension of the semantic basis.

A lemma is an assertion which can be derived from the semantic specifications by logical reasoning. In particular, lemmas in principle should be self-evident, simple and useful and able to be deduced by an automatic theorm proving program.

A theorem is a more complicated derived assertion, which would be too hard to prove with an automatic theorem prover. Instead, it should be derivable with a proof assistant (such as Coq), given various unspecified strategies, tactics and hints.

+ 3 Sets.

A set is any type with a membership predicate \(\in\) spelled \in. You can also use function mem. The parser also maps in to operator \in.

We also provide a reversed form \(\owns\) spelled \owns, and negated forms \(ni\) spelled \ni or \notin.

Three combinators are provided as well, \(\cap\) spelled cap provides intersection, \(\cup\) spelled \cup provides the usual set union, and \(\setminus\) spelled \setminus the asymmetic set difference or subtraction.

Note that sets are not necessarily finite.

share/lib/std/algebra/set.flx

  // note: eq is not necessarily required for a membership test
  // for example: string member of regexp doesn't require
  // string equality
  // Set need not be finite (example regexp again)
  // A list is a set, despite the duplications
  class Set[c,t] {
    fun mem (elt:t, container:c):bool => elt \(\in\) container;
    virtual fun \(\in\) : t * c-> bool;
    fun \(\owns\) (container:c, elt:t) => elt \(\in\) container;
    fun \(\ni\) (container:c, elt:t) => elt \(\in\) container;
    fun \(\notin\) (elt:t, container:c) => not (elt \(\in\) container);
  
    fun \(\cup\)[c2 with Set[c2,t]] 
      (x:c, y:c2) => 
      { e : t | e \(\in\) x or e \(\in\) y }
    ;
  
    fun \(\cap\)[c2 with Set[c2,t]] 
      (x:c, y:c2) => 
      { e : t | e \(\in\) x and e \(\in\) y }
    ;
  
    fun \(\setminus\)[c2 with Set[c2,t]] 
      (x:c, y:c2) => 
      { e : t | e \(\in\) x and e \(\notin\) y }
    ;
  }
  

+ 4 Set forms.

A set_form is a record type with a single member has_elt which returns true if it's argument is intended as a member of some particular set.

We construe a set_form as a Set by providing an instance.

A set_form is basically just the membership predicate remodelled as a noun by encapsulating the predicate in a closure and thereby abstracting it.

share/lib/std/algebra/set.flx

  interface set_form[T] { has_elt: T -> bool; }
  
  instance[T] Set[set_form[T], T] {
    fun \(\in\) (elt:T, s:set_form[T]) => s.has_elt elt;
  }
  open[T] Set[set_form[T],T];
  
  // INVERSE image of a set under a function
  // For a function f: t -> t2, an element e
  // is in a restriction of the domain t if its
  // image in t2 is in the specified set.
  fun invimg[t,c2,t2 with Set[c2,t2]] 
    (f:t->t2, x:c2) : set_form[t] =>
    { e : t | (f e) \(\in\) x }
  ;
  

+ 4.1 Cartesian Product of set_forms.

This uses some advanced instantiation technology to allow you to define the cartesian product of a sequence of sets using the infix TeX operator \(\otimes\) which is spelled \otimes. There's also a left associative binary operator \(\times\) spelled \times.

share/lib/std/algebra/set.flx

  
  fun \(\times\)[U,V] (x:set_form[U],y:set_form[V]) => 
    { u,v : U * V | u \(\in\) x and v \(\in\) y }
  ;
  
  fun \(\otimes\)[U,V] (x:set_form[U],y:set_form[V]) => 
    { u,v : U * V | u \(\in\) x and v \(\in\) y }
  ;
  
  fun \(\otimes\)[U,V,W] (head:set_form[U], tail:set_form[V*W]) =>
    { u,v,w : U * V * W | u \(\in\) head and (v,w) \(\in\) tail }
  ;
  
  fun \(\otimes\)[NH,OH,OT] (head:set_form[NH], tail:set_form[OH**OT]) =>
    { h,,(oh,,ot) : NH ** (OH ** OT) | h \(\in\) head and (oh,,ot) \(\in\) tail }
  ;
  

+ 5 Containers.

share/lib/std/algebra/container.flx

  // roughly, a finite Set
  class Container [c,v]
  {
    inherit Set[c,v];
    virtual fun len: c -> size;
    fun \(\Vert\) (x:c) => len x;
    virtual fun empty(x: c): bool => len x == size(0);
  }
  
  

+ 6 Orders

+ 6.1 Equivalence Relation.

An equivalence relation is a reflexive, symmetric, transitive relation. It is one of the most fundamental concepts in mathematics. One can show that for any set \(S\), for any element \(s \in S\), the subset \(\lbrack s\rbrack\) of \(S\) consisting of all elements equivalent to \(s\) are also equivalent to each other, and not equivalent to any other element outside that set.

Therefore, every equivalence relation on a set \(S\) specifies a partition of \(S\) which is a set of subsets of \(S\) known as equivalence classes, or just plain classes, such that no two classes have a common intersection, and the union of the classes spans the whole set.

In other words a partition consists of a disjoint union of subsets.

The most fundamential relation in computing which is required to be an equivalence relation is the equality operator. In particular, it allows us to have distinct encodings of a value, but still consider them equal semantically, and to provide an operational measure of that equivalence.

As a simple example, consider that the rational numbers \(1/2\) and \(2/4\) have distinct encodings but none-the-less are semantically equivalent.

An online reference on Wikibooks

share/lib/std/algebra/equiv.flx

  // equality: technically, equivalence relation
  class Eq[t] {
    virtual fun == : t * t -> bool;
    virtual fun != (x:t,y:t):bool => not (x == y);
  
    axiom reflex(x:t): x == x;
    axiom sym(x:t, y:t): (x == y) == (y == x);
    axiom trans(x:t, y:t, z:t): x == y and y == z implies x == z;
  
    fun eq(x:t, y:t)=> x == y;
    fun ne(x:t, y:t)=> x != y;
    fun \(\ne\)(x:t, y:t)=> x != y;
    fun \(\neq\)(x:t, y:t)=> x != y;
  }
  
  

+ 6.2 Partial Order

A proper partial order \(\subset\) spelled \subset is a transitive, antisymmetric irreflexive relation.

We also provide an improper operator \(\subseteq\) spelled \subseteq which is transitive, antisymmetric, and reflexive, for which either the partial order or equivalence operator == applies.

The choice of operators is motivated by the canonical exemplar of subset containment relations.

share/lib/std/algebra/partialorder.flx

  // partial order
  class Pord[t]{
    inherit Eq[t];
    virtual fun \(\subset\): t * t -> bool;
    virtual fun \(\supset\)(x:t,y:t):bool =>y \(\subset\) x;
    virtual fun \(\subseteq\)(x:t,y:t):bool => x \(\subset\) y or x == y;
    virtual fun \(\supseteq\)(x:t,y:t):bool => x \(\supset\) y or x == y;
  
    fun \(\subseteqq\)(x:t,y:t):bool => x \(\subseteq\) y;
    fun \(\supseteqq\)(x:t,y:t):bool => x \(\supseteq\) y;
  
    fun \(\nsubseteq\)(x:t,y:t):bool => not (x \(\subseteq\) y);
    fun \(\nsupseteq\)(x:t,y:t):bool => not (x \(\supseteq\) y);
    fun \(\nsubseteqq\)(x:t,y:t):bool => not (x \(\subseteq\) y);
    fun \(\nsupseteqq\)(x:t,y:t):bool => not (x \(\supseteq\) y);
  
    fun \(\supsetneq\)(x:t,y:t):bool => x \(\supset\) y;
    fun \(\supsetneqq\)(x:t,y:t):bool => x \(\supset\) y;
    fun \(\supsetneq\)(x:t,y:t):bool => x \(\supset\) y;
    fun \(\supsetneqq\)(x:t,y:t):bool => x \(\supset\) y;
  
    axiom trans(x:t, y:t, z:t): \(\subset\)(x,y) and \(\subset\)(y,z) implies \(\subset\)(x,z);
    axiom antisym(x:t, y:t): \(\subset\)(x,y) or \(\subset\)(y,x) or x == y;
    axiom reflex(x:t, y:t): \(\subseteq\)(x,y) and \(\subseteq\)(y,x) implies x == y;
  }

+ 6.3 Bounded Partial Order

A partial order may bave an upper or lower bound known as the supremum and infimum, respectively. If these values are in the type, they are called the maximum and minimum, respectively.

share/lib/std/algebra/partialorder.flx

  class UpperBoundPartialOrder[T] {
    inherit Pord[T];
    virtual fun upperbound: 1 -> T;
  }
  class LowerBoundPartialOrder[T] {
    inherit Pord[T];
    virtual fun lowerbound: 1 -> T;
  }
  class BoundPartialOrder[T] {
    inherit LowerBoundPartialOrder[T];
    inherit UpperBoundPartialOrder[T];
  }
  
  
  

+ 6.4 Total Order

A total order is a partial order with a totality law.

However we do not derive it from our partial order because we use different comparison operators. Here we use the standard ascii art comparison operators commonly found in programming languages along with the more beautiful TeX operators used in mathematical papers.

The spelling of the TeX operators can be found by holding the mouse over the symbol briefly.

share/lib/std/algebra/totalorder.flx

  // total order
  class Tord[t]{
    inherit Eq[t];
    // defined in terms of <, argument order swap, and boolean negation
  
    // less
    virtual fun < : t * t -> bool;
    fun lt (x:t,y:t): bool=> x < y;
    fun \(\lt\) (x:t,y:t): bool=> x < y;
    fun \(\lneq\) (x:t,y:t): bool=> x < y;
    fun \(\lneqq\) (x:t,y:t): bool=> x < y;
  
  
    axiom trans(x:t, y:t, z:t): x < y and y < z implies x < z;
    axiom antisym(x:t, y:t): x < y or y < x or x == y;
    axiom reflex(x:t, y:t): x < y and y <= x implies x == y;
    axiom totality(x:t, y:t): x <= y or y <= x;
  
  
    // greater
    fun >(x:t,y:t):bool => y < x;
    fun gt(x:t,y:t):bool => y < x;
    fun \(\gt\)(x:t,y:t):bool => y < x;
    fun \(\gneq\)(x:t,y:t):bool => y < x;
    fun \(\gneqq\)(x:t,y:t):bool => y < x;
  
    // less equal
    fun <= (x:t,y:t):bool => not (y < x);
    fun le (x:t,y:t):bool => not (y < x);
    fun \(\le\) (x:t,y:t):bool => not (y < x);
    fun \(\leq\) (x:t,y:t):bool => not (y < x);
    fun \(\leqq\) (x:t,y:t):bool => not (y < x);
    fun \(\leqslant\) (x:t,y:t):bool => not (y < x);
  
  
    // greater equal
    fun >= (x:t,y:t):bool => not (x < y);
    fun ge (x:t,y:t):bool => not (x < y);
    fun \(\ge\) (x:t,y:t):bool => not (x < y);
    fun \(\geq\) (x:t,y:t):bool => not (x < y);
    fun \(\geqq\) (x:t,y:t):bool => not (x < y);
    fun \(\geqslant\) (x:t,y:t):bool => not (x < y);
  
    // negated, strike-through
    fun \(\ngtr\) (x:t,y:t):bool => not (x < y);
    fun \(\nless\) (x:t,y:t):bool => not (x < y);
  
    fun \(\ngeq\) (x:t,y:t):bool => x < y;
    fun \(\ngeqq\) (x:t,y:t):bool => x < y;
    fun \(\ngeqslant\) (x:t,y:t):bool => x < y;
  
    fun \(\nleq\) (x:t,y:t):bool => not (x <= y);
    fun \(\nleqq\) (x:t,y:t):bool => not (x <= y);
    fun \(\nleqslant\) (x:t,y:t):bool => not (x <= y);
    
  
    // maxima and minima
    fun max(x:t,y:t):t=> if x < y then y else x endif;
    fun \(\vee\)(x:t,y:t) => max (x,y);
  
    fun min(x:t,y:t):t => if x < y then x else y endif;
    fun \(\wedge\)(x:t,y:t):t => min (x,y);
  
  
  }

+ 6.5 Bounded Total Orders.

share/lib/std/algebra/totalorder.flx

  class UpperBoundTotalOrder[T] {
    inherit Tord[T];
    virtual fun maxval: 1 -> T = "::std::numeric_limits<?1>::max()";
  }
  class LowerBoundTotalOrder[T] {
    inherit Tord[T];
    virtual fun minval: 1 -> T = "::std::numeric_limits<?1>::min()";
  }
  class BoundTotalOrder[T] {
    inherit LowerBoundTotalOrder[T];
    inherit UpperBoundTotalOrder[T];
  }
  
  

+ 6.6 Sequences

Sequences are discrete total orders.

share/lib/std/algebra/sequence.flx

  
  // Forward iterable
  class ForwardSequence[T] {
    inherit Tord[T];
    virtual fun succ: T -> T;
    virtual proc pre_incr: &T;
    virtual proc post_incr: &T;
  }
  
  // Bidirectional
  class BidirectionalSequence[T] {
    inherit ForwardSequence[T];
    virtual fun pred: T -> T;
    virtual proc pre_decr: &T;
    virtual proc post_decr: &T;
  }
  
  // Bounded Random access totally ordered
  // int should be any integer type really .. fix later
  class RandomSequence[T] {
    inherit BidirectionalSequence[T];
    virtual fun advance : int * T -> T;
  }
  
  // Bounded totally ordered forward iterable
  class BoundForwardSequence[T] {
    inherit ForwardSequence[T];
    inherit UpperBoundTotalOrder[T];
  }
  
  // Bounded totally ordered bidirectional
  class BoundBidirectionalSequence[T] {
    inherit BidirectionalSequence[T];
    inherit BoundTotalOrder[T];
  }
  
  // Bounded Random access totally ordered
  class BoundRandomSequence[T] {
    inherit RandomSequence[T];
    inherit BoundBidirectionalSequence[T];
  }
  

+ 7 Groupoids.

+ 7.1 Approximate Additive Group

An approximate additive group is a type for which there is a symmetric binary addition operator, a zero element, and for which there is an additive inverse or negation operator.

It is basically an additive group without the associativity requirement, and is intended to apply to floating point numbers.

Note we use the inherit statement to include the functions from class Eq.

share/lib/std/algebra/group.flx

  Additive symmetric float-approximate group, symbol +.
  Note: associativity is not assumed.
  class FloatAddgrp[t] {
    inherit Eq[t];
    virtual fun zero: unit -> t;
    virtual fun + : t * t -> t;
    virtual fun neg : t -> t;
    virtual fun prefix_plus : t -> t = "$1";
    virtual fun - (x:t,y:t):t => x + -y;
    virtual proc += (px:&t,y:t) { px <- *px + y; }
    virtual proc -= (px:&t,y:t) { px <- *px - y; }
  
    axiom sym (x:t,y:t): x+y == y+x;
  /*
    reduce id (x:t): x+zero() => x;
    reduce id (x:t): zero()+x => x;
    reduce inv(x:t): x - x => zero();
    reduce inv(x:t): - (-x) => x;
  */
    fun add(x:t,y:t)=> x + y;
    fun plus(x:t)=> +x;
    fun sub(x:t,y:t)=> x - y;
    proc pluseq(px:&t, y:t) {  += (px,y); }
    proc  minuseq(px:&t, y:t) { -= (px,y); }
  }

+ 7.2 Additive Group

A proper additive group is derived from FloatAddgrp with associativity added.

share/lib/std/algebra/group.flx

  Additive symmetric group, symbol +.
  class Addgrp[t] {
    inherit FloatAddgrp[t];
    axiom assoc (x:t,y:t,z:t): (x + y) + z == x + (y + z);
    //reduce inv(x:t,y:t): x + y - y => x;
  }
  

+ 7.3 Approximate Multiplicative Semi-Group With Unit.

An approximate multiplicative semigroup is a set with a symmetric binary multiplication operator and a unit.

share/lib/std/algebra/group.flx

  Multiplicative symmetric float-approximate semi group with unit symbol *.
  Note: associativity is not assumed.
  class FloatMultSemi1[t] {
    inherit Eq[t];
    proc muleq(px:&t, y:t) { *= (px,y); }
    fun mul(x:t, y:t) => x * y;
    fun sqr(x:t) => x * x;
    fun cube(x:t) => x * x * x;
    virtual fun one: unit -> t;
    virtual fun * : t * t -> t;
    virtual proc *= (px:&t, y:t) { px <- *px * y; }
  /*
    reduce id (x:t): x*one() => x;
    reduce id (x:t): one()*x => x;
  */
  }
  

+ 7.4 Multiplicative Semi-Group With Unit.

A multiplicative semigroup with unit is an approximate multiplicative semigroup with unit and associativity and satisfies the cancellation law.

share/lib/std/algebra/group.flx

  Multiplicative semi group with unit.
  class MultSemi1[t] {
    inherit FloatMultSemi1[t];
    axiom assoc (x:t,y:t,z:t): (x * y) * z == x * (y * z);
    //reduce cancel (x:t,y:t,z:t): x * z ==  y * z => x == y;
  }
  

+ 8 Rings

+ 8.1 Approximate Unit Ring.

An approximate ring is a set which has addition and multiplication satisfying the rules for approximate additive group and multiplicative semigroup respectively.

share/lib/std/algebra/ring.flx

  Float-approximate ring.
  class FloatRing[t] {
    inherit FloatAddgrp[t];
    inherit FloatMultSemi1[t];
  }
  

+ 8.2 Ring

A ring is a type which is a both an additive group and multiplicative semigroup with unit, and which in addition satisfies the distributive law.

share/lib/std/algebra/ring.flx

  Ring.
  class Ring[t] {
    inherit Addgrp[t];
    inherit MultSemi1[t];
    axiom distrib (x:t,y:t,z:t): x * ( y + z) == x * y + x * z;
  }

+ 8.3 Approximate Division Ring

An approximate division ring is an approximate ring with unit with a division operator.

share/lib/std/algebra/ring.flx

  Float-approximate division ring.
  class FloatDring[t] {
    inherit FloatRing[t];
    virtual fun / : t * t -> t; // pre t != 0
    fun \(\over\) (x:t,y:t) => x / y;
  
    virtual proc /= : &t * t;
    virtual fun % : t * t -> t;
    virtual proc %= : &t * t;
  
    fun div(x:t, y:t) => x / y;
    fun mod(x:t, y:t) => x % y;
    fun \(\bmod\)(x:t, y:t) => x % y;
    fun recip (x:t) => #one / x;
  
    proc diveq(px:&t, y:t) { /= (px,y); }
    proc modeq(px:&t, y:t) { %= (px,y); }
  }
  

+ 8.4 Division Ring

share/lib/std/algebra/ring.flx

  Division ring.
  class Dring[t] {
    inherit Ring[t];
    inherit FloatDring[t];
  }
  

+ 9 Integral.

+ 9.1 Bitwise operations

share/lib/std/algebra/bits.flx

  
  Bitwise operators.
  class Bits[t] {
    virtual fun \^ : t * t -> t = "(?1)($1^$2)";
    virtual fun \| : t * t -> t = "$1|$2";
    virtual fun \& : t * t -> t = "$1&$2";
    virtual fun ~: t -> t = "(?1)(~$1)";
    virtual proc ^= : &t * t = "*$1^=$2;";
    virtual proc |= : &t * t = "*$1|=$2;";
    virtual proc &= : &t * t = "*$1&=$2;";
  
    fun bxor(x:t,y:t)=> x \^ y;
    fun bor(x:t,y:t)=> x \| y;
    fun band(x:t,y:t)=> x \& y;
    fun bnot(x:t)=> ~ x;
  
  }

+ 9.2 Integer

share/lib/std/algebra/integer.flx

  
  Integers.
  class Integer[t] {
    inherit Tord[t];
    inherit Dring[t];
    inherit RandomSequence[t];
    virtual fun << : t * t -> t = "$1<<$2";
    virtual fun >> : t * t -> t = "$1>>$2";
    virtual proc <<= : &t * t = "*$1<<=$2;";
    virtual proc >>= : &t * t = "*$1>>=$2;";
  
    fun shl(x:t,y:t)=> x << y;
    fun shr(x:t,y:t)=> x >> y;
  }
  
  Signed Integers.
  class Signed_integer[t] {
    inherit Integer[t];
    virtual fun sgn: t -> int;
    virtual fun abs: t -> t;
  }
  
  Unsigned Integers.
  class Unsigned_integer[t] {
    inherit Integer[t];
    inherit Bits[t];
  }
  
  
  

+ 10 Float kinds

+ 10.1 Trigonometric Functions.

Trigonometric functions are shared by real and complex numbers.

share/lib/std/algebra/trig.flx

  
  Float-approximate trigonometric functions.
  class Trig[t] {
    inherit FloatDring[t];
  
    // NOTE: most of the axioms here WILL FAIL because they require
    // exact equality, but they're only going to succeed with approximate
    // equality, whatever that means. This needs to be fixed!
  
    // circular
    // ref http://en.wikipedia.org/wiki/Circular_functions 
  
    // core trig
    virtual fun sin: t -> t;
    fun \(\sin\) (x:t)=> sin x;
  
    virtual fun cos: t -> t;
    fun \(\cos\) (x:t)=> cos x;
  
    virtual fun tan (x:t)=> sin x / cos x;
    fun \(\tan\) (x:t)=> tan x;
  
    // reciprocals
    virtual fun sec (x:t)=> recip (cos x);
    fun \(\sec\) (x:t)=> sec x;
  
    virtual fun csc (x:t)=> recip (sin x);
    fun \(\csc\) (x:t)=> csc x;
  
    virtual fun cot (x:t)=> recip (tan x);
    fun \(\cot\) (x:t)=> cot x;
  
    // inverses
    virtual fun asin: t -> t;
    fun \(\arcsin\) (x:t) => asin x;
   
    virtual fun acos: t -> t;
    fun \(\arccos\) (x:t) => acos x;
  
    virtual fun atan: t -> t;
    fun \(\arctan\) (x:t) => atan x;
  
    virtual fun asec (x:t) => acos ( recip x);
    virtual fun acsc (x:t) => asin ( recip x);
    virtual fun acot (x:t) => atan ( recip x);
  
    // hyperbolic
    // ref http://en.wikipedia.org/wiki/Hyperbolic_functions
    virtual fun sinh: t -> t;
    fun \(\sinh\) (x:t) => sinh x;
  
    virtual fun cosh: t -> t;
    fun \(\cosh\) (x:t) => cosh x;
  
    virtual fun tanh (x:t) => sinh x / cosh x;
    fun \(\tanh\) (x:t) => tanh x;
  
    // reciprocals
    virtual fun sech (x:t) => recip (cosh x);
    fun \(\sech\) (x:t) => sech x;
  
    virtual fun csch (x:t) => recip (sinh x);
    fun \(\csch\) (x:t) => csch x;
  
    virtual fun coth (x:t) => recip (tanh x); 
    fun \(\coth\) (x:t) => coth x;
  
    // inverses
    virtual fun asinh: t -> t;
  
    virtual fun acosh: t -> t;
  
    virtual fun atanh: t -> t;
  
    virtual fun asech (x:t) => acosh ( recip x);
    virtual fun acsch (x:t) => asinh ( recip x );
    virtual fun acoth (x:t) => atanh ( recip x );
  
    // exponential
    virtual fun exp: t -> t;
    fun \(\exp\) (x:t) => exp x;
  
    // log
    virtual fun log: t -> t;
    fun \(\log\) (x:t) => log x;
    fun ln (x:t) => log x;
    fun \(\ln\) (x:t) => log x;
  
    // power
    virtual fun pow: t * t -> t;
    virtual fun pow (a:t, b:int) : t => pow (a, C_hack::cast[t] b);
    fun ^ (x:t,y:t) => pow (x,y);
    fun ^ (x:t,y:int) => pow (x,y);
  
  
  }
  
  Finance and Statistics.
  class Special[t] {
    virtual fun erf: t -> t;
    virtual fun erfc: t -> t;
  }
  

+ 10.2 Approximate Reals.

share/lib/std/algebra/real.flx

  Float-approximate real numbers.
  class Real[t] {
    inherit Tord[t];
    inherit Trig[t];
    inherit Special[t];
    virtual fun embed: int -> t;
  
    virtual fun log10: t -> t;
    virtual fun abs: t -> t;
   
    virtual fun sqrt: t -> t;
    fun \(\sqrt\) (x:t) => sqrt x;
    virtual fun ceil: t -> t;
      // tex \lceil \rceil defined in grammar
  
    virtual fun floor: t -> t;
      // tex \lfloor \rfloor defined in grammar
  
    virtual fun trunc: t -> t;
  
    // this trig function is included here because it
    // is not available for complex numbers
    virtual fun atan2: t * t -> t;
  
  }
  
  

+ 10.3 Complex numbers

share/lib/std/algebra/complex.flx

  Float-approximate Complex.
  class Complex[t,r] {
    inherit Eq[t];
    inherit Special[t];
    inherit Trig[t];
    virtual fun real: t -> r;
    virtual fun imag: t -> r;
    virtual fun abs: t -> r;
    virtual fun arg: t -> r;
    virtual fun sqrt: t -> r;
  
    virtual fun + : r * t -> t;
    virtual fun + : t * r -> t;
    virtual fun - : r * t -> t;
    virtual fun - : t * r -> t;
    virtual fun * : t * r -> t;
    virtual fun * : r * t -> t;
    virtual fun / : t * r -> t;
    virtual fun / : r * t -> t;
  }
  
  
  

+ 11 Summation and Product Quantifiers.

To be moved. Folds over streams.

share/lib/std/algebra/group.flx

  open class Quantifiers_add_mul {
    fun \(\sum\)[T,C with FloatAddgrp[T], Streamable[C,T]] (a:C):T = 
    {
      var init = #zero[T];
      for x in a perform init = init + x;
      return init;
    }
  
    fun \(\prod\)[T,C with FloatMultSemi1[T], Streamable[C,T]] (a:C):T = 
    {
      var init = #one[T];
      for x in a perform init = init * x;
      return init;
    }
  
    fun \(\sum\)[T with FloatAddgrp[T]] (f:1->opt[T])  = 
    {
      var init = #zero[T];
      for x in f perform init = init + x;
      return init;
    }
  
    fun \(\prod\)[T with FloatMultSemi1[T]] (f:1->opt[T])  = 
    {
      var init = #one[T];
      for x in f perform init = init * x;
      return init;
    }
   
  }
  

+ 12 Monad

share/lib/std/algebra/monad.flx

  
  class Monad [M: TYPE->TYPE] {
    virtual fun ret[a]: a -> M a;
    virtual fun bind[a,b]: M a * (a -> M b) -> M b;
    fun join[a] (n: M (M a)): M a => bind (n , (fun (x:M a):M a=>x));
  }