6 /******************************************************************************/
8 void duplorcnet( ptsig_dest
, ptsig_src
)
9 losig_list
*ptsig_dest
;
10 losig_list
*ptsig_src
;
12 lowire_list
*scanlowire
;
16 if( ptsig_dest
->PRCN
) {
17 rcn_error( 27, AVT_WARNING
);
21 if( !ptsig_src
->PRCN
)
24 addlorcnet( ptsig_dest
);
26 /* Capacité du signal */
27 rcn_setcapa( ptsig_dest
, rcn_getcapa( NULL
, ptsig_src
) );
29 /* Wire constituant le signal */
30 for( scanlowire
= ptsig_src
->PRCN
->PWIRE
;
32 scanlowire
= scanlowire
->NEXT
36 if( RCN_GETFLAG( scanlowire
->FLAG
, RCN_FLAG_DEL
) )
38 newwire
= heaplowire();
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
;
48 if ((ptuser
= getptype(scanlowire
->USER
, RESINAME
))!=NULL
)
49 newwire
->USER
= addptype(newwire
->USER
, RESINAME
, ptuser
->DATA
);
51 if ((ptuser
= getptype(scanlowire
->USER
, OPT_PARAMS
)))
52 newwire
->USER
= addptype(newwire
->USER
, OPT_PARAMS
, dupoptparamlst((optparam_list
*)ptuser
->DATA
));
54 ptsig_dest
->PRCN
->PWIRE
= newwire
;
57 /* CTC sur le signal : non gere */
58 ptsig_dest
->PRCN
->PCTC
= NULL
;
61 ptsig_dest
->PRCN
->NBNODE
= ptsig_src
->PRCN
->NBNODE
;
64 ptsig_dest
->PRCN
->USER
= NULL
;
67 /******************************************************************************/
69 todolist
* breakloop2( ptsig
, ptnode
, curwire
, headtodo
, cleanwire
)
74 chain_list
**cleanwire
;
77 chain_list
*scanchain
;
82 if( RCN_GETFLAG( curwire
->FLAG
, RCN_FLAG_PASS
) ) {
83 rcn_error( 28, AVT_WARNING
);
87 RCN_SETFLAG( curwire
->FLAG
, RCN_FLAG_PASS
);
92 /* On trouve une boucle */
93 if( RCN_GETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
) )
95 tmpwire
= addlowire( ptsig
,
100 addlonode( ptsig
, NULL
)
102 *cleanwire
= addchain( *cleanwire
, curwire
);
103 RCN_SETFLAG( tmpwire
->FLAG
, RCN_FLAG_PASS
);
104 RCN_SETFLAG( curwire
->FLAG
, RCN_FLAG_PASS
);
108 RCN_SETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
);
111 /* Recherche un wire non parcouru sur le noeud courant */
112 for( scanchain
= ptnode
->WIRELIST
;
114 scanchain
= scanchain
->NEXT
117 curwire
= (lowire_list
*)(scanchain
->DATA
);
118 if( ! RCN_GETFLAG( curwire
->FLAG
, RCN_FLAG_PASS
) )
123 break; /* on quitte le while */
125 /* Ajoute les autre wire non parcouru sur le noeud dans une
132 for( scanchain
= scanchain
->NEXT
;
134 scanchain
= scanchain
->NEXT
137 tmpwire
= (lowire_list
*)(scanchain
->DATA
);
139 if( ! RCN_GETFLAG( tmpwire
->FLAG
, RCN_FLAG_PASS
) )
143 newtodo
= (todolist
*)(mbkalloc( sizeof(todolist
) ) );
144 newtodo
->next
= headtodo
;
146 newtodo
->ptnode
= ptnode
;
147 newtodo
->head_wire
= NULL
;
149 newtodo
->head_wire
= addchain( newtodo
->head_wire
, tmpwire
);
154 ptnode
= getlonode( NULL
,
155 ( curwire
->NODE1
== ptnode
->INDEX
) ? curwire
->NODE2
:
159 RCN_SETFLAG( curwire
->FLAG
, RCN_FLAG_PASS
);
161 while(1); /* c'est ben vrai! */
166 int breakloop( ptsig
)
174 lowire_list
*firstwire
;
175 lowire_list
*curwire
;
177 chain_list
*cleanwire
;
178 chain_list
*scanchain
;
180 if( !ptsig
->PRCN
|| !gettabnode( ptsig
->PRCN
) ) {
182 rcn_error( 29, AVT_WARNING
);
185 clearallwireflag( ptsig
, RCN_FLAG_PASS
);
190 /* Boucle pour parcourir les differentes composantes connexes */
192 for( firstwire
= ptsig
->PRCN
->PWIRE
;
194 firstwire
= firstwire
->NEXT
197 if( RCN_GETFLAG( firstwire
->FLAG
, RCN_FLAG_DEL
) )
200 ptnode
= getlonode( NULL
, firstwire
->NODE1
);
202 if( ! RCN_GETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
) )
204 /* Corps d'une des composante connexe du reseau */
206 headtodo
= breakloop2( ptsig
, ptnode
, NULL
, NULL
, &cleanwire
);
212 for( scantodo
= headtodo
; scantodo
; scantodo
= scantodo
->next
)
214 for( scanchain
= scantodo
->head_wire
;
216 scanchain
= scanchain
->NEXT
220 curwire
= (lowire_list
*)( scanchain
->DATA
);
222 if( ! RCN_GETFLAG( curwire
->FLAG
, RCN_FLAG_PASS
) )
225 newtodo
= breakloop2( ptsig
,
227 ( scantodo
->ptnode
->INDEX
==
242 curtodo
= headtodo
->next
;
243 freechain( headtodo
->head_wire
);
253 for( scanchain
= cleanwire
; scanchain
; scanchain
= scanchain
->NEXT
)
255 curwire
= (lowire_list
*)( scanchain
->DATA
);
256 dellowire( ptsig
, curwire
->NODE1
, curwire
->NODE2
);
259 freechain ( cleanwire
);
264 int reduce_rcn( ptsig
)
267 lowire_list
*scanwire
;
280 rcn_checkwritesignal(ptsig
);
282 if( !gettabnode( ptsig
->PRCN
) ) {
283 rcn_error( 30, AVT_WARNING
);
292 rcn_setcapa( ptsig
, 0.0 );
294 for( scanwire
= ptsig
->PRCN
->PWIRE
; scanwire
; scanwire
= scanwire
->NEXT
)
296 if( RCN_GETFLAG( scanwire
->FLAG
, RCN_FLAG_DEL
) )
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
)
307 todo
= addchain( todo
, ptnode
);
308 RCN_SETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
);
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
)
316 todo
= addchain( todo
, ptnode
);
317 RCN_SETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
);
321 for( scanctc
= ptsig
->PRCN
->PCTC
; scanctc
; scanctc
= scanctc
->NEXT
)
323 ptctc
= (loctc_list
*)( scanctc
->DATA
);
324 rcn_addcapa( ptsig
, ptctc
->CAPA
);
327 for( doing
= todo
; doing
; doing
= doing
->NEXT
)
329 ptnode
= (lonode_list
*)( doing
->DATA
);
330 if( ptnode
->CTCLIST
)
334 wire1
= (lowire_list
*)( ptnode
->WIRELIST
->DATA
);
335 wire2
= (lowire_list
*)( ptnode
->WIRELIST
->NEXT
->DATA
);
337 if( ptnode
->WIRELIST
->NEXT
->NEXT
)
339 fprintf( stderr
, "Anomalie.\n" );
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
;
346 setdellowire( ptsig
, wire1
);
347 setdellowire( ptsig
, wire2
);
351 scanwire
= getlowire( ptsig
, node1
, node2
);
353 addpararesiwire( scanwire
, resi
);
365 mergedellowire( ptsig
);
372 void connexe_rec( losig_list
*ptsig
,
379 chain_list
*scanwire
;
382 /* Le noeud par lequel on arrive est deja numerote */
384 /* Propagation sur les branches droites */
385 while( RCN_GETFLAG( ptnode
->FLAG
, RCN_FLAG_TWO
) )
387 if( (lowire_list
*)(ptnode
->WIRELIST
->DATA
) == from
)
388 from
= (lowire_list
*)(ptnode
->WIRELIST
->NEXT
->DATA
);
390 from
= (lowire_list
*)(ptnode
->WIRELIST
->DATA
);
392 if( from
->NODE1
== ptnode
->INDEX
)
393 ptnode
= getlonode( ptsig
, from
->NODE2
);
395 ptnode
= getlonode( ptsig
, from
->NODE1
);
397 ptl
= getptype( ptnode
->USER
, CONNEXE
);
398 if( (int)((long)ptl
->DATA
) != 0 )
400 if( (int)((long)ptl
->DATA
) != index
)
401 rcn_error( 31, AVT_WARNING
);
405 ptl
->DATA
= (void*)((long)index
);
408 /* On arrive soit sur un noeud terminal, soit sur un embranchement */
409 for( scanwire
= ptnode
->WIRELIST
; scanwire
; scanwire
= scanwire
->NEXT
)
411 from
= ( lowire_list
* )( scanwire
->DATA
);
412 if( from
->NODE1
== ptnode
->INDEX
)
413 next
= getlonode( ptsig
, from
->NODE2
);
415 next
= getlonode( ptsig
, from
->NODE1
);
417 ptl
= getptype( next
->USER
, CONNEXE
);
418 if( (int)((long)ptl
->DATA
) == 0 )
420 ptl
->DATA
= (void*)((long)index
);
421 connexe_rec( ptsig
, from
, next
, index
);
425 if( (int)((long)ptl
->DATA
) != index
) {
426 rcn_error( 32, AVT_WARNING
);
435 int connexe( losig_list
*ptsig
)
437 lowire_list
*scanlowire
;
442 if( !gettabnode( ptsig
->PRCN
) ) {
443 rcn_error( 33, AVT_WARNING
);
447 for( scanlowire
= ptsig
->PRCN
->PWIRE
;
449 scanlowire
= scanlowire
->NEXT
452 ptnode
= getlonode( ptsig
, scanlowire
->NODE1
);
453 ptl
= getptype( ptnode
->USER
, CONNEXE
);
455 ptnode
->USER
= addptype( ptnode
->USER
, CONNEXE
, (void*)0 );
457 ptl
->DATA
= (void*)0;
459 ptnode
= getlonode( ptsig
, scanlowire
->NODE2
);
460 ptl
= getptype( ptnode
->USER
, CONNEXE
);
462 ptnode
->USER
= addptype( ptnode
->USER
, CONNEXE
, (void*)0 );
464 ptl
->DATA
= (void*)0;
469 for( scanlowire
= ptsig
->PRCN
->PWIRE
;
471 scanlowire
= scanlowire
->NEXT
474 ptnode
= getlonode( ptsig
, scanlowire
->NODE1
);
475 ptl
= getptype( ptnode
->USER
, CONNEXE
);
477 if( (int)((long)ptl
->DATA
) != 0 )
482 ptl
->DATA
= (void*)((long)index
);
483 connexe_rec( ptsig
, scanlowire
, ptnode
, index
);
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
);
495 void clean_connexe( ptsig
)
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
);
508 chain_list
* getway( ptsig
, org
, dest
)
515 clearallwireflag( ptsig
, RCN_FLAG_PASS
);
516 ptnode
= getlonode( ptsig
, org
);
517 if( rcn_testandmarknode( ptnode
) )
519 return getwayrec( ptsig
, org
, dest
, NULL
);
522 chain_list
* getwayrec( ptsig
, org
, dest
, prec
)
528 chain_list
*scanchain
;
529 lowire_list
*current_wire
;
535 ptnode
= getlonode( ptsig
, org
);
537 for( scanchain
= ptnode
->WIRELIST
; scanchain
; scanchain
= scanchain
->NEXT
)
539 current_wire
= (lowire_list
*)(scanchain
->DATA
);
541 if( current_wire
!= prec
)
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;
549 while( current_node
!= dest
&& RCN_GETFLAG( ptnode
->FLAG
, RCN_FLAG_TWO
) && loop
==0 )
551 current_wire
= ( ptnode
->WIRELIST
->DATA
== current_wire
) ?
552 ptnode
->WIRELIST
->NEXT
->DATA
:
553 ptnode
->WIRELIST
->DATA
;
555 current_node
= ( current_wire
->NODE1
== current_node
) ?
556 current_wire
->NODE2
:
557 current_wire
->NODE1
;
559 ptnode
= getlonode( NULL
, current_node
);
560 loop
= rcn_testandmarknode( ptnode
) ;
563 if( current_node
== dest
&& loop
==0)
565 current_node
= ( current_wire
->NODE1
== current_node
) ?
566 current_wire
->NODE2
:
567 current_wire
->NODE1
;
569 ptnode
= getlonode( NULL
, current_node
);
570 chemin
= addchain( NULL
, current_wire
);
572 while( current_node
!= org
)
574 current_wire
= ( ptnode
->WIRELIST
->DATA
== current_wire
) ?
575 ptnode
->WIRELIST
->NEXT
->DATA
:
576 ptnode
->WIRELIST
->DATA
;
578 current_node
= ( current_wire
->NODE1
== current_node
) ?
579 current_wire
->NODE2
:
580 current_wire
->NODE1
;
582 ptnode
= getlonode( NULL
, current_node
);
583 chemin
= addchain( chemin
, current_wire
);
588 if( RCN_GETFLAG( ptnode
->FLAG
, RCN_FLAG_CROSS
) && loop
== 0 )
590 if( (chemin
= getwayrec( ptsig
, current_node
, dest
, current_wire
)) )
592 current_node
= ( current_wire
->NODE1
== current_node
) ?
593 current_wire
->NODE2
:
594 current_wire
->NODE1
;
596 ptnode
= getlonode( NULL
, current_node
);
597 chemin
= addchain( chemin
, current_wire
);
599 while( current_node
!= org
)
601 current_wire
= ( ptnode
->WIRELIST
->DATA
== current_wire
) ?
602 ptnode
->WIRELIST
->NEXT
->DATA
:
603 ptnode
->WIRELIST
->DATA
;
605 current_node
= ( current_wire
->NODE1
== current_node
) ?
606 current_wire
->NODE2
:
607 current_wire
->NODE1
;
609 ptnode
= getlonode( NULL
, current_node
);
610 chemin
= addchain( chemin
, current_wire
);
619 static int rcn_get_a_r_way_sub(losig_list
*ptsig
, long org
, long dest
, chain_list
**res
)
621 chain_list
*scanchain
;
622 lowire_list
*current_wire
;
628 if (org
==dest
) { *res
=NULL
; return 1; }
629 ptnode
= getlonode( ptsig
, org
);
630 if( rcn_testandmarknode( ptnode
) ) return 0;
632 for( scanchain
= ptnode
->WIRELIST
; scanchain
; scanchain
= scanchain
->NEXT
)
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
))
639 *res
=addchain(*res
, current_wire
);
645 chain_list
*rcn_get_a_r_way(losig_list
*ptsig
, long org
, long dest
)
648 clearallwireflag( ptsig
, RCN_FLAG_PASS
);
649 if (rcn_get_a_r_way_sub(ptsig
, org
, dest
, &res
)) return res
;
653 void rcn_dumprcn( losig_list
*losig
,
655 char *fname
, /* nom du fichier ou null pour stdout */
656 lowire_list
*wire
, /* a mettre à NULL */
657 FILE *file
/* a mettre à NULL */
660 lonode_list
*curnode
;
668 for( wire
= losig
->PRCN
->PWIRE
; wire
; wire
= wire
->NEXT
)
669 RCN_CLEARFLAG( wire
->FLAG
, RCN_FLAG_PASS
);
671 file
= mbkfopen( fname
, NULL
, "w" );
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
;
681 "C %5ld %3ld - %5ld %3ld : %e\n",
691 curnode
= getlonode( losig
, start
);
696 if( RCN_GETFLAG( wire
->FLAG
, RCN_FLAG_PASS
) ) {
697 fprintf( file
, "\n" );
700 RCN_SETFLAG( wire
->FLAG
, RCN_FLAG_PASS
);
702 if( curnode
->INDEX
== wire
->NODE1
)
703 fprintf( file
, "W %3ld %3ld %e\n", wire
->NODE1
, wire
->NODE2
, wire
->RESI
);
705 fprintf( file
, "W %3ld %3ld %e\n", wire
->NODE2
, wire
->NODE1
, wire
->RESI
);
707 if( wire
->NODE1
== curnode
->INDEX
)
708 curnode
= getlonode( losig
, wire
->NODE2
);
710 curnode
= getlonode( losig
, wire
->NODE1
);
712 if( RCN_GETFLAG( curnode
->FLAG
, RCN_FLAG_TWO
) ) {
713 if( wire
== curnode
->WIRELIST
->DATA
)
714 wire
= (lowire_list
*)curnode
->WIRELIST
->NEXT
->DATA
;
716 wire
= (lowire_list
*)curnode
->WIRELIST
->DATA
;
725 fprintf( file
, "\n" );
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
) {
733 (lowire_list
*)scan
->DATA
,
740 if( first
) { /* premier appel */
741 for( wire
= losig
->PRCN
->PWIRE
; wire
; wire
= wire
->NEXT
)
742 RCN_CLEARFLAG( wire
->FLAG
, RCN_FLAG_PASS
);
748 // Marque un noeud. Renvoie 1 si il état déjà marqué, et 0 sinon.
750 int rcn_testandmarknode( lonode_list
*ptnode
)
752 if( RCN_GETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
) )
754 RCN_SETFLAG( ptnode
->FLAG
, RCN_FLAG_PASS
);
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
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.
768 ********************************************************************************
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
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.
782 Q : Pourquoi ne pas avoir utilisé alors systématiquement une table de hash ?
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
791 \******************************************************************************/
793 long rcn_getcoupledinformation( victime
, agresseur
, ptype
)
795 losig_list
*agresseur
;
803 ptype_ptype
= ptype
& (~((long)0x1));
804 ptype_thash
= ptype
| ((long)0x1);
806 ptl
= getptype( victime
->USER
, ptype_thash
);
810 v
= gethtitem( ((ht
*)(ptl
->DATA
)), agresseur
);
817 ptl
= getptype( victime
->USER
, ptype_ptype
);
821 for( ptl
= ((ptype_list
*)(ptl
->DATA
)) ;
822 ptl
&& (ptl
->DATA
) != agresseur
;
834 void rcn_setcoupledinformation( victime
, agresseur
, data
, ptype
)
836 losig_list
*agresseur
;
847 ptype_ptype
= ptype
& (~((long)0x1));
848 ptype_thash
= ptype
| ((long)0x1);
850 ptl
= getptype( victime
->USER
, ptype_thash
);
853 sethtitem( ((ht
*)(ptl
->DATA
)), agresseur
, (long)data
);
857 ptl
= getptype( victime
->USER
, ptype_ptype
);
861 victime
->USER
= addptype( victime
->USER
,
868 for( scan
= ((ptype_list
*)(ptl
->DATA
)), n
=0 ;
869 scan
&& scan
->DATA
!= agresseur
;
870 scan
= scan
->NEXT
, n
++ );
877 if( n
> RCN_MAXCHAIN
) {
879 newht
= addht( RCN_MAXCHAIN
+ 1 );
881 for( scan
= ((ptype_list
*)( ptl
->DATA
)) ; scan
; scan
= scan
->NEXT
)
882 addhtitem( newht
, scan
->DATA
, scan
->TYPE
);
883 addhtitem( newht
, agresseur
, data
);
885 freeptype( ((ptype_list
*)(ptl
->DATA
)) );
886 victime
->USER
= delptype( victime
->USER
, ptype_ptype
);
889 victime
->USER
= addptype( victime
->USER
, ptype_thash
, newht
);
894 ptl
->DATA
= addptype( ((ptype_list
*)(ptl
->DATA
)),
901 void rcn_freecoupledinformation( losig_list
*losig
, long ptype
)
907 ptype_ptype
= ptype
& (~((long)0x1));
908 ptype_thash
= ptype
| ((long)0x1);
910 ptl
= getptype( losig
->USER
, ptype_ptype
);
912 freeptype( (ptype_list
*)ptl
->DATA
);
913 losig
->USER
= delptype( losig
->USER
, ptype_ptype
);
916 ptl
= getptype( losig
->USER
, ptype_thash
);
918 delht( (ht
*)ptl
->DATA
);
919 losig
->USER
= delptype( losig
->USER
, ptype_thash
);
923 /******************************************************************************\
924 Fonctions de parcours générique des arbres rc.
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.
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
,
937 int fn_up( losig_list
*,
942 int fn_down( losig_list
*,
948 int fn_pack_up( losig_list
*,
962 clearallwireflag( losig
, RCN_FLAG_PASS
);
963 rcn_build_para( losig
);
966 if( ! fn_up( losig
, lonode
, NULL
, userdata
) )
967 return RCNTREETRIPUSERKO
;
970 RCN_SETFLAG( lonode
->FLAG
, RCN_FLAG_PASS
);
972 r
= rcn_treetrip_rec( losig
,
983 rcn_clean_para( losig
);
987 int rcn_treetrip_rec( losig_list
*losig
,
989 int fn_up( losig_list
*,
994 int fn_down( losig_list
*,
1000 int fn_pack_up( losig_list
*,
1011 lonode_list
*start
;
1012 lonode_list
*firstnode
;
1015 chain_list
*bellow
;
1017 chain_list
*chpack
;
1021 chain_list
*headpack
;
1022 chain_list
*scanpack
;
1023 chain_list
*nodeout
;
1027 firstnode
= lonode
;
1030 /******* parcours dans le sens montant **************************************/
1032 if( lonode
!= firstnode
) {
1034 if( RCN_GETFLAG( lonode
->FLAG
, RCN_FLAG_PASS
) )
1035 return RCNTREETRIPLOOP
;
1036 RCN_SETFLAG( lonode
->FLAG
, RCN_FLAG_PASS
);
1039 if( ! fn_up( losig
, lonode
, from
, userdata
) )
1040 return RCNTREETRIPUSERKO
;
1047 if( maxdepth
> 0 ) {
1048 if( ( RCN_GETFLAG( lonode
->FLAG
, RCN_FLAG_TWO
) == RCN_FLAG_TWO
) &&
1050 if( (lowire_list
*)lonode
->WIRELIST
->DATA
== from
)
1051 wire
= (lowire_list
*)lonode
->WIRELIST
->NEXT
->DATA
;
1053 wire
= (lowire_list
*)lonode
->WIRELIST
->DATA
;
1056 if( ( RCN_GETFLAG( lonode
->FLAG
, RCN_FLAG_ONE
) == RCN_FLAG_ONE
) &&
1058 wire
= (lowire_list
*)lonode
->WIRELIST
->DATA
;
1063 if( wire
&& RCN_GETFLAG( wire
->FLAG
, RCN_FLAG_IGNORE
) )
1067 lonode
= getlonode( losig
,
1068 (wire
->NODE1
== lonode
->INDEX
) ? wire
->NODE2
:
1078 /******* Intersection de plusieurs résistances ******************************/
1080 /* propagation montante */
1084 error
= RCNTREETRIPOK
;
1085 if( maxdepth
> 0 ) {
1086 for( list
= lonode
->WIRELIST
; list
; list
= list
->NEXT
) {
1088 wire
= (lowire_list
*)list
->DATA
;
1090 if( wire
!= from
&& !RCN_GETFLAG( wire
->FLAG
, RCN_FLAG_IGNORE
) ) {
1092 pack
= rcn_getpack( losig
, wire
);
1096 if( pack
!= prevpack
) {
1100 chpack
= (void*)gethtitem( htpack
, pack
);
1101 if( chpack
== (void*)EMPTYHT
) {
1102 chpack
= addchain( NULL
, wire
);
1105 chpack
= addchain( chpack
, wire
);
1107 addhtitem( htpack
, pack
, (long)chpack
);
1111 bellow
= addchain( bellow
, wire
);
1112 start
= getlonode( losig
,
1113 ( wire
->NODE1
== lonode
->INDEX
) ? wire
->NODE2
:
1117 if( RCN_GETFLAG( start
->FLAG
, RCN_FLAG_PASS
) ) {
1118 error
= RCNTREETRIPLOOP
;
1121 RCN_SETFLAG( start
->FLAG
, RCN_FLAG_PASS
);
1124 r
= fn_up( losig
, start
, wire
, userdata
);
1126 error
= RCNTREETRIPUSERKO
;
1133 if( maxdepth
> 0 ) {
1134 r
= rcn_treetrip_rec( losig
,
1144 if( r
!= RCNTREETRIPOK
) {
1156 if( error
== RCNTREETRIPOK
) {
1160 headpack
= GetAllHTElems( htpack
);
1162 for( scanpack
= headpack
; scanpack
; scanpack
= scanpack
->NEXT
) {
1164 chpack
= scanpack
->DATA
;
1165 wire
= (lowire_list
*)chpack
->DATA
;
1166 pack
= rcn_getpack( losig
, wire
);
1169 r
= fn_pack_up( losig
, lonode
, pack
, userdata
);
1171 error
= RCNTREETRIPUSERKO
;
1178 nodeout
= rcn_expandpack( losig
, lonode
, chpack
, 1 );
1179 rcn_expandpack( losig
, lonode
, chpack
, 0 );
1181 for( list
= nodeout
; list
; list
= list
->NEXT
) {
1183 if( RCN_GETFLAG( ((lonode_list
*)list
->DATA
)->FLAG
, RCN_FLAG_PASS
) )
1185 error
= RCNTREETRIPLOOP
;
1188 RCN_SETFLAG( ((lonode_list
*)list
->DATA
)->FLAG
, RCN_FLAG_PASS
) ;
1190 r
= rcn_treetrip_rec( losig
,
1191 (lonode_list
*)list
->DATA
,
1200 if( r
!= RCNTREETRIPOK
) {
1206 freechain( nodeout
);
1208 if( error
!= RCNTREETRIPOK
)
1214 /* propagation descendante */
1216 if( error
== RCNTREETRIPOK
) {
1218 r
= fn_down( losig
, lonode
, bellow
, htpack
, userdata
);
1220 error
= RCNTREETRIPUSERKO
;
1226 freechain(headpack
);
1227 headpack
= GetAllHTElems( htpack
);
1228 for( scanpack
= headpack
; scanpack
; scanpack
= scanpack
->NEXT
) {
1229 chpack
= scanpack
->DATA
;
1230 freechain( chpack
);
1232 freechain( headpack
);
1235 freechain( bellow
);
1238 if( error
!= RCNTREETRIPOK
)
1241 /******* parcours dans le sens descendant ***********************************/
1250 bellow
= addchain( NULL
, last
);
1251 r
= fn_down( losig
, lonode
, bellow
, NULL
, userdata
);
1252 freechain( bellow
);
1254 return RCNTREETRIPUSERKO
;
1261 if( lonode
!= firstnode
) {
1262 lonode
= getlonode( losig
,
1263 ( from
->NODE1
== lonode
->INDEX
) ? from
->NODE2
:
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
;
1277 return RCNTREETRIPOK
;
1280 /******************************************************************************\
1281 Renvoie tous les noeuds à l'exterieur d'un pack contenant les résistances
1283 \******************************************************************************/
1284 chain_list
* rcn_expandpack( losig_list
*losig
,
1294 lonode_list
*pnode
;
1297 lowire_list
*twire
;
1300 chain_list
*bellow
;
1305 pack
= rcn_getpack( losig
, (lowire_list
*)hwire
->DATA
);
1306 RCN_SETFLAG( node
->FLAG
, RCN_FLAG_PASS2
);
1309 RCN_CLEARFLAG( node
->FLAG
, RCN_FLAG_PASS2
);
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
);
1317 if( !RCN_GETFLAG( pnode
->FLAG
, RCN_FLAG_PASS2
) ) {
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
) )
1324 tpack
= rcn_getpack( losig
, twire
);
1325 if( wire
!= twire
) {
1327 todo
= addchain( todo
, twire
);
1331 bellow
= rcn_expandpack( losig
, pnode
, todo
, search
);
1332 found
= append( bellow
, found
);
1338 if( RCN_GETFLAG( pnode
->FLAG
, RCN_FLAG_PASS2
) ) {
1340 for( scan
= pnode
->WIRELIST
; scan
; scan
= scan
->NEXT
) {
1341 twire
= (lowire_list
*)scan
->DATA
;
1342 if( RCN_GETFLAG( twire
->FLAG
, RCN_FLAG_IGNORE
) )
1345 todo
= addchain( todo
, twire
);
1348 rcn_expandpack( losig
, pnode
, todo
, search
);
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
)
1365 ptl
= getptype( wire
->USER
, RCNWIREPACK
);
1369 wire
->USER
= addptype( wire
->USER
, RCNWIREPACK
, pack
);
1374 void* rcn_getpack( losig_list
*losig
, lowire_list
*wire
)
1379 ptl
= getptype( wire
->USER
, RCNWIREPACK
);
1389 void rcn_clearpack( losig_list
*losig
, lowire_list
*wire
)
1393 ptl
= getptype( wire
->USER
, RCNWIREPACK
);
1395 wire
->USER
= delptype( wire
->USER
, RCNWIREPACK
);
1399 /******************************************************************************\
1400 Pour gérer les résistances en parallèle dans les réseaux RC.
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.
1407 La construction de cette information se fait avec rcn_build_para(). Il faut la
1408 libérer avec rcn_clean_para().
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 \******************************************************************************/
1416 void rcn_build_para( losig_list
*losig
)
1420 if( RCN_GETFLAG( losig
->RCNCACHE
, RCNCACHEFLAG_NOPARA
) )
1423 RCN_SETFLAG( losig
->RCNCACHE
, RCNCACHEFLAG_NOPARA
);
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
);
1433 int rcn_build_para_from_node( losig_list
*losig
, lonode_list
*lonode
)
1438 lonode_list
*pnode
;
1439 chain_list
*chain2
;
1440 lowire_list
*retwire
;
1446 for( chain
= lonode
->WIRELIST
; chain
; chain
= chain
->NEXT
) {
1448 wire
= (lowire_list
*)chain
->DATA
;
1450 if( RCN_GETFLAG( wire
->FLAG
, RCN_FLAG_IGNORE
) )
1453 inode
= (wire
->NODE1
== lonode
->INDEX
? wire
->NODE2
: wire
->NODE1
);
1455 if( inode
== lonode
->INDEX
) {
1456 /* Résistance sur un seul noeud */
1457 RCN_SETFLAG( wire
->FLAG
, RCN_FLAG_IGNORE
) ;
1462 if( inode
> lonode
->INDEX
) {
1464 pnode
= getlonode( losig
, inode
);
1466 for( chain2
= pnode
->WIRELIST
; chain2
; chain2
= chain2
->NEXT
) {
1468 retwire
= (lowire_list
*)chain2
->DATA
;
1470 if( retwire
== wire
)
1473 if( RCN_GETFLAG( retwire
->FLAG
, RCN_FLAG_IGNORE
) )
1476 if( retwire
->NODE1
== lonode
->INDEX
||
1477 retwire
->NODE2
== lonode
->INDEX
) {
1479 /* Résistance retwire et parallele avec wire */
1480 ptl
= getptype( wire
->USER
, RCNPARA
) ;
1482 ptl
->DATA
= addchain( (chain_list
*)ptl
->DATA
, retwire
);
1484 wire
->USER
= addptype( wire
->USER
,
1486 addchain( NULL
, retwire
)
1489 RCN_SETFLAG( retwire
->FLAG
, RCN_FLAG_IGNORE
);
1499 void rcn_clean_para( losig_list
*losig
)
1504 for( wire
= losig
->PRCN
->PWIRE
; wire
; wire
= wire
->NEXT
) {
1505 ptl
= getptype( wire
->USER
, RCNPARA
) ;
1507 freechain( (chain_list
*) ptl
->DATA
);
1508 wire
->USER
= delptype( wire
->USER
, RCNPARA
);
1510 RCN_CLEARFLAG( wire
->FLAG
, RCN_FLAG_IGNORE
);
1514 float rcn_get_resi_para( lowire_list
*wire
)
1518 lowire_list
*pwire
;
1522 ptl
= getptype( wire
->USER
, RCNPARA
);
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
);
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.
1541 code de retour : RCNTRIPCONNEXE_OK ou RCNTRIPCONNEXE_USERKO.
1542 fn doit renvoyer 1 si ok, ou 0 si ko.
1544 \******************************************************************************/
1545 int rcn_tripconnexe( losig_list
*losig
,
1547 int fn( losig_list
*,
1554 lonode_list
*ptnode
;
1556 chain_list
*chwire
;
1558 for( wire
= losig
->PRCN
->PWIRE
; wire
; wire
= wire
->NEXT
)
1559 RCN_CLEARFLAG( wire
->FLAG
, RCN_FLAG_PASS
);
1561 ptnode
= getlonode( losig
, startnode
);
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
) !=
1571 return RCNTRIPCONNEXE_USERKO
;
1572 return RCNTRIPCONNEXE_OK
;
1575 int rcn_tripconnexe_rec( losig_list
*losig
,
1578 int fn( losig_list
*,
1585 lonode_list
*othernode
;
1586 chain_list
*chwire
;
1588 if( RCN_GETFLAG( wire
->FLAG
, RCN_FLAG_PASS
) ) {
1589 /* a loop is found */
1590 return RCNTRIPCONNEXE_OK
;
1593 if( fn( losig
, wire
, userdata
) == 0 )
1594 return RCNTRIPCONNEXE_USERKO
;
1595 RCN_SETFLAG( wire
->FLAG
, RCN_FLAG_PASS
);
1597 if( wire
->NODE1
== from
->INDEX
)
1598 othernode
= getlonode( losig
, wire
->NODE2
);
1600 othernode
= getlonode( losig
, wire
->NODE1
);
1602 while( RCN_GETFLAG( othernode
->FLAG
, RCN_FLAG_TWO
) ) {
1604 if( wire
== (lowire_list
*)othernode
->WIRELIST
->DATA
)
1605 wire
= (lowire_list
*)othernode
->WIRELIST
->NEXT
->DATA
;
1607 wire
= (lowire_list
*)othernode
->WIRELIST
->DATA
;
1609 if( RCN_GETFLAG( wire
->FLAG
, RCN_FLAG_PASS
) )
1612 if( fn( losig
, wire
, userdata
) == 0 )
1613 return RCNTRIPCONNEXE_USERKO
;
1614 RCN_SETFLAG( wire
->FLAG
, RCN_FLAG_PASS
);
1616 if( wire
->NODE1
== othernode
->INDEX
)
1617 othernode
= getlonode( losig
, wire
->NODE2
);
1619 othernode
= getlonode( losig
, wire
->NODE1
);
1622 for( chwire
= othernode
->WIRELIST
; chwire
; chwire
= chwire
->NEXT
) {
1623 if( rcn_tripconnexe_rec( losig
,
1625 (lowire_list
*)chwire
->DATA
,
1628 ) != RCNTRIPCONNEXE_OK
)
1633 return RCNTRIPCONNEXE_USERKO
;
1634 return RCNTRIPCONNEXE_OK
;