Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-12 08:32:20

0001 // Created on: 2002-02-22
0002 // Created by: Andrey BETENEV
0003 // Copyright (c) 2002-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _Message_ProgressScope_HeaderFile
0017 #define _Message_ProgressScope_HeaderFile
0018 
0019 #include <Standard_Assert.hxx>
0020 #include <Standard_TypeDef.hxx>
0021 #include <Standard_DefineAlloc.hxx>
0022 #include <Standard_Handle.hxx>
0023 #include <Precision.hxx>
0024 #include <TCollection_AsciiString.hxx>
0025 
0026 class Message_ProgressRange;
0027 class Message_ProgressIndicator;
0028 
0029 //! Message_ProgressScope class provides convenient way to advance progress
0030 //! indicator in context of complex program organized in hierarchical way,
0031 //! where usually it is difficult (or even not possible) to consider process
0032 //! as linear with fixed step.
0033 //!
0034 //! On every level (sub-operation) in hierarchy of operations
0035 //! the local instance of the Message_ProgressScope class is created.
0036 //! It takes a part of the upper-level scope (via Message_ProgressRange) and provides
0037 //! a way to consider this part as independent scale with locally defined range.
0038 //!
0039 //! The position on the local scale may be advanced using the method Next(),
0040 //! which allows iteration-like advancement. This method can take argument to
0041 //! advance by the specified value (with default step equal to 1).
0042 //! This method returns Message_ProgressRange object that takes responsibility
0043 //! of making the specified step, either directly at its destruction or by
0044 //! delegating this task to another sub-scope created from that range object.
0045 //!
0046 //! It is important that sub-scope must have life time less than
0047 //! the life time of its parent scope that provided the range.
0048 //! The usage pattern is to create scope objects as local variables in the
0049 //! functions that do the job, and pass range objects returned by Next() to
0050 //! the functions of the lower level, to allow them creating their own scopes.
0051 //!
0052 //! The scope has a name that can be used in visualization of the progress.
0053 //! It can be null. Note that when C string literal is used as a name, then its
0054 //! value is not copied, just pointer is stored. In other variants (char pointer
0055 //! or a string class) the string is copied, which is additional overhead.
0056 //!
0057 //! The same instance of the progress scope! must not be used concurrently from different threads.
0058 //! For the algorithm running its tasks in parallel threads, a common scope is
0059 //! created before the parallel execution, and the range objects produced by method
0060 //! Next() are used to initialise the data pertinent to each task.
0061 //! Then the progress is advanced within each task using its own range object.
0062 //! See example below.
0063 //!
0064 //! Note that while a range of the scope is specified using Standard_Real
0065 //! (double) parameter, it is expected to be a positive integer value.
0066 //! If the range is not an integer, method Next() shall be called with
0067 //! explicit step argument, and the rounded value returned by method Value()
0068 //! may be not coherent with the step and range.
0069 //!
0070 //! A scope can be created with option "infinite". This is useful when
0071 //! the number of steps is not known by the time of the scope creation.
0072 //! In this case the progress will be advanced logarithmically, approaching
0073 //! the end of the scope at infinite number of steps. The parameter Max
0074 //! for infinite scope indicates number of steps corresponding to mid-range.
0075 //!
0076 //! A progress scope created with empty constructor is not connected to any
0077 //! progress indicator, and passing the range created on it to any algorithm
0078 //! allows it executing safely without actual progress indication.
0079 //!
0080 //! Example of preparation of progress indicator:
0081 //!
0082 //! @code{.cpp}
0083 //!   Handle(Message_ProgressIndicator) aProgress = ...; // assume it can be null
0084 //!   func (Message_ProgressIndicator::Start (aProgress));
0085 //! @endcode
0086 //!
0087 //! Example of usage in sequential process:
0088 //!
0089 //! @code{.cpp}
0090 //!   Message_ProgressScope aWholePS(aRange, "Whole process", 100);
0091 //!
0092 //!   // do one step taking 20%
0093 //!   func1 (aWholePS.Next (20)); // func1 will take 20% of the whole scope
0094 //!   if (aWholePS.UserBreak()) // exit prematurely if the user requested break
0095 //!     return;
0096 //!
0097 //!   // ... do next step taking 50%
0098 //!   func2 (aWholePS.Next (50));
0099 //!   if (aWholePS.UserBreak())
0100 //!     return;
0101 //! @endcode
0102 //!
0103 //! Example of usage in nested cycle:
0104 //!
0105 //! @code{.cpp}
0106 //!   // Outer cycle
0107 //!   Message_ProgressScope anOuter (theProgress, "Outer", nbOuter);
0108 //!   for (Standard_Integer i = 0; i < nbOuter && anOuter.More(); i++)
0109 //!   {
0110 //!     // Inner cycle
0111 //!     Message_ProgressScope anInner (anOuter.Next(), "Inner", nbInner);
0112 //!     for (Standard_Integer j = 0; j < nbInner && anInner.More(); j++)
0113 //!     {
0114 //!       // Cycle body
0115 //!       func (anInner.Next());
0116 //!     }
0117 //!   }
0118 //! @endcode
0119 //!
0120 //! Example of use in function:
0121 //!
0122 //! @code{.cpp}
0123 //! //! Implementation of iterative algorithm showing its progress
0124 //! func (const Message_ProgressRange& theProgress)
0125 //! {
0126 //!   // Create local scope covering the given progress range.
0127 //!   // Set this scope to count aNbSteps steps.
0128 //!   Message_ProgressScope aScope (theProgress, "", aNbSteps);
0129 //!   for (Standard_Integer i = 0; i < aNbSteps && aScope.More(); i++)
0130 //!   {
0131 //!     // Optional: pass range returned by method Next() to the nested algorithm
0132 //!     // to allow it to show its progress too (by creating its own scope object).
0133 //!     // In any case the progress will advance to the next step by the end of the func2 call.
0134 //!     func2 (aScope.Next());
0135 //!   }
0136 //! }
0137 //! @endcode
0138 //!
0139 //! Example of usage in parallel process:
0140 //!
0141 //! @code{.cpp}
0142 //! struct Task
0143 //! {
0144 //!   Data& Data;
0145 //!   Message_ProgressRange Range;
0146 //!
0147 //!   Task (const Data& theData, const Message_ProgressRange& theRange)
0148 //!     : Data (theData), Range (theRange) {}
0149 //! };
0150 //! struct Functor
0151 //! {
0152 //!   void operator() (Task& theTask) const
0153 //!   {
0154 //!     // Note: it is essential that this method is executed only once for the same Task object
0155 //!     Message_ProgressScope aPS (theTask.Range, NULL, theTask.Data.NbItems);
0156 //!     for (Standard_Integer i = 0; i < theTask.Data.NbSteps && aPS.More(); i++)
0157 //!     {
0158 //!       do_job (theTask.Data.Item[i], aPS.Next());
0159 //!     }
0160 //!   }
0161 //! };
0162 //! ...
0163 //! {
0164 //!   std::vector<Data> aData = ...;
0165 //!   std::vector<Task> aTasks;
0166 //!
0167 //!   Message_ProgressScope aPS (aRootRange, "Data processing", aData.size());
0168 //!   for (Standard_Integer i = 0; i < aData.size(); ++i)
0169 //!     aTasks.push_back (Task (aData[i], aPS.Next()));
0170 //!
0171 //!   OSD_Parallel::ForEach (aTasks.begin(), aTasks.end(), Functor());
0172 //! }
0173 //! @endcode
0174 //!
0175 //! For lightweight algorithms that do not need advancing the progress
0176 //! within individual tasks the code can be simplified to avoid inner scopes:
0177 //!
0178 //! @code
0179 //! struct Functor
0180 //! {
0181 //!   void operator() (Task& theTask) const
0182 //!   {
0183 //!     if (theTask.Range.More())
0184 //!     {
0185 //!       do_job (theTask.Data);
0186 //!       // advance the progress
0187 //!       theTask.Range.Close();
0188 //!     }
0189 //!   }
0190 //! };
0191 //! @endcode
0192 class Message_ProgressScope
0193 {
0194 public:
0195   class NullString; //!< auxiliary type for passing NULL name to Message_ProgressScope constructor
0196 public:             //! @name Preparation methods
0197   //! Creates dummy scope.
0198   //! It can be safely passed to algorithms; no progress indication will be done.
0199   Message_ProgressScope()
0200       : myProgress(0),
0201         myParent(0),
0202         myName(0),
0203         myStart(0.),
0204         myPortion(1.),
0205         myMax(1.),
0206         myValue(0.),
0207         myIsActive(false),
0208         myIsOwnName(false),
0209         myIsInfinite(false)
0210   {
0211   }
0212 
0213   //! Creates a new scope taking responsibility of the part of the progress
0214   //! scale described by theRange. The new scope has own range from 0 to
0215   //! theMax, which is mapped to the given range.
0216   //!
0217   //! The topmost scope is created and owned by Message_ProgressIndicator
0218   //! and its pointer is contained in the Message_ProgressRange returned by the Start() method of
0219   //! progress indicator.
0220   //!
0221   //! @param[in][out] theRange  range to fill (will be disarmed)
0222   //! @param[in] theName        new scope name
0223   //! @param[in] theMax         number of steps in scope
0224   //! @param[in] isInfinite     infinite flag
0225   Message_ProgressScope(const Message_ProgressRange&   theRange,
0226                         const TCollection_AsciiString& theName,
0227                         Standard_Real                  theMax,
0228                         Standard_Boolean               isInfinite = false);
0229 
0230   //! Creates a new scope taking responsibility of the part of the progress
0231   //! scale described by theRange. The new scope has own range from 0 to
0232   //! theMax, which is mapped to the given range.
0233   //!
0234   //! The topmost scope is created and owned by Message_ProgressIndicator
0235   //! and its pointer is contained in the Message_ProgressRange returned by the Start() method of
0236   //! progress indicator.
0237   //!
0238   //! @param[in][out] theRange  range to fill (will be disarmed)
0239   //! @param[in] theName        new scope name constant (will be stored by pointer with no deep
0240   //! copy)
0241   //! @param[in] theMax         number of steps in scope
0242   //! @param[in] isInfinite     infinite flag
0243   template <size_t N>
0244   Message_ProgressScope(const Message_ProgressRange& theRange,
0245                         const char (&theName)[N],
0246                         Standard_Real    theMax,
0247                         Standard_Boolean isInfinite = false);
0248 
0249   //! Creates a new scope taking responsibility of the part of the progress
0250   //! scale described by theRange. The new scope has own range from 0 to
0251   //! theMax, which is mapped to the given range.
0252   //!
0253   //! The topmost scope is created and owned by Message_ProgressIndicator
0254   //! and its pointer is contained in the Message_ProgressRange returned by the Start() method of
0255   //! progress indicator.
0256   //!
0257   //! @param[in][out] theRange  range to fill (will be disarmed)
0258   //! @param[in] theName        empty scope name (only NULL is accepted as argument)
0259   //! @param[in] theMax         number of steps in scope
0260   //! @param[in] isInfinite     infinite flag
0261   Message_ProgressScope(const Message_ProgressRange& theRange,
0262                         const NullString*            theName,
0263                         Standard_Real                theMax,
0264                         Standard_Boolean             isInfinite = false);
0265 
0266   //! Sets the name of the scope.
0267   void SetName(const TCollection_AsciiString& theName)
0268   {
0269     if (myIsOwnName)
0270     {
0271       Standard::Free(myName);
0272       myIsOwnName = false;
0273     }
0274     myName = NULL;
0275     if (!theName.IsEmpty())
0276     {
0277       myIsOwnName = true;
0278       myName = (char*)Standard::AllocateOptimal(Standard_Size(theName.Length()) + Standard_Size(1));
0279       char* aName = (char*)myName;
0280       memcpy(aName, theName.ToCString(), theName.Length());
0281       aName[theName.Length()] = '\0';
0282     }
0283   }
0284 
0285   //! Sets the name of the scope; can be null.
0286   //! Note! Just pointer to the given string is copied,
0287   //! so do not pass string from a temporary variable whose
0288   //! lifetime is less than that of this object.
0289   template <size_t N>
0290   void SetName(const char (&theName)[N])
0291   {
0292     if (myIsOwnName)
0293     {
0294       Standard::Free(myName);
0295       myIsOwnName = false;
0296     }
0297     myName = theName;
0298   }
0299 
0300 public: //! @name Advance by iterations
0301   //! Returns true if ProgressIndicator signals UserBreak
0302   Standard_Boolean UserBreak() const;
0303 
0304   //! Returns false if ProgressIndicator signals UserBreak
0305   Standard_Boolean More() const { return !UserBreak(); }
0306 
0307   //! Advances position by specified step and returns the range
0308   //! covering this step
0309   Message_ProgressRange Next(Standard_Real theStep = 1.);
0310 
0311 public: //! @name Auxiliary methods to use in ProgressIndicator
0312   //! Force update of presentation of the progress indicator.
0313   //! Should not be called concurrently.
0314   void Show();
0315 
0316   //! Returns true if this progress scope is attached to some indicator.
0317   Standard_Boolean IsActive() const { return myIsActive; }
0318 
0319   //! Returns the name of the scope (may be null).
0320   //! Scopes with null name (e.g. root scope) should
0321   //! be bypassed when reporting progress to the user.
0322   Standard_CString Name() const { return myName; }
0323 
0324   //! Returns parent scope (null for top-level scope)
0325   const Message_ProgressScope* Parent() const { return myParent; }
0326 
0327   //! Returns the maximal value of progress in this scope
0328   Standard_Real MaxValue() const { return myMax; }
0329 
0330   //! Returns the current value of progress in this scope.
0331   //!
0332   //! The value is computed by mapping current global progress into
0333   //! this scope range; the result is rounded up to integer.
0334   //! Note that if MaxValue() is not an integer, Value() can be
0335   //! greater than MaxValue() due to that rounding.
0336   //!
0337   //! This method should not be called concurrently while the progress
0338   //! is advancing, except from implementation of method Show() in
0339   //! descendant of Message_ProgressIndicator.
0340   Standard_Real Value() const;
0341 
0342   //! Returns the infinite flag
0343   Standard_Boolean IsInfinite() const { return myIsInfinite; }
0344 
0345   //! Get the portion of the indicator covered by this scope (from 0 to 1)
0346   Standard_Real GetPortion() const { return myPortion; }
0347 
0348 public: //! @name Destruction, allocation
0349   //! Destructor - closes the scope and adds its scale to the total progress
0350   ~Message_ProgressScope()
0351   {
0352     Close();
0353     if (myIsOwnName)
0354     {
0355       Standard::Free(myName);
0356       myIsOwnName = false;
0357       myName      = NULL;
0358     }
0359   }
0360 
0361   //! Closes the scope and advances the progress to its end.
0362   //! Closed scope should not be used.
0363   void Close();
0364 
0365   DEFINE_STANDARD_ALLOC
0366 
0367 private: //! @name Internal methods
0368   //! Creates a top-level scope with default range [0,1] and step 1.
0369   //! Called only by Message_ProgressIndicator constructor.
0370   Message_ProgressScope(Message_ProgressIndicator* theProgress);
0371 
0372   //! Convert value from this scope to global scale, but disregarding
0373   //! start position of the scope, in the range [0, myPortion]
0374   Standard_Real localToGlobal(const Standard_Real theVal) const;
0375 
0376 private:
0377   //! Copy constructor is prohibited
0378   Message_ProgressScope(const Message_ProgressScope& theOther);
0379 
0380   //! Copy assignment is prohibited
0381   Message_ProgressScope& operator=(const Message_ProgressScope& theOther);
0382 
0383 private:
0384   Message_ProgressIndicator*   myProgress; //!< Pointer to progress indicator instance
0385   const Message_ProgressScope* myParent;   //!< Pointer to parent scope
0386   Standard_CString             myName; //!< Name of the operation being done in this scope, or null
0387 
0388   Standard_Real myStart;  //!< Start position on the global scale [0, 1]
0389                           // clang-format off
0390   Standard_Real      myPortion;     //!< The portion of the global scale covered by this scope [0, 1]
0391                           // clang-format on
0392 
0393   Standard_Real myMax;   //!< Maximal value of progress in this scope
0394   Standard_Real myValue; //!< Current position advanced within this scope [0, Max]
0395 
0396   Standard_Boolean myIsActive;   //!< flag indicating armed/disarmed state
0397   Standard_Boolean myIsOwnName;  //!< flag indicating if name was allocated or not
0398   Standard_Boolean myIsInfinite; //!< Option to advance by hyperbolic law
0399 
0400 private:
0401   friend class Message_ProgressIndicator;
0402   friend class Message_ProgressRange;
0403 };
0404 
0405 #include <Message_ProgressRange.hxx>
0406 
0407 //=======================================================================
0408 // function : Message_ProgressScope
0409 // purpose  :
0410 //=======================================================================
0411 inline Message_ProgressScope::Message_ProgressScope(Message_ProgressIndicator* theProgress)
0412     : myProgress(theProgress),
0413       myParent(0),
0414       myName(0),
0415       myStart(0.),
0416       myPortion(1.),
0417       myMax(1.),
0418       myValue(0.),
0419       myIsActive(theProgress != NULL),
0420       myIsOwnName(false),
0421       myIsInfinite(false)
0422 {
0423 }
0424 
0425 //=======================================================================
0426 // function : Message_ProgressScope
0427 // purpose  :
0428 //=======================================================================
0429 inline Message_ProgressScope::Message_ProgressScope(const Message_ProgressRange&   theRange,
0430                                                     const TCollection_AsciiString& theName,
0431                                                     Standard_Real                  theMax,
0432                                                     Standard_Boolean               isInfinite)
0433     : myProgress(theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
0434       myParent(theRange.myParentScope),
0435       myName(NULL),
0436       myStart(theRange.myStart),
0437       myPortion(theRange.myDelta),
0438       myMax(Max(1.e-6, theMax)), // protection against zero range
0439       myValue(0.),
0440       myIsActive(myProgress != NULL && !theRange.myWasUsed),
0441       myIsOwnName(false),
0442       myIsInfinite(isInfinite)
0443 {
0444   SetName(theName);
0445   Standard_ASSERT_VOID(!theRange.myWasUsed,
0446                        "Message_ProgressRange is used to initialize more than one scope");
0447   theRange.myWasUsed = true; // Disarm the range
0448 }
0449 
0450 //=======================================================================
0451 // function : Message_ProgressScope
0452 // purpose  :
0453 //=======================================================================
0454 template <size_t N>
0455 Message_ProgressScope::Message_ProgressScope(const Message_ProgressRange& theRange,
0456                                              const char (&theName)[N],
0457                                              Standard_Real    theMax,
0458                                              Standard_Boolean isInfinite)
0459     : myProgress(theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
0460       myParent(theRange.myParentScope),
0461       myName(theName),
0462       myStart(theRange.myStart),
0463       myPortion(theRange.myDelta),
0464       myMax(Max(1.e-6, theMax)), // protection against zero range
0465       myValue(0.),
0466       myIsActive(myProgress != NULL && !theRange.myWasUsed),
0467       myIsOwnName(false),
0468       myIsInfinite(isInfinite)
0469 {
0470   Standard_ASSERT_VOID(!theRange.myWasUsed,
0471                        "Message_ProgressRange is used to initialize more than one scope");
0472   theRange.myWasUsed = true; // Disarm the range
0473 }
0474 
0475 //=======================================================================
0476 // function : Message_ProgressScope
0477 // purpose  :
0478 //=======================================================================
0479 inline Message_ProgressScope::Message_ProgressScope(const Message_ProgressRange& theRange,
0480                                                     const NullString*,
0481                                                     Standard_Real    theMax,
0482                                                     Standard_Boolean isInfinite)
0483     : myProgress(theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
0484       myParent(theRange.myParentScope),
0485       myName(NULL),
0486       myStart(theRange.myStart),
0487       myPortion(theRange.myDelta),
0488       myMax(Max(1.e-6, theMax)), // protection against zero range
0489       myValue(0.),
0490       myIsActive(myProgress != NULL && !theRange.myWasUsed),
0491       myIsOwnName(false),
0492       myIsInfinite(isInfinite)
0493 {
0494   Standard_ASSERT_VOID(!theRange.myWasUsed,
0495                        "Message_ProgressRange is used to initialize more than one scope");
0496   theRange.myWasUsed = true; // Disarm the range
0497 }
0498 
0499 //=======================================================================
0500 // function : Close
0501 // purpose  :
0502 //=======================================================================
0503 inline void Message_ProgressScope::Close()
0504 {
0505   if (!myIsActive)
0506   {
0507     return;
0508   }
0509 
0510   // Advance indicator to the end of the scope
0511   Standard_Real aCurr  = localToGlobal(myValue);
0512   myValue              = (myIsInfinite ? Precision::Infinite() : myMax);
0513   Standard_Real aDelta = myPortion - aCurr;
0514   if (aDelta > 0.)
0515   {
0516     myProgress->Increment(aDelta, *this);
0517   }
0518   Standard_ASSERT_VOID(myParent == 0 || myParent->myIsActive,
0519                        "Parent progress scope has been closed before child");
0520 
0521   myIsActive = false;
0522 }
0523 
0524 //=======================================================================
0525 // function : UserBreak
0526 // purpose  :
0527 //=======================================================================
0528 inline Standard_Boolean Message_ProgressScope::UserBreak() const
0529 {
0530   return myProgress && myProgress->UserBreak();
0531 }
0532 
0533 //=======================================================================
0534 // function : Next
0535 // purpose  :
0536 //=======================================================================
0537 inline Message_ProgressRange Message_ProgressScope::Next(Standard_Real theStep)
0538 {
0539   if (myIsActive && theStep > 0.)
0540   {
0541     Standard_Real aCurr  = localToGlobal(myValue);
0542     Standard_Real aNext  = localToGlobal(myValue += theStep);
0543     Standard_Real aDelta = aNext - aCurr;
0544     if (aDelta > 0.)
0545     {
0546       return Message_ProgressRange(*this, myStart + aCurr, aDelta);
0547     }
0548   }
0549   return Message_ProgressRange();
0550 }
0551 
0552 //=======================================================================
0553 // function : Show
0554 // purpose  :
0555 //=======================================================================
0556 
0557 inline void Message_ProgressScope::Show()
0558 {
0559   if (myIsActive)
0560   {
0561     myProgress->Show(*this, Standard_True);
0562   }
0563 }
0564 
0565 //=======================================================================
0566 // function : localToGlobal
0567 // purpose  :
0568 //=======================================================================
0569 inline Standard_Real Message_ProgressScope::localToGlobal(const Standard_Real theVal) const
0570 {
0571   if (theVal <= 0.)
0572     return 0.;
0573 
0574   if (!myIsInfinite)
0575   {
0576     if (myMax - theVal < RealSmall())
0577       return myPortion;
0578     return myPortion * theVal / myMax;
0579   }
0580 
0581   double x = theVal / myMax;
0582   // return myPortion * ( 1. - std::exp ( -x ) ); // exponent
0583   return myPortion * x / (1. + x); // hyperbola
0584 }
0585 
0586 //=======================================================================
0587 // function : Value
0588 // purpose  :
0589 //=======================================================================
0590 
0591 inline Standard_Real Message_ProgressScope::Value() const
0592 {
0593   if (!myIsActive)
0594   {
0595     return myIsInfinite ? Precision::Infinite() : myMax;
0596   }
0597 
0598   // get current progress on the global scale counted
0599   // from the start of this scope
0600   Standard_Real aVal = myProgress->GetPosition() - myStart;
0601 
0602   // if progress has not reached yet the start of this scope, return 0
0603   if (aVal <= 0.)
0604     return 0.;
0605 
0606   // if at end of the scope (or behind), report the maximum
0607   Standard_Real aDist = myPortion - aVal;
0608   if (aDist <= Precision::Confusion())
0609     return myIsInfinite ? Precision::Infinite() : myMax;
0610 
0611   // map the value to the range of this scope [0, Max],
0612   // rounding up to integer, with small correction applied
0613   // to avoid rounding errors
0614   return std::ceil(myMax * aVal / (myIsInfinite ? aDist : myPortion) - Precision::Confusion());
0615 }
0616 
0617 #endif // _Message_ProgressScope_HeaderFile