1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
using System;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math.EC
{
internal abstract class Mod
{
public static void Invert(uint[] p, uint[] x, uint[] z)
{
int len = p.Length;
if (Nat.IsOne(len, x))
{
Array.Copy(x, 0, z, 0, len);
return;
}
uint[] u = Nat.Copy(len, x);
uint[] a = Nat.Create(len);
a[0] = 1;
if ((u[0] & 1) == 0)
{
InversionStep(p, u, a);
}
if (Nat.IsOne(len, u))
{
Array.Copy(a, 0, z, 0, len);
return;
}
uint[] v = Nat.Copy(len, p);
uint[] b = Nat.Create(len);
for (;;)
{
if (Nat.Gte(len, u, v))
{
Subtract(p, a, b, a);
Nat.Sub(len, u, v, u);
if ((u[0] & 1) == 0)
{
InversionStep(p, u, a);
}
if (Nat.IsOne(len, u))
{
Array.Copy(a, 0, z, 0, len);
return;
}
}
else
{
Subtract(p, b, a, b);
Nat.Sub(len, v, u, v);
if ((v[0] & 1) == 0)
{
InversionStep(p, v, b);
}
if (Nat.IsOne(len, v))
{
Array.Copy(b, 0, z, 0, len);
return;
}
}
}
}
public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z)
{
int len = p.Length;
int c = Nat.Sub(len, x, y, z);
if (c != 0)
{
Nat.Add(len, z, p, z);
}
}
private static void InversionStep(uint[] p, uint[] u, uint[] x)
{
int len = p.Length;
int count = 0;
while (u[0] == 0)
{
Nat.ShiftDownWord(u, len, 0);
count += 32;
}
int zeroes = GetTrailingZeroes(u[0]);
if (zeroes > 0)
{
Nat.ShiftDownBits(u, len, zeroes, 0);
count += zeroes;
}
for (int i = 0; i < count; ++i)
{
uint c = (x[0] & 1) == 0 ? 0 : Nat.Add(len, x, p, x);
Nat.ShiftDownBit(x, len, c);
}
}
private static int GetTrailingZeroes(uint x)
{
// assert x != 0;
int count = 0;
while ((x & 1) == 0)
{
x >>= 1;
++count;
}
return count;
}
}
}
|