128ビット整数クラス
C128 C++クラス
Athlon64X2 3800+ の SSE を利用して 128 ビットの論理演算が楽にできるのかと思ってたけど ビットシフト や AND や SUB の使い勝手がいまいち良く無い (コツを知らないだけ?)。 しょうがないので C++ で クラス C128 を作った。 一応 128 ビットリニアな Shift-L, Shift-R, ADD, SUB と AND, OR, XOR, NOT だけ実装してみました。 乗算、除算はありません。オパピ^^
以下のようなコードで、実装的に一番遅いと思われるビットシフト演算の速度を測ったところ 0.584秒/億。
void test_shift()
{
C128 c(1);
for (long i = 0; i < 500000; i++) {
for (long j = 0; j < 100; j++)
c <<= 1;
for (long j = 0; j < 100; j++)
c >>= 1;
}
}
上のプログラムの C128 を 64 ビットデータ型 (unsigned long long) を使うように修正し、 オプティマイズ無しでシフト演算してみると 0.340秒/億とあまり差が無い。 消費時間の大部分はループ処理の部分と思われるのであてにならないってことか。 (測定方法が悪いんでね;;)
話は違うけど、 単純な処理をいくつか NASM やインラインアセンブラのコードで試してみてたのですが C++ で組んでオプティマイズをかける (gcc -O3) のと大差ないようです。 特殊な事情が無ければ、今は C/C++ で十分なのだろう。
ソースコード C128.h (ヘッダ部)
// Copyright (C) 2007, Shu KONNO <owa@bg.wakwak.com>. All rights reserved.
// This program is free software licensed under the GPL 2 or above.
// Version: 1.0.0 (2007-11-10)
//
#ifndef _C128_H_
#define _C128_H_
typedef unsigned long long ULong;
class C128 {
private:
ULong lo;
ULong hi;
public:
C128() : lo(0), hi(0) {}
C128(ULong m, ULong n=0) : lo(m), hi(n) {}
~C128() {}
ULong getl() const { return lo; }
ULong geth() const { return hi; }
C128& operator<<=(unsigned int);
C128 operator<<(unsigned int n) const { return C128(*this) <<= n; }
C128& operator>>=(unsigned int);
C128 operator>>(unsigned int n) const { return C128(*this) >>= n; }
C128& operator+=(ULong);
C128& operator+=(C128);
C128 operator+(ULong u) const { return C128(*this) += u; }
C128 operator+(C128 c) const { return C128(*this) += c; }
C128 operator+() const { return *this; }
C128& operator-=(ULong);
C128& operator-=(C128);
C128 operator-(ULong u) const { return C128(*this) -= u; }
C128 operator-(C128 c) const { return C128(*this) -= c; }
C128 operator-() const { return C128() -= *this; }
C128& operator&=(C128);
C128 operator&(C128 c) const { return C128(*this) &= c; }
C128& operator|=(C128);
C128 operator|(C128 c) const { return C128(*this) |= c; }
C128& operator^=(C128);
C128 operator^(C128 c) const { return C128(*this) ^= c; }
C128 operator~() const { return C128(~lo, ~hi); };
};
#endif // _C128_H_
ソースコード C128.cpp (処理部)
// Copyright (C) 2007, Shu KONNO <owa@bg.wakwak.com>. All rights reserved.
// This program is free software licensed under the GPL 2 or above.
// Version: 1.0.0 (2007-11-10)
//
#include "C128.h"
C128& C128::operator<<=(unsigned int n)
{
n &= 0x07f;
if (n >= 64) {
hi = lo << (n - 64);
lo = 0;
}
else if (n) {
hi <<= n;
hi |= lo >> (64 - n);
lo <<= n;
}
return *this;
}
C128& C128::operator>>=(unsigned int n)
{
n &= 0x07f;
if (n >= 64) {
lo = hi >> (n - 64);
hi = 0;
}
else if (n) {
lo >>= n;
lo |= hi << (64 - n);
hi >>= n;
}
return *this;
}
C128& C128::operator+=(ULong u)
{
ULong t = lo;
if ((lo += u) < t)
++hi;
return *this;
}
C128& C128::operator+=(C128 c)
{
ULong t = lo;
if ((lo += c.lo) < t)
++hi;
hi += c.hi;
return *this;
}
C128& C128::operator-=(ULong u)
{
ULong t = lo;
if ((lo -= u) > t)
--hi;
return *this;
}
C128& C128::operator-=(C128 c)
{
ULong t = lo;
if ((lo -= c.lo) > t)
--hi;
hi -= c.hi;
return *this;
}
C128& C128::operator&=(C128 c)
{
lo &= c.lo;
hi &= c.hi;
return *this;
}
C128& C128::operator|=(C128 c)
{
lo |= c.lo;
hi |= c.hi;
return *this;
}
C128& C128::operator^=(C128 c)
{
lo ^= c.lo;
hi ^= c.hi;
return *this;
}