Example #1
0
        /// <summary>
        /// Получение обратного числа по модулю от текущего
        /// Используется расширенный алгоритм Евклида
        /// </summary>
        /// <param name="value">Первое число</param>
        /// <param name="modulo">Второй число</param>
        /// <param name="result">Результат</param>
        unsafe public static void Invert(uint[] value, uint[] modulo, uint[] result, uint[] cache1, uint[] cache2, uint[] cache3, uint[] cache4, uint[] cache5, uint[] cache6)
        {
            uint[] a = cache1;
            uint[] b = cache2;

            uint[] q      = cache3;
            uint[] r      = cache4;
            uint[] v2     = cache5;
            uint[] v1     = cache6;
            int    length = value.Length;

            ArrayCopyHelper.Copy(modulo, a, length);
            ArrayCopyHelper.Copy(value, b, length);
            v2[0] = 1;
            uint[] temp;
            // Пока целевое число не обнулилось
            while (!BigHelper.IfZero(b))
            {
                //TODO: Собственно бег по результату надо написать
                // Получить первый результат деления
                BigHelper.Divide(a, b, q, r);
                temp = a;
                a    = b;
                b    = r;
                r    = temp;

                Multiply(q, v2, modulo, q);
                Substraction(v1, q, modulo, v1);
                temp = v1;
                v1   = v2;
                v2   = temp;
            }
            ArrayCopyHelper.Copy(v1, result, length);
        }
Example #2
0
        unsafe public static void RightShift(uint[] value, uint[] result, uint[] modulo, uint[] cache, int shiftValue)
        {
            Array.Clear(cache, 0, cache.Length);
            // Количество сдвигов по индексам
            int indexShift = shiftValue / 32;
            // Количество внутренних сдвигов
            int valueShift = shiftValue % 32;

            // Заменить на указатели
            if (valueShift == 0)
            {
                Array.Copy(value, 0, cache, indexShift, value.Length);
            }
            else
            {
                int t1 = value.Length + indexShift;
                int t2 = 32 - valueShift;
                // Заполнить старший байт выходного вектора
                cache[t1] = (value[value.Length - 1] >> t2);
                t1--;
                // Заполнить серединку выходного массива
                for (int i = t1, i1 = value.Length - 1, i2 = value.Length - 2; i > indexShift; i--, i1--, i2--)
                {
                    cache[i] = (value[i1] << valueShift) + (value[i2] >> t2);
                }
                // Заполнить "младший" байт массива
                cache[indexShift] = (value[0] << valueShift);
            }
            BigHelper.Modulo(cache, modulo);
            ArrayCopyHelper.Copy(cache, result, value.Length);
        }
Example #3
0
        /// <summary>
        /// Умножение по модулю с результатом в отдельный массив
        /// </summary>
        /// <param name="value1">Первый массив</param>
        /// <param name="value2">Второй массив</param>
        /// <param name="modulo">Модуль</param>
        /// <param name="result">Итоговый массив, можно не чистить</param>
        /// <param name="cache">Кэш, в два раза больше длины вектора величин, в него копируются промежуточные результаты умножений</param>
        unsafe public static void Multiply(uint[] value1, uint value2, uint[] modulo, uint[] result, uint[] cache)
        {
            // Внешний цикл для скорости должен иметь меньший размер
            fixed(uint *value1Pointer = value1, moduloPointer = modulo, cachePointer = cache)
            {
                // Этап умножения
                ulong temp   = 0;
                int   length = modulo.Length;
                // Границы массивов
                uint *value1EndPointer    = value1Pointer + length;
                uint *tempValueEndPointer = cachePointer + cache.Length;

                // Переменные указатели
                uint *ptrCounter1, ptrResult;

                // Почистить кэш умножения
                for (ptrCounter1 = cachePointer; ptrCounter1 < tempValueEndPointer; ++ptrCounter1)
                {
                    *ptrCounter1 = 0;
                }
                // Внутренний цикл
                for (ptrCounter1 = value1Pointer, ptrResult = cachePointer; ptrCounter1 < value1EndPointer; ++ptrCounter1, ++ptrResult)
                {
                    // Нужно загрузить очередь блоков умножения современных процессоров (ориентировочно, латентность 3 такта, однако загрузка возможна каждый такт)
                    temp += (ulong)value2 * *ptrCounter1 + (ulong)*ptrResult;
                    *ptrResult = (uint)temp;
                    temp >>= 32;
                }
                *ptrResult = (uint)temp;
                BigHelper.Modulo(cache, modulo);
                ArrayCopyHelper.Copy(cache, result, length);
            }
        }
Example #4
0
        unsafe public static uint[] Pow(uint[] value1, uint[] modulo, int value2)
        {
            if (value2 == 0)
            {
                return new uint[] { 1 }
            }
            ;
            uint[] returnValue = new uint[value1.Length];
            ArrayCopyHelper.Copy(value1, returnValue, value1.Length);
            if (value2 < 0)
            {
                Invert(returnValue, modulo);
            }
            value2 = Math.Abs(value2);
            int nonZeroLength = BigHelper.MaxNonZeroBitIndex((uint)value2) + 1;

            if (nonZeroLength == 0)
            {
                return(null);
            }
            for (int i = nonZeroLength - 2; i >= 0; --i)
            {
                Multiply(returnValue, returnValue, modulo);
                if (((value2 >> i) & 1) == 1)
                {
                    Multiply(returnValue, value1, modulo);
                }
            }
            return(returnValue);
        }

        #endregion Pow
        #endregion Public methods
        #region Internal methods
        #endregion Internal methods
        #region Private methods
        #endregion Private methods
        #region  Events, overrides
        #endregion Events, overrides
        #endregion Methods
    }