// RuntimeForStatic base library | C+- (SysRoutine) | Author: Sergei Y.Kitáev
#include "Precompiled.h"
#include "SharedIncludes.h"
namespace RuntimeForStatic {
//==================================================================================================

int $CheckInt::Add($A, int v1, int v2 ) $fatal_error_on_failure
{
   int rslt;
   if ( !TryAdd( &rslt, v1, v2 ) )
      $FatalError::RaiseFmt($$CI, $TEXT(
         L"Operation of integer addition has failed: %d + %d.",
         L"Операция целочисленного сложения потерпела неудачу: %d + %d." ),
         v1, v2 );
   return rslt;
}
int $CheckInt::Subtract($A, int v1, int v2 ) $fatal_error_on_failure
{
   int rslt;
   if ( !TrySubtract( &rslt, v1, v2 ) )
      $FatalError::RaiseFmt($$CI, $TEXT(
         L"Operation of integer subtraction has failed: %d - %d.",
         L"Операция целочисленного вычитания потерпела неудачу: %d - %d." ),
         v1, v2 );
   return rslt;
}
int $CheckInt::Multiply($A, int v1, int v2 ) $fatal_error_on_failure
{
   int rslt;
   if ( !TryMultiply( &rslt, v1, v2 ) )
      $FatalError::RaiseFmt($$CI, $TEXT(
         L"Operation of integer multiplication has failed: %d * %d.",
         L"Операция целочисленного умножения потерпела неудачу: %d * %d." ),
         v1, v2 );
   return rslt;
}
int $CheckInt::Divide($A, int v1, int v2 ) $fatal_error_on_failure
{
   int rslt;
   if ( !TryDivide( &rslt, v1, v2 ) )
      $FatalError::RaiseFmt($$CI, $TEXT(
         L"Operation of integer division has failed: %d / %d.",
         L"Операция целочисленного деления потерпела неудачу: %d / %d." ),
         v1, v2 );
   return rslt;
}
int $CheckInt::ChangeSign($A, int v ) $fatal_error_on_failure
{
   int rslt;
   if ( !TryChangeSign( &rslt, v ) )
      $FatalError::RaiseFmt($$CI, $TEXT(
         L"Integer sign change operation of has failed: -%d.",
         L"Целочисленная операция смены знака потерпела неудачу: -%d." ),
         v );
   return rslt;
}
int $CheckInt::Double($A, int v ) $fatal_error_on_failure
{
   int rslt;
   if ( !TryDouble( &rslt, v ) )
      $FatalError::RaiseFmt($$CI, $TEXT(
         L"Operation of integer doubling has failed: %d * 2.",
         L"Операция целочисленного удвоения потерпела неудачу: %d * 2." ),
         v );
   return rslt;
}

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

bool $CheckInt::TryAdd( int* pRes $out $optional, int v1, int v2 )
{
   int r = v1 + v2;
   if ( pRes ) *pRes = r;
   return r - v2 == v1;
}
bool $CheckInt::TrySubtract( int* pRes $out $optional, int v1, int v2 )
{
   int r = v1 - v2;
   if ( pRes ) *pRes = r;
   return r + v2 == v1;
}
bool $CheckInt::TryMultiply( int* pRes $out $optional, int v1, int v2 )
{
   int r = v1 * v2;
   if ( pRes ) *pRes = r;
   return !v1 || !v2 || r / v2 == v1 && r % v2 == 0;
}
bool $CheckInt::TryDivide( int* pRes $out $optional, int v1, int v2 )
{
   int r = v2 ? v1 / v2 : 0;
   if ( pRes ) *pRes = r;
   return v2 && !( v1 == INT_MIN && v2 == -1 );
}
bool $CheckInt::TryChangeSign( int* pRes $out $optional, int v )
{
   int r = -v;
   if ( pRes ) *pRes = r;
   return -r == v;
}
bool $CheckInt::TryDouble( int* pRes $out $optional, int v )
{
   int r = v * 2;
   if ( pRes ) *pRes = r;
   return r / 2 == v;
}

//==================================================================================================
} // RuntimeForStatic
