Skip to content

Commit 00b2139

Browse files
authored
optimize: reduce time complexity from O(t^2) to O(t) (leanEthereum#158)
1 parent 2306c35 commit 00b2139

1 file changed

Lines changed: 8 additions & 17 deletions

File tree

src/lean_spec/subspecs/poseidon2/permutation.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -211,26 +211,17 @@ def internal_linear_layer(state: List[Fp], params: Poseidon2Params) -> List[Fp]:
211211
width = params.width
212212
diag_vector = params.internal_diag_vectors
213213

214-
# Construct the M_I matrix explicitly.
214+
# Compute M_I * state = (J + D) * state = J*state + D*state
215215
#
216-
# It has dimensions width x width.
217-
m_i = [[Fp(value=1) for _ in range(width)] for _ in range(width)]
216+
# J*state is a vector where each element is the sum of all elements in state.
217+
# D*state is element-wise multiplication of diagonal with state.
218218

219-
# Add the diagonal part (D) to the all-ones matrix (J)
220-
#
221-
# The result is M_I = J + D.
222-
for i in range(width):
223-
m_i[i][i] += diag_vector[i]
224-
225-
# Perform standard matrix-vector multiplication: new_state = m_i * state
226-
#
227-
# Initialize the result vector with zeros.
228-
new_state = [Fp(value=0)] * width
219+
# Calculate the sum of all state elements once (for J*state)
220+
state_sum = sum(state, Fp(value=0))
229221

230-
# For each row in the matrix, calculate the dot product of that row with the state vector.
231-
for i in range(width):
232-
for j in range(width):
233-
new_state[i] += m_i[i][j] * state[j]
222+
# Compute new_state[i] = state_sum + diag_vector[i] * state[i]
223+
# This is equivalent to (J + D) * state but much faster.
224+
new_state = [state_sum + diag_vector[i] * state[i] for i in range(width)]
234225

235226
return new_state
236227

0 commit comments

Comments
 (0)