/**
     * Copy-construct a JeodPointerContainer.
     * @note
     * This copies the Container contents, but not the Checkpointable contents.
     * @param source Pointer container to be copied.
     */


/**
     * Initialize a checkpointable object, called by the checkpoint manager.
     *
     * In the case of a JeodPointerContainer, this method gets the descriptor for
     * the type of data pointed to members of the container.
     */


/**
     * Erase a sequence of items.
     * @param first First element to be erased
     * @param last  One past last element to be erased
     */


/**
     * Extends the list by @a ncopies elements before the iterator @a position,
     * initializing each newly created element with @a new_elem.
     * @param position  Insertion position
     * @param ncopies   Number of elements to be inserted
     * @param new_elem  Element value to be inserted
     */


/**
     * Inserts the element @a other_pos of @a other before @a position,
     * deleting that element from @a other.
     */


/**
     * Inserts elements in @a other from @a first up to but not including
     * @a last before @a position, deleting those element from @a other.
     */


/**
     * Convert a primitive value to its string-equivalent.
     */


/**
     * Convert a string to its corresponding primitive value.
     */


/**
     * Find the start and end of a sequence specified by the given key.
     */


/**
     * Inserts the provided value into the associative list.
     * @param new_elem  Element value to be inserted
     */


/**
     * Construct a JeodObjectContainer.
     */


/**
     * Copy-construct a JeodObjectContainer.
     * @note
     * This copies the Container contents, but not the Checkpointable contents.
     * @param source Object container to be copied.
     */


/**
     * Prepare to checkpoint a JeodObjectContainer.
     * The contents of an object container is checkpointed by allocating a
     * C-style array of the same size as the container and populating the
     * array with copies of the container contents. The existing checkpoint
     * capabilities will checkpoint this array, so all that remains to be done
     * is to associate the array elements with the container.
     */


/**
     * Cleanup after performing a checkpoint.
     */


/**
     * Prepare to checkpoint the object in question.
     * The local checkpoint index is initialized to zero to reflect that the
     * parent class' checkpoint iterator starts at the zeroth element.
     */


/**
     * Advance to the next item to be checkpointed.
     * The local checkpoint index is advanced to keep in sync with the
     * parent class' checkpoint iterator.
     */


/**
     * Interpret the provided value and add it to the list.
     * For a JeodObjectContainer, the value should name an element of the
     * C-style copy of the object's contents.
     */


/**
     * Cleanup detritus created during the restore process.
     * Here we delete the temporary array created during checkpoint.
     * @param value String name of cleanup target.
     */


/**
     * In general, respond to the actions recorded in the checkpoint file.
     * For this class, the only recorded action is "restore", and the response
     * is to invoke the (undefined) simple_restore method.
     * @param action_name  The name of the action; here just "restore".
     * @param action_value The value of the action; here ignored.
     * @return             Success (zero) / failure (non-zero).
     */


/**
 * Convert a string to a string suitable for output.
 * Special characters are backslash-escaped.
 * @return Serialized string
 * \param[in] val String to serialize
 */


/**
 * Convert a serialized string to its internal representation.
 * Backslash-escaped characters are converted to special characters.
 * @return Deserialized string
 * \param[in] val Serialized string
 */


/**
 * Convert a float to a string suitable for output.
 * NaNs and Infs get special treatment.
 * Everything is serialized via c++ I/O.
 * @return Serialized number
 * \param[in] val Number to serialize
 */


/**
 * Convert a serialized float to its internal representation.
 * @return Deserialized float
 * \param[in] val Serialized string
 */


/**
 * Convert a double to a string suitable for output.
 * NaNs and Infs get special treatment.
 * Everything is serialized via c++ I/O.
 * @return Serialized number
 * \param[in] val Number to serialize
 */


/**
 * Convert a serialized double to its internal representation.
 * @return Deserialized double
 * \param[in] val Serialized string
 */


/**
 * Convert a long double to a string suitable for output.
 * NaNs and Infs get special treatment.
 * Everything is serialized via c++ I/O.
 * @return Serialized number
 * \param[in] val Number to serialize
 */


/**
 * Convert a serialized double to its internal representation.
 * @return Deserialized long double
 * \param[in] val Serialized string
 */


/**
 * Update from Cartesian position input.
 * \param[in] cart Cartesian coords, PCPF\n Units: M
 */


/**
 * Update from Spherical position input.
 * \param[in] spher Spherical AltLatLong position
 */


/**
 * Update from Elliptical position input.
 * \param[in] ellip Elliptical AltLatLong position
 */


/**
 * Build NED frame state based on current reference point information.
 */


/**
 * Build NED frame state based on current reference point information.
 * \param[in] pos Cartesian position, PCPF\n Units: M
 * \param[in] vel Cartesian velocity, PCPF\n Units: M/s
 */


/**
 * Allow user to set member data.
 * \param[in] alt Altitude\n Units: M
 * \param[in] lat Longitude\n Units: r
 * \param[in] lon Latitude\n Units: r
 */


/**
 * Allow user to get member data.
 * \param[out] alt_out Altitude\n Units: M
 * \param[out] lat_out Longitude\n Units: r
 * \param[out] lon_out Latitude\n Units: r
 */


/**
 * Convert from cartesian to spherical position
 */


/**
 * Convert from cartesian to elliptical position
 */


/**
 * Convert from spherical to cartesian position
 */


/**
 * Convert from elliptical to cartesian position
 */


/*******************************************************************************
Function: PlanetFixedPosition::get_elliptic_parameters
Purpose: Calculate latitude and altitude of a Cartesian point relative to
an oblate ellipsoid.
References:
(((Borkowski, K.m)
(Accurate Algorithms To Transform Geocentric To Geodetic Coordinates)
(Bull. God., 63 (1989), pp. 5056.)))
*******************************************************************************/


/**
 * Setter for Foo::num.
 */


/**
 * Destruct an LvlhFrame object.
 */


/**
 * Begin initialization of an LvlhFrame.
 * \param[in,out] dyn_manager Dynamics manager
 */


/**
 * Update the state.
 */


/**
 * Update the state of the LVLH frame wrt its parent.
 * \param[in] rel_trans Planet relative state
 */


/**
 * Compute the parent-to-child left quaternion from the input
 * transformation matrix.
 *
 * \par Assumptions and Limitations
 *  - Matrix is orthonormal.
 * \param[in] T Transformation matrix
 */


/**
 * Compute the parent-to-child transformation matrix from the
 * parent-to-child left quaternion.
 *
 * \par Assumptions and Limitations
 *  - Quaternion is normalized.
 * \param[out] T Transformation matrix
 */


/**
 * Construct a quaternion; default constructor.
 */


/**
 * Compute the minimum interpolation quaternion
 * between a start quarternion and end quaternion
 * \param[in] q1 Starting quaternion
 * \param[in] q2 Ending quaternion
 * \param[in] T Interpolation coefficient between
 * 0.0 and 1.0 representing a rotational scale factor
 * between the intial and final quaternion. When the compute_slerp
 * method is used in a loop to rotate an object from a start and end
 * orientation, a smaller step or change in T results in a smoother
 * object rotation
 */


/**
 * Compute the eigen rotation corresponding to a quaternion.
 *
 * \par Assumptions and Limitations
 *  - Quaternion is normalized.
 * \param[out] eigen_angle Eigen angle\n Units: r
 * \param[out] eigen_axis Eigen axis
 */


/**
 * Normalize the quaternion,
 * making the scalar part of the quaternion non-negative.
 */


/**
 * Normalize the quaternion,
 * but do not make the scalar part non-negative.
 */


/**
 * Normalize the quaternion,
 * but do not make the scalar part non-negative.
 * @param quat  Quaternion to be normalized.
 */


/**
 * Construct from a scalar and a vector.
 * \param[in] s Scalar part
 * \param[in] v Vector part
 */


/**
 * Set all components of the quaternion to zero.
 */


/**
 * Make the quaternion represent an identity transform.
 */


/**
 * Copy a quaternion to a four vector, with the scalar part copied
 * to arr[0] and the vector part to arr[1] to arr[3].
 * \param[out] arr Copy of quaternion
 */


/**
 * Copy a quaternion from a four vector, with the scalar part of
 * the quaternion in arr[0] and the vector part in arr[1] to arr[3].
 * \param[in] arr Quaternion source
 */


/**
 * Construct the quaternion corresponding to an eigen rotation.
 * \param[in] eigen_angle Eigen angle\n Units: r
 * \param[in] eigen_axis Eigen axis
 */


/**
 * Scale the quaternion by a real.
 * \param[in] fact Scale factor
 */


/**
 * Scale the quaternion by a real, leaving original intact.
 * \param[in] fact Scale factor
 * \param[out] quat Scaled quaternion
 */


/**
 * Form the normalized quaternion, leaving original intact.
 * \param[out] quat Normalized quaternion
 */


/**
 * Form the conjugate of a quaternion, leaving original intact.
 * \param[out] quat Conjugated quaternion
 */


/**
 * Post-multiply this quaternion by another quaternion:
 * prod = this * quat.
 * \param[in] quat Right multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Post-multiply this quaternion by another quaternion:
 * this = this * quat.
 * \param[in] quat Right multiplicand
 */


/**
 * Post-multiply this quaternion's conjugate by another quaternion:
 * prod = conj(this) * quat.
 * \param[in] quat Right multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Post-multiply this quaternion's conjugate by another quaternion:
 * this = conj(this) * quat.
 * \param[in] quat Right multiplicand
 */


/**
 * Post-multiply this quaternion by another's conjugate:
 * prod = this * conj(quat).
 * \param[in] quat Right multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Post-multiply this quaternion by another's conjugate:
 * this = this * conj(quat).
 * \param[in] quat Right multiplicand
 */


/**
 * Pre-multiply this quaternion by another quaternion:
 * prod = quat * this.
 * \param[in] quat Left multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Pre-multiply this quaternion by another quaternion:
 * this = quat * this.
 * \param[in] quat Left multiplicand
 */


/**
 * Pre-multiply this quaternion by another's conjugate:
 * prod = conj(quat) * this.
 * \param[in] quat Left multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Pre-multiply this quaternion by another's conjugate:
 * this = conj(quat) * this.
 * \param[in] quat Left multiplicand
 */


/**
 * Pre-multiply this quaternion by a pure imaginary
 * quaternion, the latter represented by a vector:
 * prod = [0, vec] * quat.
 * \param[in] vec Right multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Post-multiply this quaternion by a pure imaginary
 * quaternion, the latter represented by a vector:
 * prod = quat * [0, vec].
 * \param[in] vec Right multiplicand
 * \param[out] prod Quaternion product
 */


/**
 * Transform a vector.
 * \param[in] vec_in Vector to be transformed
 * \param[out] vec_out Transformed vector
 */


/**
 * Compute eigen decomposition of this*conj(quat).
 * \param[in] quat Quaternion to compare to
 * \param[out] eigen_angle Eigen angle\n Units: r
 * \param[out] eigen_axis Eigen axis
 */


/**
 * Compute the time derivative of a left quaternion.
 * \param[in] ang_vel Angular velocity\n Units: r/s
 * \param[out] qdot Quaternion derivative
 */


/**
 * Compute the time derivative of a left quaternion.
 * \param[in] ang_vel Angular velocity\n Units: r/s
 * \param[in] ang_acc Angular acceleration\n Units: r/s2
 * \param[out] qddot Quaternion 2nd deriv
 */


/**
 * Compute the time derivative of a left quaternion.
 * \param[in] quat Quaternion as 4-vector
 * \param[in] ang_vel Angular velocity\n Units: r/s
 * \param[out] qdot Derivative as 4-vector
 */


/**
 * Compute the second time derivative of a left quaternion.
 * \param[in] quat Quaternion as 4-vector
 * \param[in] ang_vel Angular velocity\n Units: r/s
 * \param[in] ang_acc Angular acceleration\n Units: r/s2
 * \param[out] qddot 2nd derivative as 4-vector
 */


/**
 * Activate a Subscription object.
 *
 * \par Assumptions and Limitations
 *  - Activation is valid for this object.
 */


/**
 * Deactivate a Subscription object.
 *
 * \par Assumptions and Limitations
 *  - Activation is valid for this object.
 */


/**
 * Add a subscription to a Subscription object.
 *
 * \par Assumptions and Limitations
 *  - Subscription is valid for this object.
 */


/**
 * Remove a subscription to a Subscription object.
 *
 * \par Assumptions and Limitations
 *  - Subscription is valid for this object.
 */


/**
 * Return a string indicating the set items.
 * @return Set items, by name
 * \param[in] test_items Items enum value
 */


/**
 * RefFrameManager default constructor.
 */


/**
 * Add a reference frame to the reference frame registry.
 * @param ref_frame  Reference frame to be added.
 */


/**
 * Remove a reference frame from the reference frame registry.
 * @param ref_frame  Reference frame to be removed.
 */


/**
 * Find the reference frame with the given name.
 * @param name  Reference frame name
 * @return Found reference frame, or NULL if not found
 */


/**
 * Find the reference frame with the dot-conjoined name "${prefix}.${suffix}".
 * @param prefix  Reference frame name prefix
 * @param suffix  Reference frame name suffix
 * @return Found reference frame, or NULL if not found
 */


/**
 * Check that each active reference frame has an owner.
 */


/**
 * Insert a reference frame in the reference frame tree.
 * @param ref_frame  Reference frame to be added to the ref frame tree.
 * @param parent     Parent frame
 */


/**
 * Subscribe to a reference frame, with the frame specified by name.
 *
 * ## Assumptions and limitations:
 *  - A subscriber should not double-subscribe to a frame.
 *
 * @param frame_name  Name of reference frame
 */


/**
 * Remove subscription to a reference frame, with the frame specified by name.
 *
 * ## Assumptions and limitations:
 *  - The caller is subscribed to the frame.
 *
 * @param frame_name  Name of reference frame
 */


/**
 * Remove subscription to a reference frame, with the frame specified as
 * an argument.
 *
 * ## Assumptions and limitations:
 *  - The caller is subscribed to the frame.
 *
 * @param frame  The reference frame
 */


/**
 * Checks whether frame has subscribers; frame specified by name.
 * @param frame_name  Name of reference frame
 * @return True if the frame has subscribers; false otherwise.
 */


/**
 * Check whether a name is trivially valid/invalid.
 * @param file            Usually __FILE__
 * @param line            Usually __LINE__
 * @param variable_value  Value to check
 * @param variable_type   Variable description
 * @param variable_name   Variable name
 * @return True if the name is valid, false if invalid.
 */


/**
 * Copy a reference frame state, negated.
 * \param[in] source Source state
 */


/**
 * Compute S_A:C = S_A:B + S_B:C,
 * with this initially containing S_B:C,
 * the supplied argument containing S_A:B, and
 * the resultant composition of states stored in this.
 * \param[in] s_ab Left addend
 */


/**
 * Compute S_A:C = S_A:B + S_B:C,
 * with this initially containing S_A:B,
 * the supplied argument containing S_B:C, and
 * the resultant composition of states stored in this.
 * Note that this function is untested, as it is not
 * used in the Reference Frame Model at any point, and
 * is only given here as a utility function.
 * \param[in] s_bc Right addend
 */


/**
 * Compute S_B:C = (-S_A:B) + S_A:C,
 * with this initially containing S_A:C,
 * the supplied argument containing S_A:B, and
 * the resultant composition of states stored in this.
 * \param[in] s_ab Left addend
 */


/**
 * Compute S_A:B = S_A:C + (-S_B:C)
 * with this initially containing S_A:C,
 * the supplied argument containing S_B:C, and
 * the resultant composition of states stored in this.
 * \param[in] s_bc Left addend
 */


/**
 * Compute the complete state of the invoking reference frame (*this)
 * with respect to the supplied wrt_frame reference frame.
 * The state will include:
 *   - The position and velocity of the invoking frame with respect to the
 *     supplied wrt_frame, expressed in the coordinates of the wrt_frame.
 *   - The angular velocity of the invoking frame with respect to the
 *     supplied wrt_frame, expressed in the coordinates of invoking frame.
 *   - The transformation (as a matrix and a quaternion) from the supplied
 *     wrt_frame to the invoking frame.
 *
 * \par Assumptions and Limitations
 *  - The two frames are in the same tree.
 * \param[in] wrt_frame The frame with respect to which the state is to be expressed
 * \param[out] rel_state The relative state
 */


/**
 * Compute the complete state of the invoking reference frame (*this)
 * with respect to the supplied wrt_frame reference frame.
 * If reverse_sense is false, the results are those from
 * the simpler two argument form of RefFrame::compute_relative_state.
 * If reverse_sense is true, the results from the two
 * argument form are transformed as follows:
 *   - The position and velocity are those the invoking frame with respect to the
 *     supplied wrt_frame, but expressed in invoking frame coordinates.
 *   - The angular velocity of the invoking frame with respect to the
 *     supplied wrt_frame, expressed in the coordinates of supplied wrt_frame.
 *   - The transformation (as a matrix and a quaternion) from the invoking
 *     frame to the supplied wrt_frame.
 *
 * \par Assumptions and Limitations
 *  - The two frames are in the same tree.
 * \param[in] wrt_frame The frame with respect to which the state is to be expressed
 * \param[in] reverse_sense Express position and velocity in this frame,
 *    angular velocity in the wrt_frame, and the transformations from this
 *    frame to the wrt_frame.
 * \param[out] rel_state The relative state
 */


/**
 * Compute the complete state of the invoking reference
 * frame with respect to the supplied reference frame, which *must*
 * be a predecessor of the invoking frame.
 *
 * \par Assumptions and Limitations
 *  - The predecessor frame is a predecessor.
 * \param[in] pred_frame The frame with respect to which the state is to be expressed
 * \param[out] rel_state The relative state
 */


/**
 * Compute the complete state of the invoking reference
 * frame with respect to the supplied reference frame, which *must*
 * be a predecessor of the invoking frame.
 *
 * \par Assumptions and Limitations
 *  - The predecessor frame is a predecessor.
 * \param[in] pred_frame_index  The frame with respect to which the state is to be expressed
 * \param[out] rel_state        The relative state
 */


/**
 * Compute the complete state of the supplied reference frame
 * wrt the invoking reference frame. The supplied reference frame
 * must be a predecessor of the invoking frame.
 *
 * \par Assumptions and Limitations
 *  - The predecessor frame is a predecessor.
 * \param[in] pred_frame_index  The frame with respect to which the state is to be expressed
 * \param[out] rel_state        The relative state
 */


/**
 * Compute the relative position vector from the origin of the
 * supplied reference frame to the origin of this reference frame,
 * expressed in the coordinates of the supplied frame.
 * \param[in] in_frame Relative position vector origin
 * \param[out] rel_pos Relative position vector\n Units: M
 */


/**
 * Construct a RefFrame object.
 */


/**
 * Destroy a RefFrame object.
 */


/**
 * Augment Subscription::set_active_status by telling the frame
 * owner that the active/inactive state of this frame has changed.
 * \param[in] value New active value
 */


/**
 * Move a node to a different place in the tree, keeping the
 * state with respect to the root frame constant.
 * \param[in] new_parent New parent frame
 */


/**
 * Determine if specified aspects of a RefFrameItems are set.
 * @return Are specified items set?
 * \param[in] test_items Test items
 */


/**
 * Set the value of a RefFrameItems.
 * @return Updated value
 * \param[in] new_value New value
 */


/**
 * Set aspects of a RefFrameItems.
 * @return Updated value
 * \param[in] new_items Items to add
 */


/**
 * Clear aspects of a RefFrameItems.
 * @return Updated value
 * \param[in] old_items Items to remove
 */


/**
     * Non-default constructor.
     * Create a TreeLinksAscendRange that walks over the entire path_to_node_
     * from the bottom to the top.
     */


/**
     * Non-default constructor.
     * Create a TreeLinksAscendRange given the start and end indices in the
     * input Links object's path_to_node_ vector.
     * Behavior is undefined if start_index > path_to_node_.size() or if
     * end_index >= start_index.
     * @param links  Object whose path_to_node_ vector is to be traversed,
     *   in reverse.
     * @param start_index  Index of the element in the path_to_node_ vector
     *   that immediately follows the initial element to be visited in a
     *   range-based for loop. For example, using path_to_node_.size()
     *   starts at the final element of the vector.
     * @param end_index  Index of the element in the path_to_node_ vector
     *   that is the last element to be visited in a range-based for loop.
     *   For example, using zero stops the iteration at the initial element
     *   in the vector.
     */


/**
     * Constructor.
     * Create a TreeLinksDescentRange the marches from the start_index node of
     * the links object's path_to_node_ vector to the last node.
     * Behavior is undefined if start_index > path_to_node_.size().
     * @param links  Object whose path_to_node_ vector is to be traversed,
     *   in reverse.
     * @param start_index  Index of the first node the path_to_node_ vector to
     *   be visited.
     */


/**
     * Default constructor.
     * Creates a range that will visit all children.
     */


/**
     * Non-default constructor.
     * @param[in,out] container_in  Object that contains this object
     * @param[in]     path_size     Initial size to reserve for the path
     */


/**
     * Accessor for the parent container, non-const version.
     * @return  Pointer to this object's parent Container object.
     */


/**
     * Accessor for the parent container, const version.
     * @return  Pointer to this object's parent Container object.
     */


/**
     * Accessor for the nth_from_root frame, non-const version.
     * @param index Path index (root=0)
     * @return Nth links container
     */


/**
     * Accessor for the nth_from_root frame, const version.
     * @param index Path index (root=0)
     * @return Nth links container
     */


/**
     * Make the links object a root object.
     */


/**
     * Add this object as a child of the frame containing these links.
     * This object must have no parent, no siblings.
     * @param new_parent Links object that is to be the parent of this object.
     */


/**
     * Detach a node from its parent.
     */


/**
     * Attach a node somewhere else.
     * @param new_parent Links object that is to be the parent of this object.
     */


/**
     * Determine if a node is the progeny of another.
     * @param target Target links object
     * @return True if target is an ancestor of this node, false otherwise.
     */


/**
     * Find the index of the node that represents the point of departure
     * in the tree containing two nodes.
     * @param target Some other node in the tree
     * @return Index of the last common node
     */


/**
     * Find the node that represents the point of departure in the tree
     * containing two nodes.
     * @param target Some other node in the tree
     * @return Pointer to last common node
     */


/**
     * Recursively construct the path_to_node.
     */


/**
     * Add a frame as a child of the frame containing these links.
     * @param new_parent The node to which this object is to be attached.
     */


/**
 * Each reference frame has a path from the root of the reference
 * frame tree to the frame in question. The paths for two reference
 * frames will have some initial sequence of common nodes.
 * Find the last element in this sequence.
 * @return Last common node
 * \param[in] frame Other frame
 */


/**
 * Initialize a RefFrameTrans to a null offset.
 */


/**
 * Initialize a RefFrameTrans from a source state.
 * \param[in] source Source state
 */


/**
 * Initialize a RefFrameRot to a null offset.
 */


/**
 * Initialize a RefFrameRot from a source state.
 * \param[in] source Source state
 */


/**
 * Compute the angular velocity unit vector.
 *
 * \par Assumptions and Limitations
 *  - Angular velocity magnitude has already been computed.
 */


/**
 * Compute the angular velocity magnitude and unit vector.
 */


/**
 * Initialize a RefFrameState to a null offset.
 */


/**
 * Initialize a RefFrameState from a source state.
 * \param[in] source Source state
 */


/**
 * Add a time change subscriber.
 * @param subscriber  Object to be added to list of subscribers.
 */


/**
 * Remove a time change subscriber.
 * @param subscriber  Object to be removed from list of subscribers.
 */


/**
 * Notify subscribers that the nature of time has changed.
 */


// JeodIntegrationGroup class registry.


// JeodIntegrationGroup default constructor, needed for checkpoint/restart.


// JeodIntegrationGroup non-default constructor.


// Add an integrable object to the vector of such.


// Remove an integrable object from the vector of such.


/**
 * Initialize the integration group.
 */


/**
     * Lsode currently does not implement a second order generalized step
     * integrator.
     */


/**
     * Lsode currently does not provide a second order generalized step
     * integrator.
     */


/**
 * verifies that the input data has legal values.
 */


/**
 * allocates space for vector-populated data to allow for restart
 */


/**
 * De-allocates allocated array.
 */


/**
 * set values from external
 */


// Non-default, basic constructor


// Clone a LsodeSimpleSecondOrderODEIntegrator, which is illegal.


/**
 * Clone a LsodeGeneralizedDerivSecondOrderODEIntegrator.
 */


// Default constructor for a LsodeFirstOrderODEIntegrator.


// Non-default constructor for a LsodeFirstOrderODEIntegrator.


/**
 * Gets the control data from where it can be populated in the
 * constructor and verifies that the input control parameters
 * are not out of sensible range.
 */


// Clone a LsodeFirstOrderODEIntegrator. (Not really. Abort instead.)


/**
 * returns the RMS value of {V dot W}, where V and W are N-vectors.
 *
 * Modified version of DVNORM
 *
 * The only places DVNORM is used, it is multiplying some array by the
 * error_weight array (arrays.error_weight) across control_data.num_odes terms.
 * These values are fixed for our application, and do not need to be passed in.
 *
 * We provide two implementations, one for a one-dimensional array, and one for
 * a two-dimensional array in which the first index is the variable.
 * \param v array
 */


/**
 * returns RMS value of v[*][index]
 *
 * Modified version of DVNORM, second implementation.
 * \param index use this index
 * \param v array
 */


/**
 * Factors a double array (arrays.lin_alg) by Gaussian elimination.
 *
 * Modified version of DGEFA.
 */


/**
 * Solves the equation Y' = A Y, with A = arrays.lin_alg.
 */


/*****************************************************************************
index_of_max_magnitude
Purpose:(Modified version of IDAMAX.  IDAMAX has 2 operations, one for
         situations in which the index increments by 1, and another for the
         converse.  Since all instances in LSODE use the unit-increment method,
         that is the only one represented here.
         Search through matrix "array", starting at
         array[start_ix_1][start_ix_2] for the next "num_points" elements.
         The boolean search_ix_1 controls whether to increment index#1 (true),
         or index#2 (false).
         Method returns the searched index that corresponds to the largest
         magnitude.

@note
The only call to this method passed "k" in for both indices, so I stripped the
second argument.  If DGBFA gets implemented, it will have to be added back in;
the call from DGBFA is for array starting at (M,K))
******************************************************************************/


/**
 * Load the externally generated derivative values (incoming as y_dot)i
 * into the array derivs.
 */


/**
 * Allocates memory for the variable size arrays
 */


/**
 * Allows for refactoring and reallocation of newly sized arrays.
 */


// LsodeSecondOrderODEIntegrator non-default constructor for a simple
// second order ODE.


// LsodeSecondOrderODEIntegrator non-default constructor for a generalized
// second order ODE in which position is advanced internally using the position
// derivative computed by the provided derivative function.


/**
 * Identify the smallest double precision value, epsilon, such that the
 * computer can distinguish (1+epsilon) from 1
 */


/**
 * Modified from original DCFODE subroutine.
 * calculate_integration_coefficients is called by dstode to set coefficients
 * needed there.
 * The coefficients for the current method, as given by the value of
 * integration_method, are set for all orders and saved.
 * The maximum order assumed here is 12 if integration_method =
 * ImplicitAdamsNonStiff and 5 if integration_method = ImplicitBackDiffStiff.
 *
 * NOTE - A smaller value of the maximum order is also allowed and may be set by
 * the user with the value control_data.max_order, which gets copied to the
 * protected value max_order_internal.
 *
 * calculate_integration_coefficients is called once at the beginning of the
 * problem, and again only if integration_method is changed.
 *
 * The coefficients are stored in two arrays:
 * method_coeffs_complete is a 13x12 array that contains a complete set of
 * coefficients for the method
 * test_coeffs_complete is a 3x12 array that contains the coefficients for local
 *                      error tests and selection of the step size and/or order.
 *               The 1st set of 12 coeffs is for order method_order_current - 1
 *               The 2nd set of 12 coeffs is for order method_order_current
 *               The 3rd set of 12 coeffs is for order method_order_current + 1
 *
 * The coefficients in method_coeffs_complete are computed by a genetrating
 * polynomial.  For a given order (note that order changes during the integration
 * process up to the maximum allowable, and is identified in the integrator as the
 * variable method_order_current), abbreviate
 *      method_coeffs_complete[i][order-1] to mcc[i]
 *
 * Then
 *   l(x) = mcc[0] + (mcc[1] * x) + (mcc[2] * x^2) + ... + mcc[order] * (x^order)
 * For the implicit Adams methods, l(x) is given by
 *     dl/dx = (x+1)*(x+2)*...*(x+order-1)/(order-1)!,    l(-1) = 0.;
 * For the BDF methods, l(x) is given by
 *     l(x) = (x+1)*(x+2)* ... *(x+order) / ((order)! * (1 + 1/2 + ... + 1/order))
 *
 * (! represents factorial)
 *
 * Note that while method_coeffs_compelte is a rectangular array for convenience,
 * it is effectively a triangular array since method_coeffs_complete[i][order-1]
 * has no meaning for i >= ( order + 2)
 * order=1:  method_coeffs_complete[0-1][0]
 * order=2:  method_coeffs_complete[0-2][1]
 * ...
 * order=12: method_coeffs_complete[0-12][11]
 * Hence a 13x12 array.
 */


/**
 * Interpolates the zeroth-derivative of y
 * Adapted from subroutine DINTDY, which was a general method for interpolating
 * the K-th derivative of the dependent variable vector, y.
 *
 * Implementation notes -
 * DINTDY was called exclusively with three input values that always matched.
 *
 * 1.  Argument #1 T (time).  Calls to DINTDY always passed TOUT (now
 * cycle_target_time) in for T
 * 2.  Argument #2 K (order).  Calls to DINTDY always passed 0 in for K
 * 3.  Argument #5 DKY (value). DKY is the value that DINTDY interpolates.i
 * Calls to DINTDY always passed Y in for DKY.
 * This routine uses y directly in place of DKY, so can only interpolate the 0-th
 * derivative (since that is y), and always evaluates at cycle_target_time.
 * replaced accordingly.
 *
 * The computed values are gotten by interpolation using the Nordsieck history
 * array, arrays.history.
 * The formula for Y is:
 *
 *  Y[i]  =  sum {j=0 to method_order_current}  {
 *         (cycle_target_time - stage_target_time)^(j) *
 *         arrays.history[i-1][j] / h^j}
 */


/**
 * Modified from DPREPJ.
 * DPREPJ was called by DSTODE to compute and process the matrix
 * P = I - h*el(1)*J , where J is an approximation to the Jacobian.
 *
 * NOTES
 *
 * DPREPJ has been split into 3 parts, book-ended by the external-calls.
 * jacobian_prep_init contains the code that precededs the first external-call
 * jacobian_prep_loop contains the code that continues to loop according to the
 * limits as written is DPREPJ.
 * jacobian_prep_wrap_up contains the code that follows successful completion of
 * the looping section of DPREPJ.
 *
 * Note that the division in this implementation is not linear with that in the
 * original Fortran.  The external calls within the original fortran are embedded
 * within switch-blocks and for loops; the return points - to go to the next
 * routine will pick up from one of several locations in the Fortran code,
 * depending on the configuration at the time the external call was made.
 *
 * For the ER7_Utils / JEOD / Trick implementation, the derivative/jac calls must
 * be external to the integrate call, so we must fully back out and then reenter.
 * Rentry goes to jacobian_prep_loop.
 *
 * Some variables that were local have been moved to the class so that their value
 * is not lost in going from jacobian_prep_init to jacobian_prep_loop.
 * These are typically identified with ***_dprepj to indicate that their sole
 * purpose is within dprepj (the original name of the jacobian_prep_* routines).
 *
 * Here the jacobian is computed by the user-supplied routine JAC if
 * corrector_method = NewtonIterUserJac or NewtonIterUserBandJac, or by finite
 * differencing if corrector_method = NewtonIterInternalJac,
 * JacobiNewtonInternalJac, or NewtonIterInternalBandJac.
 *
 * If corrector_method = JacobiNewtonInternalJac, a diagonal approximation to the
 * Jacobian is used.
 * The Jacobian is stored in arrays lin_alg
 *
 * If corrector_method != JacobiNewtonInternalJac, P is subjected to
 * LU decomposition in preparation for later solution of linear systems with P as
 * coefficient matrix.
 * This is done by gauss_elim_factor (DGEFA) if
 *          corrector_method = NewtonIterUserJac or NewtonIterInternalJac,
 *       and by linear_solver (DGBFA) if
 *          corrector_method = NewtonIterUserBandJac or NewtonIterInternalBandJac.
 *
 * Note that the corrector_method using the banded Jacobians is not supported in
 * this release, so linear_solver is not used.
 *
 * FTEM and ACOR were effectively the same, now arrays.accum_correction.
 * SAVF is now arrays.save.
 * WM is now arrays.lin_alg
 */


/***************************************************************************
jacobian_prep_loop
Purpose (Adapted from DPREPJ.  Gets called following the external function call
which follows the completion of dprej_init - formerly the first external call
from DPREPJ.  Continues to cycle back out to the exterior call as long as the
return value is false).
***************************************************************************/


/***************************************************************************
 * Wraps up the dprepj routine following completion of the loops.
 ***************************************************************************/


/**
 * Modified from DSOLSY.  This routine manages the solution of the linear
 * system arising from a chord iteration.
 * It is called if corrector_method != FunctionalIteration.
 *
 * If corrector_method == NewtonIterUserJac || NewtonIterInternalJac,
 * it calls linear_solver (was DGESL).
 * If corrector_method = JacobiNewtonInternalJac it updates the coefficient
 *     hl0 = step_size * method_coeff_first (previously H*EL0) in the diagonal
 *     matrix, and then computes the solution.
 */


/**
 * integrator_core provides the front-end to all of the integrator_*i
 * methods, which together perform one step of the integration of
 * an initial value problem for a system of ordinary differential
 * equations.
 *
 * Modified from DSTODE
 *
 * NOTES:
 * The entire integrator_* suite is independent of the value of the iteration
 * method indicator, corrector_method, when said is != 0, and hence is
 * independent of the type of chord method used, or the Jacobian structure.
 *
 * The value internal_state (JSTART) controls the direction that this method
 * takes.
 *
 * By commenting out substantial parts of the package that are not useful to the
 * ER7 / JEOD / Trick implementation, the only viable values for
 * internal_state are now 0 or 1.
 * internal_state = 0 : take the first step.
 * internal_state = 1 : take another step, continuing from the last.
 * internal_state = -1 was associated with externally driven changes to the input aprameters, something we do not allow.
 * internal_state = -2 is associated with the critical / singularity time avoidance, something we have not implemented.
 */


/**
 * Sets/resets the method_coeffs_current array
 */


/**
 * Resets history arrays and time-step
 */


/**
 * This section computes the predicted values by multiplying the
 * history array by the Pascal Triangle matrix.
 *
 * Extracted from DSTODE lines 200-215
 */


/**
 * This method resets the iteration loop to the values generated by the
 * integrator_predict method, which populated history[*][0].
 */


/**
 * This code follows part 1 after the break-out to get to the
 * external calls, and completes the reset of the integration iteration loop.
 */


/**
 * Keeps looping through the iterations until convergence or failure.
 */


/**
 * The corrector iteration failed to converge.
 * If corrector_method != FunctionalIteration and the Jacobian is out of date,
 * exit so that the Jacobian method can be called (externally) for the next try.
 * Otherwise, try changing the step-size in part 2 of the failure recovery.
 *
 * Extracted from DSTODE lines 410-430
 */


/**
 * Retracts the history array in the case that the correction iteration
 * failed to converge with either functional iteration or with an
 * up-to-date Jacobian.  If there are problems, the associated flags
 * are set.
 */


/**
 * Starts the processing of a converged iteration
 */


/**
 * The first steps in computing whether the order of the integrator
 * should be changed.
 *
 * Regardless of the success or failure of the step, the step-ratio factors for
 *   an increase, decrease, or retention of the integrator order are computed.
 * In the case of failure, the increase ratio (data_stode.step_ratio_order_inc)
 *   has already been set to 0.0 to prevent an order increase.
 * The largest of these factors is determined and the new order chosen
 *   accordingly.  In the unusual case of equality, the priority is given to:
 *       1. retain the order
 *       2. increase the order (if inc = dec > same)
 *
 * If the order is to be increased, we compute one additional scaled derivative.
 *
 * This process is spread over four methods -
 *    integrator_compute_new_order_prep
 *    integrator_compute_new_order
 *    integrator_compute_new_order_check_step_error
 *    integrator_set_new_order
 *
 * extracted from lines 520-540
 */


/**
 * Computes the step-size scaling factors that will result once it is
 * determined what happens to the order at the next step.
 */


/**
 * Sets the new order and the step-ratio for the next step - or the
 * current step if redoing it
 */


/**
 * Repopulates the y-array from history, recomputes the original first
 * derivatives, sets the order back to 1, and reduces the step size by
 * a factor of 10
 *
 * Called when 3 or more failures have occured.
 * It is assumed that the derivatives that have accumulated in the
 * history array have errors of the wrong order.  Hence the first
 * derivative is recomputed, and the order is set to 1.  Then
 * the step-size is reduced by a factor of 10, and the step is retried.
 * Repeat until successful, or the step reaches the minimum step-size.
 *
 * If 10 failures occur, exit with step_error = -1.
 *
 * This method is divided in two by a call to calculate the derivatives.
 * Part1 precedes that call, the execution exits from the integrator back to the
 * sim control engine; then on return to the integrator, execution immediately
 * proceeds with part2.
 *
 * extracted from lines 640-
 */


/**
 * Continue reset, with derivatives now at hand. See
 * integrator_fail_reset_order_1_part1 for details.
 */


/**
 * Wraps up the completion of the integrator.
 */


/**
 * this is the only succesful path back from integrator to manager.
 * All other returns from integrator_* back to manager_* are in response
 * to a need for new derivatives and carry with them a modified
 * re_entry_point to provide access back to the integrator on reentry.
 * All returns with re_entry_point = CycleStartFinish should go through
 * this method.
 */


/**
 * Perform one step of the integration process.
 */


/**
 * Propagate state via the LSODE method.
 */


/*****************************************************************************
process_entry_point_cycle_start
Purpose:(The code block from the main integrate routine for
         re_entry_point=CycleStartFinish)
Taken from DLSODE subroutine, lines 0-20, and direction up to 250.
******************************************************************************/


/**
 * Sets the values for the case with calculation_phase = 1
 */


/**
 * verifies whether the convergence conditions have been met to end
 * the cycle.
 */


/**
 * The iteration loop for the integration process.
 */


/**
 * Resets the integrator when the timestep changes or when identified
 * as needing a reset.
 */


/**
      Reset the integrators.
    */


/*
Purpose:
  (Construct an AngularVariance instance.)
*/


/**
     * Destroy the translation test state integrator.
     */


/*
Purpose: (Override the default values for xsubi_init.)
*/


/*
Purpose: (Reset the number of skips.)
*/


/*
Purpose: (Reseed the generator.)
*/


/*
Purpose: (Get a random uniform n-vector, each element between 0 and 1.)
*/


/*
Purpose:
  (Initialize an AngularVariance instance.)
 */


/*
Purpose:
  (Update an AngularVariance instance based on a new quaternion and
   angular velocity.)
Assumptions and limitations:
  ((The angular rate is sufficiently low.))
*/


/*
Purpose:
  (Update an AngularVariance instance based on a new quaternion and
   angular velocity.)
*/


/*
Purpose:
  (Pre-initialize a TranslationTest instance.)
*/


/*
Purpose:
  (Post-initialize a TranslationTest instance.)
 */


/*
Purpose:
  (Compute state derivative.)
 */


/*
Purpose:
  (Integrate the integrated state.)
 */


/*
Purpose:
  (Create a copy of the object.)
*/


/*
Purpose:
  (Pre-initialize a TranslationTestOrbit instance.)
*/


/*
Purpose:
  (Post-initialize a TranslationTestOrbit instance.)
 */


/*
Purpose:
  (Compute forces, including gravitational accel.)
 */


/*
Purpose:
  (Compute the true state and evaluate.)
*/


/*
Purpose:
  (Compute the true state.)
*/


/*
Purpose:
  (Pre-initialize a TranslationTestSpringDamper instance.)
*/


/*
Purpose:
  (Post-initialize a TranslationTestSpringDamper instance.)
 */


/*
Purpose:
  (Pre-initialize an RotationTest instance.)
*/


/*
Purpose:
  (Post-initialize a RotationTest instance.)
*/


/*
Purpose:
  (Pre-initialize a RotationTestTorqueFreeSphere instance.)
*/


/*
Purpose:
  (Post-initialize a RotationTestTorqueFreeSphere instance.)
 */


/*
Purpose:
  (Pre-initialize a RotationTestTorqueFreeSymTop instance.)
*/


/*
Purpose:
  (Post-initialize a RotationTestTorqueFreeSymTop instance.)
 */


/*
Purpose:
  (Pre-initialize a RotationTestSHOSphere instance.)
*/


/*
Purpose:
  (Post-initialize a RotationTestSHOSphere instance.)
 */


/*
Purpose:
  (Compute the integrated and true potential energy.)
*/


/*
Purpose:
  (Compute the torque on the object.)
*/


/*
Purpose:
  (Configure the test.)
*/


/*
Purpose:
  (Initialize the test.)
*/


/*
Purpose:
  (Pre-initialize an IntegrationTest instance.)
*/


/*
Purpose:
  (Generate the end of sim run report.)
*/


/*
Purpose:
  (Initialize the test items.)
*/


/*
Purpose:
  (Reset the integrators.)
 */


/*
Purpose:
  (Integrate the integrated states.)
 */


/*
Purpose: Propagate true state and compute errors.
*/


/*
Purpose: (Constructor, with seed set from numbers pulled out of a hat.)
*/


/*
Purpose: (Constructor, with seed set by a seed generator.)
*/


/*
Purpose: (Set/reset a RandomBase to its initial state.)
*/


/*
Purpose: (Return a random integer between -2**31 and 2**31-1, inclusive.)
*/


/*
Purpose: (Return a uniform random number.)
*/


/*
Purpose: (Populate a seed for initializing some random generator.)
*/


/*******************************************************************************
 Function: NewOrientation::initialize
 Purpose: (Initialize the instance from input.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::set_quaternion
 Purpose: (Reset the instance with a new quaternion.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::get_quaternion
 Purpose: (Accessor for the left transformation quaternion.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::set_matrix
 Purpose: (Reset the instance with a new matrix.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::get_matrix
 Purpose: (Accessor for the transformation matrix.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::set_eigen_rotation
 Purpose: (Reset the instance with a new eigen-rotation.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::get_eigen_rotation
 Purpose: (Accessor for the eigen rotation.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::set_euler_angles
 Purpose: (Reset the instance with a new Euler rotation.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::get_euler_angles
 Purpose: (Accessor for the Euler sequence.)
*******************************************************************************/


/*******************************************************************************
 Function: NewOrientation::compute_quaternion_from_euler_angles
 Purpose: (Compute the left transformation quaternion from the Euler sequence.)
*******************************************************************************/


/*******************************************************************************
 Function: VectorOrientation::initialize
 Purpose: (Initialize a VectorOrientation.)
*******************************************************************************/


/*******************************************************************************
 Function: RandomOrientation::RandomOrientation
 Purpose: (Constructor.)
*******************************************************************************/


/*******************************************************************************
 Function: RandomOrientation::RandomOrientation
 Purpose: (Initialize a RandomOrientation.)
*******************************************************************************/


// Size (but do not compute) the coefficients.


// Compute the coefficients.


// Configure the coefficients as an Adams corrector in difference form.


// Compute the Stormer-Cowell corrector coefficients.


// Compute predictor coefficients.
// Note: This calculation pertains to Adams and Stormer-Cowell coefficients.


// Convert the coefficients to ordinate form.
// Note: This assumes that the correct number of leading terms have been
// discarded from the front of the coefficients vector.


// Discard the specified number of coefficients from the front and back.


// Apply the operator (1-\nabla) to the coefficients.
// Note: This assumes that the correct number of leading terms have been
// discarded from the front of the coefficients vector.


/**
 * Check for invalid values in the supplied config.
 */


/**
 * Cast the provided integration controls to a GaussJacksonIntegrationControls.
 * @param  controls  Generic controls to be cast.
 * @return GaussJacksonIntegrationControls pointer, guaranteed to be non-null.
 */


/**
     * Copy constructor.
     * @param  src  Item to be copied.
     */


/**
     * Range-checked equivalent of const T* operator[](int N) const.
     * @param  N  Row index.
     * @return Const pointer to the Nth row in the array.
     * @throw  std::out_of_range  If @a N is an invalid index.
     */


/**
     * Range-checked equivalent of T* operator[](int N).
     * @param  N  Row index.
     * @return Modifiable pointer to the Nth row in the array.
     * @throw  std::out_of_range  If @a N is an invalid index.
     */


/**
     * Allocate the array.
     * @param  N  Number of rows in the array.
     * @param  M  Number of columns in the array.
     * @throw  std::domain_error  N and/or M won't fit in a signed int.
     */


/**
     * Rotate elements 0 to limit downward, with array element 0 moved to
     * array element limit.
     * @param limit  Index of last element participating in the rotation.
     * @throw  std::out_of_range  If @a limit is an invalid index.
     */


/**
     * Rotate elements 0 to limit upward, with array element limit moved to
     * array element 0.
     * @param limit  Index of last element participating in the rotation.
     * @throw  std::out_of_range  If @a limit is an invalid index.
     */


/**
     * Downsample the array by swapping pointers.
     * @param limit  Number of usable rows after downsample.
     * @throw  std::out_of_range  If @a limit represents an invalid index.
     */


/**
     * Swap the contents of *this with the other.
     * @param other Other array.
     */


/**
     * Allocate memory for the array.
     */


/**
     * Deallocate memory for the array.
     */


/**
     * Non-default constructor. This is the constructor invoked by the
     * GaussJacksonIntegratorConstructor.
     * @param  priming_constructor  Integrator constructor for the technique
     *                              used during priming.
     * @param  controls             The Gauss-Jackson integration controls that
     *                              drives this state integrator.
     * @param  size_in              State size.
     * @param  priming_controls     Integration controls used during priming.
     */


/**
     * Non-throwing swap.
     * @param  other  Item whose contents are to be swapped with this.
     */


/**
     * Non-default constructor.
     * @param  priming_constructor  Integrator constructor for the technique
     *                              used during priming.
     * @param  controls             The Gauss-Jackson integration controls that
     *                              drives this state integrator.
     * @param  size_in              State size.
     * @param  priming_controls     Integration controls used during priming.
     */


/**
     * Reset the integrator.
     */


/**
     * Downsample the acceleration and position histories.
     */


/**
     * Non-default constructor.
     * @param  first_in   The first element of the pair.
     * @param  second_in  The second element of the pair.
     */


/**
     * Copy constructor.
     * Note that this doesn't copy; it recomputes.
     * The end result is as if a copy had been made.
     * @param  src  Object to be copied.
     */


/**
     * Allocate (re-allocate) memory for the coefficients. Arrays are size
     & to contain max_order+1 elements.
     * @param  max_order  Maximum order that will be used.
     */


/**
     * Create the integrator to be managed.
     * @param[in] generator  Integrator constructor used to create the integrator.
     * @param[in,out] controls   Integration controls to be passed to the generator.
     */


/**
     * Restore the integrator on restart.
     */


/**
     * Create the integrator to be managed.
     * @param[in] technique_in  Integration technique; generalized step vs deriv.
     * @param[in] generator     Integrator constructor used to create the integrator.
     * @param[in,out] controls      Integration controls to be passed to the generator.
     */


/**
     * Destroy the integrator.
     */


/**
     * Merge an IntegratorResult into another.
     * @return True if merger was successful, false if some error occurred.
     * @param[in]      new_result     Size of the generalized position vector
     * @param[in,out]  merged_result  Size of the generalized position vector
     */


/**
     * Respond to a change in the nature of time.
     */


/**
     * Create the integrator to be managed.
     * @param[in] generator  Generator used to create the integrator.
     * @param[in,out] controls  Controls to be passed to the generator.
     */


/**
     * Determine whether output for a message is to be printed.
     * @return True => print message
     * \param[in] severity Severity level
     * \param[in] msg_code Message code
     */


/*******************************************************************************
Function: integrate
Purpose: (Always return zero)
*******************************************************************************/


/*******************************************************************************
Function: generate_messages
Purpose: (Generate messages)
*******************************************************************************/


/**
 * Register the MessageHandler's checkpointable contents.
 */


/**
 * Generate a message with negative severity, MessageHandler::Failure,
 * and terminate the simulation.
 * The intent of this method is to handle erroneous situations for which
 * no recovery path exists. If a recovery path does exist, even if very
 * suspect, callers of this method should consider calling
 * MessageHandler::error as an alternative.
 *
 * A conforming implementation of a class that derives MessageHandler
 * will force the simulation to terminate upon receipt of a
 * message with negative severity.
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] ... sprintf arguments
 */


/**
 * Generate a message with severity MessageHandler::Error.
 * An error represents a very serious problem.
 * The intent is to represent errors that invalidate simulation results
 * but for which a recovery path does exist. Using MessageHandler::error
 * rather than MessageHandler::fail enables the user to address
 * multiple errors at a time.
 *
 * A conforming implementation of a class that derives MessageHandler
 * will always report error messages. Errors should not be suppressed.
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] ... sprintf arguments
 */


/**
 * Generate a message with severity MessageHandler::Warning.
 * Warnings represent situations where the model developer had to make
 * some assumptions to recover from what would otherwise be an erroneous
 * condition. The recovery based on those assumptions does not
 * necessarily invalidate invalidate the simulation results.
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] ... sprintf arguments
 */


/**
 * Generates a message with severity MessageHandler::Notice.
 * Informational notices should not represent problems of any
 * significance as the default behavior is to suppress such messages.
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] ... sprintf arguments
 */


/**
 * Generate a message with severity MessageHandler::Debug.
 * Debug messages should never be used for erroneous conditions.
 * They should instead be used for describing nominal behavior.
 * Note that debug messages are nominally suppressed.
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] ... sprintf arguments
 */


/**
 * Generic variable arguments message interface.
 * This method gives the caller control over the severity level and over
 * the message prefix. These are automatically generated in the standard
 * set of MessageHandler interface methods.
 * \param[in] severity Severity level
 * \param[in] prefix Message prefix (e.g., Error)
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] ... sprintf arguments
 */


/**
 * Generic variable arguments message interface.
 * This method behaves similarly to MessageHandler::send_message except
 * that the caller has already captured the variable arguments in the
 * form of a va_list. Note that MessageHandler::va_send_message does not
 * call va_end macro.
 * \param[in] severity Severity level
 * \param[in] prefix Message prefix (e.g., Error)
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in,out] args Varargs stack
 */


/**
 * Set the suppression level in the global message handler.
 * \param[in] suppression_level New suppression level
 */


/**
 * Get the suppress_id of the global massage handler.
 * @return Suppression level value
 */


/**
 * Add a message code to the set of messages that are to be suppressed
 * for messages with positive severity level.
 * Note: Fatal errors and serious errors cannot be suppressed.
 * \param[in] msg_code Message code to be suppressed
 */


/**
 * Delete a message code from the set of suppressed message codes.
 * \param[in] msg_code Message code to be unsuppressed
 */


/**
 * Clear the set of suppressed message codes.
 */


/**
 * Set the suppress_id flag in the global message handler.
 * \param[in] suppress_id New suppress id value
 */


/**
 * Get the suppress_id of the global massage handler.
 * @return ID value\n Units: Suppress
 */


/**
 * Set the suppress_location in the global message handler.
 * \param[in] suppress_location New suppress_loc value
 */


/**
 * Get the suppress_location of the global massage handler.
 * @return Suppress location value
 */


/**
 * Set the message handler's simulation interface mode.
 *
 * \par Assumptions and Limitations
 *  - This method must not be called before the singleton message handler has
 *     been created or after it has been destroyed.
 *     A fatal error results when this is not true.
 * \param[in] new_mode New mode
 */


/**
 * Handle the error condition where there is no global handler.
 * @note That this condition exists means the simulation is non-compliant.
 *
 * \par Assumptions and Limitations
 *  - All JEOD-based  simulations must have a message handler and memory handler
 *     that at instantiated prior to instantiating any other JEOD-based model
 *     and destroyed after all those other models have been destroyed.
 *  - That no message handler exists means the simulation is not a compliant
 *     with the above restrictions.
 *  - The handling of this condition is intentionally simplistic.
 *     An error message is printed and the simulation is terminated
 *     via a system call to exit.
 */


/**
 * Construct a MessageHandler.
 * This default constructor sets the suppression level to
 * MessageHandler::Warning, which means that messages of that severity
 * and lower will be printed. The suppress_id and suppress_location
 * flags are set to false; auxiliary information is not suppressed.
 */


/**
 * Destruct a MessageHandler.
 */


// suffix: Find the part of the name that follows the prefix.


// validate_name: Check for illegal values (null pointer, empty string).


/**
 * Demangle a C++ name.
 * @return Demangled name
 * \param[in] info Typeinfo to be demangled
 */


/**
     * Construct a name from the given input, as a string.
     * The input must not be the empty string or the null pointer.
     */


/**
     * Default constructor.
     * This is the default constructor by virtue of the defaults.
     * @param name_in  Initial value of the name, defaults to the empty string.
     * @param frozen_in  Initial value of is_frozen, defaults to false.
     */


/**
     * Checks whether a name is trivially invalid, failing if it is.
     * \param[in] file Usually __FILE__
     * \param[in] line Usually __LINE__
     * \param[in] variable_type Variable description
     * \param[in] variable_name Variable name
     */


/**
 * Register the checkpointable object with Trick.
 * This function is typically called at construction or initialization time
 * via JEOD_REGISTER_CHECKPOINTABLE.
 *
 * \par Assumptions and Limitations
 *  - The following unenforced assumptions are made:
 *     - Sim objects have been constructed and registered with Trick.
 *     - Checkpointable objects are unique.
 *     - Trick has been pre-initialized.
 *     - Not in shutdown mode.
 *     .
 *     Enforcement of the above is the responsibility the simulation developer,
 *     the JEOD memory manager, and the simulation interface.
 * \param[in] owner Owner of the container
 * \param[in] owner_type Owner type descriptor
 * \param[in] elem_name Container element
 * \param[in,out] container The container
 */


/**
 * Construct the identifier for a checkpointable object.
 * @return Container ID
 * \param[in] entry Container list entry
 */


/**
 * Dump the checkpointable objects to the checkpoint file.
 */


/**
 * Restore the checkpointable objects from the checkpoint file.
 */


/**
 * Dump the allocation information to the checkpoint file.
 */


/**
 * Restore the allocated data per the checkpoint file.
 * \param[in,out] memory_manager JEOD memory manager
 */


/**
 * Register newly allocated memory with Trick.
 *
 * \par Assumptions and Limitations
 *  - Memory was indeed allocated.
 *  - The input address is not null.
 *  - The number of elements is positive.
 * @return True if registered
 * \param[in] addr Allocated memory
 * \param[in] item Description of the memory
 * \param[in] tdesc Description of the type
 * \param[in] file Source file containing JEOD_ALLOC
 * \param[in] line Line number containing JEOD_ALLOC
 */


// JeodDynbodyIntegrationLoop non-default constructor.


// Initialize an integration loop object.


// Find the sim object that contains the specified integrable object.


// Add the specified integrable object to the integration group.


// Integrate over the specified time span.


// Add a sim object to the set of objects to be integrated by this loop.


// Remove a sim object from the set of objects integrated by this loop object.


// Add the DynBody objects contained in the specified sim object to the set of
// DynBody objects integrated by this integration loop.


// Add the DynBody objects contained in all sim objects integrated by this loop.


// Remove the DynBody objects contained in the specified sim object from the set
// of DynBody objects integrated by this integration loop.


// Update the provided group.


/**
 * Construct a JeodTrick10MemoryInterface object.
 */


/**
 * Default constructor.
 *
 * This constructor creates an empty SectionedOutputBuffer -- one that
 * will return EOF on the first write attempt.
 * An empty SectionedOutputBuffer has two purposes:
 * - As the basis for a copy constructor of a containing stream, and
 * - As a graceful means of handling of erroneous conditions.
 */


/**
 * Activate the object.
 * @note
 * Using the object for writing prior to activation will result in EOF.
 * \param[in] stream Output file stream
 */


/**
 * Write a character in the case of overflow of the write buffer.
 * For now, the buffer always overflows.
 * @return Status: EOF => failed
 * \param[in] ch Character to be writter
 */


/**
 * Construct a SectionedOutputStream object that is connected to a file stream
 * and to a CheckPointOutputManager.
 * \param[in] mngr The stream manager
 * \param[in] ofstream The output file stream
 * \param[in] start_marker Start of section marker
 * \param[in] end_marker End of section marker
 * \param[in] section_name Name of the section
 */


/**
 * Construct a SectionedOutputStream object by copying from another.
 * \param[in] source Source object
 */


/**
 * Destruct a SectionedOutputStream object.
 */


/**
 * Determine if the stream is able to be activated.
 * @return True if object can be activated.
 */


/**
 * Activate the object.
 * @note
 * Using the object for writing prior to activation will write nothing.
 * @return True if activated.
 */


/**
 * Deactivate the object.
 * @note
 * Deactivation is undoable.
 */


/**
 * Construct a CheckPointOutputManager object.
 * \param[in] fname Name of file to be opened
 * \param[in] start_marker Start of section marker
 * \param[in] end_marker End of section marker
 */


/**
 * Create a C++ output stream that writes to a checkpoint file section.
 * @par Usage
 * Use this function as the initializer of a section writer variable.
 * @par Error handling
 * A null SectionedOutputStream is created when the CheckPointOutputManager
 * itself is invalid or the designated section is invalid.
 * @return A SectionedOutputStream object.
 * \param[in] trick OK to create the Trick section writer?
 * \param[in] tag Tag identifying the section to be written.
 */


/**
 * Create a C++ output stream that writes to the Trick checkpoint file section.
 * @return Trick SectionedOutputStream object.
 */


/**
 * Register the supplied section writer as the currently-active writer.
 * @return True => success.
 * \param[in] writer Writer to be Registered
 */


/**
 * Deregister the supplied section writer as the currently-active writer.
 * @return True => success.
 * \param[in] writer Writer to be deregistered
 */


/**
 * Register the TrickMessageHandler's checkpointable contents.
 */


/**
 * Handle a message.
 * All calls to the message-generating MessageHandler methods eventually result
 * in a call to thisTrickMessageHandler::process_message method. This method
 * uses the Trick function exec_terminate to process fatal errors.
 * The Trick function send_hs is used for all non-fatal messages, but only
 * if the message severity is at or below the message suppression level.
 * \param[in] severity Severity level
 * \param[in] prefix Message prefix (e.g., Error)
 * \param[in] file Typically __FILE__
 * \param[in] line Typically __LINE__
 * \param[in] msg_code Message code
 * \param[in] format sprintf format
 * \param[in] args Arguments
 */


/**
 * Construct a JeodSimulationInterfaceInit object.
 */


/**
 * Construct a JeodSimulationInterface object.
 */


/**
 * Destruct a JeodSimulationInterface object.
 */


/**
 * Configure a JeodSimulationInterface object.
 * \param[in] config Configuration spec
 */


/**
 * Create a simulation integrator interface object.
 * @return Constructed IntegratorInterface object.
 */


/**
 * Get the cycle time of the currently executing job.
 * @return Cycle time in simulation engine seconds of the currently executing job.\n Units: s
 */


/**
 * Translate the given address to a symbolic name.
 * @return Symbolic name
 * \param[in] addr Address
 * \param[in] tdesc Descriptor
 */


/**
 * Translate the given symbolic name to an address.
 * @return Address
 * \param[in] name Symbolic name
 */


/**
 * Get a reader of a section of the currently open checkpoint file.
 * @return Checkpoint reader
 * \param[in] section_id Section ID
 */


/**
 * Get a writer to a section of the currently open checkpoint file.
 * @return Checkpoint writer
 * \param[in] section_id Section ID
 */


/**
 * Set the mode, but only if allowed per the mode state transition diagram.
 *
 * \par Assumptions and Limitations
 *  - The standard JEODSys Trick sim object follows the correct state transition
 *     diagram. A similar sequence must be implemented when JEOD is used outside
 *     of the Trick environment. In a Trick environment, *nobody* should call this
 *     function except the Trick scheduler, and these calls must conform with the
 *     sequence in the standard JEODSys Trick sim object.
 * \param[in] new_mode New mode
 */


/**
 * JeodTrickMemoryInterface default constructor.
 */


/**
 * Construct an identifier for a chunk of JEOD-allocated memory.
 * @return Identifier string
 * @param unique_id_number  Identifier number
 */


/**
 * Find the attributes for a class in the symbol table.
 * @return Found attributes
 * \param[in] type_name Demangled type name
 */


/**
 * Create an attributes structure that represents a pointer type.
 * @return Constructed pointer attributes.
 * \param[in] target_attr Pointed-to type attributes.
 */


/**
 * Create an attributes structure that represents a void* pointer.
 * @return Constructed pointer attributes.
 */


/**
 * Create an attributes structure that represents a structured type.
 * @return Constructed structure attributes.
 * \param[in] target_attr Return value from find_attributes.
 * \param[in] target_size Structure size.
 */


/**
 * Activate the object.
 * @note
 * Using the object for reading prior to activation will result in EOF.
 * \param[in] stream Checkpoint file input file stream
 * \param[in] spos Section data start position
 * \param[in] epos Section data end position
 */


/**
 * Get a character in the case of depletion of the read buffer.
 * For now, the buffer is always depleted.
 * @return Character read from the underlying file.
 */


/**
 * Construct a SectionedInputStream object that is connected to a file stream
 * and to a CheckPointInputManager.
 * \param[in] mngr The stream manager
 * \param[in] ifstream The input file stream
 * \param[in] spos Start position of section data
 * \param[in] epos End position of section data
 */


/**
 * Construct a SectionedInputStream object by copying from another.
 * \param[in] source Source object
 */


/**
 * Destruct a SectionedInputStream object.
 */


/**
 * Activate the object.
 * @note
 * Using the object for reading prior to activation will result in EOF.
 * @return True if activated.
 */


/**
 * Construct a CheckPointInputManager object.
 * \param[in] fname Name of file to be opened
 * \param[in] start_marker Start of section marker
 * \param[in] end_marker End of section marker
 */


/**
 * Determine the locations of the various sections that comprise the file.
 */


/**
 * Create a C++ input stream that reads from a checkpoint file section.
 * @par Usage
 * Use this function as the initializer of a section reader variable.
 * @par Error handling
 * A null SectionedInputStream is created when the CheckPointInputManager
 * itself is invalid or when the designated section is not present in the
 * checkpoint file.
 * @return A SectionedInputStream object.
 * \param[in] trick OK to create the Trick section reader?
 * \param[in] tag Tag identifying the section to be read.
 */


/**
 * Create a C++ input stream that reads from the Trick checkpoint file section.
 * @return Trick SectionedInputStream object.
 */


/**
 * Register the supplied section reader as the currently-active reader.
 * @return True => success.
 * \param[in] reader Reader to be registered
 */


/**
 * Deregister the supplied section reader as the currently-active reader.
 * @return True => success.
 * \param[in] reader Reader to be deregistered
 */


/**
 * Get the name of the current Trick checkpoint file.
 * @return Name of the current Trick checkpoint file.\n Units:
 * \param[in] checkpoint True for checkpoint, false for restart
 */


/**
 * Get the simulation name, if any, associated with the address.
 * @return Name of the address, if any
 * \param[in] addr Address of memory whose name is to be found
 * \param[in] tdesc How to interpret address
 */


/**
Translate the given address to an address specification string, with the
address interpreted in the context of the supplied attributes. It is the
attributes structure that resolves the A versus A.B versus A.B.C ambiguity.
@note The attributes structure must be that of a pointer type.
@param addr The address to be translated.
@param attr The context in which to interpret the address.
@return Address specification string, e.g., &foo.bar.baz[42]
*/


/**
Translate the given address specification string to an address.
This is the inverse of translate_addr_to_name.
@param spec The address specification to be interpreted.
@return    Address corresponding to the address specification.
*/


/**
 * Construct a BasicJeodTrickSimInterface object.
 * \param[in,out] message_handler handler\n Units: Message
 */


/**
 * Destroy a BasicJeodTrickSimInterface object.
 */


/**
 * Set the mode.
 *
 * \par Assumptions and Limitations
 *  - See SimulationInterface::set_mode.
 * \param[in] new_mode New mode.
 */


/**
 * Open the checkpoint output file.
 */


/**
 * Get a writer to a section of the currently open checkpoint file.
 * @return Checkpoint writer
 * \param[in] section_id Section name
 */


/**
 * Close the checkpoint output file.
 */


/**
 * Open the checkpoint input file.
 */


/**
 * Get a reader to a section of the currently open checkpoint file.
 * @return Checkpoint reader
 * \param[in] section_id Section name
 */


/**
 * Close the checkpoint input file.
 */


/**
 * Restore the allocated data per the checkpoint file.
 */


/**
 * Dump the container objects to the checkpoint file.
 */


/**
 * Restore the container objects from the checkpoint file.
 */


/**
     * Reset the flag that tells the simulation engine to compute derivatives
     * on the initial step of each integration cycle. Derivatives are always
     * needed just after a reset. The behavior should revert to nominal after
     * the reset has been performed.
     */


/**
     Deactivate the object.
     Used to disconnect the buffer when the stream is done, sometimes by force.
     */


/**
         * Construct an ContainerListEntry object.
         * @param parent  Parent object
         * @param tdesc   Type descriptor
         * @param sub_id  Parent element
         * @param obj     Checkpointable itself
         */


/**
         * Construct an AllocationMapEntry object.
         * @param type_info  Type info
         * @param nelem      Array size
         * @param arrayp     Is item an array?
         */


/**
 * Set the object name.
 * \param[in] name Orbital object name
 */


/**
 * Set the planet name.
 * \param[in] name Name of planet about which the object orbits
 */


/******************************************************************************
PURPOSE:
   (Calculation of Orbital Elements from Inertial Cartesian Coordinates and the
    planetary gravitational parameter. Elements include semi-major-axis -a-,
    semiparameter -p-, eccentricity -e-, inclination -i-, longitude of the
    ascending node -Omega-, argument of periapsis -w-, true anomaly -v-,
    mean anomaly -M, and eccentric -E-, hyperbolic -H-, or parabolic anomaly
    -B-.)

REFERENCE:
   (((Vallado, David A.) (Fundamentals of Astrodynamics and Applications)
     (McGraw-Hill) (New York) (1997)))

ASSUMPTIONS AND LIMITATIONS:
   ((Input cartesian coordinates are assumed to be in an inertial frame.))

CLASS:
   (scheduled)

******************************************************************************/


/******************************************************************************
PURPOSE:
    (Calculation of Inertial Cartesian Coordinates from Orbital Elements
     semiparameter -p-, eccentricity -e-, inclination -i-, longitude of the
     ascending node -Omega-, argument of periapsis -w-, mean anomaly -M-,
     and gravitational parameter -mu-.)

REFERENCE:
    (((Vallado, D.) (Fundamentals of Astrodynamics and Applications, 2nd Ed.)
      (Kluwer Acedemic Publishers) (2001) (Pages 135-230) (ISBN:0-07-066834-5))
     ((Montenbruck, O. and Gill, E.) (Satellite Orbits)
      (Springer) (2000) (Pages 157-190) (ISBN:3 540 67280))
     ((Pedro Ramon Escobal) (Methods of Orbital Determination)
      (Krieger Publishing) (1976) (pages 393-422) (ISBN:0-88275-319-3)))

ASSUMPTIONS AND LIMITATIONS:
    ((This routine is intended to be used at initialization only.)
     (Output cartesian coordinates are in an inertial frame.)
     (This routine works for all types of orbits.))

CLASS:
    (initialization)

******************************************************************************/


/******************************************************************************
PURPOSE:
    (Calculation of the Mean Anomaly and the Eccentric, Hyperbolic, or
     Parabolic Anomalies, given the True Anomaly and eccentricity)

REFERENCE:
    (((Vallado, D.) (Fundamentals of Astrodynamics and Applications, 2nd Ed.)
      (Kluwer Acedemic Publishers) (2001) (Pages 135-230) (ISBN:0-07-066834-5))
     ((Montenbruck, O. and Gill, E.) (Satellite Orbits)
      (Springer) (2000) (Pages 157-190) (ISBN:3 540 67280))
     ((Pedro Ramon Escobal) (Methods of Orbital Determination)
      (Krieger Publishing) (1976) (pages 393-422) (ISBN:0-88275-319-3)))

ASSUMPTIONS AND LIMITATIONS:
    ((This routine works for all types of orbits.))

CLASS:
    (N/A)

******************************************************************************/


/******************************************************************************
PURPOSE:
    (Calculation of the True Anomaly from the Mean Anomaly and Eccentricity.)

REFERENCE:
    (((Vallado, David A.) (Fundamentals of Astrodynamics and Applications)
      (McGraw-Hill) (New York) (1997)))

ASSUMPTIONS AND LIMITATIONS:
    ((This routine works for all types of orbits.))

CLASS:
    (N/A)

******************************************************************************/


/******************************************************************************
PURPOSE:
    (Calculation of Eccentric Anomaly from the Mean Anomaly and Eccentricity)

REFERENCE:
    (((Vallado, David A.) (Fundamentals of Astrodynamics and Applications)
      (McGraw-Hill) (New York) (1997)))

ASSUMPTIONS AND LIMITATIONS:
    ((Only call this routine for elliptical orbits: e < 1.0)
     (If a "-1" is returned, the solution did not converge; otherwise, the
      number of iterations required is returned))

CLASS:
    (N/A)

******************************************************************************/


/******************************************************************************
PURPOSE:
    (Calculation of the Hyperbolic Anomaly from the Mean Anomaly and the
     Eccentricity)

REFERENCE:
    (((Vallado, David A.) (Fundamentals of Astrodynamics and Applications)
      (McGraw-Hill) (New York) (1997)))

ASSUMPTIONS AND LIMITATIONS:
    ((Only call this routine for hyperbolic orbits: e > 1.0)
     (If a "-1" is returned, the solution did not converge; otherwise, the
      number of iterations required is returned))

CLASS:
    (N/A)

******************************************************************************/


/******************************************************************************
PURPOSE:
    (Calculation of the Parabolic Anomaly from the Mean Anomaly)

REFERENCE:
    (((Vallado, David A.) (Fundamentals of Astrodynamics and Applications)
      (McGraw-Hill) (New York) (1997)))

ASSUMPTIONS AND LIMITATIONS:
    ((Only call this routine for Parabolic orbits: e = 1.0))

CLASS:
    (N/A)

******************************************************************************/


/**
 * Construct an Orientation instance from a transformation matrix.
 * \param[in] trans_in Transformation matrix
 */


/**
 * Construct an Orientation instance from a Quaternion.
 * \param[in] quat_in Quaternion
 */


/**
 * Construct an Orientation instance from an eigen rotation.
 * \param[in] eigen_angle_in Rotation angle\n Units: r
 * \param[in] eigen_axis_in Rotation axis, unit vector
 */


/**
 * Construct an Orientation instance from an Euler rotation.
 * \param[in] sequence_in Euler sequence
 * \param[in] angles_in Euler angles\n Units: r
 */


/*
Purpose:
  (Forget that we have any data.
   Note that this method does not reset the euler_sequence member;
   that is intentional.)
*/


/**
 * Mark the item specified by the data_source as available.
 * Note that this method doesn't compute any products.
 *
 * \par Assumptions and Limitations
 *  - The data_source member datum is valid.
 */


/*
Purpose:
  (Compute the transformation matrix from the source.)
*/


/**
 * Compute the left transformation quaternion from the source.
 */


/**
 * Compute the eigen rotation from the source.
 */


/**
 * Compute all represented charts on SO3 from the specified source.
 */


/**
 * Compute the transformation matrix and quaternion.
 */


/*
Purpose:
  (Accessor for the transformation matrix.)
*/


/**
 * Accessor for the left transformation quaternion.
 * \param[out] quat_out Copy of the quaternion
 */


/**
 * Accessor for the eigen rotation.
 * \param[out] eigen_angle_out Copy of the single axis rotation angle\n Units: r
 * \param[out] eigen_axis_out Copy of the single axis rotation axis
 */


/**
 * Accessor for the Euler angles.
 * \param[out] sequence Copy of the Euler sequence
 * \param[out] angles Copy of the Euler angles\n Units: r
 */


/**
 * Accessor for the Euler angles.
 * \param[out] angles Copy of the Euler angles\n Units: r
 */


/*
Purpose:
  (Reset the instance with a new matrix.)
*/


/**
 * Reset the instance with a new quaternion.
 * \param[in] quat_in New quaternion
 */


/**
 * Reset the instance with a new eigen rotation.
 * \param[in] eigen_angle_in New single axis rotation angle
 * \param[in] eigen_axis_in New single axis rotation axis
 */


/**
 * Reset the instance with a new Euler rotation.
 * \param[in] sequence New Euler sequence
 * \param[in] angles New Euler angles\n Units: r
 */


/**
 * Reset the instance with a new Euler rotation.
 *
 * \par Assumptions and Limitations
 *  - The euler_sequence data member must have previously been set to
 *     a valid value.
 * \param[in] angles New Euler angles\n Units: r
 */


/**
 * Set the euler_sequence data member.
 * \param[in] sequence New Euler sequence
 */


/**
 * Reset the euler_sequence data member.
 * Issues arise if the data source is the Euler rotation sequence.
 * The resolution is to preserve the existing input elsewhere.
 */


/**
 * Compute the transformation matrix from the eigen rotation.
 * Given a rotation by an angle \f$\phi\f$ about an axis
 * \f$\hat{\mathbf u}\f$,
 * the [i][j] element of the transformation matrix is given by
 * \f[
 *   T_{ij} =
 *      \cos\phi\,\delta_{ij} +
 *      (1-\cos\phi)\,\hat u_i \hat u_j +
 *      \epsilon_{ijk}\sin\phi\,\hat u_k
 * \f]
 * where
 *   - \f$\delta_{ij}\f$ is the Kronecker delta,
 *   -  @e k is \f$(i+j) \bmod 3\f$, and
 *   - \f$\epsilon_{ijk}\f$ is the Levi-Civita symbol taken with respect
 *      to (0,1,2).
 *
 * \par Assumptions and Limitations
 *  - The eigen axis is a unit vector.
 * \param[in] eigen_angle Rotation angle\n Units: r
 * \param[in] eigen_axis Rotation axis, unit vector
 * \param[out] trans Resultant transformation matrix
 */


/**
 * Compute the eigen rotation from the transformation matrix.
 * There are several alternate expressions for computing the eigen rotation
 * from a matrix, all of which are equivalent in infinite precision arithmetic.
 * The use of finite precision arithmetic means that care must be taken
 * in choosing the algorithm to be used. The starting point is the
 * generic expression
 * \f[
 *   T_{ij} =
 *      \cos\phi\,\delta_{ij} +
 *      (1-\cos\phi)\,\hat u_i \hat u_j +
 *      \epsilon_{ijk}\sin\phi\,\hat u_k
 * \f]
 * From this, the trace of the matrix and the difference between and sum of
 * pairs of off-diagonal elements are
 * \f{eqnarray*}{
 *   \mathrm{tr}(T) &=& 2\cos\phi + 1 \\
 *    T_{ij}-T_{ji} &=& 2\epsilon_{ijk}\sin\phi\,\hat u_k \\
 *    T_{ij}+T_{ji} &=& 2(1-\cos\phi)\,\hat u_i \hat u_j
 * \f}
 *
 * Method 1\n
 * One approach to determining the eigen rotation involves the construction
 * of a vector of differences between pairs of off-diagonal elements of the
 * transformation matrix,
 * \f[
 *    d_k = T_{ij}-T_{ji} = 2 \sin\phi\,\hat u_k
 * \f]
 * where (i,j,k) is an even permutation of (0,1,2). With this,
 * \f{eqnarray*}{
 *    \phi &=& \arcsin\left(\frac{||\mathbf d||} 2\right) \\
 *    \hat{\mathbf u} &=& \frac{\mathbf d}{||\mathbf d||}
 * \f}
 * Note that the above of the inverse sine will restrict the rotation angle to
 * be between 0 and 90 degrees. Special processing is needed when the rotation
 * angle is between 90 and 180 degrees.
 * Note also that the symmetric difference vector will
 * be identically zero if the rotation angle is 0 or 180 degrees and will be
 * very small for rotation angles close to 0 or 180 degrees.
 * The precision loss for rotation angles near 0 and 180 degrees means the
 * individual components of the eigen axis will not be as precise with this
 * approach compared to alternatives.
 *
 * Method 2\n
 * The diagonal elements of the matrix yields another method for determining the
 * single axis rotation angle and the rotation axis:
 * \f{eqnarray*}{
 *    \phi &=& \arccos\left(\frac{\mathrm{tr}(T)-1} 2\right) \\
 *    |\hat u_i| &=& \sqrt{\frac{T_{ii} - \cos \phi}{1-\cos\phi}}
 * \f}
 * Note that this approach determines the magnitudes but not the signs of the
 * components of the eigen axis vector. Because this method is based on the
 * inverse cosine, the calculated phi angle will be less precise than that
 * obtained by method 1 for angles near 0 or 180 degrees. The unit vector
 * however will be more accurate than that obtained from method 1 for small
 * rotation angles.
 *
 * Method 3\n
 * Yet another alternative for computing components of the eigen axis is to
 * use the sum of pairs of off-diagonal elements of the transformation metrix,
 * \f{eqnarray*}{
 *    T_{ij}+T_{ji} &=& 2(1-\cos\phi)\,\hat u_i \hat u_j \\
 *    T_{ik}+T_{ki} &=& 2(1-\cos\phi)\,\hat u_i \hat u_k
 * \f}
 * This enables the calculation of two components of the unit vector. One
 * component needs to be computed by one of the two previous methods.
 *
 * \par Assumptions and Limitations
 *  - The matrix is a proper transformation matrix.
 * \param[in] trans Transformation matrix
 * \param[out] eigen_angle Resultant rotation angle\n Units: r
 * \param[out] eigen_axis Resultant rotation axis
 */


/**
 * Compute the left transformation quaternion from the Euler sequence.
 * The quaternion is formed by generating a sequence of three simple
 * quaternions corresponding to the three rotations. The composite
 * quaternion is the reverse-order product of these three simple quaternions.
 * \param[in] euler_sequence Euler sequence
 * \param[in] euler_angles Euler angles\n Units: r
 * \param[out] quat Resultant quaternion
 */


/**
 * Compute the transformation matrix from the Euler sequence.
 * The matrix is formed by generating a sequence of three simple transformation
 * matrices corresponding to the three rotations. The composite transformation
 * matrix is the reverse-order product of these three simple matrices.
 * \param[in] euler_sequence Euler sequence
 * \param[in] euler_angles Euler angles\n Units: r
 * \param[out] trans Resultant transformation matrix
 */


/**
 * Extract an Euler sequence from the transformation matrix.
 * A transformation matrix constructed from an XYZ Euler sequence
 * is of the form @f[
 *    \left[\array{ccc}
 *       \cos\psi\cos\theta & \cdots & \cdots \\
 *      -\sin\psi\cos\theta & \cdots & \cdots \\
 *       \sin\theta  & -\cos\theta\sin\phi & \cos\theta\cos\phi
 *    \endarray\right]
 * @f]
 * Note that the [2][0] element of the matrix depends on theta only.
 * The other two elements of the leftmost column are simple terms that depend on
 * theta and psi only, and the other two elements of the bottommost row are
 * simple terms that depend on theta and phi only.
 * Those five elements are the key to extracting an XYZ Euler sequence from a
 * transformation matrix.
 * The same principle applies to all twelve of the Euler sequences:
 * Five key elements contain all of the information needed to extract the
 * desired sequence. The location and form of those key elements of course
 * depends on the sequence.
 *
 * A problem arises in the above when cos(theta) is zero, or nearly so. This
 * siutation is called 'gimbal lock'. Those four elements used to determine phi
 * and psi are zero or nearly so. Fortunately That ugly stuff isn't so ugly in
 * the case of gimbal lock. Once again looking at the matrix generated from an
 * XYZ Euler sequence, when theta=pi/2 the matrix becomes @f[
 *    \left[\array{ccc}
 *        0 & \sin(\phi+\psi) & -cos(\phi+\psi) \\
 *        0 &  \cos(\phi+\psi) & \sin(\phi+\psi) \\
 *        1 & 0 & 0
 *    \endarray\right]
 * @f]
 * In this case there no way to determine both phi and psi; all that can be
 * determined is their sum. One way to overcome this problem is to arbitrarily
 * set one of those angles to an arbitrary value such as zero. That is the
 * approach used in this method. This arbitrary setting enables an XYZ Euler
 * sequence to be extracted from the matrix even in the case of gimbal lock.
 * The same principle once again applies to all twelve sequences.
 *
 * In summary, for a transformation matrix corresponding to an XYZ sequence,
 *  - The [2][0] element of the matrix specifies theta.
 *  - The [1][0] and [0][0] elements of the matrix specify psi.
 *  - The [2][1] and [2][2] elements of the matrix specify phi.
 *    These psi and phi values are valid only when gimbal lock is not present.
 *  - The [1][2] and [1][1] elements of the matrix specify phi in the
 *    case of gimbal lock.
 *
 * Extending this analysis to the remaining eleven sequences provides the
 * essential information needed to extract the desired Euler angles from a
 * transformation matrix. This information is captured in the EulerInfo
 * array Euler_info defined at the head of this file. With a
 * reference <tt>info</tt> to the appropriate element of this array,
 *  - The [info.indices[2]][info.indices[0]] element of the matrix
 *    specifies the angle theta.
 *  - The [info.indices[1]][info.indices[0]] and
 *        [info.alternate_x][info.indices[0]] elements of the matrix
 *    specify the angle psi when gimbal lock is not present.
 *  - The [info.indices[2]][info.indices[1]] and
 *        [info.indices[2]][info.alternate_z] elements of the matrix
 *    specify the angle phi when gimbal lock is not present.
 *  - The [info.indices[1]][info.alternate_z] and
 *        [info.indices[1]][info.indices[1]] elements of the matrix
 *    specify angle phi when gimbal lock is present.
 *
 * \par Assumptions and Limitations
 *  - To within numerical accuracy, the transformation matrix in the
 *     Orientation object @e is a proper transformation matrix:
 *      - The magnitude of each row and column vector is nearly one.
 *      - The inner product of any two different rows / two different columns of
 *        the matrix nearly zero.
 *      - The determinant of the matrix is nearly one.
 *      - An element whose value is outside the range [-1,1] is only slightly
 *        outside that range and the deviation is numerical.
 * \param[in] trans Transformation matrix
 * \param[in] euler_sequence Euler sequence
 * \param[out] euler_angles Resultant Euler angles\n Units: r
 */


/**
 * Compute the inverse of a symmetric 3x3 matrix.
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 *  - Input matrix is symmetric.
 *  - Determinate is non-zero.
 * @return 0=success, non-zero=singular
 * \param[in] matrix Symmetric matrix to invert
 * \param[out] inverse Inverse
 */


/**
 * Compute the inverse of a 3x3 matrix.
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 *  - Input matrix is well-conditioned.
 * @return 0=success, non-zero=singular
 * \param[in] matrix Matrix to invert
 * \param[out] inverse Inverse
 */


/**
 * Absolute value
 * @return Absolute value of x
 * \param[in] x x
 */


/**
 * Compute the square of a number, protecting against undeflow
 * @return value^2 or zero if too small
 * \param[in] value Value
 */


/**
 * Add number squared to accumulator, protecting against undeflow
 * @return Accumulated value
 * \param[in] value Value
 * \param[in,out] sum Accumulator
 */


/**
 * Zero-fill matrix: mat[i][j] = 0.0
 * \param[out] mat Zero-filled matrix
 */


/**
 * Construct identity matrix: mat[i][j] = delta_ij
 * \param[out] mat Identity matrix
 */


/**
 * Construct the skew symmetric cross product matrix:
 * mat[i][k] = epsilon_ijk vec[j], epsilon_ijk is the Levi-Cevita symbol
 * \param[in] vec Vector
 * \param[out] cross_mat Cross product matrix
 */


/**
 * Construct the outer product of two vectors:
 * mat[i][j] = vec_left[i] * vec_right[j]
 * \param[in] vec_left Vector
 * \param[in] vec_right Vector
 * \param[out] prod Outer product matrix
 */


/**
 * Negated matrix in-place: mat[i][j] = -mat[i][j]
 * \param[in,out] mat Negated matrix
 */


/**
 * Transpose matrix in-place: mat[i][j] = mat[j][i]
 * \param[in,out] mat Transposed matrix
 */


/**
 * Scale matrix in-place, mat[i][j] = scalar * mat[i][j]
 * \param[in] scalar Scalar
 * \param[in,out] mat Scaled matrix
 */


/**
 * Increment matrix in-place: mat[i][j] = mat[i][j] + addend[i][j]
 * \param[in] addend Increment
 * \param[in,out] mat Incremented matrix
 */


/**
 * Decrement matrix in-place: mat[i][j] = mat[i][j] - subtrahend[i][j]
 * \param[in] subtrahend Decrement
 * \param[in,out] mat Decremented matrix
 */


/**
 * Copy matrix: copy[i][j] = mat[i][j]
 * \param[in] input_mat Source matrix
 * \param[out] copy Matrix copy
 */


/**
 * Negate matrix: copy[i][j] = -mat[i][j]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] input_mat Source matrix
 * \param[out] copy Negated matrix
 */


/**
 * Transpose matrix: copy[i][j] = mat[j][i]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] input_mat Source matrix
 * \param[out] trans Matrix transpose
 */


/**
 * Scale matrix: copy[i][j] = scalar * mat[i][j]
 * \param[in] mat Matrix
 * \param[in] scalar Scalar
 * \param[out] prod Product
 */


/**
 * Add matrices: sum[i][j] = augend[i][j] + addend[i][j]
 * \param[in] augend Matrix
 * \param[in] addend Matrix
 * \param[out] sum Sum
 */


/**
 * Subtract matrices: diff[i][j] = minuend[i][j] - subtrahend[i][j]
 * \param[in] minuend Matrix
 * \param[in] subtrahend Matrix
 * \param[out] diff Difference
 */


/**
 * Compute the matrix product mat_left * mat_right:
 * prod[i][j] = mat_left[i][k] * mat_right[k][j]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] mat_left Multiplier
 * \param[in] mat_right Multiplicand
 * \param[out] prod Product
 */


/**
 * Compute the matrix product mat_left^T * mat_right:
 * prod[i][j] = mat_left[k][i] * mat_right[k][j]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] mat_left Multiplier
 * \param[in] mat_right Multiplicand
 * \param[out] prod Product
 */


/**
 * Compute the matrix product mat_left * mat_right^T:
 * prod[i][j] = sum_k mat_left[i][k] * mat_right[j][k]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] mat_left Multiplier
 * \param[in] mat_right Multiplicand
 * \param[out] prod Product
 */


/**
 * Compute the matrix product mat_left^T * mat_right^T:
 * prod[i][j] = sum_k mat_left[k][i] * mat_right[j][k]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] mat_left Multiplier
 * \param[in] mat_right Multiplicand
 * \param[out] prod Product
 */


/**
 * Compute the matrix product trans * mat * trans^T
 * prod[i][j] = trans[i][k] * mat[k][l] * trans[j][l]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] trans Transformation matrix
 * \param[in] mat Matrix to transform
 * \param[out] prod Product
 */


/**
 * Compute the matrix product trans^T * mat * trans
 * prod[i][j] = trans[k][i] * mat[k][l] * trans[l][j]
 *
 * \par Assumptions and Limitations
 *  - Input and output matrices are distinct.
 * \param[in] trans Transformation matrix
 * \param[in] mat Matrix to transform
 * \param[out] prod Product
 */


/**
 * Print matrix to standard error
 * \param[in] mat Matrix to print
 */


/**
 * Zero-fill vector,
 * vec[i] = 0.0
 * @return Zero-filled vector
 * \param[out] vec Zero-filled vector
 */


/**
 * Construct unit vector,
 * vec[i] = delta_ij (delta_ij is the Kronecker delta)
 * @return Unit vector
 * \param[in] index Unit index: 0,1,2=x,y,z hat
 * \param[out] vec Unit vector
 */


/**
 * Construct a vector from scalar,
 * vec[i] = scalar
 * @return Filled vector
 * \param[in] scalar Scalar
 * \param[out] vec Filled vector
 */


/**
 * Zero-out small components of a vector,
 * vec[i] = 0 if abs(vec[i]) < limit
 * @return Truncated vector
 * \param[in] limit Limit
 * \param[in,out] vec Truncated vector
 */


/**
 * Copy vector contents,
 * copy[i] = vec[i]
 * @return Copied vector
 * \param[in] vec Source vector
 * \param[out] copy Copied vector
 */


/**
 * Make vector a unit vector in-place,
 * vec = vec * 1/vmag(vec)
 * @return Normalized vector
 * \param[in,out] vec Vector
 */


/**
 * Construct unit vector,
 * unit_vec = vec * 1/vmag(vec)
 * @return Unit vector
 * \param[in] vec Vector
 * \param[out] unit_vec Unit vector
 */


/**
 * Scale a vector in-place,
 * vec[i] = scalar
 * @return Scaled vector
 * \param[in] scalar Scalar
 * \param[in,out] vec Scaled vector
 */