source: git/src/network.c @ d938f98d

warn-only-for-hanging-survey
Last change on this file since d938f98d was 6a29ae1, checked in by Olly Betts <olly@…>, 12 months ago

Only warn about hanging surveys

This has been an error previously, but at least for Walls data it
seems having hanging surveys is the norm, and Walls itself only
warns about them.

  • Property mode set to 100644
File size: 22.0 KB
RevLine 
[ff6cfe1]1/* network.c
[5853657]2 * Survex network reduction - find patterns and apply network reductions
[a4ae909]3 * Copyright (C) 1991-2002,2005 Olly Betts
[846746e]4 *
[89231c4]5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
[846746e]9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[89231c4]12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
[846746e]14 *
[89231c4]15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
[ecbc6c18]17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[a420b49]18 */
19
[032ed06]20#if 0
[564f471]21#define DEBUG_INVALID 1
22#define VALIDATE 1
[5853657]23#define DUMP_NETWORK 1
[032ed06]24#endif
25
[4c83f84]26#include <config.h>
[d1b1380]27
28#include "validate.h"
29#include "debug.h"
[a420b49]30#include "cavern.h"
[4167edd]31#include "message.h"
[d1b1380]32#include "netbits.h"
33#include "network.h"
34#include "out.h"
35
[a420b49]36/* type field isn't vital - join3 is unused except for deltastar, so
37 * we can set its value to indicate which type this is:
38 * join3 == NULL for noose, join3 == join1 for ||, otherwise D* */
39#ifdef EXPLICIT_STACKRED_TYPE
[5853657]40#define SET_NOOSE(SR) (SR)->type = 1
[4d695ce3]41#define IS_NOOSE(SR) ((SR)->type == 1)
[5853657]42#define SET_PARALLEL(SR) (SR)->type = 0
[4d695ce3]43#define IS_PARALLEL(SR) ((SR)->type == 0)
[5853657]44#define SET_DELTASTAR(SR) (SR)->type = 2
[4d695ce3]45#define IS_DELTASTAR(SR) ((SR)->type == 2)
[a420b49]46#else
47#define IS_NOOSE(SR) ((SR)->join3 == NULL)
[5853657]48#define SET_NOOSE(SR) (SR)->join3 = NULL
[a420b49]49#define IS_PARALLEL(SR) ((SR)->join3 == (SR)->join1)
[5853657]50#define SET_PARALLEL(SR) (SR)->join3 = (SR)->join1
51#define IS_DELTASTAR(SR) (!IS_NOOSE(SR) && !IS_PARALLEL(SR))
52#define SET_DELTASTAR(SR) NOP
[a420b49]53#endif
[4d695ce3]54
[d1b1380]55typedef struct StackRed {
[4d695ce3]56   struct Link *join1, *join2, *join3;
[a420b49]57#ifdef EXPLICIT_STACKRED_TYPE
[4d695ce3]58   int type; /* 1 => noose, 0 => parallel legs, 2 => delta-star */
[a420b49]59#endif
[4d695ce3]60   struct StackRed *next;
[d1b1380]61} stackRed;
62
63static stackRed *ptrRed; /* Ptr to TRaverse linked list for C*-*< , -*=*- */
64
[5853657]65/* can be altered by -z<letters> on command line */
66unsigned long optimize = BITA('l') | BITA('p') | BITA('d');
67/* Lollipops, Parallel legs, Iterate mx, Delta* */
[a420b49]68
69extern void
70remove_subnets(void)
71{
72   node *stn, *stn2, *stn3, *stn4;
73   int dirn, dirn2, dirn3, dirn4;
74   stackRed *trav;
75   linkfor *newleg, *newleg2;
[63d4f07]76   bool fMore = true;
[a420b49]77
[5853657]78   ptrRed = NULL;
[cb3d1e2]79
[a420b49]80   out_current_action(msg(/*Simplifying network*/129));
81
82   while (fMore) {
[63d4f07]83      fMore = false;
[a420b49]84      if (optimize & BITA('l')) {
[1e431a4e]85#if PRINT_NETBITS
86         printf("replacing lollipops\n");
87#endif
[421b7d2]88         /*      _
[a420b49]89          *     ( )
90          *      * stn
91          *      |
92          *      * stn2
93          * stn /|
94          *  4 * * stn3  -->  stn4 *-* stn3
[a4ae909]95          *    : :                 : :
[a420b49]96          */
97         /* NB can have non-fixed 0 nodes */
[564f471]98         FOR_EACH_STN(stn, stnlist) {
99            if (!fixed(stn) && three_node(stn)) {
[a420b49]100               dirn = -1;
101               if (stn->leg[1]->l.to == stn) dirn++;
102               if (stn->leg[0]->l.to == stn) dirn += 2;
103               if (dirn < 0) continue;
104
105               stn2 = stn->leg[dirn]->l.to;
106               if (fixed(stn2)) continue;
107
[4c07c51]108               SVX_ASSERT(three_node(stn2));
[a420b49]109
110               dirn2 = reverse_leg_dirn(stn->leg[dirn]);
111               dirn2 = (dirn2 + 1) % 3;
112               stn3 = stn2->leg[dirn2]->l.to;
113               if (stn2 == stn3) continue; /* dumb-bell - leave alone */
114
115               dirn3 = reverse_leg_dirn(stn2->leg[dirn2]);
116
117               trav = osnew(stackRed);
118               newleg2 = (linkfor*)osnew(linkrev);
119
120               newleg = copy_link(stn3->leg[dirn3]);
121
122               dirn2 = (dirn2 + 1) % 3;
123               stn4 = stn2->leg[dirn2]->l.to;
124               dirn4 = reverse_leg_dirn(stn2->leg[dirn2]);
[d1b1380]125#if 0
[a420b49]126               printf("Noose found with stn...stn4 = \n");
127               print_prefix(stn->name); putnl();
128               print_prefix(stn2->name); putnl();
129               print_prefix(stn3->name); putnl();
130               print_prefix(stn4->name); putnl();
[d1b1380]131#endif
132
[a420b49]133               addto_link(newleg, stn2->leg[dirn2]);
[d1b1380]134
[564f471]135               /* remove stn and stn2 */
136               remove_stn_from_list(&stnlist, stn);
137               remove_stn_from_list(&stnlist, stn2);
[d1b1380]138
[a420b49]139               /* stack noose and replace with a leg between stn3 and stn4 */
140               trav->join1 = stn3->leg[dirn3];
141               newleg->l.to = stn4;
142               newleg->l.reverse = dirn4 | FLAG_DATAHERE | FLAG_REPLACEMENTLEG;
[d1b1380]143
[a420b49]144               trav->join2 = stn4->leg[dirn4];
145               newleg2->l.to = stn3;
146               newleg2->l.reverse = dirn3 | FLAG_REPLACEMENTLEG;
[d1b1380]147
[a420b49]148               stn3->leg[dirn3] = newleg;
149               stn4->leg[dirn4] = newleg2;
[d1b1380]150
[a420b49]151               trav->next = ptrRed;
[421b7d2]152               SET_NOOSE(trav);
[032ed06]153#if PRINT_NETBITS
154               printf("remove noose\n");
[a420b49]155#endif
156               ptrRed = trav;
[63d4f07]157               fMore = true;
[a420b49]158            }
159         }
[d1b1380]160      }
161
[a420b49]162      if (optimize & BITA('p')) {
[032ed06]163#if PRINT_NETBITS
164         printf("replacing parallel legs\n");
165#endif
[564f471]166         FOR_EACH_STN(stn, stnlist) {
[a420b49]167            /*
168             *  :
169             *  * stn3
[a4ae909]170             *  |            :
171             *  * stn        * stn3
[a420b49]172             * ( )      ->   |
173             *  * stn2       * stn4
[a4ae909]174             *  |            :
[a420b49]175             *  * stn4
176             *  :
177             */
[564f471]178            if (!fixed(stn) && three_node(stn)) {
[a420b49]179               stn2 = stn->leg[0]->l.to;
180               if (stn2 == stn->leg[1]->l.to) {
181                  dirn = 2;
182               } else if (stn2 == stn->leg[2]->l.to) {
183                  dirn = 1;
184               } else {
185                  if (stn->leg[1]->l.to != stn->leg[2]->l.to) continue;
186                  stn2 = stn->leg[1]->l.to;
187                  dirn = 0;
188               }
189
190               /* stn == stn2 => noose */
191               if (fixed(stn2) || stn == stn2) continue;
192
[4c07c51]193               SVX_ASSERT(three_node(stn2));
[a420b49]194
195               stn3 = stn->leg[dirn]->l.to;
196               /* 3 parallel legs (=> nothing else) so leave */
197               if (stn3 == stn2) continue;
198
199               dirn3 = reverse_leg_dirn(stn->leg[dirn]);
200               dirn2 = (0 + 1 + 2 - reverse_leg_dirn(stn->leg[(dirn + 1) % 3])
201                        - reverse_leg_dirn(stn->leg[(dirn + 2) % 3]));
202
203               stn4 = stn2->leg[dirn2]->l.to;
204               dirn4 = reverse_leg_dirn(stn2->leg[dirn2]);
205
206               trav = osnew(stackRed);
207
208               newleg = copy_link(stn->leg[(dirn + 1) % 3]);
209               /* use newleg2 for scratch */
210               newleg2 = copy_link(stn->leg[(dirn + 2) % 3]);
211                 {
[43d6ecfe]212#ifdef NO_COVARIANCES
[dac18d8]213                    vars sum;
214                    var prod;
[eb18f4d]215                    delta temp, temp2;
[dac18d8]216                    addss(&sum, &newleg->v, &newleg2->v);
[4c07c51]217                    SVX_ASSERT2(!fZeros(&sum), "loop of zero variance found");
[dac18d8]218                    mulss(&prod, &newleg->v, &newleg2->v);
219                    mulsd(&temp, &newleg2->v, &newleg->d);
220                    mulsd(&temp2, &newleg->v, &newleg2->d);
[a420b49]221                    adddd(&temp, &temp, &temp2);
[dac18d8]222                    divds(&newleg->d, &temp, &sum);
223                    sdivvs(&newleg->v, &prod, &sum);
[43d6ecfe]224#else
[59f2dbb]225                    svar inv1, inv2, sum;
[eb18f4d]226                    delta temp, temp2;
[43d6ecfe]227                    /* if leg one is an equate, we can just ignore leg two
228                     * whatever it is */
[dac18d8]229                    if (invert_svar(&inv1, &newleg->v)) {
230                       if (invert_svar(&inv2, &newleg2->v)) {
[59f2dbb]231                          addss(&sum, &inv1, &inv2);
[dac18d8]232                          if (!invert_svar(&newleg->v, &sum)) {
[2d3f65a]233                             BUG("matrix singular in parallel legs replacement");
[43d6ecfe]234                          }
[cb3d1e2]235
[59f2dbb]236                          mulsd(&temp, &inv1, &newleg->d);
237                          mulsd(&temp2, &inv2, &newleg2->d);
[43d6ecfe]238                          adddd(&temp, &temp, &temp2);
[59f2dbb]239                          mulsd(&newleg->d, &newleg->v, &temp);
[43d6ecfe]240                       } else {
241                          /* leg two is an equate, so just ignore leg 1 */
242                          linkfor *tmpleg;
243                          tmpleg = newleg;
244                          newleg = newleg2;
245                          newleg2 = tmpleg;
246                       }
247                    }
248#endif
[a420b49]249                 }
250               osfree(newleg2);
251               newleg2 = (linkfor*)osnew(linkrev);
252
253               addto_link(newleg, stn2->leg[dirn2]);
254               addto_link(newleg, stn3->leg[dirn3]);
[d1b1380]255
256#if 0
[a420b49]257               printf("Parallel found with stn...stn4 = \n");
258               (dump_node)(stn); (dump_node)(stn2); (dump_node)(stn3); (dump_node)(stn4);
259               printf("dirns = %d %d %d %d\n", dirn, dirn2, dirn3, dirn4);
[d1b1380]260#endif
[4c07c51]261               SVX_ASSERT2(stn3->leg[dirn3]->l.to == stn, "stn3 end of || doesn't recip");
262               SVX_ASSERT2(stn4->leg[dirn4]->l.to == stn2, "stn4 end of || doesn't recip");
263               SVX_ASSERT2(stn->leg[(dirn+1)%3]->l.to == stn2 && stn->leg[(dirn + 2) % 3]->l.to == stn2, "|| legs aren't");
[a420b49]264
[564f471]265               /* remove stn and stn2 (already discarded triple parallel) */
[a420b49]266               /* so stn!=stn4 <=> stn2!=stn3 */
[564f471]267               remove_stn_from_list(&stnlist, stn);
268               remove_stn_from_list(&stnlist, stn2);
[a420b49]269
270               /* stack parallel and replace with a leg between stn3 and stn4 */
271               trav->join1 = stn3->leg[dirn3];
272               newleg->l.to = stn4;
273               newleg->l.reverse = dirn4 | FLAG_DATAHERE | FLAG_REPLACEMENTLEG;
274
275               trav->join2 = stn4->leg[dirn4];
276               newleg2->l.to = stn3;
277               newleg2->l.reverse = dirn3 | FLAG_REPLACEMENTLEG;
278
279               stn3->leg[dirn3] = newleg;
280               stn4->leg[dirn4] = newleg2;
281
282               trav->next = ptrRed;
[421b7d2]283               SET_PARALLEL(trav);
[032ed06]284#if PRINT_NETBITS
285               printf("remove parallel\n");
[a420b49]286#endif
287               ptrRed = trav;
[63d4f07]288               fMore = true;
[a420b49]289            }
290         }
[d1b1380]291      }
292
[a420b49]293      if (optimize & BITA('d')) {
294         node *stn5, *stn6;
295         int dirn5, dirn6, dirn0;
296         linkfor *legAB, *legBC, *legCA;
[1e431a4e]297#if PRINT_NETBITS
298         printf("replacing deltas with stars\n");
299#endif
[564f471]300         FOR_EACH_STN(stn, stnlist) {
[a420b49]301            /*    printf("*");*/
302            /*
[a4ae909]303             *          :
304             *          * stn5            :
305             *          |                 * stn5
306             *          * stn2            |
307             *         / \        ->      O stnZ
308             *    stn *---* stn3         / \
[421b7d2]309             *       /     \       stn4 *   * stn6
[a420b49]310             * stn4 *       * stn6      :   :
311             *      :       :
312             */
[3aa9b01]313            if (!fixed(stn) && three_node(stn)) {
[a420b49]314               for (dirn0 = 0; ; dirn0++) {
315                  if (dirn0 >= 3) goto nodeltastar; /* continue outer loop */
316                  dirn = dirn0;
317                  stn2 = stn->leg[dirn]->l.to;
318                  if (fixed(stn2) || stn2 == stn) continue;
319                  dirn2 = reverse_leg_dirn(stn->leg[dirn]);
320                  dirn2 = (dirn2 + 1) % 3;
321                  stn3 = stn2->leg[dirn2]->l.to;
322                  if (fixed(stn3) || stn3 == stn || stn3 == stn2)
323                     goto nextdirn2;
324                  dirn3 = reverse_leg_dirn(stn2->leg[dirn2]);
325                  dirn3 = (dirn3 + 1) % 3;
326                  if (stn3->leg[dirn3]->l.to == stn) {
327                     legAB = copy_link(stn->leg[dirn]);
328                     legBC = copy_link(stn2->leg[dirn2]);
329                     legCA = copy_link(stn3->leg[dirn3]);
330                     dirn = 0 + 1 + 2 - dirn - reverse_leg_dirn(stn3->leg[dirn3]);
331                     dirn2 = (dirn2 + 1) % 3;
332                     dirn3 = (dirn3 + 1) % 3;
333                  } else if (stn3->leg[(dirn3 + 1) % 3]->l.to == stn) {
334                     legAB = copy_link(stn->leg[dirn]);
335                     legBC = copy_link(stn2->leg[dirn2]);
336                     legCA = copy_link(stn3->leg[(dirn3 + 1) % 3]);
337                     dirn = (0 + 1 + 2 - dirn
338                             - reverse_leg_dirn(stn3->leg[(dirn3 + 1) % 3]));
339                     dirn2 = (dirn2 + 1) % 3;
340                     break;
341                  } else {
342                     nextdirn2:;
343                     dirn2 = (dirn2 + 1) % 3;
344                     stn3 = stn2->leg[dirn2]->l.to;
345                     if (fixed(stn3) || stn3 == stn || stn3 == stn2) continue;
346                     dirn3 = reverse_leg_dirn(stn2->leg[dirn2]);
347                     dirn3 = (dirn3 + 1) % 3;
348                     if (stn3->leg[dirn3]->l.to == stn) {
349                        legAB = copy_link(stn->leg[dirn]);
350                        legBC = copy_link(stn2->leg[dirn2]);
351                        legCA = copy_link(stn3->leg[dirn3]);
[cb3d1e2]352                        dirn = (0 + 1 + 2 - dirn
[a420b49]353                                - reverse_leg_dirn(stn3->leg[dirn3]));
354                        dirn2 = (dirn2 + 2) % 3;
355                        dirn3 = (dirn3 + 1) % 3;
356                        break;
357                     } else if (stn3->leg[(dirn3 + 1) % 3]->l.to == stn) {
358                        legAB = copy_link(stn->leg[dirn]);
359                        legBC = copy_link(stn2->leg[dirn2]);
360                        legCA = copy_link(stn3->leg[(dirn3 + 1) % 3]);
361                        dirn = (0 + 1 + 2 - dirn
362                                - reverse_leg_dirn(stn3->leg[(dirn3 + 1) % 3]));
363                        dirn2 = (dirn2 + 2) % 3;
364                        break;
365                     }
366                  }
367               }
[cb3d1e2]368
[4c07c51]369               SVX_ASSERT(three_node(stn2));
370               SVX_ASSERT(three_node(stn3));
[a420b49]371
372               stn4 = stn->leg[dirn]->l.to;
373               stn5 = stn2->leg[dirn2]->l.to;
374               stn6 = stn3->leg[dirn3]->l.to;
375
376               if (stn4 == stn2 || stn4 == stn3 || stn5 == stn3) break;
377
378               dirn4 = reverse_leg_dirn(stn->leg[dirn]);
379               dirn5 = reverse_leg_dirn(stn2->leg[dirn2]);
380               dirn6 = reverse_leg_dirn(stn3->leg[dirn3]);
[d1b1380]381#if 0
[a420b49]382               printf("delta-star, stn ... stn6 are:\n");
383               (dump_node)(stn);
384               (dump_node)(stn2);
385               (dump_node)(stn3);
386               (dump_node)(stn4);
387               (dump_node)(stn5);
388               (dump_node)(stn6);
[d1b1380]389#endif
[4c07c51]390               SVX_ASSERT(stn4->leg[dirn4]->l.to == stn);
391               SVX_ASSERT(stn5->leg[dirn5]->l.to == stn2);
392               SVX_ASSERT(stn6->leg[dirn6]->l.to == stn3);
[a420b49]393
394               trav = osnew(stackRed);
395                 {
[e322717]396                    linkfor *legAZ, *legBZ, *legCZ;
[a420b49]397                    node *stnZ;
398                    prefix *nameZ;
[59f2dbb]399                    svar invAB, invBC, invCA, tmp, sum, inv;
400                    var vtmp;
401                    svar sumAZBZ, sumBZCZ, sumCZAZ;
[eb18f4d]402                    delta temp, temp2;
[cb3d1e2]403
[43d6ecfe]404                    /* FIXME: ought to handle cases when some legs are
405                     * equates, but handle as a special case maybe? */
[dac18d8]406                    if (!invert_svar(&invAB, &legAB->v)) break;
407                    if (!invert_svar(&invBC, &legBC->v)) break;
408                    if (!invert_svar(&invCA, &legCA->v)) break;
[43d6ecfe]409
[59f2dbb]410                    addss(&sum, &legBC->v, &legCA->v);
411                    addss(&tmp, &sum, &legAB->v);
[dac18d8]412                    if (!invert_svar(&inv, &tmp)) {
[647407d]413                       /* impossible - loop of zero variance */
414                       BUG("loop of zero variance found");
415                    }
[cb3d1e2]416
[e322717]417                    legAZ = osnew(linkfor);
418                    legBZ = osnew(linkfor);
419                    legCZ = osnew(linkfor);
420
[43d6ecfe]421                    /* AZBZ */
[c861f75]422                    /* done above: addvv(&sum, &legBC->v, &legCA->v); */
[59f2dbb]423                    mulss(&vtmp, &sum, &inv);
424                    smulvs(&sumAZBZ, &vtmp, &legAB->v);
[43d6ecfe]425
426                    adddd(&temp, &legBC->d, &legCA->d);
[59f2dbb]427                    divds(&temp2, &temp, &sum);
428                    mulsd(&temp, &invAB, &legAB->d);
[c861f75]429                    subdd(&temp, &temp2, &temp);
[59f2dbb]430                    mulsd(&legBZ->d, &sumAZBZ, &temp);
[43d6ecfe]431
[c861f75]432                    /* leg vectors after transform are determined up to
433                     * a constant addition, so arbitrarily fix AZ = 0 */
434                    legAZ->d[2] = legAZ->d[1] = legAZ->d[0] = 0;
[43d6ecfe]435
[c861f75]436                    /* BZCZ */
[59f2dbb]437                    addss(&sum, &legCA->v, &legAB->v);
438                    mulss(&vtmp, &sum, &inv);
439                    smulvs(&sumBZCZ, &vtmp, &legBC->v);
[43d6ecfe]440
441                    /* CZAZ */
[59f2dbb]442                    addss(&sum, &legAB->v, &legBC->v);
443                    mulss(&vtmp, &sum, &inv);
444                    smulvs(&sumCZAZ, &vtmp, &legCA->v);
[43d6ecfe]445
446                    adddd(&temp, &legAB->d, &legBC->d);
[59f2dbb]447                    divds(&temp2, &temp, &sum);
448                    mulsd(&temp, &invCA, &legCA->d);
[c861f75]449                    /* NB: swapped arguments to negate answer for legCZ->d */
450                    subdd(&temp, &temp, &temp2);
[59f2dbb]451                    mulsd(&legCZ->d, &sumCZAZ, &temp);
[43d6ecfe]452
[e322717]453                    osfree(legAB);
454                    osfree(legBC);
455                    osfree(legCA);
456
[43d6ecfe]457                    /* Now add two, subtract third, and scale by 0.5 */
[59f2dbb]458                    addss(&sum, &sumAZBZ, &sumCZAZ);
459                    subss(&sum, &sum, &sumBZCZ);
460                    mulsc(&legAZ->v, &sum, 0.5);
[43d6ecfe]461
[59f2dbb]462                    addss(&sum, &sumBZCZ, &sumAZBZ);
463                    subss(&sum, &sum, &sumCZAZ);
464                    mulsc(&legBZ->v, &sum, 0.5);
[43d6ecfe]465
[59f2dbb]466                    addss(&sum, &sumCZAZ, &sumBZCZ);
467                    subss(&sum, &sum, &sumAZBZ);
468                    mulsc(&legCZ->v, &sum, 0.5);
[43d6ecfe]469
[a420b49]470                    nameZ = osnew(prefix);
[be97baf]471                    nameZ->pos = osnew(pos);
[ff6cfe1]472                    nameZ->ident = NULL;
[6adb88c]473                    nameZ->shape = 3;
[a420b49]474                    stnZ = osnew(node);
475                    stnZ->name = nameZ;
476                    nameZ->stn = stnZ;
477                    nameZ->up = NULL;
[932f7e9]478                    nameZ->min_export = nameZ->max_export = 0;
[a420b49]479                    unfix(stnZ);
[564f471]480                    add_stn_to_list(&stnlist, stnZ);
[a420b49]481                    legAZ->l.to = stnZ;
482                    legAZ->l.reverse = 0 | FLAG_DATAHERE | FLAG_REPLACEMENTLEG;
483                    legBZ->l.to = stnZ;
484                    legBZ->l.reverse = 1 | FLAG_DATAHERE | FLAG_REPLACEMENTLEG;
485                    legCZ->l.to = stnZ;
486                    legCZ->l.reverse = 2 | FLAG_DATAHERE | FLAG_REPLACEMENTLEG;
487                    stnZ->leg[0] = (linkfor*)osnew(linkrev);
488                    stnZ->leg[1] = (linkfor*)osnew(linkrev);
489                    stnZ->leg[2] = (linkfor*)osnew(linkrev);
490                    stnZ->leg[0]->l.to = stn4;
491                    stnZ->leg[0]->l.reverse = dirn4;
492                    stnZ->leg[1]->l.to = stn5;
493                    stnZ->leg[1]->l.reverse = dirn5;
494                    stnZ->leg[2]->l.to = stn6;
495                    stnZ->leg[2]->l.reverse = dirn6;
[dbb4e19]496                    addto_link(legAZ, stn4->leg[dirn4]);
497                    addto_link(legBZ, stn5->leg[dirn5]);
498                    addto_link(legCZ, stn6->leg[dirn6]);
[a420b49]499                    /* stack stuff */
500                    trav->join1 = stn4->leg[dirn4];
501                    trav->join2 = stn5->leg[dirn5];
502                    trav->join3 = stn6->leg[dirn6];
503                    trav->next = ptrRed;
[5853657]504                    SET_DELTASTAR(trav);
[032ed06]505#if PRINT_NETBITS
506                    printf("remove delta*\n");
[a420b49]507#endif
508                    ptrRed = trav;
[63d4f07]509                    fMore = true;
[cb3d1e2]510
[564f471]511                    remove_stn_from_list(&stnlist, stn);
512                    remove_stn_from_list(&stnlist, stn2);
513                    remove_stn_from_list(&stnlist, stn3);
[a420b49]514                    stn4->leg[dirn4] = legAZ;
515                    stn5->leg[dirn5] = legBZ;
516                    stn6->leg[dirn6] = legCZ;
517                 }
[cb3d1e2]518
[a420b49]519            }
520            nodeltastar:;
521         }
522      }
[d1b1380]523
[a420b49]524   }
[d1b1380]525}
526
[5853657]527extern void
[a420b49]528replace_subnets(void)
529{
[4d695ce3]530   stackRed *ptrOld;
[eb18f4d]531   node *stn2, *stn3, *stn4;
532   int dirn2, dirn3, dirn4;
[4d695ce3]533
534   /* help to catch bad accesses */
[eb18f4d]535   stn2 = stn3 = stn4 = NULL;
536   dirn2 = dirn3 = dirn4 = 0;
[4d695ce3]537
[a420b49]538   out_current_action(msg(/*Calculating network*/130));
[4d695ce3]539
540   while (ptrRed != NULL) {
[a420b49]541      /*  printf("replace_subnets() type %d\n", ptrRed->type);*/
[032ed06]542
543#if PRINT_NETBITS
544      printf("replace_subnets\n");
545      if (IS_NOOSE(ptrRed)) printf("isnoose\n");
546      if (IS_PARALLEL(ptrRed)) printf("isparallel\n");
547      if (IS_DELTASTAR(ptrRed)) printf("isdelta*\n");
548#endif
549
[4d695ce3]550      if (!IS_DELTASTAR(ptrRed)) {
[eb18f4d]551         linkfor *leg;
[421b7d2]552         leg = ptrRed->join1; leg = reverse_leg(leg);
553         stn3 = leg->l.to; dirn3 = reverse_leg_dirn(leg);
554         leg = ptrRed->join2; leg = reverse_leg(leg);
555         stn4 = leg->l.to; dirn4 = reverse_leg_dirn(leg);
[cb3d1e2]556
[6a29ae1]557         if (!fixed(stn3) || !fixed(stn4)) {
558             SVX_ASSERT(!fixed(stn3) && !fixed(stn4));
559             goto skip;
560         }
[4c07c51]561         SVX_ASSERT(data_here(stn3->leg[dirn3]));
[4d695ce3]562      }
[d1b1380]563
[e530a96]564      if (IS_NOOSE(ptrRed)) {
[421b7d2]565         /* noose (hanging-loop) */
[eb18f4d]566         node *stn;
[421b7d2]567         delta e;
568         linkfor *leg;
[e6cfe52]569         int zero;
[43d6ecfe]570
[e6cfe52]571         leg = stn3->leg[dirn3];
572         stn2 = ptrRed->join1->l.to;
573         dirn2 = reverse_leg_dirn(ptrRed->join1);
574
575         zero = fZeros(&leg->v);
576         if (!zero) {
577            delta tmp;
578            subdd(&e, &POSD(stn4), &POSD(stn3));
579            subdd(&tmp, &e, &leg->d);
580            divds(&e, &tmp, &leg->v);
581         }
582         if (data_here(ptrRed->join1)) {
583            adddd(&POSD(stn2), &POSD(stn3), &ptrRed->join1->d);
584            if (!zero) {
[eb18f4d]585               delta tmp;
[e6cfe52]586               mulsd(&tmp, &ptrRed->join1->v, &e);
587               adddd(&POSD(stn2), &POSD(stn2), &tmp);
588            }
589         } else {
590            subdd(&POSD(stn2), &POSD(stn3), &stn2->leg[dirn2]->d);
591            if (!zero) {
592               delta tmp;
593               mulsd(&tmp, &stn2->leg[dirn2]->v, &e);
594               adddd(&POSD(stn2), &POSD(stn2), &tmp);
595            }
596         }
597         fix(stn2);
598         dirn2 = (dirn2 + 2) % 3; /* point back at stn again */
599         stn = stn2->leg[dirn2]->l.to;
[d1b1380]600#if 0
[e6cfe52]601         printf("Replacing noose with stn...stn4 = \n");
602         print_prefix(stn->name); putnl();
603         print_prefix(stn2->name); putnl();
604         print_prefix(stn3->name); putnl();
605         print_prefix(stn4->name); putnl();
[d1b1380]606#endif
[e6cfe52]607         if (data_here(stn2->leg[dirn2]))
608            adddd(&POSD(stn), &POSD(stn2), &stn2->leg[dirn2]->d);
609         else
610            subdd(&POSD(stn), &POSD(stn2), &reverse_leg(stn2->leg[dirn2])->d);
611
612         /* the "rope" of the noose is a new articulation */
613         stn2->leg[dirn2]->l.reverse |= FLAG_ARTICULATION;
614         reverse_leg(stn2->leg[dirn2])->l.reverse |= FLAG_ARTICULATION;
615
616         fix(stn);
[402c753]617
[ec8a439]618         add_stn_to_list(&stnlist, stn);
619         add_stn_to_list(&stnlist, stn2);
[d1b1380]620
[421b7d2]621         osfree(stn3->leg[dirn3]);
622         stn3->leg[dirn3] = ptrRed->join1;
623         osfree(stn4->leg[dirn4]);
624         stn4->leg[dirn4] = ptrRed->join2;
[4d695ce3]625      } else if (IS_PARALLEL(ptrRed)) {
[421b7d2]626         /* parallel legs */
[eb18f4d]627         node *stn;
[421b7d2]628         delta e, e2;
629         linkfor *leg;
[e6cfe52]630         int dirn;
[421b7d2]631
[ec8a439]632         stn = ptrRed->join1->l.to;
[fb2e93c]633         stn2 = ptrRed->join2->l.to;
[402c753]634
[e6cfe52]635         dirn = reverse_leg_dirn(ptrRed->join1);
636         dirn2 = reverse_leg_dirn(ptrRed->join2);
637
638         leg = stn3->leg[dirn3];
639
640         if (leg->l.reverse & FLAG_ARTICULATION) {
641            ptrRed->join1->l.reverse |= FLAG_ARTICULATION;
642            stn->leg[dirn]->l.reverse |= FLAG_ARTICULATION;
643            ptrRed->join2->l.reverse |= FLAG_ARTICULATION;
644            stn2->leg[dirn2]->l.reverse |= FLAG_ARTICULATION;
645         }
646
647         if (fZeros(&leg->v))
648            e[0] = e[1] = e[2] = 0.0;
649         else {
650            delta tmp;
651            subdd(&e, &POSD(stn4), &POSD(stn3));
652            subdd(&tmp, &e, &leg->d);
653            divds(&e, &tmp, &leg->v);
654         }
655
656         if (data_here(ptrRed->join1)) {
657            leg = ptrRed->join1;
658            adddd(&POSD(stn), &POSD(stn3), &leg->d);
659         } else {
660            leg = stn->leg[dirn];
661            subdd(&POSD(stn), &POSD(stn3), &leg->d);
662         }
663         mulsd(&e2, &leg->v, &e);
664         adddd(&POSD(stn), &POSD(stn), &e2);
665
666         if (data_here(ptrRed->join2)) {
667            leg = ptrRed->join2;
668            adddd(&POSD(stn2), &POSD(stn4), &leg->d);
669         } else {
670            leg = stn2->leg[dirn2];
671            subdd(&POSD(stn2), &POSD(stn4), &leg->d);
672         }
673         mulsd(&e2, &leg->v, &e);
674         subdd(&POSD(stn2), &POSD(stn2), &e2);
675         fix(stn);
676         fix(stn2);
[d1b1380]677#if 0
[e6cfe52]678         printf("Replacing parallel with stn...stn4 = \n");
679         print_prefix(stn->name); putnl();
680         print_prefix(stn2->name); putnl();
681         print_prefix(stn3->name); putnl();
682         print_prefix(stn4->name); putnl();
[d1b1380]683#endif
[e6cfe52]684
[ec8a439]685         add_stn_to_list(&stnlist, stn);
686         add_stn_to_list(&stnlist, stn2);
[cb3d1e2]687
[421b7d2]688         osfree(stn3->leg[dirn3]);
[a420b49]689         stn3->leg[dirn3] = ptrRed->join1;
[421b7d2]690         osfree(stn4->leg[dirn4]);
[a420b49]691         stn4->leg[dirn4] = ptrRed->join2;
[4d695ce3]692      } else if (IS_DELTASTAR(ptrRed)) {
[421b7d2]693         node *stnZ;
694         node *stn[3];
695         int dirn[3];
696         linkfor *legs[3];
697         int i;
698         linkfor *leg;
699
700         legs[0] = ptrRed->join1;
701         legs[1] = ptrRed->join2;
702         legs[2] = ptrRed->join3;
703
704         /* work out ends as we don't bother stacking them */
705         leg = reverse_leg(legs[0]);
706         stn[0] = leg->l.to;
707         dirn[0] = reverse_leg_dirn(leg);
708         stnZ = stn[0]->leg[dirn[0]]->l.to;
[4c07c51]709         SVX_ASSERT(fixed(stnZ));
[6a29ae1]710         if (!fixed(stnZ)) {
711            SVX_ASSERT(!fixed(stn[0]));
712            goto skip;
713         }
[421b7d2]714         stn[1] = stnZ->leg[1]->l.to;
[a420b49]715         dirn[1] = reverse_leg_dirn(stnZ->leg[1]);
[421b7d2]716         stn[2] = stnZ->leg[2]->l.to;
[a420b49]717         dirn[2] = reverse_leg_dirn(stnZ->leg[2]);
[564f471]718         /*print_prefix(stnZ->name);printf(" %p\n",(void*)stnZ);*/
[4d695ce3]719
[e6cfe52]720         for (i = 0; i < 3; i++) {
[4c07c51]721            SVX_ASSERT2(fixed(stn[i]), "stn not fixed for D*");
[1e431a4e]722
[e6cfe52]723            leg = stn[i]->leg[dirn[i]];
[1e431a4e]724
[4c07c51]725            SVX_ASSERT2(data_here(leg), "data not on leg for D*");
726            SVX_ASSERT2(leg->l.to == stnZ, "bad sub-network for D*");
[1e431a4e]727
[e6cfe52]728            stn2 = legs[i]->l.to;
[1e431a4e]729
730            if (data_here(legs[i])) {
731               adddd(&POSD(stn2), &POSD(stn[i]), &legs[i]->d);
732            } else {
733               subdd(&POSD(stn2), &POSD(stn[i]), &reverse_leg(legs[i])->d);
734            }
735
[e6cfe52]736            if (!fZeros(&leg->v)) {
737               delta e, tmp;
738               subdd(&e, &POSD(stnZ), &POSD(stn[i]));
739               subdd(&e, &e, &leg->d);
740               divds(&tmp, &e, &leg->v);
[1e431a4e]741               if (data_here(legs[i])) {
742                  mulsd(&e, &legs[i]->v, &tmp);
743               } else {
744                  mulsd(&e, &reverse_leg(legs[i])->v, &tmp);
745               }
[e6cfe52]746               adddd(&POSD(stn2), &POSD(stn2), &e);
747            }
748            fix(stn2);
749            add_stn_to_list(&stnlist, stn2);
750            osfree(leg);
751            stn[i]->leg[dirn[i]] = legs[i];
752            /* transfer the articulation status of the radial legs */
753            if (stnZ->leg[i]->l.reverse & FLAG_ARTICULATION) {
754               legs[i]->l.reverse |= FLAG_ARTICULATION;
755               reverse_leg(legs[i])->l.reverse |= FLAG_ARTICULATION;
756            }
757            osfree(stnZ->leg[i]);
758            stnZ->leg[i] = NULL;
759         }
760/*printf("---%f %f %f\n",POS(stnZ, 0), POS(stnZ, 1), POS(stnZ, 2));*/
[dbb4e19]761         remove_stn_from_list(&stnlist, stnZ);
762         osfree(stnZ->name);
763         osfree(stnZ);
[4d695ce3]764      } else {
[421b7d2]765         BUG("ptrRed has unknown type");
[4d695ce3]766      }
[d1b1380]767
[6a29ae1]768skip:
[a420b49]769      ptrOld = ptrRed;
770      ptrRed = ptrRed->next;
[4d695ce3]771      osfree(ptrOld);
772   }
[d1b1380]773}
Note: See TracBrowser for help on using the repository browser.