-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathPrimeField.java
110 lines (85 loc) · 2.57 KB
/
PrimeField.java
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
/*
* Reed-Solomon error-correcting code decoder (Java)
*
* Copyright (c) 2019 Project Nayuki
* All rights reserved. Contact Nayuki for licensing.
* https://www.nayuki.io/page/reed-solomon-error-correcting-code-decoder
*/
import java.util.Objects;
/**
* A finite field of the form Z<sub><var>p</var></sub>, where <var>p</var> is a prime number.
* Each element of this kind of field is an integer in the range [0, <var>p</var>).
* Both the field and the elements are immutable and thread-safe.
*/
public final class PrimeField extends Field<Integer> {
/*---- Fields ----*/
/**
* The modulus of this field, which is also the number
* of elements in this finite field. Must be prime.
*/
public final int modulus;
/*---- Constructor ----*/
/**
* Constructs a prime field with the specified modulus. The modulus must be a
* prime number, but this critical property is not checked by the constructor.
* @param mod the modulus, which must be prime
* @throws IllegalArgumentException if {@code mod} < 2
*/
public PrimeField(int mod) {
if (mod < 2)
throw new IllegalArgumentException("Modulus must be prime");
modulus = mod;
}
/*---- Methods ----*/
public Integer zero() {
return 0;
}
public Integer one() {
return 1;
}
public boolean equals(Integer x, Integer y) {
return check(x) == check(y);
}
public Integer negate(Integer x) {
return (modulus - check(x)) % modulus;
}
public Integer add(Integer x, Integer y) {
return (int)(((long)check(x) + check(y)) % modulus);
}
public Integer subtract(Integer x, Integer y) {
return (int)(((long)check(x) + modulus - check(y)) % modulus);
}
public Integer multiply(Integer x, Integer y) {
return (int)((long)check(x) * check(y) % modulus);
}
public Integer reciprocal(Integer w) {
// Extended Euclidean GCD algorithm
int x = modulus;
int y = check(w);
if (y == 0)
throw new ArithmeticException("Division by zero");
int a = 0;
int b = 1;
while (y != 0) {
int z = x % y;
int c = a - x / y * b;
x = y;
y = z;
a = b;
b = c;
}
if (x == 1)
return (int)(((long)a + modulus) % modulus);
else // All non-zero values must have a reciprocal
throw new IllegalStateException("Field modulus is not prime");
}
// Checks if the given object is non-null and within the range
// of valid values, and returns the unboxed primitive value.
private int check(Integer x) {
Objects.requireNonNull(x);
int y = x.intValue();
if (y < 0 || y >= modulus)
throw new IllegalArgumentException("Not an element of this field: " + y);
return y;
}
}