/*********************************************************
** Copyright (c) 2005
** University of Washington
** Licensed under the terms set forth by University of
** Washington. If you did not sign such a license, you
** are using this software/code illegally and you do not
** have permission to use, modify, or redistribute
** this or any files in this software package.
**
** File: SafeInt.h
**
**********************************************************/
#ifndef SAFEINT_H
#define SAFEINT_H

#include <stdint.h>
#include <stdexcept>
using namespace std;

template<typename inttype>
class CSafeInt
{
 public:
  static inttype Add(inttype a, inttype b)
  {
    inttype c = a + b;
    if(c < a || c < b)
      throw new out_of_range("Add argument out of range");
    return c;
  }
  
  static inttype Subtract(inttype a, inttype b)
  {
    if (b > a)
      throw new out_of_range("Subtract argument out of range");
    return a - b;
  }
  
  static inttype Multiply(inttype a, inttype b)
  {
    if (0 == a || 0 == b)
      return 0;
  
    inttype c = a*b;
    if(c < a || c < b)
      throw new out_of_range("Multiply argument out of range");
  
    return c;
  }
  
  static inttype Divide(inttype a, inttype b)
  {
    if (b == 0)
      throw new out_of_range("Divide argument out of range");
    return a / b;
  }
  
  static inttype Mod(inttype a, inttype b)
  {
    if (b == 0)
      throw new out_of_range("Mod argument out of range");
    return a % b;
  }
};

typedef CSafeInt<uintmax_t> CSafeUIntMax;
#endif
