-
-
Save vxgmichel/080e9999a1020711f27cd60b5c2d14de to your computer and use it in GitHub Desktop.
| def adjugate(a, m=None): | |
| # Initialize | |
| sign = 1 | |
| previous = pivot = 1 | |
| # Bareiss formula | |
| def do_pivot(a, b, c, d, e): | |
| x = a * d - b * c | |
| if m is None: | |
| q, r = divmod(x, e) | |
| assert r == 0 | |
| return q | |
| q = x * pow(e, -1, m) | |
| return q % m | |
| # Assert square matrix | |
| n = len(a) | |
| assert all(len(row) == n for row in a) | |
| # Build augmented matrix | |
| am = [ | |
| list(map(int, row)) + [0] * i + [1] + [0] * (n - i - 1) | |
| for i, row in enumerate(a) | |
| ] | |
| # Iterate diagonally | |
| for c in range(n): | |
| # Test pivot | |
| if am[c][c] == 0: | |
| # Find pivot | |
| for i in range(c, n): | |
| if am[i][c] != 0: | |
| break | |
| # Non-invertible detection | |
| else: | |
| return 0, [[0] * n for _ in range(n)] | |
| # Switch rows | |
| am[c], am[i] = am[i], am[c] | |
| sign *= -1 | |
| # Get pivot | |
| previous, pivot = pivot, am[c][c] | |
| # Set zeros | |
| for i, row in enumerate(am): | |
| if i == c: | |
| continue | |
| am[i] = [ | |
| do_pivot(pivot, y, row[c], x, previous) for x, y in zip(row, am[c]) | |
| ] | |
| # Determinant | |
| determinant = sign * pivot | |
| if m is not None: | |
| determinant %= m | |
| # Return | |
| return determinant, [row[n:] for row in am] |
@orah29 Yes, every time the matrix is updated the result is taken modulo m. I used it mostly with m=2 since the addition in Z/2 corresponds to the XOR operation over bits.
With A = np.eye(9) + np.arange(9) there is no pb when I test adjugate(A) (=equal to np.linalg.det(A) * np.linalg.inv(A)) but adjugate(A, 256) stop on an AssertionError (r != 0). I have to deal with the ff Z/2^8. Obviously, detA % 256 != 0. I translated your code in numpy, but the pb is the same. Could you help me? Thank you per advance.
Sorry I confused Z/p with Z/p^n ... I going to use an irreducible polynomial to calculate on Z/256
@orah29 Oh right I made a mistake.
When m is provided, the new values should be computed not as (a * d - b * c) // e but as (a * d - b * c) * modinv(e, m) where modinv is the modular multiplicative inverse. Still, it requires that e and m are coprime, meaning m should be prime.
Hi Michel,
Could you confirm that 'm' is the size of a finite field?
Thank you