146 lines
2.8 KiB
C++
146 lines
2.8 KiB
C++
// bigfix.h
|
|
//
|
|
// Copyright (C) 2007-2008, Chris Laurel <claurel@shatters.net>
|
|
//
|
|
// 128-bit fixed point (64.64) numbers for high-precision celestial
|
|
// coordinates. When you need millimeter accurate navigation across a scale
|
|
// of thousands of light years, double precision floating point numbers
|
|
// are inadequate.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
#ifndef _CELUTIL_BIGFIX64_H_
|
|
#define _CELUTIL_BIGFIX64_H_
|
|
|
|
#include <string>
|
|
#include <limits>
|
|
|
|
/*! 64.64 signed fixed point numbers.
|
|
*/
|
|
|
|
class BigFix
|
|
{
|
|
public:
|
|
BigFix();
|
|
BigFix(uint64_t);
|
|
BigFix(double);
|
|
BigFix(const std::string&);
|
|
|
|
operator double() const;
|
|
operator float() const;
|
|
|
|
BigFix operator-() const;
|
|
BigFix operator+=(const BigFix&);
|
|
BigFix operator-=(const BigFix&);
|
|
|
|
friend BigFix operator+(const BigFix&, const BigFix&);
|
|
friend BigFix operator-(const BigFix&, const BigFix&);
|
|
friend BigFix operator*(const BigFix&, const BigFix&);
|
|
friend BigFix operator*(BigFix, double);
|
|
friend bool operator==(const BigFix&, const BigFix&);
|
|
friend bool operator!=(const BigFix&, const BigFix&);
|
|
friend bool operator<(const BigFix&, const BigFix&);
|
|
friend bool operator>(const BigFix&, const BigFix&);
|
|
|
|
int sign() const;
|
|
|
|
// for debugging
|
|
void dump();
|
|
std::string toString();
|
|
|
|
private:
|
|
bool isNegative() const
|
|
{
|
|
return hi > static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
|
|
}
|
|
|
|
static void negate128(uint64_t& hi, uint64_t& lo);
|
|
|
|
private:
|
|
uint64_t hi;
|
|
uint64_t lo;
|
|
};
|
|
|
|
|
|
// Compute the additive inverse of a 128-bit twos complement value
|
|
// represented by two 64-bit values.
|
|
inline void BigFix::negate128(uint64_t& hi, uint64_t& lo)
|
|
{
|
|
// For a twos-complement number, -n = ~n + 1
|
|
hi = ~hi;
|
|
lo = ~lo;
|
|
lo++;
|
|
if (lo == 0)
|
|
hi++;
|
|
}
|
|
|
|
inline BigFix BigFix::operator-() const
|
|
{
|
|
BigFix result = *this;
|
|
|
|
negate128(result.hi, result.lo);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
inline BigFix BigFix::operator+=(const BigFix& a)
|
|
{
|
|
lo += a.lo;
|
|
hi += a.hi;
|
|
|
|
// carry
|
|
if (lo < a.lo)
|
|
hi++;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline BigFix BigFix::operator-=(const BigFix& a)
|
|
{
|
|
lo -= a.lo;
|
|
hi -= a.hi;
|
|
|
|
// borrow
|
|
if (lo > a.lo)
|
|
hi--;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline BigFix operator+(const BigFix& a, const BigFix& b)
|
|
{
|
|
BigFix c;
|
|
|
|
c.lo = a.lo + b.lo;
|
|
c.hi = a.hi + b.hi;
|
|
|
|
// carry
|
|
if (c.lo < a.lo)
|
|
c.hi++;
|
|
|
|
return c;
|
|
}
|
|
|
|
|
|
inline BigFix operator-(const BigFix& a, const BigFix& b)
|
|
{
|
|
BigFix c;
|
|
|
|
c.lo = a.lo - b.lo;
|
|
c.hi = a.hi - b.hi;
|
|
|
|
// borrow
|
|
if (c.lo > a.lo)
|
|
c.hi--;
|
|
|
|
return c;
|
|
}
|
|
|
|
#endif // _CELUTIL_BIGFIX64_H_
|