//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / COMMON
//
//File: moduloint.cpp
//
//Version: $Revision: 1.7 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/04 16:22:11 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications and Multimedia
//
//Author:
//      Juhana Räsänen
//
//Description:
//      See corresponding header file
//
//Copyright:
//
//
//Licence:
//
//
//History: 


#include <assert.h>
#include <limits.h>
#include "pf/debug.h"
#include "moduloint.h"


//
// Function: moduloInteger constructor
//
// Description:
//     Constructor initializes moduloInteger by setting value to 0
//     and checking modulus supplied by user. Modulus must be >= 1
//     (although ints modulo 1 make little sense...) and < ULONG_MAX/2.
//     Upper limit cannot be ULONG_MAX for the class to function
//     properly, consider eg. case:
//           ((ULONG_MAX-2) + (ULONG_MAX-2)) % (ULONG_MAX-1)
//     (Temporary) variable holding the sum before modulo operator
//     will overflow and result will be nonsense.
//

moduloInteger :: moduloInteger(unsigned long modulus_)
    : _value(0)
{
    assert((modulus_ > 0) && (modulus_ < (ULONG_MAX / 2)));
    _modulus = modulus_;
    return;
}


moduloInteger :: moduloInteger(const moduloInteger &other_)
    : _value(other_._value),
      _modulus(other_._modulus)
{
    return;
}


moduloInteger :: ~moduloInteger(void)
{
    return;
}


//
// Functions: moduloInteger :: getValue
//            moduloInteger :: getModulus
//
// Description:
//     Get methods for moduloInteger attributes.
//

unsigned long moduloInteger :: getValue(void) const
{
    return _value;
}


unsigned long moduloInteger :: getModulus(void) const
{
    return _modulus;
}


//
// Functions: moduloInteger :: operator=
//            moduloInteger :: operator==
//            moduloInteger :: operator!=
//            moduloInteger :: operator<
//            moduloInteger :: operator>
//            moduloInteger :: operator<=
//            moduloInteger :: operator>=
//            moduloInteger :: operator+
//            moduloInteger :: operator-
//            moduloInteger :: operator+=
//            moduloInteger :: operator-=
//            moduloInteger :: operator++
//            moduloInteger :: operator--
//
// Description:
//     Some arithmetic operators for moduloIntegers. Some operators
//     return numeric value (unsigned long) of the moduloInteger
//     (instead of const reference).
//     Functionality of + and - operators is defined only once (in
//     operator+(unsigned long) and operator-(unsigned long)), other
//     variations of these operators call those versions.
//

const moduloInteger & moduloInteger :: operator=(unsigned long value_)
{
    _value = (value_ % _modulus);
    return *this;
}


const moduloInteger & moduloInteger :: operator=(const moduloInteger &other_)
{
    _value = other_._value;
    _modulus = other_._modulus;
    return *this;
}


int moduloInteger :: operator==(unsigned long value_) const
{
    int isEqual = (_value == value_);
    return isEqual;
}


int moduloInteger :: operator==(const moduloInteger &other_) const
{
    int isEqual = ((_value == other_._value) &&
                   (_modulus == other_._modulus));
    return isEqual;
}


int moduloInteger :: operator!=(unsigned long value_) const
{
    int isNotEqual = (_value != value_);
    return isNotEqual;
}


int moduloInteger :: operator!=(const moduloInteger &other_) const
{
    int isNotEqual = ((_value != other_._value) ||
                      (_modulus != other_._modulus));
    return isNotEqual;
}


int moduloInteger :: operator<(unsigned long value_) const
{
    int isSmallerThan = _value < value_;
    return isSmallerThan;
}


int moduloInteger :: operator<(const moduloInteger &other_) const
{
    int isSmallerThan = _value < other_._value;
    return isSmallerThan;
}


int moduloInteger :: operator>(unsigned long value_) const
{
    int isGreaterThan = _value > value_;
    return isGreaterThan;
}


int moduloInteger :: operator>(const moduloInteger &other_) const
{
    int isGreaterThan = _value > other_._value;
    return isGreaterThan;
}


int moduloInteger :: operator<=(unsigned long value_) const
{
    int isSmallerOrEqual = ((this->operator<(value_)) ||
                            (this->operator==(value_)));
    return isSmallerOrEqual;
}


int moduloInteger :: operator<=(const moduloInteger &other_) const
{
    int isSmallerOrEqual = ((this->operator<(other_)) ||
                            (this->operator==(other_)));
    return isSmallerOrEqual;
}


int moduloInteger :: operator>=(unsigned long value_) const
{
    int isGreaterOrEqual = ((this->operator>(value_)) ||
                            (this->operator==(value_)));
    return isGreaterOrEqual;
}


int moduloInteger :: operator>=(const moduloInteger &other_) const
{
    int isGreaterOrEqual = ((this->operator>(other_)) ||
                            (this->operator==(other_)));
    return isGreaterOrEqual;
}


unsigned long moduloInteger :: operator+(unsigned long value_) const
{
    unsigned long retval = ((_value + (value_ % _modulus)) % _modulus);
    return retval;
}


unsigned long moduloInteger :: operator+(const moduloInteger &other_) const
{
    unsigned long retval = this->operator+(other_._value);
    return retval;
}


unsigned long moduloInteger :: operator-(unsigned long value_) const
{
    // Note the semantics of substraction: moduloIntegers are meant
    // to be unsigned longs with a modulus. When value would become
    // -1, it will get to modulus-1.

    unsigned long value = value_ % _modulus;
    unsigned long retval = 0;
    if (value > _value)
    {
        retval = _modulus - (value - _value);
    }
    else
    {
        retval = _value - value;
    }
    return retval;
}


unsigned long moduloInteger :: operator-(const moduloInteger &other_) const
{
    unsigned long retval = this->operator-(other_._value);
    return retval;
}


unsigned long moduloInteger :: operator+=(unsigned long value_)
{
    _value = this->operator+(value_);
    return _value;
}


unsigned long moduloInteger :: operator+=(const moduloInteger &other_)
{
    _value = this->operator+(other_._value);
    return _value;
}


unsigned long moduloInteger :: operator-=(unsigned long value_)
{
    _value = this->operator-(value_);
    return _value;
}


unsigned long moduloInteger :: operator-=(const moduloInteger &other_)
{
    _value = this->operator-(other_._value);
    return _value;
}


unsigned long moduloInteger :: operator++(void)
{
    _value = ((++_value) % _modulus);
    return _value;
}


unsigned long moduloInteger :: operator--(void)
{
    if (_value == 0)
    {
        _value = _modulus - 1;
    }
    else
    {
        _value--;
    }
    return _value;
}


unsigned long moduloInteger :: operator++(int)
{
    unsigned long saved = _value;
    this->operator++();
    return saved;
}


unsigned long moduloInteger :: operator--(int)
{
    unsigned long saved = _value;
    this->operator--();
    return saved;
}


int moduloInteger :: compareWithBase(
    const moduloInteger &left_,
    const moduloInteger &right_,
    const moduloInteger &base_)
{
    int retval = 0;

    int base = base_._value;
    int left = left_._value;
    int right = right_._value;

#if 0
    debugUser("compareWithBase");
    debugPfUlong("base", base);
    debugPfUlong("left", left);
    debugPfUlong("right", right);
#endif

    int lvalue = ((left - base) & 0xffffff);
    int rvalue = ((right - base) & 0xffffff);

    if (lvalue != rvalue)
    {
#if 0
    if (left_ != right_)
    {
        moduloInteger leftNorm(left_);
        leftNorm -= base_;
        moduloInteger rightNorm(right_);
        rightNorm -= base_;
        if (leftNorm._value  < rightNorm._value)

        if (((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)))
#endif
	if (lvalue < rvalue)
        {
            retval = -1;
        }
        else
        {
            retval = 1;
        }
    }
#if 0
    debugPfUlong("return", retval);
#endif
    return retval;
}


// These functions can't be member functions, so they are defined
// as friend functions. They are needed to ensure that operators work
// properly in both moduloInteger + ulong and ulong + moduloInteger
// cases.

unsigned long operator+(unsigned long lhs_, const moduloInteger &rhs_)
{
    unsigned long retval = rhs_.operator+(lhs_);
    return retval;
}


unsigned long operator-(unsigned long lhs_, const moduloInteger &rhs_)
{
    unsigned long retval = rhs_.operator-(lhs_);
    return retval;
}


int operator==(unsigned long lhs_, const moduloInteger &rhs_)
{
    int isEqual = rhs_.operator==(lhs_);
    return isEqual;
}


int operator!=(unsigned long lhs_, const moduloInteger &rhs_)
{
    int isNotEqual = rhs_.operator!=(lhs_);
    return isNotEqual;
}


int operator<(unsigned long lhs_, const moduloInteger &rhs_)
{
    int isSmallerThan = rhs_.operator<(lhs_);
    return isSmallerThan;
}


int operator>(unsigned long lhs_, const moduloInteger &rhs_)
{
    int isGreaterThan = rhs_.operator>(lhs_);
    return isGreaterThan;
}


int operator<=(unsigned long lhs_, const moduloInteger &rhs_)
{
    int isSmallerOrEqual = rhs_.operator<=(lhs_);
    return isSmallerOrEqual;
}


int operator>=(unsigned long lhs_, const moduloInteger &rhs_)
{
    int isGreaterOrEqual = rhs_.operator>=(lhs_);
    return isGreaterOrEqual;
}
