kryptools 1.9.2__tar.gz → 1.9.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kryptools-1.9.2 → kryptools-1.9.4}/PKG-INFO +1 -1
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/__init__.py +3 -3
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/la.py +7 -5
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/lat.py +12 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/lat2.py +8 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/poly.py +96 -38
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools.egg-info/PKG-INFO +1 -1
- {kryptools-1.9.2 → kryptools-1.9.4}/pyproject.toml +1 -1
- {kryptools-1.9.2 → kryptools-1.9.4}/LICENSE +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/README.md +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/GF2.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/Zmod.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/aes.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/blockcipher.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/code.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/conway_polynomials.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/des.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/dlp.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/dlp_ic.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/dlp_qs.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/dlp_rho.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/ec.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor_dix.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor_ecm.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor_fmt.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor_pm1.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor_qs.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/factor_rho.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/intfuncs.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/keccak.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/nt.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/primes.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools/sha1.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools.egg-info/SOURCES.txt +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/setup.cfg +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_GF2.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_Zmod.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_aes.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_code.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_des.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_dlog.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_ec.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_factor.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_factor_fmt.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_factor_pm1.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_factor_qs.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_intfuncs.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_keccak.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_la.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_lat.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_nt.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_poly.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_primes.py +0 -0
- {kryptools-1.9.2 → kryptools-1.9.4}/tests/test_sha1.py +0 -0
|
@@ -5,7 +5,7 @@ Implemenation of same basic algorithms used in cryptography.
|
|
|
5
5
|
__author__ = "Gerald Teschl"
|
|
6
6
|
__copyright__ = "Copyright 2024-2026, Gerald Teschl"
|
|
7
7
|
__license__ = "MIT License"
|
|
8
|
-
__version__ = "1.9.
|
|
8
|
+
__version__ = "1.9.4"
|
|
9
9
|
__email__ = "Gerald.Teschl@univie.ac.at"
|
|
10
10
|
|
|
11
11
|
from .nt import egcd, cf, convergents, legendre_symbol, jacobi_symbol, sqrt_mod, euler_phi, carmichael_lambda, moebius_mu, is_carmichael_number, order, crt
|
|
@@ -16,8 +16,8 @@ from .dlp import dlog
|
|
|
16
16
|
from .ec import EC_Weierstrass
|
|
17
17
|
from .la import Matrix, zeros, eye, circulant, BinaryMatrix
|
|
18
18
|
from .lat import Lattice, random_unimodular_matrix
|
|
19
|
-
from .lat2 import q_ary_lattice, gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round_cvp, babai_plane_cvp, babai_plane_bnd, lll, svp, cvp, sis, isis, sis_search, isis_search
|
|
20
|
-
from .poly import Poly, PolyBinMult, lagrange_interpolation
|
|
19
|
+
from .lat2 import q_ary_lattice, gram_det, hadamard_ratio, hermite_factor, root_hermite_factor, hermite_nf, gram_schmidt, babai_round_cvp, babai_plane_cvp, babai_plane_bnd, lll, svp, cvp, sis, isis, sis_search, isis_search
|
|
20
|
+
from .poly import Poly, PolyBinMult, lagrange_interpolation, sylvester, resultant
|
|
21
21
|
from .Zmod import Zmod
|
|
22
22
|
from .GF2 import GF2, GF2_aes, GF2_miniaes, GF2_ghash
|
|
23
23
|
from .code import gen2pchk, hamming_dist, BinaryCode, GolayCode, HammingCode, ReedMullerCode, GoppaCode, CyclicCode, ReedSolomonCode, BCHCode
|
|
@@ -709,7 +709,7 @@ class Matrix:
|
|
|
709
709
|
R = [ list(map(lambda x: Fraction(int(x)), row)) for row in self.matrix ]
|
|
710
710
|
zero, one = ring(0), 1
|
|
711
711
|
elif self.is_integer():
|
|
712
|
-
ring =
|
|
712
|
+
ring = int
|
|
713
713
|
R = [ list(map(Fraction, row)) for row in self.matrix ]
|
|
714
714
|
zero, one = 0, 1
|
|
715
715
|
else:
|
|
@@ -868,17 +868,19 @@ def eye(m: int, n: int = None, zero=0, one=1, ring=None) -> "Matrix":
|
|
|
868
868
|
raise ValueError(f"Matrix dimensions {m}x{n} must be positive!")
|
|
869
869
|
return Matrix([[delta(i, j) for j in range(n)] for i in range(m)], ring=ring)
|
|
870
870
|
|
|
871
|
-
def rotate(l: list, n: int) -> list:
|
|
871
|
+
def rotate(l: list, n: int, skew=False) -> list:
|
|
872
872
|
"Rotate a list cyclically n places to the left."
|
|
873
873
|
n %= len(l)
|
|
874
|
+
if skew:
|
|
875
|
+
return l[n:] + [ -a for a in l[:n] ]
|
|
874
876
|
return l[n:] + l[:n]
|
|
875
877
|
|
|
876
|
-
def circulant(vector: list|tuple, m: int = None, ring=None) -> "Matrix":
|
|
877
|
-
"Returns a circulant matrix from the given vector."
|
|
878
|
+
def circulant(vector: list|tuple, m: int = None, ring=None, skew=False) -> "Matrix":
|
|
879
|
+
"Returns a (skew) circulant matrix from the given vector."
|
|
878
880
|
if m is None:
|
|
879
881
|
m = len(vector)
|
|
880
882
|
vector = list(reversed(vector))
|
|
881
|
-
return Matrix([rotate(vector, -n-1) for n in range(m)], ring=ring)
|
|
883
|
+
return Matrix([rotate(vector, -n-1, skew=skew) for n in range(m)], ring=ring)
|
|
882
884
|
|
|
883
885
|
class BinaryMatrix:
|
|
884
886
|
"""
|
|
@@ -473,6 +473,18 @@ class Lattice():
|
|
|
473
473
|
"Compute the Hadamard ratio of the current basis."
|
|
474
474
|
return (self.gram_det() / prod(map(self.norm2, self.U)) ) ** (1 / self.len)
|
|
475
475
|
|
|
476
|
+
def hermite_factor(self) -> float:
|
|
477
|
+
"Compute the Hermit factor of the current basis."
|
|
478
|
+
if self.Nu is not None:
|
|
479
|
+
norm = self.Nu[0] ** (1/2)
|
|
480
|
+
else:
|
|
481
|
+
norm = self.norm2(self.U[0]) ** (1/2)
|
|
482
|
+
return norm / (self.gram_det() ** (1 / self.len))
|
|
483
|
+
|
|
484
|
+
def root_hermite_factor(self) -> float:
|
|
485
|
+
"Compute the root Hermit factor of the current basis."
|
|
486
|
+
return self.hermite_factor() ** (1 / (self.len - 1))
|
|
487
|
+
|
|
476
488
|
def svp(self, method: str = 'all', delta: float = 0.75) -> Matrix:
|
|
477
489
|
"Solve the SVP (approximately) using a given method."
|
|
478
490
|
method = method.lower()
|
|
@@ -45,6 +45,14 @@ def hadamard_ratio(M: Matrix) -> float:
|
|
|
45
45
|
m = M.rows
|
|
46
46
|
return (gram_det(M) / prod([M[:, i].norm() for i in range(m)])) ** (1 / m)
|
|
47
47
|
|
|
48
|
+
def hermite_factor(M: Matrix) -> float:
|
|
49
|
+
"Compute the Hermite factor of the current basis."
|
|
50
|
+
return M[:, 0].norm() / (gram_det(M) ** (1 / M.rows))
|
|
51
|
+
|
|
52
|
+
def root_hermite_factor(M: Matrix) -> float:
|
|
53
|
+
"Compute the Hermite root factor of the current basis."
|
|
54
|
+
return hermite_factor(M) ** (1 / (M.rows - 1))
|
|
55
|
+
|
|
48
56
|
def babai_round_cvp(x: Matrix, U: Matrix) -> Matrix:
|
|
49
57
|
"Babai's rounding algorithm for approximately solving the CVP."
|
|
50
58
|
s = U.inv() * x
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
Polynomials
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from math import prod, comb
|
|
5
|
+
from math import prod, gcd, lcm, comb, sqrt
|
|
6
|
+
from fractions import Fraction
|
|
6
7
|
from numbers import Number
|
|
7
8
|
from random import randint
|
|
8
9
|
from itertools import combinations
|
|
9
10
|
from copy import copy
|
|
10
11
|
from .Zmod import Zmod
|
|
11
12
|
from .nt import crt
|
|
13
|
+
from .la import Matrix, zeros
|
|
12
14
|
|
|
13
15
|
class Poly:
|
|
14
16
|
"""
|
|
@@ -102,7 +104,7 @@ class Poly:
|
|
|
102
104
|
def __hash__(self):
|
|
103
105
|
return hash(tuple(self.coeff))
|
|
104
106
|
|
|
105
|
-
def __repr__(self, latex=None):
|
|
107
|
+
def __repr__(self, latex: bool|None = None):
|
|
106
108
|
def prx(i: int) -> str:
|
|
107
109
|
if i == 0:
|
|
108
110
|
return ""
|
|
@@ -116,7 +118,7 @@ class Poly:
|
|
|
116
118
|
|
|
117
119
|
if latex is None:
|
|
118
120
|
latex = self.__class__.print_latex
|
|
119
|
-
if
|
|
121
|
+
if len(self.coeff) == 1:
|
|
120
122
|
return str(self.coeff[0])
|
|
121
123
|
one = self.coeff[0]**0
|
|
122
124
|
plus = ""
|
|
@@ -132,25 +134,17 @@ class Poly:
|
|
|
132
134
|
tmp += plus + prx(i)
|
|
133
135
|
plus = " + "
|
|
134
136
|
continue
|
|
135
|
-
|
|
136
|
-
if
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
s = s.sharp()
|
|
147
|
-
if plus and s < 0:
|
|
148
|
-
tmp += " - " + str(-s)
|
|
149
|
-
if i != 0:
|
|
150
|
-
tmp += " " + prx(i)
|
|
151
|
-
continue
|
|
152
|
-
except: # pylint: disable=W0702
|
|
153
|
-
pass
|
|
137
|
+
if not s + one and i != 0 and str(s)[0] == '-':
|
|
138
|
+
if plus:
|
|
139
|
+
plus = " "
|
|
140
|
+
tmp += plus + "- " + prx(i)
|
|
141
|
+
plus = " + "
|
|
142
|
+
continue
|
|
143
|
+
if plus and str(s)[0] == '-':
|
|
144
|
+
tmp += " - " + str(-s)
|
|
145
|
+
if i != 0:
|
|
146
|
+
tmp += " " + prx(i)
|
|
147
|
+
continue
|
|
154
148
|
tmp += plus + str(s)
|
|
155
149
|
if i != 0:
|
|
156
150
|
tmp += " " + prx(i)
|
|
@@ -181,7 +175,7 @@ class Poly:
|
|
|
181
175
|
def __eq__(self, other):
|
|
182
176
|
if not isinstance(other, self.__class__):
|
|
183
177
|
return False
|
|
184
|
-
return
|
|
178
|
+
return self.coeff == other.coeff
|
|
185
179
|
|
|
186
180
|
def __bool__(self):
|
|
187
181
|
return bool(self.degree()) or bool(self.coeff[0])
|
|
@@ -306,7 +300,16 @@ class Poly:
|
|
|
306
300
|
return self.__class__([other * s for s in self.coeff], modulus = self.modulus, cyclic = self.cyclic, check = False)
|
|
307
301
|
return NotImplemented
|
|
308
302
|
ls, lo = len(self.coeff), len(other.coeff)
|
|
309
|
-
|
|
303
|
+
modulus = self.modulus
|
|
304
|
+
if not modulus and other.modulus:
|
|
305
|
+
modulus = other.modulus
|
|
306
|
+
cyclic = self.cyclic
|
|
307
|
+
if not self.cyclic and other.cyclic:
|
|
308
|
+
cyclic = other.cyclic
|
|
309
|
+
modulus = other.modulus
|
|
310
|
+
if (ls == 1 and not self.coeff[0]) or (lo == 1 and not other.coeff[0]):
|
|
311
|
+
return self.__class__([zero], modulus = modulus, cyclic = cyclic, check = False)
|
|
312
|
+
if cyclic:
|
|
310
313
|
if self.cyclic:
|
|
311
314
|
cyclic = self.cyclic
|
|
312
315
|
modulus = self.modulus
|
|
@@ -397,6 +400,22 @@ class Poly:
|
|
|
397
400
|
"Sum of the absolute value of all coefficients."
|
|
398
401
|
return sum(abs(c) for c in self.coeff)
|
|
399
402
|
|
|
403
|
+
def norm(self) -> int:
|
|
404
|
+
"Euclidean norm of the coefficients."
|
|
405
|
+
return sqrt(sum(abs(c)**2 for c in self.coeff))
|
|
406
|
+
|
|
407
|
+
def content(self) -> int:
|
|
408
|
+
"Return the content, the gcd of all coefficients, of a polynomial."
|
|
409
|
+
if not all(map(lambda _: isinstance(_, int), self.coeff)):
|
|
410
|
+
raise ValueError("Content requires integer coefficients.")
|
|
411
|
+
return gcd(*self.coeff)
|
|
412
|
+
|
|
413
|
+
def primitive_part(self) -> int:
|
|
414
|
+
"Return the primitive part of a polynomial."
|
|
415
|
+
if not all(map(lambda _: isinstance(_, int), self.coeff)):
|
|
416
|
+
raise ValueError("Primitive part requires integer coefficients.")
|
|
417
|
+
return self // gcd(*self.coeff)
|
|
418
|
+
|
|
400
419
|
def __floordiv__(self, other: "Poly") -> "Poly":
|
|
401
420
|
return self.divmod(other)[0]
|
|
402
421
|
|
|
@@ -554,18 +573,24 @@ class Poly:
|
|
|
554
573
|
"Least common multiple with a given polynomial."
|
|
555
574
|
return self * other // self.gcd(other)
|
|
556
575
|
|
|
557
|
-
def egcd(self, other: "Poly") -> ("Poly", "Poly", "Poly"):
|
|
558
|
-
"""Perform the extended Euclidean agorithm for polynomials. Returns gcd, x, y such that
|
|
576
|
+
def egcd(self, other: "Poly", integer:bool = False) -> ("Poly", "Poly", "Poly"):
|
|
577
|
+
"""Perform the extended Euclidean agorithm for polynomials. Returns gcd, x, y such that self * x + other * y = gcd."""
|
|
559
578
|
zero, one, _ = self._guess_ring()
|
|
560
579
|
if not isinstance(other, self.__class__):
|
|
561
580
|
raise NotImplementedError(f"Cannot perform egcd: {other} must be a polynomial.")
|
|
581
|
+
if integer:
|
|
582
|
+
if not( all(map(lambda _: isinstance(_, int), self.coeff)) and all(map(lambda _: isinstance(_, int), other.coeff)) ):
|
|
583
|
+
raise ValueError("The option 'integer' requires integer coefficients.")
|
|
562
584
|
if not self:
|
|
563
585
|
if not other:
|
|
564
586
|
return self.__class__([zero], check = False), self.__class__([zero], check = False), self.__class__([zero], check = False)
|
|
565
|
-
if other.coeff[-1] == one:
|
|
587
|
+
if other.coeff[-1] == one or integer:
|
|
566
588
|
return other, self.__class__([zero], check = False), self.__class__([one], check = False)
|
|
567
589
|
return other / other.coeff[-1], __class__([zero], check = False), self.__class__([one / other.coeff[-1]], check = False)
|
|
568
|
-
|
|
590
|
+
if integer:
|
|
591
|
+
r0, r1 = self.applyfunc(Fraction), other.applyfunc(Fraction)
|
|
592
|
+
else:
|
|
593
|
+
r0, r1 = self, other
|
|
569
594
|
x0, x1 = self.__class__([one], check = False), self.__class__([zero], check = False)
|
|
570
595
|
y0, y1 = x1, x0
|
|
571
596
|
while r1:
|
|
@@ -574,9 +599,17 @@ class Poly:
|
|
|
574
599
|
x0, x1 = x1, x0 - x1 * q
|
|
575
600
|
y0, y1 = y1, y0 - y1 * q
|
|
576
601
|
lcr0 = r0.coeff[-1]
|
|
577
|
-
if lcr0
|
|
578
|
-
|
|
579
|
-
|
|
602
|
+
if lcr0 != one:
|
|
603
|
+
r0, x0, y0 = r0 / lcr0, x0 / lcr0, y0 / lcr0
|
|
604
|
+
if integer:
|
|
605
|
+
lcmx = lcm(*map(lambda _: _.denominator, x0.coeff))
|
|
606
|
+
lcmy = lcm(*map(lambda _: _.denominator, y0.coeff))
|
|
607
|
+
lcmxy = lcm(lcmx,lcmy)
|
|
608
|
+
r0, x0, y0 = lcmxy * r0, lcmxy * x0, lcmxy * y0
|
|
609
|
+
r0.map(int)
|
|
610
|
+
x0.map(int)
|
|
611
|
+
y0.map(int)
|
|
612
|
+
return r0, x0, y0
|
|
580
613
|
|
|
581
614
|
def derivative(self) -> "Poly":
|
|
582
615
|
"Returns the formal derivative."
|
|
@@ -767,7 +800,7 @@ class PolyBinMult():
|
|
|
767
800
|
self.monomials.append(combination)
|
|
768
801
|
i += 1
|
|
769
802
|
|
|
770
|
-
def __repr__(self, latex=None):
|
|
803
|
+
def __repr__(self, latex: bool|None = None):
|
|
771
804
|
def prx(i: int) -> str:
|
|
772
805
|
if len(self.__class__.print_x) >= self.m:
|
|
773
806
|
return self.__class__.print_x[i]
|
|
@@ -792,7 +825,7 @@ class PolyBinMult():
|
|
|
792
825
|
def _repr_mimebundle_(self, **kwargs): # pylint: disable=W0613
|
|
793
826
|
return {
|
|
794
827
|
"text/plain": repr(self),
|
|
795
|
-
"text/latex": "$" + self.__repr__(latex=True) + "$" # pylint: disable=C2801
|
|
828
|
+
"text/latex": "$" + self.__repr__(latex = True) + "$" # pylint: disable=C2801
|
|
796
829
|
}
|
|
797
830
|
|
|
798
831
|
def index2monomial(self, idx: int) -> tuple|None:
|
|
@@ -842,7 +875,7 @@ class PolyBinMult():
|
|
|
842
875
|
val += prod(x[i] for i in monomial)
|
|
843
876
|
return val % 2
|
|
844
877
|
|
|
845
|
-
def __eq__(self, other):
|
|
878
|
+
def __eq__(self, other: "PolyBinMult"):
|
|
846
879
|
if not isinstance(other, self.__class__):
|
|
847
880
|
return False
|
|
848
881
|
return not bool(self + other)
|
|
@@ -850,7 +883,7 @@ class PolyBinMult():
|
|
|
850
883
|
def __bool__(self):
|
|
851
884
|
return bool(self.monomials)
|
|
852
885
|
|
|
853
|
-
def __add__(self, other) -> "PolyBinMult":
|
|
886
|
+
def __add__(self, other: "PolyBinMult") -> "PolyBinMult":
|
|
854
887
|
if not isinstance(other, self.__class__):
|
|
855
888
|
return NotImplemented
|
|
856
889
|
if other.m != self.m:
|
|
@@ -870,7 +903,7 @@ class PolyBinMult():
|
|
|
870
903
|
|
|
871
904
|
__neg__ = __pos__
|
|
872
905
|
|
|
873
|
-
def __mul__(self, other) -> "PolyBinMult":
|
|
906
|
+
def __mul__(self, other: "PolyBinMult") -> "PolyBinMult":
|
|
874
907
|
if isinstance(other, self.__class__):
|
|
875
908
|
return self.multiply(other)
|
|
876
909
|
if isinstance(other, int):
|
|
@@ -879,14 +912,14 @@ class PolyBinMult():
|
|
|
879
912
|
return self.__class__([], self.m)
|
|
880
913
|
return NotImplemented
|
|
881
914
|
|
|
882
|
-
def __rmul__(self, other) -> "PolyBinMult":
|
|
915
|
+
def __rmul__(self, other: "PolyBinMult") -> "PolyBinMult":
|
|
883
916
|
if isinstance(other, int):
|
|
884
917
|
if other % 2:
|
|
885
918
|
return self
|
|
886
919
|
return self.__class__([], self.m)
|
|
887
920
|
return NotImplemented
|
|
888
921
|
|
|
889
|
-
def multiply(self, other) -> "PolyBinMult":
|
|
922
|
+
def multiply(self, other: "PolyBinMult") -> "PolyBinMult":
|
|
890
923
|
"Polynomial Multiplication."
|
|
891
924
|
res = []
|
|
892
925
|
for monomials in self.monomials:
|
|
@@ -929,3 +962,28 @@ def lagrange_interpolation(x_coordinates: list, y_coordinates: list) -> "Poly":
|
|
|
929
962
|
poly += (y /
|
|
930
963
|
prod([x - xx for xx in x_coordinates if xx != x], start=one)) * L
|
|
931
964
|
return poly
|
|
965
|
+
|
|
966
|
+
def sylvester(p: "Poly", q: "Poly") -> "Matrix":
|
|
967
|
+
"Sylvester matrix of the given polynomials."
|
|
968
|
+
n = q.degree()
|
|
969
|
+
m = p.degree()
|
|
970
|
+
S = zeros(m + n)
|
|
971
|
+
k = 0
|
|
972
|
+
for i in range(n):
|
|
973
|
+
j = k
|
|
974
|
+
for c in p.coeff:
|
|
975
|
+
S[j, i] = c
|
|
976
|
+
j += 1
|
|
977
|
+
k = k + 1
|
|
978
|
+
k = 0
|
|
979
|
+
for i in range(n, m + n):
|
|
980
|
+
j = k
|
|
981
|
+
for c in q.coeff:
|
|
982
|
+
S[j, i] = c
|
|
983
|
+
j += 1
|
|
984
|
+
k = k + 1
|
|
985
|
+
return S
|
|
986
|
+
|
|
987
|
+
def resultant(p: "Poly", q: "Poly") -> int:
|
|
988
|
+
"Resultant of the given polynomials."
|
|
989
|
+
return sylvester(p,q).det()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|