次のように、インデックスの「正規」形式を定義します。
- [h] は最大マグニチュード インデックスで、符号は +1 です。
- [k] は 2 番目に大きいマグニチュード インデックスです。
- [l] は残りのインデックス
- すべての共通要因が除外されました
次に、すべてのインデックスを正規の形式に変換し、既に見つかったものと重複している場合は削除します。
このフォームでは、Miller インデックスの並べ替え、検索の高速化なども可能です。
私は物理学の学位を持っています。ミラー指数が大きくなりすぎないことはわかっていました。;-)
これが「正規化」手順です。因数分解に総当たりを使用しますが、問題の領域にはそれで十分だと思います。パフォーマンスが後で対処できる問題である場合。
2013-03-09: 事前に計算された素数の表 <= 31 を使用するように更新
public struct MillerIndex {
public int H { get; private set; }
public int K { get; private set; }
public int L { get; private set; }
public MillerIndex( int h, int k, int l) : this() {
H = h; K = k; L = l;
}
}
public static class MillereHandler {
static IList<int> Primes = new List<int> {2,3,5,7,11,13,17,19,23,29,31};
public static MillerIndex GetCanonical(MillerIndex mi) {
int h, k, l, sign;
if (Math.Abs(mi.H) > Math.Abs(mi.K) && Math.Abs(mi.H) > Math.Abs(mi.L) ) {
sign = Math.Sign(mi.H);
h = mi.H;
k = Math.Abs(mi.K) > Math.Abs(mi.L) ? mi.K : mi.L;
l = Math.Abs(mi.K) > Math.Abs(mi.L) ? mi.L : mi.K;
} else if (Math.Abs(mi.K) > Math.Abs(mi.H) && Math.Abs(mi.K) > Math.Abs(mi.L) ) {
sign = Math.Sign(mi.K);
h = mi.K;
k = Math.Abs(mi.H) > Math.Abs(mi.L) ? mi.H : mi.L;
l = Math.Abs(mi.H) > Math.Abs(mi.L) ? mi.L : mi.H;
} else {
sign = Math.Sign(mi.L);
h = mi.L;
k = Math.Abs(mi.H) > Math.Abs(mi.K) ? mi.H : mi.K;
l = Math.Abs(mi.H) > Math.Abs(mi.K) ? mi.K : mi.H;
}
h *= sign; k *= sign; l *= sign;
foreach (var i in Primes.Where(i=> (i^2) < l) ) {
while ( (h/i)*i == h && (k/i)*i == k && (l/i)*i == l ) {
h /= h/i; k /= k/i; l /= l/i;
}
}
return new MillerIndex(h, k, l);
}
}