Namelist.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
46 //------------------------------------------------------------------------------------
47 // system includes
48 #include <string>
49 #include <vector>
50 #include <algorithm>
51 #include <fstream> // for copyfmt
52 #include <ostream>
53 // GNSSTk
54 #include "Exception.hpp"
55 #include "StringUtils.hpp"
56 #include "Namelist.hpp"
57 
58 using namespace std;
59 
60 namespace gnsstk
61 {
62 
63  using namespace StringUtils;
64 
65  //---------------------------------------------------------------------------------
66  // constructor given dimension - creates default labels
67  Namelist::Namelist(const unsigned int& n)
68  {
69  try
70  {
71  if (n == 0)
72  return;
73  string name;
74  for (unsigned int i = 0; i < n; i++)
75  {
76  ostringstream oss;
77  oss << "NAME" << setw(3) << setfill('0') << i;
78  name = oss.str();
79  labels.push_back(name);
80  }
81  }
82  catch (Exception& e) {
83  GNSSTK_RETHROW(e);
84  }
85  }
86 
87  // explicit constructor - only a unique subset of names will be included.
88  Namelist::Namelist(const std::vector<std::string>& names)
89  {
90  try
91  {
92  for (unsigned int i = 0; i < names.size(); i++)
93  {
94  bool unique = true;
95  for (unsigned int j = i + 1; j < names.size(); j++)
96  {
97  if (names[i] == names[j])
98  {
99  unique = false;
100  break;
101  }
102  }
103  if (unique)
104  labels.push_back(names[i]);
105  }
106  }
107  catch (Exception& e)
108  {
109  GNSSTK_RETHROW(e);
110  }
111  }
112 
113  // add a name to the Namelist; throw if the name is not unique.
114  Namelist& Namelist::operator+=(const std::string& name)
115  {
116  try
117  {
118  if (contains(name))
119  {
120  GNSSTK_THROW(Exception("Name is not unique: " + name));
121  }
122  labels.push_back(name);
123  return *this;
124  }
125  catch (Exception& e)
126  {
127  GNSSTK_RETHROW(e);
128  }
129  }
130 
131  // remove a name from the Namelist; does nothing if the name is not found.
132  Namelist& Namelist::operator-=(const std::string& name)
133  {
134  try
135  {
136  vector<string>::iterator it;
137  it = find(labels.begin(), labels.end(), name);
138  if (it != labels.end())
139  labels.erase(it);
140  return *this;
141  }
142  catch (Exception& e)
143  {
144  GNSSTK_RETHROW(e);
145  }
146  }
147 
148  // swap two elements, as given by their indexes; no effect if either index
149  // is out of range.
150  void Namelist::swap(const unsigned int& i, const unsigned int& j)
151  {
152  try
153  {
154  if (i == j)
155  {
156  return;
157  }
158  if (i >= labels.size() || j >= labels.size())
159  {
160  return;
161  }
162  string str = labels[i];
163  labels[i] = labels[j];
164  labels[j] = str;
165  }
166  catch (Exception& e)
167  {
168  GNSSTK_RETHROW(e);
169  }
170  }
171 
172  // reorder the list by sorting
173  void Namelist::sort()
174  {
175  try
176  {
177  // compiler tries Namelist::sort() first...
178  std::sort(labels.begin(), labels.end());
179  }
180  catch (Exception& e)
181  {
182  GNSSTK_RETHROW(e);
183  }
184  }
185 
186  // resize the list by either truncation or adding default names.
187  void Namelist::resize(unsigned int n)
188  {
189  try
190  {
191  if (n == labels.size())
192  {
193  return;
194  }
195  int N = labels.size();
196  while (labels.size() < n)
197  {
198  string s;
199  do
200  {
201  ostringstream oss;
202  oss << "NAME" << setw(3) << setfill('0') << N;
203  s = oss.str();
204  N++;
205  } while (contains(s));
206  labels.push_back(s);
207  }
208  while (labels.size() > n)
209  {
210  labels.pop_back();
211  }
212  }
213  catch (Exception& e)
214  {
215  GNSSTK_RETHROW(e);
216  }
217  }
218 
219  // randomize the list
220  void Namelist::randomize(long seed)
221  {
222  try
223  {
224  if (labels.size() <= 1)
225  {
226  return;
227  }
228 
229  // random_shuffle(labels.begin(), labels.end());
230  if (seed)
231  {
232  std::srand(seed);
233  }
234  for (int i = labels.size() - 1; i > 0; --i)
235  {
236  using std::swap;
237  swap(labels[i], labels[std::rand() % (i + 1)]);
238  }
239  }
240  catch (Exception& e)
241  {
242  GNSSTK_RETHROW(e);
243  }
244  }
245 
246  // is the Namelist valid? checks for repeated names
247  bool Namelist::valid() const
248  {
249  try
250  {
251  for (unsigned int i = 0; i < labels.size(); i++)
252  for (unsigned int j = i + 1; j < labels.size(); j++)
253  if (labels[i] == labels[j])
254  return false;
255  return true;
256  }
257  catch (Exception& e)
258  {
259  GNSSTK_RETHROW(e);
260  }
261  }
262 
263  // does the Namelist contain the input name?
264  bool Namelist::contains(const std::string& name) const
265  {
266  try
267  {
268  for (unsigned int i = 0; i < labels.size(); i++)
269  {
270  if (labels[i] == name)
271  return true;
272  }
273  return false;
274  }
275  catch (Exception& e)
276  {
277  GNSSTK_RETHROW(e);
278  }
279  }
280 
281  // are two Namelists identical, ignoring a permutation?
282  bool operator==(const Namelist& N1, const Namelist& N2)
283  {
284  try
285  {
286  if (N1.size() != N2.size())
287  {
288  return false;
289  }
290  if (N1.size() == 0)
291  {
292  return true;
293  }
294  for (unsigned int i = 0; i < N1.size(); i++)
295  {
296  unsigned int match = 0;
297  for (unsigned int j = 0; j < N2.size(); j++)
298  {
299  if (N1.labels[i] == N2.labels[j])
300  {
301  match++;
302  }
303  }
304  if (match != 1)
305  {
306  return false; // if > 1, N2 is invalid
307  }
308  }
309  return true;
310  }
311  catch (Exception& e)
312  {
313  GNSSTK_RETHROW(e);
314  }
315  }
316 
317  // are two Namelists different, ignoring a permutation?
318  bool operator!=(const Namelist& N1, const Namelist& N2)
319  {
320  try
321  {
322  return !(N1 == N2);
323  }
324  catch (Exception& e)
325  {
326  GNSSTK_RETHROW(e);
327  }
328  }
329 
330  // are two Namelists exactly identical, even considering permutations?
331  bool identical(const Namelist& N1, const Namelist& N2)
332  {
333  try
334  {
335  if (N1.size() != N2.size())
336  {
337  return false;
338  }
339  if (N1.size() == 0)
340  {
341  return true;
342  }
343  for (unsigned int i = 0; i < N1.size(); i++)
344  {
345  if (N1.labels[i] != N2.labels[i])
346  return false;
347  }
348  return true;
349  }
350  catch (Exception& e)
351  {
352  GNSSTK_RETHROW(e);
353  }
354  }
355 
356  // construct the subset Namelist which is common to the two input (AND)
357  Namelist operator&(const Namelist& N1, const Namelist& N2)
358  {
359  try
360  {
361  Namelist N(N1);
362  N &= N2;
363  return N;
364  }
365  catch (Exception& e)
366  {
367  GNSSTK_RETHROW(e);
368  }
369  }
370 
371  // merge two Namelists, i.e. construct a non-redundant combination (OR)
372  Namelist operator|(const Namelist& N1, const Namelist& N2)
373  {
374  try
375  {
376  Namelist N(N1);
377  N |= N2;
378  return N;
379  }
380  catch (Exception& e)
381  {
382  GNSSTK_RETHROW(e);
383  }
384  }
385 
386  // construct the subset Namelist which is NOT common to two others (XOR)
387  Namelist operator^(const Namelist& N1, const Namelist& N2)
388  {
389  try
390  {
391  Namelist N(N1);
392  N ^= N2;
393  return N;
394  }
395  catch (Exception& e)
396  {
397  GNSSTK_RETHROW(e);
398  }
399  }
400 
401  // replace this with (this & input) (AND - common to both)
402  Namelist& Namelist::operator&=(const Namelist& N)
403  {
404  try
405  {
406  Namelist NAND;
407  for (unsigned int i = 0; i < N.labels.size(); i++)
408  {
409  if (contains(N.labels[i]))
410  {
411  NAND += N.labels[i];
412  }
413  }
414  *this = NAND;
415  return *this;
416  }
417  catch (Exception& e)
418  {
419  GNSSTK_RETHROW(e);
420  }
421  }
422 
423  // replace this with (this | input) (OR - merge - superset)
424  // NB new elements must be added at the end (for class SRI).
425  Namelist& Namelist::operator|=(const Namelist& N)
426  {
427  try
428  {
429  Namelist NOR(*this);
430  for (unsigned int i = 0; i < N.labels.size(); i++)
431  {
432  if (!(contains(N.labels[i])))
433  {
434  NOR += N.labels[i];
435  }
436  }
437  *this = NOR;
438  return *this;
439  }
440  catch (Exception& e)
441  {
442  GNSSTK_RETHROW(e);
443  }
444  }
445 
446  // replace this with (this ^ input) (XOR - not common)
447  Namelist& Namelist::operator^=(const Namelist& N)
448  {
449  try
450  {
451  unsigned int i;
452  Namelist NXOR;
453  for (i = 0; i < labels.size(); i++)
454  {
455  if (!(N.contains(labels[i])))
456  {
457  NXOR += labels[i];
458  }
459  }
460  for (i = 0; i < N.labels.size(); i++)
461  {
462  if (!(contains(N.labels[i])))
463  {
464  NXOR += N.labels[i];
465  }
466  }
467  *this = NXOR;
468  return *this;
469  }
470  catch (Exception& e)
471  {
472  GNSSTK_RETHROW(e);
473  }
474  }
475 
476  /* access to a specific name, given its index; may be used as lvalue.
477  string& Namelist::operator[](const unsigned int in)
478  {
479  if(in >= labels.size()) throw ...
480  return labels[in];
481  } */
482 
483  /* access to a specific name, given its index.
484  returns 'out-of-range' if the index is out of range. */
485  std::string Namelist::getName(const unsigned int in) const
486  {
487  try
488  {
489  if (in >= labels.size())
490  {
491  return string("out-of-range");
492  }
493  return labels[in];
494  }
495  catch (Exception& e)
496  {
497  GNSSTK_RETHROW(e);
498  }
499  }
500 
501  /* assign a specific name, given its index;
502  no effect if the index is out of range or the name is not unique.
503  return true if successful*/
504  bool Namelist::setName(const unsigned int in, const std::string& name)
505  {
506  try
507  {
508  if (in >= labels.size())
509  {
510  return false;
511  }
512  if (labels[in] == name)
513  {
514  return true; // NB b/c contains(name) would be true..
515  }
516  if (contains(name))
517  {
518  return false;
519  }
520  labels[in] = name;
521  return true;
522  }
523  catch (Exception& e)
524  {
525  GNSSTK_RETHROW(e);
526  }
527  }
528 
529  // return the index of the name in the list that matches the input, -1 if not found.
530  int Namelist::index(const std::string& name) const
531  {
532  try
533  {
534  for (unsigned int i = 0; i < labels.size(); i++)
535  {
536  if (labels[i] == name)
537  {
538  return i;
539  }
540  }
541  return -1;
542  }
543  catch (Exception& e)
544  {
545  GNSSTK_RETHROW(e);
546  }
547  }
548 
549  // output operator
550  ostream& operator<<(ostream& os, const Namelist& N)
551  {
552  try
553  {
554  if (N.labels.size() > 0)
555  {
556  for (unsigned int i = 0; i < N.labels.size(); i++)
557  {
558  os << " / " << N.labels[i];
559  }
560  os << " / ";
561  }
562  return os;
563  }
564  catch (Exception& e)
565  {
566  GNSSTK_RETHROW(e);
567  }
568  }
569 
570  ostream& operator<<(ostream& os, const LabeledVector& LV)
571  {
572  try
573  {
574  size_t i;
575  string s;
576  // ofstream savefmt;
577  // savefmt.copyfmt(os);
578  // int wid=os.width(),prec=os.precision();
579 
580  // print message or blanks
581  os << LV.tag << " ";
582  if (LV.msg.size() > 0)
583  s = LV.msg;
584  else
585  s = rightJustify(string(""), LV.msg.size()); // LV.wid);
586  os << s << " ";
587 
588  // print each label
589  for (i = 0; i < LV.NL.size(); i++)
590  {
591  if (int(LV.NL.getName(i).size()) > LV.wid)
592  {
593  s = leftJustify(LV.NL.getName(i), LV.wid);
594  }
595  else
596  {
597  s = rightJustify(LV.NL.getName(i), LV.wid);
598  }
599  os << s;
600  if (i - LV.NL.size() + 1)
601  {
602  os << " ";
603  }
604  }
605  os << endl; // next line
606 
607  // print same space as with labels
608  s = rightJustify(string(""), LV.msg.size() + 2); // LV.wid);
609  os << LV.tag << " " << s << " ";
610  if (LV.form == 1)
611  {
612  os << fixed;
613  }
614  if (LV.form == 2)
615  {
616  os << scientific;
617  }
618  for (i = 0; i < LV.V.size(); i++)
619  {
620  // os.copyfmt(savefmt);
621  // os << LV.V(i);
622  os << setw(LV.wid) << setprecision(LV.prec) << LV.V(i);
623  if (i - LV.V.size() + 1)
624  {
625  os << " ";
626  }
627  }
628 
629  return os;
630  }
631  catch (Exception& e)
632  {
633  GNSSTK_RETHROW(e);
634  }
635  }
636 
637  std::ostream& operator<<(std::ostream& os, const LabeledMatrix& LM)
638  {
639  try
640  {
641  int nspace;
642  size_t i, j, jlast, n;
643  string s;
644  const Namelist *pNLcol = &LM.NLcols;
645  const Namelist *pNLrow = &LM.NLrows;
646 
647  // first make sure we have both namelists
648  if (LM.NLrows.size() == 0 && LM.NLcols.size() == 0)
649  {
650  os << " Error -- Namelists in LabeledMatrix are empty! ";
651  return os;
652  }
653  if (LM.NLrows.size() == 0)
654  {
655  pNLrow = pNLcol;
656  }
657  if (LM.NLcols.size() == 0)
658  {
659  pNLcol = pNLrow;
660  }
661 
662  // on column labels line
663  os << setw(0);
664  if (LM.rc == 0)
665  { // only if printing both column and row labels
666  os << LM.tag << " "; // tag
667  if (LM.msg.size() > 0) // msg
668  {
669  s = LM.msg + " ";
670  }
671  else
672  {
673  s = rightJustify(string(" "), LM.wid);
674  }
675  os << s << " ";
676  if (int(LM.msg.size()) > 0 && int(LM.msg.size()) < LM.wid)
677  {
678  os << rightJustify(string(" "), LM.wid - LM.msg.size()); // space
679  }
680  }
681  // print column labels
682  if (LM.rc != 1)
683  { // but not if 'rows only'
684  n = (LM.M.cols() < pNLcol->size() ? LM.M.cols() : pNLcol->size());
685  if (LM.rc == 2)
686  {
687  os << " ";
688  }
689  for (i = 0; i < n; i++)
690  {
691  if (int(pNLcol->getName(i).size()) > LM.wid)
692  {
693  s = leftJustify(pNLcol->getName(i), LM.wid);
694  }
695  else
696  {
697  s = rightJustify(pNLcol->getName(i), LM.wid);
698  }
699  os << s; // label
700  if (i < n - 1)
701  os << " ";
702  }
703  os << endl;
704  }
705 
706  if (LM.form == 1)
707  {
708  os << fixed;
709  }
710  if (LM.form == 2)
711  {
712  os << scientific;
713  }
714  if (int(LM.msg.size()) > LM.wid)
715  {
716  nspace = LM.msg.size() - LM.wid + 2;
717  }
718  else if (int(LM.msg.size()))
719  {
720  nspace = 2;
721  }
722  else
723  {
724  nspace = 0;
725  }
726 
727  // print one row per line
728  for (i = 0; i < LM.M.rows(); i++)
729  {
730  os << LM.tag << " "; // tag
731  if (nspace)
732  {
733  os << rightJustify(string(" "), nspace); // space
734  }
735  // print row labels
736  if (LM.rc != 2)
737  { // but not if 'columns only'
738  if (int(pNLrow->getName(i).size()) > LM.wid)
739  {
740  s = leftJustify(pNLrow->getName(i), LM.wid);
741  }
742  else
743  {
744  s = rightJustify(pNLrow->getName(i), LM.wid);
745  }
746  os << s << " "; // label
747  }
748  // finally, print the data
749  jlast = (LM.sym ? i + 1 : LM.M.cols());
750  for (j = 0; j < jlast; j++)
751  {
752  // clean print
753  if (LM.cln && ::fabs(LM.M(i, j)) < ::pow(10.0, -LM.prec))
754  {
755  os << rightJustify("0", LM.wid);
756  }
757  else
758  {
759  os << setw(LM.wid) << setprecision(LM.prec) << LM.M(i, j);
760  }
761  if (j < jlast - 1)
762  {
763  os << " "; // data
764  }
765  }
766  if (i < LM.M.rows() - 1)
767  {
768  os << endl;
769  }
770  }
771 
772  return os;
773  }
774  catch (Exception& e)
775  {
776  GNSSTK_RETHROW(e);
777  }
778  }
779 
780 } // end namespace gnsstk
781 
782 //------------------------------------------------------------------------------------
783 //------------------------------------------------------------------------------------
gnsstk::LabeledVector::NL
const Namelist & NL
Namelist of names.
Definition: Namelist.hpp:93
gnsstk::LabeledMatrix::sym
bool sym
if true, print only lower triangle
Definition: Namelist.hpp:169
gnsstk::Namelist::labels
std::vector< std::string > labels
vector of names (strings)
Definition: Namelist.hpp:437
gnsstk::LabeledMatrix::NLrows
const Namelist & NLrows
Namelist of rows.
Definition: Namelist.hpp:173
gnsstk::LabeledMatrix::NLcols
const Namelist & NLcols
Namelist of columns.
Definition: Namelist.hpp:174
StringUtils.hpp
gnsstk::Namelist::contains
bool contains(const std::string &name) const
does the Namelist contain the input name?
Definition: Namelist.cpp:264
gnsstk::Matrix::cols
size_t cols() const
The number of columns in the matrix.
Definition: Matrix.hpp:167
gnsstk::Matrix::rows
size_t rows() const
The number of rows in the matrix.
Definition: Matrix.hpp:165
gnsstk::operator!=
bool operator!=(const Namelist &N1, const Namelist &N2)
Definition: Namelist.cpp:318
gnsstk::LabeledMatrix::form
int form
format: 1=fixed, 2=scientific
Definition: Namelist.hpp:167
gnsstk::LabeledVector::wid
int wid
width of fields, in characters
Definition: Namelist.hpp:88
gnsstk::LabeledVector
forward declaration
Definition: Namelist.hpp:85
gnsstk::identical
bool identical(const Namelist &N1, const Namelist &N2)
Definition: Namelist.cpp:331
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::LabeledVector::tag
std::string tag
text at beginning of each line (row)
Definition: Namelist.hpp:92
gnsstk::LabeledMatrix::msg
std::string msg
label (name in Namelist) for each row
Definition: Namelist.hpp:171
gnsstk::operator|
Namelist operator|(const Namelist &N1, const Namelist &N2)
Definition: Namelist.cpp:372
gnsstk::Namelist::size
unsigned int size() const
return the size of the list.
Definition: Namelist.hpp:408
gnsstk::LabeledVector::msg
std::string msg
label (name in Namelist) for each row
Definition: Namelist.hpp:91
gnsstk::operator==
bool operator==(const Namelist &N1, const Namelist &N2)
Definition: Namelist.cpp:282
example6.valid
valid
Definition: example6.py:20
gnsstk::Namelist::getName
std::string getName(const unsigned int in) const
Definition: Namelist.cpp:485
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
std::operator<<
std::ostream & operator<<(std::ostream &s, gnsstk::StringUtils::FFLead v)
Definition: FormattedDouble_T.cpp:44
gnsstk::LabeledMatrix
Definition: Namelist.hpp:162
gnsstk::LabeledMatrix::M
const Matrix< double > & M
Matrix to print.
Definition: Namelist.hpp:175
gnsstk::operator&
Namelist operator&(const Namelist &N1, const Namelist &N2)
Definition: Namelist.cpp:357
gnsstk::StringUtils::rightJustify
std::string & rightJustify(std::string &s, const std::string::size_type length, const char pad=' ')
Definition: StringUtils.hpp:1557
gnsstk::Vector::size
size_t size() const
STL size.
Definition: Vector.hpp:207
Exception.hpp
std
Definition: Angle.hpp:142
gnsstk::LabeledMatrix::rc
int rc
label rows only (1) columns only (2) or both (0)
Definition: Namelist.hpp:168
Namelist.hpp
gnsstk::LabeledMatrix::tag
std::string tag
text at beginning of each line (row)
Definition: Namelist.hpp:172
gnsstk::StringUtils::leftJustify
std::string & leftJustify(std::string &s, const std::string::size_type length, const char pad=' ')
Definition: StringUtils.hpp:1582
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::Namelist
Definition: Namelist.hpp:287
gnsstk::LabeledMatrix::wid
int wid
width of fields, in characters
Definition: Namelist.hpp:165
gnsstk::LabeledVector::prec
int prec
precision of fixed, in digits
Definition: Namelist.hpp:89
gnsstk::operator^
Namelist operator^(const Namelist &N1, const Namelist &N2)
Definition: Namelist.cpp:387
gnsstk::LabeledMatrix::prec
int prec
precision of fixed, in digits
Definition: Namelist.hpp:166
gnsstk::LabeledVector::V
const Vector< double > & V
Vector to print.
Definition: Namelist.hpp:94
gnsstk::LabeledMatrix::cln
bool cln
if true, print 0.0 as "0"
Definition: Namelist.hpp:170
gnsstk::LabeledVector::form
int form
format - 0=general, 1=fixed(default), 2=integer
Definition: Namelist.hpp:90


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:40