#include <cmath>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stdint.h>
#include <string>
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
namespace Astrome
{
typedef uint8_t BitCountType;
typedef uint64_t IntegerDataType;
class FixedPoint
{
const BitCountType _totalBits;
const BitCountType _integerBits;
const bool _isSigned;
const IntegerDataType _constant; // This is the number of possible states
const IntegerDataType _factor; // This is the scaling factor
const IntegerDataType _mask;
IntegerDataType _integerValue;
public:
FixedPoint(BitCountType totalBits,
BitCountType integerBits,
bool isSigned,
IntegerDataType integerValue = 0) :
_totalBits(totalBits),
_integerBits(integerBits), _isSigned(isSigned), _constant(1 << _totalBits),
_factor(1 << (_totalBits - _integerBits)), _mask(_constant - 1),
_integerValue(integerValue & _mask)
{
}
FixedPoint(BitCountType totalBits, BitCountType integerBits, bool isSigned, double floatValue) :
FixedPoint(totalBits, integerBits, isSigned, floatToInt(floatValue))
{
}
IntegerDataType floatToInt(const double &value)
{
if (_isSigned)
{
if (value < 0)
return (round(_constant + value * _factor));
else
return round(value * _factor);
}
else
{
return round(value * _factor);
}
}
bool isNegative() const
{
if (_isSigned)
return _integerValue >> (_totalBits - 1);
return false;
}
double floatValue() const
{
if (isNegative())
return (_integerValue - _constant) * 1.0 / _factor;
return _integerValue * 1.0 / _factor;
}
FixedPoint &operator=(const FixedPoint &other)
{
_integerValue = floatToInt(other.floatValue());
return *this;
}
FixedPoint operator>>(const BitCountType &bits)
{
return FixedPoint(_totalBits, _integerBits, _isSigned, _integerValue >> bits);
}
FixedPoint operator<<(const BitCountType &bits)
{
IntegerDataType integerValue = _integerValue << bits;
return FixedPoint(_totalBits, _integerBits, _isSigned, integerValue);
}
FixedPoint operator-() const
{
return FixedPoint(_totalBits, _integerBits, _isSigned, (~_integerValue) + 1); // Error
}
FixedPoint operator+(const FixedPoint &other) const
{
return FixedPoint(_totalBits, _integerBits, _isSigned, floatValue() + other.floatValue());
}
FixedPoint operator-(const FixedPoint &other) const
{
return (*this) + (-other);
}
std::string hexValue() const
{
std::stringstream stream;
stream << "0x" << std::setfill('0') << std::setw(_totalBits / 4) << std::hex << _integerValue;
return (stream.str());
}
};
}
#ifdef DEBUG
#define PRINT(t, x, f) \
std::cout << t << "\033[20G" << x.floatValue() << " " << x.hexValue() << "\033[50G" \
<< (fabs(x.floatValue() - f) < 1e-4 ? "OK" : "FAIL") << std::endl;
#else
#define PRINT(t, x, f) std::cout << x.floatValue() << " " << x.hexValue() << std::endl;
#endif
#define TEST(x) \
{ \
FixedPoint g(16, 1, true, x); \
PRINT("X", g, x) \
\
FixedPoint h = g >> 1; \
PRINT("X>>1", h, x / 2) \
\
FixedPoint i = h << 1; \
PRINT("(X>>1)<<1", i, x) \
\
FixedPoint j = -g; \
PRINT("-X", j, -x) \
\
FixedPoint k = g + h; \
PRINT("X + (X>>1)", k, 1.5 * x); \
\
FixedPoint l = g - h; \
PRINT("X - (X>>1)", l, 0.5 * x); \
std::cout << "-" << std::endl; \
}
int main()
{
using namespace Astrome;
TEST(1.0)
TEST(-1.0)
TEST(-0.5)
TEST(0.7)
TEST(-0.7)
TEST(M_PI / 4)
}
I2luY2x1ZGUgPGNtYXRoPgojaW5jbHVkZSA8aW9tYW5pcD4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3N0cmVhbT4KI2luY2x1ZGUgPHN0ZGludC5oPgojaW5jbHVkZSA8c3RyaW5nPgoKI2RlZmluZSBNQVgoQSwgQikgKChBKSA+IChCKSA/IChBKSA6IChCKSkKI2RlZmluZSBNSU4oQSwgQikgKChBKSA8IChCKSA/IChBKSA6IChCKSkKCm5hbWVzcGFjZSBBc3Ryb21lCnsKdHlwZWRlZiB1aW50OF90IEJpdENvdW50VHlwZTsKdHlwZWRlZiB1aW50NjRfdCBJbnRlZ2VyRGF0YVR5cGU7CgpjbGFzcyBGaXhlZFBvaW50CnsKICBjb25zdCBCaXRDb3VudFR5cGUgX3RvdGFsQml0czsKICBjb25zdCBCaXRDb3VudFR5cGUgX2ludGVnZXJCaXRzOwogIGNvbnN0IGJvb2wgX2lzU2lnbmVkOwogIGNvbnN0IEludGVnZXJEYXRhVHlwZSBfY29uc3RhbnQ7IC8vIFRoaXMgaXMgdGhlIG51bWJlciBvZiBwb3NzaWJsZSBzdGF0ZXMKICBjb25zdCBJbnRlZ2VyRGF0YVR5cGUgX2ZhY3RvcjsgICAvLyBUaGlzIGlzIHRoZSBzY2FsaW5nIGZhY3RvcgogIGNvbnN0IEludGVnZXJEYXRhVHlwZSBfbWFzazsKCiAgSW50ZWdlckRhdGFUeXBlIF9pbnRlZ2VyVmFsdWU7CgpwdWJsaWM6CiAgRml4ZWRQb2ludChCaXRDb3VudFR5cGUgdG90YWxCaXRzLAogICAgICAgICAgICAgQml0Q291bnRUeXBlIGludGVnZXJCaXRzLAogICAgICAgICAgICAgYm9vbCBpc1NpZ25lZCwKICAgICAgICAgICAgIEludGVnZXJEYXRhVHlwZSBpbnRlZ2VyVmFsdWUgPSAwKSA6CiAgICBfdG90YWxCaXRzKHRvdGFsQml0cyksCiAgICBfaW50ZWdlckJpdHMoaW50ZWdlckJpdHMpLCBfaXNTaWduZWQoaXNTaWduZWQpLCBfY29uc3RhbnQoMSA8PCBfdG90YWxCaXRzKSwKICAgIF9mYWN0b3IoMSA8PCAoX3RvdGFsQml0cyAtIF9pbnRlZ2VyQml0cykpLCBfbWFzayhfY29uc3RhbnQgLSAxKSwKICAgIF9pbnRlZ2VyVmFsdWUoaW50ZWdlclZhbHVlICYgX21hc2spCiAgewogIH0KCiAgRml4ZWRQb2ludChCaXRDb3VudFR5cGUgdG90YWxCaXRzLCBCaXRDb3VudFR5cGUgaW50ZWdlckJpdHMsIGJvb2wgaXNTaWduZWQsIGRvdWJsZSBmbG9hdFZhbHVlKSA6CiAgICBGaXhlZFBvaW50KHRvdGFsQml0cywgaW50ZWdlckJpdHMsIGlzU2lnbmVkLCBmbG9hdFRvSW50KGZsb2F0VmFsdWUpKQogIHsKICB9CgoKICBJbnRlZ2VyRGF0YVR5cGUgZmxvYXRUb0ludChjb25zdCBkb3VibGUgJnZhbHVlKQogIHsKICAgIGlmIChfaXNTaWduZWQpCiAgICB7CiAgICAgIGlmICh2YWx1ZSA8IDApCiAgICAgICAgcmV0dXJuIChyb3VuZChfY29uc3RhbnQgKyB2YWx1ZSAqIF9mYWN0b3IpKTsKICAgICAgZWxzZQogICAgICAgIHJldHVybiByb3VuZCh2YWx1ZSAqIF9mYWN0b3IpOwogICAgfQogICAgZWxzZQogICAgewogICAgICByZXR1cm4gcm91bmQodmFsdWUgKiBfZmFjdG9yKTsKICAgIH0KICB9CgogIGJvb2wgaXNOZWdhdGl2ZSgpIGNvbnN0CiAgewogICAgaWYgKF9pc1NpZ25lZCkKICAgICAgcmV0dXJuIF9pbnRlZ2VyVmFsdWUgPj4gKF90b3RhbEJpdHMgLSAxKTsKICAgIHJldHVybiBmYWxzZTsKICB9CgogIGRvdWJsZSBmbG9hdFZhbHVlKCkgY29uc3QKICB7CiAgICBpZiAoaXNOZWdhdGl2ZSgpKQogICAgICByZXR1cm4gKF9pbnRlZ2VyVmFsdWUgLSBfY29uc3RhbnQpICogMS4wIC8gX2ZhY3RvcjsKICAgIHJldHVybiBfaW50ZWdlclZhbHVlICogMS4wIC8gX2ZhY3RvcjsKICB9CgogIEZpeGVkUG9pbnQgJm9wZXJhdG9yPShjb25zdCBGaXhlZFBvaW50ICZvdGhlcikKICB7CiAgICBfaW50ZWdlclZhbHVlID0gZmxvYXRUb0ludChvdGhlci5mbG9hdFZhbHVlKCkpOwogICAgcmV0dXJuICp0aGlzOwogIH0KCiAgRml4ZWRQb2ludCBvcGVyYXRvcj4+KGNvbnN0IEJpdENvdW50VHlwZSAmYml0cykKICB7CiAgICByZXR1cm4gRml4ZWRQb2ludChfdG90YWxCaXRzLCBfaW50ZWdlckJpdHMsIF9pc1NpZ25lZCwgX2ludGVnZXJWYWx1ZSA+PiBiaXRzKTsKICB9CgogIEZpeGVkUG9pbnQgb3BlcmF0b3I8PChjb25zdCBCaXRDb3VudFR5cGUgJmJpdHMpCiAgewogICAgSW50ZWdlckRhdGFUeXBlIGludGVnZXJWYWx1ZSA9IF9pbnRlZ2VyVmFsdWUgPDwgYml0czsKICAgIHJldHVybiBGaXhlZFBvaW50KF90b3RhbEJpdHMsIF9pbnRlZ2VyQml0cywgX2lzU2lnbmVkLCBpbnRlZ2VyVmFsdWUpOwogIH0KCiAgRml4ZWRQb2ludCBvcGVyYXRvci0oKSBjb25zdAogIHsKICAgIHJldHVybiBGaXhlZFBvaW50KF90b3RhbEJpdHMsIF9pbnRlZ2VyQml0cywgX2lzU2lnbmVkLCAofl9pbnRlZ2VyVmFsdWUpICsgMSk7IC8vIEVycm9yCiAgfQoKICBGaXhlZFBvaW50IG9wZXJhdG9yKyhjb25zdCBGaXhlZFBvaW50ICZvdGhlcikgY29uc3QKICB7CiAgICByZXR1cm4gRml4ZWRQb2ludChfdG90YWxCaXRzLCBfaW50ZWdlckJpdHMsIF9pc1NpZ25lZCwgZmxvYXRWYWx1ZSgpICsgb3RoZXIuZmxvYXRWYWx1ZSgpKTsKICB9CgogIEZpeGVkUG9pbnQgb3BlcmF0b3ItKGNvbnN0IEZpeGVkUG9pbnQgJm90aGVyKSBjb25zdAogIHsKICAgIHJldHVybiAoKnRoaXMpICsgKC1vdGhlcik7CiAgfQoKCiAgc3RkOjpzdHJpbmcgaGV4VmFsdWUoKSBjb25zdAogIHsKICAgIHN0ZDo6c3RyaW5nc3RyZWFtIHN0cmVhbTsKICAgIHN0cmVhbSA8PCAiMHgiIDw8IHN0ZDo6c2V0ZmlsbCgnMCcpIDw8IHN0ZDo6c2V0dyhfdG90YWxCaXRzIC8gNCkgPDwgc3RkOjpoZXggPDwgX2ludGVnZXJWYWx1ZTsKICAgIHJldHVybiAoc3RyZWFtLnN0cigpKTsKICB9Cn07Cgp9CgojaWZkZWYgREVCVUcKI2RlZmluZSBQUklOVCh0LCB4LCBmKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgc3RkOjpjb3V0IDw8IHQgPDwgIlwwMzNbMjBHIiA8PCB4LmZsb2F0VmFsdWUoKSA8PCAiICIgPDwgeC5oZXhWYWx1ZSgpIDw8ICJcMDMzWzUwRyIgXAogICAgICAgICAgICA8PCAoZmFicyh4LmZsb2F0VmFsdWUoKSAtIGYpIDwgMWUtNCA/ICJPSyIgOiAiRkFJTCIpIDw8IHN0ZDo6ZW5kbDsKI2Vsc2UKI2RlZmluZSBQUklOVCh0LCB4LCBmKSBzdGQ6OmNvdXQgPDwgeC5mbG9hdFZhbHVlKCkgPDwgIiAiIDw8IHguaGV4VmFsdWUoKSA8PCBzdGQ6OmVuZGw7CiNlbmRpZgoKCiNkZWZpbmUgVEVTVCh4KSAgICAgICAgICAgICAgICAgICAgICBcCiAgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBGaXhlZFBvaW50IGcoMTYsIDEsIHRydWUsIHgpOyAgICBcCiAgICBQUklOVCgiWCIsIGcsIHgpICAgICAgICAgICAgICAgICBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBGaXhlZFBvaW50IGggPSBnID4+IDE7ICAgICAgICAgICBcCiAgICBQUklOVCgiWD4+MSIsIGgsIHggLyAyKSAgICAgICAgICBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBGaXhlZFBvaW50IGkgPSBoIDw8IDE7ICAgICAgICAgICBcCiAgICBQUklOVCgiKFg+PjEpPDwxIiwgaSwgeCkgICAgICAgICBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBGaXhlZFBvaW50IGogPSAtZzsgICAgICAgICAgICAgICBcCiAgICBQUklOVCgiLVgiLCBqLCAteCkgICAgICAgICAgICAgICBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBGaXhlZFBvaW50IGsgPSBnICsgaDsgICAgICAgICAgICBcCiAgICBQUklOVCgiWCArIChYPj4xKSIsIGssIDEuNSAqIHgpOyBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBGaXhlZFBvaW50IGwgPSBnIC0gaDsgICAgICAgICAgICBcCiAgICBQUklOVCgiWCAtIChYPj4xKSIsIGwsIDAuNSAqIHgpOyBcCiAgICBzdGQ6OmNvdXQgPDwgIi0iIDw8IHN0ZDo6ZW5kbDsgICBcCiAgfQoKaW50IG1haW4oKQp7CiAgdXNpbmcgbmFtZXNwYWNlIEFzdHJvbWU7CgogIFRFU1QoMS4wKQogIFRFU1QoLTEuMCkKICBURVNUKC0wLjUpCgogIFRFU1QoMC43KQogIFRFU1QoLTAuNykKICBURVNUKE1fUEkgLyA0KQp9