//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// 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>
/// Value operations
/// </summary>
public static partial class val {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static bool IsZero<T>( T val )
where T: struct, IEquatable<T> =>
   val.Equals( default );

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

public static bool IsZeroB<T>( T val )
where T: struct =>
   val.Equals( default );

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

/// <exception cref="ArgumentException" />
[u.failure_as_minus_1]
public static int IndexOf<T>( T val, params T[] values )
where T: struct, IEquatable<T>
{
   u.array_argcheck.ZeroBased( values, nameof(values) );
   for ( int i=0; i<values.Length; i++ )
      if ( val.Equals( values[i] ) )
         return i;
   return -1;
}

/// <exception cref="ArgumentException" />
[u.strict_result]
public static int StrictIndexOf<T>( T val, params T[] values )
where T: struct, IEquatable<T> =>
   u.ops.VerifyArgListIndexOf( IndexOf( val, values ) );

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

/// <exception cref="ArgumentException" />
public static bool IsOneOf<T>( T val, params T[] values )
where T: struct, IEquatable<T> =>
   IndexOf<T>( val, values ) >= 0;

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

public static bool IsBetween<T>( T value, T lowerBound, T upperBound )
where T: struct, IComparable<T> =>
   value.CompareTo( lowerBound )>=0 && value.CompareTo( upperBound )<=0;

public static bool IsExBetween<T>( T value, T lowerBound, T upperBound )
where T: struct, IComparable<T> =>
   value.CompareTo( lowerBound )>0 && value.CompareTo( upperBound )<0;

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

public static T ZeroExchange<T>( ref T location )
where T: struct =>
   u.ops.Exchange<T>( ref location, default );

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

public static T ValueSubst<T>( T value, T comparand, T subst )
where T: struct, IEquatable<T> =>
   value.Equals( comparand ) ? subst : value;

public static T ReplaceValue<T>( ref T location, T comparand, T subst )
where T: struct, IEquatable<T> =>
   location.Equals( comparand ) ? location=subst : location;

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

public static T ReplaceZero<T>( ref T location, T subst )
where T: struct, IEquatable<T>
{
   if ( location.Equals( default ) )
      location = subst;
   return location;
}

public static bool IfReplaceZero<T>( ref T location, T subst )
where T: struct, IEquatable<T>
{
   if ( !location.Equals( default ) )
      return false;
   location = subst;
   return true;
}

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

public static T ReplaceZeroB<T>( ref T location, T subst )
where T: struct
{
   if ( location.Equals( default ) )
      location = subst;
   return location;
}

public static bool IfReplaceZeroB<T>( ref T location, T subst )
where T: struct
{
   if ( !location.Equals( default ) )
      return false;
   location = subst;
   return true;
}

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

public static T Or<T>( params T[] values )
where T: struct, IEquatable<T>
{
   foreach ( T v in values )
      if ( !v.Equals( default ) )
         return v;
   return default;
}

public static T OrB<T>( params T[] values )
where T: struct
{
   foreach ( T v in values )
      if ( !v.Equals( default ) )
         return v;
   return default;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // val

} // user_rtx (.wasm)
