12 //#include "mbk_matrix.h"
14 //#define FINEST_PIVOT
17 // ----- optimizaions ------
19 #define OPTIM_MULTIPLY
21 // -------------------------
22 void mbk_FreeMatrix(mbk_matrix
*mm
)
24 DeleteHeap(&mm
->mbk_matrix_elem_heap
);
27 if (mm
->resolve_line_order
!=NULL
) mbkfree(mm
->resolve_line_order
);
28 if (mm
->resolve_unk_order
!=NULL
) mbkfree(mm
->resolve_unk_order
);
32 mbk_matrix
*mbk_CreateMatrix(int nbx
, int nby
)
36 mm
=(mbk_matrix
*)mbkalloc(sizeof(mbk_matrix
));
37 mm
->tracker0
=mm
->tracker1
=NULL
;
38 mm
->line
=(elem_index_tab
*)mbkalloc(sizeof(elem_index_tab
)*nby
);
39 mm
->col
=(elem_index_tab
*)mbkalloc(sizeof(elem_index_tab
)*nbx
);
42 mm
->col
[i
].first_elem
=NULL
;
43 mm
->col
[i
].last_elem
=NULL
;
44 mm
->col
[i
].tracker
=NULL
;
49 mm
->line
[i
].first_elem
=NULL
;
50 mm
->line
[i
].last_elem
=NULL
;
51 mm
->line
[i
].tracker
=NULL
;
56 mm
->resolve_line_order
=NULL
;
57 mm
->resolve_unk_order
=NULL
;
58 CreateHeap(sizeof(mbk_matrix_elem
), nbx
>4096?nbx
:4096, &mm
->mbk_matrix_elem_heap
);
63 static int from_line_border(mbk_matrix
*mm
, int x
, int y
,mbk_matrix_elem
**found
, mbk_matrix_elem
**last
)
65 if (mm
->col
[x
].first_elem
==NULL
) { *last
=NULL
; *found
=NULL
; return 1; }
66 if (y
==mm
->col
[x
].first_elem
->y
) { *last
=mm
->col
[x
].first_elem
; *found
=*last
; return 1;}
67 else if (y
<mm
->col
[x
].first_elem
->y
) { *last
=mm
->col
[x
].first_elem
; *found
=NULL
; return 1;}
68 if (y
==mm
->col
[x
].last_elem
->y
) { *last
=mm
->col
[x
].last_elem
; *found
=*last
; return 1;}
69 else if (y
>mm
->col
[x
].last_elem
->y
) { *last
=mm
->col
[x
].last_elem
; *found
=NULL
; return 1;}
72 static int from_col_border(mbk_matrix
*mm
, int x
, int y
, mbk_matrix_elem
**found
, mbk_matrix_elem
**last
)
74 if (mm
->line
[y
].first_elem
==NULL
) { *last
=NULL
; *found
=NULL
; return 1; }
75 if (x
==mm
->line
[y
].first_elem
->x
) { *last
=mm
->line
[y
].first_elem
; *found
=*last
; return 1;}
76 else if (x
<mm
->line
[y
].first_elem
->x
) { *last
=mm
->line
[y
].first_elem
; *found
=NULL
; return 1;}
77 if (x
==mm
->line
[y
].last_elem
->x
) { *last
=mm
->line
[y
].last_elem
; *found
=*last
; return 1;}
78 else if (x
>mm
->line
[y
].last_elem
->x
) { *last
=mm
->line
[y
].last_elem
; *found
=NULL
; return 1;}
82 static mbk_matrix_elem
*goto_line(mbk_matrix
*mm
, mbk_matrix_elem
*start
, int y
, mbk_matrix_elem
**last
)
87 if (start
==NULL
) return NULL
;
89 if (start
->y
==y
) return start
;
91 if (from_line_border(mm
, start
->x
, y
, &res
, last
)==1) return res
;
95 while (start
!=NULL
&& y
>start
->y
)
103 while (start
!=NULL
&& y
<start
->y
)
109 if (start
!=NULL
&& start
->y
==y
) return start
;
113 static mbk_matrix_elem
*goto_col(mbk_matrix
*mm
, mbk_matrix_elem
*start
, int x
, mbk_matrix_elem
**last
)
115 mbk_matrix_elem
*res
;
118 if (start
==NULL
) return NULL
;
120 if (start
->x
==x
) return start
;
122 if (from_col_border(mm
, x
, start
->y
, &res
, last
)==1) return res
;
126 while (start
!=NULL
&& x
>start
->x
)
134 while (start
!=NULL
&& x
<start
->x
)
140 if (start
!=NULL
&& start
->x
==x
) return start
;
144 static mbk_matrix_elem
*matrix_get(mbk_matrix
*mm
, int x
, int y
, mbk_matrix_elem
**last
)
146 mbk_matrix_elem
*res
=NULL
;
149 if (from_col_border(mm
, x
, y
, &res
, last
)==1
151 from_line_border(mm
, x
, y
, &res
, last
)==1) return res
;
153 if (mm
->tracker0
!=NULL
)
155 if (mm
->tracker0
->y
==y
)
156 res
=goto_col(mm
, mm
->tracker0
, x
, last
);
158 if (mm
->tracker0
->x
==x
)
159 res
=goto_line(mm
, mm
->tracker0
, y
, last
);
160 if (res
) mm
->tracker0
=res
;
161 if (*last
!=NULL
) return res
;
163 if (mm
->tracker1
!=NULL
&& res
==NULL
)
165 if (mm
->tracker1
->y
==y
)
166 res
=goto_col(mm
, mm
->tracker1
, x
, last
);
168 if (mm
->tracker1
->x
==x
)
169 res
=goto_line(mm
, mm
->tracker1
, y
, last
);
170 if (res
) mm
->tracker1
=res
;
171 if (*last
!=NULL
) return res
;
174 res
=goto_col(mm
, mm
->line
[y
].first_elem
, x
, last
);
179 static inline void get_up_down(mbk_matrix_elem
*mme
, int y
, mbk_matrix_elem
**up
, mbk_matrix_elem
**down
)
181 if (mme
->y
>y
) { *down
=mme
; *up
=(*down
)->UP
; }
182 else { *up
=mme
; *down
=(*up
)->DOWN
; }
185 static inline void get_left_right(mbk_matrix_elem
*mme
, int x
, mbk_matrix_elem
**left
, mbk_matrix_elem
**right
)
187 if (mme
->x
>x
) { *right
=mme
; *left
=(*right
)->LEFT
; }
188 else { *left
=mme
; *right
=(*left
)->RIGHT
; }
191 static mbk_matrix_elem
*matrix_create_elem(mbk_matrix
*mm
, mbk_matrix_elem
*left
, mbk_matrix_elem
*right
, mbk_matrix_elem
*up
, mbk_matrix_elem
*down
, int x
, int y
)
193 mbk_matrix_elem
*mme
;
195 mme
=AddHeapItem(&mm
->mbk_matrix_elem_heap
);
202 if (left
==NULL
) mm
->line
[mme
->y
].first_elem
=mme
;
203 else left
->RIGHT
=mme
;
204 if (up
==NULL
) mm
->col
[mme
->x
].first_elem
=mme
;
206 if (right
==NULL
) mm
->line
[mme
->y
].last_elem
=mme
;
207 else right
->LEFT
=mme
;
208 if (down
==NULL
) mm
->col
[mme
->x
].last_elem
=mme
;
215 // a utiliser que si l'element n'existe pas
216 static mbk_matrix_elem
*matrix_create_for_set(mbk_matrix
*mm
, int x
, int y
)
218 mbk_matrix_elem
*mme
, *last
;
219 mbk_matrix_elem
*up
=NULL
, *down
=NULL
, *left
=NULL
, *right
=NULL
;
221 if (mm
->tracker0
!=NULL
)
223 if (mm
->tracker0
->y
==y
)
225 goto_col(mm
, mm
->tracker0
, x
, &last
);
226 get_left_right(last
, x
, &left
, &right
);
229 if (mm
->tracker0
->x
==x
)
231 goto_line(mm
, mm
->tracker0
, y
, &last
);
232 get_up_down(last
, y
, &up
, &down
);
235 if (mm
->tracker1
!=NULL
)
237 if (mm
->tracker1
->y
==y
&& (left
==NULL
&& right
==NULL
))
239 goto_col(mm
, mm
->tracker1
, x
, &last
);
240 get_left_right(last
, x
, &left
, &right
);
243 if (mm
->tracker1
->x
==x
&& (up
==NULL
&& down
==NULL
))
245 goto_line(mm
, mm
->tracker1
, y
, &last
);
246 get_up_down(last
, y
, &up
, &down
);
250 if (left
==NULL
&& right
==NULL
)
252 goto_col(mm
, mm
->line
[y
].first_elem
, x
, &last
);
254 get_left_right(last
, x
, &left
, &right
);
256 if (up
==NULL
&& down
==NULL
)
258 goto_line(mm
, mm
->col
[x
].first_elem
, y
, &last
);
260 get_up_down(last
, y
, &up
, &down
);
263 mme
=matrix_create_elem(mm
, left
, right
, up
, down
, x
, y
);
269 static inline void settracker(mbk_matrix
*mm
, mbk_matrix_elem
*mme
)
272 if (mm
->tracker0
==mme
|| mm
->tracker1
==mme
) return;
273 if (mm
->tracker0
==NULL
) d1
=0;
274 else d1
=(mm
->tracker0
->x
-mme
->x
)+(mm
->tracker0
->y
-mme
->y
);
275 if (mm
->tracker1
==NULL
) d2
=0;
276 else d2
=(mm
->tracker1
->x
-mme
->x
)+(mm
->tracker1
->y
-mme
->y
);
279 if (d1
<d2
) mm
->tracker0
=mme
;
280 else mm
->tracker1
=mme
;
283 double mbk_GetMatrixValue(mbk_matrix
*mm
, int x
, int y
)
285 mbk_matrix_elem
*res
, *last
;
286 res
=matrix_get(mm
, x
, y
, &last
);
289 if (last
!=NULL
) settracker(mm
, last
);
296 static void matrix_remove(mbk_matrix
*mm
, mbk_matrix_elem
*mme
)
298 if (mme
->LEFT
==NULL
) mm
->line
[mme
->y
].first_elem
=mme
->RIGHT
;
299 else mme
->LEFT
->RIGHT
=mme
->RIGHT
;
301 if (mme
->RIGHT
==NULL
) mm
->line
[mme
->y
].last_elem
=mme
->LEFT
;
302 else mme
->RIGHT
->LEFT
=mme
->LEFT
;
304 if (mme
->UP
==NULL
) mm
->col
[mme
->x
].first_elem
=mme
->DOWN
;
305 else mme
->UP
->DOWN
=mme
->DOWN
;
307 if (mme
->DOWN
==NULL
) mm
->col
[mme
->x
].last_elem
=mme
->UP
;
308 else mme
->DOWN
->UP
=mme
->UP
;
310 if (mm
->tracker0
==mme
) mm
->tracker0
=mme
->LEFT
;
311 if (mm
->tracker1
==mme
) mm
->tracker1
=mme
->LEFT
;
313 if (mm
->col
[mme
->x
].tracker
==mme
) mm
->col
[mme
->x
].tracker
=mme
->DOWN
;
314 if (mm
->line
[mme
->y
].tracker
==mme
) mm
->line
[mme
->y
].tracker
=mme
->LEFT
;
316 mm
->line
[mme
->y
].NZ
--;
317 mm
->col
[mme
->x
].NZ
--;
319 DelHeapItem(&mm
->mbk_matrix_elem_heap
, mme
);
322 void matrix_clearline(mbk_matrix
*mm
, int i
)
324 mbk_matrix_elem
*res
, *nres
;
325 for (res
=mm
->line
[i
].first_elem
; res
!=NULL
; res
=nres
)
328 matrix_remove(mm
, res
);
332 void matrix_clearcol(mbk_matrix
*mm
, int i
)
334 mbk_matrix_elem
*res
, *nres
;
335 for (res
=mm
->col
[i
].first_elem
; res
!=NULL
; res
=nres
)
338 matrix_remove(mm
, res
);
342 void mbk_SetMatrixValue(mbk_matrix
*mm
, int x
, int y
, double val
)
344 mbk_matrix_elem
*res
, *last
;
345 res
=matrix_get(mm
, x
, y
, &last
);
350 matrix_remove(mm
, res
);
360 res
=matrix_create_for_set(mm
, x
, y
);
366 inline int mbk_GetMatrixNZUR(mbk_matrix
*mm
, int x
)
368 return mm
->col
[x
].NZ
;
371 inline int mbk_GetMatrixNZLC(mbk_matrix
*mm
, int y
)
373 return mm
->line
[y
].NZ
;
376 void mbk_DisplayMatrix(char *filename
, mbk_matrix
*mm
)
384 f
=fopen(filename
,"wt");
387 for (j
=0; j
<mm
->nby
; j
++)
389 for (i
=0; i
<mm
->nbx
; i
++)
391 sprintf(buf
, "%.3g", mbk_GetMatrixValue(mm
, i
, j
));
392 fprintf(f
," %9s", buf
);
398 for (i
=0; i
<mm
->nbx
; i
++)
400 sprintf(buf
, "%d", mbk_GetMatrixNZUR(mm
, i
));
401 fprintf(f
," %2s", buf
);
405 for (j
=0; j
<mm
->nby
; j
++)
407 sprintf(buf
, "%d", mbk_GetMatrixNZLC(mm
, j
));
408 fprintf(f
," %2s", buf
);
411 if (mm
->resolve_line_order
!=NULL
)
413 fprintf(f
,"RESOLVE LINE ORDER:");
414 for (i
=0; i
<mm
->nby
; i
++)
415 fprintf(f
," %d", mm
->resolve_line_order
[i
]);
418 if (mm
->resolve_unk_order
!=NULL
)
420 fprintf(f
,"RESOLVE UNK ORDER:");
421 for (i
=0; i
<mm
->nby
; i
++)
422 fprintf(f
," %d", mm
->resolve_unk_order
[i
]);
425 if (f
!=stdout
) fclose(f
);
429 static chain_list
*find_lowestNZ(elem_index_tab
*eit
, chain_list
**unlocked
)
431 int i
, lowest
=INT_MAX
;
432 chain_list
*cl
=NULL
, **prev
, *ch
;
438 i
=(int)(long)ch
->DATA
;
439 if (eit
[i
].NZ
<lowest
)
442 cl
=addchain(NULL
, prev
);
446 else if (eit
[i
].NZ
==lowest
) { cl
=addchain(cl
, prev
); }
455 static int findPivot(mbk_matrix
*u
, chain_list
**unlockedlines
, chain_list
**unlockedcols
, int *x
, int *y
)
457 chain_list
*colcandidates
, *linecandidates
;
458 chain_list
*clx
, *cly
, **tmp
, *tmpfree
, **bestx
=NULL
, **besty
=NULL
;
459 double highest
=-DBL_MAX
, val
;
461 colcandidates
=find_lowestNZ(u
->col
, unlockedcols
);
462 linecandidates
=find_lowestNZ(u
->line
, unlockedlines
);
463 if (colcandidates
->NEXT
==NULL
&& linecandidates
->NEXT
==NULL
)
465 tmp
=(chain_list
**)colcandidates
->DATA
;
467 *x
=(int)(long)tmpfree
->DATA
;
469 tmpfree
->NEXT
=NULL
; freechain(tmpfree
);
471 tmp
=(chain_list
**)linecandidates
->DATA
;
473 *y
=(int)(long)tmpfree
->DATA
;
475 tmpfree
->NEXT
=NULL
; freechain(tmpfree
);
476 // ligne et column du pivot sont enleves des listes des col et ligne non bloque
481 for (cly
=linecandidates
; cly
!=NULL
; cly
=cly
->NEXT
)
483 tmp
=(chain_list
**)cly
->DATA
;
484 j
=(int)(long)(*tmp
)->DATA
;
485 for (clx
=colcandidates
; clx
!=NULL
; clx
=clx
->NEXT
)
487 tmp
=(chain_list
**)clx
->DATA
;
488 i
=(int)(long)(*tmp
)->DATA
;
489 val
=mbk_GetMatrixValue(u
, i
, j
);
496 bestx
=(chain_list
**)clx
->DATA
;
497 besty
=(chain_list
**)cly
->DATA
;
501 if (bestx
==NULL
|| besty
==NULL
)
503 avt_error("mbk_matrix", 2, AVT_ERR
, "<NaN> or <Inf> value found in matrix\n");
506 // enleve ligne et column du pivot des listes des col et ligne non bloque
507 tmpfree
=*bestx
; *bestx
=(*bestx
)->NEXT
;
508 tmpfree
->NEXT
=NULL
; freechain(tmpfree
);
509 tmpfree
=*besty
; *besty
=(*besty
)->NEXT
;
510 tmpfree
->NEXT
=NULL
; freechain(tmpfree
);
512 freechain(colcandidates
);
513 freechain(linecandidates
);
518 static chain_list **find_MAXPivot(mbk_matrix *u, int y, chain_list **unlockedcols, char *locking, double *highest, chain_list **who)
520 mbk_matrix_elem *mme;
526 for (cl=unlockedcols; cl!=NULL; cl=cl->NEXT)
529 val=mbk_GetMatrixValue(u, x, y);
540 static int findPivot(mbk_matrix
*u
, chain_list
**unlockedlines
, chain_list
**unlockedcols
, int *x
, int *y
)
542 chain_list
**colfound
, *linecandidates
, **linefound
, *cl
, *ch
, **prev
;
543 chain_list
**tmp
, *tmpfree
;
544 double highest
=-DBL_MAX
, val
;
547 // colcandidates=find_lowestNZ(u->col, unlockedcols);
548 colfound
=NULL
; linefound
=NULL
;
549 linecandidates
=find_lowestNZ(u
->line
, unlockedlines
);
551 // version en dessous, on parcourt quasiment toute la matrice dans notre cas
553 if (linecandidates
->NEXT
!=NULL
)
555 colcandidates
=find_lowestNZ(u
->col
, unlockedcols
);
556 for (cl
=colcandidates
; cl
!=NULL
; cl
=cl
->NEXT
)
558 tmp
=(chain_list
**)ch
->DATA
;
559 xx
=(int)(long)(*tmp
)->DATA
;
560 for (ch
=linecandidates
; ch
!=NULL
; ch
=ch
->NEXT
)
562 tmp
=(chain_list
**)ch
->DATA
;
563 yy
=(int)(long)(*tmp
)->DATA
;
567 freechain(colcandidates
);
572 for (ch
=linecandidates
; ch
!=NULL
; ch
=ch
->NEXT
)
574 tmp
=(chain_list
**)ch
->DATA
;
575 yy
=(int)(long)(*tmp
)->DATA
;
577 for (cl
=*unlockedcols
; cl
!=NULL
; prev
=&cl
->NEXT
, cl
=cl
->NEXT
)
579 xx
=(int)(long)cl
->DATA
;
580 val
=mbk_GetMatrixValue(u
, xx
, yy
);
585 linefound
=(chain_list
**)ch
->DATA
;
594 if (colfound
==NULL
) return 1;
596 *x
=(int)(long)(*colfound
)->DATA
;
597 *y
=(int)(long)(*linefound
)->DATA
;
599 // enleve ligne et column du pivot des listes des col et ligne non bloque
600 tmpfree
=*colfound
; *colfound
=(*colfound
)->NEXT
;
601 tmpfree
->NEXT
=NULL
; freechain(tmpfree
);
602 tmpfree
=*linefound
; *linefound
=(*linefound
)->NEXT
;
603 tmpfree
->NEXT
=NULL
; freechain(tmpfree
);
605 freechain(linecandidates
);
609 void mbk_MatrixCopyCol(mbk_matrix
*u
, mbk_matrix
*l
, int xu
, int xl
, char *locking
)
611 mbk_matrix_elem
*res
, *nres
;
612 for (res
=l
->col
[xl
].first_elem
; res
!=NULL
; res
=nres
)
615 matrix_remove(l
, res
);
617 for (res
=u
->col
[xu
].first_elem
; res
!=NULL
; res
=res
->DOWN
)
619 if (locking
==NULL
|| locking
[res
->y
]==0)
620 mbk_SetMatrixValue(l
, xl
, res
->y
, res
->value
);
624 void mbk_MatrixCopyCol__notfinished(mbk_matrix
*u
, mbk_matrix
*l
, int xu
, int xl
, char *locking
)
626 mbk_matrix_elem
*res
, *nres
, *mme
;
627 for (res
=l
->col
[xl
].first_elem
; res
!=NULL
; res
=nres
)
630 matrix_remove(l
, res
);
633 for (res
=u
->col
[xu
].first_elem
; res
!=NULL
; res
=res
->DOWN
)
635 if (locking
==NULL
|| locking
[res
->y
]==0)
637 mme
=matrix_create_elem(l
, NULL
, NULL
, nres
, NULL
, xl
, res
->y
);
638 mme
->value
=res
->value
;
639 if (nres
==NULL
) l
->col
[xl
].first_elem
=mme
;
644 l
->col
[xl
].last_elem
=mme
;
647 void mbk_MatrixCopyCol__notfinished_linkline(mbk_matrix
*l
)
649 mbk_matrix_elem
*res
;
652 for (xl
=0; xl
<l
->nby
; xl
++) l
->line
[xl
].tracker
=NULL
;
654 for (xl
=0; xl
<l
->nbx
; xl
++)
656 for (res
=l
->col
[xl
].first_elem
; res
!=NULL
; res
=res
->DOWN
)
658 res
->LEFT
=l
->line
[res
->y
].tracker
;
659 if (res
->LEFT
!=NULL
) res
->LEFT
->RIGHT
=res
;
660 else l
->line
[res
->y
].first_elem
=res
;
661 l
->line
[res
->y
].tracker
=res
;
664 for (xl
=0; xl
<l
->nby
; xl
++) l
->line
[xl
].last_elem
=l
->line
[xl
].tracker
;
669 void mbk_MatrixMultiplyLineBy(mbk_matrix
*u
, int y
, char *locking
, double mult
)
671 mbk_matrix_elem
*res
, *nres
;
673 for (res
=u
->line
[y
].first_elem
; res
!=NULL
; res
=nres
)
676 if (locking
==NULL
|| locking
[res
->x
]==0)
681 matrix_remove(u
, res
);
687 void mbk_MatrixDivideLineBy(mbk_matrix
*u
, int y
, char *locking
, double mult
)
689 mbk_matrix_elem
*res
, *nres
;
691 for (res
=u
->line
[y
].first_elem
; res
!=NULL
; res
=nres
)
694 if (locking
==NULL
|| locking
[res
->x
]==0)
699 matrix_remove(u
, res
);
705 mbk_matrix_elem
*tracker_goto_line(mbk_matrix
*mm
, int x
, int y
)
707 mbk_matrix_elem
*res
, *last
;
709 if (from_line_border(mm
, x
, y
, &res
, &last
)==1)
711 mm
->col
[x
].tracker
=last
;
716 if (mm
->col
[x
].tracker
==NULL
) mm
->col
[x
].tracker
=mm
->col
[x
].first_elem
;
717 res
=mm
->col
[x
].tracker
;
722 while (res
!=NULL
&& y
>res
->y
)
727 mm
->col
[x
].tracker
=last
;
731 while (res
!=NULL
&& y
<res
->y
)
738 mm
->col
[x
].tracker
=last
;
740 return mm
->col
[x
].tracker
;
743 void followline(mbk_matrix
*mm
, int dy
, int sy
, char *locking
, double mult
)
745 mbk_matrix_elem
*a
, *b
, *na
, *preva
=NULL
, *last
;
746 mbk_matrix_elem
*left
, *right
, *up
, *down
;
748 a
=mm
->line
[dy
].first_elem
;
749 b
=mm
->line
[sy
].first_elem
;
751 while (a
!=NULL
|| b
!=NULL
)
753 if (a
!=NULL
&& b
!=NULL
&& a
->x
==b
->x
)
756 if (locking
[a
->x
]==0)
758 val
=a
->value
=a
->value
-(b
->value
*mult
);
759 if (val
==0) matrix_remove(mm
, a
);
769 else if (b
==NULL
|| (a
!=NULL
&& a
->x
<b
->x
))
774 else //if (a->x>b->x)
777 val
=0-(b
->value
*mult
);
778 if (locking
[b
->x
]==0)
780 last
=tracker_goto_line(mm
, b
->x
, dy
);
782 left
=right
=up
=down
=NULL
;
785 get_up_down(last
, dy
, &up
, &down
);
787 a
=matrix_create_elem(mm
, preva
, a
, up
, down
, b
->x
, dy
);
798 // elem(dy)(x) = elem(dy)(x) - elem(sy)(x) * mult
799 void mbk_MatrixLineMultThenSub(mbk_matrix
*u
, int dy
, int sy
, char *locking
, double mult
)
801 /* double sval, dval;
803 followline(u
, dy
, sy
, locking
, mult
);
805 /* for (i=0; i<u->nbx; i++)
807 if (locking==NULL || locking[i]==0)
809 sval=mbk_GetMatrixValue(u, i, sy);
810 dval=mbk_GetMatrixValue(u, i, dy);
811 dval=dval-(sval*mult);
812 mbk_SetMatrixValue(u, i, dy, dval);
818 void mbkMatrixSwapCols(mbk_matrix
*u
, int x0
, int x1
)
822 for (j
=0; j
<u
->nby
; j
++)
824 val0
=mbk_GetMatrixValue(u
, x0
, j
);
825 val1
=mbk_GetMatrixValue(u
, x1
, j
);
826 mbk_SetMatrixValue(u
, x1
, j
, val0
);
827 mbk_SetMatrixValue(u
, x0
, j
, val1
);
831 void mbkMatrixSwapLines(mbk_matrix
*u
, int y0
, int y1
)
835 for (j
=0; j
<u
->nbx
; j
++)
837 val0
=mbk_GetMatrixValue(u
, j
, y0
);
838 val1
=mbk_GetMatrixValue(u
, j
, y1
);
839 mbk_SetMatrixValue(u
, j
, y1
, val0
);
840 mbk_SetMatrixValue(u
, j
, y0
, val1
);
844 int mbk_CreateLUMatrix(mbk_matrix
*u
, mbk_matrix
*l
, mbk_matrix
*sol
)
846 char *lockedCOL
, *lockedLINE
;
847 int i
, j
, pivot_x
, pivot_y
;
848 double pivot_value
, val
;
849 mbk_matrix_elem
*mme
, *last
;
850 chain_list
*unlockedCOL
, *unlockedLINE
, *cl
;
854 avt_errmsg (MBK_ERRMSG
, "036", AVT_ERROR
);
857 if (l
!=NULL
&& (u
->nbx
!=l
->nbx
|| l
->nbx
!=l
->nby
))
859 avt_errmsg (MBK_ERRMSG
, "037", AVT_ERROR
);
863 if (u
->resolve_line_order
==NULL
)
865 u
->resolve_line_order
=mbkalloc(sizeof(int)*u
->nby
);
866 u
->resolve_unk_order
=mbkalloc(sizeof(int)*u
->nby
);
868 if (l
!=NULL
&& l
->resolve_line_order
==NULL
)
870 l
->resolve_line_order
=mbkalloc(sizeof(int)*l
->nby
);
871 l
->resolve_unk_order
=mbkalloc(sizeof(int)*l
->nby
);
873 lockedCOL
=mbkalloc(sizeof(char)*u
->nbx
);
874 lockedLINE
=mbkalloc(sizeof(char)*u
->nby
);
875 unlockedCOL
=unlockedLINE
=NULL
;
877 for (i
=u
->nbx
-1;i
>=0;i
--)
881 unlockedCOL
=addchain(unlockedCOL
, (void *)(long)i
);
882 unlockedLINE
=addchain(unlockedLINE
, (void *)(long)i
);
885 for (i
=0; i
<u
->nbx
; i
++)
888 if (findPivot(u
, &unlockedLINE
, &unlockedCOL
, &pivot_x
, &pivot_y
))
890 avt_errmsg (MBK_ERRMSG
, "038", AVT_ERROR
);
895 unlockedLINE
=unlockedLINE
->NEXT
;
896 unlockedCOL
=unlockedCOL
->NEXT
;
900 mbkMatrixSwapCols(u
, i
, pivot_x
);
904 mbkMatrixSwapLines(u
, i
, pivot_y
);
909 mbk_MatrixCopyCol__notfinished(u
, l
, pivot_x
, pivot_y
, lockedLINE
);
911 pivot_value
=mbk_GetMatrixValue(u
, pivot_x
, pivot_y
);
914 avt_errmsg (MBK_ERRMSG
, "039", AVT_ERROR
);
920 l
->resolve_line_order
[i
]=pivot_y
;
921 l
->resolve_unk_order
[i
]=pivot_y
;
923 u
->resolve_line_order
[u
->nby
-i
-1]=pivot_y
;
924 u
->resolve_unk_order
[u
->nby
-i
-1]=pivot_x
;
926 mbk_MatrixDivideLineBy(u
, pivot_y
, lockedCOL
, pivot_value
);
928 mbk_MatrixDivideLineBy(sol
, pivot_y
, NULL
, pivot_value
);
930 for (cl
=unlockedLINE
; cl
!=NULL
; cl
=cl
->NEXT
)
932 j
=(int)(long)cl
->DATA
;
934 if (cl
==unlockedLINE
)
936 mme
=matrix_get(u
, pivot_x
, j
, &last
);
937 if (mme
==NULL
) { val
=0; mme
=u
->col
[pivot_x
].first_elem
; }
938 else { val
=mme
->value
; mme
=mme
->DOWN
; }
942 while (mme
!=NULL
&& mme
->y
<j
) { mme
=mme
->DOWN
; }
943 if (mme
==NULL
|| mme
->y
!=j
) val
=0;
944 else { val
=mme
->value
; mme
=mme
->DOWN
; }
947 val
=mbk_GetMatrixValue(u
, pivot_x
, j
);
951 mbk_MatrixLineMultThenSub(u
, j
, pivot_y
, lockedCOL
, val
);
953 mbk_MatrixLineMultThenSub(sol
, j
, pivot_y
, NULL
, val
);
957 lockedCOL
[pivot_x
]=1;
958 lockedLINE
[pivot_y
]=1;
960 printf("U' *************\n");
961 mbk_DisplayMatrix(stdout
,u
);
965 if (l
!=NULL
) mbk_MatrixCopyCol__notfinished_linkline(l
);
972 mbk_matrix
*mbk_MatrixMultiplyMatrix(mbk_matrix
*a
, mbk_matrix
*b
)
977 mbk_matrix_elem
*mmx
, *mmy
, *mmxstart
;
980 avt_errmsg (MBK_ERRMSG
, "040", AVT_ERROR
);
983 res
=mbk_CreateMatrix(b
->nbx
, a
->nby
);
985 #ifndef OPTIM_MULTIPLY
986 for (j
=0; j
<a
->nby
; j
++)
988 for (k
=0; k
<b
->nbx
; k
++)
991 for (i
=0; i
<b
->nby
; i
++)
993 cumul
+=mbk_GetMatrixValue(a
, i
, j
)*mbk_GetMatrixValue(b
, k
, i
);
995 mbk_SetMatrixValue(res
, k
, j
, cumul
);
999 for (j
=0; j
<a
->nby
; j
++)
1001 mmxstart
=a
->line
[j
].first_elem
;
1002 for (k
=0; k
<b
->nbx
; k
++)
1004 mmy
=b
->col
[k
].first_elem
;
1007 while (mmx
!=NULL
&& mmy
!=NULL
)
1009 if (mmx
->x
<mmy
->y
) mmx
=mmx
->RIGHT
;
1010 else if (mmy
->y
<mmx
->x
) mmy
=mmy
->DOWN
;
1013 cumul
+=mmx
->value
*mmy
->value
;
1019 mbk_SetMatrixValue(res
, k
, j
, cumul
);
1026 mbk_matrix
*mbk_MatrixSubstractMatrix(mbk_matrix
*a
, mbk_matrix
*b
)
1031 if (a
->nbx
!=b
->nbx
|| a
->nby
!=b
->nby
)
1033 avt_errmsg (MBK_ERRMSG
, "041", AVT_ERROR
);
1037 res
=mbk_CreateMatrix(a
->nbx
, a
->nby
);
1038 for (j
=0; j
<a
->nby
; j
++)
1040 for (k
=0; k
<a
->nbx
; k
++)
1042 cumul
=mbk_GetMatrixValue(a
, k
, j
)-mbk_GetMatrixValue(b
, k
, j
);
1043 mbk_SetMatrixValue(res
, k
, j
, cumul
);
1049 mbk_matrix
*mbk_MatrixDuplicateMatrix(mbk_matrix
*a
)
1054 res
=mbk_CreateMatrix(a
->nbx
, a
->nby
);
1055 for (j
=0; j
<a
->nby
; j
++)
1057 for (k
=0; k
<a
->nbx
; k
++)
1059 cumul
=mbk_GetMatrixValue(a
, k
, j
);
1060 mbk_SetMatrixValue(res
, k
, j
, cumul
);
1066 void mbk_MatrixAddHalfLinkedElem(mbk_matrix
*mm
, int x
, int y
, double value
)
1068 mbk_matrix_elem
*mme
;
1069 if (value
==0) return;
1070 mme
=matrix_create_elem(mm
, NULL
, NULL
, mm
->col
[x
].tracker
, NULL
, x
, y
);
1072 if (mm
->col
[x
].tracker
!=NULL
) mm
->col
[x
].tracker
->DOWN
=mme
;
1073 mm
->col
[x
].tracker
=mme
;
1076 void mbk_MatrixFinishElemLink(mbk_matrix
*mm
)
1078 mbk_MatrixCopyCol__notfinished_linkline(mm
);
1081 double *mbk_MatrixSolveUsingArray(mbk_matrix
*a
, double *solval
, double *unkval
)
1084 double divval
, cumul
;
1085 mbk_matrix_elem
*mme
;
1087 if (a
->resolve_line_order
==NULL
)
1089 avt_errmsg (MBK_ERRMSG
, "042", AVT_ERROR
);
1092 if (unkval
==NULL
) unkval
=mbkalloc(sizeof(double)*a
->nbx
);
1094 for (o
=0; o
<a
->nby
; o
++)
1096 i
=a
->resolve_line_order
[o
];
1097 u
=a
->resolve_unk_order
[o
];
1099 for (mme
=a
->line
[i
].first_elem
; mme
!=NULL
; mme
=mme
->RIGHT
)
1101 if (mme
->x
==u
) divval
=mme
->value
;
1102 else cumul
=cumul
+(mme
->value
*unkval
[mme
->x
]);
1104 unkval
[u
]=(solval
[i
]-cumul
)/divval
;
1109 mbk_matrix
*mbk_MatrixSolve(mbk_matrix
*a
, mbk_matrix
*sol
)
1112 double *unkval
, *solval
;
1115 if (sol
->nbx
!=1 || sol
->nby
!=a
->nby
)
1117 avt_errmsg (MBK_ERRMSG
, "043", AVT_ERROR
);
1120 solval
=mbkalloc(sizeof(double)*sol
->nby
);
1121 for (i
=0;i
<sol
->nby
;i
++) solval
[i
]=mbk_GetMatrixValue(sol
, 0, i
);
1123 unkval
=mbk_MatrixSolveUsingArray(a
, solval
, NULL
);
1127 if ((res
=mbk_CreateMatrix(1, a
->nbx
))==NULL
) return res
;
1129 for (i
=0;i
<a
->nbx
;i
++)
1130 if (unkval
[i
]!=0) mbk_SetMatrixValue(res
, 0, i
, unkval
[i
]);
1135 int mbk_MatrixReduce(mbk_matrix
*a
, int limit_index
)
1138 double pval
, lval
, sval
;
1139 mbk_matrix_elem
*mme
;
1142 for (i
=a
->nby
-1; i
>=limit_index
; i
--)
1144 if ((mme
=a
->line
[i
].last_elem
)==NULL
|| mme
->x
!=i
)
1147 avt_errmsg (MBK_ERRMSG
, "044", AVT_ERROR
);
1154 mbk_MatrixDivideLineBy(a
, i
, NULL
, -pval
);
1157 if ((mme
=a
->line
[j
].last_elem
)==NULL
|| mme
->x
!=i
)
1165 for (mme
=a
->line
[i
].first_elem
; mme
!=NULL
&& mme
->x
<i
; mme
=mme
->RIGHT
)
1167 sval
=mbk_GetMatrixValue(a
, mme
->x
, j
);
1168 mbk_SetMatrixValue(a
, mme
->x
, j
, sval
+lval
*mme
->value
);
1172 matrix_clearcol(a
, i
);
1173 matrix_clearline(a
, i
);
1178 for (i
=a
->nby
-1; i
>=limit_index
; i
--)
1180 pval
=mbk_GetMatrixValue(a
, i
, i
);
1181 mbk_MatrixDivideLineBy(a
, i
, NULL
, -pval
);
1184 pval
=mbk_GetMatrixValue(a
, k
, i
);
1187 lval
=mbk_GetMatrixValue(a
, i
, j
);
1190 sval
=mbk_GetMatrixValue(a
, k
, j
);
1191 mbk_SetMatrixValue(a
, k
, j
,
1202 int mbk_MatrixTraverse(mbk_matrix
*a
, matrix_traverse_func mtf
, void *data
)
1205 mbk_matrix_elem
*mme
, *nextmme
;
1207 for (i
=0; i
<a
->nby
; i
++)
1209 for (mme
=a
->line
[i
].first_elem
; mme
!=NULL
; mme
=nextmme
)
1212 ret
=mtf(mme
->x
, mme
->y
, &mme
->value
, data
);
1213 if (mme
->value
==0) matrix_remove(a
, mme
);
1214 if (ret
!=0) return 1;
1220 static int pp(int x
, int y
, double *val
, void *data
)
1223 fprintf((FILE *)data
, "mbk_SetMatrixValue(u,%d,%d,%e);\n",x
, y
, *val
);
1227 void matdrive(mbk_matrix
*a
, char *name
)
1230 f
=fopen("toto.c","wt");
1231 fprintf(f
,"u=mbk_CreateMatrix(%d, %d);\n",a
->nbx
, a
->nby
);
1232 fprintf(f
,"l=mbk_CreateMatrix(%d, %d);\n",a
->nbx
, a
->nby
);
1233 mbk_MatrixTraverse(a
, pp
, f
);