Skip to content

Latest commit

 

History

History
891 lines (727 loc) · 26.4 KB

numbers.rst

File metadata and controls

891 lines (727 loc) · 26.4 KB

Package: src/packages/numbers.fdoc

Operations on numbers.

key file
number.flx share/lib/std/scalar/number.flx
real.flx share/lib/std/scalar/real.flx
float_format.flx share/lib/std/scalar/float_format.flx
float_math.flx share/lib/std/scalar/float_math.flx
int.flx share/lib/std/scalar/int.flx
quaternion.flx share/lib/std/scalar/quaternion.flx
random.flx share/lib/std/random.flx

General Numeric operations.

zero(fun)

neg(fun)

one(fun)

//[number.flx]

instance[t in numbers] FloatAddgrp[t] {
  fun zero: unit -> t = "(?1)0" ;
  fun + : t * t -> t = "$1+$2" ;
  fun neg : t -> t = "-$1" ;
  fun - : t * t -> t = "$1-$2" ;
  proc += : &t * t = "*$1+=$2;";
  proc -= : &t * t = "*$1-=$2;";
}

instance[t in numbers] FloatMultSemi1[t] {
  fun one: unit -> t = "(?1)1";
  fun * : t * t -> t = "$1*$2";
  proc *= : &t * t = "*$1*=$2;";
}

instance[t in numbers] FloatRing[t] {}
instance[t in ints \cup complexes] FloatDring[t] {
  fun / : t * t -> t = "$1/$2";
  fun % : t * t -> t = "$1%$2";
  proc /= : &t * t = "*$1/=$2;";
  proc %= : &t * t = "*$1%=$2;";
}
instance[t in floats] FloatDring[t] {
  fun / : t * t -> t = "$1/$2";
  fun % : t * t -> t = "fmod($1,$2)";
  proc /= : &t * t = "*$1/=$2;";
  proc %= : &t * t = "*$1=fmod($1,$2);";
}

Floating Numbers.

Operations on Real and Complex numbers.

Floatinf(class)

Doubleinf(class)

Ldoubleinf(class)

Fcomplex(class)

Dcomplex(class)

Lcomplex(class)

real(fun)

imag(fun)

abs(fun)

arg(fun)

neg(fun)

zero(fun)

one(fun)

sin(fun)

cos(fun)

tan(fun)

asin(fun)

acos(fun)

atan(fun)

sinh(fun)

cosh(fun)

tanh(fun)

asinh(fun)

acosh(fun)

atanh(fun)

exp(fun)

log(fun)

pow(fun)

abs(fun)

log10(fun)

sqrt(fun)

ceil(fun)

floor(fun)

trunc(fun)

embed(fun)

atan2(fun)

CartComplex(class)

def(type)

//[float_math.flx]

// note: has to be called Fcomplex to avoid clash with class Complex

// Note: ideally we'd use constrained polymorphism for the instances..
// saves typing it all out so many times
open class Floatinf
{
   const FINFINITY : float = "INFINITY" requires C99_headers::math_h;
}

open class Doubleinf
{
   const DINFINITY : double = "(double)INFINITY" requires C99_headers::math_h;
}

open class Ldoubleinf
{
   const LINFINITY : ldouble = "(long double)INFINITY" requires C99_headers::math_h;
}

fun isinf[T in reals] : T -> bool = "::std::isinf($1)" requires Cxx_headers::cmath;
fun isfinite[T in reals] : T -> bool = "::std::isfinite($1)" requires Cxx_headers::cmath;
fun isnan[T in reals] : T -> bool = "::std::isnan($1)" requires Cxx_headers::cmath;

ctor[T in ints] float : T = "(float)($1)";
ctor[T in ints] double  : T = "(double)($1)";
ctor[T in ints] ldouble : T = "(long double)($1)";

ctor float : string = "::std::stof($1)";
ctor double  : string = "::std::stod($1)";
ctor ldouble : string = "::std::stold($1)";


open class Fcomplex
{
  ctor[t in reals] fcomplex : t * t = "::std::complex<float>($1,$2)";
  ctor[t in reals] fcomplex : t = "::std::complex<float>($1,0)";
  instance Str[fcomplex] {
    fun str (z:fcomplex) => str(real z) + "+" + str(imag z)+"i";
  }
}

open class Dcomplex
{
  ctor[t in reals] dcomplex : t * t = "::std::complex<double>($1,$2)";
  ctor[t in reals] dcomplex : t = "::std::complex<double>($1,0)";
  instance Str[dcomplex] {
    fun str (z:dcomplex) => str(real z) + "+" + str(imag z)+"i";
  }
}

open class Lcomplex
{
  ctor[t in reals] lcomplex : t * t = "::std::complex<long double>($1,$2)";
  ctor[t in reals] lcomplex : t = "::std::complex<long double>($1,0)";
  instance Str[lcomplex] {
    fun str (z:lcomplex) => str(real z) + "+" + str(imag z)+"i";
  }
}

instance[t in floats] Complex[complex[t],t] {
  fun real : complex[t] -> t = "real($1)";
  fun imag : complex[t] -> t = "imag($1)";
  fun abs: complex[t] -> t = "abs($1)";
  fun arg : complex[t] -> t = "arg($1)";
  fun neg : complex[t] -> complex[t] = "-$1";
  fun + : complex[t] * complex[t] -> complex[t] = "$1+$2";
  fun - : complex[t] * complex[t] -> complex[t] = "$1-$2";
  fun * : complex[t] * complex[t] -> complex[t] = "$1*$2";
  fun / : complex[t] * complex[t] -> complex[t] = "$1/$2";
  fun + : complex[t] * t -> complex[t] = "$1+$2";
  fun - : complex[t] * t -> complex[t] = "$1-$2";
  fun * : complex[t] * t -> complex[t] = "$1*$2";
  fun / : complex[t] * t -> complex[t] = "$1/$2";
  fun + : t * complex[t] -> complex[t] = "$1+$2";
  fun - : t * complex[t] -> complex[t] = "$1-$2";
  fun * : t * complex[t] -> complex[t] = "$1*$2";
  fun / : t * complex[t] -> complex[t] = "$1/$2";
  fun zero: 1 -> complex[t] = "::std::complex<?1>(0.0)";
  fun one: 1 -> complex[t] = "::std::complex<?1>(1.0)";
}

instance[t in (floats  \cup  complexes)] Trig[t] {
  requires Cxx_headers::cmath;
  fun sin: t -> t = "::std::sin($1)";
  fun cos: t -> t = "::std::cos($1)";
  fun tan: t -> t = "::std::tan($1)";
  fun asin: t -> t = "::std::asin($1)";
  fun acos: t -> t = "::std::acos($1)";
  fun atan: t -> t = "::std::atan($1)";
  fun sinh: t -> t = "::std::sinh($1)";
  fun cosh: t -> t = "::std::cosh($1)";
  fun tanh: t -> t = "::std::tanh($1)";
  fun asinh: t -> t = "::std::asinh($1)";
  fun acosh: t -> t = "::std::acosh($1)";
  fun atanh: t -> t = "::std::atanh($1)";
  fun exp: t -> t = "::std::exp($1)";
  fun log: t -> t = "::std::log($1)";
  fun pow: t * t -> t = "::std::pow($1,$2)";
}

instance[t in floats] Real[t] {
  requires Cxx_headers::cmath;
  fun abs: t -> t = "::std::abs($1)";
  fun log10: t -> t = "::std::log10($1)";
  fun sqrt: t -> t = "::std::sqrt($1)";
  fun ceil: t -> t = "::std::ceil($1)";
  fun floor: t -> t = "::std::floor($1)";
  fun trunc: t -> t = "::std::trunc($1)";
  fun embed: int -> t = "(?1)($1)";
  fun atan2: t * t -> t = "::std::atan2($1,$2)";
}

class CartComplex[r] {
  typedef t = complex[r];
  inherit Complex[t,r];
}

typedef complex[t in floats] = typematch t with
  | float => fcomplex
  | double => dcomplex
  | ldouble => lcomplex
  endmatch
;

Complex Constructors.

//[float_math.flx]

ctor complex[float] (x:float, y:float) => fcomplex(x,y);
ctor complex[double] (x:double, y:double) => dcomplex(x,y);
ctor complex[ldouble] (x:ldouble, y:ldouble) => lcomplex(x,y);

ctor complex[float] (x:float) => fcomplex(x,0.0f);
ctor complex[double] (x:double) => dcomplex(x,0.0);
ctor complex[ldouble] (x:ldouble) => lcomplex(x,0.0l);

typedef polar[t in floats] = complex[t];
ctor[t in floats] polar[t] : t * t = "::std::polar($1,$2)";


instance[r in floats] CartComplex[r] {}

open Real[float];
open Real[double];
open Real[ldouble];
open Complex[fcomplex, float];
open Complex[dcomplex, double];
open Complex[lcomplex, ldouble];
open CartComplex[float];
open CartComplex[double];
open CartComplex[ldouble];

Real numbers

//[real.flx]
instance[t in reals] Tord[t] {
  fun < : t * t -> bool = "$1<$2";
}

Floating Formats

float_format(class)

fmt(fun)

fmt(fun)

fmt_default(fun)

fmt_fixed(fun)

fmt_scientific(fun)

xstr(fun)

xstr(fun)

xstr(fun)

//[float_format.flx ]
//$ Functions to format floating point numbers.
open class float_format
{
  //$ Style of formatting.
  //$ default (w,d)    : like C "w.dG" format
  //$ fixed (w,d)      : like C "w.dF" format
  //$ scientific (w,d) : like C "w.dE" format
  variant mode =
    | default of int * int
    | fixed of int * int
    | scientific of int * int
  ;

  //$ Format a real number v with format m.
  fun fmt[t in reals] (v:t, m: mode) =>
    match m with
    | default (w,p) => fmt_default(v,w,p)
    | fixed (w,p) => fmt_fixed(v,w,p)
    | scientific(w,p) => fmt_scientific(v,w,p)
    endmatch
  ;

  //$ Format a complex number v in x + iy form,
  //$ with format m for x and y.
  fun fmt[t,r with Complex[t,r]] (v:t, m: mode) =>
    match m with
    | default (w,p) => fmt_default(real v,w,p) +"+"+fmt_default(imag v,w,p)+"i"
    | fixed (w,p) => fmt_fixed(real v,w,p)+"+"+fmt_fixed(imag v,w,p)+"i"
    | scientific(w,p) => fmt_scientific(real v,w,p)+"+"+fmt_scientific(imag v,w,p)+"i"
    endmatch
  ;

  //$ Format default.
  fun fmt_default[t] : t * int * int -> string="::flx::rtl::strutil::fmt_default($a)" requires package "flx_strutil";

  //$ Format fixed.
  fun fmt_fixed[t] : t * int * int -> string="::flx::rtl::strutil::fmt_fixed($a)" requires package "flx_strutil";

  //$ Format scientfic.
  fun fmt_scientific[t] : t * int * int -> string="::flx::rtl::strutil::fmt_scientific($a)" requires package "flx_strutil";
}

instance Str[float] {
  fun xstr: float -> string = "::flx::rtl::strutil::str<#1>($1)" requires package "flx_strutil";

  //$ Default format float, also supports nan, +inf, -inf.
  noinline fun str(x:float):string =>
    if isnan x then "nan"
    elif isinf x then
      if x > 0.0f then "+inf" else "-inf" endif
    else xstr x
    endif
  ;
}

instance Str[double] {
  fun xstr: double -> string = "::flx::rtl::strutil::str<#1>($1)" requires package "flx_strutil";

  //$ Default format double, also supports nan, +inf, -inf.
  noinline fun str(x:double):string =>
    if isnan x then "nan"
    elif isinf x then
      if x > 0.0 then "+inf" else "-inf" endif
    else xstr x
    endif
  ;
}

instance Str[ldouble] {
  fun xstr: ldouble -> string = "::flx::rtl::strutil::str<#1>($1)" requires package "flx_strutil";

  //$ Default format long double, also supports nan, +inf, -inf.
  noinline fun str(x:ldouble):string =>
    if isnan x then "nan"
    elif isinf x then
      if x > 0.0l then "+inf" else "-inf" endif
    else xstr x
    endif
  ;
}

Conversion operators.

Tiny(class)

tiny(ctor)

Short(class)

short(ctor)

Int(class)

int(ctor)

int(ctor)

int(ctor)

Long(class)

long(ctor)

Vlong(class)

vlong(ctor)

Utiny(class)

utiny(ctor)

Ushort(class)

ushort(ctor)

Uint(class)

uint(ctor)

Ulong(class)

ulong(ctor)

Uvlong(class)

uvlong(ctor)

Int8(class)

int8(ctor)

Int16(class)

int16(ctor)

Int32(class)

int32(ctor)

Int64(class)

int64(ctor)

Uint8(class)

uint8(ctor)

Uint16(class)

uint16(ctor)

Uint32(class)

uint32(ctor)

Uint64(class)

uint64(ctor)

Size(class)

size(ctor)

size(ctor)

Ptrdiff(class)

ptrdiff(ctor)

Intptr(class)

intptr(ctor)

Uintptr(class)

uintptr(ctor)

Intmax(class)

intmax(ctor)

Uintmax(class)

uintmax(ctor)

//[int.flx]
open class Tiny
{
  ctor tiny: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] tiny: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Short
{
  ctor short: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] short: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Int
{
  ctor int: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] int: T = "static_cast<#0>($1)/*int.flx: ctor*/";
  ctor int : int = "($1)/*int.flx: ctor int IDENT*/";
  // special hack
  ctor int(x:bool)=> match x with | true => 1 | false => 0 endmatch;
}

open class Long
{
  ctor long: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] long: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Vlong
{
  ctor vlong: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] vlong: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Utiny
{
  ctor utiny: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] utiny: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Ushort
{
  ctor ushort: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] ushort: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uint
{
  ctor uint: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uint: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Ulong
{
  ctor ulong: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] ulong: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uvlong
{
  ctor uvlong: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uvlong: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Int8
{
  ctor int8: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] int8: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Int16
{
  ctor int16: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] int16: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Int32
{
  ctor int32: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] int32: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Int64
{
  ctor int64: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] int64: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uint8
{
  ctor uint8: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uint8: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uint16
{
  ctor uint16: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uint16: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uint32
{
  ctor uint32: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uint32: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uint64
{
  ctor uint64: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uint64: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Size
{
  ctor size: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] size: T = "static_cast<#0>($1)/*int.flx: ctor size from #0*/";
  ctor size: size = "($1)/*int.flx: ctor size IDENT*/";

  // special overrides so s.len - 1 works
  fun - : size * int -> size = "$1-$2";
  fun + : size * int -> size = "$1+$2";
}

open class Ptrdiff
{
  ctor ptrdiff: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] ptrdiff: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Intptr
{
  ctor intptr: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] intptr: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uintptr
{
  ctor uintptr: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uintptr: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Intmax 
{
  ctor intmax: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] intmax: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

open class Uintmax
{
  ctor uintmax: string = "static_cast<#0>(::std::atoi($1.c_str()))" requires Cxx_headers::cstdlib;
  ctor[T in reals] uintmax: T = "static_cast<#0>($1)/*int.flx: ctor*/";
}

Convert to decimal string.

str(fun)

str(fun)

str(fun)

//[int.flx]
instance Str[tiny] {
  fun str: tiny -> string = "::flx::rtl::strutil::str<int>($1)" requires package "flx_strutil";
}

instance Str[utiny] {
  fun str: utiny -> string = "::flx::rtl::strutil::str<unsigned int>($1)" requires package "flx_strutil";
}

instance
[
  T in 
    short \cup ushort \cup int \cup uint \cup long \cup ulong \cup vlong \cup uvlong \cup 
    exact_ints \cup weird_sints \cup weird_uints
] 
Str[T] 
{
  fun str: T -> string = "::flx::rtl::strutil::str<#1>($1)" requires package "flx_strutil";
}

Convert to lexical string.

//[int.flx]
instance Repr[tiny]   { fun repr[with Str[tiny]]   (t:tiny)   : string => (str t) + "t";  }
instance Repr[short]  { fun repr[with Str[short]]  (t:short)  : string => (str t) + "s";  }
instance Repr[int]   { fun repr[with Str[int]]   (t:int)   : string => (str t) + "";  }
instance Repr[long]   { fun repr[with Str[long]]   (t:long)   : string => (str t) + "l";  }
instance Repr[vlong]  { fun repr[with Str[vlong]]  (t:vlong)  : string => (str t) + "v";  }
instance Repr[int8]  { fun repr[with Str[int8]]  (t:int8)  : string => (str t) + "i8";  }
instance Repr[int16]  { fun repr[with Str[int16]]  (t:int16)  : string => (str t) + "i16";  }
instance Repr[int32]  { fun repr[with Str[int32]]  (t:int32)  : string => (str t) + "i32";  }
instance Repr[int64]  { fun repr[with Str[int64]]  (t:int64)  : string => (str t) + "i64";  }
instance Repr[intmax]  { fun repr[with Str[intmax]]  (t:intmax)  : string => (str t) + "j";  }
instance Repr[intptr]  { fun repr[with Str[intptr]]  (t:intptr)  : string => (str t) + "p";  }
instance Repr[ptrdiff]  { fun repr[with Str[ptrdiff]]  (t:ptrdiff)  : string => (str t) + "d";  }

instance Repr[utiny]  { fun repr[with Str[utiny]]  (t:utiny)  : string => (str t) + "ut"; }
instance Repr[ushort] { fun repr[with Str[ushort]] (t:ushort) : string => (str t) + "us"; }
instance Repr[uint]   { fun repr[with Str[uint]]   (t:uint)   : string => (str t) + "u";  }
instance Repr[ulong]  { fun repr[with Str[ulong]]  (t:ulong)  : string => (str t) + "ul"; }
instance Repr[uvlong] { fun repr[with Str[uvlong]] (t:uvlong) : string => (str t) + "uv"; }
instance Repr[uint8]  { fun repr[with Str[uint8]]  (t:uint8)  : string => (str t) + "u8";  }
instance Repr[uint16]  { fun repr[with Str[uint16]]  (t:uint16)  : string => (str t) + "u16";  }
instance Repr[uint32]  { fun repr[with Str[uint32]]  (t:uint32)  : string => (str t) + "u32";  }
instance Repr[uint64]  { fun repr[with Str[uint64]]  (t:uint64)  : string => (str t) + "u64";  }
instance Repr[size]  { fun repr[with Str[size]]  (t:size)  : string => (str t) + "uz";  }
instance Repr[uintmax]  { fun repr[with Str[uintmax]]  (t:uintmax)  : string => (str t) + "uj";  }
instance Repr[uintptr]  { fun repr[with Str[uintptr]]  (t:uintptr)  : string => (str t) + "up";  }

Methods of integers

succ(fun)

pre_incr(proc)

post_incr(proc)

pred(fun)

pre_decr(proc)

post_decr(proc)

advance(fun)

maxval(fun)

minval(fun)

//[int.flx]
instance[t in ints] Addgrp[t] {}
instance[t in ints] Ring[t] {}
instance[t in ints] MultSemi1[t] {}
instance[t in ints] Dring[t] {}

instance [t in uints] Bits [t] {
  fun \^ : t * t -> t = "(?1)($1^$2)";
  fun \| : t * t -> t = "(?1)($1|$2)";
  fun \& : t * t -> t = "(?1)($1&$2)";

  // note: the cast is essential to ensure ~1tu is 254tu
  fun ~ : t -> t = "(?1)~$1";
  proc ^= : &t * t = "*$1^=$2;";
  proc |= : &t * t = "*$1|=$2;";
  proc &= : &t * t = "*$1&=$2;";
}

instance[t in ints] ForwardSequence[t] {
  fun succ: t -> t = "$1+1";
  proc pre_incr: &t = "++*$1;";
  proc post_incr: &t = "(*$1)++;";
}

instance[t in ints] BidirectionalSequence[t] {
  fun pred: t -> t = "$1-1";
  proc pre_decr: &t = "--*$1;";
  proc post_decr: &t = "(*$1)--;";
}
instance[t in ints] RandomSequence[t] {
  fun advance: int * t -> t = "$1+$2";
}
instance[t in ints] UpperBoundTotalOrder[t] {
  fun maxval: 1 -> t = "::std::numeric_limits<?1>::max()";
}
instance[t in ints] LowerBoundTotalOrder[t] {
  fun minval: 1 -> t = "::std::numeric_limits<?1>::min()";
}

instance[t in ints] Integer[t] {
  fun << : t * t -> t = "$1<<$2";
  fun >> : t * t -> t = "$1>>$2";
}

Methods of signed integers

sgn(fun)

abs(fun)

//[int.flx]
instance[t in sints] Signed_integer[t] {
  fun sgn: t -> int = "$1<0??-1:$1>0??1:0";
  fun abs: t -> t = "$1<0??-$1:$1";
}

Methods of unsigned integers

//[int.flx]
instance[t in uints] Unsigned_integer[t] {}

Make functions accessible without qualification

//[int.flx]
//open[T in sints] Signed_integer[T];
open Signed_integer[tiny];
open Signed_integer[short];
open Signed_integer[int];
open Signed_integer[long];
open Signed_integer[vlong];
open Signed_integer[int8];
open Signed_integer[int16];
open Signed_integer[int32];
open Signed_integer[int64];
open Signed_integer[intmax];
open Signed_integer[ptrdiff];
open Signed_integer[intptr];

//open[T in uints] Unsigned_integer[T];
open Unsigned_integer[utiny];
open Unsigned_integer[ushort];
open Unsigned_integer[uint];
open Unsigned_integer[ulong];
open Unsigned_integer[uvlong];
open Unsigned_integer[uint8];
open Unsigned_integer[uint16];
open Unsigned_integer[uint32];
open Unsigned_integer[uint64];
open Unsigned_integer[uintmax];
open Unsigned_integer[size];
open Unsigned_integer[uintptr];

Quaternions

Quaternion(class)

quaternion(type)

quaternion(ctor)

r(fun)

i(fun)

j(fun)

k(fun)

q(ctor)

conj(fun)

norm(fun)

reciprocal(fun)

//[quaternion.flx]

class Quaternion
{
  type quaternion = new double ^ 4;
  ctor quaternion (x:double^4) => _make_quaternion x;
  private typedef q = quaternion;
  fun r(x:q)=> (_repr_ x) . 0;
  fun i(x:q)=> (_repr_ x) . 1;
  fun j(x:q)=> (_repr_ x) . 2;
  fun k(x:q)=> (_repr_ x) . 3;

  ctor q (x:double) => quaternion (x,0.0,0.0,0.0);

  fun + (a:q,b:q):q =>
    quaternion (a.r+ b.r, a.i + b.i, a.j + b.j, a.k+b.k)
  ;

  fun * (a:q, b:q):q =>
    quaternion (
      a.r * b.r - a.i * b.i - a.j * b.j - a.k * b.k,
      a.r * b.i + a.i * b.r + a.j * b.k - a.k * b.j,
      a.r * b.j - a.i * b.k + a.j * b.r - a.k * b.i,
      a.r * b.k + a.i * b.j - a.j * b.i + a.k * b.r
    )
  ;

  fun conj (a:q):q => quaternion (a.r, -a.i, -a.j, -a.k);
  fun norm (a:q):double => sqrt (a.r * a.r + a.i * a.i + a.j * a.j +a.k * a.k);

  fun * (a:q, b: double):q => quaternion (a.r * b, a.i * b, a.j * b, a.k * b);
  fun * (a: double, b:q):q => a * b;

  fun reciprocal (a:q):q => let n = norm a in conj a * (1.0/ (n * n));

  // add more later, generalise scalar type
  // Later, GET RID of complex and quaternions
  // by introducing typeclasses for arbitrary R-modules
}

Random number generation

Random(class)

//[random.flx]

class Random {
    private type random_device = "::std::random_device*"
        requires Cxx11_headers::random;
    private type random_engine = "::std::default_random_engine*"
        requires Cxx11_headers::random;
    private ctor random_device: 1 = "new ::std::random_device{}";
    private ctor random_engine: random_device =
        "new ::std::default_random_engine{(*$1)()}";
    private gen generate_canonical: random_engine -> double =
        "::std::generate_canonical<double, ::std::numeric_limits<float>::digits>(*$1)"
        requires Cxx_headers::limits;

    private struct random_ctl {
        rd: random_device;
        e: random_engine;
    }
    type random = new random_ctl;
    ctor random() => let rd = #random_device in
                     _make_random$ random_ctl (rd, rd.random_engine);

    private gen range[I in ints]: random_engine * I * I -> I =
        "::std::uniform_int_distribution<decltype($2)>{$2, $3-1}(*$1)";
    gen range[I in ints](r: random)(start: I, stop: I) =>
        range (r._repr_.e, start, stop);
    gen range[I in ints](r: random)(stop: I): I =>
         r.range (C_hack::cast[I] 0, stop);

    gen randint[I in ints with FloatAddgrp[I]](r: random)(start: I, stop: I) =>
        r.range (start, stop+C_hack::cast[I] 1);

    gen choice[T,S with ArrayValue[S,T]](r: random)(seq: S): T =>
        unsafe_get (seq, r.range seq.len);

    gen randflt(r: random) => r._repr_.e.generate_canonical;

    proc shuffle[T,S with ArrayObject[S,T]](r: random)(seq: S) {
        for var i in 0zu upto seq.len - 2 do
            j := r.randint (0zu, i);
            ei := unsafe_get (seq, i);
            ej := unsafe_get (seq, j);
            unsafe_set (seq, i, ej);
            unsafe_set (seq, j, ei);
        done
    }
}