Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / mbk / rcn_lo_util.c
1
2 #include "rcn.h"
3 #include "mlu_lib.h"
4 #include MSL_H
5
6 /******************************************************************************/
7
8 void duplorcnet( ptsig_dest, ptsig_src )
9 losig_list *ptsig_dest;
10 losig_list *ptsig_src;
11 {
12 lowire_list *scanlowire;
13 lowire_list *newwire;
14 ptype_list *ptuser;
15
16 if( ptsig_dest->PRCN ) {
17 rcn_error( 27, AVT_WARNING );
18 return ;
19 }
20
21 if( !ptsig_src->PRCN )
22 return;
23
24 addlorcnet( ptsig_dest );
25
26 /* Capacité du signal */
27 rcn_setcapa( ptsig_dest, rcn_getcapa( NULL, ptsig_src ) );
28
29 /* Wire constituant le signal */
30 for( scanlowire = ptsig_src->PRCN->PWIRE ;
31 scanlowire ;
32 scanlowire = scanlowire->NEXT
33 )
34 {
35
36 if( RCN_GETFLAG( scanlowire->FLAG, RCN_FLAG_DEL ) )
37 continue;
38 newwire = heaplowire();
39
40 newwire->NEXT = ptsig_dest->PRCN->PWIRE;
41 newwire->RESI = scanlowire->RESI;
42 newwire->CAPA = scanlowire->CAPA;
43 newwire->NODE1 = scanlowire->NODE1;
44 newwire->NODE2 = scanlowire->NODE2;
45 newwire->FLAG = scanlowire->FLAG;
46 newwire->USER = NULL;
47
48 if ((ptuser = getptype(scanlowire->USER, RESINAME))!=NULL)
49 newwire->USER = addptype(newwire->USER, RESINAME, ptuser->DATA);
50
51 if ((ptuser = getptype(scanlowire->USER, OPT_PARAMS)))
52 newwire->USER = addptype(newwire->USER, OPT_PARAMS, dupoptparamlst((optparam_list *)ptuser->DATA));
53
54 ptsig_dest->PRCN->PWIRE = newwire;
55 }
56
57 /* CTC sur le signal : non gere */
58 ptsig_dest->PRCN->PCTC = NULL;
59
60 /* NBNODE */
61 ptsig_dest->PRCN->NBNODE = ptsig_src->PRCN->NBNODE ;
62
63 /* USER */
64 ptsig_dest->PRCN->USER = NULL;
65 }
66
67 /******************************************************************************/
68
69 todolist* breakloop2( ptsig, ptnode, curwire, headtodo, cleanwire )
70 losig_list *ptsig;
71 lonode_list *ptnode;
72 lowire_list *curwire;
73 todolist *headtodo;
74 chain_list **cleanwire;
75 {
76 lowire_list *tmpwire;
77 chain_list *scanchain;
78 todolist *newtodo;
79
80 if( curwire )
81 {
82 if( RCN_GETFLAG( curwire->FLAG, RCN_FLAG_PASS ) ) {
83 rcn_error( 28, AVT_WARNING );
84 return NULL ;
85 }
86
87 RCN_SETFLAG( curwire->FLAG, RCN_FLAG_PASS );
88 }
89
90 do
91 {
92 /* On trouve une boucle */
93 if( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_PASS ) )
94 {
95 tmpwire = addlowire( ptsig,
96 curwire->FLAG,
97 curwire->RESI,
98 curwire->CAPA,
99 curwire->NODE1,
100 addlonode( ptsig, NULL )
101 );
102 *cleanwire = addchain( *cleanwire, curwire );
103 RCN_SETFLAG( tmpwire->FLAG, RCN_FLAG_PASS );
104 RCN_SETFLAG( curwire->FLAG, RCN_FLAG_PASS );
105 }
106 else
107 {
108 RCN_SETFLAG( ptnode->FLAG, RCN_FLAG_PASS );
109 }
110
111 /* Recherche un wire non parcouru sur le noeud courant */
112 for( scanchain = ptnode->WIRELIST ;
113 scanchain ;
114 scanchain = scanchain->NEXT
115 )
116 {
117 curwire = (lowire_list*)(scanchain->DATA);
118 if( ! RCN_GETFLAG( curwire->FLAG, RCN_FLAG_PASS ) )
119 break;
120 }
121
122 if( ! scanchain )
123 break; /* on quitte le while */
124
125 /* Ajoute les autre wire non parcouru sur le noeud dans une
126 * structure todo */
127
128 newtodo = NULL;
129
130 if( scanchain )
131 {
132 for( scanchain = scanchain->NEXT ;
133 scanchain ;
134 scanchain = scanchain->NEXT
135 )
136 {
137 tmpwire = (lowire_list*)(scanchain->DATA);
138
139 if( ! RCN_GETFLAG( tmpwire->FLAG, RCN_FLAG_PASS ) )
140 {
141 if( !newtodo )
142 {
143 newtodo = (todolist*)(mbkalloc( sizeof(todolist) ) );
144 newtodo->next = headtodo ;
145 headtodo = newtodo;
146 newtodo->ptnode = ptnode;
147 newtodo->head_wire = NULL;
148 }
149 newtodo->head_wire = addchain( newtodo->head_wire, tmpwire );
150 }
151 }
152 }
153
154 ptnode = getlonode( NULL,
155 ( curwire->NODE1 == ptnode->INDEX ) ? curwire->NODE2 :
156 curwire->NODE1
157 );
158
159 RCN_SETFLAG( curwire->FLAG, RCN_FLAG_PASS );
160 }
161 while(1); /* c'est ben vrai! */
162
163 return( headtodo );
164 }
165
166 int breakloop( ptsig )
167 losig_list *ptsig;
168 {
169
170 todolist *headtodo ;
171 todolist *curtodo ;
172 todolist *scantodo ;
173 todolist *newtodo ;
174 lowire_list *firstwire;
175 lowire_list *curwire;
176 lonode_list *ptnode;
177 chain_list *cleanwire;
178 chain_list *scanchain;
179
180 if( !ptsig->PRCN || !gettabnode( ptsig->PRCN ) ) {
181 return 0 ;
182 rcn_error( 29, AVT_WARNING );
183 }
184
185 clearallwireflag( ptsig, RCN_FLAG_PASS );
186 cleanwire = NULL;
187
188 getlonode(ptsig,0) ;
189
190 /* Boucle pour parcourir les differentes composantes connexes */
191
192 for( firstwire = ptsig->PRCN->PWIRE ;
193 firstwire ;
194 firstwire = firstwire->NEXT
195 )
196 {
197 if( RCN_GETFLAG( firstwire->FLAG, RCN_FLAG_DEL ) )
198 continue;
199
200 ptnode = getlonode( NULL, firstwire->NODE1 );
201
202 if( ! RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_PASS ) )
203 {
204 /* Corps d'une des composante connexe du reseau */
205
206 headtodo = breakloop2( ptsig, ptnode, NULL, NULL, &cleanwire );
207
208 while( headtodo )
209 {
210 newtodo = NULL;
211
212 for( scantodo = headtodo ; scantodo ; scantodo = scantodo->next )
213 {
214 for( scanchain = scantodo->head_wire ;
215 scanchain ;
216 scanchain = scanchain->NEXT
217 )
218 {
219
220 curwire = (lowire_list*)( scanchain->DATA );
221
222 if( ! RCN_GETFLAG( curwire->FLAG, RCN_FLAG_PASS ) )
223 {
224
225 newtodo = breakloop2( ptsig,
226 getlonode( NULL,
227 ( scantodo->ptnode->INDEX ==
228 curwire->NODE1 ) ?
229 curwire->NODE2 :
230 curwire->NODE1
231 ),
232 curwire,
233 newtodo,
234 &cleanwire
235 );
236 }
237 }
238 }
239
240 while( headtodo )
241 {
242 curtodo = headtodo->next;
243 freechain( headtodo->head_wire );
244 mbkfree( headtodo );
245 headtodo = curtodo;
246 }
247
248 headtodo = newtodo;
249 }
250 }
251 }
252
253 for( scanchain = cleanwire ; scanchain ; scanchain = scanchain->NEXT )
254 {
255 curwire = (lowire_list*)( scanchain->DATA );
256 dellowire( ptsig, curwire->NODE1, curwire->NODE2 );
257 }
258
259 freechain ( cleanwire );
260
261 return(1);
262 }
263
264 int reduce_rcn( ptsig )
265 losig_list *ptsig;
266 {
267 lowire_list *scanwire;
268 lonode_list *ptnode;
269 chain_list *todo;
270 chain_list *doing;
271 chain_list *scanctc;
272 loctc_list *ptctc;
273 float resi;
274 int node1;
275 int node2;
276 lowire_list *wire1;
277 lowire_list *wire2;
278 int another;
279
280 rcn_checkwritesignal(ptsig);
281
282 if( !gettabnode( ptsig->PRCN ) ) {
283 rcn_error( 30, AVT_WARNING );
284 return 0 ;
285 }
286
287 do
288 {
289 another = 0;
290
291 todo = NULL;
292 rcn_setcapa( ptsig, 0.0 );
293
294 for( scanwire = ptsig->PRCN->PWIRE ; scanwire ; scanwire = scanwire->NEXT )
295 {
296 if( RCN_GETFLAG( scanwire->FLAG, RCN_FLAG_DEL ) )
297 continue;
298
299 rcn_addcapa( ptsig, scanwire->CAPA );
300 scanwire->CAPA = 0.0;
301 ptnode = getlonode( ptsig, scanwire->NODE1 );
302 if( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_TWO ) &&
303 ! RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_LOCON ) &&
304 ! RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_PASS )
305 )
306 {
307 todo = addchain( todo, ptnode );
308 RCN_SETFLAG( ptnode->FLAG, RCN_FLAG_PASS );
309 }
310 ptnode = getlonode( ptsig, scanwire->NODE2 );
311 if( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_TWO ) &&
312 ! RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_LOCON ) &&
313 ! RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_PASS )
314 )
315 {
316 todo = addchain( todo, ptnode );
317 RCN_SETFLAG( ptnode->FLAG, RCN_FLAG_PASS );
318 }
319 }
320
321 for( scanctc = ptsig->PRCN->PCTC ; scanctc ; scanctc = scanctc->NEXT )
322 {
323 ptctc = (loctc_list*)( scanctc->DATA );
324 rcn_addcapa( ptsig, ptctc->CAPA );
325 }
326
327 for( doing = todo ; doing ; doing = doing->NEXT )
328 {
329 ptnode = (lonode_list*)( doing->DATA );
330 if( ptnode->CTCLIST )
331 continue;
332
333 another = 1;
334 wire1 = (lowire_list*)( ptnode->WIRELIST->DATA );
335 wire2 = (lowire_list*)( ptnode->WIRELIST->NEXT->DATA );
336
337 if( ptnode->WIRELIST->NEXT->NEXT )
338 {
339 fprintf( stderr, "Anomalie.\n" );
340 }
341
342 resi = wire1->RESI + wire2->RESI ;
343 node1 = ( wire1->NODE1 == ptnode->INDEX ) ? wire1->NODE2 : wire1->NODE1 ;
344 node2 = ( wire2->NODE1 == ptnode->INDEX ) ? wire2->NODE2 : wire2->NODE1 ;
345
346 setdellowire( ptsig, wire1 );
347 setdellowire( ptsig, wire2 );
348 wire1 = NULL;
349 wire2 = NULL;
350
351 scanwire = getlowire( ptsig, node1, node2 );
352 if( scanwire )
353 addpararesiwire( scanwire, resi );
354 else
355 addlowire( ptsig,
356 0,
357 resi,
358 0.0,
359 node1,
360 node2
361 );
362 }
363 freechain( todo );
364
365 mergedellowire( ptsig );
366 }
367 while( another );
368
369 return(1);
370 }
371
372 void connexe_rec( losig_list *ptsig,
373 lowire_list *from,
374 lonode_list *ptnode,
375 int index
376 )
377 {
378 ptype_list *ptl;
379 chain_list *scanwire;
380 lonode_list *next;
381
382 /* Le noeud par lequel on arrive est deja numerote */
383
384 /* Propagation sur les branches droites */
385 while( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_TWO ) )
386 {
387 if( (lowire_list*)(ptnode->WIRELIST->DATA) == from )
388 from = (lowire_list*)(ptnode->WIRELIST->NEXT->DATA);
389 else
390 from = (lowire_list*)(ptnode->WIRELIST->DATA);
391
392 if( from->NODE1 == ptnode->INDEX )
393 ptnode = getlonode( ptsig, from->NODE2 );
394 else
395 ptnode = getlonode( ptsig, from->NODE1 );
396
397 ptl = getptype( ptnode->USER, CONNEXE );
398 if( (int)((long)ptl->DATA) != 0 )
399 {
400 if( (int)((long)ptl->DATA) != index )
401 rcn_error( 31, AVT_WARNING);
402 return;
403 }
404 else
405 ptl->DATA = (void*)((long)index);
406 }
407
408 /* On arrive soit sur un noeud terminal, soit sur un embranchement */
409 for( scanwire = ptnode->WIRELIST ; scanwire ; scanwire = scanwire->NEXT )
410 {
411 from = ( lowire_list* )( scanwire->DATA );
412 if( from->NODE1 == ptnode->INDEX )
413 next = getlonode( ptsig, from->NODE2 );
414 else
415 next = getlonode( ptsig, from->NODE1 );
416
417 ptl = getptype( next->USER, CONNEXE );
418 if( (int)((long)ptl->DATA) == 0 )
419 {
420 ptl->DATA = (void*)((long)index);
421 connexe_rec( ptsig, from, next, index );
422 }
423 else
424 {
425 if( (int)((long)ptl->DATA) != index ) {
426 rcn_error( 32, AVT_WARNING );
427 return ;
428 }
429 }
430 }
431
432 return;
433 }
434
435 int connexe( losig_list *ptsig )
436 {
437 lowire_list *scanlowire;
438 ptype_list *ptl;
439 lonode_list *ptnode;
440 int index;
441
442 if( !gettabnode( ptsig->PRCN ) ) {
443 rcn_error( 33, AVT_WARNING );
444 return 0 ;
445 }
446
447 for( scanlowire = ptsig->PRCN->PWIRE ;
448 scanlowire ;
449 scanlowire = scanlowire->NEXT
450 )
451 {
452 ptnode = getlonode( ptsig, scanlowire->NODE1 );
453 ptl = getptype( ptnode->USER, CONNEXE );
454 if( !ptl )
455 ptnode->USER = addptype( ptnode->USER, CONNEXE, (void*)0 );
456 else
457 ptl->DATA = (void*)0;
458
459 ptnode = getlonode( ptsig, scanlowire->NODE2 );
460 ptl = getptype( ptnode->USER, CONNEXE );
461 if( !ptl )
462 ptnode->USER = addptype( ptnode->USER, CONNEXE, (void*)0 );
463 else
464 ptl->DATA = (void*)0;
465 }
466
467 index = 0;
468
469 for( scanlowire = ptsig->PRCN->PWIRE ;
470 scanlowire ;
471 scanlowire = scanlowire->NEXT
472 )
473 {
474 ptnode = getlonode( ptsig, scanlowire->NODE1 );
475 ptl = getptype( ptnode->USER, CONNEXE );
476
477 if( (int)((long)ptl->DATA) != 0 )
478 continue;
479
480 index++;
481
482 ptl->DATA = (void*)((long)index);
483 connexe_rec( ptsig, scanlowire, ptnode, index );
484
485 ptnode = getlonode( ptsig, scanlowire->NODE2 );
486 ptl = getptype( ptnode->USER, CONNEXE );
487 ptl->DATA = (void*)((long)index);
488 connexe_rec( ptsig, scanlowire, ptnode, index );
489
490 }
491
492 return( index );
493 }
494
495 void clean_connexe( ptsig )
496 losig_list *ptsig ;
497 {
498 lowire_list *wire ;
499 lonode_list *ptnode ;
500 for( wire = ptsig->PRCN->PWIRE ; wire ; wire = wire->NEXT ) {
501 ptnode = getlonode( ptsig, wire->NODE1 );
502 ptnode->USER = testanddelptype( ptnode->USER, CONNEXE );
503 ptnode = getlonode( ptsig, wire->NODE2 );
504 ptnode->USER = testanddelptype( ptnode->USER, CONNEXE );
505 }
506 }
507
508 chain_list* getway( ptsig, org, dest )
509 losig_list *ptsig;
510 long org;
511 long dest;
512 {
513 lonode_list *ptnode;
514
515 clearallwireflag( ptsig, RCN_FLAG_PASS );
516 ptnode = getlonode( ptsig, org );
517 if( rcn_testandmarknode( ptnode ) )
518 return NULL;
519 return getwayrec( ptsig, org, dest, NULL );
520 }
521
522 chain_list* getwayrec( ptsig, org, dest, prec )
523 losig_list *ptsig;
524 long org;
525 long dest;
526 lowire_list *prec;
527 {
528 chain_list *scanchain;
529 lowire_list *current_wire;
530 long current_node;
531 lonode_list *ptnode;
532 chain_list *chemin;
533 int loop;
534
535 ptnode = getlonode( ptsig, org );
536
537 for( scanchain = ptnode->WIRELIST ; scanchain ; scanchain = scanchain->NEXT )
538 {
539 current_wire = (lowire_list*)(scanchain->DATA);
540
541 if( current_wire != prec )
542 {
543 current_node = current_wire->NODE1 == org ? current_wire->NODE2 :
544 current_wire->NODE1 ;
545 ptnode = getlonode( NULL, current_node );
546 if( rcn_testandmarknode( ptnode ) ) continue;
547
548 loop = 0;
549 while( current_node != dest && RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_TWO ) && loop==0 )
550 {
551 current_wire = ( ptnode->WIRELIST->DATA == current_wire ) ?
552 ptnode->WIRELIST->NEXT->DATA :
553 ptnode->WIRELIST->DATA ;
554
555 current_node = ( current_wire->NODE1 == current_node ) ?
556 current_wire->NODE2 :
557 current_wire->NODE1 ;
558
559 ptnode = getlonode( NULL, current_node );
560 loop = rcn_testandmarknode( ptnode ) ;
561 }
562
563 if( current_node == dest && loop==0)
564 {
565 current_node = ( current_wire->NODE1 == current_node ) ?
566 current_wire->NODE2 :
567 current_wire->NODE1 ;
568
569 ptnode = getlonode( NULL, current_node );
570 chemin = addchain( NULL, current_wire );
571
572 while( current_node != org )
573 {
574 current_wire = ( ptnode->WIRELIST->DATA == current_wire ) ?
575 ptnode->WIRELIST->NEXT->DATA :
576 ptnode->WIRELIST->DATA ;
577
578 current_node = ( current_wire->NODE1 == current_node ) ?
579 current_wire->NODE2 :
580 current_wire->NODE1 ;
581
582 ptnode = getlonode( NULL, current_node );
583 chemin = addchain( chemin, current_wire );
584 }
585 return( chemin );
586 }
587
588 if( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_CROSS ) && loop == 0 )
589 {
590 if( (chemin = getwayrec( ptsig, current_node, dest, current_wire )) )
591 {
592 current_node = ( current_wire->NODE1 == current_node ) ?
593 current_wire->NODE2 :
594 current_wire->NODE1 ;
595
596 ptnode = getlonode( NULL, current_node );
597 chemin = addchain( chemin, current_wire );
598
599 while( current_node != org )
600 {
601 current_wire = ( ptnode->WIRELIST->DATA == current_wire ) ?
602 ptnode->WIRELIST->NEXT->DATA :
603 ptnode->WIRELIST->DATA ;
604
605 current_node = ( current_wire->NODE1 == current_node ) ?
606 current_wire->NODE2 :
607 current_wire->NODE1 ;
608
609 ptnode = getlonode( NULL, current_node );
610 chemin = addchain( chemin, current_wire );
611 }
612 return( chemin );
613 }
614 }
615 }
616 }
617 return( NULL );
618 }
619 static int rcn_get_a_r_way_sub(losig_list *ptsig, long org, long dest, chain_list **res)
620 {
621 chain_list *scanchain;
622 lowire_list *current_wire;
623 long current_node;
624 lonode_list *ptnode;
625 chain_list *chemin;
626 int loop;
627
628 if (org==dest) { *res=NULL; return 1; }
629 ptnode = getlonode( ptsig, org );
630 if( rcn_testandmarknode( ptnode ) ) return 0;
631
632 for( scanchain = ptnode->WIRELIST ; scanchain ; scanchain = scanchain->NEXT )
633 {
634 current_wire = (lowire_list*)(scanchain->DATA);
635 current_node = current_wire->NODE1 == org ? current_wire->NODE2 :
636 current_wire->NODE1 ;
637 if (rcn_get_a_r_way_sub(ptsig, current_node, dest, res))
638 {
639 *res=addchain(*res, current_wire);
640 return 1;
641 }
642 }
643 return 0;
644 }
645 chain_list *rcn_get_a_r_way(losig_list *ptsig, long org, long dest)
646 {
647 chain_list *res;
648 clearallwireflag( ptsig, RCN_FLAG_PASS );
649 if (rcn_get_a_r_way_sub(ptsig, org, dest, &res)) return res;
650 return NULL;
651 }
652
653 void rcn_dumprcn( losig_list *losig,
654 long start,
655 char *fname, /* nom du fichier ou null pour stdout */
656 lowire_list *wire, /* a mettre à NULL */
657 FILE *file /* a mettre à NULL */
658 )
659 {
660 lonode_list *curnode;
661 chain_list *scan;
662 int encore;
663 loctc_list *ctc;
664 char first=0;
665
666 if( !file ) {
667 first=1;
668 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
669 RCN_CLEARFLAG( wire->FLAG, RCN_FLAG_PASS );
670 if( fname )
671 file = mbkfopen( fname, NULL, "w" );
672 else
673 file = stdout;
674 }
675
676 if( wire==NULL ) {
677 fprintf( file, "*** RCN DUMP FOR SIGNAL %s ***\n", getsigname( losig ) );
678 for( scan = losig->PRCN->PCTC ; scan ; scan=scan->NEXT ) {
679 ctc = (loctc_list*)scan->DATA;
680 fprintf( file,
681 "C %5ld %3ld - %5ld %3ld : %e\n",
682 ctc->SIG1->INDEX,
683 ctc->NODE1,
684 ctc->SIG2->INDEX,
685 ctc->NODE2,
686 ctc->CAPA
687 );
688 }
689 }
690
691 curnode = getlonode( losig, start );
692
693 if( wire ) {
694
695 do {
696 if( RCN_GETFLAG( wire->FLAG, RCN_FLAG_PASS ) ) {
697 fprintf( file, "\n" );
698 return;
699 }
700 RCN_SETFLAG( wire->FLAG, RCN_FLAG_PASS );
701
702 if( curnode->INDEX == wire->NODE1 )
703 fprintf( file, "W %3ld %3ld %e\n", wire->NODE1, wire->NODE2, wire->RESI );
704 else
705 fprintf( file, "W %3ld %3ld %e\n", wire->NODE2, wire->NODE1, wire->RESI );
706
707 if( wire->NODE1 == curnode->INDEX )
708 curnode = getlonode( losig, wire->NODE2 );
709 else
710 curnode = getlonode( losig, wire->NODE1 );
711
712 if( RCN_GETFLAG( curnode->FLAG, RCN_FLAG_TWO ) ) {
713 if( wire == curnode->WIRELIST->DATA )
714 wire = (lowire_list*)curnode->WIRELIST->NEXT->DATA;
715 else
716 wire = (lowire_list*)curnode->WIRELIST->DATA;
717 encore = 1;
718 }
719 else
720 encore = 0;
721 }
722 while( encore );
723
724 }
725 fprintf( file, "\n" );
726
727 if( RCN_GETFLAG( curnode->FLAG, RCN_FLAG_CROSS ) || wire == NULL ) {
728 for( scan = curnode->WIRELIST ; scan ; scan = scan->NEXT ) {
729 if( scan->DATA != wire ) {
730 rcn_dumprcn( losig,
731 curnode->INDEX,
732 NULL,
733 (lowire_list*)scan->DATA,
734 file
735 );
736 }
737 }
738 }
739
740 if( first ) { /* premier appel */
741 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
742 RCN_CLEARFLAG( wire->FLAG, RCN_FLAG_PASS );
743 if( file != stdout )
744 fclose(file);
745 }
746 }
747
748 // Marque un noeud. Renvoie 1 si il état déjà marqué, et 0 sinon.
749
750 int rcn_testandmarknode( lonode_list *ptnode )
751 {
752 if( RCN_GETFLAG( ptnode->FLAG, RCN_FLAG_PASS ) )
753 return 1;
754 RCN_SETFLAG( ptnode->FLAG, RCN_FLAG_PASS );
755 return 0;
756 }
757
758
759 /******************************************************************************\
760 Fonctions permettant de mémoriser de l'information entre deux losig. L'ordre
761 victime agresseur est significatif.
762 La variable 'ptype' sert à différencier plusieurs informations différentes.
763 C'est un identifiant de ptype ordinaire, mais dont le dernier bit est géré par
764 ces fonctions.
765 ex : le ptype 1702 ( 11010100110 ) devient dans le USER des losig 1702 ou 1703.
766 L'argument data doit être différent de EMPTYHT.
767
768 ********************************************************************************
769
770 Principe :
771
772 Dans beaucoups de cas, il y a très peu de couplage. Une ptype_list pour stocker
773 l'agresseur (champs DATA) et l'information (champs TYPE) est donc satisfaisante.
774 Si on récupère successivement toutes les informations de couplage, cela conduit
775 à un algos en n².
776
777 Lorsque le n² devient inacceptable ( RCN_MAXCHAIN²), les ptype_list sont
778 remplacées par des tables de hash. Le gain est double : la consomation mémoire
779 ( la table de hash est un tableau de 2 valeurs, il n'y a pas de champs NEXT)
780 et le temps de calcul sont réduit.
781
782 Q : Pourquoi ne pas avoir utilisé alors systématiquement une table de hash ?
783
784 Parceque le malloc() standard utilisé par défaut dans addht() consomme en
785 réalité 24 octets au lieu de 12, et si on prend un petit nombre initial (par
786 exemple 2), le malloc des htitem consomme 24 octets au lieu de 16. Pour les
787 petits nombres d'agresseurs actifs (jusqu'à 6), la table de hash est donc plus
788 coûteuse en mémoire, pour un temps CPU plus grand à cause de la fonction de
789 hash.
790
791 \******************************************************************************/
792
793 long rcn_getcoupledinformation( victime, agresseur, ptype )
794 losig_list *victime;
795 losig_list *agresseur;
796 long ptype;
797 {
798 ptype_list *ptl;
799 long v;
800 long ptype_ptype;
801 long ptype_thash;
802
803 ptype_ptype = ptype & (~((long)0x1));
804 ptype_thash = ptype | ((long)0x1);
805
806 ptl = getptype( victime->USER, ptype_thash );
807
808 if( ptl ) {
809
810 v = gethtitem( ((ht*)(ptl->DATA)), agresseur );
811 if( v != EMPTYHT )
812 return v ;
813
814 return 0l;
815 }
816
817 ptl = getptype( victime->USER, ptype_ptype );
818
819 if( ptl ) {
820
821 for( ptl = ((ptype_list*)(ptl->DATA)) ;
822 ptl && (ptl->DATA) != agresseur ;
823 ptl = ptl->NEXT );
824
825 if( ptl )
826 return ptl->TYPE ;
827
828 return 0l;
829 }
830
831 return 0l;
832 }
833
834 void rcn_setcoupledinformation( victime, agresseur, data, ptype )
835 losig_list *victime;
836 losig_list *agresseur;
837 long data;
838 long ptype;
839 {
840 ptype_list *ptl;
841 ptype_list *scan;
842 int n;
843 ht *newht;
844 long ptype_ptype;
845 long ptype_thash;
846
847 ptype_ptype = ptype & (~((long)0x1));
848 ptype_thash = ptype | ((long)0x1);
849
850 ptl = getptype( victime->USER, ptype_thash );
851
852 if( ptl ) {
853 sethtitem( ((ht*)(ptl->DATA)), agresseur, (long)data );
854 return ;
855 }
856
857 ptl = getptype( victime->USER, ptype_ptype );
858
859 if( !ptl ) {
860
861 victime->USER = addptype( victime->USER,
862 ptype_ptype,
863 NULL
864 );
865 ptl = victime->USER;
866 }
867
868 for( scan = ((ptype_list*)(ptl->DATA)), n=0 ;
869 scan && scan->DATA != agresseur ;
870 scan = scan->NEXT, n++ );
871
872 if( scan ) {
873 scan->TYPE = data;
874 return ;
875 }
876
877 if( n > RCN_MAXCHAIN ) {
878
879 newht = addht( RCN_MAXCHAIN + 1 );
880
881 for( scan = ((ptype_list*)( ptl->DATA )) ; scan ; scan = scan->NEXT )
882 addhtitem( newht, scan->DATA, scan->TYPE );
883 addhtitem( newht, agresseur, data );
884
885 freeptype( ((ptype_list*)(ptl->DATA)) );
886 victime->USER = delptype( victime->USER, ptype_ptype );
887 ptl = NULL;
888
889 victime->USER = addptype( victime->USER, ptype_thash, newht );
890
891 }
892 else {
893
894 ptl->DATA = addptype( ((ptype_list*)(ptl->DATA)),
895 data,
896 agresseur
897 );
898 }
899 }
900
901 void rcn_freecoupledinformation( losig_list *losig, long ptype )
902 {
903 ptype_list *ptl;
904 long ptype_ptype;
905 long ptype_thash;
906
907 ptype_ptype = ptype & (~((long)0x1));
908 ptype_thash = ptype | ((long)0x1);
909
910 ptl = getptype( losig->USER, ptype_ptype );
911 if( ptl ) {
912 freeptype( (ptype_list*)ptl->DATA );
913 losig->USER = delptype( losig->USER, ptype_ptype );
914 }
915
916 ptl = getptype( losig->USER, ptype_thash );
917 if( ptl ) {
918 delht( (ht*)ptl->DATA );
919 losig->USER = delptype( losig->USER, ptype_thash );
920 }
921 }
922
923 /******************************************************************************\
924 Fonctions de parcours générique des arbres rc.
925 renvoie :
926 RCNTREETRIPOK : tout s'est bien passé
927 RCNTREETRIPUSERKO : une fonction utilisateur a renvoyée 0
928 RCNTREETRIPLOOP : une boucle a été détectée.
929
930 Algo iteratif sur les résistances mises bout à bout pour éviter trop
931 de recursion qui peuvent provoquer un débordement de pile.
932 Au retour, tous les noeuds parcourus ont l'indicateur RCN_FLAG_PASS positionné.
933 maxdepth est la profondeur de parcours maximum. Si 0, le parcours est illimité.
934 \******************************************************************************/
935 int rcn_treetrip( losig_list *losig,
936 lonode_list *lonode,
937 int fn_up( losig_list*,
938 lonode_list*,
939 lowire_list*,
940 void*
941 ),
942 int fn_down( losig_list*,
943 lonode_list*,
944 chain_list*,
945 ht*,
946 void*
947 ),
948 int fn_pack_up( losig_list*,
949 lonode_list*,
950 void*,
951 void*
952 ),
953 void *userdata,
954 int maxdepth
955 )
956 {
957 int r ;
958
959 if( maxdepth <= 0 )
960 maxdepth = INT_MAX ;
961
962 clearallwireflag( losig, RCN_FLAG_PASS );
963 rcn_build_para( losig );
964
965 if( fn_up ) {
966 if( ! fn_up( losig, lonode, NULL, userdata ) )
967 return RCNTREETRIPUSERKO ;
968 }
969
970 RCN_SETFLAG( lonode->FLAG, RCN_FLAG_PASS );
971
972 r = rcn_treetrip_rec( losig,
973 lonode,
974 fn_up,
975 fn_down,
976 fn_pack_up,
977 NULL,
978 NULL,
979 userdata,
980 maxdepth
981 );
982
983 rcn_clean_para( losig );
984 return r ;
985 }
986
987 int rcn_treetrip_rec( losig_list *losig,
988 lonode_list *lonode,
989 int fn_up( losig_list*,
990 lonode_list*,
991 lowire_list*,
992 void*
993 ),
994 int fn_down( losig_list*,
995 lonode_list*,
996 chain_list*,
997 ht*,
998 void*
999 ),
1000 int fn_pack_up( losig_list*,
1001 lonode_list*,
1002 void*,
1003 void*
1004 ),
1005 lowire_list *from,
1006 void *prevpack,
1007 void *userdata,
1008 int maxdepth
1009 )
1010 {
1011 lonode_list *start ;
1012 lonode_list *firstnode ;
1013 lowire_list *wire ;
1014 char doitagain ;
1015 chain_list *bellow ;
1016 ht *htpack ;
1017 chain_list *chpack ;
1018 void *pack ;
1019 chain_list *list ;
1020 int r ;
1021 chain_list *headpack ;
1022 chain_list *scanpack ;
1023 chain_list *nodeout ;
1024 lowire_list *last ;
1025 int error ;
1026
1027 firstnode = lonode ;
1028 doitagain = 1 ;
1029
1030 /******* parcours dans le sens montant **************************************/
1031 do {
1032 if( lonode != firstnode ) {
1033
1034 if( RCN_GETFLAG( lonode->FLAG, RCN_FLAG_PASS ) )
1035 return RCNTREETRIPLOOP ;
1036 RCN_SETFLAG( lonode->FLAG, RCN_FLAG_PASS );
1037
1038 if( fn_up ) {
1039 if( ! fn_up( losig, lonode, from, userdata ) )
1040 return RCNTREETRIPUSERKO;
1041 }
1042 maxdepth--;
1043 }
1044
1045 wire = NULL ;
1046
1047 if( maxdepth > 0 ) {
1048 if( ( RCN_GETFLAG( lonode->FLAG, RCN_FLAG_TWO ) == RCN_FLAG_TWO ) &&
1049 from != NULL ) {
1050 if( (lowire_list*)lonode->WIRELIST->DATA == from )
1051 wire = (lowire_list*)lonode->WIRELIST->NEXT->DATA ;
1052 else
1053 wire = (lowire_list*)lonode->WIRELIST->DATA ;
1054 }
1055 else {
1056 if( ( RCN_GETFLAG( lonode->FLAG, RCN_FLAG_ONE ) == RCN_FLAG_ONE ) &&
1057 from == NULL ) {
1058 wire = (lowire_list*)lonode->WIRELIST->DATA ;
1059 }
1060 }
1061 }
1062
1063 if( wire && RCN_GETFLAG( wire->FLAG, RCN_FLAG_IGNORE ) )
1064 wire = NULL ;
1065
1066 if( wire ) {
1067 lonode = getlonode( losig,
1068 (wire->NODE1 == lonode->INDEX ) ? wire->NODE2 :
1069 wire->NODE1
1070 );
1071 from = wire ;
1072 }
1073 else
1074 doitagain = 0 ;
1075 }
1076 while( doitagain );
1077
1078 /******* Intersection de plusieurs résistances ******************************/
1079
1080 /* propagation montante */
1081
1082 htpack = NULL;
1083 bellow = NULL ;
1084 error = RCNTREETRIPOK ;
1085 if( maxdepth > 0 ) {
1086 for( list = lonode->WIRELIST ; list ; list = list->NEXT ) {
1087
1088 wire = (lowire_list*)list->DATA ;
1089
1090 if( wire != from && !RCN_GETFLAG( wire->FLAG, RCN_FLAG_IGNORE ) ) {
1091
1092 pack = rcn_getpack( losig, wire );
1093
1094 if( pack ) {
1095
1096 if( pack != prevpack ) {
1097 if( !htpack )
1098 htpack = addht(5);
1099
1100 chpack = (void*)gethtitem( htpack, pack );
1101 if( chpack == (void*)EMPTYHT ) {
1102 chpack = addchain( NULL, wire );
1103 }
1104 else {
1105 chpack = addchain( chpack, wire );
1106 }
1107 addhtitem( htpack, pack, (long)chpack );
1108 }
1109 }
1110 else {
1111 bellow = addchain( bellow, wire );
1112 start = getlonode( losig,
1113 ( wire->NODE1 == lonode->INDEX ) ? wire->NODE2 :
1114 wire->NODE1
1115 );
1116
1117 if( RCN_GETFLAG( start->FLAG, RCN_FLAG_PASS ) ) {
1118 error = RCNTREETRIPLOOP ;
1119 break ;
1120 }
1121 RCN_SETFLAG( start->FLAG, RCN_FLAG_PASS );
1122
1123 if( fn_up ) {
1124 r = fn_up( losig, start, wire, userdata );
1125 if( !r ) {
1126 error = RCNTREETRIPUSERKO ;
1127 break ;
1128 }
1129 }
1130
1131 maxdepth-- ;
1132
1133 if( maxdepth > 0 ) {
1134 r = rcn_treetrip_rec( losig,
1135 start,
1136 fn_up,
1137 fn_down,
1138 fn_pack_up,
1139 wire,
1140 NULL,
1141 userdata,
1142 maxdepth
1143 );
1144 if( r != RCNTREETRIPOK ) {
1145 error = r;
1146 break;
1147 }
1148 }
1149 }
1150 }
1151 }
1152 }
1153
1154 headpack = NULL ;
1155
1156 if( error == RCNTREETRIPOK ) {
1157
1158 if( htpack ) {
1159
1160 headpack = GetAllHTElems( htpack );
1161
1162 for( scanpack = headpack ; scanpack ; scanpack = scanpack->NEXT ) {
1163
1164 chpack = scanpack->DATA ;
1165 wire = (lowire_list*)chpack->DATA;
1166 pack = rcn_getpack( losig, wire );
1167
1168 if( fn_pack_up ) {
1169 r = fn_pack_up( losig, lonode, pack, userdata );
1170 if( !r ) {
1171 error = RCNTREETRIPUSERKO ;
1172 break ;
1173 }
1174 }
1175
1176 maxdepth-- ;
1177
1178 nodeout = rcn_expandpack( losig, lonode, chpack, 1 );
1179 rcn_expandpack( losig, lonode, chpack, 0 );
1180
1181 for( list = nodeout ; list ; list = list->NEXT ) {
1182
1183 if( RCN_GETFLAG( ((lonode_list*)list->DATA)->FLAG, RCN_FLAG_PASS ) )
1184 {
1185 error = RCNTREETRIPLOOP ;
1186 break ;
1187 }
1188 RCN_SETFLAG( ((lonode_list*)list->DATA)->FLAG, RCN_FLAG_PASS ) ;
1189
1190 r = rcn_treetrip_rec( losig,
1191 (lonode_list*)list->DATA,
1192 fn_up,
1193 fn_down,
1194 fn_pack_up,
1195 NULL,
1196 pack,
1197 userdata,
1198 maxdepth
1199 );
1200 if( r != RCNTREETRIPOK ) {
1201 error = r ;
1202 break ;
1203 }
1204 }
1205
1206 freechain( nodeout );
1207
1208 if( error != RCNTREETRIPOK )
1209 break ;
1210 }
1211 }
1212 }
1213
1214 /* propagation descendante */
1215
1216 if( error == RCNTREETRIPOK ) {
1217 if( fn_down ) {
1218 r= fn_down( losig, lonode, bellow, htpack, userdata );
1219 if( !r )
1220 error = RCNTREETRIPUSERKO ;
1221 }
1222 }
1223
1224 /* lé ménache */
1225 if( htpack ) {
1226 freechain(headpack);
1227 headpack = GetAllHTElems( htpack );
1228 for( scanpack = headpack ; scanpack ; scanpack = scanpack->NEXT ) {
1229 chpack = scanpack->DATA ;
1230 freechain( chpack );
1231 }
1232 freechain( headpack );
1233 delht( htpack );
1234 }
1235 freechain( bellow );
1236 bellow = NULL;
1237
1238 if( error != RCNTREETRIPOK )
1239 return error ;
1240
1241 /******* parcours dans le sens descendant ***********************************/
1242
1243 doitagain = 1 ;
1244 last = NULL ;
1245
1246 do {
1247
1248 if( fn_down ) {
1249 if( last ) {
1250 bellow = addchain( NULL, last );
1251 r = fn_down( losig, lonode, bellow, NULL, userdata );
1252 freechain( bellow );
1253 if( !r )
1254 return RCNTREETRIPUSERKO ;
1255 }
1256 }
1257
1258
1259 last = from ;
1260
1261 if( lonode != firstnode ) {
1262 lonode = getlonode( losig,
1263 ( from->NODE1 == lonode->INDEX ) ? from->NODE2 :
1264 from->NODE1
1265 );
1266 if( lonode != firstnode ) {
1267 from = ( (lowire_list*)lonode->WIRELIST->DATA == from ) ?
1268 (lowire_list*)lonode->WIRELIST->NEXT->DATA :
1269 (lowire_list*)lonode->WIRELIST->DATA ;
1270 }
1271 }
1272 else
1273 doitagain = 0 ;
1274 }
1275 while( doitagain );
1276
1277 return RCNTREETRIPOK ;
1278 }
1279
1280 /******************************************************************************\
1281 Renvoie tous les noeuds à l'exterieur d'un pack contenant les résistances
1282 données dans hwire.
1283 \******************************************************************************/
1284 chain_list* rcn_expandpack( losig_list *losig,
1285 lonode_list *node,
1286 chain_list *hwire,
1287 char search
1288 )
1289 {
1290 chain_list *chain ;
1291 lowire_list *wire ;
1292 void *pack ;
1293 int inode ;
1294 lonode_list *pnode ;
1295 chain_list *todo ;
1296 chain_list *scan ;
1297 lowire_list *twire ;
1298 void *tpack ;
1299 chain_list *found ;
1300 chain_list *bellow ;
1301
1302 found = NULL ;
1303
1304 if( search ) {
1305 pack = rcn_getpack( losig, (lowire_list*)hwire->DATA );
1306 RCN_SETFLAG( node->FLAG, RCN_FLAG_PASS2 );
1307 }
1308 else {
1309 RCN_CLEARFLAG( node->FLAG, RCN_FLAG_PASS2 );
1310 }
1311
1312 for( chain = hwire ; chain ; chain = chain->NEXT ) {
1313 wire = (lowire_list*)chain->DATA ;
1314 inode = ( wire->NODE1 == node->INDEX ? wire->NODE2 : wire->NODE1 );
1315 pnode = getlonode( losig, inode );
1316 if( search ) {
1317 if( !RCN_GETFLAG( pnode->FLAG, RCN_FLAG_PASS2 ) ) {
1318 todo = NULL ;
1319 found = addchain( found, pnode );
1320 for( scan = pnode->WIRELIST ; scan ; scan = scan->NEXT ) {
1321 twire = (lowire_list*)scan->DATA;
1322 if( RCN_GETFLAG( twire->FLAG, RCN_FLAG_IGNORE ) )
1323 continue ;
1324 tpack = rcn_getpack( losig, twire );
1325 if( wire != twire ) {
1326 if( tpack == pack )
1327 todo = addchain( todo, twire );
1328 }
1329 }
1330 if( todo ) {
1331 bellow = rcn_expandpack( losig, pnode, todo, search );
1332 found = append( bellow, found );
1333 freechain( todo );
1334 }
1335 }
1336 }
1337 else {
1338 if( RCN_GETFLAG( pnode->FLAG, RCN_FLAG_PASS2 ) ) {
1339 todo = NULL ;
1340 for( scan = pnode->WIRELIST ; scan ; scan = scan->NEXT ) {
1341 twire = (lowire_list*)scan->DATA ;
1342 if( RCN_GETFLAG( twire->FLAG, RCN_FLAG_IGNORE ) )
1343 continue ;
1344 if( wire != twire )
1345 todo = addchain( todo, twire );
1346 }
1347 if( todo ) {
1348 rcn_expandpack( losig, pnode, todo, search );
1349 freechain( todo );
1350 }
1351 }
1352 }
1353 }
1354
1355 return found ;
1356 }
1357
1358 /******************************************************************************\
1359 Pour gérer les ensembles de résistance dans les arbres RC.
1360 \******************************************************************************/
1361 void rcn_setpack( losig_list *losig, lowire_list *wire, void *pack )
1362 {
1363 ptype_list *ptl ;
1364
1365 ptl = getptype( wire->USER, RCNWIREPACK );
1366 if( ptl )
1367 ptl->DATA = pack ;
1368 else
1369 wire->USER = addptype( wire->USER, RCNWIREPACK, pack );
1370
1371 losig = NULL ;
1372 }
1373
1374 void* rcn_getpack( losig_list *losig, lowire_list *wire )
1375 {
1376 ptype_list *ptl ;
1377 void *pack ;
1378
1379 ptl = getptype( wire->USER, RCNWIREPACK );
1380 if( ptl )
1381 pack = ptl->DATA ;
1382 else
1383 pack = NULL ;
1384
1385 losig = NULL ;
1386 return pack ;
1387 }
1388
1389 void rcn_clearpack( losig_list *losig, lowire_list *wire )
1390 {
1391 ptype_list *ptl ;
1392
1393 ptl = getptype( wire->USER, RCNWIREPACK );
1394 if( ptl )
1395 wire->USER = delptype( wire->USER, RCNWIREPACK );
1396 losig = NULL ;
1397 }
1398
1399 /******************************************************************************\
1400 Pour gérer les résistances en parallèle dans les réseaux RC.
1401
1402 Parmis n resistances parallèles, une seule est à conserver. Elle contient un
1403 ptype RCNPARA qui contient une chain_list des autres résistances en parallèles.
1404 Ces autres résistances sont marquées RCN_FLAG_IGNORE.
1405 Marque aussi les résistances entre deux même noeud avec RCN_FLAG_IGNORE.
1406
1407 La construction de cette information se fait avec rcn_build_para(). Il faut la
1408 libérer avec rcn_clean_para().
1409
1410 Problème avec l'utilisation des caches RC : cette information ne doit pas
1411 être conservée. Pour ne pas reconstruire plusieurs fois cette information si
1412 ce n'est pas nécessaire, on utilise le flag RCNCACHEFLAG_NOPARA dans le losig
1413 pour indiquer que la recherche a déjà été effectuée et qu'elle n'a rien donnée.
1414 \******************************************************************************/
1415
1416 void rcn_build_para( losig_list *losig )
1417 {
1418 lowire_list *wire ;
1419
1420 if( RCN_GETFLAG( losig->RCNCACHE, RCNCACHEFLAG_NOPARA ) )
1421 return ;
1422
1423 RCN_SETFLAG( losig->RCNCACHE, RCNCACHEFLAG_NOPARA );
1424
1425 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT ) {
1426 if( rcn_build_para_from_node( losig, getlonode( losig, wire->NODE1 ) ) )
1427 RCN_CLEARFLAG( losig->RCNCACHE, RCNCACHEFLAG_NOPARA );
1428 if( rcn_build_para_from_node( losig, getlonode( losig, wire->NODE2 ) ) )
1429 RCN_CLEARFLAG( losig->RCNCACHE, RCNCACHEFLAG_NOPARA );
1430 }
1431 }
1432
1433 int rcn_build_para_from_node( losig_list *losig, lonode_list *lonode )
1434 {
1435 chain_list *chain ;
1436 lowire_list *wire ;
1437 int inode ;
1438 lonode_list *pnode ;
1439 chain_list *chain2 ;
1440 lowire_list *retwire ;
1441 int found ;
1442 ptype_list *ptl ;
1443
1444 found = 0 ;
1445
1446 for( chain = lonode->WIRELIST ; chain ; chain = chain->NEXT ) {
1447
1448 wire = (lowire_list*)chain->DATA ;
1449
1450 if( RCN_GETFLAG( wire->FLAG, RCN_FLAG_IGNORE ) )
1451 continue ;
1452
1453 inode = (wire->NODE1 == lonode->INDEX ? wire->NODE2 : wire->NODE1 );
1454
1455 if( inode == lonode->INDEX ) {
1456 /* Résistance sur un seul noeud */
1457 RCN_SETFLAG( wire->FLAG, RCN_FLAG_IGNORE ) ;
1458 found = 1 ;
1459 continue ;
1460 }
1461
1462 if( inode > lonode->INDEX ) {
1463
1464 pnode = getlonode( losig, inode );
1465
1466 for( chain2 = pnode->WIRELIST ; chain2 ; chain2 = chain2->NEXT ) {
1467
1468 retwire = (lowire_list*)chain2->DATA ;
1469
1470 if( retwire == wire )
1471 continue ;
1472
1473 if( RCN_GETFLAG( retwire->FLAG, RCN_FLAG_IGNORE ) )
1474 continue ;
1475
1476 if( retwire->NODE1 == lonode->INDEX ||
1477 retwire->NODE2 == lonode->INDEX ) {
1478
1479 /* Résistance retwire et parallele avec wire */
1480 ptl = getptype( wire->USER, RCNPARA ) ;
1481 if( ptl )
1482 ptl->DATA = addchain( (chain_list*)ptl->DATA, retwire );
1483 else
1484 wire->USER = addptype( wire->USER,
1485 RCNPARA,
1486 addchain( NULL, retwire )
1487 );
1488
1489 RCN_SETFLAG( retwire->FLAG, RCN_FLAG_IGNORE );
1490 found = 1 ;
1491 }
1492 }
1493 }
1494 }
1495
1496 return found ;
1497 }
1498
1499 void rcn_clean_para( losig_list *losig )
1500 {
1501 lowire_list *wire ;
1502 ptype_list *ptl ;
1503
1504 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT ) {
1505 ptl = getptype( wire->USER, RCNPARA ) ;
1506 if( ptl ) {
1507 freechain( (chain_list*) ptl->DATA );
1508 wire->USER = delptype( wire->USER, RCNPARA );
1509 }
1510 RCN_CLEARFLAG( wire->FLAG, RCN_FLAG_IGNORE );
1511 }
1512 }
1513
1514 float rcn_get_resi_para( lowire_list *wire )
1515 {
1516 float resi ;
1517 ptype_list *ptl ;
1518 lowire_list *pwire ;
1519 chain_list *chain ;
1520
1521 resi = wire->RESI ;
1522 ptl = getptype( wire->USER, RCNPARA );
1523 if( ptl ) {
1524 for( chain = (chain_list*)ptl->DATA ; chain ; chain = chain->NEXT ) {
1525 pwire = (lowire_list*)chain->DATA ;
1526 resi = ( resi * pwire->RESI ) / ( resi + pwire->RESI );
1527 }
1528 }
1529 return resi ;
1530 }
1531
1532 /******************************************************************************\
1533 Applique la fonction fn() sur toutes les résistances d'un réseau RC accessibles
1534 depuis le noeud start. L'ordre de parcour est en profondeur d'abord, sauf si des
1535 boucles sont présentes.
1536 Au retour de la fonction, tous les noeuds parcourus ont l'indicateur
1537 RCN_FLAG_PASS positionné.
1538 Algo iteratif sur les résistances mises bout à bout pour éviter trop
1539 de recursion qui peuvent provoquer un débordement de pile.
1540
1541 code de retour : RCNTRIPCONNEXE_OK ou RCNTRIPCONNEXE_USERKO.
1542 fn doit renvoyer 1 si ok, ou 0 si ko.
1543
1544 \******************************************************************************/
1545 int rcn_tripconnexe( losig_list *losig,
1546 int startnode,
1547 int fn( losig_list*,
1548 lowire_list*,
1549 void*
1550 ),
1551 void *userdata
1552 )
1553 {
1554 lonode_list *ptnode ;
1555 lowire_list *wire ;
1556 chain_list *chwire ;
1557
1558 for( wire = losig->PRCN->PWIRE ; wire ; wire = wire->NEXT )
1559 RCN_CLEARFLAG( wire->FLAG, RCN_FLAG_PASS );
1560
1561 ptnode = getlonode( losig, startnode );
1562
1563 for( chwire = ptnode->WIRELIST ; chwire ; chwire = chwire->NEXT ) {
1564 wire = (lowire_list*)chwire->DATA ;
1565 if( rcn_tripconnexe_rec( losig, ptnode, wire, fn, userdata ) !=
1566 RCNTRIPCONNEXE_OK )
1567 break ;
1568 }
1569
1570 if( chwire )
1571 return RCNTRIPCONNEXE_USERKO ;
1572 return RCNTRIPCONNEXE_OK ;
1573 }
1574
1575 int rcn_tripconnexe_rec( losig_list *losig,
1576 lonode_list *from,
1577 lowire_list *wire,
1578 int fn( losig_list*,
1579 lowire_list*,
1580 void*
1581 ),
1582 void *userdata
1583 )
1584 {
1585 lonode_list *othernode ;
1586 chain_list *chwire ;
1587
1588 if( RCN_GETFLAG( wire->FLAG, RCN_FLAG_PASS ) ) {
1589 /* a loop is found */
1590 return RCNTRIPCONNEXE_OK ;
1591 }
1592
1593 if( fn( losig, wire, userdata ) == 0 )
1594 return RCNTRIPCONNEXE_USERKO ;
1595 RCN_SETFLAG( wire->FLAG, RCN_FLAG_PASS );
1596
1597 if( wire->NODE1 == from->INDEX )
1598 othernode = getlonode( losig, wire->NODE2 );
1599 else
1600 othernode = getlonode( losig, wire->NODE1 );
1601
1602 while( RCN_GETFLAG( othernode->FLAG, RCN_FLAG_TWO ) ) {
1603
1604 if( wire == (lowire_list*)othernode->WIRELIST->DATA )
1605 wire = (lowire_list*)othernode->WIRELIST->NEXT->DATA ;
1606 else
1607 wire = (lowire_list*)othernode->WIRELIST->DATA ;
1608
1609 if( RCN_GETFLAG( wire->FLAG, RCN_FLAG_PASS ) )
1610 break ;
1611
1612 if( fn( losig, wire, userdata ) == 0 )
1613 return RCNTRIPCONNEXE_USERKO ;
1614 RCN_SETFLAG( wire->FLAG, RCN_FLAG_PASS );
1615
1616 if( wire->NODE1 == othernode->INDEX )
1617 othernode = getlonode( losig, wire->NODE2 );
1618 else
1619 othernode = getlonode( losig, wire->NODE1 );
1620 }
1621
1622 for( chwire = othernode->WIRELIST ; chwire ; chwire = chwire->NEXT ) {
1623 if( rcn_tripconnexe_rec( losig,
1624 othernode,
1625 (lowire_list*)chwire->DATA,
1626 fn,
1627 userdata
1628 ) != RCNTRIPCONNEXE_OK )
1629 break ;
1630 }
1631
1632 if( chwire )
1633 return RCNTRIPCONNEXE_USERKO;
1634 return RCNTRIPCONNEXE_OK ;
1635 }