public void TestV3fCoder()
 {
     foreach (var bits in new[] { 5, 8, 12, 16, 20, 24, 32 })
     {
         RasterTest(V3fCoder.RasterForBits(bits));
     }
 }
        public void NeigbourTest(uint raster)
        {
            var coder = new V3fCoder(raster);

            for (uint code = 0; code < coder.Count; code++)
            {
                uint[] neighbours = new uint[8];
                V3f    n          = coder.DecodeOnCube(code, false);
                uint   nCount     = coder.NeighbourCodes(code, neighbours);

                float min = float.MaxValue;
                float max = float.MinValue;
                for (uint nc = 0; nc < nCount; nc++)
                {
                    V3f   nv   = coder.DecodeOnCube(neighbours[nc], false);
                    float diff = (nv - n).Length;
                    if (diff < min)
                    {
                        min = diff;
                    }
                    if (diff > max)
                    {
                        max = diff;
                    }
                }

                if (min < 0.000001)
                {
                    Console.WriteLine("min too small");
                }
                if (max > 2.0 * min)
                {
                    Console.WriteLine("max too large");
                }

                if (raster < 3)
                {
                    Console.WriteLine("code {0} min {1} max {2}",
                                      code, min, max);
                }

                min *= 0.99f;

                for (uint nc0 = 0; nc0 < nCount; nc0++)
                {
                    V3f nv0 = coder.DecodeOnCube(neighbours[nc0], false);
                    for (uint nc1 = nc0 + 1; nc1 < nCount; nc1++)
                    {
                        V3f   nv1  = coder.DecodeOnCube(neighbours[nc1], false);
                        float diff = (nv1 - nv0).Length;
                        if (diff < min)
                        {
                            Console.Write("neighbours too close");
                        }
                    }
                }
            }
        }
        public void RasterTest(uint raster)
        {
            int iraster = (int)raster;

            V3fCoder coder = new V3fCoder(raster);

            uint step  = 1;
            bool large = false;

            if (iraster > 52)
            {
                step = 7; large = true;
            }
            if (iraster > 591)
            {
                step = 63;
            }
            if (iraster > 6688)
            {
                step = 2039;
            }

            int bits = (int)Fun.Ceiling(Fun.Log2(coder.Count));

            Test.Begin("normal coder raster {0} ({1} bits)", iraster, bits);

            /*
             * Console.WriteLine("  raster = {0}", m_raster);
             * Console.WriteLine("  rasterMul2Sub1 = {0}", m_r2Sub1);
             * Console.WriteLine("  doubleRaster = {0}", m_doubleRaster);
             * Console.WriteLine("  invDoubleRaster = {0}", m_invDoubleRaster);
             * Console.WriteLine("  edgeBasis = {0}", m_edgeBasis);
             * Console.WriteLine("  cornerBasis = {0}", m_cornerBasis);
             */
            Test.Begin("testing {0} of {1} codes", 1 + ((long)coder.Count - 1) / (long)step, coder.Count);
            for (uint code = 0; code < coder.Count; code += step)
            {
                V3f  dir     = coder.Decode(code);
                uint newCode = coder.Encode(dir);
                Test.IsTrue(code == newCode);
            }
            Test.End();

            double minDot = 1.0;

            float eps = Constant <float> .PositiveTinyValue;

            float[] factorTable = { 1.0f - eps, 1.0f, 1.0f + eps };

            for (int sign = -1; sign < 2; sign += 2)
            {
                for (int axis = 0; axis < 3; axis++)
                {
                    float factor = factorTable[axis];

                    for (int xi = -2 * iraster; xi <= 2 * iraster; xi++)
                    {
                        if (large && (xi > 3 - 2 * iraster) && (xi < -3))
                        {
                            continue;
                        }
                        if (large && (xi < 2 * iraster - 3) && (xi > +3))
                        {
                            continue;
                        }
                        double x = (double)xi * factor / (2 * iraster);
                        #if (!V3FCODER_NO_WARP)
                        x = V3fCoder.SphericalOfBox(x);
                        #endif
                        for (int yi = -2 * iraster; yi <= 2 * iraster; yi++)
                        {
                            if (large && (yi > 3 - 2 * iraster) && (yi < -3))
                            {
                                continue;
                            }
                            if (large && (yi < 2 * iraster - 3) && (yi > +3))
                            {
                                continue;
                            }
                            double y = (double)yi * factor / (2 * iraster);

                            #if (!V3FCODER_NO_WARP)
                            y = V3fCoder.SphericalOfBox(y);
                            #endif
                            V3f n = new V3f(0, 0, 0); // init to make compiler h.
                            n[axis]           = sign;
                            n[(axis + 1) % 3] = (float)x;
                            n[(axis + 2) % 3] = (float)y;

                            n.Normalize();

                            uint code = coder.Encode(n);
                            V3f  newN = coder.Decode(code);

                            double newDot = V3f.Dot(n, newN);
                            if (newDot < minDot)
                            {
                                minDot = newDot;
                            }
                        }
                    }
                }
            }
            double maxErr = System.Math.Acos(minDot) * 180.0 / System.Math.PI;
            Report.Line("maximal error {0:g4} degrees", maxErr);
            Test.End();
        }