Coverage for src\pqlattice\lattice\_embeddings.py: 34%

41 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-01-10 12:32 +0100

1import numpy as np 

2 

3from .._utils import as_integer, zeros_mat 

4from ..linalg import hnf 

5from ..typing import Matrix, SquareMatrix, Vector, validate_aliases 

6 

7 

8def lwe_basis(A: Matrix, q: int) -> SquareMatrix: 

9 """ 

10 _summary_ 

11 

12 Parameters 

13 ---------- 

14 A : Matrix 

15 _description_ 

16 q : int 

17 _description_ 

18 

19 Returns 

20 ------- 

21 SquareMatrix 

22 _description_ 

23 """ 

24 # lattice: L = { x | Ax = 0 mod q } 

25 m, _ = A.shape 

26 Im = q * as_integer(np.identity(m)) 

27 G = np.vstack((A.T, Im)) 

28 H, _ = hnf(G) 

29 

30 return H[:m] 

31 

32 

33def sis_basis(A: Matrix, q: int) -> SquareMatrix: 

34 """ 

35 _summary_ 

36 

37 Parameters 

38 ---------- 

39 A : Matrix 

40 _description_ 

41 q : int 

42 _description_ 

43 

44 Returns 

45 ------- 

46 SquareMatrix 

47 _description_ 

48 """ 

49 # lattice: L = { y | y = xA mod q } 

50 B_p = lwe_basis(A, q) 

51 B_inv = np.linalg.inv(B_p.astype(float)) 

52 B_dual = np.round(q * B_inv.T).astype(int) 

53 return B_dual 

54 

55 

56@validate_aliases 

57def kannan(A: Matrix, b: Vector, q: int) -> SquareMatrix: 

58 """ 

59 _summary_ 

60 

61 Parameters 

62 ---------- 

63 A : Matrix 

64 _description_ 

65 b : Vector 

66 _description_ 

67 q : int 

68 _description_ 

69 

70 Returns 

71 ------- 

72 SquareMatrix 

73 _description_ 

74 """ 

75 return bai_galbraith(A, b, q, 1) 

76 

77 

78@validate_aliases 

79def bai_galbraith(A: Matrix, b: Vector, q: int, M: int) -> SquareMatrix: 

80 """ 

81 _summary_ 

82 

83 Parameters 

84 ---------- 

85 A : Matrix 

86 _description_ 

87 b : Vector 

88 _description_ 

89 q : int 

90 _description_ 

91 M : int 

92 _description_ 

93 

94 Returns 

95 ------- 

96 SquareMatrix 

97 _description_ 

98 """ 

99 m, n = A.shape 

100 

101 Im = as_integer(np.identity(m)) 

102 In = as_integer(np.identity(n)) 

103 

104 Zmxn = zeros_mat(m, n) 

105 Zmx1 = zeros_mat(m, 1) 

106 Znx1 = zeros_mat(n, 1) 

107 Z1xn = zeros_mat(1, n) 

108 

109 bT = b.reshape(1, -1) 

110 IM = M * (zeros_mat(1, 1) + 1) 

111 

112 return np.block( 

113 [ 

114 [q * Im, Zmxn, Zmx1], 

115 [A.T, In, Znx1], 

116 [-bT, Z1xn, IM], 

117 ] 

118 ) 

119 

120 

121@validate_aliases 

122def subset_sum(sequence: Vector, S: int) -> SquareMatrix: 

123 """ 

124 _summary_ 

125 

126 Parameters 

127 ---------- 

128 sequence : Vector 

129 _description_ 

130 S : int 

131 _description_ 

132 

133 Returns 

134 ------- 

135 SquareMatrix 

136 _description_ 

137 """ 

138 n = len(sequence) 

139 A = as_integer(np.identity(n + 1) * 2) 

140 A[-1] = 1 

141 A[:-1, -1] = sequence 

142 A[-1, -1] = S 

143 

144 return A 

145 

146 

147@validate_aliases 

148def ntru() -> SquareMatrix: 

149 raise NotImplementedError()