PSoC 4200 Prototyping Kit (6)

中国剰余定理自体の証明や、一般的な解法については省略し、今回の応用に関する解法のみを説明します。
その前に「合同式」について触れておきます。 以降、特にことわりのない限り変数や定数は整数であるとします。

a ≡ b (mod m)

と書いて「m を法 (modulus) として a と b は 合同」と読みます。
これは a を m で割った余りと b を m で割った余りとが等しいことを意味します。 つまり、m で割った余りとしての数値が同値ならば、割る前の b と a の「見た目」が違っていても (法 m のもとで) 同じとみなすということです。
今回の応用での計算方法の説明に移ります。
下のような「ディオファントス方程式」(Diophantine equation) を考えます。
(m1, m2 は係数、x, y は変数)

m1·x + m2·y = 1

ディオファントス方程式」とは「整数係数の多元不定方程式」の総称で、この場合は「整数係数の 2 元 1 次方程式」です。 ディオファントス方程式が与えられたとき、整数解や有理数解を求めることを「ディオファントス問題」といいます。
任意の係数の場合には整数解が求まるとは限りませんが、m1 と m2 とが「互いに素」つまり、共通の約数を持たない場合には整数解が存在します。
その解は「拡張されたユークリッド互除法」(Extended Euclidean algorithm) によって求めることができますが、今回の場合は自明な解がすぐ見つかります。

m1 = 216 = 65536
m2 = (m1 - 1) = (216 - 1) = 65535

ですから、

m1·x + m2·y = 1
m1·x + (m1-1)·y = 1
m1·(x + y) - y = 1

となり、x = 1、y = -1 という解が導きだされます。
求めたい (32 ビットの) 数を n として、キャプチャする (16 ビットの) 数を a1、a2 とすると、合同式で、

n ≡ a1 (mod m1)
n ≡ a2 (mod m2)

と表せます。
もとのディオファントス方程式の両辺に a1 を掛け、m1 による剰余を取って合同式で表すと、

a1·(m1·x + m2·y) = a1
a1·m1·x + a1·m2·y = a1


a1·m2·y ≡ a1 (mod m1)

となります。 なぜなら、左辺第 1 項の m1 を含む因子は m1 による除算で剰余はゼロとなり、右辺の a1 はすでに m1 で割った剰余となっているので変化しません。
同様に、もとのディオファントス方程式の両辺に a2 を掛け、m2 による剰余を取って合同式で表すと、

a2·(m1·x + m2·y) = a2
a2·m1·x + a2·m2·y = a2


a2·m1·x ≡ a2 (mod m2)

となります。
もとの数 n を上の 2 つの合同式の左辺の和、

n = a2·m1·x + a1·m2·y

で表すと、n と a1、a2 との合同関係を満たしていることが容易に分かります。
今回の応用での x, y の値 x = 1、y = -1 を代入して具体的な形にすると、

n = a2·m1·(1) + a1·m2·(-1)
   = a2·m1 - a1·m2
   = a2·m1 - a1·(m1 - 1)
   = (a2 - a1)·m1 + a1

これが今回の応用の基本的な式です。
m1 = 216 ですから、m1 による乗算は実際には 16 ビット左シフトするだけですみ、本当の乗算を行う必要はありません。
シフトによって空いた下位 16 ビットに 16 ビット数値である a1 がスッポリとおさまる形となり、式の上では「加算」になっていますが、実際には OR (論理和) 演算でも正しい結果が得られます。
次回は、この基本式をさらに変形していきます。