1 #ifndef SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
2 #define SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
3 
4 /* -------------------------------------------------------------------------- *
5  *                       Simbody(tm): SimTKcommon                             *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from           *
8  * Simbios, the NIH National Center for Physics-Based Simulation of           *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
11  *                                                                            *
12  * Portions copyright (c) 2008-14 Stanford University and the Authors.        *
13  * Authors: Michael Sherman                                                   *
14  * Contributors:                                                              *
15  *                                                                            *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
17  * not use this file except in compliance with the License. You may obtain a  *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
19  *                                                                            *
20  * Unless required by applicable law or agreed to in writing, software        *
21  * distributed under the License is distributed on an "AS IS" BASIS,          *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
23  * See the License for the specific language governing permissions and        *
24  * limitations under the License.                                             *
25  * -------------------------------------------------------------------------- */
26 
27 #include "SimTKcommon/basics.h"
28 #include "SimTKcommon/Simmatrix.h"
29 #include "SimTKcommon/internal/State.h"
30 #include "SimTKcommon/internal/Measure.h"
31 #include "SimTKcommon/internal/Subsystem.h"
32 #include "SimTKcommon/internal/System.h"
33 #include "SimTKcommon/internal/SubsystemGuts.h"
34 
35 #include <cmath>
36 
37 
38 namespace SimTK {
39 
40 
41 //==============================================================================
42 //                    ABSTRACT MEASURE :: IMPLEMENTATION
43 //==============================================================================
44 
45 /**
46  * The abstract parent of all Measure Implementation classes.
47  */
48 class SimTK_SimTKCOMMON_EXPORT AbstractMeasure::Implementation {
49 protected:
50     /** This default constructor is for use by concrete measure implementation
51     classes. **/
Implementation()52     Implementation() : copyNumber(0), mySubsystem(0), refCount(0) {}
53 
54     /** Base class copy constructor removes the Subsystem
55     and sets the reference count to zero. This gets used by the clone()
56     methods in the concrete classes. **/
Implementation(const Implementation & src)57     Implementation(const Implementation& src)
58     :   copyNumber(src.copyNumber+1), mySubsystem(0), refCount(0) {}
59 
60     /** Base class copy assignment operator removes the
61     Subsystem, and sets the reference count to zero. This is probably
62     not used. **/
63     Implementation& operator=(const Implementation& src) {
64         if (&src != this)
65         {   copyNumber=src.copyNumber+1;
66             refCount=0; mySubsystem=0; }
67         return *this;
68     }
69 
70     // destructor is virtual; below
71 
72     // Increment the reference count and return its new value.
incrRefCount()73     int incrRefCount() const {return ++refCount;}
74 
75     // Decrement the reference count and return its new value.
decrRefCount()76     int decrRefCount() const {return --refCount;}
77 
78     // Get the current value of the reference counter.
getRefCount()79     int getRefCount() const {return refCount;}
80 
getCopyNumber()81     int           getCopyNumber()  const {return copyNumber;}
82 
83     /** This is a deep copy of the concrete Implementation object, except the
84     Subsystem will have been removed. The reference count on the new object
85     will be zero; be sure to increment it if you put it in a handle. **/
clone()86     Implementation* clone() const {return cloneVirtual();}
87 
88     // realizeTopology() is pure virtual below for Measure_<T> to supply.
realizeModel(State & s)89     void realizeModel       (State& s)       const {realizeMeasureModelVirtual(s);}
realizeInstance(const State & s)90     void realizeInstance    (const State& s) const {realizeMeasureInstanceVirtual(s);}
realizeTime(const State & s)91     void realizeTime        (const State& s) const {realizeMeasureTimeVirtual(s);}
realizePosition(const State & s)92     void realizePosition    (const State& s) const {realizeMeasurePositionVirtual(s);}
realizeVelocity(const State & s)93     void realizeVelocity    (const State& s) const {realizeMeasureVelocityVirtual(s);}
realizeDynamics(const State & s)94     void realizeDynamics    (const State& s) const {realizeMeasureDynamicsVirtual(s);}
realizeAcceleration(const State & s)95     void realizeAcceleration(const State& s) const {realizeMeasureAccelerationVirtual(s);}
realizeReport(const State & s)96     void realizeReport      (const State& s) const {realizeMeasureReportVirtual(s);}
97 
98     /** This should be called at the start of a time stepping study to
99     cause this %Measure to set its state variables (if any) in the supplied
100     state to their initial conditions. **/
initialize(State & s)101     void initialize(State& s) const {initializeVirtual(s);}
102 
getNumTimeDerivatives()103     int getNumTimeDerivatives() const {return getNumTimeDerivativesVirtual();}
104 
getDependsOnStage(int derivOrder)105     Stage getDependsOnStage(int derivOrder) const {
106         SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(),
107             "Measure::getDependsOnStage()",
108             "derivOrder %d was out of range; this Measure allows 0-%d.",
109             derivOrder, getNumTimeDerivatives());
110         return getDependsOnStageVirtual(derivOrder);
111     }
112 
113 
setSubsystem(Subsystem & sub,MeasureIndex mx)114     void setSubsystem(Subsystem& sub, MeasureIndex mx)
115     {   assert(!mySubsystem && mx.isValid());
116         mySubsystem = &sub; myIndex = mx; }
117 
isInSubsystem()118     bool             isInSubsystem() const {return mySubsystem != 0;}
getSubsystem()119     const Subsystem& getSubsystem() const {assert(mySubsystem); return *mySubsystem;}
updSubsystem()120     Subsystem&       updSubsystem() {assert(mySubsystem); return *mySubsystem;}
getSubsystemMeasureIndex()121     MeasureIndex     getSubsystemMeasureIndex() const {assert(mySubsystem); return myIndex;}
getSubsystemIndex()122     SubsystemIndex   getSubsystemIndex() const
123     {   return getSubsystem().getMySubsystemIndex(); }
124 
invalidateTopologyCache()125     void invalidateTopologyCache() const
126     {   if (isInSubsystem()) getSubsystem().invalidateSubsystemTopologyCache(); }
127 
getStage(const State & s)128     Stage getStage(const State& s) const {return getSubsystem().getStage(s);}
129 
130     // VIRTUALS //
131 
~Implementation()132     virtual ~Implementation() {}
133     virtual Implementation* cloneVirtual() const = 0;
134 
135     virtual void realizeTopology(State&)const = 0;
136 
realizeMeasureModelVirtual(State &)137     virtual void realizeMeasureModelVirtual(State&) const {}
realizeMeasureInstanceVirtual(const State &)138     virtual void realizeMeasureInstanceVirtual(const State&) const {}
realizeMeasureTimeVirtual(const State &)139     virtual void realizeMeasureTimeVirtual(const State&) const {}
realizeMeasurePositionVirtual(const State &)140     virtual void realizeMeasurePositionVirtual(const State&) const {}
realizeMeasureVelocityVirtual(const State &)141     virtual void realizeMeasureVelocityVirtual(const State&) const {}
realizeMeasureDynamicsVirtual(const State &)142     virtual void realizeMeasureDynamicsVirtual(const State&) const {}
realizeMeasureAccelerationVirtual(const State &)143     virtual void realizeMeasureAccelerationVirtual(const State&) const {}
realizeMeasureReportVirtual(const State &)144     virtual void realizeMeasureReportVirtual(const State&) const {}
145 
initializeVirtual(State &)146     virtual void  initializeVirtual(State&) const {}
getNumTimeDerivativesVirtual()147     virtual int   getNumTimeDerivativesVirtual() const {return 0;}
148     virtual Stage getDependsOnStageVirtual(int order) const = 0;
149 
150 private:
151     int             copyNumber; // bumped each time we do a deep copy
152 
153     // These are set when this Measure is adopted by a Subsystem.
154     Subsystem*      mySubsystem;
155     MeasureIndex    myIndex;
156 
157     // Measures have shallow copy semantics so they share the Implementation
158     // objects, which are only deleted when the refCount goes to zero.
159     mutable int     refCount;
160 
161 friend class AbstractMeasure;
162 friend class Subsystem::Guts;
163 };
164 
165 //==============================================================================
166 //                      ABSTRACT MEASURE DEFINITIONS
167 //==============================================================================
168 // These had to wait for AbstractMeasure::Implementation to be defined.
169 
170 inline AbstractMeasure::
AbstractMeasure(Implementation * g)171 AbstractMeasure(Implementation* g)
172 :   impl(g)
173 {   if (impl) impl->incrRefCount(); }
174 
175 inline AbstractMeasure::
AbstractMeasure(Subsystem & sub,Implementation * g,const SetHandle &)176 AbstractMeasure(Subsystem& sub, Implementation* g, const SetHandle&)
177 :   impl(g) {
178     SimTK_ERRCHK(hasImpl(), "AbstractMeasure::AbstractMeasure()",
179         "An empty Measure handle can't be put in a Subsystem.");
180     impl->incrRefCount();
181     sub.adoptMeasure(*this);
182 }
183 
184 // Shallow copy constructor.
AbstractMeasure(const AbstractMeasure & src)185 inline AbstractMeasure::AbstractMeasure(const AbstractMeasure& src)
186 :   impl(0) {
187     if (src.impl) {
188         impl = src.impl;
189         impl->incrRefCount();
190     }
191 }
192 
193 // Shallow assignment.
194 inline AbstractMeasure& AbstractMeasure::
shallowAssign(const AbstractMeasure & src)195 shallowAssign(const AbstractMeasure& src) {
196     if (impl != src.impl) {
197         if (impl && impl->decrRefCount()==0) delete impl;
198         impl = src.impl;
199         impl->incrRefCount();
200     }
201     return *this;
202 }
203 
204 // Note that even if the source and destination are currently pointing
205 // to the same Implementation, we still have to make a new copy so that
206 // afterwards the destination has its own, refcount==1 copy.
207 inline AbstractMeasure& AbstractMeasure::
deepAssign(const AbstractMeasure & src)208 deepAssign(const AbstractMeasure& src) {
209     if (&src != this) {
210         if (impl && impl->decrRefCount()==0) delete impl;
211         if (src.impl) {
212             impl = src.impl->clone();
213             impl->incrRefCount();
214         } else
215             impl = 0;
216     }
217     return *this;
218 }
219 
220 inline AbstractMeasure::
~AbstractMeasure()221 ~AbstractMeasure()
222 {   if (impl && impl->decrRefCount()==0) delete impl;}
223 
224 inline bool AbstractMeasure::
isInSubsystem()225 isInSubsystem() const
226 {   return hasImpl() && getImpl().isInSubsystem(); }
227 
228 inline const Subsystem& AbstractMeasure::
getSubsystem()229 getSubsystem() const
230 {   return getImpl().getSubsystem(); }
231 
232 inline bool AbstractMeasure::
isSameSubsystem(const Subsystem & other)233 isSameSubsystem(const Subsystem& other) const
234 {   return getSubsystem().isSameSubsystem(other); }
235 
236 inline MeasureIndex AbstractMeasure::
getSubsystemMeasureIndex()237 getSubsystemMeasureIndex() const
238 {   return getImpl().getSubsystemMeasureIndex();}
239 
240 inline int AbstractMeasure::
getNumTimeDerivatives()241 getNumTimeDerivatives() const
242 {   return getImpl().getNumTimeDerivatives(); }
243 
244 inline Stage AbstractMeasure::
getDependsOnStage(int derivOrder)245 getDependsOnStage(int derivOrder) const
246 {   return getImpl().getDependsOnStage(derivOrder); }
247 
248 inline int AbstractMeasure::
getRefCount()249 getRefCount() const
250 {   return getImpl().getRefCount(); }
251 
252 
253 /** @cond **/ // Hide from Doxygen.
254 // This is a helper class that makes it possible to treat Real, Vec, and
255 // Vector objects uniformly.
256 template <class T> class Measure_Num {
257 };
258 
259 template <> class Measure_Num<float> {
260 public:
261     typedef float Element;
size(const float &)262     static int size(const float&) {return 1;}
get(const float & v,int i)263     static const float& get(const float& v, int i) {assert(i==0); return v;}
upd(float & v,int i)264     static float& upd(float& v, int i) {assert(i==0); return v;}
makeNaNLike(const float &,float & nanValue)265     static void makeNaNLike(const float&, float& nanValue)
266     {   nanValue = CNT<float>::getNaN();}
makeZeroLike(const float &,float & zeroValue)267     static void makeZeroLike(const float&, float& zeroValue) {zeroValue=0.f;}
268 };
269 
270 template <> class Measure_Num<double> {
271 public:
272     typedef double Element;
size(const double &)273     static int size(const double&) {return 1;}
get(const double & v,int i)274     static const double& get(const double& v, int i) {assert(i==0); return v;}
upd(double & v,int i)275     static double& upd(double& v, int i) {assert(i==0); return v;}
makeNaNLike(const double &,double & nanValue)276     static void makeNaNLike(const double&, double& nanValue)
277     {  nanValue = CNT<double>::getNaN(); }
makeZeroLike(const double &,double & zeroValue)278     static void makeZeroLike(const double&, double& zeroValue) {zeroValue=0.;}
279 };
280 
281 // We only support stride 1 (densely packed) Vec types.
282 template <int M, class E>
283 class Measure_Num< Vec<M,E,1> > {
284     typedef Vec<M,E,1> T;
285 public:
286     typedef E Element;
size(const T &)287     static int size(const T&) {return M;}
get(const T & v,int i)288     static const E& get(const T& v, int i) {return v[i];}
upd(T & v,int i)289     static E& upd(T& v, int i) {return v[i];}
makeNaNLike(const T &,T & nanValue)290     static void makeNaNLike (const T&, T& nanValue)  {nanValue.setToNaN();}
makeZeroLike(const T &,T & zeroValue)291     static void makeZeroLike(const T&, T& zeroValue) {zeroValue.setToZero();}
292 };
293 
294 // We only support column major (densely packed) Mat types.
295 template <int M, int N, class E>
296 class Measure_Num< Mat<M,N,E> > {
297     typedef Mat<M,N,E> T;
298 public:
299     typedef E Element;
size(const T &)300     static int size(const T&) {return N;} // number of columns
get(const T & m,int j)301     static const typename T::TCol& get(const T& m, int j) {return m.col(j);}
upd(T & m,int j)302     static typename T::TCol& upd(T& m, int j) {return m.col(j);}
makeNaNLike(const T &,T & nanValue)303     static void makeNaNLike (const T&, T& nanValue)  {nanValue.setToNaN();}
makeZeroLike(const T &,T & zeroValue)304     static void makeZeroLike(const T&, T& zeroValue) {zeroValue.setToZero();}
305 };
306 
307 
308 template <class E>
309 class Measure_Num< Vector_<E> > {
310     typedef Vector_<E> T;
311 public:
312     typedef E Element;
size(const T & v)313     static int size(const T& v) {return v.size();}
get(const T & v,int i)314     static const E& get(const T& v, int i) {return v[i];}
upd(T & v,int i)315     static E& upd(T& v, int i) {return v[i];}
makeNaNLike(const T & v,T & nanValue)316     static void makeNaNLike(const T& v, T& nanValue)
317     {   nanValue.resize(v.size()); nanValue.setToNaN(); }
makeZeroLike(const T & v,T & zeroValue)318     static void makeZeroLike(const T& v, T& zeroValue)
319     {   zeroValue.resize(v.size()); zeroValue.setToZero(); }
320 };
321 
322 
323 template <class E>
324 class Measure_Num< Rotation_<E> > {
325     typedef Rotation_<E> T;
326 public:
327     typedef T Element;
size(const T &)328     static int size(const T&) {return 1;}
get(const T & v,int i)329     static const T& get(const T& v, int i) {assert(i==0); return v;}
upd(T & v,int i)330     static T& upd(T& v, int i) {assert(i==0); return v;}
makeNaNLike(const T &,T & nanValue)331     static void makeNaNLike(const T&, T& nanValue)
332     {   nanValue.setRotationToNaN(); }
makeZeroLike(const T &,T & zeroValue)333     static void makeZeroLike(const T&, T& zeroValue)
334     {   zeroValue.setRotationToIdentityMatrix(); }
335 };
336 
337 template <class E>
338 class Measure_Num< Transform_<E> > {
339     typedef Transform_<E> T;
340 public:
341     typedef T Element;
size(const T &)342     static int size(const T&) {return 1;}
get(const T & v,int i)343     static const T& get(const T& v, int i) {assert(i==0); return v;}
upd(T & v,int i)344     static T& upd(T& v, int i) {assert(i==0); return v;}
makeNaNLike(const T &,T & nanValue)345     static void makeNaNLike(const T&, T& nanValue)
346     {   nanValue.setToNaN(); }
makeZeroLike(const T &,T & zeroValue)347     static void makeZeroLike(const T&, T& zeroValue)
348     {   zeroValue.setToZero(); }
349 };
350 
351 /** @endcond **/
352 
353 //==============================================================================
354 //                       MEASURE_<T> :: IMPLEMENTATION
355 //==============================================================================
356 /** This is the base Implementation class for all Measures whose value type is
357 known. This class is still abstract but provides many services related to the
358 values of the derived Measure and its derivatives, all of which require cache
359 entries of type T.
360 
361 The constructor needs to be told how many type-T cache entries to allocate. **/
362 template <class T>
363 class Measure_<T>::Implementation : public AbstractMeasure::Implementation {
364 public:
getValue(const State & s,int derivOrder)365     const T& getValue(const State& s, int derivOrder) const {
366         SimTK_ERRCHK2(0 <= derivOrder && derivOrder <= getNumTimeDerivatives(),
367             "Measure_<T>::getValue()",
368             "derivOrder %d was out of range; this Measure allows 0-%d.",
369             derivOrder, getNumTimeDerivatives());
370 
371         // We require the stage to have been advanced to at least the one
372         // before this measure's depends-on stage since this will get called
373         // towards the end of the depends-on stage realization.
374         if (getDependsOnStage(derivOrder) != Stage::Empty) {
375 #ifndef NDEBUG
376             Stage prevStage = getDependsOnStage(derivOrder).prev();
377 #endif
378 
379             SimTK_ERRCHK2
380                 (   ( isInSubsystem() && getStage(s)>=prevStage)
381                  || (!isInSubsystem() && s.getSystemStage()>=prevStage),
382                 "Measure_<T>::getValue()",
383                 "Expected State to have been realized to at least stage "
384                 "%s but stage was %s.",
385                 prevStage.getName().c_str(),
386                 (isInSubsystem() ? getStage(s) : s.getSystemStage())
387                     .getName().c_str());
388         }
389 
390         if (derivOrder < getNumCacheEntries()) {
391             if (!isCacheValueRealized(s,derivOrder)) {
392                 T& value = updCacheEntry(s,derivOrder);
393                 calcCachedValueVirtual(s, derivOrder, value);
394                 markCacheValueRealized(s,derivOrder);
395                 return value;
396             }
397             return getCacheEntry(s,derivOrder);
398         }
399 
400         // We can't handle it here -- punt to the concrete Measure
401         // for higher order derivatives.
402         return getUncachedValueVirtual(s,derivOrder);
403     }
404 
405     /** Set a new default value for this %Measure. This is a topological
406     change. **/
setDefaultValue(const T & defaultValue)407     void setDefaultValue(const T& defaultValue) {
408         this->defaultValue = defaultValue;
409         Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
410         this->invalidateTopologyCache();
411     }
412 
413     /** Return a reference to the value that this %Measure will use to
414     initialize its value-level state resource (state variable or cache entry)
415     during the next call to realizeTopology(). **/
getDefaultValue()416     const T& getDefaultValue() const {return defaultValue;}
417 
setIsPresumedValidAtDependsOnStage(bool presume)418     void setIsPresumedValidAtDependsOnStage(bool presume)
419     {   presumeValidAtDependsOnStage = presume;
420         this->invalidateTopologyCache(); }
421 
getIsPresumedValidAtDependsOnStage()422     bool getIsPresumedValidAtDependsOnStage() const
423     {   return presumeValidAtDependsOnStage; }
424 
425 protected:
426     explicit Implementation(const T& defaultValue, int numCacheEntries=1)
presumeValidAtDependsOnStage(false)427     :   presumeValidAtDependsOnStage(false),
428         defaultValue(defaultValue),
429         derivIx(numCacheEntries)
430     {
431         Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
432     }
433 
434     /** Argument \a numCacheEntries should be one greater than the number of
435     derivatives; that is, there is room for the value ("0th" derivative) also.
436     The default is to allocate just room for the value. **/
437     explicit Implementation(int numCacheEntries=1)
presumeValidAtDependsOnStage(false)438     :   presumeValidAtDependsOnStage(false),
439         defaultValue(),
440         derivIx(numCacheEntries)
441     {
442         Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
443     }
444 
445     /** Copy constructor copies the \e number of cache entries from the source,
446     but not the cache indices themselves as those must be allocated uniquely
447     for the copy. **/
Implementation(const Implementation & source)448     Implementation(const Implementation& source)
449     :   presumeValidAtDependsOnStage(source.presumeValidAtDependsOnStage),
450         defaultValue(source.defaultValue),
451         derivIx(source.derivIx.size())
452     {
453         Measure_Num<T>::makeZeroLike(defaultValue, zeroValue);
454     }
455 
456 
457     /** Return the number of elements in the data type of this %Measure; for
458     Vector measures this is determined by the size of the default value. **/
size()459     int size() const {return Measure_Num<T>::size(defaultValue);}
460 
461     /** Return the number of cache entries allocated for the value and
462     derivatives of this %Measure. **/
getNumCacheEntries()463     int getNumCacheEntries() const {return (int)derivIx.size();}
464 
465     /** Get a const reference to the value stored in one of this %Measure's
466     cache entries, indexed by the derivative order (with the value treated as
467     the 0th derivative). **/
getCacheEntry(const State & s,int derivOrder)468     const T& getCacheEntry(const State& s, int derivOrder) const {
469         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
470             "Measure_<T>::Implementation::getCacheEntry()",
471             "Derivative order %d is out of range; only %d cache entries"
472             " were allocated.", derivOrder, getNumCacheEntries());
473 
474         return Value<T>::downcast(
475             this->getSubsystem().getCacheEntry(s, derivIx[derivOrder]));
476     }
477 
478     /** Get a writable reference to the value stored in one of this %Measure's
479     cache entries, indexed by the derivative order (with the value treated as
480     the 0th derivative). **/
updCacheEntry(const State & s,int derivOrder)481     T& updCacheEntry(const State& s, int derivOrder) const {
482         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
483             "Measure_<T>::Implementation::updCacheEntry()",
484             "Derivative order %d is out of range; only %d cache entries"
485             " were allocated.", derivOrder, getNumCacheEntries());
486 
487         return Value<T>::updDowncast(
488             this->getSubsystem().updCacheEntry(s, derivIx[derivOrder]));
489     }
490 
491     /** Determine whether a particular one of this %Measure's cache entries has
492     already been realized since the given state was modified. **/
isCacheValueRealized(const State & s,int derivOrder)493     bool isCacheValueRealized(const State& s, int derivOrder) const {
494         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
495             "Measure_<T>::Implementation::isCacheValueRealized()",
496             "Derivative order %d is out of range; only %d cache entries"
497             " were allocated.", derivOrder, getNumCacheEntries());
498 
499         return this->getSubsystem().isCacheValueRealized(s, derivIx[derivOrder]);
500     }
501 
502     /** Mark one of this %Measure's cache entries up to date; call this after
503     you have calculated a value or derivative and stored it in the
504     corresponding cache entry. **/
markCacheValueRealized(const State & s,int derivOrder)505     void markCacheValueRealized(const State& s, int derivOrder) const {
506         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
507             "Measure_<T>::Implementation::markCacheValueRealized()",
508             "Derivative order %d is out of range; only %d cache entries"
509             " were allocated.", derivOrder, getNumCacheEntries());
510 
511         this->getSubsystem().markCacheValueRealized(s, derivIx[derivOrder]);
512     }
513 
514     /** Invalidate one of this %Measure's cache entries. This is not normally
515     necessary since the cache entries will be invalidated automatically when
516     state variables they depend on change. However, this can be useful in
517     some cases, particularly during debugging and testing. **/
markCacheValueNotRealized(const State & s,int derivOrder)518     void markCacheValueNotRealized(const State& s, int derivOrder) const {
519         SimTK_ERRCHK2(0 <= derivOrder && derivOrder < getNumCacheEntries(),
520             "Measure_<T>::Implementation::markCacheValueNotRealized()",
521             "Derivative order %d is out of range; only %d cache entries"
522             " were allocated.", derivOrder, getNumCacheEntries());
523 
524         this->getSubsystem().markCacheValueNotRealized(s, derivIx[derivOrder]);
525     }
526 
527     // VIRTUALS //
528 
529     /** Concrete measures can override this to allocate Topology-stage
530     resources. **/
realizeMeasureTopologyVirtual(State &)531     virtual void realizeMeasureTopologyVirtual(State&) const {}
532 
533     /** Concrete measures must override this if the state cache is used for
534     precalculated values or derivatives. **/
535     virtual void
calcCachedValueVirtual(const State &,int derivOrder,T & value)536     calcCachedValueVirtual(const State&, int derivOrder, T& value) const
537     {   SimTK_ERRCHK1_ALWAYS(!"implemented",
538         "Measure_<T>::Implementation::calcCachedValueVirtual()",
539         "This method should have been overridden by the derived"
540         " Measure but was not. It is needed to calculate the"
541         " cached value for derivOrder=%d.", derivOrder); }
542 
543     /** This is only called when derivOrder >= the number of cache
544     entries we have, but still <= the number of derivatives the
545     %Measure says it can deliver. You don't need to override this if that
546     condition can't occur. This is commonly used for functions whose derivatives
547     above a certain order are zero. **/
548     virtual const T&
getUncachedValueVirtual(const State &,int derivOrder)549     getUncachedValueVirtual(const State&, int derivOrder) const
550     {   SimTK_ERRCHK1_ALWAYS(!"implemented",
551             "Measure_<T>::Implementation::getUncachedValueVirtual()",
552             "This method should have been overridden by the derived"
553             " Measure but was not. It is needed to return the uncached"
554             " value at derivOrder=%d.", derivOrder);
555         return *reinterpret_cast<T*>(0);
556     }
557 
558     /** Return a reference to a zero of the same type and size as this
559     %Measure's value. **/
getValueZero()560     const T& getValueZero() const {return zeroValue;}
561 
562 private:
563     // Satisfy the realizeTopology() pure virtual here now that we know the
564     // data type T. Allocate lazy- or auto-validated- cache entries depending
565     // on the setting of presumeValidAtDependsOnStage.
realizeTopology(State & s)566     void realizeTopology(State& s) const override final {
567         // Allocate cache entries. Initialize the value cache entry to
568         // the given defaultValue; all the derivative cache entries should be
569         // initialized to a NaN of the same size.
570         if (getNumCacheEntries()) {
571             derivIx[0] = presumeValidAtDependsOnStage
572                 ? this->getSubsystem().allocateCacheEntry
573                         (s, getDependsOnStage(0), new Value<T>(defaultValue))
574                 : this->getSubsystem().allocateLazyCacheEntry
575                         (s, getDependsOnStage(0), new Value<T>(defaultValue));
576 
577             if (getNumCacheEntries() > 1) {
578                 T nanValue; Measure_Num<T>::makeNaNLike(defaultValue, nanValue);
579                 for (int i=1; i < getNumCacheEntries(); ++i) {
580                     derivIx[i] = presumeValidAtDependsOnStage
581                         ? this->getSubsystem().allocateCacheEntry
582                             (s, getDependsOnStage(i), new Value<T>(nanValue))
583                         : this->getSubsystem().allocateLazyCacheEntry
584                             (s, getDependsOnStage(i), new Value<T>(nanValue));
585                 }
586             }
587         }
588 
589         // Call the concrete class virtual if any.
590         realizeMeasureTopologyVirtual(s);
591     }
592 
593 //------------------------------------------------------------------------------
594 private:
595     // TOPOLOGY STATE
596     bool    presumeValidAtDependsOnStage;
597     T       defaultValue;
598     T       zeroValue;
599 
600     // TOPOLOGY CACHE
601     mutable Array_<CacheEntryIndex> derivIx;
602 };
603 
604 
605 
606 //==============================================================================
607 //                       CONSTANT :: IMPLEMENTATION
608 //==============================================================================
609 template <class T>
610 class Measure_<T>::Constant::Implementation
611 :   public Measure_<T>::Implementation
612 {
613 public:
614     // We don't want the base class to allocate *any* cache entries.
Implementation()615     Implementation() : Measure_<T>::Implementation(0) {}
Implementation(const T & value)616     explicit Implementation(const T& value)
617     :   Measure_<T>::Implementation(value,0) {}
618 
619     /** Changing the value of a %Constant measure is a topological change;
620     if this is a Vector measure you can change the size here too. **/
setValue(const T & v)621     void setValue(const T& v) {this->setDefaultValue(v);}
622 
623     // Implementations of virtual methods.
624     // Measure_<T> virtuals:
625     // No cached values.
626 
getUncachedValueVirtual(const State &,int derivOrder)627     const T& getUncachedValueVirtual(const State&, int derivOrder) const
628         override
629     {   return derivOrder>0 ? this->getValueZero() : this->getDefaultValue(); }
630 
631     // AbstractMeasure virtuals:
cloneVirtual()632     Implementation* cloneVirtual() const override
633     {   return new Implementation(*this); }
getDependsOnStageVirtual(int derivOrder)634     Stage getDependsOnStageVirtual(int derivOrder) const override
635     {   return derivOrder>0 ? Stage::Empty : Stage::Topology; }
getNumTimeDerivativesVirtual()636     int getNumTimeDerivativesVirtual() const override
637     {   return std::numeric_limits<int>::max(); }
638 };
639 
640 
641 
642 //==============================================================================
643 //                        MEASURE ZERO and ONE
644 //==============================================================================
645 // These had to wait for Constant::Implementation to be declared.
646 
647 template <class T> inline
Zero()648 Measure_<T>::Zero::Zero() : Constant(T(0)) {}
649 template <class T> inline
Zero(Subsystem & sub)650 Measure_<T>::Zero::Zero(Subsystem& sub) : Constant(sub, T(0)) {}
651 
Zero(int size)652 inline Measure_< Vector >::Zero::Zero(int size)
653 :   Constant(Vector(size, Real(0))) {}
Zero(Subsystem & sub,int size)654 inline Measure_< Vector >::Zero::Zero(Subsystem& sub, int size)
655 :  Constant(sub, Vector(size, Real(0))) {}
656 
657 template <class T> inline
One()658 Measure_<T>::One::One() : Constant(T(1)) {}
659 template <class T> inline
One(Subsystem & sub)660 Measure_<T>::One::One(Subsystem& sub) : Constant(sub, T(1)) {}
661 
One(int size)662 inline Measure_< Vector >::One::One(int size)
663 :   Constant(Vector(size, Real(1))) {}
One(Subsystem & sub,int size)664 inline Measure_< Vector >::One::One(Subsystem& sub, int size)
665 :  Constant(sub, Vector(size, Real(1))) {}
666 
667 
668 
669 //==============================================================================
670 //                         TIME :: IMPLEMENTATION
671 //==============================================================================
672 template <class T>
673 class Measure_<T>::Time::Implementation {};
674 
675 template <>
676 class Measure_<Real>::Time::Implementation
677 :   public Measure_<Real>::Implementation
678 {
679 public:
680     // We don't want the base class to allocate *any* cache entries.
Implementation()681     Implementation() : Measure_<Real>::Implementation(0) {}
682 
683     // Implementations of virtual methods.
684     // Measure_<Real> virtuals:
685     // No cached values.
686 
getUncachedValueVirtual(const State & s,int derivOrder)687     const Real& getUncachedValueVirtual(const State& s, int derivOrder) const
688         override
689     {   return derivOrder==0 ? s.getTime()
690             : (derivOrder==1 ? SimTK::One
691                              : SimTK::Zero); }
692 
693     // AbstractMeasure virtuals:
cloneVirtual()694     Implementation* cloneVirtual() const override
695     {   return new Implementation(*this); }
getDependsOnStageVirtual(int derivOrder)696     Stage getDependsOnStageVirtual(int derivOrder) const override
697     {   return derivOrder>0 ? Stage::Empty : Stage::Time; }
698 
699     // Value is t, 1st derivative is 1, the rest are 0.
getNumTimeDerivativesVirtual()700     int getNumTimeDerivativesVirtual() const override
701     {   return std::numeric_limits<int>::max(); }
702 };
703 
704 
705 
706 //==============================================================================
707 //                        VARIABLE :: IMPLEMENTATION
708 //==============================================================================
709 template <class T>
710 class Measure_<T>::Variable::Implementation
711 :   public Measure_<T>::Implementation
712 {
713 public:
714     // We don't want the base class to allocate *any* cache entries;
715     // we'll use the variable as its own value and zeroes for all
716     // the derivatives.
Implementation()717     Implementation()
718     :   Measure_<T>::Implementation(0),
719         invalidatedStage(Stage::Empty) {}
720 
Implementation(Stage invalidated,const T & defaultValue)721     Implementation(Stage invalidated, const T& defaultValue)
722     :   Measure_<T>::Implementation(defaultValue, 0),
723         invalidatedStage(invalidated) {}
724 
725     // Copy constructor should not copy the variable.
Implementation(const Implementation & source)726     Implementation(const Implementation& source)
727     :   Measure_<T>::Implementation(source.getDefaultValue(), 0),
728         invalidatedStage(source.invalidatedStage) {}
729 
setInvalidatedStage(Stage invalidates)730     void setInvalidatedStage(Stage invalidates) {
731         invalidatedStage = invalidates;
732         this->invalidateTopologyCache();
733     }
734 
getInvalidatedStage()735     Stage getInvalidatedStage() const {return invalidatedStage;}
736 
737     /** Change the value of this %Measure in the given \a state. Invalidates
738     cache entries in that \a state for any stage at or above the "invalidates"
739     stage that was set when this %Measure was constructed. **/
setValue(State & state,const T & value)740     void setValue(State& state, const T& value) const
741     {   updVarValue(state) = value; }
742 
743     // Implementations of virtual methods.
cloneVirtual()744     Implementation* cloneVirtual() const override
745     {   return new Implementation(*this); }
746 
getNumTimeDerivativesVirtual()747     int getNumTimeDerivativesVirtual() const override
748     {   return std::numeric_limits<int>::max(); }
749 
750     // Discrete variable is available after Model stage; but all its
751     // derivatives are zero so are always available.
getDependsOnStageVirtual(int derivOrder)752     Stage getDependsOnStageVirtual(int derivOrder) const override
753     {   return derivOrder>0 ? Stage::Empty : Stage::Model;}
754 
getUncachedValueVirtual(const State & s,int derivOrder)755     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
756         override
757     {   return derivOrder>0 ? this->getValueZero() : getVarValue(s); }
758 
759     // No cached values.
760 
realizeMeasureTopologyVirtual(State & s)761     void realizeMeasureTopologyVirtual(State& s) const override {
762         discreteVarIndex = this->getSubsystem().allocateDiscreteVariable
763             (s, invalidatedStage, new Value<T>(this->getDefaultValue()));
764     }
765 private:
getVarValue(const State & s)766     const T& getVarValue(const State& s) const {
767         assert(discreteVarIndex.isValid());
768         return Value<T>::downcast(
769             this->getSubsystem().getDiscreteVariable(s, discreteVarIndex));
770     }
updVarValue(State & s)771     T& updVarValue(State& s) const {
772         assert(discreteVarIndex.isValid());
773         return Value<T>::downcast(
774             this->getSubsystem().updDiscreteVariable(s, discreteVarIndex));
775     }
776 
777     // TOPOLOGY STATE
778     Stage   invalidatedStage; // TODO this shouldn't be needed
779 
780     // TOPOLOGY CACHE
781     mutable DiscreteVariableIndex discreteVarIndex;
782 };
783 
784 
785 
786 //==============================================================================
787 //                         RESULT :: IMPLEMENTATION
788 //==============================================================================
789 template <class T>
790 class Measure_<T>::Result::Implementation
791 :   public Measure_<T>::Implementation
792 {
793 public:
794     // We want the base class to allocate a single cache entry of type T.
Implementation()795     Implementation()
796     :   Measure_<T>::Implementation(1),
797         dependsOnStage(Stage::Topology), invalidatedStage(Stage::Infinity) {}
798 
Implementation(Stage dependsOn,Stage invalidated)799     Implementation(Stage dependsOn, Stage invalidated)
800     :   Measure_<T>::Implementation(1),
801         dependsOnStage(dependsOn==Stage::Empty ? Stage::Topology : dependsOn),
802         invalidatedStage(invalidated)
803     {   SimTK_ERRCHK2_ALWAYS(invalidated > dependsOn,"Measure::Result::ctor()",
804             "Got invalidated stage %s and dependsOn stage %s which is illegal "
805             "because the invalidated stage must be later than dependsOn.",
806             invalidated.getName().c_str(), dependsOn.getName().c_str());
807     }
808 
809     // Copy constructor will not copy the cache entry index.
Implementation(const Implementation & source)810     Implementation(const Implementation& source)
811     :   Measure_<T>::Implementation(source),
812         dependsOnStage(source.dependsOnStage),
813         invalidatedStage(source.invalidatedStage) {}
814 
setDependsOnStage(Stage dependsOn)815     void setDependsOnStage(Stage dependsOn) {
816         if (dependsOn == Stage::Empty) dependsOn = Stage::Topology;
817         SimTK_ERRCHK2_ALWAYS(dependsOn < getInvalidatedStage(),
818             "Measure::Result::setDependsOnStage()",
819             "The provided dependsOn stage %s is illegal because it is not "
820             "less than the current invalidated stage %s. Change the "
821             "invalidated stage first with setInvalidatedStage().",
822             dependsOn.getName().c_str(),
823             getInvalidatedStage().getName().c_str());
824 
825         dependsOnStage = dependsOn;
826         this->invalidateTopologyCache();
827     }
828 
setInvalidatedStage(Stage invalidated)829     void setInvalidatedStage(Stage invalidated) {
830         SimTK_ERRCHK2_ALWAYS(invalidated > getDependsOnStage(),
831             "Measure::Result::setInvalidatedStage()",
832             "The provided invalidated stage %s is illegal because it is not "
833             "greater than the current dependsOn stage %s. Change the "
834             "dependsOn stage first with setDependsOnStage().",
835             invalidated.getName().c_str(),
836             getDependsOnStage().getName().c_str());
837 
838         invalidatedStage = invalidated;
839         this->invalidateTopologyCache();
840     }
841 
842 
getDependsOnStage()843     Stage getDependsOnStage()   const {return dependsOnStage;}
getInvalidatedStage()844     Stage getInvalidatedStage() const {return invalidatedStage;}
845 
846 
markAsValid(const State & state)847     void markAsValid(const State& state) const
848     {   const Stage subsystemStage = this->getSubsystem().getStage(state);
849         SimTK_ERRCHK3_ALWAYS(subsystemStage >= getDependsOnStage().prev(),
850             "Measure::Result::markAsValid()",
851             "This Result Measure cannot be marked valid in a State where this "
852             "measure's Subsystem has been realized only to stage %s, because "
853             "its value was declared to depend on stage %s. To mark it valid, "
854             "we require that the State have been realized at least to the "
855             "previous stage (%s in this case); that is, you must at least be "
856             "*working on* the dependsOn stage in order to claim this result is "
857             "available.",
858             subsystemStage.getName().c_str(),
859             getDependsOnStage().getName().c_str(),
860             getDependsOnStage().prev().getName().c_str());
861         this->markCacheValueRealized(state, 0); }
862 
isValid(const State & state)863     bool isValid(const State& state) const
864     {   return this->isCacheValueRealized(state, 0); }
865 
markAsNotValid(const State & state)866     void markAsNotValid(const State& state) const
867     {   this->markCacheValueNotRealized(state, 0);
868         state.invalidateAllCacheAtOrAbove(invalidatedStage); }
869 
updValue(const State & state)870     T& updValue(const State& state) const
871     {   markAsNotValid(state); return this->updCacheEntry(state, 0); }
872 
873 
874     // Implementations of virtual methods.
cloneVirtual()875     Implementation* cloneVirtual() const override
876     {   return new Implementation(*this); }
877 
getNumTimeDerivativesVirtual()878     int getNumTimeDerivativesVirtual() const override {return 0;}
879 
880     /** Cache value is available after its "depends on" stage has been
881     realized; but all its derivatives are zero so are always available. **/
getDependsOnStageVirtual(int derivOrder)882     Stage getDependsOnStageVirtual(int derivOrder) const override
883     {   return derivOrder>0 ? Stage::Empty : dependsOnStage;}
884 
calcCachedValueVirtual(const State &,int derivOrder,T & value)885     void calcCachedValueVirtual(const State&, int derivOrder, T& value) const
886         override
887     {   SimTK_ERRCHK_ALWAYS(!"calcCachedValueVirtual() implemented",
888         "Measure_<T>::Result::getValue()",
889         "Measure_<T>::Result::getValue() was called when the value was not "
890         "yet valid. For most Measure types, this would have initiated "
891         "computation of the value, but Result measures must have their values "
892         "calculated and set externally, and then marked valid."); }
893 
894 private:
895     // TOPOLOGY STATE
896     Stage   dependsOnStage;
897     Stage   invalidatedStage;
898 };
899 
900 
901 
902 //==============================================================================
903 //                        SINUSOID :: IMPLEMENTATION
904 //==============================================================================
905 template <class T>
906 class Measure_<T>::Sinusoid::Implementation
907 :   public Measure_<T>::Implementation
908 {
909     static const int NumDerivs = 3;
910 public:
Implementation()911     Implementation()
912     :   Measure_<T>::Implementation(NumDerivs+1),
913         a(CNT<T>::getNaN()), w(CNT<T>::getNaN()), p(CNT<T>::getNaN()) {}
914 
915     Implementation(const T& amplitude,
916                    const T& frequency,
917                    const T& phase=T(0))
918     :   Measure_<T>::Implementation(NumDerivs+1),
919         a(amplitude), w(frequency), p(phase) {}
920 
921     // Default copy constructor is fine.
922 
923     // Implementations of virtual methods.
cloneVirtual()924     Implementation* cloneVirtual() const override
925     {   return new Implementation(*this); }
926 
getNumTimeDerivativesVirtual()927     int getNumTimeDerivativesVirtual() const override {return NumDerivs;}
928 
getDependsOnStageVirtual(int order)929     Stage getDependsOnStageVirtual(int order) const override
930     {   return Stage::Time; }
931 
calcCachedValueVirtual(const State & s,int derivOrder,T & value)932     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
933         override
934     {
935         // We need to allow the compiler to select std::sin or SimTK::sin
936         // based on the argument type.
937         using std::sin; using std::cos;
938 
939         assert(NumDerivs == 3);
940         const Real t = s.getTime();
941         const T arg = w*t + p;
942 
943         switch (derivOrder) {
944         case 0: value =        a*sin(arg); break;
945         case 1: value =      w*a*cos(arg); break;
946         case 2: value =   -w*w*a*sin(arg); break;
947         case 3: value = -w*w*w*a*cos(arg); break;
948         default: SimTK_ASSERT1_ALWAYS(!"out of range",
949                      "Measure::Sinusoid::Implementation::calcCachedValueVirtual():"
950                      " derivOrder %d is out of range 0-3.", derivOrder);
951         }
952     }
953 
954     // There are no uncached values.
955 
956 private:
957     // TOPOLOGY STATE
958     T a, w, p;
959 
960     // TOPOLOGY CACHE
961     // nothing
962 };
963 
964 
965 
966 //==============================================================================
967 //                          PLUS :: IMPLEMENTATION
968 //==============================================================================
969 template <class T>
970 class Measure_<T>::Plus::Implementation : public Measure_<T>::Implementation {
971 public:
972     // TODO: Currently allocates just one cache entry.
973     // left and right will be empty handles.
Implementation()974     Implementation() {}
975 
Implementation(const Measure_<T> & left,const Measure_<T> & right)976     Implementation(const Measure_<T>& left,
977                    const Measure_<T>& right)
978     :   left(left), right(right) {}
979 
980     // Default copy constructor gives us a new Implementation object,
981     // but with references to the *same* operand measures.
982 
983     // Implementations of virtual methods.
984 
985     // This uses the default copy constructor.
cloneVirtual()986     Implementation* cloneVirtual() const override
987     {   return new Implementation(*this); }
988 
989     // TODO: Let this be settable up to the min number of derivatives
990     // provided by the arguments.
getNumTimeDerivativesVirtual()991     int getNumTimeDerivativesVirtual() const override {return 0;}
992     //{   return std::min(left.getNumTimeDerivatives(),
993     //                    right.getNumTimeDerivatives()); }
994 
getDependsOnStageVirtual(int order)995     Stage getDependsOnStageVirtual(int order) const override
996     {   return Stage(std::max(left.getDependsOnStage(order),
997                               right.getDependsOnStage(order))); }
998 
999 
calcCachedValueVirtual(const State & s,int derivOrder,T & value)1000     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1001         override
1002     {
1003         value = left.getValue(s,derivOrder) + right.getValue(s,derivOrder);
1004     }
1005 
1006     // There are no uncached values.
1007 
1008 private:
1009     // TOPOLOGY STATE
1010     Measure_<T> left;
1011     Measure_<T> right;
1012 
1013     // TOPOLOGY CACHE
1014     // nothing
1015 };
1016 
1017 
1018 
1019 //==============================================================================
1020 //                          MINUS :: IMPLEMENTATION
1021 //==============================================================================
1022 template <class T>
1023 class Measure_<T>::Minus::Implementation : public Measure_<T>::Implementation {
1024 public:
1025     // TODO: Currently allocates just one cache entry.
1026     // left and right will be empty handles.
Implementation()1027     Implementation() {}
1028 
Implementation(const Measure_<T> & left,const Measure_<T> & right)1029     Implementation(const Measure_<T>& left,
1030                    const Measure_<T>& right)
1031     :   left(left), right(right) {}
1032 
1033     // Default copy constructor gives us a new Implementation object,
1034     // but with references to the *same* operand measures.
1035 
1036     // Implementations of virtual methods.
1037 
1038     // This uses the default copy constructor.
cloneVirtual()1039     Implementation* cloneVirtual() const override
1040     {   return new Implementation(*this); }
1041 
1042     // TODO: Let this be settable up to the min number of derivatives
1043     // provided by the arguments.
getNumTimeDerivativesVirtual()1044     int getNumTimeDerivativesVirtual() const override {return 0;}
1045     //{   return std::min(left.getNumTimeDerivatives(),
1046     //                    right.getNumTimeDerivatives()); }
1047 
getDependsOnStageVirtual(int order)1048     Stage getDependsOnStageVirtual(int order) const override
1049     {   return Stage(std::max(left.getDependsOnStage(order),
1050                               right.getDependsOnStage(order))); }
1051 
1052 
calcCachedValueVirtual(const State & s,int derivOrder,T & value)1053     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1054         override
1055     {
1056         value = left.getValue(s,derivOrder) - right.getValue(s,derivOrder);
1057     }
1058 
1059     // There are no uncached values.
1060 
1061 private:
1062     // TOPOLOGY STATE
1063     Measure_<T> left;
1064     Measure_<T> right;
1065 
1066     // TOPOLOGY CACHE
1067     // nothing
1068 };
1069 
1070 
1071 
1072 //==============================================================================
1073 //                          SCALE :: IMPLEMENTATION
1074 //==============================================================================
1075 template <class T>
1076 class Measure_<T>::Scale::Implementation
1077 :   public Measure_<T>::Implementation
1078 {
1079 public:
1080     // TODO: Currently allocates just one cache entry.
1081     // scale will be uninitialized, operand will be empty handle.
Implementation()1082     Implementation() : factor(NaN) {}
1083 
Implementation(Real factor,const Measure_<T> & operand)1084     Implementation(Real factor, const Measure_<T>& operand)
1085     :   factor(factor), operand(operand) {}
1086 
1087     // Default copy constructor gives us a new Implementation object,
1088     // but with references to the *same* operand measure.
1089 
setScaleFactor(Real sf)1090     void setScaleFactor(Real sf) {
1091         factor = sf;
1092         this->invalidateTopologyCache();
1093     }
1094 
getOperandMeasure()1095     const Measure_<T>& getOperandMeasure() const
1096     {
1097         return operand;
1098     }
1099 
1100     // Implementations of virtual methods.
1101 
1102     // This uses the default copy constructor.
cloneVirtual()1103     Implementation* cloneVirtual() const override
1104     {   return new Implementation(*this); }
1105 
1106     // TODO: Let this be settable up to the min number of derivatives
1107     // provided by the arguments.
getNumTimeDerivativesVirtual()1108     int getNumTimeDerivativesVirtual() const override {return 0;}
1109     //{   return std::min(left.getNumTimeDerivatives(),
1110     //                    right.getNumTimeDerivatives()); }
1111 
getDependsOnStageVirtual(int order)1112     Stage getDependsOnStageVirtual(int order) const override
1113     {   return operand.getDependsOnStage(order); }
1114 
1115 
calcCachedValueVirtual(const State & s,int derivOrder,T & value)1116     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1117         override
1118     {
1119         value = factor * operand.getValue(s,derivOrder);
1120     }
1121 
1122     // There are no uncached values.
1123 
1124 private:
1125     // TOPOLOGY STATE
1126     Real        factor;
1127     Measure_<T> operand;
1128 
1129     // TOPOLOGY CACHE
1130     // nothing
1131 };
1132 
1133 
1134 
1135 //==============================================================================
1136 //                        INTEGRATE :: IMPLEMENTATION
1137 //==============================================================================
1138 /** The implementation for %Integrate measures allocates a continuous state
1139 variable or variables from the State's z pool and generates zdot values to be
1140 integrated into those z variables. The z's are then copied into a type T,
1141 Time-stage cache entry so that we can return the value as a type T reference.
1142 Derivative requests are passed through to the integrand so only one cache
1143 entry is required here. **/
1144 template <class T>
1145 class Measure_<T>::Integrate::Implementation
1146 :   public Measure_<T>::Implementation {
1147 public:
1148     /** The derivative and initialConditions Measures will be empty handles if
1149     this is default constructed. **/
Implementation()1150     Implementation() : Measure_<T>::Implementation(1) {}
1151 
1152     /** Here we're shallow-copying the Measure handles so we'll be referring to
1153     the original Measures. **/
Implementation(const Measure_<T> & deriv,const Measure_<T> & ic,const T & defaultValue)1154     Implementation(const Measure_<T>& deriv, const Measure_<T>& ic,
1155                    const T& defaultValue)
1156     :   Measure_<T>::Implementation(defaultValue, 1),
1157         derivMeasure(deriv), icMeasure(ic) {}
1158 
1159     /** Copy constructor shallow-copies the referenced measures, but we don't
1160     want to share our state variables. **/
Implementation(const Implementation & source)1161     Implementation(const Implementation& source)
1162     :   Measure_<T>::Implementation(source.getDefaultValue(), 1),
1163         derivMeasure(source.derivMeasure), icMeasure(source.icMeasure) {}
1164 
1165     /** Set the value of the state variables(s) that hold the integral. This
1166     cannot be used to change the size if the type T is a Vector; the supplied
1167     \a value must be the same length as the default value of this %Measure. **/
setValue(State & s,const T & value)1168     void setValue(State& s, const T& value) const
1169     {   assert(zIndex >= 0);
1170         for (int i=0; i < this->size(); ++i)
1171             this->getSubsystem().updZ(s)[zIndex+i] =
1172                 Measure_Num<T>::get(value, i); }
1173 
getDerivativeMeasure()1174     const Measure_<T>& getDerivativeMeasure() const
1175     {   SimTK_ERRCHK(!derivMeasure.isEmptyHandle(),
1176             "Measure_<T>::Integrate::getDerivativeMeasure()",
1177             "No derivative measure is available for this integrated measure.");
1178         return derivMeasure; }
1179 
getInitialConditionMeasure()1180     const Measure_<T>& getInitialConditionMeasure() const
1181     {   SimTK_ERRCHK(!icMeasure.isEmptyHandle(),
1182             "Measure_<T>::Integrate::getInitialConditionMeasure()",
1183             "No initial condition measure is available for this "
1184             "integrated measure.");
1185         return icMeasure; }
1186 
setDerivativeMeasure(const Measure_<T> & d)1187     void setDerivativeMeasure(const Measure_<T>& d)
1188     {   derivMeasure = d; this->invalidateTopologyCache(); }
setInitialConditionMeasure(const Measure_<T> & ic)1189     void setInitialConditionMeasure(const Measure_<T>& ic)
1190     {   icMeasure = ic; this->invalidateTopologyCache(); }
1191 
1192     // Implementations of virtuals.
1193 
1194     // This uses the copy constructor defined above.
cloneVirtual()1195     Implementation* cloneVirtual() const override
1196     {   return new Implementation(*this); }
1197 
1198     /** This measure has one more time derivative than the integrand. **/
getNumTimeDerivativesVirtual()1199     int getNumTimeDerivativesVirtual() const override
1200     {   int integralDerivs = getDerivativeMeasure().getNumTimeDerivatives();
1201         // Careful - can't add 1 to max int and stay an int.
1202         if (integralDerivs < std::numeric_limits<int>::max())
1203             ++integralDerivs;
1204         return integralDerivs; }
1205 
calcCachedValueVirtual(const State & s,int derivOrder,T & value)1206     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
1207         override
1208     {   assert(derivOrder == 0); // only one cache entry
1209         assert(Measure_Num<T>::size(value) == this->size());
1210         assert(zIndex.isValid());
1211         const Vector& allZ = this->getSubsystem().getZ(s);
1212         for (int i=0; i < this->size(); ++i)
1213             Measure_Num<T>::upd(value,i) = allZ[zIndex+i];
1214     }
1215 
getUncachedValueVirtual(const State & s,int derivOrder)1216     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
1217         override
1218     {   assert(derivOrder > 0); // 0th entry is cached
1219         return getDerivativeMeasure().getValue(s, derivOrder-1);
1220     }
1221 
getDependsOnStageVirtual(int derivOrder)1222     Stage getDependsOnStageVirtual(int derivOrder) const override
1223     {   return derivOrder>0
1224             ? getDerivativeMeasure().getDependsOnStage(derivOrder-1)
1225             : Stage::Time; }
1226 
1227     /** Initialize the state to the current value of the initial condition
1228     measure, if there is one, otherwise to the default value. **/
initializeVirtual(State & s)1229     void initializeVirtual(State& s) const override {
1230         assert(zIndex.isValid());
1231         Vector& allZ = this->getSubsystem().updZ(s);
1232         if (!icMeasure.isEmptyHandle()) {
1233             this->getSubsystem().getSystem()
1234                 .realize(s, icMeasure.getDependsOnStage());
1235             const T& ic = icMeasure.getValue(s);
1236             for (int i=0; i < this->size(); ++i)
1237                 allZ[zIndex+i] = Measure_Num<T>::get(ic,i);
1238         } else {
1239             for (int i=0; i < this->size(); ++i)
1240                 allZ[zIndex+i] = Measure_Num<T>::get(this->getDefaultValue(),i);
1241         }
1242     }
1243 
1244     /** Allocate one Real continuous state variable z per element of this
1245     %Measure's data type T, using the default value to determine
1246     how many are needed (if that's not part of the type T), and initialize them
1247     to the corresponding element from the default value. **/
realizeMeasureTopologyVirtual(State & s)1248     void realizeMeasureTopologyVirtual(State& s) const override {
1249         Vector init(this->size());
1250         for (int i=0; i < this->size(); ++i)
1251             init[i] = Measure_Num<T>::get(this->getDefaultValue(),i);
1252         zIndex = this->getSubsystem().allocateZ(s, init);
1253     }
1254 
1255     /** Set the zdots to the integrand (derivative measure) value. If no
1256     integrand was provided it is treated as though it were zero. **/
realizeMeasureAccelerationVirtual(const State & s)1257     void realizeMeasureAccelerationVirtual(const State& s) const override {
1258         assert(zIndex.isValid());
1259         Vector& allZDot = this->getSubsystem().updZDot(s);
1260         if (!derivMeasure.isEmptyHandle()) {
1261             const T& deriv = derivMeasure.getValue(s);
1262              for (int i=0; i < this->size(); ++i)
1263                  allZDot[zIndex+i] = Measure_Num<T>::get(deriv,i);
1264         } else {
1265             allZDot(zIndex,this->size()) = 0; // derivative is zero
1266         }
1267     }
1268 
1269 private:
1270     // TOPOLOGY STATE
1271     Measure_<T> derivMeasure; // just handles
1272     Measure_<T> icMeasure;
1273 
1274     // TOPOLOGY CACHE
1275     mutable ZIndex zIndex;  // This is the first index if more than one z.
1276 };
1277 
1278 
1279 
1280 //==============================================================================
1281 //                      DIFFERENTIATE :: IMPLEMENTATION
1282 //==============================================================================
1283 
1284 /** @cond **/ // Hide from Doxygen.
1285 // This helper class is the contents of the discrete state variable and
1286 // corresponding cache entry maintained by this measure. The variable is
1287 // auto-update, meaning the value of the cache entry replaces the state
1288 // variable at the start of each step.
1289 // TODO: This was a local class in Measure_<T>::Differentiate::Implementation
1290 // but VC++ 8 (2005) failed to properly instantiate the templatized operator<<()
1291 // in that case; doing it this way is a workaround.
1292 template <class T>
1293 class Measure_Differentiate_Result {
1294 public:
Measure_Differentiate_Result()1295     Measure_Differentiate_Result() : derivIsGood(false) {}
1296     T       operand;    // previous value of operand
1297     T       operandDot; // previous value of derivative
1298     bool    derivIsGood; // do we think the deriv is a good one?
1299 };
1300 /** @endcond **/
1301 
1302 template <class T>
1303 class Measure_<T>::Differentiate::Implementation
1304 :   public Measure_<T>::Implementation
1305 {
1306     typedef Measure_Differentiate_Result<T> Result;
1307 public:
1308     // Don't allocate any cache entries in the base class.
Implementation()1309     Implementation() : Measure_<T>::Implementation(0) {}
1310 
Implementation(const Measure_<T> & operand)1311     Implementation(const Measure_<T>& operand)
1312     :   Measure_<T>::Implementation(0),
1313         operand(operand), forceUseApprox(false), isApproxInUse(false) {}
1314 
1315     // Default copy constructor gives us a new Implementation object,
1316     // but with reference to the *same* operand measure.
1317 
setForceUseApproximation(bool mustApproximate)1318     void setForceUseApproximation(bool mustApproximate) {
1319         forceUseApprox = mustApproximate;
1320         this->invalidateTopologyCache();
1321     }
1322 
setOperandMeasure(const Measure_<T> & operand)1323     void setOperandMeasure(const Measure_<T>& operand) {
1324         this->operand = operand;
1325         this->invalidateTopologyCache();
1326     }
1327 
getForceUseApproximation()1328     bool getForceUseApproximation() const {return forceUseApprox;}
isUsingApproximation()1329     bool isUsingApproximation() const {return isApproxInUse;}
getOperandMeasure()1330     const Measure_<T>& getOperandMeasure() const {return operand;}
1331 
1332     // Implementations of virtual methods.
1333 
1334     // This uses the default copy constructor.
cloneVirtual()1335     Implementation* cloneVirtual() const override
1336     {   return new Implementation(*this); }
1337 
1338     // This has one fewer than the operand.
getNumTimeDerivativesVirtual()1339     int getNumTimeDerivativesVirtual() const override
1340     {   if (!isApproxInUse) return operand.getNumTimeDerivatives()-1;
1341         else return 0; }
1342 
getDependsOnStageVirtual(int order)1343     Stage getDependsOnStageVirtual(int order) const override
1344     {   if (!isApproxInUse) return operand.getDependsOnStage(order+1);
1345         else return operand.getDependsOnStage(order); }
1346 
1347 
1348     // We're not using the Measure_<T> base class cache services, but
1349     // we do have one of our own. It looks uncached from the base class
1350     // point of view which is why we're implementing it here.
getUncachedValueVirtual(const State & s,int derivOrder)1351     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
1352         override
1353     {   if (!isApproxInUse)
1354             return operand.getValue(s, derivOrder+1);
1355 
1356         ensureDerivativeIsRealized(s);
1357         const Subsystem& subsys = this->getSubsystem();
1358         const Result& result = Value<Result>::downcast
1359                                 (subsys.getDiscreteVarUpdateValue(s,resultIx));
1360         return result.operandDot; // has a value but might not be a good one
1361     }
1362 
initializeVirtual(State & s)1363     void initializeVirtual(State& s) const override {
1364         if (!isApproxInUse) return;
1365 
1366         assert(resultIx.isValid());
1367         const Subsystem& subsys = this->getSubsystem();
1368         Result& result = Value<Result>::updDowncast
1369                             (subsys.updDiscreteVariable(s,resultIx));
1370         this->getSubsystem().getSystem().realize(s,operand.getDependsOnStage());
1371         result.operand = operand.getValue(s);
1372         result.operandDot = this->getValueZero();
1373         result.derivIsGood = false;
1374     }
1375 
realizeMeasureTopologyVirtual(State & s)1376     void realizeMeasureTopologyVirtual(State& s) const override {
1377         isApproxInUse = (forceUseApprox || operand.getNumTimeDerivatives()==0);
1378         if (!isApproxInUse)
1379             return;
1380 
1381         resultIx = this->getSubsystem()
1382             .allocateAutoUpdateDiscreteVariable(s, operand.getDependsOnStage(0),
1383                 new Value<Result>(), operand.getDependsOnStage(0));
1384     }
1385 
1386     /** In case no one has updated the value of this measure yet, we have
1387     to make sure it gets updated before the integration moves ahead. **/
realizeMeasureAccelerationVirtual(const State & s)1388     void realizeMeasureAccelerationVirtual(const State& s) const override {
1389         ensureDerivativeIsRealized(s);
1390     }
1391 
ensureDerivativeIsRealized(const State & s)1392     void ensureDerivativeIsRealized(const State& s) const {
1393         assert(resultIx.isValid());
1394         const Subsystem& subsys = this->getSubsystem();
1395         if (subsys.isDiscreteVarUpdateValueRealized(s,resultIx))
1396             return;
1397 
1398         const Real t0 = subsys.getDiscreteVarLastUpdateTime(s,resultIx);
1399         const Result& prevResult = Value<Result>::downcast
1400            (subsys.getDiscreteVariable(s,resultIx));
1401         const T&   f0         = prevResult.operand;
1402         const T&   fdot0      = prevResult.operandDot;   // may be invalid
1403         const bool good0      = prevResult.derivIsGood;
1404 
1405         const Real t  = s.getTime();
1406         Result& result = Value<Result>::updDowncast
1407            (subsys.updDiscreteVarUpdateValue(s,resultIx));
1408         T&         f          = result.operand;          // renaming
1409         T&         fdot       = result.operandDot;
1410         bool&      good       = result.derivIsGood;
1411 
1412         f = operand.getValue(s);
1413         good = false;
1414         if (!isFinite(t0))
1415             fdot = this->getValueZero();
1416         else if (t == t0) {
1417             fdot = fdot0;
1418             good = good0;
1419         } else {
1420             fdot = (f-f0)/(t-t0); // 1st order
1421             if (good0)
1422                 fdot = Real(2)*fdot - fdot0; // now 2nd order
1423             good = true; // either 1st or 2nd order estimate
1424         }
1425         subsys.markDiscreteVarUpdateValueRealized(s,resultIx);
1426     }
1427 private:
1428     // TOPOLOGY STATE
1429     Measure_<T>     operand;
1430     bool            forceUseApprox;
1431 
1432     // TOPOLOGY CACHE
1433     mutable bool                    isApproxInUse;
1434     mutable DiscreteVariableIndex   resultIx;    // auto-update
1435 };
1436 
1437 
1438 
1439 //==============================================================================
1440 //                         EXTREME :: IMPLEMENTATION
1441 //==============================================================================
1442 template <class T>
1443 class Measure_<T>::Extreme::Implementation : public Measure_<T>::Implementation
1444 {
1445     typedef typename Measure_<T>::Extreme Extreme;
1446     typedef typename Extreme::Operation   Operation;
1447 public:
1448     /** Default constructor leaves the operand measure unspecified; no base
1449     class cache entries are allocated. **/
Implementation()1450     Implementation()
1451     :   Measure_<T>::Implementation(0), operation(Extreme::MaxAbs) {}
1452 
1453     /** Construct a measure that returns the extreme value taken on by the
1454     operand measure during a time stepping study. **/
Implementation(const Measure_<T> & operand,Operation op)1455     Implementation(const Measure_<T>& operand, Operation op)
1456     :   Measure_<T>::Implementation(0), operand(operand), operation(op) {}
1457 
1458     // Default copy constructor gives us a new Implementation object,
1459     // but with reference to the *same* operand measure.
1460 
1461     /** Set the operand measure for this %Extreme measure; this is a Topology
1462     stage change so you'll have to call realizeTopology() again if you call
1463     this. **/
setOperandMeasure(const Measure_<T> & operand)1464     void setOperandMeasure(const Measure_<T>& operand) {
1465         this->operand = operand;
1466         this->invalidateTopologyCache();
1467     }
1468 
1469     /** Set the particular operation to be performed by this %Extreme measure;
1470     this is a Topology stage change so you'll have to call realizeTopology()
1471     again if you call this. **/
setOperation(Operation op)1472     void setOperation(Operation op) {
1473         this->operation = op;
1474         this->invalidateTopologyCache();
1475     }
1476 
1477     /** Return a reference to the operand measure for this %Extreme measure. **/
getOperandMeasure()1478     const Measure_<T>& getOperandMeasure() const {return operand;}
1479 
1480     /** Return the particular operation being performed by this %Extreme
1481     measure. **/
getOperation()1482     Operation getOperation() const {return operation;}
1483 
1484     /** Set the current extreme value stored in this %Extreme measure's state
1485     variable. **/
setValue(State & s,const T & value)1486     void setValue(State& s, const T& value) const {
1487         assert(extremeIx.isValid());
1488         const Subsystem& subsys = this->getSubsystem();
1489         T& prevMin = Value<T>::updDowncast
1490                             (subsys.updDiscreteVariable(s,extremeIx));
1491         prevMin = value;
1492     }
1493 
1494     /** Return the time at which the extreme was last updated. This will be
1495     the current time if the operand is currently at its most extreme value,
1496     otherwise it will be sometime in the past. **/
getTimeOfExtremeValue(const State & s)1497     Real getTimeOfExtremeValue(const State& s) const {
1498         const Subsystem& subsys = this->getSubsystem();
1499         const bool hasNewExtreme = ensureExtremeHasBeenUpdated(s);
1500         Real tUpdate;
1501         if (hasNewExtreme)
1502             tUpdate = s.getTime(); // i.e., now
1503         else
1504             tUpdate = subsys.getDiscreteVarLastUpdateTime(s,extremeIx);
1505         return tUpdate;
1506     }
1507 
1508     // Implementations of virtual methods.
1509 
1510     // This uses the default copy constructor.
cloneVirtual()1511     Implementation* cloneVirtual() const override
1512     {   return new Implementation(*this); }
1513 
1514     /** Extreme(f(t)) has the same number of derivatives as f except that
1515     they are all zero unless f(t) is a new extreme. **/
getNumTimeDerivativesVirtual()1516     int getNumTimeDerivativesVirtual() const override
1517     {   return operand.getNumTimeDerivatives(); }
1518 
1519     /** The depends-on stage for this measure is the same as for its
1520     operand. **/
getDependsOnStageVirtual(int order)1521     Stage getDependsOnStageVirtual(int order) const override
1522     {   return operand.getDependsOnStage(order); }
1523 
1524 
1525     /** We're not using the Measure_<T> base class cache services, but
1526     we do have one of our own. It looks uncached from the base class
1527     point of view which is why we're implementing it here. **/
getUncachedValueVirtual(const State & s,int derivOrder)1528     const T& getUncachedValueVirtual(const State& s, int derivOrder) const
1529         override
1530     {
1531         const Subsystem& subsys = this->getSubsystem();
1532         const bool hasNewExtreme = ensureExtremeHasBeenUpdated(s);
1533         if (derivOrder > 0) {
1534             // TODO: should be handled elementwise and zero unless the
1535             // derivative is acting in the direction that changes the
1536             // extreme.
1537             return hasNewExtreme ? operand.getValue(s, derivOrder)
1538                                  : this->getValueZero();
1539         }
1540         if (hasNewExtreme) {
1541             const T& newExt = Value<T>::downcast
1542                                 (subsys.getDiscreteVarUpdateValue(s,extremeIx));
1543             return newExt;
1544         } else {
1545             const T& currentExt = Value<T>::downcast
1546                                 (subsys.getDiscreteVariable(s,extremeIx));
1547             return currentExt;
1548         }
1549     }
1550 
1551     /** At start of a time stepping study, this should be called to set the
1552     current extreme value to the current value of the operand. **/
initializeVirtual(State & s)1553     void initializeVirtual(State& s) const override {
1554         this->getSubsystem().getSystem().realize(s,operand.getDependsOnStage());
1555         setValue(s, operand.getValue(s));
1556     }
1557 
1558     /** Allocate the auto-updated state variable that holds the extreme seen
1559     so far. We'll assume that changes to this variable invalidate Dynamics
1560     (force) stage so that any forces that depend on it will be recomputed if
1561     it changes. Also allocate an auxiliary boolean variable that is used to hold
1562     whether the current value is a new extreme; that is private to the
1563     implementation and not user-accessible since you can instead check the
1564     time of last update. **/
realizeMeasureTopologyVirtual(State & s)1565     void realizeMeasureTopologyVirtual(State& s) const override {
1566         // TODO: this should be NaN once initialization is working properly.
1567         T initVal = this->getDefaultValue();
1568         switch(operation) {
1569         case Minimum: initVal = Infinity; break;
1570         case Maximum: initVal = -Infinity; break;
1571         case MinAbs:  initVal = Infinity; break;
1572         case MaxAbs:  initVal = 0; break;
1573         };
1574 
1575         extremeIx = this->getSubsystem()
1576             .allocateAutoUpdateDiscreteVariable(s, Stage::Dynamics,
1577                 new Value<T>(initVal), operand.getDependsOnStage(0));
1578 
1579         isNewExtremeIx = this->getSubsystem()
1580             .allocateAutoUpdateDiscreteVariable(s, Stage::Dynamics,
1581                 new Value<bool>(false), operand.getDependsOnStage(0));
1582     }
1583 
1584     /** In case no one has updated the value of this measure yet, we have
1585     to make sure it gets updated before the integration moves ahead. **/
realizeMeasureAccelerationVirtual(const State & s)1586     void realizeMeasureAccelerationVirtual(const State& s) const override {
1587         ensureExtremeHasBeenUpdated(s);
1588     }
1589 
1590     /** Here we make sure that the cache entry is updated if the current value
1591     of the operand is more extreme than the previous one, and return a bool
1592     indicating whether we have a new extreme. We don't want to create an update
1593     entry unless the extreme value has changed, because we would like the state
1594     variable's last update value to reflect the last actual change. **/
ensureExtremeHasBeenUpdated(const State & s)1595     bool ensureExtremeHasBeenUpdated(const State& s) const {
1596         assert(extremeIx.isValid() && isNewExtremeIx.isValid());
1597         const Subsystem& subsys = this->getSubsystem();
1598 
1599         // We may have already determined whether we're at a new extreme in
1600         // which case we don't need to do it again.
1601         if (subsys.isDiscreteVarUpdateValueRealized(s, isNewExtremeIx))
1602             return Value<bool>::downcast
1603                (subsys.getDiscreteVarUpdateValue(s,isNewExtremeIx));
1604 
1605         // We're going to have to decide if we're at a new extreme, and if
1606         // so record the new extreme value in the auto-update cache entry of
1607         // the extreme value state variable.
1608 
1609         // Get the previous extreme value and the current operand value.
1610         const T& prevExtreme = Value<T>::downcast
1611                                     (subsys.getDiscreteVariable(s,extremeIx));
1612         const T& currentVal = operand.getValue(s);
1613 
1614         // Search to see if any element has reached a new extreme.
1615         bool foundNewExt = false;
1616         for (int i=0; i < this->size() && !foundNewExt; ++i)
1617             foundNewExt = isNewExtreme(Measure_Num<T>::get(currentVal,i),
1618                                        Measure_Num<T>::get(prevExtreme,i));
1619 
1620         // Record the result and mark the auto-update cache entry valid
1621         // so we won't have to recalculate. When the integrator advances to the
1622         // next step this cache entry will be swapped with the corresponding
1623         // state and marked invalid so we'll be sure to recalculate each step.
1624         Value<bool>::updDowncast
1625            (subsys.updDiscreteVarUpdateValue(s,isNewExtremeIx)) = foundNewExt;
1626         subsys.markDiscreteVarUpdateValueRealized(s,isNewExtremeIx);
1627 
1628         // Don't update the auto-update cache entry if we didn't see a new
1629         // extreme. That way no auto-update will occur and the state variable
1630         // will remain unchanged with the existing update time preserved.
1631         if (!foundNewExt)
1632             return false;
1633 
1634         // We have encountered a new extreme. We'll record the new extreme
1635         // in the auto-update cache entry which will be used as the current
1636         // result until the integrator advances to the next step at which time
1637         // this will be swapped with the state variable to serve as the previous
1638         // extreme value until a further extreme is encountered.
1639         T& newExtreme = Value<T>::updDowncast
1640                                 (subsys.updDiscreteVarUpdateValue(s,extremeIx));
1641 
1642         for (int i=0; i < this->size(); ++i)
1643             Measure_Num<T>::upd(newExtreme,i) =
1644                 extremeOf(Measure_Num<T>::get(currentVal,i),
1645                           Measure_Num<T>::get(prevExtreme,i));
1646 
1647         // Marking this valid is what ensures that an auto-update occurs later.
1648         subsys.markDiscreteVarUpdateValueRealized(s,extremeIx);
1649         return true;
1650     }
1651 private:
1652     // Return true if newVal is "more extreme" than oldExtreme, according
1653     // to the operation we're performing.
isNewExtreme(const typename Measure_Num<T>::Element & newVal,const typename Measure_Num<T>::Element & oldExtreme)1654     bool isNewExtreme(const typename Measure_Num<T>::Element& newVal,
1655                       const typename Measure_Num<T>::Element& oldExtreme) const
1656     {
1657         switch (operation) {
1658         case Extreme::Maximum: return newVal > oldExtreme;
1659         case Extreme::Minimum: return newVal < oldExtreme;
1660         case Extreme::MaxAbs: return std::abs(newVal) > std::abs(oldExtreme);
1661         case Extreme::MinAbs: return std::abs(newVal) < std::abs(oldExtreme);
1662         };
1663         SimTK_ASSERT1_ALWAYS(!"recognized",
1664             "Measure::Extreme::Implementation::isNewExtreme(): "
1665             "unrecognized operation %d", (int)operation);
1666         return false; /*NOTREACHED*/
1667     }
1668 
1669     // Given the value of one element of the operand, and that value's time
1670     // derivative, determine whether the derivative is moving the element
1671     // into the "more extreme" direction, according to the operation.
isExtremeDir(const typename Measure_Num<T>::Element & value,const typename Measure_Num<T>::Element & deriv)1672     bool isExtremeDir(const typename Measure_Num<T>::Element& value,
1673                       const typename Measure_Num<T>::Element& deriv) const
1674     {
1675         const int sv = sign(value), sd = sign(deriv);
1676         if (sd == 0) return false; // derivative is zero; not changing
1677         switch (operation) {
1678         case Extreme::Maximum: return sd ==  1; // getting larger
1679         case Extreme::Minimum: return sd == -1; // getting smaller
1680         case Extreme::MaxAbs: return sv==0 || sd==sv; // abs is growing
1681         case Extreme::MinAbs: return sd == -sv;
1682         };
1683         SimTK_ASSERT1_ALWAYS(!"recognized",
1684             "Measure::Extreme::Implementation::isExtremeDir(): "
1685             "unrecognized operation %d", (int)operation);
1686         return false; /*NOTREACHED*/
1687     }
1688 
1689     typename Measure_Num<T>::Element
extremeOf(const typename Measure_Num<T>::Element & newVal,const typename Measure_Num<T>::Element & oldExtreme)1690     extremeOf(const typename Measure_Num<T>::Element& newVal,
1691               const typename Measure_Num<T>::Element& oldExtreme) const
1692     {
1693         return isNewExtreme(newVal,oldExtreme) ? newVal : oldExtreme;
1694     }
1695 
1696     // TOPOLOGY STATE
1697     Measure_<T>                     operand;
1698     Operation                       operation;
1699 
1700     // TOPOLOGY CACHE
1701     mutable DiscreteVariableIndex   extremeIx; // extreme so far; auto-update
1702 
1703     // This auto-update flag records whether the current value is a new
1704     // extreme. We don't really need to save it as a state variable since you
1705     // can figure this out from the timestamp, but we need to to get invalidated
1706     // by the auto-update swap so that we'll figure it out anew each step.
1707     mutable DiscreteVariableIndex   isNewExtremeIx;
1708 };
1709 
1710 
1711 
1712 //==============================================================================
1713 //                         DELAY :: IMPLEMENTATION
1714 //==============================================================================
1715 /** @cond **/ // Hide from Doxygen.
1716 // This helper class is the contents of the discrete state variable and
1717 // corresponding cache entry maintained by this measure. The variable is
1718 // auto-update, meaning the value of the cache entry replaces the state
1719 // variable at the start of each step.
1720 //
1721 // Circular buffers look like this:
1722 //
1723 //             oldest=0, n=0
1724 //                  v
1725 // Empty buffer:   |    available    |
1726 //
1727 // By convention, oldest=0 whenever the buffer is empty.
1728 //
1729 //
1730 //           oldest            next=(oldest+n)%capacity
1731 //                 v           v
1732 //    | available | | | | | | | available |
1733 //     ^                n=6                ^
1734 //     0                                   capacity
1735 //     v                                   v
1736 // or | | | | | | available | | | | | | | |    n=12
1737 //               ^           ^
1738 //               next        oldest
1739 //                 = (oldest+n)%capacity
1740 //
1741 // Number of entries = n (called size() below)
1742 // Empty = n==0
1743 // Full = n==capacity()
1744 // Next available = (oldest+n)%capacity()
1745 template <class T>
1746 class Measure_Delay_Buffer {
1747 public:
Measure_Delay_Buffer()1748     explicit Measure_Delay_Buffer() {initDataMembers();}
clear()1749     void clear() {initDataMembers();}
size()1750     int  size() const {return m_size;} // # saved entries, *not* size of arrays
capacity()1751     int  capacity() const {return m_times.size();}
empty()1752     bool empty() const {return size()==0;}
full()1753     bool full()  const {return size()==capacity();}
1754 
getEntryTime(int i)1755     double getEntryTime(int i) const
1756     {   assert(i < size()); return m_times[getArrayIndex(i)];}
getEntryValue(int i)1757     const T& getEntryValue(int i) const
1758     {   assert(i < size()); return m_values[getArrayIndex(i)];}
1759 
1760     enum {
1761         InitialAllocation  = 8,  // smallest allocation
1762         GrowthFactor       = 2,  // how fast to grow (double)
1763         MaxShrinkProofSize = 16, // won't shrink unless bigger
1764         TooBigFactor       = 5   // 5X too much->maybe shrink
1765     };
1766 
1767     // Add a new entry to the end of the list, throwing out old entries that
1768     // aren't needed to answer requests at tEarliest or later.
append(double tEarliest,double tNow,const T & valueNow)1769     void append(double tEarliest, double tNow, const T& valueNow) {
1770         forgetEntriesMuchOlderThan(tEarliest);
1771         removeEntriesLaterOrEq(tNow);
1772         if (full())
1773             makeMoreRoom();
1774         else if (capacity() > std::max((int)MaxShrinkProofSize,
1775                                        (int)TooBigFactor * (size()+1)))
1776             makeLessRoom(); // less than 1/TooBigFactor full
1777         const int nextFree = getArrayIndex(m_size++);
1778         m_times[nextFree] = tNow;
1779         m_values[nextFree] = valueNow;
1780         m_maxSize = std::max(m_maxSize, size());
1781     }
1782 
1783     // Prepend an older entry to the beginning of the list. No cleanup is done.
prepend(double tNewOldest,const T & value)1784     void prepend(double tNewOldest, const T& value) {
1785         assert(empty() || tNewOldest < m_times[m_oldest]);
1786         if (full()) makeMoreRoom();
1787         m_oldest = empty() ? 0 : getArrayIndex(-1);
1788         m_times[m_oldest] = tNewOldest;
1789         m_values[m_oldest] = value;
1790         ++m_size;
1791         m_maxSize = std::max(m_maxSize, size());
1792     }
1793 
1794     // This is a specialized copy assignment for copying an old buffer
1795     // to a new one with updated contents. We are told the earliest time we'll
1796     // be asked about from now on, and won't copy any entries older than those
1797     // needed to answer that earliest request. We won't copy anything at or
1798     // newer than tNow, and finally we'll push (tNow,valueNow) as the newest
1799     // entry.
copyInAndUpdate(const Measure_Delay_Buffer & oldBuf,double tEarliest,double tNow,const T & valueNow)1800     void copyInAndUpdate(const Measure_Delay_Buffer& oldBuf, double tEarliest,
1801                          double tNow, const T& valueNow) {
1802         // clear all current entries (no heap activity)
1803         m_oldest = m_size = 0;
1804 
1805         // determine how may old entries we have to keep
1806         int firstNeeded = oldBuf.countNumUnneededOldEntries(tEarliest);
1807         int lastNeeded  = oldBuf.findLastEarlier(tNow); // might be -1
1808         int numOldEntriesToKeep = lastNeeded-firstNeeded+1;
1809         int newSize = numOldEntriesToKeep+1; // includes the new one
1810 
1811         int newSizeRequest = -1;
1812         if (capacity() < newSize) {
1813             newSizeRequest = std::max((int)InitialAllocation,
1814                                       (int)GrowthFactor * newSize);
1815             ++m_nGrows;
1816         } else if (capacity() > std::max((int)MaxShrinkProofSize,
1817                                          (int)TooBigFactor * newSize)) {
1818             newSizeRequest = std::max((int)MaxShrinkProofSize,
1819                                       (int)GrowthFactor * newSize);
1820             ++m_nShrinks;
1821         }
1822 
1823         // Reallocate space if advisable.
1824         if (newSizeRequest != -1) {
1825             const double dNaN = NTraits<double>::getNaN();
1826             m_values.resize(newSizeRequest);
1827             if (m_values.capacity() > m_values.size())
1828                 m_values.resize(m_values.capacity()); // don't waste any
1829             m_times.resize(m_values.size(), dNaN);
1830         }
1831 
1832         m_maxCapacity = std::max(m_maxCapacity, capacity());
1833 
1834         // Copy the entries we need to keep.
1835         int nxt = 0;
1836         for (int i=firstNeeded; i<=lastNeeded; ++i, ++nxt) {
1837             m_times[nxt]  = oldBuf.getEntryTime(i);
1838             m_values[nxt] = oldBuf.getEntryValue(i);
1839         }
1840         // Now add the newest entry and set the size.
1841         m_times[nxt]  = tNow;
1842         m_values[nxt] = valueNow;
1843         assert(nxt+1==newSize);
1844         m_size = nxt+1;
1845         m_maxSize = std::max(m_maxSize, size());
1846     }
1847 
1848     // Given the current time and value and the earlier time at which the
1849     // value is needed, use the buffer and (if necessary) the current value
1850     // to estimate the delayed value.
1851     T calcValueAtTime(double tDelay, double tNow, const T& valueNow) const;
1852 
1853     // Given the current time but *not* the current value of the source measure,
1854     // provide an estimate for the value at tDelay=tNow-delay using only the
1855     // buffer contents and linear interpolation or extrapolation.
calcValueAtTimeLinearOnly(double tDelay,T & delayedValue)1856     void calcValueAtTimeLinearOnly(double tDelay, T& delayedValue) const {
1857         if (empty()) {
1858             // Nothing in the buffer?? Shouldn't happen. Return empty Vector
1859             // or NaN for fixed-size types.
1860             Measure_Num<T>::makeNaNLike(T(), delayedValue);
1861             return;
1862         }
1863 
1864         int firstLater = findFirstLaterOrEq(tDelay);
1865 
1866         if (firstLater > 0) {
1867             // Normal case: tDelay is between two buffer entries.
1868             int firstEarlier = firstLater-1;
1869             double t0=getEntryTime(firstEarlier), t1=getEntryTime(firstLater);
1870             const T& v0=getEntryValue(firstEarlier);
1871             const T& v1=getEntryValue(firstLater);
1872             Real fraction = Real((tDelay-t0)/(t1-t0));
1873             delayedValue = T(v0 + fraction*(v1-v0));
1874             return;
1875         }
1876 
1877         if (firstLater==0) {
1878             // Startup case: tDelay is at or before the oldest buffer entry.
1879             // Assume the value was flat before that.
1880             delayedValue = getEntryValue(firstLater);
1881             return;
1882         }
1883 
1884         // tDelay is later than the latest entry in the buffer. We are going
1885         // to have to extrapolate (yuck).
1886 
1887         if (size() == 1) {
1888             // Just one entry; we'll have to assume the value is flat.
1889             delayedValue = getEntryValue(0);
1890             return;
1891         }
1892 
1893         // Extrapolate using the last two entries.
1894         double t0=getEntryTime(size()-2), t1=getEntryTime(size()-1);
1895         const T& v0=getEntryValue(size()-2);
1896         const T& v1=getEntryValue(size()-1);
1897         Real fraction = Real((tDelay-t0)/(t1-t0));  // > 1
1898         assert(fraction > 1.0);
1899         delayedValue = T(v0 + fraction*(v1-v0));   // Extrapolate.
1900     }
1901 
1902     // Return the number of times we had to grow the buffer.
getNumGrows()1903     int getNumGrows() const {return m_nGrows;}
1904     // Return the number of times we decided the buffer was so overallocated
1905     // that we had to shrink it.
getNumShrinks()1906     int getNumShrinks() const {return m_nShrinks;}
1907     // Return the largest number of values we ever had in the buffer.
getMaxSize()1908     int getMaxSize() const {return m_maxSize;}
1909     // Return the largest capacity the buffer ever had.
getMaxCapacity()1910     int getMaxCapacity() const {return m_maxCapacity;}
1911 
1912 private:
1913     // Return the i'th oldest entry
1914     // (0 -> oldest, size-1 -> newest, size -> first free, -1 -> last free)
getArrayIndex(int i)1915     int getArrayIndex(int i) const
1916     {   assert(-1<=i && i<=size());
1917         const int rawIndex = m_oldest + i;
1918         if (rawIndex < 0) return rawIndex + capacity();
1919         else return rawIndex % capacity(); }
1920 
1921     // Remove all but two entries older than the given time.
forgetEntriesMuchOlderThan(double tEarliest)1922     void forgetEntriesMuchOlderThan(double tEarliest) {
1923         const int numToRemove = countNumUnneededOldEntries(tEarliest);
1924         if (numToRemove) {
1925             m_oldest = getArrayIndex(numToRemove);
1926             m_size -= numToRemove;
1927         }
1928     }
1929 
1930     // Count up how many old entries at the beginning of the buffer are so old
1931     // that they wouldn't be needed to respond to a request at time tEarliest or
1932     // later. We'll keep no more than two entries earlier than tEarliest.
countNumUnneededOldEntries(double tEarliest)1933     int countNumUnneededOldEntries(double tEarliest) const {
1934         const int firstLater = findFirstLaterOrEq(tEarliest);
1935         return std::max(0, firstLater-2);
1936     }
1937 
1938     // Given the time now, delete anything at the end of the queue that is
1939     // at that same time or later.
removeEntriesLaterOrEq(double t)1940     void removeEntriesLaterOrEq(double t) {
1941         int lastEarlier = findLastEarlier(t);
1942         m_size = lastEarlier+1;
1943         if (m_size==0) m_oldest=0; // restart at beginning of array
1944     }
1945 
1946     // Return the entry number (0..size-1) of the first entry whose time
1947     // is >= the given time, or -1 if there is none such.
findFirstLaterOrEq(double tDelay)1948     int findFirstLaterOrEq(double tDelay) const {
1949         for (int i=0; i < size(); ++i)
1950             if (getEntryTime(i) >= tDelay)
1951                 return i;
1952         return -1;
1953     }
1954 
1955     // Return the entry number(size-1..0) of the last entry whose time
1956     // is < the given time, or -1 if there is none such.
findLastEarlier(double t)1957     int findLastEarlier(double t) const {
1958         for (int i=size()-1; i>=0; --i)
1959             if (getEntryTime(i) < t)
1960                 return i;
1961         return -1;
1962     }
1963 
1964     // We don't have enough space. This is either the initial allocation or
1965     // we need to double the current space.
makeMoreRoom()1966     void makeMoreRoom() {
1967         const int newSizeRequest = std::max((int)InitialAllocation,
1968                                             (int)GrowthFactor * size());
1969         resize(newSizeRequest);
1970         ++m_nGrows;
1971         m_maxCapacity = std::max(m_maxCapacity, capacity());
1972     }
1973 
1974     // We are wasting a lot of space, reduce the heap allocation to just
1975     // double what we're using now.
makeLessRoom()1976     void makeLessRoom() {
1977         const int targetMaxSize = std::max((int)MaxShrinkProofSize,
1978                                            (int)GrowthFactor * size());
1979         if (capacity() > targetMaxSize) {
1980             resize(targetMaxSize);
1981             ++m_nShrinks;
1982         }
1983     }
1984 
1985     // Reallocate memory to get more space or stop wasting space. The new
1986     // size request must be big enough to hold all the current contents. The
1987     // amount we actually get may be somewhat larger than the request. On
1988     // return, the times and values arrays will have been resized and the
1989     // oldest entry will now be entry 0.
resize(int newSizeRequest)1990     void resize(int newSizeRequest) {
1991         assert(newSizeRequest >= size());
1992         const double dNaN = NTraits<double>::getNaN();
1993         Array_<T,int> newValues(newSizeRequest);
1994         if (newValues.capacity() > newValues.size())
1995             newValues.resize(newValues.capacity()); // don't waste any
1996         Array_<double,int> newTimes(newValues.size(), dNaN);
1997 
1998         // Pack existing values into start of new arrays.
1999         for (int i=0; i < size(); ++i) {
2000             const int ix = getArrayIndex(i);
2001             newTimes[i]  = m_times[ix];
2002             newValues[i] = m_values[ix];
2003         }
2004         m_times.swap(newTimes); // switch heap space
2005         m_values.swap(newValues);
2006         m_oldest = 0; // starts at the beginning now; size unchanged
2007     }
2008 
2009     // Initialize everything to its default-constructed state.
initDataMembers()2010     void initDataMembers() {
2011         m_times.clear(); m_values.clear();
2012         m_oldest=m_size=0;
2013         m_nGrows=m_nShrinks=m_maxSize=m_maxCapacity=0;
2014     }
2015 
2016     // These are circular buffers of the same size.
2017     Array_<double,int>  m_times;
2018     Array_<T,int>       m_values;
2019     int                 m_oldest; // Array index of oldest (time,value)
2020     int                 m_size;   // number of entries in use
2021 
2022     // Statistics.
2023     int m_nGrows, m_nShrinks, m_maxSize, m_maxCapacity;
2024 };
2025 /** @endcond **/
2026 
2027 template <class T>
2028 class Measure_<T>::Delay::Implementation: public Measure_<T>::Implementation {
2029     typedef Measure_Delay_Buffer<T> Buffer;
2030 public:
2031     // Allocate one cache entry in the base class for the value; we allocate
2032     // a specialized one for the buffer.
Implementation()2033     Implementation()
2034     :   Measure_<T>::Implementation(1), m_delay(NaN),
2035         m_canUseCurrentValue(false), m_useLinearInterpolationOnly(false) {}
2036 
Implementation(const Measure_<T> & source,Real delay)2037     Implementation(const Measure_<T>& source, Real delay)
2038     :   Measure_<T>::Implementation(1), m_source(source), m_delay(delay),
2039         m_canUseCurrentValue(false), m_useLinearInterpolationOnly(false) {}
2040 
2041     // Default copy constructor gives us a new Implementation object,
2042     // but with reference to the *same* source measure.
2043 
setSourceMeasure(const Measure_<T> & source)2044     void setSourceMeasure(const Measure_<T>& source) {
2045         if (!source.isSameMeasure(this->m_source)) {
2046             this->m_source = source;
2047             this->invalidateTopologyCache();
2048         }
2049     }
2050 
setDelay(Real delay)2051     void setDelay(Real delay) {
2052         if (delay != this->m_delay) {
2053             this->m_delay = delay;
2054             this->invalidateTopologyCache();
2055         }
2056     }
2057 
setUseLinearInterpolationOnly(bool linearOnly)2058     void setUseLinearInterpolationOnly(bool linearOnly) {
2059         if (linearOnly != this->m_useLinearInterpolationOnly) {
2060             this->m_useLinearInterpolationOnly = linearOnly;
2061             this->invalidateTopologyCache();
2062         }
2063     }
2064 
setCanUseCurrentValue(bool canUseCurrentValue)2065     void setCanUseCurrentValue(bool canUseCurrentValue) {
2066         if (canUseCurrentValue != this->m_canUseCurrentValue) {
2067             this->m_canUseCurrentValue = canUseCurrentValue;
2068             this->invalidateTopologyCache();
2069         }
2070     }
2071 
getSourceMeasure()2072     const Measure_<T>& getSourceMeasure() const {return this->m_source;}
getDelay()2073     Real getDelay() const {return this->m_delay;}
getUseLinearInterpolationOnly()2074     bool getUseLinearInterpolationOnly() const
2075     {   return this->m_useLinearInterpolationOnly; }
getCanUseCurrentValue()2076     bool getCanUseCurrentValue() const
2077     {   return this->m_canUseCurrentValue; }
2078 
2079 
2080     // Implementations of virtual methods.
2081 
2082     // This uses the default copy constructor.
cloneVirtual()2083     Implementation* cloneVirtual() const override
2084     {   return new Implementation(*this); }
2085 
2086     // Currently no derivative supported.
getNumTimeDerivativesVirtual()2087     int getNumTimeDerivativesVirtual() const override
2088     {   return 0; }
2089 
2090     // If we are allowed to use the current value of the source measure to
2091     // determine the delayed value, the depends-on stage here is the same as
2092     // for the source; otherwise it is Stage::Time.
getDependsOnStageVirtual(int order)2093     Stage getDependsOnStageVirtual(int order) const override
2094     {   return this->m_canUseCurrentValue ? m_source.getDependsOnStage(order)
2095                                           : Stage::Time; }
2096 
2097     // Calculate the delayed value and return it to the Measure base class to
2098     // be put in a cache entry.
calcCachedValueVirtual(const State & s,int derivOrder,T & value)2099     void calcCachedValueVirtual(const State& s, int derivOrder, T& value) const
2100         override
2101     {   const Subsystem& subsys = this->getSubsystem();
2102         const Buffer& buffer = Value<Buffer>::downcast
2103                                 (subsys.getDiscreteVariable(s,m_bufferIx));
2104         //TODO: use cubic interpolation if allowed
2105         buffer.calcValueAtTimeLinearOnly(s.getTime()-m_delay, value);
2106     }
2107 
initializeVirtual(State & s)2108     void initializeVirtual(State& s) const override {
2109         assert(m_bufferIx.isValid());
2110         const Subsystem& subsys = this->getSubsystem();
2111         Buffer& buffer = Value<Buffer>::updDowncast
2112                             (subsys.updDiscreteVariable(s,m_bufferIx));
2113         buffer.clear();
2114         this->getSubsystem().getSystem().realize(s,m_source.getDependsOnStage());
2115         buffer.append(s.getTime()-m_delay, s.getTime(), m_source.getValue(s));
2116     }
2117 
realizeMeasureTopologyVirtual(State & s)2118     void realizeMeasureTopologyVirtual(State& s) const override {
2119         m_bufferIx = this->getSubsystem()
2120             .allocateAutoUpdateDiscreteVariable(s, Stage::Report,
2121                 new Value<Buffer>(), getDependsOnStageVirtual(0));
2122     }
2123 
2124     /** In case no one has updated the value of this measure yet, we have
2125     to make sure it gets updated before the integration moves ahead. **/
realizeMeasureAccelerationVirtual(const State & s)2126     void realizeMeasureAccelerationVirtual(const State& s) const override {
2127         updateBuffer(s);
2128     }
2129 
2130     // This uses the buffer from the state to update the one in the
2131     // corresponding cache entry. The update adds the current value of the
2132     // source to the end of the buffer and tosses out unneeded old entries.
updateBuffer(const State & s)2133     void updateBuffer(const State& s) const {
2134         assert(m_bufferIx.isValid());
2135         const Subsystem& subsys = this->getSubsystem();
2136 
2137         const Buffer& prevBuffer = Value<Buffer>::downcast
2138            (subsys.getDiscreteVariable(s,m_bufferIx));
2139 
2140         Buffer& nextBuffer = Value<Buffer>::updDowncast
2141            (subsys.updDiscreteVarUpdateValue(s,m_bufferIx));
2142 
2143         const Real t = s.getTime();
2144         nextBuffer.copyInAndUpdate(prevBuffer, t-m_delay,
2145                                    t, m_source.getValue(s));
2146 
2147         subsys.markDiscreteVarUpdateValueRealized(s,m_bufferIx);
2148     }
2149 private:
2150     // TOPOLOGY STATE
2151     Measure_<T>     m_source;
2152     Real            m_delay;
2153     bool            m_canUseCurrentValue;
2154     bool            m_useLinearInterpolationOnly;
2155 
2156     // TOPOLOGY CACHE
2157     mutable DiscreteVariableIndex   m_bufferIx;    // auto-update
2158 };
2159 
2160 
2161 } // namespace SimTK
2162 
2163 
2164 
2165 
2166 #endif // SimTK_SimTKCOMMON_MEASURE_IMPLEMENTATION_H_
2167