Example #1
0
        /// Compute `limbs/R` (mod l), where R is the Montgomery modulus 2^260

        public static UnpackedScalar montgomery_reduce(UInt128[] limbs)
        {
            (UInt128, ulong) part1(UInt128 sum)
            {
                var p = ((ulong)sum) * (Constant.LFACTOR) & (((ulong)1 << 52) - 1);

                return((sum + m(p, Constant.L.value.Span[0])) >> 52, p);
            }

            (UInt128, ulong) part2(UInt128 sum)
            {
                var w = ((ulong)sum) & (((ulong)1 << 52) - 1);

                return(sum >> 52, w);
            }

            // note: l3 is zero, so its multiplies can be skipped
            var l  = Constant.L;
            var ls = l.value.Span;

            // the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R
            UInt128 carry;
            ulong   n0;

            (carry, n0) = part1(limbs[0]);
            ulong n1;

            (carry, n1) = part1(carry + limbs[1] + m(n0, ls[1]));
            ulong n2;

            (carry, n2) = part1(carry + limbs[2] + m(n0, ls[2]) + m(n1, ls[1]));
            ulong n3;

            (carry, n3) = part1(carry + limbs[3] + m(n1, ls[2]) + m(n2, ls[1]));
            ulong n4;

            (carry, n4) = part1(carry + limbs[4] + m(n0, ls[4]) + m(n2, ls[2]) + m(n3, ls[1]));

            // limbs is divisible by R now, so we can divide by R by simply storing the upper half as the result
            ulong r0;

            (carry, r0) = part2(carry + limbs[5] + m(n1, ls[4]) + m(n3, ls[2]) + m(n4, ls[1]));
            ulong r1;

            (carry, r1) = part2(carry + limbs[6] + m(n2, ls[4]) + m(n4, ls[2]));
            ulong r2;

            (carry, r2) = part2(carry + limbs[7] + m(n3, ls[4]));
            ulong r3;

            (carry, r3) = part2(carry + limbs[8] + m(n4, ls[4]));
            var r4 = (ulong)carry;

            // result may be >= l, so attempt to subtract l
            return(UnpackedScalar.sub(new UnpackedScalar(new ulong[] { r0, r1, r2, r3, r4 }), l));
        }
Example #2
0
        /// Compute `a + b` (mod l)
        public static UnpackedScalar add(UnpackedScalar a, UnpackedScalar b)
        {
            var sum  = UnpackedScalar.zero();
            var sums = sum.value.Span;
            var mask = ((ulong)1 << 52) - 1;

            var asp = a.value.Span;
            var bsp = b.value.Span;

            // a + b
            ulong carry = 0;

            for (int i = 0; i < 5; i++)
            {
                carry   = asp[i] + bsp[i] + (carry >> 52);
                sums[i] = carry & mask;
            }


            // subtract l if the sum is >= l
            return(UnpackedScalar.sub(sum, Constant.L));
        }
Example #3
0
 public static Scalar operator -(Scalar rhs)
 {
     return(UnpackedScalar.sub(one().unpack(), rhs.unpack()).pack());
 }