Created
May 8, 2014 01:34
-
-
Save marionette-of-u/9b4ac800460b3f9d3c32 to your computer and use it in GitHub Desktop.
160行で分かる(可能性がある)!多倍精度整数演算!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <cstdint> | |
| #include <cmath> | |
| namespace delta_zero{ | |
| namespace impl{ | |
| // primitive quadriplegic integer. | |
| template<class UInt = std::uint32_t, class DoubleUInt = std::uint64_t, class DoubleInt = std::int64_t, DoubleUInt BitNum = sizeof(UInt) * 8> | |
| struct quint{ | |
| template<DoubleUInt Count> | |
| struct make_bitmask{ | |
| static const DoubleUInt value = (static_cast<DoubleUInt>(1) << Count) | make_bitmask<Count - static_cast<DoubleUInt>(1)>::value; | |
| }; | |
| template<> | |
| struct make_bitmask<0>{ | |
| static const DoubleUInt value = static_cast<DoubleUInt>(1); | |
| }; | |
| static const DoubleUInt base_mask = make_bitmask<BitNum - 1>::value; | |
| UInt data[4]; | |
| quint(){ | |
| for(int i = 0; i < 4; ++i){ data[i] = 0; } | |
| } | |
| quint(const quint &other){ | |
| for(int i = 0; i < 4; ++i){ data[i] = other.data[i]; } | |
| } | |
| quint(quint &&other){ | |
| for(int i = 0; i < 4; ++i){ data[i] = other.data[i]; } | |
| } | |
| ~quint() = default; | |
| quint(int x){ | |
| data[0] = static_cast<UInt>(x); | |
| data[1] = data[2] = data[3] = 0; | |
| } | |
| quint(UInt x){ | |
| data[0] = x; | |
| data[1] = data[2] = data[3] = 0; | |
| } | |
| quint add(const quint &other) const{ | |
| quint result; | |
| DoubleUInt c = 0; | |
| for(int i = 0; i < 4; ++i){ | |
| DoubleUInt v = static_cast<DoubleUInt>(data[i]) + static_cast<DoubleUInt>(other.data[i]) + c; | |
| result.data[i] = static_cast<UInt>(v & base_mask); | |
| c = v >> BitNum; | |
| } | |
| return result; | |
| } | |
| quint sub(const quint &other) const{ | |
| quint result; | |
| for(int i = 0; i < 4; ++i){ result.data[i] = ~other.data[i]; } | |
| DoubleUInt c = 1; | |
| for(int i = 0; i < 4; ++i){ | |
| DoubleUInt v = static_cast<DoubleUInt>(data[i]) + static_cast<DoubleUInt>(result.data[i]) + c; | |
| result.data[i] = static_cast<UInt>(v & base_mask); | |
| c = v >> BitNum; | |
| } | |
| return result; | |
| } | |
| quint mul(const quint &other) const{ | |
| UInt extended_data[8] = { 0 }; | |
| for(int i = 0; i < 4; ++i){ | |
| for(int j = 0; j < 4; ++j){ | |
| DoubleUInt c = static_cast<DoubleUInt>(data[i]) * static_cast<DoubleUInt>(other.data[j]); | |
| for(int k = 0; k < 4; ++k){ | |
| DoubleUInt v = static_cast<DoubleUInt>(extended_data[i + j + k]) + c; | |
| extended_data[i + j + k] = static_cast<UInt>(v & base_mask); | |
| c = v >> BitNum; | |
| } | |
| } | |
| } | |
| quint result; | |
| for(int i = 0; i < 4; ++i){ | |
| result.data[i] = extended_data[i]; | |
| } | |
| return result; | |
| } | |
| quint div(const quint &other) const{ | |
| quint r = *this, result; | |
| UInt u = other.lc(); | |
| int n = degree(), m = other.degree(), i = n - m; | |
| while(i >= 0){ | |
| if(r.degree() == m + i){ | |
| result.data[i] = r.lc() / u; | |
| r = r.sub(other.mul(result.data[i])); | |
| }else{ | |
| result.data[i] = 0; | |
| } | |
| --i; | |
| } | |
| return result; | |
| } | |
| quint rem(const quint &other) const{ | |
| return sub(other.mul(div(other))); | |
| } | |
| int degree() const{ | |
| int i; | |
| for(i = 4; i > 0; --i){ | |
| if(data[i - 1] > 0){ break; } | |
| } | |
| return i; | |
| } | |
| UInt lc() const{ return data[degree() - 1]; } | |
| }; | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator +( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.add(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator -( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.sub(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator *( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.mul(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator /( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.div(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator %( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.rem(rhs); } | |
| } | |
| } | |
| int main(){ | |
| using quint = delta_zero::impl::quint<>; | |
| quint a = 39, b = 8, c; | |
| c = a % b; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment