CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
recorder.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_RECORDER_HPP
2 # define CPPAD_LOCAL_RECORDER_HPP
3 /* --------------------------------------------------------------------------
4 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
5 
6 CppAD is distributed under multiple licenses. This distribution is under
7 the terms of the
8  Eclipse Public License Version 1.0.
9 
10 A copy of this license is included in the COPYING file of this distribution.
11 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
12 -------------------------------------------------------------------------- */
13 # include <cppad/core/hash_code.hpp>
15 
16 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
17 /*!
18 \file recorder.hpp
19 File used to define the recorder class.
20 */
21 
22 /*!
23 Class used to store an operation sequence while it is being recorded
24 (the operation sequence is copied to the player class for playback).
25 
26 \tparam Base
27 This is an AD< \a Base > operation sequence recording; i.e.,
28 it records operations of type AD< \a Base >.
29 */
30 template <class Base>
31 class recorder {
32  friend class player<Base>;
33 
34 private:
35  /// operator index at which to abort recording with an error
36  /// (do not abort when zero)
38 
39  /// offset for this thread in the static hash table
40  const size_t thread_offset_;
41 
42  /// Number of variables in the recording.
43  size_t num_var_rec_;
44 
45  /// Number vecad load operations (LdpOp or LdvOp) currently in recording.
47 
48  /// The operators in the recording.
50 
51  /// The VecAD indices in the recording.
53 
54  /// The argument indices in the recording
56 
57  /// The parameters in the recording.
58  /// Note that Base may not be plain old data, so use false in consructor.
60 
61  /// Character strings ('\\0' terminated) in the recording.
63 // ---------------------- Public Functions -----------------------------------
64 public:
65  /// Default constructor
66  recorder(void) :
68  num_var_rec_(0) ,
70  {
71  abort_op_index_ = 0;
72  }
73 
74  /// Set the abort index
75  void set_abort_op_index(size_t abort_op_index)
76  { abort_op_index_ = abort_op_index; }
77 
78  /// Get the abort index
79  size_t get_abort_op_index(void)
80  { return abort_op_index_; }
81 
82  /// Destructor
83  ~recorder(void)
84  { }
85 
86  /*!
87  Frees all information in recording.
88 
89  Frees the operation sequence store in this recording
90  (the operation sequence is empty after this operation).
91  The buffers used to store the current recording are returned
92  to the system (so as to conserve on memory).
93  */
94  void free(void)
95  { num_var_rec_ = 0;
96  num_load_op_rec_ = 0;
97  op_vec_.clear();
99  arg_vec_.clear();
100  par_vec_.clear();
101  text_vec_.clear();
102  }
103  /// Put next operator in the operation sequence.
104  inline addr_t PutOp(OpCode op);
105  /// Put a vecad load operator in the operation sequence (special case)
106  inline addr_t PutLoadOp(OpCode op);
107  /// Add a value to the end of the current vector of VecAD indices.
108  inline addr_t PutVecInd(size_t vec_ind);
109  /// Find or add a parameter to the current vector of parameters.
110  inline addr_t PutPar(const Base &par);
111  /// Put one operation argument index in the recording
112  inline void PutArg(addr_t arg0);
113  /// Put two operation argument index in the recording
114  inline void PutArg(addr_t arg0, addr_t arg1);
115  /// Put three operation argument index in the recording
116  inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2);
117  /// Put four operation argument index in the recording
118  inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3);
119  /// Put five operation argument index in the recording
120  inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3,
121  addr_t arg4);
122  /// Put six operation argument index in the recording
123  inline void PutArg(addr_t arg0, addr_t arg1, addr_t arg2, addr_t arg3,
124  addr_t arg4, addr_t arg5);
125 
126  // Reserve space for a specified number of arguments
127  inline size_t ReserveArg(size_t n_arg);
128 
129  // Replace an argument value
130  void ReplaceArg(size_t i_arg, size_t value);
131 
132  /// Put a character string in the text for this recording.
133  inline addr_t PutTxt(const char *text);
134 
135  /// Number of variables currently stored in the recording.
136  size_t num_var_rec(void) const
137  { return num_var_rec_; }
138 
139  /// Number of LdpOp and LdvOp operations currently in the recording.
140  size_t num_load_op_rec(void) const
141  { return num_load_op_rec_; }
142 
143  /// Number of operators currently stored in the recording.
144  size_t num_op_rec(void) const
145  { return op_vec_.size(); }
146 
147  /// Approximate amount of memory used by the recording
148  size_t Memory(void) const
149  { return op_vec_.capacity() * sizeof(OpCode)
150  + vecad_ind_vec_.capacity() * sizeof(size_t)
151  + arg_vec_.capacity() * sizeof(addr_t)
152  + par_vec_.capacity() * sizeof(Base)
153  + text_vec_.capacity() * sizeof(char);
154  }
155 };
156 
157 /*!
158 Put next operator in the operation sequence.
159 
160 This sets the op code for the next operation in this recording.
161 This call must be followed by putting the corresponding
162 \verbatim
163  NumArg(op)
164 \endverbatim
165 argument indices in the recording.
166 
167 \param op
168 Is the op code corresponding to the the operation that is being
169 recorded (which must not be LdpOp or LdvOp).
170 
171 \return
172 The return value is the index of the primary (last) variable
173 corresponding to the result of this operation.
174 The number of variables corresponding to the operation is given by
175 \verbatim
176  NumRes(op)
177 \endverbatim
178 With each call to PutOp or PutLoadOp,
179 the return index increases by the number of variables corresponding
180 to the call.
181 This index starts at zero after the default constructor
182 and after each call to Erase.
183 */
184 template <class Base>
186 { size_t i = op_vec_.extend(1);
188  (abort_op_index_ == 0) || (abort_op_index_ != i),
189  "Operator index equals abort_op_index in Independent"
190  );
191  op_vec_[i] = op;
192  CPPAD_ASSERT_UNKNOWN( op_vec_.size() == i + 1 );
193  CPPAD_ASSERT_UNKNOWN( (op != LdpOp) & (op != LdvOp) );
194 
195  // first operator should be a BeginOp and NumRes( BeginOp ) > 0
196  num_var_rec_ += NumRes(op);
197  CPPAD_ASSERT_UNKNOWN( num_var_rec_ > 0 );
198 
199  // index of last variable corresponding to this operation
200  // (if NumRes(op) > 0)
202  (size_t) std::numeric_limits<addr_t>::max() >= num_var_rec_ - 1,
203  "cppad_tape_addr_type maximum value has been exceeded"
204  )
205 
206  return static_cast<addr_t>( num_var_rec_ - 1 );
207 }
208 
209 /*!
210 Put next LdpOp or LdvOp operator in operation sequence (special cases).
211 
212 This sets the op code for the next operation in this recording.
213 This call must be followed by putting the corresponding
214 \verbatim
215  NumArg(op)
216 \endverbatim
217 argument indices in the recording.
218 
219 \param op
220 Is the op code corresponding to the the operation that is being
221 recorded (which must be LdpOp or LdvOp).
222 
223 \return
224 The return value is the index of the primary (last) variable
225 corresponding to the result of this operation.
226 The number of variables corresponding to the operation is given by
227 \verbatim
228  NumRes(op)
229 \endverbatim
230 which must be one for this operation.
231 With each call to PutLoadOp or PutOp,
232 the return index increases by the number of variables corresponding
233 to this call to the call.
234 This index starts at zero after the default constructor
235 and after each call to Erase.
236 
237 \par num_load_op_rec()
238 The return value for <code>num_load_op_rec()</code>
239 increases by one after each call to this function
240 (and starts at zero after the default constructor or Erase).
241 */
242 template <class Base>
244 { size_t i = op_vec_.extend(1);
246  (abort_op_index_ == 0) || (abort_op_index_ != i),
247  "This is the abort operator index specified by "
248  "Independent(x, abort_op_index)."
249  );
250  op_vec_[i] = op;
251  CPPAD_ASSERT_UNKNOWN( op_vec_.size() == i + 1 );
252  CPPAD_ASSERT_UNKNOWN( (op == LdpOp) | (op == LdvOp) );
253 
254  // first operator should be a BeginOp and NumRes( BeginOp ) > 0
255  num_var_rec_ += NumRes(op);
256  CPPAD_ASSERT_UNKNOWN( num_var_rec_ > 0 );
257 
258  // count this vecad load operation
259  num_load_op_rec_++;
260 
261  // index of last variable corresponding to this operation
262  // (if NumRes(op) > 0)
264  (size_t) std::numeric_limits<addr_t>::max() >= num_var_rec_ - 1,
265  "cppad_tape_addr_type maximum value has been exceeded"
266  )
267  return static_cast<addr_t>( num_var_rec_ - 1 );
268 }
269 
270 /*!
271 Add a value to the end of the current vector of VecAD indices.
272 
273 For each VecAD vector, this routine is used to store the length
274 of the vector followed by the parameter index corresponding to each
275 value in the vector.
276 This value for the elements of the VecAD vector corresponds to the
277 beginning of the operation sequence.
278 
279 \param vec_ind
280 is the index to be palced at the end of the vector of VecAD indices.
281 
282 \return
283 is the index in the vector of VecAD indices corresponding to this value.
284 This index starts at zero after the recorder default constructor
285 and after each call to Erase.
286 It increments by one for each call to PutVecInd..
287 */
288 template <class Base>
289 inline addr_t recorder<Base>::PutVecInd(size_t vec_ind)
290 { size_t i = vecad_ind_vec_.extend(1);
291  CPPAD_ASSERT_UNKNOWN( std::numeric_limits<addr_t>::max() >= vec_ind );
292  vecad_ind_vec_[i] = addr_t( vec_ind );
293  CPPAD_ASSERT_UNKNOWN( vecad_ind_vec_.size() == i + 1 );
294 
296  std::numeric_limits<addr_t>::max() >= i,
297  "cppad_tape_addr_type maximum value has been exceeded"
298  );
299  return static_cast<addr_t>( i );
300 }
301 
302 /*!
303 Find or add a parameter to the current vector of parameters.
304 
305 \param par
306 is the parameter to be found or placed in the vector of parameters.
307 
308 \return
309 is the index in the parameter vector corresponding to this parameter value.
310 This value is not necessarily placed at the end of the vector
311 (because values that are identically equal may be reused).
312 */
313 template <class Base>
315 { static size_t hash_table[CPPAD_HASH_TABLE_SIZE * CPPAD_MAX_NUM_THREADS];
316  size_t i;
317  size_t code;
318 
320  thread_offset_ / CPPAD_HASH_TABLE_SIZE
321  ==
323  );
324 
325  // get hash code for this value
326  code = static_cast<size_t>( hash_code(par) );
328 
329  // If we have a match, return the parameter index
330  i = hash_table[code + thread_offset_];
331  if( i < par_vec_.size() && IdenticalEqualPar(par_vec_[i], par) )
333  static_cast<size_t>( std::numeric_limits<addr_t>::max() ) >= i,
334  "cppad_tape_addr_type maximum value has been exceeded"
335  )
336  return static_cast<addr_t>( i );
337  }
338 
339  // place a new value in the table
340  i = par_vec_.extend(1);
341  par_vec_[i] = par;
342  CPPAD_ASSERT_UNKNOWN( par_vec_.size() == i + 1 );
343 
344  // make the hash code point to this new value
345  hash_table[code + thread_offset_] = i;
346 
347  // return the parameter index
349  static_cast<size_t>( std::numeric_limits<addr_t>::max() ) >= i,
350  "cppad_tape_addr_type maximum value has been exceeded"
351  )
352  return static_cast<addr_t>( i );
353 }
354 // -------------------------- PutArg --------------------------------------
355 /*!
356 Prototype for putting operation argument indices in the recording.
357 
358 The following syntax
359 \verbatim
360  rec.PutArg(arg0)
361  rec.PutArg(arg0, arg1)
362  .
363  .
364  .
365  rec.PutArg(arg0, arg1, ..., arg5)
366 \endverbatim
367 places the values passed to PutArg at the current end of the
368 operation argument indices for the recording.
369 \a arg0 comes before \a arg1, etc.
370 The proper number of operation argument indices
371 corresponding to the operation code op is given by
372 \verbatim
373  NumArg(op)
374 \endverbatim
375 The number of the operation argument indices starts at zero
376 after the default constructor and each call to Erase.
377 It increases by the number of indices placed by each call to PutArg.
378 */
379 inline void prototype_put_arg(void)
380 { // This routine should not be called
381  CPPAD_ASSERT_UNKNOWN(false);
382 }
383 /*!
384 Put one operation argument index in the recording
385 
386 \param arg0
387 The operation argument index
388 
389 \copydetails prototype_put_arg
390 */
391 template <class Base>
393 {
394  size_t i = arg_vec_.extend(1);
395  arg_vec_[i] = static_cast<addr_t>( arg0 );
396  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + 1 );
397 }
398 /*!
399 Put two operation argument index in the recording
400 
401 \param arg0
402 First operation argument index.
403 
404 \param arg1
405 Second operation argument index.
406 
407 \copydetails prototype_put_arg
408 */
409 template <class Base>
410 inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1)
411 {
412  size_t i = arg_vec_.extend(2);
413  arg_vec_[i++] = static_cast<addr_t>( arg0 );
414  arg_vec_[i] = static_cast<addr_t>( arg1 );
415  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + 1 );
416 }
417 /*!
418 Put three operation argument index in the recording
419 
420 \param arg0
421 First operation argument index.
422 
423 \param arg1
424 Second operation argument index.
425 
426 \param arg2
427 Third operation argument index.
428 
429 \copydetails prototype_put_arg
430 */
431 template <class Base>
432 inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2)
433 {
434  size_t i = arg_vec_.extend(3);
435  arg_vec_[i++] = static_cast<addr_t>( arg0 );
436  arg_vec_[i++] = static_cast<addr_t>( arg1 );
437  arg_vec_[i] = static_cast<addr_t>( arg2 );
438  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + 1 );
439 }
440 /*!
441 Put four operation argument index in the recording
442 
443 \param arg0
444 First operation argument index.
445 
446 \param arg1
447 Second operation argument index.
448 
449 \param arg2
450 Third operation argument index.
451 
452 \param arg3
453 Fourth operation argument index.
454 
455 \copydetails prototype_put_arg
456 */
457 template <class Base>
458 inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2,
459  addr_t arg3)
460 {
461  size_t i = arg_vec_.extend(4);
462  arg_vec_[i++] = static_cast<addr_t>( arg0 );
463  arg_vec_[i++] = static_cast<addr_t>( arg1 );
464  arg_vec_[i++] = static_cast<addr_t>( arg2 );
465  arg_vec_[i] = static_cast<addr_t>( arg3 );
466  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + 1 );
467 
468 }
469 /*!
470 Put five operation argument index in the recording
471 
472 \param arg0
473 First operation argument index.
474 
475 \param arg1
476 Second operation argument index.
477 
478 \param arg2
479 Third operation argument index.
480 
481 \param arg3
482 Fourth operation argument index.
483 
484 \param arg4
485 Fifth operation argument index.
486 
487 \copydetails prototype_put_arg
488 */
489 template <class Base>
490 inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2,
491  addr_t arg3, addr_t arg4)
492 {
493  size_t i = arg_vec_.extend(5);
494  arg_vec_[i++] = static_cast<addr_t>( arg0 );
495  arg_vec_[i++] = static_cast<addr_t>( arg1 );
496  arg_vec_[i++] = static_cast<addr_t>( arg2 );
497  arg_vec_[i++] = static_cast<addr_t>( arg3 );
498  arg_vec_[i] = static_cast<addr_t>( arg4 );
499  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + 1 );
500 
501 }
502 /*!
503 Put six operation argument index in the recording
504 
505 \param arg0
506 First operation argument index.
507 
508 \param arg1
509 Second operation argument index.
510 
511 \param arg2
512 Third operation argument index.
513 
514 \param arg3
515 Fourth operation argument index.
516 
517 \param arg4
518 Fifth operation argument index.
519 
520 \param arg5
521 Sixth operation argument index.
522 
523 \copydetails prototype_put_arg
524 */
525 template <class Base>
526 inline void recorder<Base>::PutArg(addr_t arg0, addr_t arg1, addr_t arg2,
527  addr_t arg3, addr_t arg4, addr_t arg5)
528 {
529  size_t i = arg_vec_.extend(6);
530  arg_vec_[i++] = static_cast<addr_t>( arg0 );
531  arg_vec_[i++] = static_cast<addr_t>( arg1 );
532  arg_vec_[i++] = static_cast<addr_t>( arg2 );
533  arg_vec_[i++] = static_cast<addr_t>( arg3 );
534  arg_vec_[i++] = static_cast<addr_t>( arg4 );
535  arg_vec_[i] = static_cast<addr_t>( arg5 );
536  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + 1 );
537 }
538 // --------------------------------------------------------------------------
539 /*!
540 Reserve space for arguments, but delay placing values there.
541 
542 \param n_arg
543 number of arguements to reserve space for
544 
545 \return
546 is the index in the argument vector corresponding to the
547 first of the arguments being reserved.
548 */
549 template <class Base>
550 inline size_t recorder<Base>::ReserveArg(size_t n_arg)
551 {
552  size_t i = arg_vec_.extend(n_arg);
553  CPPAD_ASSERT_UNKNOWN( arg_vec_.size() == i + n_arg );
554  return i;
555 }
556 
557 /*!
558 \brief
559 Replace an argument value in the recording
560 (intended to fill in reserved values).
561 
562 \param i_arg
563 is the index, in argument vector, for the value that is replaced.
564 
565 \param value
566 is the new value for the argument with the specified index.
567 */
568 template <class Base>
569 inline void recorder<Base>::ReplaceArg(size_t i_arg, size_t value)
570 { arg_vec_[i_arg] = static_cast<addr_t>( value ); }
571 // --------------------------------------------------------------------------
572 /*!
573 Put a character string in the text for this recording.
574 
575 \param text
576 is a '\\0' terminated character string that is to be put in the
577 vector of characters corresponding to this recording.
578 The terminator '\\0' will be included.
579 
580 \return
581 is the offset with in the text vector for this recording at which
582 the character string starts.
583 */
584 template <class Base>
585 inline addr_t recorder<Base>::PutTxt(const char *text)
586 {
587  // determine length of the text including terminating '\0'
588  size_t n = 0;
589  while( text[n] != '\0' )
590  n++;
591  CPPAD_ASSERT_UNKNOWN( n <= 1000 );
592  n++;
593  CPPAD_ASSERT_UNKNOWN( text[n-1] == '\0' );
594 
595  // copy text including terminating '\0'
596  size_t i = text_vec_.extend(n);
597  size_t j;
598  for(j = 0; j < n; j++)
599  text_vec_[i + j] = text[j];
600  CPPAD_ASSERT_UNKNOWN( text_vec_.size() == i + n );
601 
603  std::numeric_limits<addr_t>::max() >= i,
604  "cppad_tape_addr_type maximum value has been exceeded"
605  );
606  //
607  return static_cast<addr_t>( i );
608 }
609 // -------------------------------------------------------------------------
610 
611 
612 } } // END_CPPAD_LOCAL_NAMESPACE
613 # endif
~recorder(void)
Destructor.
Definition: recorder.hpp:83
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
addr_t PutOp(OpCode op)
Put next operator in the operation sequence.
Definition: recorder.hpp:185
void clear(void)
Remove all the elements from this vector and free its memory.
Definition: pod_vector.hpp:246
recorder(void)
Default constructor.
Definition: recorder.hpp:66
size_t abort_op_index_
operator index at which to abort recording with an error (do not abort when zero) ...
Definition: recorder.hpp:37
CPPAD_TAPE_ADDR_TYPE addr_t
Definition: declare_ad.hpp:44
pod_vector< OpCode > op_vec_
The operators in the recording.
Definition: recorder.hpp:49
pod_vector< Base > par_vec_
The parameters in the recording. Note that Base may not be plain old data, so use false in consructor...
Definition: recorder.hpp:59
addr_t PutTxt(const char *text)
Put a character string in the text for this recording.
Definition: recorder.hpp:585
size_t ReserveArg(size_t n_arg)
Reserve space for arguments, but delay placing values there.
Definition: recorder.hpp:550
Class used to store and play back an operation sequence recording.
Definition: declare_ad.hpp:27
pod_vector< addr_t > vecad_ind_vec_
The VecAD indices in the recording.
Definition: recorder.hpp:52
size_t num_load_op_rec(void) const
Number of LdpOp and LdvOp operations currently in the recording.
Definition: recorder.hpp:140
Capacity vector for memory allocation block sizes.
static size_t thread_num(void)
Get current thread number.
size_t num_var_rec(void) const
Number of variables currently stored in the recording.
Definition: recorder.hpp:136
void PutArg(addr_t arg0)
Put one operation argument index in the recording.
Definition: recorder.hpp:392
size_t NumRes(OpCode op)
Number of variables resulting from the specified operation.
Definition: op_code.hpp:281
File used to define pod_vector class.
addr_t PutPar(const Base &par)
Find or add a parameter to the current vector of parameters.
Definition: recorder.hpp:314
addr_t PutLoadOp(OpCode op)
Put a vecad load operator in the operation sequence (special case)
Definition: recorder.hpp:243
OpCode
Type used to distinguish different AD&lt; Base &gt; atomic operations.
Definition: op_code.hpp:49
size_t num_var_rec_
Number of variables in the recording.
Definition: recorder.hpp:43
void free(void)
Frees all information in recording.
Definition: recorder.hpp:94
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
pod_vector< char > text_vec_
Character strings (&#39;\0&#39; terminated) in the recording.
Definition: recorder.hpp:62
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
bool IdenticalEqualPar(const std::complex< double > &x, const std::complex< double > &y)
const size_t thread_offset_
offset for this thread in the static hash table
Definition: recorder.hpp:40
size_t num_load_op_rec_
Number vecad load operations (LdpOp or LdvOp) currently in recording.
Definition: recorder.hpp:46
size_t num_op_rec(void) const
Number of operators currently stored in the recording.
Definition: recorder.hpp:144
unsigned short hash_code(const Value &value)
General purpose hash code for an arbitrary value.
void set_abort_op_index(size_t abort_op_index)
Set the abort index.
Definition: recorder.hpp:75
size_t get_abort_op_index(void)
Get the abort index.
Definition: recorder.hpp:79
size_t capacity(void) const
current capacity (amount of allocated storage) for this vector.
Definition: pod_vector.hpp:83
CppAD hashing utility.
addr_t PutVecInd(size_t vec_ind)
Add a value to the end of the current vector of VecAD indices.
Definition: recorder.hpp:289
size_t Memory(void) const
Approximate amount of memory used by the recording.
Definition: recorder.hpp:148
void prototype_put_arg(void)
Prototype for putting operation argument indices in the recording.
Definition: recorder.hpp:379
#define CPPAD_HASH_TABLE_SIZE
the codes retruned by hash_code are between zero and CPPAD_HASH_TABLE_SIZE minus one.
Definition: base_hash.hpp:82
void ReplaceArg(size_t i_arg, size_t value)
Replace an argument value in the recording (intended to fill in reserved values). ...
Definition: recorder.hpp:569
pod_vector< addr_t > arg_vec_
The argument indices in the recording.
Definition: recorder.hpp:55