📄 ubiginteger.cs
字号:
if(expanded == null)
throw new OutOfMemoryException();
expanded[nEnd] = carry;
while(nEnd < nCapacity)
{
expanded[nEnd + 1] = values[nEnd];
nEnd ++;
}
values = expanded;
nCapacity ++;
}
nLength ++;
}
return this;
}
/// <summary>
/// 将指定大整数乘数:num = num.Multiply(multiplier),相当于Num *= multiplier
/// </summary>
/// <param name="multiplier">乘数</param>
/// <returns>返回被乘以乘数之后的乘积</returns>
public UBigInteger Multiply(UBigInteger multiplier)
{
if(multiplier == 0)
{
nLength = 0;
return this;
}
if(multiplier.nLength == 1)
{
return this.Multiply(multiplier.values[multiplier.nCapacity - 1]);
}
ulong sum, product = 0, carry = 0;
int nLoop = nLength + multiplier.nLength - 1;
int nEndThis = nCapacity - 1;
int nMultiplier = multiplier.nCapacity - 1;
nCapacity = nLoop + 1;
uint[] expanded = new uint[nCapacity];
if(expanded == null)
throw new OutOfMemoryException();
for(int i=0; i<nLoop; i++)
{
sum = carry;
carry = 0;
for(int j=0; j<multiplier.nLength; j++)
{
if((i-j) >= 0 && (i - j) < nLength)
{
product = values[nEndThis + j - i];
product *= multiplier.values[nMultiplier - j];
carry += product >> 32;
sum += product & 0xffffffff;
}
}
carry += sum >> 32;
expanded[nLoop - i] = (uint)sum;
}
if(carry > 0)
{
expanded[0] = (uint)carry;
nLength = nLoop + 1;
}
else
{
expanded[0] = 0;
nLength = nLoop;
}
values = expanded;
return this;
}
/// <summary>
/// 大数被减除一个大数:num = num.Subtraction(subtrahend),相当于Num -= substrahend
/// </summary>
/// <param name="subtrahend">减数</param>
/// <returns>返回减除减数之后的大整数</returns>
public UBigInteger Subtraction(UBigInteger subtrahend)
{
if(this <= subtrahend)
{
nLength = 0;
return this;
}
int nEndLeft = nCapacity;
int nEndRight = subtrahend.nCapacity;
int nLeftLength = nLength;
int nRightLength = subtrahend.nLength;
ulong minuend = 0;
uint carry = 0;
while(nRightLength > 0)
{
uint nLeft = values[--nEndLeft];
uint nRight = subtrahend.values[--nEndRight];
if(nLeft < nRight || (nLeft == nRight && carry > 0))
{
minuend = 0x100000000u + nLeft;
values[nEndLeft] = (uint)(minuend - nRight - carry);
carry = 1;
}
else
{
values[nEndLeft] = (uint)(nLeft - nRight - carry);
carry = 0;
}
nLeftLength --;
nRightLength --;
}
if(carry > 0)
{
while(values[--nEndLeft] == 0)
{
values[nEndLeft] = 0xffffffff;
nLeftLength --;
}
values[nEndLeft] --;
nLeftLength --;
}
while (nLeftLength > 0) // 搜索最高位
{
nLeftLength --;
nEndLeft --;
}
while(values[nEndLeft] == 0)
{
nEndLeft ++;
}
nLength = nCapacity - nEndLeft;
return this;
}
/// <summary>
/// 大数减除一个正整数:num = num.Subtraction(subtrahend),相当于Num -= subtrahend
/// </summary>
/// <param name="subtrahend">减数</param>
/// <returns>返回减除减数之后的剩余值</returns>
public UBigInteger Subtraction(uint subtrahend)
{
if(nLength == 0)
return this;
int nEnd = nCapacity - 1;
if(values[nEnd] > subtrahend)
{
values[nEnd] -= subtrahend;
return this;
}
if(nLength == 1)
{
this.Assign(0);
return this;
}
ulong minuend = 0x100000000u + values[nEnd];
values[nEnd] = (uint)(minuend - subtrahend);
while(values[--nEnd] ==0)
{
values[nEnd] = 0xffffffff;
}
values[nEnd] --;
if(values[nEnd] == 0)
nLength --;
return this;
}
/// <summary>
/// 大数加一个大数: num = num.Add(addend),相当于 Num += addend
/// </summary>
/// <param name="addend">加数</param>
/// <returns>返回大数加以加数之后的结果</returns>
public UBigInteger Addition(UBigInteger addend)
{
uint carry = 0;
ulong sum;
int nEndAugend = nCapacity;
int nMaxLength = addend.nLength > nLength ? addend.nLength : nLength;
if(nMaxLength >= nCapacity) // 防止溢出
{
nMaxLength ++;
uint[] expanded = new uint[nMaxLength];
if(expanded == null)
{
throw new OutOfMemoryException();
}
nCapacity = nMaxLength;
int nNumber = nLength;
while(nNumber -- > 0)
{
expanded[--nMaxLength] = values[--nEndAugend];
}
while(nMaxLength > 0)
{
expanded[--nMaxLength] = 0;
}
values = expanded;
}
int nEndAddend = addend.nCapacity; // 加数最低位
nEndAugend = nCapacity; // 被加数最低位
int nAddend = addend.nLength;
//int nAugend = nLength;
while(nAddend > 0)// && nEndAugend > 0)
{
sum = values[--nEndAugend];
sum += addend.values[--nEndAddend];
sum += carry;
values[nEndAugend] = (uint)(sum);
carry = (uint)(sum >> 32);
//nAugend --;
nAddend --;
}
while(carry > 0)
{
sum = values[--nEndAugend];
sum += carry;
values[nEndAugend] = (uint)sum;
carry = (uint)(sum >> 32);
}
// 确定最后的数据位数
nLength = 0;
while(nLength < nCapacity && values[nLength] == 0)
nLength ++;
nLength = nCapacity - nLength;
return this;
}
/// <summary>
/// 大数加一个32位正整数: num = num.Add(addend),Num += addend
/// </summary>
/// <param name="addend">加数</param>
/// <returns></returns>
public UBigInteger Addition(uint addend)
{
int nEnd = nCapacity;
int nNumber = nLength;
while(addend > 0 && nNumber > 0)
{
ulong sum = values[--nEnd];
sum += addend;
values[nEnd] = (uint)sum;
addend = (uint)(sum >> 32);
nNumber --;
}
if(addend > 0) // 进位
{
if(nEnd > 0)
{
values[--nEnd] = addend;
}
else
{
uint[] expanded = new uint[nCapacity + 1];
if(expanded == null)
{
throw new OutOfMemoryException();
}
expanded[0] = addend;
// to here the nEnd must be 0
while(nEnd < nCapacity)
{
expanded[nEnd + 1] = values[nEnd];
nEnd ++;
}
nCapacity ++;
values = expanded;
}
nLength ++;
}
return this;
}
/// <summary>
/// 求乘方的模:调用方式Num.RSATranslate(amp, mod),返回值: Num = Num^amp % mod
/// </summary>
/// <param name="amp">幂</param>
/// <param name="mod">用于取模的除数</param>
/// <returns>返回大整数实例,它被乘方amp次之后对mod取模</returns>
public UBigInteger RSATranslate(UBigInteger amp, UBigInteger mod)
{
UBigInteger saved = new UBigInteger(this); // 保存原始Num
int k = amp.nLength * 32 - 32;
uint nValue = amp.values[amp.nCapacity - amp.nLength];
while(nValue > 0)
{
nValue >>= 1;
k ++;
}
UBigInteger temp = new UBigInteger(nCapacity);
UBigInteger y = new UBigInteger(nCapacity);
for(int i=k-2; i>=0; i--)
{
int nStart = nCapacity - nLength;
y.Item = this;
y.Multiply(this.values[nStart]);
y.Modulus(mod);
while(nStart < this.nCapacity - 1)
{
//int j = 1;
y.LeftShift(1);
temp.Item = this;
temp.Multiply(values[++nStart]);
y.Addition(temp);
y.Modulus(mod);
//y.Item = y + (result * result.values[++ nStart]);
//y.Item = y % mod;
}
this.Item = y;
// if(nLength == 0)
// break;
nStart = nCapacity - nLength;
if((((amp.values[amp.nCapacity - 1 - (i >> 5)] >> (i & 0x1f)) & 1) != 0))
{
y.Item = saved;
y.Multiply(values[nStart]);
y.Modulus(mod);
//y.Item = (this) * result.values[nStart];
//y.Item = y % mod;
while(nStart < nCapacity - 1)
{
y.LeftShift(1);
//y.Item = y + (this) * result.values[++nStart];
//y.Item = y % mod;
temp.Item = saved;
temp.Multiply(values[++nStart]);
y.Addition(temp);
y.Modulus(mod);
}
this.Item = y;
}
}
return this;
}
#endregion
#region 内部操作方法
/// <summary>
/// 将大整数赋值为无符号32位整数
/// </summary>
/// <param name="value">无符号32位整数</param>
private void Assign(uint value)
{
if(value > 0)
{
nLength = 1;
values[nCapacity - 1] = value;
}
else
{
nLength = 0;
}
int nEnd = nCapacity - nLength;
while(nEnd > 0)
{
values[--nEnd] = 0;
}
}
/// <summary>
/// 刷新位数
/// </summary>
private void RefreshLength()
{
int nzPosition = 0;
while(nzPosition < nCapacity)
{
if(values[nzPosition] > 0)
{
break;
}
nzPosition ++;
}
nLength = nCapacity - nzPosition;
}
/// <summary>
/// 大整数左以一位(以0x100000000进制计算)
/// </summary>
/// <param name="digit2Pow32">位数</param>
private void LeftShift(int digit2Pow32) // 按照2^32进制左移位
{
if(digit2Pow32 == 0)
return;
int nStart = nCapacity - nLength;
int nNewLength = digit2Pow32 + nLength;
if(nNewLength > nCapacity)
{
uint[] expanded = new uint[nNewLength];
int nStartExpanded = 0;
while(nStart < nCapacity)
{
expanded[nStartExpanded ++] = values[nStart++];
}
while(nStartExpanded < nNewLength)
{
expanded[nStartExpanded ++] = 0;
}
values = expanded;
nCapacity = nLength = nNewLength;
}
else
{
nStart = nCapacity - nLength;
while(nStart < nCapacity)
{
values[nStart - digit2Pow32] = values[nStart];
values[nStart] = 0;
nStart ++;
}
nLength += digit2Pow32;
}
}
/// <summary>
/// 大整数右移digit2Pow32位(以0x100000000进制计算)
/// </summary>
/// <param name="digit2Pow32">右移位数</param>
private void RightShift(int digit2Pow32) // 按照2^32进制右移位
{
if(digit2Pow32 == 0)
return;
int nStart = nCapacity - nLength;
if(digit2Pow32 >= nLength)
{
while(nStart < nCapacity)
{
values[nStart ++] = 0;
}
nLength = 0;
return;
}
int nEnd = nCapacity - digit2Pow32 - 1;
while(nEnd >= nStart)
{
values[nEnd + digit2Pow32] = values[nEnd];
values[nEnd] = 0;
nEnd --;
}
nLength -= digit2Pow32;
}
#endregion
#region 素数操作
/// <summary>
/// 拉宾米勒测试素数
/// </summary>
/// <returns>如果大数实例是一个素数,返回真值,否则返回假</returns>
public bool PrimalityRabTest()
{
for(int i=0; i<(PrimeTable.Length); i++)
{
if( (this % (uint)PrimeTable[i]) == 0)
return false;
}
UBigInteger k = new UBigInteger(this);
k.values[k.nCapacity - 1] --;
UBigInteger a = new UBigInteger(nCapacity);
UBigInteger s = new UBigInteger(k.nCapacity);
for(int i=0; i<5; i++)
{
bool fPassed = false;
// s 赋予随机数
a.values[a.nCapacity - 1] = (uint)((random.Next(0x10000) << 16) + random.Next(0x10000));
a.nLength = 1;
s.Item = k;
UBigInteger pInv = null;
while((s.values[s.nCapacity-1] & 1 ) == 0)
{
// 右移一bit,即除以2
int nStart = s.nCapacity - s.nLength;
uint carry = 0;
while(nStart < s.nCapacity)
{
uint preSave = s.values[nStart] >> 1;
preSave |= carry;
carry = s.values[nStart] << 31;
s.values[nStart] = preSave;
nStart ++;
}
while(s.nLength > 0 && s.values[s.nCapacity - s.nLength] == 0)
s.nLength --;
pInv = RSATranslate(a, s, this);
if(pInv == k)
{
fPassed = true;
break;
}
}
if(pInv == 1)
fPassed = true;
if(!fPassed)
return false;
}
return true;
}
/// <summary>
/// 产生随机素数,nDigits2Pow32表示位数(2^32进制)
/// </summary>
/// <param name="nDigits2Pow32">以0x100000000进制计算的位数</param>
/// <returns>返回指定(0x100000000进制)位数的素数</returns>
public static UBigInteger RandomPrime(int nDigits2Pow32)
{
UBigInteger result = new UBigInteger(nDigits2Pow32);
result.nLength = nDigits2Pow32;
int i;
UBigInteger k = new UBigInteger(nDigits2Pow32);
UBigInteger a = new UBigInteger(nDigits2Pow32);
UBigInteger s = new UBigInteger(nDigits2Pow32);
bool fNotReady = true;
while(fNotReady)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -