Skip to content

Commit 4c3eabd

Browse files
committed
Small improvements/extensions
1 parent 6452fbc commit 4c3eabd

File tree

4 files changed

+128
-49
lines changed

4 files changed

+128
-49
lines changed

Diff for: doc/kryptools.ipynb

+53-20
Original file line numberDiff line numberDiff line change
@@ -1476,6 +1476,39 @@
14761476
"U"
14771477
]
14781478
},
1479+
{
1480+
"cell_type": "markdown",
1481+
"id": "e88ff7af-c3aa-4fdc-a83f-2f535df0b72c",
1482+
"metadata": {},
1483+
"source": [
1484+
"To get a random unimodular matrix use"
1485+
]
1486+
},
1487+
{
1488+
"cell_type": "code",
1489+
"execution_count": 45,
1490+
"id": "694c25e5-d01f-4acf-ab57-69bffb0fb9a8",
1491+
"metadata": {},
1492+
"outputs": [
1493+
{
1494+
"data": {
1495+
"text/plain": [
1496+
"[ 1, -8, -9 ]\n",
1497+
"[ 0, 3, 4 ]\n",
1498+
"[ 4, 2, 9 ]"
1499+
]
1500+
},
1501+
"execution_count": 45,
1502+
"metadata": {},
1503+
"output_type": "execute_result"
1504+
}
1505+
],
1506+
"source": [
1507+
"from kryptools import random_unimodular_matrix\n",
1508+
"\n",
1509+
"random_unimodular_matrix(3, max_val = 9)"
1510+
]
1511+
},
14791512
{
14801513
"cell_type": "markdown",
14811514
"id": "c8427b8b-db49-4fa1-ba07-63382746bcca",
@@ -1494,7 +1527,7 @@
14941527
},
14951528
{
14961529
"cell_type": "code",
1497-
"execution_count": 45,
1530+
"execution_count": 46,
14981531
"id": "d3c69787-da17-4cd3-b282-a68ee4d177e6",
14991532
"metadata": {},
15001533
"outputs": [
@@ -1504,7 +1537,7 @@
15041537
"3 x^2 + 2 x + 1"
15051538
]
15061539
},
1507-
"execution_count": 45,
1540+
"execution_count": 46,
15081541
"metadata": {},
15091542
"output_type": "execute_result"
15101543
}
@@ -1533,7 +1566,7 @@
15331566
},
15341567
{
15351568
"cell_type": "code",
1536-
"execution_count": 46,
1569+
"execution_count": 47,
15371570
"id": "8d4c4b43-e593-407a-92f8-86b653a09c8a",
15381571
"metadata": {},
15391572
"outputs": [],
@@ -1567,7 +1600,7 @@
15671600
},
15681601
{
15691602
"cell_type": "code",
1570-
"execution_count": 47,
1603+
"execution_count": 48,
15711604
"id": "bf50f802-93f5-4c79-b982-a208486f9a72",
15721605
"metadata": {},
15731606
"outputs": [
@@ -1578,7 +1611,7 @@
15781611
"[ 27 x^3 + 74 x^2 + 45 x + 61, 17 x^3 + 36 x^2 + 17 x + 64 ]"
15791612
]
15801613
},
1581-
"execution_count": 47,
1614+
"execution_count": 48,
15821615
"metadata": {},
15831616
"output_type": "execute_result"
15841617
}
@@ -1603,7 +1636,7 @@
16031636
},
16041637
{
16051638
"cell_type": "code",
1606-
"execution_count": 48,
1639+
"execution_count": 49,
16071640
"id": "9e0ebbd3-0d4b-4e1b-b4dd-323b5a86dc23",
16081641
"metadata": {},
16091642
"outputs": [
@@ -1614,7 +1647,7 @@
16141647
"[ 96 x^2 + x + 1 ]"
16151648
]
16161649
},
1617-
"execution_count": 48,
1650+
"execution_count": 49,
16181651
"metadata": {},
16191652
"output_type": "execute_result"
16201653
}
@@ -1634,7 +1667,7 @@
16341667
},
16351668
{
16361669
"cell_type": "code",
1637-
"execution_count": 49,
1670+
"execution_count": 50,
16381671
"id": "563280a9-27b9-4707-ae14-9aeef9bbe5a6",
16391672
"metadata": {},
16401673
"outputs": [
@@ -1645,7 +1678,7 @@
16451678
"[ 2 x ]"
16461679
]
16471680
},
1648-
"execution_count": 49,
1681+
"execution_count": 50,
16491682
"metadata": {},
16501683
"output_type": "execute_result"
16511684
}
@@ -1666,7 +1699,7 @@
16661699
},
16671700
{
16681701
"cell_type": "code",
1669-
"execution_count": 50,
1702+
"execution_count": 51,
16701703
"id": "fabcbecf-cf96-4211-a1e3-ad0f5a337a09",
16711704
"metadata": {},
16721705
"outputs": [
@@ -1677,7 +1710,7 @@
16771710
"[ 47 x^3 + 30 x^2 + 42 x + 47 ]"
16781711
]
16791712
},
1680-
"execution_count": 50,
1713+
"execution_count": 51,
16811714
"metadata": {},
16821715
"output_type": "execute_result"
16831716
}
@@ -1705,7 +1738,7 @@
17051738
},
17061739
{
17071740
"cell_type": "code",
1708-
"execution_count": 51,
1741+
"execution_count": 52,
17091742
"id": "9b566550-f23c-4fbc-8b7c-63bbee8e0c72",
17101743
"metadata": {},
17111744
"outputs": [
@@ -1744,7 +1777,7 @@
17441777
},
17451778
{
17461779
"cell_type": "code",
1747-
"execution_count": 52,
1780+
"execution_count": 53,
17481781
"id": "55c29e0c-e0c2-409a-af23-6590fd9cc545",
17491782
"metadata": {},
17501783
"outputs": [
@@ -1754,7 +1787,7 @@
17541787
"(113, 91)"
17551788
]
17561789
},
1757-
"execution_count": 52,
1790+
"execution_count": 53,
17581791
"metadata": {},
17591792
"output_type": "execute_result"
17601793
}
@@ -1776,7 +1809,7 @@
17761809
},
17771810
{
17781811
"cell_type": "code",
1779-
"execution_count": 53,
1812+
"execution_count": 54,
17801813
"id": "2a3d8e7d-71b3-4a93-b6cc-803f00432c56",
17811814
"metadata": {},
17821815
"outputs": [
@@ -1786,7 +1819,7 @@
17861819
"129"
17871820
]
17881821
},
1789-
"execution_count": 53,
1822+
"execution_count": 54,
17901823
"metadata": {},
17911824
"output_type": "execute_result"
17921825
}
@@ -1806,7 +1839,7 @@
18061839
},
18071840
{
18081841
"cell_type": "code",
1809-
"execution_count": 54,
1842+
"execution_count": 55,
18101843
"id": "bb93b5fc-99c9-4977-8299-9342b84e143d",
18111844
"metadata": {},
18121845
"outputs": [],
@@ -1826,7 +1859,7 @@
18261859
},
18271860
{
18281861
"cell_type": "code",
1829-
"execution_count": 55,
1862+
"execution_count": 56,
18301863
"id": "41e18357-da42-4cd7-bd4e-1c3355f1c69d",
18311864
"metadata": {},
18321865
"outputs": [],
@@ -1849,7 +1882,7 @@
18491882
},
18501883
{
18511884
"cell_type": "code",
1852-
"execution_count": 56,
1885+
"execution_count": 57,
18531886
"id": "af81d5f2-a524-4555-8e74-06a0c9a7ea08",
18541887
"metadata": {},
18551888
"outputs": [
@@ -1860,7 +1893,7 @@
18601893
" 0x02449ef2ed30a8deb96e584a08c329adbf1be87ce40f1a0e7b4e86178682c41a9c)"
18611894
]
18621895
},
1863-
"execution_count": 56,
1896+
"execution_count": 57,
18641897
"metadata": {},
18651898
"output_type": "execute_result"
18661899
}

Diff for: kryptools/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from .dlp import dlog
66
from .ec import EC_Weierstrass
77
from .factor import factorint
8-
from .la import Matrix
9-
from .lat import gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round_cvp, babai_plane_cvp, lagrange_lr, lll
8+
from .la import Matrix, zeros, eye
9+
from .lat import gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round_cvp, babai_plane_cvp, lagrange_lr, lll, random_unimodular_matrix
1010
from .nt import cf, convergents, jacobi_symbol, sqrt_mod, euler_phi, order, carmichael_lambda
1111
from .poly import Poly
1212
from .primes import sieve_eratosthenes, isprime

Diff for: kryptools/la.py

+65-18
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Linear algebra
33
"""
44

5-
from math import sqrt, prod
5+
from math import inf, sqrt, prod
66

77
class Matrix:
88
"""
@@ -48,12 +48,18 @@ def __getitem__(self, item):
4848
i, j = item
4949
if isinstance(i, int) and isinstance(j, int):
5050
return self.matrix[i][j]
51-
rows = range(self.rows)[i]
5251
if isinstance(i, int):
53-
rows = [ rows ]
54-
cols = range(self.cols)[j]
52+
rows = [ i ]
53+
elif isinstance(i, list):
54+
rows = i
55+
else:
56+
rows = range(self.rows)[i]
5557
if isinstance(j, int):
56-
cols = [ cols ]
58+
cols = [ j ]
59+
elif isinstance(j, list):
60+
cols = i
61+
else:
62+
cols = range(self.cols)[j]
5763
return Matrix([[self.matrix[i][j] for j in cols] for i in rows])
5864
i, j = divmod(item, self.cols)
5965
return self.matrix[i][j]
@@ -64,12 +70,18 @@ def __setitem__(self, item, value):
6470
if isinstance(i, int) and isinstance(j, int):
6571
self.matrix[i][j] = value
6672
return
67-
rows = range(self.rows)[i]
6873
if isinstance(i, int):
69-
rows = [ rows ]
70-
cols = range(self.cols)[j]
74+
rows = [ i ]
75+
elif isinstance(i, list):
76+
rows = i
77+
else:
78+
rows = range(self.rows)[i]
7179
if isinstance(j, int):
72-
cols = [ cols ]
80+
cols = [ j ]
81+
elif isinstance(j, list):
82+
cols = i
83+
else:
84+
cols = range(self.cols)[j]
7385
for i, ii in zip(cols,range(len(cols))):
7486
for j, jj in zip(rows,range(len(rows))):
7587
self.matrix[j][i] = value[jj,ii]
@@ -97,9 +109,17 @@ def norm2(self) -> float:
97109
"Squared Frobenius/Euclidean norm."
98110
return sum( sum(x*x for x in row) for row in self.matrix )
99111

100-
def norm(self) -> float:
101-
"Frobenius/Euclidean norm."
102-
return sqrt(self.norm2())
112+
def norm(self, p: int = 2) -> float:
113+
"p-norm of a matrix regarded as a vector."
114+
if p == 2:
115+
return sqrt(self.norm2())
116+
if p == 1:
117+
return sum( sum(abs(x) for x in row) for row in self.matrix )
118+
if p == inf:
119+
return max( max(abs(x) for x in row) for row in self.matrix )
120+
tmp = sum( sum(abs(x)**p for x in row) for row in self.matrix )
121+
return(tmp**(1/p))
122+
103123

104124
def dot(self, other) -> int:
105125
if self.rows == 1 and other.rows == 1 and self.cols == other.cols:
@@ -112,14 +132,16 @@ def transpose(self) -> "Matrix":
112132
return Matrix([list(i) for i in zip(*self.matrix)])
113133

114134
def multiply(self, other) -> "Matrix":
115-
if not isinstance(other, Matrix) or self.cols != other.rows:
135+
if not isinstance(other, Matrix):
116136
return NotImplemented
117-
result = [[0 for j in range(other.cols)] for i in range(self.rows)]
137+
if self.cols != other.rows:
138+
raise NotImplementedError("Matrix dimensions do not match!")
139+
result = self.zeros(self.rows, other.cols)
118140
for i in range(self.rows):
119141
for j in range(other.cols):
120142
for k in range(other.rows):
121-
result[i][j] += self.matrix[i][k] * other.matrix[k][j]
122-
return Matrix(result)
143+
result.matrix[i][j] += self.matrix[i][k] * other.matrix[k][j]
144+
return result
123145

124146
def __add__(self, other) -> "Matrix":
125147
if isinstance(other, Matrix) and other.cols == self.cols and other.rows == self.rows:
@@ -211,13 +233,38 @@ def inv(self) -> "Matrix":
211233
raise ValueError("Matrix is not invertible!")
212234
return MM[:,n:]
213235

236+
def zeros(self, m: int = None, n: int = None):
237+
if not m and not n:
238+
n, m = self.cols, self.rows
239+
elif not n:
240+
n = m
241+
zero = 0 * self[0]
242+
return Matrix([[ zero for j in range(n)] for i in range(m) ])
243+
244+
def eye(self, m: int = None, n: int = None):
245+
def delta(i, j):
246+
if i == j:
247+
return 1
248+
return 0
249+
if not m and not n:
250+
n, m = self.cols, self.rows
251+
elif not n:
252+
n = m
253+
zero = 0 * self[0]
254+
one = 1 + zero
255+
return Matrix([[ delta(i, j) for j in range(n) ] for i in range(m) ])
256+
214257

215-
def zeros(m:int, n: int) -> "Matrix":
258+
def zeros(m: int, n: int = None) -> "Matrix":
259+
if not n:
260+
n = m
216261
return Matrix([[ 0 for j in range(n)] for i in range(m) ])
217262

218-
def eye(m:int, n: int) -> "Matrix":
263+
def eye(m:int, n: int = None) -> "Matrix":
219264
def delta(i, j):
220265
if i == j:
221266
return 1
222267
return 0
268+
if not n:
269+
n = m
223270
return Matrix([[ delta(i, j) for j in range(n) ] for i in range(m) ])

0 commit comments

Comments
 (0)