#line 45 "/home/travis/build/felix-lang/felix/src/packages/numbers.fdoc"

// 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;
}

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] {
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] {
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)"; } 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 ; #line 161 "/home/travis/build/felix-lang/felix/src/packages/numbers.fdoc" 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];