Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:17

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 
0198   //! Creates dummy scope.
0199   //! It can be safely passed to algorithms; no progress indication will be done.
0200   Message_ProgressScope()
0201   : myProgress (0),
0202     myParent (0),
0203     myName (0),
0204     myStart (0.),
0205     myPortion (1.),
0206     myMax (1.),
0207     myValue (0.),
0208     myIsActive (false),
0209     myIsOwnName (false),
0210     myIsInfinite (false)
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 progress indicator.
0219   //!
0220   //! @param theRange [in][out] range to fill (will be disarmed)
0221   //! @param theName  [in]      new scope name
0222   //! @param theMax   [in]      number of steps in scope
0223   //! @param isInfinite [in]    infinite flag
0224   Message_ProgressScope (const Message_ProgressRange& theRange,
0225                          const TCollection_AsciiString& theName,
0226                          Standard_Real theMax,
0227                          Standard_Boolean isInfinite = false);
0228 
0229   //! Creates a new scope taking responsibility of the part of the progress 
0230   //! scale described by theRange. The new scope has own range from 0 to 
0231   //! theMax, which is mapped to the given range.
0232   //!
0233   //! The topmost scope is created and owned by Message_ProgressIndicator
0234   //! and its pointer is contained in the Message_ProgressRange returned by the Start() method of progress indicator.
0235   //!
0236   //! @param theRange [in][out] range to fill (will be disarmed)
0237   //! @param theName  [in]      new scope name constant (will be stored by pointer with no deep copy)
0238   //! @param theMax   [in]      number of steps in scope
0239   //! @param isInfinite [in]    infinite flag
0240   template<size_t N>
0241   Message_ProgressScope (const Message_ProgressRange& theRange,
0242                          const char (&theName)[N],
0243                          Standard_Real theMax,
0244                          Standard_Boolean isInfinite = false);
0245 
0246   //! Creates a new scope taking responsibility of the part of the progress 
0247   //! scale described by theRange. The new scope has own range from 0 to 
0248   //! theMax, which is mapped to the given range.
0249   //!
0250   //! The topmost scope is created and owned by Message_ProgressIndicator
0251   //! and its pointer is contained in the Message_ProgressRange returned by the Start() method of progress indicator.
0252   //!
0253   //! @param theRange [in][out] range to fill (will be disarmed)
0254   //! @param theName  [in]      empty scope name (only NULL is accepted as argument)
0255   //! @param theMax   [in]      number of steps in scope
0256   //! @param isInfinite [in]    infinite flag
0257   Message_ProgressScope (const Message_ProgressRange& theRange,
0258                          const NullString* theName,
0259                          Standard_Real theMax,
0260                          Standard_Boolean isInfinite = false);
0261 
0262   //! Sets the name of the scope.
0263   void SetName (const TCollection_AsciiString& theName)
0264   {
0265     if (myIsOwnName)
0266     {
0267       Standard::Free (myName);
0268       myIsOwnName = false;
0269     }
0270     myName = NULL;
0271     if (!theName.IsEmpty())
0272     {
0273       myIsOwnName = true;
0274       myName = (char* )Standard::AllocateOptimal(Standard_Size(theName.Length()) + Standard_Size(1));
0275       char* aName = (char* )myName;
0276       memcpy (aName, theName.ToCString(), theName.Length());
0277       aName[theName.Length()] = '\0';
0278     }
0279   }
0280 
0281   //! Sets the name of the scope; can be null.
0282   //! Note! Just pointer to the given string is copied,
0283   //! so do not pass string from a temporary variable whose
0284   //! lifetime is less than that of this object.
0285   template<size_t N>
0286   void SetName (const char (&theName)[N])
0287   {
0288     if (myIsOwnName)
0289     {
0290       Standard::Free (myName);
0291       myIsOwnName = false;
0292     }
0293     myName = theName;
0294   }
0295 
0296 public: //! @name Advance by iterations
0297 
0298   //! Returns true if ProgressIndicator signals UserBreak
0299   Standard_Boolean UserBreak() const;
0300 
0301   //! Returns false if ProgressIndicator signals UserBreak
0302   Standard_Boolean More() const
0303   {
0304     return !UserBreak();
0305   }
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 
0313   //! Force update of presentation of the progress indicator.
0314   //! Should not be called concurrently.
0315   void Show();
0316 
0317   //! Returns true if this progress scope is attached to some indicator.
0318   Standard_Boolean IsActive() const
0319   {
0320     return myIsActive;
0321   }
0322 
0323   //! Returns the name of the scope (may be null).
0324   //! Scopes with null name (e.g. root scope) should
0325   //! be bypassed when reporting progress to the user.
0326   Standard_CString Name() const
0327   {
0328     return myName;
0329   }
0330 
0331   //! Returns parent scope (null for top-level scope)
0332   const Message_ProgressScope* Parent() const
0333   {
0334     return myParent;
0335   }
0336 
0337   //! Returns the maximal value of progress in this scope
0338   Standard_Real MaxValue() const
0339   {
0340     return myMax;
0341   }
0342 
0343   //! Returns the current value of progress in this scope.
0344   //!
0345   //! The value is computed by mapping current global progress into 
0346   //! this scope range; the result is rounded up to integer.
0347   //! Note that if MaxValue() is not an integer, Value() can be 
0348   //! greater than MaxValue() due to that rounding.
0349   //!
0350   //! This method should not be called concurrently while the progress
0351   //! is advancing, except from implementation of method Show() in
0352   //! descendant of Message_ProgressIndicator.
0353   Standard_Real Value() const;
0354 
0355   //! Returns the infinite flag
0356   Standard_Boolean IsInfinite() const
0357   {
0358     return myIsInfinite;
0359   }
0360 
0361   //! Get the portion of the indicator covered by this scope (from 0 to 1)
0362   Standard_Real GetPortion() const
0363   {
0364     return myPortion;
0365   }
0366 
0367 public: //! @name Destruction, allocation
0368 
0369   //! Destructor - closes the scope and adds its scale to the total progress
0370   ~Message_ProgressScope()
0371   {
0372     Close();
0373     if (myIsOwnName)
0374     {
0375       Standard::Free (myName);
0376       myIsOwnName = false;
0377       myName = NULL;
0378     }
0379   }
0380 
0381   //! Closes the scope and advances the progress to its end.
0382   //! Closed scope should not be used.
0383   void Close();
0384 
0385   DEFINE_STANDARD_ALLOC
0386 
0387 private: //! @name Internal methods
0388   
0389   //! Creates a top-level scope with default range [0,1] and step 1.
0390   //! Called only by Message_ProgressIndicator constructor.
0391   Message_ProgressScope (Message_ProgressIndicator* theProgress);
0392 
0393   //! Convert value from this scope to global scale, but disregarding
0394   //! start position of the scope, in the range [0, myPortion]
0395   Standard_Real localToGlobal(const Standard_Real theVal) const;
0396 
0397 private:
0398   //! Copy constructor is prohibited
0399   Message_ProgressScope (const Message_ProgressScope& theOther);
0400 
0401   //! Copy assignment is prohibited
0402   Message_ProgressScope& operator= (const Message_ProgressScope& theOther);
0403 
0404 private:
0405 
0406   Message_ProgressIndicator* myProgress; //!< Pointer to progress indicator instance
0407   const Message_ProgressScope* myParent; //!< Pointer to parent scope
0408   Standard_CString   myName;        //!< Name of the operation being done in this scope, or null
0409 
0410   Standard_Real      myStart;       //!< Start position on the global scale [0, 1]
0411   Standard_Real      myPortion;     //!< The portion of the global scale covered by this scope [0, 1]
0412 
0413   Standard_Real      myMax;         //!< Maximal value of progress in this scope
0414   Standard_Real      myValue;       //!< Current position advanced within this scope [0, Max]
0415 
0416   Standard_Boolean   myIsActive;    //!< flag indicating armed/disarmed state
0417   Standard_Boolean   myIsOwnName;   //!< flag indicating if name was allocated or not
0418   Standard_Boolean   myIsInfinite;  //!< Option to advance by hyperbolic law
0419 
0420 private:
0421   friend class Message_ProgressIndicator;
0422   friend class Message_ProgressRange;
0423 };
0424 
0425 #include <Message_ProgressRange.hxx>
0426 
0427 //=======================================================================
0428 //function : Message_ProgressScope
0429 //purpose  :
0430 //=======================================================================
0431 inline Message_ProgressScope::Message_ProgressScope (Message_ProgressIndicator* theProgress)
0432 : myProgress(theProgress),
0433   myParent(0),
0434   myName(0),
0435   myStart(0.),
0436   myPortion(1.),
0437   myMax(1.),
0438   myValue(0.),
0439   myIsActive(theProgress != NULL),
0440   myIsOwnName(false),
0441   myIsInfinite(false)
0442 {
0443 }
0444 
0445 //=======================================================================
0446 //function : Message_ProgressScope
0447 //purpose  :
0448 //=======================================================================
0449 inline Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange& theRange,
0450                                                      const TCollection_AsciiString& theName,
0451                                                      Standard_Real theMax,
0452                                                      Standard_Boolean isInfinite)
0453 : myProgress (theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
0454   myParent (theRange.myParentScope),
0455   myName (NULL),
0456   myStart (theRange.myStart),
0457   myPortion (theRange.myDelta),
0458   myMax (Max (1.e-6, theMax)), // protection against zero range
0459   myValue (0.),
0460   myIsActive (myProgress != NULL && !theRange.myWasUsed),
0461   myIsOwnName (false),
0462   myIsInfinite (isInfinite)
0463 {
0464   SetName (theName);
0465   Standard_ASSERT_VOID (! theRange.myWasUsed, "Message_ProgressRange is used to initialize more than one scope");
0466   theRange.myWasUsed = true; // Disarm the range
0467 }
0468 
0469 //=======================================================================
0470 //function : Message_ProgressScope
0471 //purpose  :
0472 //=======================================================================
0473 template<size_t N>
0474 Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange& theRange,
0475                                               const char (&theName)[N],
0476                                               Standard_Real theMax,
0477                                               Standard_Boolean isInfinite)
0478 : myProgress (theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
0479   myParent (theRange.myParentScope),
0480   myName (theName),
0481   myStart (theRange.myStart),
0482   myPortion (theRange.myDelta),
0483   myMax (Max (1.e-6, theMax)), // protection against zero range
0484   myValue (0.),
0485   myIsActive (myProgress != NULL && !theRange.myWasUsed),
0486   myIsOwnName (false),
0487   myIsInfinite (isInfinite)
0488 {
0489   Standard_ASSERT_VOID (! theRange.myWasUsed, "Message_ProgressRange is used to initialize more than one scope");
0490   theRange.myWasUsed = true; // Disarm the range
0491 }
0492 
0493 //=======================================================================
0494 //function : Message_ProgressScope
0495 //purpose  :
0496 //=======================================================================
0497 inline Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange& theRange,
0498                                                      const NullString* ,
0499                                                      Standard_Real theMax,
0500                                                      Standard_Boolean isInfinite)
0501 : myProgress (theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
0502   myParent (theRange.myParentScope),
0503   myName (NULL),
0504   myStart (theRange.myStart),
0505   myPortion (theRange.myDelta),
0506   myMax (Max (1.e-6, theMax)), // protection against zero range
0507   myValue (0.),
0508   myIsActive (myProgress != NULL && !theRange.myWasUsed),
0509   myIsOwnName (false),
0510   myIsInfinite (isInfinite)
0511 {
0512   Standard_ASSERT_VOID (! theRange.myWasUsed, "Message_ProgressRange is used to initialize more than one scope");
0513   theRange.myWasUsed = true; // Disarm the range
0514 }
0515 
0516 //=======================================================================
0517 //function : Close
0518 //purpose  :
0519 //=======================================================================
0520 inline void Message_ProgressScope::Close()
0521 {
0522   if (!myIsActive)
0523   {
0524     return;
0525   }
0526 
0527   // Advance indicator to the end of the scope
0528   Standard_Real aCurr = localToGlobal (myValue);
0529   myValue = (myIsInfinite ? Precision::Infinite() : myMax);
0530   Standard_Real aDelta = myPortion - aCurr;
0531   if (aDelta > 0.)
0532   {
0533     myProgress->Increment (aDelta, *this);
0534   }
0535   Standard_ASSERT_VOID (myParent == 0 || myParent->myIsActive,
0536     "Parent progress scope has been closed before child");
0537 
0538   myIsActive = false;
0539 }
0540 
0541 //=======================================================================
0542 //function : UserBreak
0543 //purpose  :
0544 //=======================================================================
0545 inline Standard_Boolean Message_ProgressScope::UserBreak() const
0546 {
0547   return myProgress && myProgress->UserBreak();
0548 }
0549 
0550 //=======================================================================
0551 //function : Next
0552 //purpose  :
0553 //=======================================================================
0554 inline Message_ProgressRange Message_ProgressScope::Next (Standard_Real theStep)
0555 {
0556   if (myIsActive && theStep > 0.)
0557   {
0558     Standard_Real aCurr = localToGlobal(myValue);
0559     Standard_Real aNext = localToGlobal(myValue += theStep);
0560     Standard_Real aDelta = aNext - aCurr;
0561     if (aDelta > 0.)
0562     {
0563       return Message_ProgressRange(*this, myStart + aCurr, aDelta);
0564     }
0565   }
0566   return Message_ProgressRange();
0567 }
0568 
0569 //=======================================================================
0570 //function : Show
0571 //purpose  :
0572 //=======================================================================
0573 
0574 inline void Message_ProgressScope::Show ()
0575 {
0576   if (myIsActive)
0577   {
0578     myProgress->Show (*this, Standard_True);
0579   }
0580 }
0581 
0582 //=======================================================================
0583 //function : localToGlobal
0584 //purpose  :
0585 //=======================================================================
0586 inline Standard_Real Message_ProgressScope::localToGlobal (const Standard_Real theVal) const
0587 {
0588   if (theVal <= 0.)
0589     return 0.;
0590 
0591   if (!myIsInfinite)
0592   {
0593     if (myMax - theVal < RealSmall())
0594       return myPortion;
0595     return myPortion * theVal / myMax;
0596   }
0597 
0598   double x = theVal / myMax;
0599   // return myPortion * ( 1. - std::exp ( -x ) ); // exponent
0600   return myPortion * x / (1. + x);  // hyperbola
0601 }
0602 
0603 //=======================================================================
0604 //function : Value
0605 //purpose  :
0606 //=======================================================================
0607 
0608 inline Standard_Real Message_ProgressScope::Value () const
0609 {
0610   if (!myIsActive)
0611   {
0612     return myIsInfinite ? Precision::Infinite() : myMax;
0613   }
0614 
0615   // get current progress on the global scale counted 
0616   // from the start of this scope
0617   Standard_Real aVal = myProgress->GetPosition() - myStart;
0618 
0619   // if progress has not reached yet the start of this scope, return 0
0620   if (aVal <= 0.)
0621     return 0.;
0622 
0623   // if at end of the scope (or behind), report the maximum
0624   Standard_Real aDist = myPortion - aVal;
0625   if (aDist <= Precision::Confusion())
0626     return myIsInfinite ? Precision::Infinite() : myMax;
0627 
0628   // map the value to the range of this scope [0, Max],
0629   // rounding up to integer, with small correction applied
0630   // to avoid rounding errors
0631   return std::ceil (myMax * aVal / (myIsInfinite ? aDist : myPortion) - Precision::Confusion());
0632 }
0633 
0634 #endif // _Message_ProgressScope_HeaderFile