159 lines
3.7 KiB
C++
159 lines
3.7 KiB
C++
|
//
|
||
|
// Created by trotfunky on 04/11/2020.
|
||
|
//
|
||
|
|
||
|
#include <iostream>
|
||
|
#include "NegBin.h"
|
||
|
|
||
|
|
||
|
NegBin::NegBin(longBitField binaryRepresentation) :
|
||
|
value(binaryRepresentation.to_ulong())
|
||
|
{}
|
||
|
|
||
|
NegBin::NegBin(long decimalValue) : value(0)
|
||
|
{
|
||
|
unsigned int currentPower = 0;
|
||
|
decimalValue *= -1;
|
||
|
// This works by checking the remainder by -2, giving the lowest bit of the converted number.
|
||
|
// Then, shift to the right to drop the bit we just checked and start again until every set bit has been checked.
|
||
|
// The sign flips each time as we are in base -2 and not 2.
|
||
|
// Miiight be UDB...
|
||
|
while (decimalValue != 0)
|
||
|
{
|
||
|
value |= std::abs(decimalValue%-2) << currentPower;
|
||
|
decimalValue = -decimalValue >> 1;
|
||
|
currentPower++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NegBin& NegBin::operator+=(const NegBin& rhs)
|
||
|
{
|
||
|
unsigned long carry = 0;
|
||
|
|
||
|
for(unsigned int i = 0;i<sizeof(long)*8;i++)
|
||
|
{
|
||
|
unsigned long temp_carry = carry >> i;
|
||
|
unsigned long temp_rhs = rhs.value >> i;
|
||
|
unsigned long temp_lhs = this->value >> i;
|
||
|
|
||
|
// Nothing remaining to add
|
||
|
if (!(temp_rhs | temp_carry)) break;
|
||
|
|
||
|
// Both carry and right hand side are 1 so we need to add a carry
|
||
|
if (temp_carry & temp_rhs & 1)
|
||
|
{
|
||
|
// If the carry is already set for this bit, it needs to be cleared for this bit and the next
|
||
|
if (temp_carry >> 1 & 1)
|
||
|
{
|
||
|
carry &= ~(0b11 << i);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Else add a two bit carry
|
||
|
carry |= 0b11 << (i+1);
|
||
|
}
|
||
|
}
|
||
|
// If either of them are set, add to lhs, otherwise don't bother
|
||
|
else if ((temp_carry ^ temp_rhs) & 1)
|
||
|
{
|
||
|
// If a carry was already set for the next bit too, discard both carries and the current bit
|
||
|
if (temp_lhs & temp_carry & 1 && temp_carry >> 1 & 1)
|
||
|
{
|
||
|
carry &= ~(0b11 << i);
|
||
|
this->value &= ~(0b1 << i);
|
||
|
}
|
||
|
else if (temp_lhs & 1)
|
||
|
{
|
||
|
// If the current bit was set, clear and add a two bit carry
|
||
|
carry |= 0b11 << (i+1);
|
||
|
this->value &= ~(0b1 << i);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->value |= 0b1 << i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
NegBin operator+(NegBin lhs, const NegBin& rhs)
|
||
|
{
|
||
|
lhs += rhs;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
NegBin& NegBin::operator-=(const NegBin& rhs)
|
||
|
{
|
||
|
// lhs - rhs <=> lhs + (-rhs)
|
||
|
*this += ~rhs;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
NegBin operator-(NegBin lhs, const NegBin& rhs)
|
||
|
{
|
||
|
lhs -= rhs;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
NegBin& NegBin::operator*=(const int& rhs)
|
||
|
{
|
||
|
auto unit = *this;
|
||
|
for (int i=0;i<rhs;i++)
|
||
|
{
|
||
|
*this += unit;
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
NegBin operator*(NegBin lhs, const int& rhs)
|
||
|
{
|
||
|
lhs *= rhs;
|
||
|
return lhs;
|
||
|
}
|
||
|
|
||
|
NegBin operator*(const int& lhs, NegBin rhs)
|
||
|
{
|
||
|
return rhs*lhs;
|
||
|
}
|
||
|
|
||
|
NegBin NegBin::operator~() const
|
||
|
{
|
||
|
// Shifting to the right is equivalent to dividing by the base. As we are using base -2,
|
||
|
// multiplying by 2 and shifting to the right gives us the opposite of the number.
|
||
|
return (*this+*this) >> 1;
|
||
|
}
|
||
|
|
||
|
NegBin NegBin::operator>>(const int& rhs)
|
||
|
{
|
||
|
this->value >>= rhs;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
NegBin NegBin::operator<<(const int& rhs)
|
||
|
{
|
||
|
this->value <<= rhs;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
NegBin::operator long() const
|
||
|
{
|
||
|
long result = 0;
|
||
|
for(unsigned int i = 0;i<sizeof(long)*8;i++)
|
||
|
{
|
||
|
result += ((value >> i) & 1)*std::pow(-2,i);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
NegBin operator ""_nb(unsigned long long number)
|
||
|
{
|
||
|
return NegBin(longBitField(number));
|
||
|
}
|
||
|
|
||
|
std::ostream& operator<<(std::ostream& ostream, const NegBin& number)
|
||
|
{
|
||
|
ostream << static_cast<long>(number);
|
||
|
return ostream;
|
||
|
}
|