//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// UserRTX.NET satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;

#if !WASM
namespace user_rtx { using u = user_rtx;
#else
namespace user_rtx.wasm { using u = user_rtx.wasm;
#endif

/// <summary>
/// Mathematical operations (floating point, fixed point)
/// </summary>
public static partial class math {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static double NaNAsZero( double x ) =>
   double.IsNaN( x ) ? 0 : x;

//==================================================================================================

public static double Sign( double x )
{
   if ( x > 0 ) return  1d;
   if ( x < 0 ) return -1d;
   return 0;
}
public static decimal Sign( decimal x )
{
   if ( x > 0 ) return  1m;
   if ( x < 0 ) return -1m;
   return 0;
}

//--------------------------------------------------------------------------------------------------

public static int IntSign( double x )
{
   if ( x > 0 ) return  1;
   if ( x < 0 ) return -1;
   return 0;
}
public static int IntSign( decimal x )
{
   if ( x > 0 ) return  1;
   if ( x < 0 ) return -1;
   return 0;
}

//--------------------------------------------------------------------------------------------------

public static bool HaveSameSign( double x, double y ) =>
   Sign( x ) * Sign( y ) >= 0;

public static bool HaveSameSign( decimal x, decimal y ) =>
   Sign( x ) * Sign( y ) >= 0;

//==================================================================================================

public static double FractionalPart( double value ) =>
   value - Math.Truncate( value );

public static decimal FractionalPart( decimal value ) =>
   value - Math.Truncate( value );

//--------------------------------------------------------------------------------------------------

public static bool HasFractionalPart( double value ) =>
   FractionalPart( value ) != 0;

public static bool HasFractionalPart( decimal value ) =>
   FractionalPart( value ) != 0;

//==================================================================================================

public static double DoubleDiv( double x, double y ) =>
   x / y;

public static decimal DecimalDiv( decimal x, decimal y ) =>
   x / y;

//==================================================================================================

public static double RoundUp( double value )
{
   if ( double.IsNaN( value ) )
      return double.NaN;
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ? trunc+1 : trunc;
}

public static double RoundDown( double value )
{
   if ( double.IsNaN( value ) )
      return double.NaN;
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ? trunc-1 : trunc;
}

public static double RoundFromZero( double value )
{
   if ( double.IsNaN( value ) )
      return double.NaN;
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ?
      value >= 0 ? trunc+1 : trunc-1 :
      trunc;
}

public static double RoundToZero( double value )
{
   if ( double.IsNaN( value ) )
      return double.NaN;
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ?
      value == 0 ? 0 : value > 0 ? trunc-1 : trunc+1 :
      trunc;
}

//--------------------------------------------------------------------------------------------------

public static decimal RoundUp( decimal value )
{
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ? trunc+1 : trunc;
}

public static decimal RoundDown( decimal value )
{
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ? trunc-1 : trunc;
}

public static decimal RoundFromZero( decimal value )
{
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ?
      value >= 0 ? trunc+1 : trunc-1 :
      trunc;
}

public static decimal RoundToZero( decimal value )
{
   var trunc = Math.Truncate( value );
   return HasFractionalPart( value ) ?
      value == 0 ? 0 : value > 0 ? trunc-1 : trunc+1 :
      trunc;
}

//==================================================================================================

/// <exception cref="ArgumentOutOfRangeException" />
static double DoubleValueArg( double value ) =>
   u.math_argcheck.Number( value, nameof(value) );

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // math

} // user_rtx (.wasm)
