-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrow.cpp
More file actions
314 lines (272 loc) · 8.42 KB
/
row.cpp
File metadata and controls
314 lines (272 loc) · 8.42 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#include "row.h"
#include <stdio.h>
// ===============================================================================
// PUBLIC
// ===============================================================================
// ===================== PUBLIC OPERATORS ================================
// ==============================================================================
/**
Vytiskne vsechny prvky tak jak jdou za sebou vcetne nul
*/
void ROW::print_full()
{
long ac=0;
for (long i=0;i<full_length;i++){
if (index[ac] == i && ac<value_number){
printf("%f\t",values[ac]);
ac++;
}else{
printf("0\t");
}
}
printf("\n");
}
// ==============================================================================
/**
\brief Ziska alokovane pole, bud najde dost. dlouhe, nebo zalokuje nove a nastavi ho jako vychozi.
Pouzivat jen kdyz nechci pouzivat prvky, ktere byly v radku.
*/
void ROW::initialize(const long& l)
{
if(allocated[a]){//je alokovane prvni pole?
if(length[a] > l){//je pole dostatecne dlouhe?
value_number=0;
return;
}else{//neni dost dlouhe... Co to druhe?
if(allocated[na]){//je vubec druhe alokovane?
if (length[na] > l){
switch_fields();
value_number=0;
return;
}
}else{//neni alokovane, zalokuj
switch_fields();
alloc(l);
return;
}
}
}else{//neni jeste alokovane prvni pole
alloc(l);
return;
}
}
// ==============================================================================
/**
*/
void ROW::operator+=(const ROW& b)
{
prepare_field((b.value_number + value_number));//orig pole bude volne k zapisu
merge_fields(b.values, val[na], b.index, in[na], b.value_number, value_number, values, index, value_number);
}
// ==============================================================================
/**
\param b - hodnota, kterou se roznasobi dany radek
*/
const ROW ROW::operator*(const double& b)
{
double* vv = new double[value_number];
long* ii = new long[value_number];
for (long i=0; i<value_number; i++)
{
vv[i] = values[i] * b;
ii[i] = index[i];
}
return ROW(vv, ii, value_number, full_length);
}
// ==============================================================================
/**
*/
double ROW::operator*(const ROW& a)
{
double result = 0;
long ia=0;
long i=0;
while(ia<a.value_number && i<value_number){//udelej pro kazdou hodnotu nebo dokud nedojdes na konec "a"
while(a.index[ia] < index[i])//popojed v acku na sloupec, ktery neni mensi
ia++;
if(ia >= a.value_number)
break;
if(a.index[ia]==index[i]){//neni nahodou i stejne velky?
result += a.values[ia]*values[i];
ia++;
}
i++;
}
return result;
}
// ==============================================================================
/**
\brief Roznasobi radek s vektorem, pouzivam napriklad u podfunkci solve_Axb
*/
double ROW::operator* (const VTR& b)
{
double result = 0;
long i;
for(i=0;i<value_number;i++)
result += values[i] * (b.val[index[i]]);
return result;
}
// ==============================================================================
/**
*/
void ROW::operator/=(const double& b)
{
for (long i=0; i<value_number; i++)
values[i] /= b;
}
// ===============================================================================
// PRIVATE
// ===============================================================================
// ===================== PRIVATE CONSTRUCTORS ================================
// ===============================================================================
/**
\brief prevezme pole a vytvori z nich novy radek
\param v - pole hodnot
\param l - pole indexu sloupce
\param v_num - pocet hodnot v radku
\param r_len - celkovy pocet sloupcu v radku
\param d - pozice diagonalniho prvku v ridkem radku
*/
ROW::ROW(double* v, long* l, long v_num, long r_len):
a(0),na(1),value_number(v_num)
{
allocated[a] = true;
allocated[na] = false;
full_length = r_len;
length[a] = v_num;
length[na] = 0;
values = val[a] = v;
index = in[a] = l;
}
// ==============================================================================
// ===================== PRIVATE METHODS ================================
// ==============================================================================
// ==============================================================================
/**
\brief Pokud neni k dispozici dostatecne dlouhe pole, alokuje nove.
*/
void ROW::alloc(long n)
{
if(allocated[a]){//je prvni pole alokovane?
if(length[a]<n){//neni moc kratke?
length[a] = n*enlarge;
delete[] values;
delete[] index;
values = val[a] = new double[length[a]];
index = in[a] = new long[length[a]];
}
}else{//poprve zalokuj pole
length[a]=n*enlarge;
values = val[a] = new double[length[a]];
index = in[a] = new long[length[a]];
allocated[a] = true;
}
}
// ==============================================================================
/**
*/
void ROW::dealoc()
{
if(allocated[a]){
delete[] val[a];
delete[] in[a];
allocated[a]=false;
}
if(allocated[na]){
delete[] val[na];
delete[] in[na];
allocated[na]=false;
}
}
// ==============================================================================
/**
\brief zajisti aby nove bylo k dispozici pole orig o minimalni velikosti n, zachova puvodni hodnoty ve druhem poli val[na]
\param n - vyzadovana delka pole(max. pocet ktery budu potrebovat)
*/
void ROW::prepare_field(const long& n)
{
switch_fields();
alloc(n);
}
// ==============================================================================
/**
\brief Prohodi pole orig a addit
*/
void ROW::switch_fields()
{
switch (a){
case 0:
a=1;
na=0;
break;
case 1:
a=0;
na=1;
break;
default:
throw "ROW.switch_fields - Je nastaveno nespravne pole";
}
values = val[a];
index = in[a];
}
// ==============================================================================
/**
\brief Vytvori presnou kopii dat ze vstupniho radku.
*/
void ROW::copy_row(const ROW& b)
{
alloc(b.value_number);
full_length = b.full_length;
value_number = b.value_number;
for (long i=0; i<value_number; i++){
values[i]=b.values[i];
index[i]=b.index[i];
}
}
// ==============================================================================
/**
Spoj pole v1,v2 do v_out a i1, i2 do i_out a pocet setridenych hodnot i_num.
Spojuje podle i1 a i2, pocita, ze pole jsou setridena
\return v_out-spojene double hodn
\return i_out indexy sloupcu v_out
\return i_sum pocet spojenych hodnot (delka pole)
\return k-celkovy pocet hodnot ve spojenem poli
*/
void ROW::merge_fields(const double* v1, const double* v2, const long* i1, const long* i2, const long& i1_num, const long& i2_num, double*& v_out, long*& i_out, long& i_sum)
{
long i = 0; /// \param i - akt umisteni indexu [0]
long j = 0; /// \param j - akt umisteni indexu [1]
long k = 0; /// \param k - akt pocet vystupu
// Dokud nedojdes na konec obou poli indexu...
while ((i<i1_num && j<i2_num)){
//======================================================
//???Ktera hodnota z indexu na ktere se divam je vetsi???
if(i1[i] < i2[j]){// Prvni index bude zapsan
i_out[k] = i1[i];
v_out[k] = v1[i];
i++;
}else{
if(i2[j] < i1[i]){// Druhy index bude zapsan
i_out[k] = i2[j];
v_out[k] = v2[j];
j++;
}else{// Oba indexy jsou stejne -> secist values
i_out[k] = i1[i];
v_out[k] = v1[i]+v2[j];
i++; j++;
}
}
k++;
}
while (i<i1_num){
i_out[k] = i1[i];
v_out[k] = v1[i];
i++; k++;
}
while (j<i2_num){
i_out[k] = i2[j];
v_out[k] = v2[j];
j++; k++;
}
i_sum = k;
}