forked from natikgadzhi/XNMaths
-
Notifications
You must be signed in to change notification settings - Fork 1
/
XNLinearEquationSystem.m
158 lines (116 loc) · 3.64 KB
/
XNLinearEquationSystem.m
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//
// XNLinearEquationSystem.m
// Assignation 3.2
//
// Created by Нат Гаджибалаев on 15.11.09.
// Copyright 2009 Нат Гаджибалаев. All rights reserved.
//
#import "XNLinearEquationSystem.h"
#import <Accelerate/Accelerate.h>
@implementation XNLinearEquationSystem
@synthesize iterationsSpent, iterationsLimit;
#pragma mark -
#pragma mark Initialization methods
- (XNLinearEquationSystem *) initWithMatrix: (XNMatrix *)newEquationMatrix
{
self = [super init];
equationMatrix = [newEquationMatrix retain];
leftSideMatrix = [newEquationMatrix copy];
[leftSideMatrix removeColumnAtIndex: (leftSideMatrix.columnsCount - 1)];
rightSideVector = [newEquationMatrix columnVectorAtIndex:(newEquationMatrix.columnsCount - 1)];
return self;
}
//
// sweep
// solves the equation system using lapack's sgtsv routine.
//
- (XNVector *) sweep
{
if( ![leftSideMatrix isSquare] ){
[NSException raise:@"Not a square matrix error." format:@"The left-side equation matrix should be square to use sweep."];
}
//
// params preparation
// n
NSUInteger n = [leftSideMatrix rowsCount];
// nrhs (b columns)
NSUInteger nrhs = 1;
// matrix representation with diagonals.
CGFloat *dl, *d, *du;
// b vector data
CGFloat *b;
// rows count in b vector
NSUInteger ldb = n;
// kinda return code
NSInteger info;
//
// Init float arrays
b = calloc(n, sizeof(CGFloat));
d = calloc(n, sizeof(CGFloat));
du = calloc(n-1, sizeof(CGFloat));
dl = calloc(n-1, sizeof(CGFloat));
for( NSUInteger i = 0; i < n; i++ ){
b[i] = [rightSideVector valueAtIndex:i];
d[i] = [leftSideMatrix valueAtRow:i column:i];
}
for( NSUInteger i = 0; i < (n-1); i++){
dl[i] = [leftSideMatrix valueAtRow:i+1 column:i];
du[i] = [leftSideMatrix valueAtRow:i column:i+1];
}
//
// call the routine
sgtsv_(&n, &nrhs, dl, d, du, b, &ldb, &info);
if( info != 0){
[NSException raise:@"Linear equation system sweep LAPACK error." format:@"LAPACK return code: %d", info];
}
//
// Create a solution vector from lapack output
XNVector *solution = [[XNVector alloc] initWithCapacity: n filledWith: b];
//
// Free resources after lapack routines
free(d);
free(b);
free(du);
free(dl);
//
// Autorelease and return solution vector
return [solution autorelease];
}
- (XNVector *) solveWithMaxIterations: (NSUInteger) aIterationsLimit withPrecision: (CGFloat) precision withFirstApproximation: (XNVector*) firstApproximation allowRelaxation: (BOOL) allowRelaxation
{
iterationsLimit = aIterationsLimit;
XNVector *solution = [firstApproximation retain];
XNVector *oldSolution = nil;
iterationsSpent = 1;
CGFloat speed = 1.5f;
while( (iterationsSpent < iterationsLimit) && [[[leftSideMatrix multiplyByVector:solution] substract: rightSideVector] norm] > precision){
oldSolution = [solution copy];
// calculate new solution and place it right into the old one.
for( NSInteger i = 0; i < solution.capacity; i++ ){
CGFloat newValue = [rightSideVector valueAtIndex: i];
for(NSInteger j = 0; j < [leftSideMatrix columnsCount]; j++ ){
if( i == j){
continue;
}
newValue -= [leftSideMatrix valueAtRow:i column:j] * [solution valueAtIndex:j];
}
newValue /= [leftSideMatrix valueAtRow: i column: i];
[solution setValue: newValue atIndex:i ];
}
iterationsSpent++;
if( allowRelaxation ){
for( NSInteger i = 0; i < solution.capacity; i++ ){
[ solution setValue: speed * [solution valueAtIndex: i] + (1 - speed)* [oldSolution valueAtIndex: i] atIndex: i];
}
}
}
return solution;
}
#pragma mark -
#pragma mark Dealloc
- (void) dealloc
{
[equationMatrix dealloc];
[super dealloc];
}
@end