//==============================================================================
//
// long64.c
//
// demo program for 64-bit arithmetic
//
// developer: Henry Guennadi Levkin
//
// for Microsoft compiler use __int64 instead of "long long"
//
//==============================================================================

#include <stdio.h>
#include <string.h>
#include <limits.h>

//------------------------------------------------------------------------------
// 64-bit integer (long long) to string conversion
// version 0.2
void L64toStr(long long n, char* pStr)
{
  int i = 0;
  int m;
  int len;
  char c;
  char s = '+';

  if(n == LONG_LONG_MIN) // _I64_MIN  for Windows Microsoft compiler
  {
    strcpy(pStr,"-9223372036854775808");
    return;
  }

  if( n < 0 )
  {
    s = '-';
    n = - n;
    pStr[0]='-';
    i++;
  }

  do
  {
    m = n % (long long)10;
    pStr[i] = '0'+ m;
    n = n / (long long)10;
    i++;
  }
  while(n != 0);

  if(s == '+')
  {
    len = i;
  }
  else /* s=='-' */
  {
    len = i-1;
    pStr++;
  }

  for(i=0; i<len/2; i++)
  {
    c = pStr[i];
    pStr[i]       = pStr[len-1-i];
    pStr[len-1-i] = c;
  }
  pStr[len] = 0;

  if(s == '-')
  {
    pStr--;
  }
}

//------------------------------------------------------------------------------
// string to 64-bit integer conversion
// version 0.2
int StrtoL64(char* pStr, long long* pN)
{
  int i;
  int len = strlen(pStr);
  char s = pStr[0];

  *pN = 0;

  if(s == '-')
  {
    pStr++;
    len--;
  }

  for(i=0; i<len; i++)
  {
    if(pStr[i]>='0'  &&  pStr[i]<='9')
    {
      *pN = (*pN)*(long long)10 + (pStr[i]-'0');
    }
    else
    {
      return 1;
    }
  }

  if(s == '-')
  {
    pStr--;
    (*pN) = - (*pN);
  }

  return 0;
}

//------------------------------------------------------------------------------
int main(int nArgs, char** ppArg)
{
  long long n, m, nm;
  char str[128];
  int i;

  // 64-bit integers input
  printf("n= ");
  scanf("%s", str);
  StrtoL64(str, &n);

  printf("m= ");
  scanf("%s", str);
  StrtoL64(str, &m);

  // multiplication
  nm = n * m;
  L64toStr(nm, str);
  printf("n * m = %s\n", str);

  // division
  nm = n / m;
  L64toStr(nm, str);
  printf("n / m = %s\n", str);

  nm = n % m;
  L64toStr(nm, str);
  printf("n %% m = %s\n", str);
  
  nm = 9223372036854775807LL;
  L64toStr(nm, str);
  printf("LONG_LONG_MAX = %s\n", str);

  //---------------------------
  printf("powers of two table:\n");
  n = 1;
  for(i=1; i<63; i++)
  {
    printf("%d ",i);
    n = n << 1;
    L64toStr(n, str);
    printf("%s\n", str);
  }

  //---------------------------
  printf("factorial table:\n");
  n = 1;
  for(i=1; i<21; i++)
  {
    printf("%d ",i);
    n = n * (long long)i;
    L64toStr(n, str);
    printf("%s\n", str);
  }

  return 0;
}

