<vint>
 
/*
    Hamilton Project/ Hamilton bat 1
    Copyright (C) 2009  The group of Hamiltonian Contributors
 
    This software belongs to Hamilton Project, and automatically inherit
    every property of Hamilton Project, including GNU Lesser General Public
    License.
 
    The group of Hamiltonian Contributors is the group of contributors of
    each software under Hamilton Project. For each software, you can check
    the contributors.
 
    You can see the details of Hamilton Project in the document that should
    be attached with this program maybe named "HAMILTON LICENSE".
 
 
    Hamilton Project is free software group: you can redistribute
    and/or modify a software under Hamilton Project, under the terms of
    the GNU Lesser General Public License version 3 as published by
    the Free Software Foundation.
 
    A software under Hamilton Project is distributed in the hope that it will
    be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program as a file named "COPYING", and a copy of
    the GNU Lesser General Public License along with this program
    as a file named "COPYING LESSER" If not, see <http://www.gnu.org/licenses/>.
 
 
    /vint
    Contributor: Albert Rim
*/
 
#ifndef H_VINT
#define H_VINT
 
 
#include <iostream>
#include <vector>
#include <string>
#include <limits>
 
template <class _MyClass>
_MyClass max(const _MyClass& op1, const _MyClass& op2){
	return (op1 < op2)? op2:op1;
}
 
template <class _MyClass>
_MyClass min(const _MyClass& op1, const _MyClass& op2){
	return (op1 < op2)? op1: op2;
}
 
//template <class _MyClass>
//defined bool operator == (const _MyClass& op1, const _MyClass& op2);
//defined bool operator < (const _MyClass& op1, const _MyClass& op2);
 
template <class _MyClass>
bool operator != (const _MyClass& op1, const _MyClass& op2){
	return !(op1 == op2);
}
 
template <class _MyClass>
bool operator > (const _MyClass& op1, const _MyClass& op2){
	return op2 < op1;
}
 
template <class _MyClass>
bool operator <= (const _MyClass& op1, const _MyClass& op2){
	return (op1 == op2) || (op1 < op2);
}
 
template <class _MyClass>
bool operator >= (const _MyClass& op1, const _MyClass& op2){
	return (op1 == op2) || (op1 > op2);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
class vint{
private:
	std::vector<unsigned char> data;
protected:
	bool is_negative() const;
	bool is_reduceable() const;
	void sz_expand() throw (int);
	void sz_expand_until(const _Byte_size_type&);
	void sz_reduce() throw (int);
	void sz_reduce_min();
	bool is_bit(const _Bit_size_type&) const;
	_Bit_size_type effdigit() const;
 
public:
	vint();
	vint(const vint&);
	explicit vint(const std::vector<char>&);
	explicit vint(const std::vector<unsigned char>&);
	explicit vint(const int&);
	explicit vint(const unsigned int&);
	operator bool () const;
	_Byte_size_type size() const;
 
	bool operator == (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	bool operator < (const vint<_Bit_size_type,_Byte_size_type>& op) const;
 
	vint<_Bit_size_type,_Byte_size_type>& operator = (const vint<_Bit_size_type,_Byte_size_type>& op);
	vint<_Bit_size_type,_Byte_size_type>& operator += (const vint<_Bit_size_type,_Byte_size_type>& op);
	vint<_Bit_size_type,_Byte_size_type>& operator ++();
	vint<_Bit_size_type,_Byte_size_type> operator ~() const;
	vint<_Bit_size_type,_Byte_size_type> operator -() const;
	vint<_Bit_size_type,_Byte_size_type>& operator -= (const vint<_Bit_size_type,_Byte_size_type>& op);
	vint<_Bit_size_type,_Byte_size_type>& operator --();
	vint<_Bit_size_type,_Byte_size_type>& operator ++ (int dummy);
	vint<_Bit_size_type,_Byte_size_type>& operator -- (int dummy);
 
	vint vint::operator << (_Bit_size_type) const;
	vint vint::operator >> (_Bit_size_type) const;
	vint& vint::operator <<= (_Bit_size_type _Size) {return operator = (operator << (_Size));}
	vint& vint::operator >>= (_Bit_size_type _Size) {return operator = (operator >> (_Size));}
 
	vint<_Bit_size_type,_Byte_size_type> abs() const;
 
	vint<_Bit_size_type,_Byte_size_type> operator & (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	vint<_Bit_size_type,_Byte_size_type> operator | (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	vint<_Bit_size_type,_Byte_size_type> operator ^ (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	vint<_Bit_size_type,_Byte_size_type>& operator &= (const vint<_Bit_size_type,_Byte_size_type>& op);
	vint<_Bit_size_type,_Byte_size_type>& operator |= (const vint<_Bit_size_type,_Byte_size_type>& op);
	vint<_Bit_size_type,_Byte_size_type>& operator ^= (const vint<_Bit_size_type,_Byte_size_type>& op);
 
	vint<_Bit_size_type,_Byte_size_type> operator * (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	vint<_Bit_size_type,_Byte_size_type> operator / (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	vint<_Bit_size_type,_Byte_size_type>& operator *= (const vint<_Bit_size_type,_Byte_size_type>& op){return operator = (operator * (op));}
	vint<_Bit_size_type,_Byte_size_type>& operator /= (const vint<_Bit_size_type,_Byte_size_type>& op){return operator = (operator / (op));}
	vint<_Bit_size_type,_Byte_size_type> operator % (const vint<_Bit_size_type,_Byte_size_type>& op) const;
	vint<_Bit_size_type,_Byte_size_type>& operator %= (const vint<_Bit_size_type,_Byte_size_type>& op);
 
	void input(const std::string& str);
	std::string output() const;
};
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> operator + (const vint<_Bit_size_type,_Byte_size_type>& op1, const vint<_Bit_size_type,_Byte_size_type>& op2);
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> operator - (const vint<_Bit_size_type,_Byte_size_type>& op1, const vint<_Bit_size_type,_Byte_size_type>& op2);
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::vint(): data(2){
	data[0] = 0;
	data[1] = 0;
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::vint(const vint& op): data(op.data){
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::vint(const std::vector<unsigned char>& op): data(op){
	sz_reduce_min();
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::vint(const std::vector<char>& op): data(op.size()){
	for (size_t i = 0; i < op.size(); i++)
		data[i] = static_cast<unsigned char>(op[i]);
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::vint(const int& op): data(sizeof(int)){
	int temp = op;
	for (size_t i = 0; i < sizeof(int); i++){
		data[i] = static_cast<unsigned char>(temp);
		temp >>= 8;
	}
	sz_reduce_min();
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::vint(const unsigned int& op): data(sizeof(unsigned int) +1){
	unsigned temp = op;
	for (size_t i = 0; i < sizeof(int); i++){
		data[i] = static_cast<unsigned char>(temp);
		temp >>= 8;
	}
	data.back() = 0;
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>::operator bool () const{
	return ((*this) != vint(0));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
bool vint<_Bit_size_type,_Byte_size_type>::is_negative() const{
	return (data.back() >= 128);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
bool vint<_Bit_size_type,_Byte_size_type>::is_reduceable() const{
	if (data.size() <= 2) return false;
	if (data.back() == 255 && data[data.size() - 2] >= 128)
		return true;
	else if (data.back() == 0 && data[data.size() - 2] < 128){
		return true;
	} else return false;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
void vint<_Bit_size_type,_Byte_size_type>::sz_expand() throw (int){
	if (size() == std::numeric_limits<_Byte_size_type>::max()) throw 1;
	if (is_negative()) data.push_back(255);
	else	data.push_back(0);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
void vint<_Bit_size_type,_Byte_size_type>::sz_expand_until(const _Byte_size_type& _Size){
	while(size() < _Size)	sz_expand();
	return;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
void vint<_Bit_size_type,_Byte_size_type>::sz_reduce() throw (int){
	if (!is_reduceable()) throw 1;
	data.pop_back();
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
void vint<_Bit_size_type,_Byte_size_type>::sz_reduce_min(){
	while (is_reduceable()) sz_reduce();
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
_Byte_size_type vint<_Bit_size_type,_Byte_size_type>::size() const{
	return data.size();
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
bool vint<_Bit_size_type,_Byte_size_type>::is_bit(const _Bit_size_type& pos) const{
	if (pos >= size()*8) return is_negative();
	else
		return ((data[pos/8] >> (pos % 8)) % 2);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
_Bit_size_type vint<_Bit_size_type,_Byte_size_type>::effdigit() const{
	for (size_t i = 0; i < size()*8; i++)
		if (is_negative() ^ is_bit(size()*8 - i - 1))
			return size()*8 - i;
	return 0;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
bool vint<_Bit_size_type,_Byte_size_type>::operator == (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	if (size() != op.size()) return false;
	for (size_t i = 0; i < size(); i++)
		if (data[i] != op.data[i]) return false;
	return true;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
bool vint<_Bit_size_type,_Byte_size_type>::operator <(const vint<_Bit_size_type,_Byte_size_type>& op) const{
	if (is_negative() && !op.is_negative()) return true;
	if (!is_negative() && op.is_negative()) return false;
	_Byte_size_type maxsize = max(size(),op.size())*8;
	for (_Byte_size_type i = 0; i < maxsize; i++){
		if (!is_bit(maxsize - i - 1) && op.is_bit(maxsize - i - 1))
			return true;
		else if (is_bit(maxsize - i - 1) && !op.is_bit(maxsize - i - 1))
			return false;
	}
	return false;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator = (const vint<_Bit_size_type,_Byte_size_type>& op){
	data.operator=(op.data);
	return (*this);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator+= (const vint<_Bit_size_type,_Byte_size_type>& op){
	vint temp2(op);
	if (is_negative()^temp2.is_negative()){
		sz_expand_until(max(size(), temp2.size()));
		temp2.sz_expand_until(size());
	}else{
		sz_expand_until(max(size(), temp2.size())+1);
		temp2.sz_expand_until(size());
	}
	char roundup = 0;
	for (size_t i = 0; i < size(); i++){
		data[i] += roundup;
		if (data[i] == 0 && roundup == 1) roundup = 1;
		else roundup = 0;
		if (static_cast<unsigned char>(255) - data[i] < temp2.data[i]) roundup = 1;
		data[i] += temp2.data[i];
	}
	sz_reduce_min();
	return (*this);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator ++ (){
	return operator += (vint<_Bit_size_type,_Byte_size_type>(1));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator~() const{
	vint temp(*this);
	for (size_t i = 0; i < size(); i++)
		temp.data[i] = ~(temp.data[i]);
	return temp;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator - () const{
	return operator ~ ().operator ++();
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator -= (const vint<_Bit_size_type,_Byte_size_type>& op){
	return operator += (-op);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator -- (){
	return operator -= (vint(1));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator ++ (int dummy){
	return operator ++();
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator -- (int dummy){
	return operator--();
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator << (_Bit_size_type _Size) const{
	vint<_Bit_size_type,_Byte_size_type> temp(*this);
	for (_Byte_size_type i = 0; i < _Size/8; i++){
		temp.sz_expand();
		temp.data[i] = 0;
	}
	for (size_t i = 0; i < size(); i++)
		temp.data[i+ size_t(_Size/8)] = data[i];
	temp.sz_expand();
	for (_Bit_size_type i = 0; i < _Size%8; i++){
		bool roundup = false;
		for (size_t j = _Size/8; j < temp.size(); j++){
			bool tempround = (temp.data[j]>=128);
			temp.data[j] <<= 1;
			if (roundup) temp.data[j]++;
			roundup = tempround;
		}
	}
	temp.sz_reduce_min();
	return temp;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator >> (_Bit_size_type _Size) const{
	vint<_Bit_size_type,_Byte_size_type> temp(*this);
	for (_Byte_size_type i = 0; i < _Size/8; i++)
		temp.sz_reduce();
	for (_Byte_size_type i = _Size/8; i <size(); i++)
		temp.data[i - _Size/8] = data[i];
	for (_Bit_size_type i = 0; i < _Size % 8; i++){
		for (_Byte_size_type j = 0; j < temp.size(); j++){
			if (j > 0){
				if ((temp.data[j] % 2 == 0) && (temp.data[j - 1] >= 128))
					temp.data[j - 1] -= 128;
				else if ((temp.data[j] % 2 == 1) && (temp.data[j - 1] < 128))
					temp.data[j - 1] += 128;
			}
			temp.data[j] >>= 1;
		}
		if (temp.data.back() % 128 >= 64 && temp.data.back() < 128) 
			temp.data.back() += 128;
		if (temp.data.back() % 128 < 64 && temp.data.back() >= 128) 
			temp.data.back() -= 128;
	}
	temp.sz_reduce_min();
	return temp;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::abs() const{
	if (is_negative()) return operator - ();
	else return (*this);
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator & (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	vint<_Bit_size_type,_Byte_size_type> temp1(*this);
	vint<_Bit_size_type,_Byte_size_type> temp2(op);
	temp1.sz_expand_until(max(size(),op.size()));
	temp2.sz_expand_until(max(size(),op.size()));
	vint<_Bit_size_type,_Byte_size_type> result;
	result.sz_expand_until(max(size(),op.size()));
	for (_Byte_size_type i = 0; i < result.size(); i++)
		result.data[i] = temp1.data[i] & temp2.data[i];
	result.sz_reduce_min();
	return result;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator | (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	vint<_Bit_size_type,_Byte_size_type> temp1(*this);
	vint<_Bit_size_type,_Byte_size_type> temp2(op);
	temp1.sz_expand_until(max(size(),op.size()));
	temp2.sz_expand_until(max(size(),op.size()));
	vint<_Bit_size_type,_Byte_size_type> result;
	result.sz_expand_until(max(size(),op.size()));
	for (_Byte_size_type i = 0; i < result.size(); i++)
		result.data[i] = temp1.data[i] | temp2.data[i];
	result.sz_reduce_min();
	return result;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator ^ (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	vint<_Bit_size_type,_Byte_size_type> temp1(*this);
	vint<_Bit_size_type,_Byte_size_type> temp2(op);
	temp1.sz_expand_until(max(size(),op.size()));
	temp2.sz_expand_until(max(size(),op.size()));
	vint<_Bit_size_type,_Byte_size_type> result;
	result.sz_expand_until(max(size(),op.size()));
	for (_Byte_size_type i = 0; i < result.size(); i++)
		result.data[i] = temp1.data[i] ^ temp2.data[i];
	result.sz_reduce_min();
	return result;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator &= (const vint<_Bit_size_type,_Byte_size_type>& op){
	return operator = (operator& (op));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator |= (const vint<_Bit_size_type,_Byte_size_type>& op){
	return operator = (operator| (op));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator ^= (const vint<_Bit_size_type,_Byte_size_type>& op){
	return operator = (operator^ (op));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator * (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	bool neg = (is_negative() ^ op.is_negative());
	vint<_Bit_size_type,_Byte_size_type> temp1 = abs();
	vint<_Bit_size_type,_Byte_size_type> temp2 = op.abs();
	vint<_Bit_size_type,_Byte_size_type> result = vint(0);
	for (_Bit_size_type i = 0; i < temp2.size()*8; i++){
		if (temp2.is_bit(i)) result += temp1;
		temp1 <<= 1;
	}
	if (neg) result = -result;
	result.sz_reduce_min();
	return result;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator / (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	vint<_Bit_size_type,_Byte_size_type> temp1 = abs();
	vint<_Bit_size_type,_Byte_size_type> temp2 = op.abs();
	vint<_Bit_size_type,_Byte_size_type> one = vint(1);
	vint<_Bit_size_type,_Byte_size_type> result = vint(0);
	if (effdigit() >= op.effdigit()){
		temp2 <<= (effdigit() - op.effdigit());
		one <<= (effdigit() - op.effdigit());
		for (_Bit_size_type i = 0; i <= effdigit()-op.effdigit(); i++){
			if (temp1 >= temp2){
				temp1 -= temp2;
				result += one;
			}
			temp2 >>= 1;
			one >>= 1;
		}
	}
	if (is_negative()) result++;
	if (is_negative() ^ op.is_negative()) result = -result;
	result.sz_reduce_min();
	return result;
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> vint<_Bit_size_type,_Byte_size_type>::operator % (const vint<_Bit_size_type,_Byte_size_type>& op) const{
	return ((*this) - (((*this) / (op)) * (op)));
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type>& vint<_Bit_size_type,_Byte_size_type>::operator %= (const vint<_Bit_size_type,_Byte_size_type>& op){
	return operator = (operator % (op));
}
 
 
char num(int nu){
	return '0'+nu;
}
 
int invnum(char w){
	return w - '0';
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
void vint<_Bit_size_type,_Byte_size_type>::input(const std::string& str){
	size_t start = 0;
	bool neg = false;
	operator = (vint(0));
	if (str[0] == '-') {
		start = 1;
		neg = true;
	}else if (str[0] == '+'){
		start = 1;
	}
	for (size_t i = start; i < str.size(); i++){
		operator *= (vint(10));
		operator += (vint(invnum(str[i])));
	}
	if (neg) operator = (operator -());
}
 
template <typename _Bit_size_type, typename _Byte_size_type>
std::string vint<_Bit_size_type,_Byte_size_type>::output() const{
	vint temp(*this);
	bool neg = false;
	std::string result;
	if (temp == vint(0)) return "0";
	if (is_negative()){
		neg = true;
		temp = -temp;
	}
	while (temp > vint(0)){
		result.insert(result.begin(),num((temp%vint(10)).data[0]));
		temp /= vint(10);
	}
	if (neg) result.insert(result.begin(),'-');
	return result;
}
 
 
 
 
template <typename _Bit_size_type, typename _Byte_size_type>
vint<_Bit_size_type,_Byte_size_type> operator + (const vint<_Bit_size_type,_Byte_size_type>& op1, const vint<_Bit_size_type,_Byte_size_type>& op2){
	vint temp(op1);
	return temp += op2;
}
 
vint<_Bit_size_type,_Byte_size_type> operator - (const vint<_Bit_size_type,_Byte_size_type>& op1, const vint<_Bit_size_type,_Byte_size_type>& op2){
	vint temp(op1);
	return temp -= op2;
}
 
 
 
 
#endif
最終更新:2009年07月17日 18:59