-
Notifications
You must be signed in to change notification settings - Fork 15
/
gauss_solve.py
98 lines (74 loc) · 2.43 KB
/
gauss_solve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#----------------------------------------------------------------
# File: gauss_solve.py
#----------------------------------------------------------------
#
# Author: Marek Rychlik ([email protected])
# Date: Thu Sep 26 10:38:32 2024
# Copying: (C) Marek Rychlik, 2020. All rights reserved.
#
#----------------------------------------------------------------
# A Python wrapper module around the C library libgauss.so
import ctypes
gauss_library_path = './libgauss.so'
def unpack(A):
""" Extract L and U parts from A, fill with 0's and 1's """
n = len(A)
L = [[A[i][j] for j in range(i)] + [1] + [0 for j in range(i+1, n)]
for i in range(n)]
U = [[0 for j in range(i)] + [A[i][j] for j in range(i, n)]
for i in range(n)]
return L, U
def lu_c(A):
""" Accepts a list of lists A of floats and
it returns (L, U) - the LU-decomposition as a tuple.
"""
# Load the shared library
lib = ctypes.CDLL(gauss_library_path)
# Create a 2D array in Python and flatten it
n = len(A)
flat_array_2d = [item for row in A for item in row]
# Convert to a ctypes array
c_array_2d = (ctypes.c_double * len(flat_array_2d))(*flat_array_2d)
# Define the function signature
lib.lu_in_place.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.c_double))
# Modify the array in C (e.g., add 10 to each element)
lib.lu_in_place(n, c_array_2d)
# Convert back to a 2D Python list of lists
modified_array_2d = [
[c_array_2d[i * n + j] for j in range(n)]
for i in range(n)
]
# Extract L and U parts from A, fill with 0's and 1's
return unpack(modified_array_2d)
def lu_python(A):
n = len(A)
for k in range(n):
for i in range(k,n):
for j in range(k):
A[k][i] -= A[k][j] * A[j][i]
for i in range(k+1, n):
for j in range(k):
A[i][k] -= A[i][j] * A[j][k]
A[i][k] /= A[k][k]
return unpack(A)
def lu(A, use_c=False):
if use_c:
return lu_c(A)
else:
return lu_python(A)
if __name__ == "__main__":
def get_A():
""" Make a test matrix """
A = [[2.0, 3.0, -1.0],
[4.0, 1.0, 2.0],
[-2.0, 7.0, 2.0]]
return A
A = get_A()
L, U = lu(A, use_c = False)
print(L)
print(U)
# Must re-initialize A as it was destroyed
A = get_A()
L, U = lu(A, use_c=True)
print(L)
print(U)