Skip to content

Instantly share code, notes, and snippets.

@marionette-of-u
Created May 8, 2014 01:34
Show Gist options
  • Select an option

  • Save marionette-of-u/9b4ac800460b3f9d3c32 to your computer and use it in GitHub Desktop.

Select an option

Save marionette-of-u/9b4ac800460b3f9d3c32 to your computer and use it in GitHub Desktop.
160行で分かる(可能性がある)!多倍精度整数演算!
#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