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.¶
//[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.
//[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.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.¶
//[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.¶
//[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¶
//[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¶
//[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.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.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
}
}