private static void ScalarMultBase(byte[] k, PointAccum r) { Precompute(); PointSetNeutral(r); uint[] n = new uint[ScalarUints]; DecodeScalar(k, 0, n); // Recode the scalar into signed-digit form, then group comb bits in each block { uint c1 = Nat.CAdd(ScalarUints, ~(int)n[0] & 1, n, L, n); Debug.Assert(c1 == 0); uint c2 = Nat.ShiftDownBit(ScalarUints, n, 1U); Debug.Assert(c2 == (1U << 31)); for (int i = 0; i < ScalarUints; ++i) { n[i] = Interleave.Shuffle2(n[i]); } } PointPrecomp p = new PointPrecomp(); int cOff = (PrecompSpacing - 1) * PrecompTeeth; for (; ;) { for (int b = 0; b < PrecompBlocks; ++b) { uint w = n[b] >> cOff; int sign = (int)(w >> (PrecompTeeth - 1)) & 1; int abs = ((int)w ^ -sign) & PrecompMask; Debug.Assert(sign == 0 || sign == 1); Debug.Assert(0 <= abs && abs < PrecompPoints); PointLookup(b, abs, p); X25519Field.CSwap(sign, p.ypx_h, p.ymx_h); X25519Field.CNegate(sign, p.xyd); PointAddPrecomp(p, r); } if ((cOff -= PrecompTeeth) < 0) { break; } PointDouble(r); } }