//
// Math operation structures produced with the help of T4 (Maths.tt)
// NOTE: THIS CODE HAS NOT BEEN WELL-TESTED AND DOES NOT YET HAVE A TEST SUITE.
//
<#@ template language="C#" #>
<#@ output extension="cs" #>
<#@ include file="NumTraits.ttinclude" #>
using System.Collections.Generic;
<# foreach(Traits T in _traits) { #>
namespace Loyc.Math
{
using System;
using T = <#=T.QualifiedName#>;
public struct <#=T.MathType#> : <#=T.Interfaces#>
{
public static readonly <#=T.MathType#> Value = new <#=T.MathType#>();
#region INumTraits
public T MinValue { get { return T.MinValue; } }
public T MaxValue { get { return T.MaxValue; } }
public T Epsilon { get { return <#=T.Epsilon#>; } }
public T PositiveInfinity { get { return <#=T.PositiveInfinity#>; } }
public T NegativeInfinity { get { <#=T.ReturnNegativeInfinity#>; } }
public T NaN { get { <#=T.ReturnNaN#>; } }
public bool IsInfinity(T value) { return <#=T.IsInfinity#>; }
public bool IsNaN(T value) { return <#=T.IsNaN#>; }
public bool IsSigned { get { return <#=T.IsSigned?"true":"false"#>; } }
public bool IsFloatingPoint { get { return <#=T.IsFloat?"true":"false"#>; } }
public bool IsInteger { get { return <#=T.IsInt?"true":"false"#>; } }
public bool IsOrdered { get { return true; } }
public int SignificantBits { get { return <#=T.SignificantBits#>; } }
public int MaxIntPowerOf2 { get { return <#=T.WholeBits#>; } }
public ulong MaxInt { get { return (ulong)<#=T.MaxInt()#>; } }
public long MinInt { get { return (long)<#=T.MinInt()#>; } }
public T Zero { get { return <#=T.Zero()#>; } }
public T One { get { return <#=T.One()#>; } }
#endregion
#region <#= T.IsSigned ? "ISignedMath" : "IMath" #>
<# if (T.IsFixed) { #>
public T From(uint t) { return T.FastCast(t); }
public T From(int t) { return T.FastCast(t); }
public T From(ulong t) { return T.FastCast((long)t); }
public T From(long t) { return T.FastCast(t); }
public T From(double t) { return T.FastCast(t); }
public T Clip(uint t) { return new T(t); }
public T Clip(int t) { return new T(t); }
public T Clip(ulong t) { return new T(t); }
public T Clip(long t) { return new T(t); }
public T Clip(double t) { return new T(t); }
<# } else { #>
public T From(uint t) { return (T)t; }
public T From(int t) { return (T)t; }
public T From(ulong t) { return (T)t; }
public T From(long t) { return (T)t; }
public T From(double t) { return (T)t; }
<# if (T.IsFloat) { #>
public T Clip(uint t) { return (T)t; }
public T Clip(int t) { return (T)t; }
public T Clip(ulong t) { return (T)t; }
public T Clip(long t) { return (T)t; }
public T Clip(double t) { return (T)t; }
<# } else { #>
public T Clip(uint t) { return<#if(T.WholeBits<32){#> t > (uint)T.MaxValue ? T.MaxValue : <#}#>(T)t; }
public T Clip(ulong t) { return<#if(T.WholeBits<64){#> t > (ulong)T.MaxValue ? T.MaxValue : <#}#>(T)t; }
public T Clip(int t) { return<#if(T.WholeBits<31){#> t > (int)T.MaxValue ? T.MaxValue : <#}#>
<#if(!T.IsSigned||T.WholeBits<31){#> t < (int)T.MinValue ? T.MinValue : <#}#>(T)t; }
public T Clip(long t) { return<#if(T.WholeBits<63){#> t > (long)T.MaxValue ? T.MaxValue : <#}#>
<#if(!T.IsSigned||T.WholeBits<63){#> t < (long)T.MinValue ? T.MinValue : <#}#>(T)t; }
public T Clip(double t) { return (T)MathEx.InRange(t, (double)0, (double)T.MaxValue); }
<# } #>
<# } #>
public bool IsLess(T a, T b) { return a < b; }
public bool IsLessOrEqual(T a, T b) { return a <= b; }
public T Abs(T a) { return <#=T.Abs()#>; }
public T Max(T a, T b) { return a > b ? a : b; }
public T Min(T a, T b) { return a < b ? a : b; }
public int Compare(T x, T y) { return x.CompareTo(y); }
public bool Equals(T x, T y) { return x == y; }
public int GetHashCode(T x) { return x.GetHashCode(); }
public T Incremented(T a) { a++; return a; }
public T Decremented(T a) { a--; return a; }
<# if (T.IsFloat) { #>
public T NextHigher(T a) { return MathEx.NextHigher(a); }
public T NextLower(T a) { return MathEx.NextLower(a); }
<# } else { #>
public T NextHigher(T a) { a++; return a; }
public T NextLower(T a) { a--; return a; }
<# } #>
public T Add(T a, T b) { return (T)(a + b); }
public T Subtract(T a, T b) { return (T)(a - b); }
public T Multiply(T a, T b) { return (T)(a * b); }
public T Divide(T a, T b) { return (T)(a / b); }
public T MulDiv(T a, T mul, T div) { return (T)<#=T.MulDiv("a", "mul", "div")#>; }
<# if (!T.IsInt) { #>
public T Reciprocal(T a) { return One / a; }
<# } #>
<# if (T.IsSigned) { #>
public T Negate(T a) { return (T)(-a); }
<# } #>
public T ShiftLeft(T a, int amount) { return <#=T.ShiftLeft()#>; }
public T ShiftRight(T a, int amount) { return <#=T.ShiftRight()#>; }
public T Sqrt(T a) { return <#=T.Sqrt()#>; }
public T Square(T a) { return (T)(a * a); }
#endregion
<# if (T.IsInt || T.IsFixed) { #>
#region BinaryMath
public T And(T a, T b) { return (T)(a & b); }
public T Or(T a, T b) { return (T)(a | b); }
public T Xor(T a, T b) { return (T)(a ^ b); }
public T Not(T a) { return (T)~a; }
public int CountOnes(T a) { return <#=T.CountOnes()#>; }
public int Log2Floor(T a) { return <#=T.Log2Floor()#>; }
#endregion
<# } else if (T.IsFloat) { #>
#region ITrigonometry & IExp Members
public T Asin(T a) { return (T)Math.Asin(a); }
public T Acos(T a) { return (T)Math.Acos(a); }
public T Atan(T a) { return (T)Math.Atan(a); }
public T Atan2(T y, T x) { return (T)Math.Atan2(y, x); }
public T Sin(T a) { return (T)Math.Sin(a); }
public T Cos(T a) { return (T)Math.Cos(a); }
public T Tan(T a) { return (T)Math.Tan(a); }
public T Exp(T a) { return (T)Math.Exp(a); }
public T Pow(T @base, T exponent) { return (T)Math.Pow(@base, exponent); }
public T Ln(T a) { return (T)Math.Log(a); }
#if CompactFramework
public T Log(T a, T @base) { return (T)(Math.Log(a) / Math.Log(@base)); }
#else
public T Log(T a, T @base) { return (T)Math.Log(a, @base); }
#endif
#endregion
<# } #>
}
}
<# } #>