1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
//
// GENERATED FILE
//
use super::*;
use crate::SpiceContext;
use f2rust_std::*;
const NROWS: i32 = 6;
const NCOLS: i32 = 6;
const BLOCK: i32 = 3;
/// Inverse of state transformation matrix
///
/// Return the inverse of a state transformation matrix.
///
/// # Required Reading
///
/// * [ROTATION](crate::required_reading::rotation)
///
/// # Brief I/O
///
/// ```text
/// VARIABLE I/O DESCRIPTION
/// -------- --- --------------------------------------------------
/// MAT I A state transformation matrix.
/// INVMAT O The inverse of MAT.
/// ```
///
/// # Detailed Input
///
/// ```text
/// MAT is a state transformation matrix for converting states
/// relative to one frame to states relative to another.
/// The state transformation of a state vector, S, is
/// performed by the matrix-vector product.
///
/// MAT * S.
///
/// For MAT to be a "true" state transformation matrix
/// it must have the form
///
/// .- -.
/// | : |
/// | R : 0 |
/// |.......:......|
/// | : |
/// | W*R : R |
/// | : |
/// `- -'
///
/// where R is a 3x3 rotation matrix, 0 is the 3x3 zero
/// matrix and W is a 3x3 skew-symmetric matrix.
///
/// NOTE: no checks are performed on MAT to ensure that it
/// does indeed have the form described above.
/// ```
///
/// # Detailed Output
///
/// ```text
/// INVMAT is the inverse of MAT under the operation of matrix
/// multiplication.
///
/// If MAT has the form described above, then INVMAT has
/// the form shown below.
///
/// .- -.
/// | t : |
/// | R : 0 |
/// |........:......|
/// | t : t |
/// | (W*R) : R |
/// | : |
/// `- -'
///
/// (The superscript "t" denotes the matrix transpose
/// operation.)
/// ```
///
/// # Exceptions
///
/// ```text
/// Error free.
///
/// 1) No checks are performed to ensure that the input matrix is
/// indeed a state transformation matrix.
/// ```
///
/// # Particulars
///
/// ```text
/// Given a matrix for transforming states relative frame 1 to
/// states relative frame 2, the routine produces the inverse
/// matrix. That is, it returns the matrix for transforming states
/// relative to frame 2 to states relative to frame 1.
///
/// This special routine exists because unlike the inverse of a
/// rotation matrix, the inverse of a state transformation matrix,
/// is NOT simply the transpose of the matrix.
/// ```
///
/// # Examples
///
/// ```text
/// The numerical results shown for this example may differ across
/// platforms. The results depend on the SPICE kernels used as
/// input, the compiler and supporting libraries, and the machine
/// specific arithmetic implementation.
///
/// 1) Suppose you have a geometric state of a spacecraft in Earth
/// body-fixed reference frame and wish to express this state
/// relative to an Earth centered J2000 frame. The following
/// example code illustrates how to carry out this computation.
///
/// Use the PCK kernel below to load the required high precision
/// orientation of the ITRF93 Earth body-fixed reference frame.
/// Note that the body ID code used in this file for the Earth is
/// 3000.
///
/// earth_720101_070426.bpc
///
///
/// Example code begins here.
///
///
/// PROGRAM INVSTM_EX1
/// IMPLICIT NONE
///
/// C
/// C Local variables.
/// C
/// DOUBLE PRECISION ET
/// DOUBLE PRECISION INVMAT ( 6, 6 )
/// DOUBLE PRECISION ISTAT1 ( 6 )
/// DOUBLE PRECISION ISTAT2 ( 6 )
/// DOUBLE PRECISION MAT ( 6, 6 )
/// DOUBLE PRECISION STATE ( 6 )
/// DOUBLE PRECISION XMAT ( 6, 6 )
///
/// INTEGER EARTH
///
/// C
/// C Define the state of the spacecraft, in km and
/// C km/s, and the ET epoch, in seconds past J2000.
/// C
/// DATA ET / 0.0D0 /
/// DATA STATE / 175625246.29100420D0,
/// . 164189388.12540060D0,
/// . -62935198.26067264D0,
/// . 11946.73372264D0,
/// . -12771.29732556D0,
/// . 13.84902914D0 /
///
/// C
/// C Load the required high precision Earth PCK.
/// C
/// CALL FURNSH ( 'earth_720101_070426.bpc' )
///
/// C
/// C First get the state transformation from J2000 frame
/// C to Earth body-fixed frame at the time of interest ET.
/// C The body ID code used in high precision PCK files for
/// C the Earth is 3000; this number indicates that the
/// C terrestrial frame used is ITRF93.
/// C
/// EARTH = 3000
/// CALL TISBOD ( 'J2000', EARTH, ET, MAT )
///
/// C
/// C Get the inverse of MAT.
/// C
/// CALL INVSTM ( MAT, INVMAT )
///
/// C
/// C Transform from bodyfixed state to inertial state.
/// C
/// CALL MXVG ( INVMAT, STATE, 6, 6, ISTAT1 )
///
/// C
/// C Print the resulting state.
/// C
/// WRITE(*,'(A)') 'Input state in Earth centered J2000 '
/// . // 'frame, using INVSTM:'
/// WRITE(*,'(A,3F16.3)') ' Position:', ISTAT1(1:3)
/// WRITE(*,'(A,3F16.3)') ' Velocity:', ISTAT1(4:6)
///
/// C
/// C Compute the same state using SXFORM.
/// C
/// CALL SXFORM ( 'ITRF93', 'J2000', ET, XMAT )
/// CALL MXVG ( XMAT, STATE, 6, 6, ISTAT2 )
///
/// WRITE(*,*)
/// WRITE(*,'(A)') 'Input state in Earth centered J2000 '
/// . // 'frame, using SXFORM:'
/// WRITE(*,'(A,3F16.3)') ' Position:', ISTAT2(1:3)
/// WRITE(*,'(A,3F16.3)') ' Velocity:', ISTAT2(4:6)
///
/// END
///
///
/// When this program was executed on a Mac/Intel/gfortran/64-bit
/// platform, the output was:
///
///
/// Input state in Earth centered J2000 frame, using INVSTM:
/// Position: 192681395.921 -143792821.383 -62934296.473
/// Velocity: 30.312 32.007 13.876
///
/// Input state in Earth centered J2000 frame, using SXFORM:
/// Position: 192681395.921 -143792821.383 -62934296.473
/// Velocity: 30.312 32.007 13.876
/// ```
///
/// # Author and Institution
///
/// ```text
/// N.J. Bachman (JPL)
/// J. Diaz del Rio (ODC Space)
/// W.L. Taber (JPL)
/// ```
///
/// # Version
///
/// ```text
/// - SPICELIB Version 1.1.0, 25-NOV-2021 (JDR)
///
/// Added IMPLICIT NONE statement.
///
/// Removed unnecessary Standard SPICE error handling calls to
/// register/unregister this routine in the error handling
/// subsystem; this routine is Error free.
///
/// Edited the header to comply with NAIF standard.
/// Added complete code example based on the existing fragment.
///
/// - SPICELIB Version 1.0.2, 22-APR-2010 (NJB)
///
/// Header correction: assertions that the output
/// can overwrite the input have been removed.
///
/// - SPICELIB Version 1.0.1, 10-MAR-1992 (WLT)
///
/// Comment section for permuted index source lines was added
/// following the header.
///
/// - SPICELIB Version 1.0.0, 29-OCT-1990 (WLT)
/// ```
pub fn invstm(
ctx: &mut SpiceContext,
mat: &[[f64; 6]; 6],
invmat: &mut [[f64; 6]; 6],
) -> crate::Result<()> {
INVSTM(
mat.as_flattened(),
invmat.as_flattened_mut(),
ctx.raw_context(),
)?;
ctx.handle_errors()?;
Ok(())
}
//$Procedure INVSTM ( Inverse of state transformation matrix )
pub fn INVSTM(MAT: &[f64], INVMAT: &mut [f64], ctx: &mut Context) -> f2rust_std::Result<()> {
let MAT = DummyArray2D::new(MAT, 1..=6, 1..=6);
let mut INVMAT = DummyArrayMut2D::new(INVMAT, 1..=6, 1..=6);
//
// Local parameters
//
//
// Not much to this. Just call the more general routine XPOSBL.
//
XPOSBL(
MAT.as_slice(),
NROWS,
NCOLS,
BLOCK,
INVMAT.as_slice_mut(),
ctx,
)?;
Ok(())
}