source: git/src/validate.c @ 66be513

stereo-2025
Last change on this file since 66be513 was bf9faf6, checked in by Olly Betts <olly@…>, 8 months ago

Fix component counting bugs

The component count was wrong in some cases, and we calculate the number
of loops using this component count, so the loop count would be wrong by
the same amount in these cases.

  • Property mode set to 100644
File size: 7.3 KB
RevLine 
[421b7d2]1/* validate.c
[d1b1380]2 *
3 *   Checks that SURVEX's data structures are valid and consistent
4 *
5 *   NB The checks currently done aren't very comprehensive - more will be
6 *    added if bugs require them
7 *
[bf9faf6]8 *   Copyright (C) 1993,1994,1996,2000,2001,2024 Olly Betts
[846746e]9 *
[89231c4]10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
[846746e]14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[89231c4]17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
[846746e]19 *
[89231c4]20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
[ecbc6c18]22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[d1b1380]23 */
24
[4c83f84]25#include <config.h>
[d1b1380]26
[a420b49]27#include "cavern.h"
[c082b69]28#include "filename.h"
29#include "message.h"
[d1b1380]30#include "netbits.h"
31#include "validate.h"
32
33/* maximum absolute value allowed for a coordinate of a fixed station */
[577d6c1]34#define MAX_POS 10000000.0
[d1b1380]35
[a420b49]36static bool validate_prefix_tree(void);
37static bool validate_prefix_subtree(prefix *pfx);
[d1b1380]38
[a420b49]39static bool validate_station_list(void);
[d1b1380]40
[a420b49]41#undef validate
42extern bool
43validate(void)
44{
[63d4f07]45   bool fOk = true;
46   if (!validate_prefix_tree()) fOk = false;
47   if (!validate_station_list()) fOk = false;
[a420b49]48   if (fOk) puts("*** Data structures passed consistency checks");
[6d3f931]49   else puts("*** Data structures FAILED consistency checks");
[a420b49]50   return fOk;
51}
[d1b1380]52
[a420b49]53static bool
54validate_prefix_tree(void)
55{
[63d4f07]56   bool fOk = true;
[a420b49]57   if (root->up != NULL) {
58      printf("*** root->up == %p\n", root->up);
[63d4f07]59      fOk = false;
[a420b49]60   }
61   if (root->right != NULL) {
62      printf("*** root->right == %p\n", root->right);
[63d4f07]63      fOk = false;
[a420b49]64   }
65   if (root->stn != NULL) {
66      printf("*** root->stn == %p\n", root->stn);
[63d4f07]67      fOk = false;
[a420b49]68   }
69   if (root->pos != NULL) {
70      printf("*** root->pos == %p\n", root->pos);
[63d4f07]71      fOk = false;
[a420b49]72   }
73   fOk &= validate_prefix_subtree(root);
74   return fOk;
75}
[d1b1380]76
[a420b49]77static bool
78validate_prefix_subtree(prefix *pfx)
79{
[63d4f07]80   bool fOk = true;
[a420b49]81   prefix *pfx2;
82   pfx2 = pfx->down;
83   /* this happens now, as nodes are freed after solving */
[d1b1380]84#if 0
[a420b49]85   if (pfx2 == NULL) {
86      if (pfx->stn == NULL) {
87         printf("*** Leaf prefix '");
88         print_prefix(pfx);
89         printf("' has no station attached\n");
[63d4f07]90         fOk = false;
[a420b49]91      }
92      return fOk;
[d1b1380]93   }
94#endif
95
[a420b49]96   while (pfx2 != NULL) {
97      if (pfx2->stn != NULL && pfx2->stn->name != pfx2) {
98         printf("*** Prefix '");
99         print_prefix(pfx2);
100         printf("' ->stn->name is '");
101         print_prefix(pfx2->stn->name);
102         printf("'\n");
[63d4f07]103         fOk = false;
[a420b49]104      }
105      if (pfx2->up != pfx) {
106         printf("*** Prefix '");
107         print_prefix(pfx2);
108         printf("' ->up is '");
109         print_prefix(pfx);
110         printf("'\n");
[63d4f07]111         fOk = false;
[a420b49]112      }
113      fOk &= validate_prefix_subtree(pfx2);
114      pfx2 = pfx2->right;
[d1b1380]115   }
[a420b49]116   return fOk;
117}
118
119static bool
120validate_station_list(void)
121{
[63d4f07]122   bool fOk = true;
[bf9faf6]123   node *stn2;
[a420b49]124   int d, d2;
125
[4c07c51]126   SVX_ASSERT(!stnlist || !stnlist->prev);
[6d3f931]127   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]128   for (int fixed = 0; fixed < 2; ++fixed) {
129      for (node *stn = fixed ? fixedlist : stnlist; stn; stn = stn->next) {
130         if (fixed(stn) != fixed) {
131             printf("*** Station '");
132             print_prefix(stn->name);
133             printf("' is %sfixed but on %sfixed list\n",
134                    fixed ? "un" : "", fixed ? "" : "un");
135             fOk = false;
136         }
137
138         bool fGap = false;
[095ef764]139#if 0
[bf9faf6]140         printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
[095ef764]141#endif
[bf9faf6]142         SVX_ASSERT(stn->prev == NULL || stn->prev->next == stn);
143         SVX_ASSERT(stn->next == NULL || stn->next->prev == stn);
144         for (d = 0; d <= 2; d++) {
145            if (!stn->leg[d]) {
146               fGap = true;
147            } else {
148               if (fGap) {
[a420b49]149                  printf("*** Station '");
150                  print_prefix(stn->name);
[bf9faf6]151                  printf("', leg %d is used, but an earlier leg isn't\n", d);
[63d4f07]152                  fOk = false;
[a420b49]153               }
[bf9faf6]154               stn2 = stn->leg[d]->l.to;
155               SVX_ASSERT(stn2);
156               d2 = reverse_leg_dirn(stn->leg[d]);
157               if (stn2->leg[d2] == NULL) {
158                  /* fine iff stn is at the disconnected end of a fragment */
159                  node *s;
160                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
161                  for (s = stnlist; s; s = s->next) if (s == stn) break;
162                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
163                  if (s) {
164                     printf("*** Station '");
165                     print_prefix(stn->name);
166                     printf("', leg %d doesn't reciprocate from station '", d);
167                     print_prefix(stn2->name);
168                     printf("'\n");
169                     fOk = false;
170                  }
171               } else if (stn2->leg[d2]->l.to == NULL) {
[a420b49]172                  printf("*** Station '");
173                  print_prefix(stn2->name);
[bf9faf6]174                  printf("' [%p], leg %d points to NULL\n", stn2, d2);
[63d4f07]175                  fOk = false;
[bf9faf6]176               } else if (stn2->leg[d2]->l.to!=stn) {
177                  /* fine iff stn is at the disconnected end of a fragment */
178                  node *s;
179                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
180                  for (s = stnlist; s; s = s->next) if (s == stn) break;
181                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
182                  if (s) {
[a420b49]183                     printf("*** Station '");
184                     print_prefix(stn->name);
[bf9faf6]185                     printf("' [%p], leg %d reciprocates via station '", stn, d);
186                     print_prefix(stn2->name);
187                     printf("' to station '");
188                     print_prefix(stn2->leg[d2]->l.to->name);
189                     printf("'\n");
[63d4f07]190                     fOk = false;
[a420b49]191                  }
[bf9faf6]192               } else if ((data_here(stn->leg[d]) != 0) ^
193                          (data_here(stn2->leg[d2]) == 0)) {
194                  printf("*** Station '");
195                  print_prefix(stn->name);
196                  printf("' [%p], leg %d reciprocates via station '", stn, d);
197                  print_prefix(stn2->name);
198                  if (data_here(stn->leg[d]))
199                     printf("' - data on both legs\n");
200                  else
201                     printf("' - data on neither leg\n");
202                  fOk = false;
203               }
204               if (data_here(stn->leg[d])) {
205                  int i;
206                  for (i = 0; i < 3; i++)
207                     if (fabs(stn->leg[d]->d[i]) > MAX_POS) {
208                        printf("*** Station '");
209                        print_prefix(stn->name);
210                        printf("', leg %d, d[%d] = %g\n",
211                               d, i, (double)(stn->leg[d]->d[i]));
212                        fOk = false;
213                     }
214               }
[a420b49]215            }
216
[bf9faf6]217            if (fixed(stn)) {
218               if (fabs(POS(stn, 0)) > MAX_POS ||
219                   fabs(POS(stn, 1)) > MAX_POS ||
220                   fabs(POS(stn, 2)) > MAX_POS) {
221                  printf("*** Station '");
222                  print_prefix(stn->name);
223                  printf("' fixed at coords (%f,%f,%f)\n",
224                         POS(stn, 0), POS(stn, 1), POS(stn, 2) );
225                  fOk = false;
226               }
[a420b49]227            }
228         }
[d1b1380]229      }
[a420b49]230   }
231   return fOk;
232}
233
234#undef dump_node
235extern void
236dump_node(node *stn)
237{
238   int d;
239   if (stn->name)
[d1b1380]240      print_prefix(stn->name);
[a420b49]241   else
242      printf("<null>");
[d1b1380]243
[564f471]244   printf(" stn [%p] name (%p) colour %ld %sfixed\n",
245          stn, stn->name, stn->colour, fixed(stn) ? "" : "un");
[d1b1380]246
[a420b49]247   for (d = 0; d <= 2; d++) {
[05312022]248      if (stn->leg[d]) {
[6d3f931]249         printf("  leg %d -> stn [%p] rev %d ", d, stn->leg[d]->l.to,
250                reverse_leg_dirn(stn->leg[d]));
[05312022]251         print_prefix(stn->leg[d]->l.to->name);
[5b68ae1]252         putnl();
[05312022]253      }
[d1b1380]254   }
[a420b49]255}
[d1b1380]256
[b6e9e7e]257/* This doesn't cover removed stations - might be nice to have
258 * dump_entire_network() which iterates prefix tree */
[cb3d1e2]259#undef dump_network
[a420b49]260extern void
261dump_network(void)
262{
263   node *stn;
[6d3f931]264   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]265   for (stn = fixedlist; stn; stn = stn->next) dump_node(stn);
[6d3f931]266   for (stn = stnlist; stn; stn = stn->next) dump_node(stn);
[a420b49]267}
Note: See TracBrowser for help on using the repository browser.