Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/parameterisations/Par04/include/Par04InferenceSetup.hh

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 ]

Diff markup

Differences between /examples/extended/parameterisations/Par04/include/Par04InferenceSetup.hh (Version 11.3.0) and /examples/extended/parameterisations/Par04/include/Par04InferenceSetup.hh (Version 11.0)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 #ifdef USE_INFERENCE                               26 #ifdef USE_INFERENCE
 27 #  ifndef PAR04INFEERENCESETUP_HH              <<  27 #ifndef PAR04INFEERENCESETUP_HH
 28 #    define PAR04INFEERENCESETUP_HH            <<  28 #define PAR04INFEERENCESETUP_HH
 29                                                    29 
 30 #    include "CLHEP/Units/SystemOfUnits.h"  // <<  30 #include "G4ThreeVector.hh"
                                                   >>  31 #include "globals.hh"
                                                   >>  32 #include "CLHEP/Units/SystemOfUnits.h"
                                                   >>  33 
                                                   >>  34 #include "Par04DetectorConstruction.hh"
                                                   >>  35 #include "Par04InferenceMessenger.hh"
                                                   >>  36 #include "Par04InferenceInterface.hh"
 31                                                    37 
 32 #    include "G4ThreeVector.hh"  // for G4Thre <<  38 namespace CLHEP
 33                                                <<  39 {
 34 #    include <G4String.hh>  // for G4String    <<  40   class HepRandomEngine;
 35 #    include <G4SystemOfUnits.hh>  // for mm   <<  41 }
 36 #    include <G4Types.hh>  // for G4int, G4dou << 
 37 #    include <memory>  // for unique_ptr       << 
 38 #    include <vector>  // for vector           << 
 39 class Par04DetectorConstruction;               << 
 40 class Par04InferenceInterface;                 << 
 41 class Par04InferenceMessenger;                     42 class Par04InferenceMessenger;
 42                                                    43 
 43 /**                                                44 /**
 44  * @brief Inference setup.                         45  * @brief Inference setup.
 45  *                                                 46  *
 46  * Constructs the input vector of size b+c to  <<  47  * Constructs the input vector of size b+c to run the inference, b represents the size of
 47  * the size of the latent space (or the encode <<  48  * the latent space (or the encoded space in a Variational Autoencoder based model),
 48  * Autoencoder based model), c represents the  <<  49  * c represents the size of the conditional vector. The b values of the input vector
 49  *The b values of the input vector are randoml <<  50  * are randomly sampled from b-dimensional Gaussian distribution. The c values
 50  *Gaussian distribution. The c values represen <<  51  * represent respectively the condition values of the particle energy, angle and
 51  *values of the particle energy, angle and det <<  52  * detector geometry. These condition values are user-specific application.
 52  *values are user-specific application. The en <<  53  * The energy rescaling is used to retrieve the original energy scale in MeV.
 53  *the original energy scale in MeV. Computes t <<  54  * Computes the cell position in the detector of each inferred energy value.
 54  *of each inferred energy value.               << 
 55  *                                                 55  *
 56  **/                                               56  **/
 57                                                    57 
 58 class Par04InferenceSetup                          58 class Par04InferenceSetup
 59 {                                                  59 {
 60   public:                                      <<  60  public:
 61     Par04InferenceSetup();                     <<  61   Par04InferenceSetup();
 62     ~Par04InferenceSetup();                    <<  62   ~Par04InferenceSetup();
 63                                                <<  63 
 64     /// Geometry setup                         <<  64   /// Geometry setup
 65     /// Check if inference should be performed <<  65   /// Check if inference should be performed for the particle
 66     /// @param[in] aEnergy Particle's energy   <<  66   /// @param[in] aEnergy Particle's energy
 67     G4bool IfTrigger(G4double aEnergy);        <<  67   G4bool IfTrigger(G4double aEnergy);
 68     /// Set mesh size.                         <<  68   /// Specify if cylindrical coordinates are to be used (or Carthesian instead).
 69     /// @param aSize (x,y,x) size for Carthesi <<  69   inline void SetIfCylindrical(const G4bool aIfCylindrical) { fIfCylindrical = aIfCylindrical; };
 70     /// cylindrical coordinates.               <<  70   /// Get flag specifying if cylindrical are used (or Carthesian instead).
 71     inline void SetMeshSize(const G4ThreeVecto <<  71   inline G4double GetIfCylindrical() const { return fIfCylindrical; };
 72     /// Get mesh size.                         <<  72   /// Set mesh size.
 73     /// @return G4ThreeVector (x,y,x) size for <<  73   /// @param aSize (x,y,x) size for Carthesian coordinates, or (R, phi, z) for
 74     /// z) for cylindrical coordinates.        <<  74   /// cylindrical coordinates.
 75     inline G4ThreeVector GetMeshSize() const { <<  75   inline void SetMeshSize(const G4ThreeVector& aSize) { fMeshSize = aSize; };
 76     /// Set number of mesh cells.              <<  76   /// Get mesh size.
 77     /// @param aSize (x,y,x) size for Carthesi <<  77   /// @return G4ThreeVector (x,y,x) size for Carthesian coordinates, or (R, phi,
 78     /// cylindrical coordinates.               <<  78   /// z) for cylindrical coordinates.
 79     inline void SetMeshNumber(const G4ThreeVec <<  79   inline G4ThreeVector GetMeshSize() const { return fMeshSize; };
 80     /// Get number of mesh cells.              <<  80   /// Set number of mesh cells.
 81     /// @return G4ThreeVector (x,y,x) size for <<  81   /// @param aSize (x,y,x) size for Carthesian coordinates, or (R, phi, z) for
 82     /// z) for cylindrical coordinates.        <<  82   /// cylindrical coordinates.
 83     inline G4ThreeVector GetMeshNumber() const <<  83   inline void SetMeshNumber(const G4ThreeVector& aSize) { fMeshNumber = aSize; };
 84     /// Set size of the condition vector       <<  84   /// Get number of mesh cells.
 85     inline void SetSizeConditionVector(G4int a <<  85   /// @return G4ThreeVector (x,y,x) size for Carthesian coordinates, or (R, phi,
 86     /// Get size of the condition vector       <<  86   /// z) for cylindrical coordinates.
 87     inline G4int GetSizeConditionVector() cons <<  87   inline G4ThreeVector GetMeshNumber() const { return fMeshNumber; };
 88     /// Set size of the latent space vector    <<  88   /// Set size of the condition vector
 89     inline void SetSizeLatentVector(G4int aNum <<  89   inline void SetSizeConditionVector(G4int aNumber) { fSizeConditionVector = aNumber; };
 90     /// Get size of the latent space vector    <<  90   /// Get size of the condition vector
 91     inline G4int GetSizeLatentVector() const { <<  91   inline G4int GetSizeConditionVector() const { return fSizeConditionVector; };
 92     /// Set path and name of the model         <<  92   /// Set size of the latent space vector
 93     inline void SetModelPathName(G4String aNam <<  93   inline void SetSizeLatentVector(G4int aNumber) { fSizeLatentVector = aNumber; };
 94     /// Get path and name of the model         <<  94   /// Get size of the latent space vector
 95     inline G4String GetModelPathName() const { <<  95   inline G4int GetSizeLatentVector() const { return fSizeLatentVector; };
 96     /// Set profiling flag                     <<  96   /// Set path and name of the model
 97     inline void SetProfileFlag(G4int aNumber)  <<  97   inline void SetModelPathName(G4String aName) { fModelPathName = aName; };
 98     /// Get profiling flag                     <<  98   /// Get path and name of the model
 99     inline G4int GetProfileFlag() const { retu <<  99   inline G4String GetModelPathName() const { return fModelPathName; };
100     /// Set optimization flag                  << 100   /// Set profiling flag
101     inline void SetOptimizationFlag(G4int aNum << 101   inline void SetProfileFlag(G4int aNumber) { fProfileFlag = aNumber; };
102     /// Get optimization flag                  << 102   /// Get profiling flag
103     inline G4int GetOptimizationFlag() const { << 103   inline G4int GetProfileFlag() const { return fProfileFlag; };
104     /// Get name of the inference library      << 104   /// Set optimization flag
105     inline G4String GetInferenceLibrary() cons << 105   inline void SetOptimizationFlag(G4int aNumber) { fOptimizationFlag = aNumber; };
106     /// Set name of the inference library and  << 106   /// Get optimization flag
107     /// interface                              << 107   inline G4int GetOptimizationFlag() const { return fOptimizationFlag; };
108     void SetInferenceLibrary(G4String aName);  << 108   /// Get name of the inference library
109     /// Check settings of the inference librar << 109   inline G4String GetInferenceLibrary() const { return fInferenceLibrary; };
110     void CheckInferenceLibrary();              << 110   /// Set name of the inference library and create a pointer to chosen inference interface
111     /// Set number of Mesh cells in cylindrica << 111   void SetInferenceLibrary(G4String aName);
112     inline void SetMeshNbOfCells(G4ThreeVector << 112   /// Check settings of the inference library
113     /// Set number of Mesh cells in cylindrica << 113   void CheckInferenceLibrary();
114     /// @param[in] aIndex index of cylindrical << 114   /// Set number of Mesh cells in cylindrical coordinates (r, phi, z)
115     inline void SetMeshNbOfCells(G4int aIndex, << 115   inline void SetMeshNbOfCells(G4ThreeVector aNb) { fMeshNumber = aNb; };
116     /// Get number of Mesh cells in cylindrica << 116   /// Set number of Mesh cells in cylindrical coordinates
117     inline G4ThreeVector GetMeshNbOfCells() co << 117   /// @param[in] aIndex index of cylindrical axis (0,1,2) = (r, phi, z)
118     /// Set size of Mesh cells in cylindrical  << 118   inline void SetMeshNbOfCells(G4int aIndex, G4double aNb) { fMeshNumber[aIndex] = aNb; };
119     inline void SetMeshSizeOfCells(G4ThreeVect << 119   /// Get number of Mesh cells in cylindrical coordinates (r, phi, z)
120     /// Set size of Mesh cells in cylindrical  << 120   inline G4ThreeVector GetMeshNbOfCells() const { return fMeshNumber; };
121     /// @param[in] aIndex index of cylindrical << 121   /// Set size of Mesh cells in cylindrical coordinates (r, phi, z)
122     inline void SetMeshSizeOfCells(G4int aInde << 122   inline void SetMeshSizeOfCells(G4ThreeVector aNb) { fMeshSize = aNb; };
123     /// Get size of Mesh cells in cylindrical  << 123   /// Set size of Mesh cells in cylindrical coordinates
124     inline G4ThreeVector GetMeshSizeOfCells()  << 124   /// @param[in] aIndex index of cylindrical axis (0,1,2) = (r, phi, z)
125     /// Setting execution providers flags      << 125   inline void SetMeshSizeOfCells(G4int aIndex, G4double aNb) { fMeshSize[aIndex] = aNb; };
126     /// GPU                                    << 126   /// Get size of Mesh cells in cylindrical coordinates (r, phi, z)
127     inline void SetCudaFlag(G4int aNumber) { f << 127   inline G4ThreeVector GetMeshSizeOfCells() const { return fMeshSize; };
128     inline G4int GetCudaFlag() const { return  << 128 
129     /// Setting execution providers Options    << 129   /// Execute inference
130     /// Cuda                                   << 130   /// @param[out] aDepositsEnergies of inferred energies deposited in the
131     inline void SetCudaDeviceId(G4String aNumb << 131   /// detector
132     inline G4String GetCudaDeviceId() const {  << 132   /// @param[in] aParticleEnergy Energy of initial particle
133     inline void SetCudaGpuMemLimit(G4String aN << 133   void GetEnergies(std::vector<G4double>& aEnergies, G4double aParticleEnergy,
134     inline G4String GetCudaGpuMemLimit() const << 134                    G4float aInitialAngle);
135     inline void SetCudaArenaExtendedStrategy(G << 135 
136     {                                          << 136   /// Calculate positions
137       fCudaArenaExtendedStrategy = aNumber;    << 137   /// @param[out] aDepositsPositions Vector of positions corresponding to
138     };                                         << 138   /// energies deposited in the detector
139     inline G4String GetCudaArenaExtendedStrate << 139   /// @param[in] aParticlePosition Initial particle position which is centre of
140     inline void SetCudaCudnnConvAlgoSearch(G4S << 140   /// transverse plane of the mesh
141     {                                          << 141   ///            and beginning of the mesh in the longitudinal direction
142       fCudaCudnnConvAlgoSearch = aNumber;      << 142   /// @param[in] aParticleDirection Initial particle direction for the mesh
143     };                                         << 143   /// rotation
144     inline G4String GetCudaCudnnConvAlgoSearch << 144   void GetPositions(std::vector<G4ThreeVector>& aDepositsPositions, G4ThreeVector aParticlePosition,
145     inline void SetCudaDoCopyInDefaultStream(G << 145                     G4ThreeVector aParticleDirection);
146     {                                          << 146 
147       fCudaDoCopyInDefaultStream = aNumber;    << 147  private:
148     };                                         << 148   /// Pointer to detector construction to retrieve (once) the detector
149     inline G4String GetCudaDoCopyInDefaultStre << 149   /// dimensions
150     inline void SetCudaCudnnConvUseMaxWorkspac << 150   Par04DetectorConstruction* fDetector;
151     {                                          << 151   // Alpha parameter of the Sigma distribution
152       fCudaCudnnConvUseMaxWorkspace = aNumber; << 152   /// Can be changed with UI command `/example/mesh/cylindrical <true/false>`
153     };                                         << 153   bool fIfCylindrical = true;
154     inline G4String GetCudaCudnnConvUseMaxWork << 154   /// Cell's size: (x,y,x) for Carthesian, and (R, phi, z) for cylindrical
155     {                                          << 155   /// coordinates Can be changed with UI command `/example/mesh/size <x y z>/<r
156       return fCudaCudnnConvUseMaxWorkspace;    << 156   /// phi z> <unit>`. For cylindrical coordinates phi is ignored and calculated
157     };                                         << 157   /// from fMeshNumber.
158                                                << 158   G4ThreeVector fMeshSize = G4ThreeVector(2.325 * CLHEP::mm, 1, 3.4 * CLHEP::mm);
159     /// Execute inference                      << 159   /// Number of cells: (x,y,x) for Carthesian, and (R, phi, z) for cylindrical
160     /// @param[out] aDepositsEnergies of infer << 160   /// coordinates. Can be changed with UI command `/example/mesh/number <Nx Ny
161     /// detector                               << 161   /// Nz>/<Nr Nphi Nz>`
162     /// @param[in] aParticleEnergy Energy of i << 162   G4ThreeVector fMeshNumber = G4ThreeVector(18, 50, 45);
163     void GetEnergies(std::vector<G4double>& aE << 163   /// Inference interface
164                      G4float aInitialAngle);   << 164   std::unique_ptr<Par04InferenceInterface> fInferenceInterface;
165                                                << 165   /// Inference messenger
166     /// Calculate positions                    << 166   Par04InferenceMessenger* fInferenceMessenger;
167     /// @param[out] aDepositsPositions Vector  << 167   /// Maximum particle energy value (in MeV) in the training range
168     /// energies deposited in the detector     << 168   float fMaxEnergy = 1024000.0;
169     /// @param[in] aParticlePosition Initial p << 169   /// Maximum particle angle (in degrees) in the training range
170     /// transverse plane of the mesh           << 170   float fMaxAngle = 90.0;
171     ///            and beginning of the mesh i << 171   /// Name of the inference library
172     /// @param[in] aParticleDirection Initial  << 172   G4String fInferenceLibrary = "ONNX";
173     /// rotation                               << 173   /// Size of the latent space vector
174     void GetPositions(std::vector<G4ThreeVecto << 174   G4int fSizeLatentVector = 10;
175                       G4ThreeVector aParticleP << 175   /// Size of the condition vector
176                                                << 176   G4int fSizeConditionVector = 4;
177   private:                                     << 177   /// Name of the inference library
178     /// Cell's size: (x,y,x) for Carthesian, a << 178   G4String fModelPathName = "MLModels/Generator.onnx";
179     /// coordinates Can be changed with UI com << 179   /// ONNX specific
180     /// phi z> <unit>`. For cylindrical coordi << 180   /// Profiling flag
181     /// from fMeshNumber.                      << 181   G4bool fProfileFlag = false;
182     G4ThreeVector fMeshSize = G4ThreeVector(2. << 182   /// Optimization flag
183     /// Number of cells: (x,y,x) for Carthesia << 183   G4bool fOptimizationFlag = false;
184     /// coordinates. Can be changed with UI co << 184   /// Intra-operation number of threads
185     /// Nz>/<Nr Nphi Nz>`                      << 185   G4int fIntraOpNumThreads = 1;
186     G4ThreeVector fMeshNumber = G4ThreeVector( << 
187     /// Inference interface                    << 
188     std::unique_ptr<Par04InferenceInterface> f << 
189     /// Inference messenger                    << 
190     Par04InferenceMessenger* fInferenceMesseng << 
191     /// Maximum particle energy value (in MeV) << 
192     float fMaxEnergy = 1024000.0;              << 
193     /// Maximum particle angle (in degrees) in << 
194     float fMaxAngle = 90.0;                    << 
195     /// Name of the inference library          << 
196     G4String fInferenceLibrary = "ONNX";       << 
197     /// Size of the latent space vector        << 
198     G4int fSizeLatentVector = 10;              << 
199     /// Size of the condition vector           << 
200     G4int fSizeConditionVector = 4;            << 
201     /// Name of the inference library          << 
202     G4String fModelPathName = "MLModels/Genera << 
203     /// ONNX specific                          << 
204     /// Profiling flag                         << 
205     G4bool fProfileFlag = false;               << 
206     /// Optimization flag                      << 
207     G4bool fOptimizationFlag = false;          << 
208     /// Optimization file                      << 
209     G4String fModelSavePath = "MLModels/Optimi << 
210     /// Profiling file                         << 
211     G4String fProfilingOutputSavePath = "opt.j << 
212     /// Intra-operation number of threads      << 
213     G4int fIntraOpNumThreads = 1;              << 
214     /// Flags for execution providers          << 
215     /// GPU                                    << 
216     G4bool fCudaFlag = false;                  << 
217     /// Execution Provider Options             << 
218     /// Cuda options                           << 
219     G4String fCudaDeviceId = "0";              << 
220     G4String fCudaGpuMemLimit = "2147483648";  << 
221     G4String fCudaArenaExtendedStrategy = "kSa << 
222     G4String fCudaCudnnConvAlgoSearch = "DEFAU << 
223     G4String fCudaDoCopyInDefaultStream = "1"; << 
224     G4String fCudaCudnnConvUseMaxWorkspace = " << 
225     std::vector<const char*> cuda_keys{        << 
226       "device_id",                             << 
227       "gpu_mem_limit",                         << 
228       "arena_extend_strategy",                 << 
229       "cudnn_conv_algo_search",                << 
230       "do_copy_in_default_stream",             << 
231       "cudnn_conv_use_max_workspace",          << 
232     };                                         << 
233     std::vector<const char*> cuda_values{      << 
234       fCudaDeviceId.c_str(),                   << 
235       fCudaGpuMemLimit.c_str(),                << 
236       fCudaArenaExtendedStrategy.c_str(),      << 
237       fCudaCudnnConvAlgoSearch.c_str(),        << 
238       fCudaDoCopyInDefaultStream.c_str(),      << 
239       fCudaCudnnConvUseMaxWorkspace.c_str(),   << 
240     };                                         << 
241 };                                                186 };
242                                                   187 
243 #  endif /* PAR04INFEERENCESETUP_HH */         << 188 #endif /* PAR04INFEERENCESETUP_HH */
244 #endif                                            189 #endif
245                                                   190