/// <summary> /// Maximum Length Sequenceを録再したものを入力し、 /// MLSとのCircular Cross Correlationを計算し出力する。 /// </summary> /// <param name="recorded">Maximum Length Sequenceを録再したもの。長さは(1 << order)サンプル。</param> /// <returns></returns> public double[] Deconvolution(double[] from) { int N = mOrder; int P = (1 << N) - 1; if (from.Length != P + 1) { throw new ArgumentException("from.Length should be (1 << order)"); } // Walsh-Hadamard変換を使ってMLS deconvolutionを行う。 var reorderedFrom = new double[P + 1]; for (int i = 0; i < P + 1; ++i) { reorderedFrom[mFromReorder[i]] = from[i]; } var hR = FastWalshHadamardTransform.Transform(reorderedFrom); var hTo = new double[P + 1]; for (int i = 0; i < P + 1; ++i) { hTo[i] = -(hR[mToReorder[i]] - 1.0) / (P + 1); } //Print(hTo, "hTo"); return(hTo); }
public void TransformTest() { var dwht = new DiscreteWalshHadamardTransform(); var fwht = new FastWalshHadamardTransform(); var points = new List <double>(new double[] { 1, 2, 1, 2, 1, 3, 1, 5, 1, 1, 1, 8, 2, 1, 3, 4 }); var r1 = dwht.Transform(points.Select(d => new Point(0, d)).ToArray()).ToArray(); var r2 = fwht.Transform(points.Select(d => new Point(0, d)).ToArray()).ToArray(); for (var i = 0; i < 16; i++) { Assert.AreEqual(r1[i], r2[i]); } }
public void TransformTest() { var r = new Random(); var transformD = new DiscreteWalshHadamardTransform(); var transformF = new FastWalshHadamardTransform(); var points = new List <Point>(); for (int i = 0; i < 256; i++) { points.Add(new Point(i, r.Next())); } var first = transformD.Transform(points.ToArray()).ToList(); var second = transformF.Transform(points.ToArray()).ToList(); for (int i = 0; i < first.Count; i++) { Assert.AreEqual(first[i], second[i]); } }
public void Test(double[] recorded) { // 動作テスト int N = mOrder; int P = (1 << N) - 1; var from = new double[P + 1]; { int copySize = recorded.Length; if (from.Length < copySize) { copySize = from.Length; } Array.Copy(recorded, from, copySize); } byte[] mlsSeq; { var mls = new MaximumLengthSequence(N); mlsSeq = mls.Sequence(); for (int i = 0; i < mlsSeq.Length; ++i) { Console.Write("{0} ", mlsSeq[i]); } Console.WriteLine(""); } { var mlsD = new double[mlsSeq.Length]; for (int i = 0; i < mlsD.Length; ++i) { mlsD[i] = mlsSeq[i] * 2.0 - 1.0; } var ccc = CrossCorrelation.CalcCircularCrossCorrelation(mlsD, mlsD); for (int i = 0; i < ccc.Length; ++i) { Console.Write("{0:g2} ", ccc[i]); } Console.WriteLine(""); } var mlsMat = new MatrixGF2(P, P); { for (int y = 0; y < P; ++y) { for (int x = 0; x < P; ++x) { mlsMat.Set(y, x, (0 != mlsSeq[(x + y) % P]) ? GF2.One : GF2.Zero); } } } mlsMat.Print("MLS matrix"); // σ: mlsMatの左上N*N要素 var σ = mlsMat.Subset(0, 0, N, N); σ.Print("σ"); var σInv = σ.Inverse(); σInv.Print("σ^-1"); // S: MLS行列の上N行。 var S = mlsMat.Subset(0, 0, N, P); S.Print("S"); // Sの転置S^T S.Transpose().Print("S^T"); // L: Sの転置 x σInv var L = S.Transpose().Mul(σInv); L.Print("L"); // L x S == MLS行列 var LS = L.Mul(S); LS.Print("L x S"); int diff = LS.CompareTo(mlsMat); System.Diagnostics.Debug.Assert(diff == 0); // 2進で0~P-1までの値が入っている行列 var B = new MatrixGF2(P + 1, N); var Bt = new MatrixGF2(N, P + 1); for (int r = 0; r < P + 1; ++r) { for (int c = 0; c < N; ++c) { int v = r & (1 << (N - 1 - c)); var b = (v == 0) ? GF2.Zero : GF2.One; B.Set(r, c, b); Bt.Set(c, r, b); } } B.Print("B"); Bt.Print("Bt"); // アダマール行列H8 var H8 = MatrixGF2.Mul(B, Bt); H8.Print("H8"); var vTest = new double[P + 1]; for (int i = 0; i < P + 1; ++i) { vTest[i] = i; } var r1 = H8.ToMatrix().Mul(vTest); Print(r1, "R1"); var r2 = FastWalshHadamardTransform.Transform(vTest); Print(r2, "R2"); // Ps: S行列の列の値を2進数として、順番入れ替え行列を作る var Ps = new MatrixGF2(P + 1, P + 1); var PsReorder = new List <int>(); PsReorder.Add(0); for (int c = 0; c < P; ++c) { int sum = 0; for (int r = 0; r < N; ++r) { sum += (1 << (N - 1 - r)) * S.At(r, c).Val; } Console.WriteLine("Ps: c={0} sum={1}", c, sum); Ps.Set(sum, c + 1, GF2.One); PsReorder.Add(sum); } Ps.Print("Ps"); { var testMat = new WWMatrix(P + 1, 1); for (int r = 0; r < P + 1; ++r) { testMat.Set(r, 0, PsReorder[r]); } var PsTest = Ps.ToMatrix().Mul(testMat); PsTest.Print("Ps x n"); } // Pl: L行列の列の値を2進数として、順番入れ替え行列を作る var Pl = new MatrixGF2(P + 1, P + 1); var PlReorder = new List <int>(); PlReorder.Add(0); for (int r = 0; r < P; ++r) { int sum = 0; for (int c = 0; c < N; ++c) { sum += (1 << (N - 1 - c)) * L.At(r, c).Val; } Console.WriteLine("Pl: r={0} sum={1}", r, sum); Pl.Set(r + 1, sum, GF2.One); PlReorder.Add(sum); } Pl.Print("Pl"); S.Print("S"); var BtPs = Bt.Mul(Ps); BtPs.Print("BtPs"); L.Print("L"); var PlB = Pl.Mul(B); PlB.Print("PlB"); { var test2Mat = new WWMatrix(P + 1, 1); for (int r = 0; r < P + 1; ++r) { test2Mat.Set(r, 0, r); } var PlTest = Pl.ToMatrix().Mul(test2Mat); PlTest.Print("Pl x n"); } mlsMat.Print("MLS mat"); var Mhat = Pl.Mul(H8).Mul(Ps); Mhat.Print("Mhat"); // MLS deconvolution var decon = Mhat.ToMatrix().Mul(from); Print(decon, "decon"); // 同じ処理をWalsh-Hadamard変換を使って行う。 var reorderedFrom = new double[P + 1]; for (int i = 0; i < P + 1; ++i) { reorderedFrom[PsReorder[i]] = from[i]; } #if true var hR = FastWalshHadamardTransform.Transform(reorderedFrom); #else var hR = H8.ToMatrix().Mul(reorderedFrom); #endif var hTo = new double[P + 1]; for (int i = 0; i < P + 1; ++i) { hTo[i] = hR[PlReorder[i]]; } Print(hTo, "hTo"); }