public static unsafe DwtOutput Forward(double[] input, Wavelet wavelet, Int32 level)
        {
            Int32 Len = wavelet.DecompositionLow.Length;
            Int32 CircleInd;

            double[] output = new Double[input.Length];
            Double[] Buff   = new Double[input.Length];
            Buffer.BlockCopy(input, 0, output, 0, input.Length * 8);
            Double  BufScal = 0;
            Double  BufDet  = 0;
            Double *DecLow  = stackalloc Double[Len];
            Double *DecHigh = stackalloc Double[Len];

            for (int i = 0; i < Len; i++)
            {
                DecLow[i]  = wavelet.DecompositionLow[i];
                DecHigh[i] = wavelet.DecompositionHigh[i];
            }

            fixed(Double *pout = output, pbuf = Buff)
            {
                for (int lvl = 0; lvl < level; lvl++)
                {
                    Int32 Bound      = input.Length >> lvl;
                    Int32 StartIndex = -((Len >> 1) - 1);
                    Buffer.BlockCopy(output, 0, Buff, 0, Bound * 8);

                    for (int i = 0; i < Bound >> 1; i++)
                    {
                        for (int j = StartIndex, k = 0; k < Len; j++, k++)
                        {
                            if ((StartIndex < 0) || j >= Bound)
                            {
                                CircleInd = ((j % Bound) + Bound) % Bound;
                            }
                            else
                            {
                                CircleInd = j;
                            }
                            BufScal += DecLow[k] * pout[CircleInd];
                            BufDet  += DecHigh[k] * pout[CircleInd];
                        }
                        StartIndex            += 2;
                        pbuf[i]                = BufScal;
                        pbuf[i + (Bound >> 1)] = BufDet;
                        BufScal                = 0;
                        BufDet = 0;
                    }
                    Buffer.BlockCopy(Buff, 0, output, 0, Bound * 8);
                }
            }

            DwtOutput res = new DwtOutput(output, level, wavelet);

            return(res);
        }
        public static unsafe double[] Inverse(DwtOutput dwtInput)
        {
            var   wavelet = dwtInput.Wavelet;
            var   input   = dwtInput.FullVector;
            var   level   = dwtInput.Level;
            Int32 Len     = wavelet.ReconstructionLow.Length;
            Int32 CircleInd;

            double[] output     = new Double[input.Length];
            Double[] Buff       = new Double[input.Length];
            Double[] BufferLow  = new Double[input.Length];
            Double[] BufferHigh = new Double[input.Length];
            Buffer.BlockCopy(input, 0, output, 0, input.Length * 8);
            Double  Buf     = 0;
            Double *RecLow  = stackalloc Double[Len];
            Double *RecHigh = stackalloc Double[Len];

            for (int i = 0; i < Len; i++)
            {
                RecLow[i]  = wavelet.ReconstructionLow[i];
                RecHigh[i] = wavelet.ReconstructionHigh[i];
            }

            fixed(Double *pbuf = Buff, pLow = BufferLow, pHigh = BufferHigh)
            {
                for (int lvl = level; lvl > 0; lvl--)
                {
                    Int32 Bound      = input.Length >> lvl;
                    Int32 StartIndex = -((Len >> 1) - 1);
                    for (int i = 0, j = 0; i < Bound << 1; i += 2, j++)
                    {
                        pLow[i]      = 0;
                        pHigh[i]     = 0;
                        pLow[i + 1]  = output[j];
                        pHigh[i + 1] = output[Bound + j];
                    }

                    for (int i = 0; i < Bound << 1; i++)
                    {
                        for (int j = StartIndex, k = 0; k < Len; j++, k++)
                        {
                            if ((StartIndex < 0) || j >= (Bound << 1))
                            {
                                CircleInd = (j % (Bound << 1) + (Bound << 1)) % (Bound << 1);
                            }
                            else
                            {
                                CircleInd = j;
                            }
                            Buf += RecLow[k] * pLow[CircleInd] + RecHigh[k] * pHigh[CircleInd];
                        }
                        StartIndex += 1;
                        pbuf[i]     = Buf;
                        Buf         = 0;
                    }
                    Buffer.BlockCopy(Buff, 0, output, 0, Bound * 16);
                }
            }

            return(output);
        }