Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/persistency/ascii/src/G4tgrUtils.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 // G4tgrUtils implementation
 27 //
 28 // Author: P.Arce, CIEMAT (November 2007)
 29 // --------------------------------------------------------------------
 30 
 31 #include <iomanip>
 32 #include <set>
 33 
 34 #include "G4tgrUtils.hh"
 35 
 36 #include "geomdefs.hh"
 37 #include "G4PhysicalConstants.hh"
 38 #include "G4tgrParameterMgr.hh"
 39 #include "G4tgrMessenger.hh"
 40 #include "G4UnitsTable.hh"
 41 #include "G4GeometryTolerance.hh"
 42 #include "G4UIcommand.hh"
 43 
 44 G4ThreadLocal G4tgrEvaluator* G4tgrUtils::theEvaluator = nullptr;
 45 
 46 // --------------------------------------------------------------------
 47 G4tgrUtils::G4tgrUtils()
 48 {
 49   if(theEvaluator == nullptr)
 50   {
 51     theEvaluator = new G4tgrEvaluator;
 52   }
 53 }
 54 
 55 // --------------------------------------------------------------------
 56 G4tgrUtils::~G4tgrUtils()
 57 {
 58   delete theEvaluator;
 59   theEvaluator = nullptr;
 60 }
 61 
 62 // --------------------------------------------------------------------
 63 G4bool G4tgrUtils::IsSeparator(const char ch)
 64 {
 65   char nonCharacters[7] = { "()+-*/" };
 66   for(std::size_t ii = 0; ii < 6; ++ii)
 67   {
 68     if(ch == nonCharacters[ii])
 69     {
 70       return true;
 71     }
 72   }
 73   return false;
 74 }
 75 
 76 // --------------------------------------------------------------------
 77 G4bool G4tgrUtils::IsNumber(const G4String& str)
 78 {
 79   G4int isnum = 1;
 80   G4int numE  = 0;
 81   for(G4int ii = 0; ii < (G4int)str.length(); ++ii)
 82   {
 83     if(!isdigit(str[ii]) && (str[ii] != '.') && (str[ii] != '-') &&
 84        (str[ii] != '+'))
 85     {
 86       //--- check for E(xponential)
 87       if(str[ii] == 'E' || str[ii] == 'e')
 88       {
 89         if(ii == 0)
 90         {
 91           return 0;
 92         }
 93         if(numE != 0 || ii == G4int(str.length() - 1))
 94         {
 95           isnum = 0;
 96           break;
 97         }
 98         numE++;
 99       }
100       else
101       {
102         isnum = 0;
103         break;
104       }
105     }
106   }
107   return isnum;
108 }
109 
110 // --------------------------------------------------------------------
111 G4bool G4tgrUtils::IsInteger(const G4double val, const G4double precision)
112 {
113   if(G4int(val) / val - 1 > precision)
114   {
115     return false;
116   }
117   else
118   {
119     return true;
120   }
121 }
122 
123 // --------------------------------------------------------------------
124 void G4tgrUtils::Dump3v(const G4ThreeVector& vec, const char* msg)
125 {
126   G4cout << msg << std::setprecision(8) << vec << std::setprecision(6)
127          << G4endl;
128 }
129 
130 // --------------------------------------------------------------------
131 void G4tgrUtils::Dumprm(const G4RotationMatrix& rm, const char* msg)
132 {
133   G4cout << msg << G4endl << " xx=" << rm.xx() << " yx=" << rm.yx()
134          << " zx=" << rm.zx() << G4endl << " xy=" << rm.xy()
135          << " yy=" << rm.yy() << " zy=" << rm.zy() << G4endl
136          << " xz=" << rm.xz() << " yz=" << rm.yz() << " zz=" << rm.zz()
137          << G4endl;
138 }
139 
140 // --------------------------------------------------------------------
141 void G4tgrUtils::DumpVS(const std::vector<G4String>& wl, const char* msg,
142                         std::ostream& outs)
143 {
144   outs << msg << G4endl;
145   for(auto ite = wl.cbegin(); ite != wl.cend(); ++ite)
146   {
147     outs << *ite << " ";
148   }
149   outs << G4endl;
150 }
151 
152 // --------------------------------------------------------------------
153 void G4tgrUtils::DumpVS(const std::vector<G4String>& wl, const char* msg)
154 {
155   DumpVS(wl, msg, G4cout);
156 }
157 
158 // --------------------------------------------------------------------
159 G4String G4tgrUtils::SubColon(const G4String& str)
160 {
161   if(str.find(':') != 0)
162   {
163     G4String ErrMessage = "Trying to subtract leading colon from a word\n" +
164                           G4String("that has no leading colon: ") + str;
165     G4Exception("G4tgrUtils::SubColon()", "ParseError", FatalException,
166                 ErrMessage);
167   }
168   G4String strt = str.substr(1, str.size() - 1);
169   return strt;
170 }
171 
172 // --------------------------------------------------------------------
173 G4String G4tgrUtils::GetString(const G4String& str)
174 {
175   //----------- first check if it is parameter
176   const char* cstr = str.c_str();
177   if(cstr[0] == '$')
178   {
179 #ifdef G4VERBOSE
180     if(G4tgrMessenger::GetVerboseLevel() >= 3)
181     {
182       G4cout << " G4tgrUtils::GetString() - Substitute parameter: "
183              << G4tgrParameterMgr::GetInstance()->FindParameter(
184                   str.substr(1, str.size()))
185              << G4endl;
186     }
187 #endif
188     return G4tgrParameterMgr::GetInstance()->FindParameter(
189       str.substr(1, str.size()));
190   }
191   else
192   {
193     return str;
194   }
195 }
196 
197 // --------------------------------------------------------------------
198 G4double G4tgrUtils::GetDouble(const G4String& str, G4double unitval)
199 {
200   if(!theEvaluator)
201   {
202     theEvaluator = new G4tgrEvaluator;
203   }
204 #ifdef G4VERBOSE
205   if(G4tgrMessenger::GetVerboseLevel() >= 3)
206   {
207     G4cout << "G4tgrUtils::GetDouble() - Processing: " << str
208            << " default unit " << unitval << G4endl;
209   }
210 #endif
211   if(str == "DBL_MAX")
212   {
213     return DBL_MAX;
214   }
215   else if(str == "DBL_MIN")
216   {
217     return DBL_MIN;
218   }
219   else if(str == "FLT_MAX")
220   {
221     return FLT_MAX;
222   }
223   else if(str == "FLT_MIN")
224   {
225     return FLT_MIN;
226   }
227   else if(str == "INT_MAX")
228   {
229     return INT_MAX;
230   }
231   else if(str == "INT_MIN")
232   {
233     return INT_MIN;
234   }
235   //----- Look for arithmetic symbols, (, )
236   const char* cstr = str.c_str();
237   std::set<G4int> separators;
238   separators.insert(-1);
239   G4int strlen = G4int(str.length());
240   for(G4int ii = 0; ii < strlen; ++ii)
241   {
242     char cs = cstr[ii];
243     if(cs == '*' || cs == '/' || cs == '(' || cs == ')')
244     {
245       separators.insert(ii);
246     }
247     else if(cs == '+' || cs == '-')
248     {
249       // Check if it is not an exponential
250       //
251       if((ii < 2) || ((cstr[ii - 1] != 'E') && (cstr[ii - 1] != 'e')) ||
252    !IsNumber(G4String(1,cstr[ii - 2])))
253       {
254         separators.insert(ii);
255       }
256     }
257   }
258   separators.insert(strlen);
259   std::string strnew;  // build a new word with Parameters
260                        // and units substituted by values
261   //----- Process words, defined as characters between two separators
262   G4int nUnits = 0;
263   std::set<G4int>::const_iterator site, site2;
264   site  = separators.cbegin();
265   site2 = site;
266   ++site2;
267   for(; site2 != separators.cend(); ++site, ++site2)
268   {
269 #ifdef G4VERBOSE
270     if(G4tgrMessenger::GetVerboseLevel() >= 3)
271     {
272       G4cout << "   Loop to find word between " << *site << " " << *site2
273              << G4endl;
274     }
275 #endif
276 
277     if(*site != -1)
278     {
279       strnew += str.substr(*site, 1);
280     }
281 
282     G4int wlen = (*site2) - (*site) - 1;  // do not count contiguous separators
283     std::string word;
284     if(wlen != 0)
285     {
286       word = str.substr((*site) + 1, (*site2) - (*site) - 1);
287     }
288     else
289     {
290       //--- Check combination of separators
291       //--- Check number of parentheses
292       continue;
293     }
294 
295 #ifdef G4VERBOSE
296     if(G4tgrMessenger::GetVerboseLevel() >= 3)
297     {
298       G4cout << "   Processing word: " << word << G4endl;
299     }
300 #endif
301     //----------- first check if it is parameter
302     const char* cword = word.c_str();
303     if(cword[0] == '$')
304     {
305       G4String parstr = G4tgrParameterMgr::GetInstance()->FindParameter(
306         word.substr(1, word.size()));
307       if(parstr.substr(0, 1) == "-")
308       {
309         strnew += "(";
310       }
311       strnew += parstr;
312       if(parstr.substr(0, 1) == "-")
313       {
314         strnew += ")";
315       }
316 #ifdef G4VERBOSE
317       if(G4tgrMessenger::GetVerboseLevel() >= 3)
318       {
319         G4cout << " G4tgrutils::GetDouble() - Param found: " << word
320                << " in string " << str << " , substituted by " << parstr
321                << G4endl;
322       }
323 #endif
324     }
325     else
326     {
327       //----- Get if it is a number
328       if(IsNumber(word))
329       {
330         //--- left separator cannot be ')'
331         if((*site != -1) && (cstr[*site] == ')'))
332         {
333           G4String ErrMessage =
334             "There cannot be a ')' before a number: " + word +
335             " in string: " + str;
336           G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
337                       ErrMessage);
338         }
339         //--- right separator cannot be '('
340         if((*site2 != strlen) && (cstr[*site2] == '('))
341         {
342           G4String ErrMessage =
343             "There cannot be a '(' after a number: " + word +
344             " in string: " + str;
345           G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
346                       ErrMessage);
347         }
348         strnew += word;
349 
350         //------ If it is an string, check if it is a unit
351       }
352       else
353       {
354         //--- First character cannot be a digit
355         if(isdigit(word[0]))
356         {
357           G4String ErrMessage =
358             "String words cannot start with a digit: " + word +
359             " in string: " + str;
360           G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
361                       ErrMessage);
362         }
363 
364         //----- Check if it is a function
365         G4bool bWordOK = false;
366         if(G4tgrUtils::IsFunction(word))
367         {
368           //--- It must be followed by '('
369           if((*site2 == strlen) || (cstr[*site2] != '('))
370           {
371             G4String ErrMessage =
372               "There must be a '(' after a function: " + word +
373               " in string: " + str;
374             G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
375                         ErrMessage);
376           }
377           strnew += word;
378           bWordOK = true;
379           //----- Check if it is a unit
380         }
381         else if(G4tgrUtils::WordIsUnit(word))
382         {
383           //--- It must be preceded by a *
384           if((*site == -1) || ((cstr[*site] != '*') && (cstr[*site] != '/')))
385           {
386             G4String ErrMess =
387               "There must be a '*' before a unit definition: " + word +
388               " in string " + str;
389             G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
390                         ErrMess);
391           }
392           //--- check that it is indeed a CLHEP unit
393           if(G4UnitDefinition::GetValueOf(word) != 0.)
394           {
395             bWordOK = true;
396             nUnits++;
397             if(nUnits > 1)
398             {
399               // G4String ErrMess = "There cannot be two unit definitions: "
400               //                  + word + " in string " + str;
401               // G4Exception("G4tgrUtils::GetDouble()", "ParseError",
402               //             FatalException, ErrMess );
403             }
404             strnew +=
405               G4UIcommand::ConvertToString(G4UnitDefinition::GetValueOf(word));
406           }
407         }
408         if(!bWordOK)
409         {
410           G4String ErrMess = "String word is not a parameter, nor a unit\n" +
411                              G4String("definition nor a function: ") + word +
412                              G4String(" in string: ") + str;
413           G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
414                       ErrMess);
415         }
416       }
417     }
418   }
419 
420   G4double val = theEvaluator->evaluate(strnew.c_str());
421   if(theEvaluator->status() != HepTool::Evaluator::OK)
422   {
423     theEvaluator->print_error(theEvaluator->status());
424     G4String ErrMessage = "Evaluator error: " + strnew;
425     G4Exception("G4tgrUtils::GetDouble()", "ParseError", FatalException,
426                 ErrMessage);
427   }
428 
429   if(nUnits == 0)
430   {
431     val *= unitval;
432   }
433 
434 #ifdef G4VERBOSE
435   if(G4tgrMessenger::GetVerboseLevel() >= 3)
436   {
437     G4cout << " G4tgrUtils::GetDouble() - RESULT= " << val << G4endl
438            << "   from string: " << str << " converted to: " << strnew.c_str()
439            << " with unit val: " << unitval << G4endl;
440   }
441 #endif
442 
443   return val;
444 }
445 
446 // --------------------------------------------------------------------
447 G4int G4tgrUtils::GetInt(const G4String& str)
448 {
449   //----- Convert it to a number (it can be a parameter)
450   G4double val = GetDouble(str);
451 
452   //----- Check it is an integer
453   if(!IsInteger(val))
454   {
455     G4String ErrMessage = G4String("Trying to get the integer from a number") +
456                           G4String(" which is not an integer ") + str;
457     G4Exception("G4tgrUtils::GetInt()", "ParseError", FatalException,
458                 ErrMessage);
459   }
460   return G4int(val);
461 }
462 
463 // --------------------------------------------------------------------
464 G4bool G4tgrUtils::GetBool(const G4String& str)
465 {
466   G4bool val = false;
467 
468   //----------- first check that it is a not number
469   if((str == "ON") || (str == "TRUE"))
470   {
471     val = true;
472   }
473   else if((str == "OFF") || (str == "FALSE"))
474   {
475     val = false;
476   }
477   else
478   {
479     G4String ErrMessage = G4String("Trying to get a float from a string") +
480                           G4String(" which is not 'ON'/'OFF'/'TRUE'/'FALSE' ") +
481                           str;
482     G4Exception("G4tgrUtils::GetBool()", "ParseError", FatalException,
483                 ErrMessage);
484   }
485 
486   return val;
487 }
488 
489 // --------------------------------------------------------------------
490 void G4tgrUtils::CheckWLsize(const std::vector<G4String>& wl,
491                              unsigned int nWcheck, WLSIZEtype st,
492                              const G4String& methodName)
493 {
494   G4String outStr = methodName + G4String(".  Line read with number of words ");
495   unsigned int wlsize = (unsigned int)wl.size();
496 
497   G4bool isOK = CheckListSize(wlsize, nWcheck, st, outStr);
498 
499   if(!isOK)
500   {
501     G4String chartmp = G4UIcommand::ConvertToString(G4int(nWcheck));
502     outStr += chartmp + G4String(" words");
503     DumpVS(wl, outStr.c_str());
504     G4String ErrMessage =
505       " NUMBER OF WORDS: " + G4UIcommand::ConvertToString(G4int(wlsize));
506     G4Exception("G4tgrUtils::CheckWLsize()", "ParseError", FatalException,
507                 ErrMessage);
508   }
509 }
510 
511 // --------------------------------------------------------------------
512 G4bool G4tgrUtils::CheckListSize(unsigned int nWreal, unsigned int nWcheck,
513                                  WLSIZEtype st, G4String& outStr)
514 {
515   G4bool isOK = true;
516   switch(st)
517   {
518     case WLSIZE_EQ:
519       if(nWreal != nWcheck)
520       {
521         isOK = false;
522         outStr += G4String("not equal than ");
523       }
524       break;
525     case WLSIZE_NE:
526       if(nWreal == nWcheck)
527       {
528         isOK = false;
529         outStr += G4String("equal than ");
530       }
531       break;
532     case WLSIZE_LE:
533       if(nWreal > nWcheck)
534       {
535         isOK = false;
536         outStr += G4String("greater than ");
537       }
538       break;
539     case WLSIZE_LT:
540       if(nWreal >= nWcheck)
541       {
542         isOK = false;
543         outStr += G4String("greater or equal than ");
544       }
545       break;
546     case WLSIZE_GE:
547       if(nWreal < nWcheck)
548       {
549         isOK = false;
550         outStr += G4String("less than ");
551       }
552       break;
553     case WLSIZE_GT:
554       if(nWreal <= nWcheck)
555       {
556         isOK = false;
557         outStr += G4String("less or equal than ");
558       }
559       break;
560     default:
561       G4cerr << " ERROR!! - G4tgrUtils::CheckListSize()" << G4endl
562              << "           Type of WLSIZE type not found " << st << G4endl;
563       break;
564   }
565 
566   return isOK;
567 }
568 
569 // --------------------------------------------------------------------
570 G4bool G4tgrUtils::WordIsUnit(const G4String& word)
571 {
572   return !IsNumber(word);
573   if(word == "mm" || word == "cm" || word == "m" || word == "km" ||
574      word == "millimeter" || word == "centimeter" || word == "meter" ||
575      word == "kilometer" || word == "parsec" || word == "micrometer" ||
576      word == "nanometer" || word == "angstrom" || word == "fermi" ||
577      word == "nm" || word == "um" || word == "pc" || word == "radian" ||
578      word == "milliradian" || word == "degree" || word == "rad" ||
579      word == "mrad" || word == "deg" || word == "ns" || word == "becquerel" ||
580      word == "curie")
581   {
582     return true;
583   }
584   else
585   {
586     return false;
587   }
588 }
589 
590 // --------------------------------------------------------------------
591 G4bool G4tgrUtils::IsFunction(const G4String& word)
592 {
593   if(word == "sin" || word == "cos" || word == "tan" || word == "asin" ||
594      word == "acos" || word == "atan" || word == "atan2" || word == "sinh" ||
595      word == "cosh" || word == "tanh" || word == "asinh" || word == "acosh" ||
596      word == "atanh" || word == "sqrt" || word == "exp" || word == "log" ||
597      word == "log10" || word == "pow")
598   {
599     return true;
600   }
601   else
602   {
603     return false;
604   }
605 }
606 
607 // --------------------------------------------------------------------
608 G4RotationMatrix G4tgrUtils::GetRotationFromDirection(G4ThreeVector dir)
609 {
610   G4RotationMatrix rotation;
611 
612   if(std::fabs(dir.mag() - 1.) >
613      G4GeometryTolerance::GetInstance()->GetSurfaceTolerance())
614   {
615     G4String WarMessage = "Direction cosines have been normalized to one.\n" +
616                           G4String("They were normalized to ") +
617                           G4UIcommand::ConvertToString(dir.mag());
618     G4Exception("G4tgrUtils::GetRotationFromDirection()", "WrongArgument",
619                 JustWarning, WarMessage);
620     dir /= dir.mag();
621   }
622   G4double angx = -std::asin(dir.y());
623 
624   // There are always two solutions angx, angy and PI-angx,
625   // PI+angy, choose first
626   //
627   G4double angy;
628   if(dir.y() == 1.)
629   {
630     angy = 0.;
631   }
632   else if(dir.y() == 0.)
633   {
634     angy = 0.;
635   }
636   else
637   {
638     angy = std::asin(dir.x() / std::sqrt(1 - dir.y() * dir.y()));
639   }
640 
641   // choose between  angy and PI-angy
642   if(dir.z() * std::cos(angx) * std::cos(angy) < 0)
643   {
644     angy = pi - angy;
645   }
646   rotation.rotateX(angx);
647   rotation.rotateY(angy);
648 
649   return rotation;
650 }
651 
652 // --------------------------------------------------------------------
653 G4bool G4tgrUtils::AreWordsEquivalent(const G4String& word1,
654                                       const G4String& word2)
655 {
656   G4bool bEqual = true;
657   std::vector<std::pair<size_t, size_t>> stringPairs;
658   // start of substring, number of characters
659 
660   //--- Get string limits between asterisks in word1
661 
662   std::size_t cStart = 0;
663   for(;;)
664   {
665     size_t cAster = word1.find("*", cStart);
666     if(cAster != std::string::npos)
667     {
668       if(cAster == cStart)
669       {
670         if(cAster != 0)
671         {
672           G4Exception("G4tgrUtils::AreWordsEquivalent()",
673                       "A word has two asterisks together, please correct it",
674                       FatalException, ("Offending word is: " + word1).c_str());
675         }
676         else
677         {
678           // word1 == *
679           if(word1.size() == 1)
680           {
681             return true;
682           }
683         }
684       }
685       if(cAster != cStart)
686       {
687         stringPairs.push_back(
688           std::pair<size_t, size_t>(cStart, cAster - cStart));
689       }
690       cStart = cAster + 1;
691     }
692     else
693     {
694       if(cStart == 0)
695       {
696         //--- If there is no asterisk check if they are the same
697         return word1 == word2;
698       }
699       break;
700     }
701   }
702 
703   //---- Add characters after last asterisk as string pair
704   if(cStart <= word1.length())
705   {
706     if(word1.length() != cStart)
707     {
708       stringPairs.push_back(
709         std::pair<size_t, size_t>(cStart, word1.length() - cStart));
710     }
711   }
712 
713   //--- If there are not asterisk, simple comparison
714   if(stringPairs.size() == 0)
715   {
716     if(word1 == word2)
717     {
718       return true;
719     }
720     else
721     {
722       return false;
723     }
724   }
725 
726   //--- Find substrings in word2, in same order as in word1
727   cStart = 0;
728   for(std::size_t ii = 0; ii < stringPairs.size(); ++ii)
729   {
730     std::pair<size_t, size_t> spair = stringPairs[ii];
731     size_t sFound = word2.find(word1.substr(spair.first, spair.second), cStart);
732     if(sFound == std::string::npos)
733     {
734       bEqual = false;
735       break;
736     }
737     else
738     {
739       //---- If there is no asterisk before first character,
740       //     the fisrt string pair found has to start at the first character
741       if(spair.first == 0 && sFound != 0)
742       {
743         bEqual = false;
744         break;
745         //---- If there is no asterisk after last character,
746         //     the last string pair found has to end at the last character
747       }
748       else if((spair.first + spair.second - 1 == word1.length()) &&
749               (sFound + spair.second - 1 != word2.length()))
750       {
751         bEqual = false;
752         break;
753       }
754       cStart += spair.second;
755     }
756   }
757 
758   return bEqual;
759 }
760