singrdk/base/Libraries/Crypto/Digit2.cs

52 lines
1.8 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Diagnostics;
namespace Microsoft.Singularity.Crypto.PublicKey {
internal class Digit2 {
internal static Digit Lo(UInt64 x) {
return unchecked((UInt32)(x & Digit.MaxValue));
}
internal static Digit Hi(UInt64 x) {
Digit hi = unchecked((UInt32)(x >> Digit.BitN));
return hi;
}
internal static void
Div(UInt64 num, Digit denom, out Digit q, out Digit r) {
Digit numHi = Hi(num), numLo = Lo(num);
if (numHi >= denom) { throw new ArgumentException(); }
q = (Digit)(num / denom);
r = unchecked(numLo - denom * q);
Digit rr = unchecked((Digit)(num - denom * q));
Debug.Assert(rr == r, "internal error");
}
internal static void Div(
UInt64 num
, Digit denom
, Reciprocal recip
, out Digit q
, out Digit r
) {
Digit numHi = Hi(num)
, numLo = Lo(num)
, qEst = Digit.MaxValue - recip.EstQuotient(numHi, numLo, 0);
UInt64 rEst = unchecked(
((UInt64)(numHi - denom) << Digit.BitN | numLo)
+ (UInt64)qEst * denom
);
q = unchecked((Digit)(Hi(rEst) - qEst));
r = unchecked(Lo(rEst) + (denom & Hi(rEst)));
Digit qq, rr;
Div(num, denom, out qq, out rr);
Debug.Assert(qq == q && rr == r, "internal error");
}
}
}