ああ、ビット単位の演算の喜び。多くの除算ルーチンの副作用はモジュラスです。したがって、実際には除算がモジュラスよりも速い場合がほとんどありません。あなたがこの情報を入手した情報源に興味があります。乗算器を備えたプロセッサには、乗算器を使用した興味深い除算ルーチンがありますが、除算の結果からモジュラスまで、さらに2つのステップ(乗算と減算)で取得できるため、比較可能です。プロセッサに除算ルーチンが組み込まれている場合は、余りも提供されていることがわかります。
それでも、モジュラ演算を最適化する方法を本当に理解したい場合は、研究が必要なモジュラー算術に特化した数論の小さなブランチがあります。たとえば、モジュラー算術は魔方陣を生成するのに非常に便利です。
したがって、その流れの中で、xの例のモジュラスの数学を非常に低レベルで見てみましょう。これは、除算と比較してどれほど単純であるかを示しているはずです。
たぶん、問題について考えるより良い方法は、基数とモジュロ算術の観点からです。たとえば、目標はDOW mod 7を計算することです。ここで、DOWは曜日の16ビット表現です。これは次のように書くことができます:
DOW = DOW_HI*256 + DOW_LO
DOW%7 = (DOW_HI*256 + DOW_LO) % 7
= ((DOW_HI*256)%7 + (DOW_LO % 7)) %7
= ((DOW_HI%7 * 256%7) + (DOW_LO%7)) %7
= ((DOW_HI%7 * 4) + (DOW_LO%7)) %7
このように表現すると、上位バイトと下位バイトのモジュロ7の結果を個別に計算できます。高値の結果に4を掛けて低値に加算し、最後に7を法として結果を計算します。
8ビット数のmod7の結果の計算も、同様の方法で実行できます。次のように、8ビットの数値を8進数で書き込むことができます。
X = a*64 + b*8 + c
ここで、a、b、およびcは3ビットの数値です。
X%7 = ((a%7)*(64%7) + (b%7)*(8%7) + c%7) % 7
= (a%7 + b%7 + c%7) % 7
= (a + b + c) % 7
以来64%7 = 8%7 = 1
もちろん、a、b、cは
c = X & 7
b = (X>>3) & 7
a = (X>>6) & 7 // (actually, a is only 2-bits).
の可能な最大値はa+b+c
です7+7+3 = 17
。したがって、もう1つの8進ステップが必要になります。完全な(テストされていない)Cバージョンは次のように書くことができます:
unsigned char Mod7Byte(unsigned char X)
{
X = (X&7) + ((X>>3)&7) + (X>>6);
X = (X&7) + (X>>3);
return X==7 ? 0 : X;
}
PICバージョンを書くのに少し時間を費やしました。実際の実装は、上記とは少し異なります
Mod7Byte:
movwf temp1 ;
andlw 7 ;W=c
movwf temp2 ;temp2=c
rlncf temp1,F ;
swapf temp1,W ;W= a*8+b
andlw 0x1F
addwf temp2,W ;W= a*8+b+c
movwf temp2 ;temp2 is now a 6-bit number
andlw 0x38 ;get the high 3 bits == a'
xorwf temp2,F ;temp2 now has the 3 low bits == b'
rlncf WREG,F ;shift the high bits right 4
swapf WREG,F ;
addwf temp2,W ;W = a' + b'
; at this point, W is between 0 and 10
addlw -7
bc Mod7Byte_L2
Mod7Byte_L1:
addlw 7
Mod7Byte_L2:
return
これがアルゴリズムをテストするためのliitleルーチンです
clrf x
clrf count
TestLoop:
movf x,W
RCALL Mod7Byte
cpfseq count
bra fail
incf count,W
xorlw 7
skpz
xorlw 7
movwf count
incfsz x,F
bra TestLoop
passed:
最後に、16ビットの結果(私はテストしていません)について、次のように書くことができます。
uint16 Mod7Word(uint16 X)
{
return Mod7Byte(Mod7Byte(X & 0xff) + Mod7Byte(X>>8)*4);
}
スコット