public void ReferenceTest()
        {
            int inchannels = 7, outchannels = 11, inwidth = 13;

            float[] xval  = (new float[inwidth * inchannels]).Select((_, idx) => idx * 1e-3f).ToArray();
            float[] gyval = (new float[inwidth * outchannels]).Select((_, idx) => idx * 1e-3f).Reverse().ToArray();

            Map1D x  = new Map1D(inchannels, inwidth, 1, xval);
            Map1D gy = new Map1D(outchannels, inwidth, 1, gyval);

            Filter1D gw = Reference(x, gy);

            float[] gw_expect =
            {
                2.748200e-02f, 2.847000e-02f, 2.945800e-02f, 3.044600e-02f, 3.143400e-02f, 3.242200e-02f, 3.341000e-02f,
                2.693600e-02f, 2.791100e-02f, 2.888600e-02f, 2.986100e-02f, 3.083600e-02f, 3.181100e-02f, 3.278600e-02f,
                2.639000e-02f, 2.735200e-02f, 2.831400e-02f, 2.927600e-02f, 3.023800e-02f, 3.120000e-02f, 3.216200e-02f,
                2.584400e-02f, 2.679300e-02f, 2.774200e-02f, 2.869100e-02f, 2.964000e-02f, 3.058900e-02f, 3.153800e-02f,
                2.529800e-02f, 2.623400e-02f, 2.717000e-02f, 2.810600e-02f, 2.904200e-02f, 2.997800e-02f, 3.091400e-02f,
                2.475200e-02f, 2.567500e-02f, 2.659800e-02f, 2.752100e-02f, 2.844400e-02f, 2.936700e-02f, 3.029000e-02f,
                2.420600e-02f, 2.511600e-02f, 2.602600e-02f, 2.693600e-02f, 2.784600e-02f, 2.875600e-02f, 2.966600e-02f,
                2.366000e-02f, 2.455700e-02f, 2.545400e-02f, 2.635100e-02f, 2.724800e-02f, 2.814500e-02f, 2.904200e-02f,
                2.311400e-02f, 2.399800e-02f, 2.488200e-02f, 2.576600e-02f, 2.665000e-02f, 2.753400e-02f, 2.841800e-02f,
                2.256800e-02f, 2.343900e-02f, 2.431000e-02f, 2.518100e-02f, 2.605200e-02f, 2.692300e-02f, 2.779400e-02f,
                2.202200e-02f, 2.288000e-02f, 2.373800e-02f, 2.459600e-02f, 2.545400e-02f, 2.631200e-02f, 2.717000e-02f,
            };

            float[] gw_actual = gw.ToArray();

            AssertError.Tolerance(gw_expect, gw_actual, 1e-7f, 1e-5f, $"mismatch value {inchannels},{outchannels},{inwidth}");
        }
        public void OptimizeTest()
        {
            float max_err = 0;

            foreach (int batch in new int[] { 1, 2 })
            {
                foreach (int inchannels in new int[] { 1, 2, 3, 4, 5, 10, 15, 20 })
                {
                    foreach (int outchannels in new int[] { 7, 13 })
                    {
                        foreach (int inwidth in new int[] { 8, 9, 13, 17 })
                        {
                            float[] xval  = (new float[inwidth * inchannels * batch]).Select((_, idx) => idx * 1e-3f).ToArray();
                            float[] gyval = (new float[inwidth * outchannels * batch]).Select((_, idx) => idx * 1e-3f).Reverse().ToArray();

                            Map1D x  = new Map1D(inchannels, inwidth, batch, xval);
                            Map1D gy = new Map1D(outchannels, inwidth, batch, gyval);

                            Filter1D gw           = Reference(x, gy);
                            Filter1D gw_optimized = OptimizedReference(x, gy);

                            float[] gw_expect = gw.ToArray();
                            float[] gw_actual = gw_optimized.ToArray();

                            AssertError.Tolerance(gw_expect, gw_actual, 1e-7f, 1e-5f, $"mismatch value {inchannels},{outchannels},{inwidth},{batch}");

                            Console.WriteLine($"pass: {inchannels},{outchannels},{inwidth},{batch}");
                        }
                    }
                }
            }

            Console.WriteLine($"maxerr:{max_err}");
        }
        public void ExecuteTest()
        {
            float max_err = 0;

            foreach (int batch in new int[] { 1, 2 })
            {
                foreach (int inchannels in new int[] { 1, 2, 3, 4, 5, 10, 15, 20 })
                {
                    foreach (int outchannels in new int[] { 7, 13 })
                    {
                        foreach (int kwidth in new int[] { 1, 3, 5 })
                        {
                            foreach (int stride in new int[] { 1, 2, 3 })
                            {
                                foreach (int inwidth in new int[] { 8, 9, 13, 17 })
                                {
                                    int outwidth = (inwidth - kwidth) / stride + 1;

                                    float[] xval  = (new float[inwidth * inchannels * batch]).Select((_, idx) => idx * 1e-3f).ToArray();
                                    float[] gyval = (new float[outwidth * outchannels * batch]).Select((_, idx) => idx * 1e-3f).Reverse().ToArray();

                                    Map1D x  = new Map1D(inchannels, inwidth, batch, xval);
                                    Map1D gy = new Map1D(outchannels, outwidth, batch, gyval);

                                    Filter1D gw = Reference(x, gy, kwidth, stride);

                                    OverflowCheckedTensor x_tensor  = new OverflowCheckedTensor(Shape.Map1D(inchannels, inwidth, batch), xval);
                                    OverflowCheckedTensor gy_tensor = new OverflowCheckedTensor(Shape.Map1D(outchannels, outwidth, batch), gyval);

                                    OverflowCheckedTensor gw_tensor = new OverflowCheckedTensor(Shape.Kernel1D(inchannels, outchannels, kwidth));

                                    KernelProduct ope = new KernelProduct(inwidth, inchannels, outchannels, kwidth, stride, batch);

                                    ope.Execute(x_tensor, gy_tensor, gw_tensor);

                                    float[] gw_expect = gw.ToArray();
                                    float[] gw_actual = gw_tensor.State;

                                    CollectionAssert.AreEqual(xval, x_tensor.State);
                                    CollectionAssert.AreEqual(gyval, gy_tensor.State);

                                    AssertError.Tolerance(gw_expect, gw_actual, 1e-7f, 1e-5f, ref max_err, $"mismatch value {inchannels},{outchannels},{kwidth},{stride},{inwidth},{batch}");

                                    Console.WriteLine($"pass: {inchannels},{outchannels},{kwidth},{stride},{inwidth},{batch}");
                                }
                            }
                        }
                    }
                }
            }

            Console.WriteLine($"maxerr:{max_err}");
        }
        public void ReferenceTest()
        {
            int channels = 7, kwidth = 3, stride = 2, inwidth = 13;
            int outwidth = (inwidth - kwidth) / stride + 1;

            float[] xval  = (new float[inwidth * channels]).Select((_, idx) => idx * 1e-3f).ToArray();
            float[] gyval = (new float[outwidth * channels]).Select((_, idx) => idx * 1e-3f).Reverse().ToArray();

            Map1D x  = new Map1D(channels, inwidth, 1, xval);
            Map1D gy = new Map1D(channels, outwidth, 1, gyval);

            Filter1D gw = Reference(x, gy, kwidth, stride);

            float[] gw_expect =
            {
                3.22000007e-03f, 3.14499997e-03f, 3.05800000e-03f, 2.95899995e-03f, 2.84800003e-03f, 2.72500003e-03f, 2.58999993e-03f,
                4.20700014e-03f, 4.08999994e-03f, 3.96100013e-03f, 3.81999998e-03f, 3.66699998e-03f, 3.50199989e-03f, 3.32499994e-03f,
                5.19399997e-03f, 5.03499992e-03f, 4.86399978e-03f, 4.68100002e-03f, 4.48600017e-03f, 4.27900022e-03f, 4.06000018e-03f,
            };

            float[] gw_actual = gw.ToArray();

            AssertError.Tolerance(gw_expect, gw_actual, 1e-7f, 1e-5f, $"mismatch value {channels},{kwidth},{stride},{inwidth}");
        }
        public void ReferenceTest()
        {
            int inchannels = 7, outchannels = 11, kwidth = 3, stride = 2, inwidth = 13;
            int outwidth = (inwidth - kwidth) / stride + 1;

            float[] xval  = (new float[inwidth * inchannels]).Select((_, idx) => idx * 1e-3f).ToArray();
            float[] gyval = (new float[outwidth * outchannels]).Select((_, idx) => idx * 1e-3f).Reverse().ToArray();

            Map1D x  = new Map1D(inchannels, inwidth, 1, xval);
            Map1D gy = new Map1D(outchannels, outwidth, 1, gyval);

            Filter1D gw = Reference(x, gy, kwidth, stride);

            float[] gw_expect =
            {
                5.180000e-03f, 5.405000e-03f, 5.630000e-03f, 5.855000e-03f, 6.080000e-03f,
                6.305000e-03f, 6.530000e-03f, 4.970000e-03f, 5.189000e-03f, 5.408000e-03f,
                5.627000e-03f, 5.846000e-03f, 6.065000e-03f, 6.284000e-03f, 4.760000e-03f,
                4.973000e-03f, 5.186000e-03f, 5.399000e-03f, 5.612000e-03f, 5.825000e-03f,
                6.038000e-03f, 4.550000e-03f, 4.757000e-03f, 4.964000e-03f, 5.171000e-03f,
                5.378000e-03f, 5.585000e-03f, 5.792000e-03f, 4.340000e-03f, 4.541000e-03f,
                4.742000e-03f, 4.943000e-03f, 5.144000e-03f, 5.345000e-03f, 5.546000e-03f,
                4.130000e-03f, 4.325000e-03f, 4.520000e-03f, 4.715000e-03f, 4.910000e-03f,
                5.105000e-03f, 5.300000e-03f, 3.920000e-03f, 4.109000e-03f, 4.298000e-03f,
                4.487000e-03f, 4.676000e-03f, 4.865000e-03f, 5.054000e-03f, 3.710000e-03f,
                3.893000e-03f, 4.076000e-03f, 4.259000e-03f, 4.442000e-03f, 4.625000e-03f,
                4.808000e-03f, 3.500000e-03f, 3.677000e-03f, 3.854000e-03f, 4.031000e-03f,
                4.208000e-03f, 4.385000e-03f, 4.562000e-03f, 3.290000e-03f, 3.461000e-03f,
                3.632000e-03f, 3.803000e-03f, 3.974000e-03f, 4.145000e-03f, 4.316000e-03f,
                3.080000e-03f, 3.245000e-03f, 3.410000e-03f, 3.575000e-03f, 3.740000e-03f,
                3.905000e-03f, 4.070000e-03f, 6.755000e-03f, 6.980000e-03f, 7.205000e-03f,
                7.430000e-03f, 7.655000e-03f, 7.880000e-03f, 8.105000e-03f, 6.503000e-03f,
                6.722000e-03f, 6.941000e-03f, 7.160000e-03f, 7.379000e-03f, 7.598000e-03f,
                7.817000e-03f, 6.251000e-03f, 6.464000e-03f, 6.677000e-03f, 6.890000e-03f,
                7.103000e-03f, 7.316000e-03f, 7.529000e-03f, 5.999000e-03f, 6.206000e-03f,
                6.413000e-03f, 6.620000e-03f, 6.827000e-03f, 7.034000e-03f, 7.241000e-03f,
                5.747000e-03f, 5.948000e-03f, 6.149000e-03f, 6.350000e-03f, 6.551000e-03f,
                6.752000e-03f, 6.953000e-03f, 5.495000e-03f, 5.690000e-03f, 5.885000e-03f,
                6.080000e-03f, 6.275000e-03f, 6.470000e-03f, 6.665000e-03f, 5.243000e-03f,
                5.432000e-03f, 5.621000e-03f, 5.810000e-03f, 5.999000e-03f, 6.188000e-03f,
                6.377000e-03f, 4.991000e-03f, 5.174000e-03f, 5.357000e-03f, 5.540000e-03f,
                5.723000e-03f, 5.906000e-03f, 6.089000e-03f, 4.739000e-03f, 4.916000e-03f,
                5.093000e-03f, 5.270000e-03f, 5.447000e-03f, 5.624000e-03f, 5.801000e-03f,
                4.487000e-03f, 4.658000e-03f, 4.829000e-03f, 5.000000e-03f, 5.171000e-03f,
                5.342000e-03f, 5.513000e-03f, 4.235000e-03f, 4.400000e-03f, 4.565000e-03f,
                4.730000e-03f, 4.895000e-03f, 5.060000e-03f, 5.225000e-03f, 8.330000e-03f,
                8.555000e-03f, 8.780000e-03f, 9.005000e-03f, 9.230000e-03f, 9.455000e-03f,
                9.680000e-03f, 8.036000e-03f, 8.255000e-03f, 8.474000e-03f, 8.693000e-03f,
                8.912000e-03f, 9.131000e-03f, 9.350000e-03f, 7.742000e-03f, 7.955000e-03f,
                8.168000e-03f, 8.381000e-03f, 8.594000e-03f, 8.807000e-03f, 9.020000e-03f,
                7.448000e-03f, 7.655000e-03f, 7.862000e-03f, 8.069000e-03f, 8.276000e-03f,
                8.483000e-03f, 8.690000e-03f, 7.154000e-03f, 7.355000e-03f, 7.556000e-03f,
                7.757000e-03f, 7.958000e-03f, 8.159000e-03f, 8.360000e-03f, 6.860000e-03f,
                7.055000e-03f, 7.250000e-03f, 7.445000e-03f, 7.640000e-03f, 7.835000e-03f,
                8.030000e-03f, 6.566000e-03f, 6.755000e-03f, 6.944000e-03f, 7.133000e-03f,
                7.322000e-03f, 7.511000e-03f, 7.700000e-03f, 6.272000e-03f, 6.455000e-03f,
                6.638000e-03f, 6.821000e-03f, 7.004000e-03f, 7.187000e-03f, 7.370000e-03f,
                5.978000e-03f, 6.155000e-03f, 6.332000e-03f, 6.509000e-03f, 6.686000e-03f,
                6.863000e-03f, 7.040000e-03f, 5.684000e-03f, 5.855000e-03f, 6.026000e-03f,
                6.197000e-03f, 6.368000e-03f, 6.539000e-03f, 6.710000e-03f, 5.390000e-03f,
                5.555000e-03f, 5.720000e-03f, 5.885000e-03f, 6.050000e-03f, 6.215000e-03f,
                6.380000e-03f,
            };

            float[] gw_actual = gw.ToArray();

            AssertError.Tolerance(gw_expect, gw_actual, 1e-7f, 1e-5f, $"mismatch value {inchannels},{outchannels},{kwidth},{stride},{inwidth}");
        }