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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
//
// GENERATED FILE
//
use super::*;
use f2rust_std::*;
const MAXTRM: i32 = 25;
const MAXREC: i32 = 300;
const MAXDEG: i32 = 23;
const MAXDIM: i32 = MAXTRM;
const MDAOFF: i32 = (MAXTRM + 7);
const MDASIZ: i32 = MAXTRM;
const MAXCOF: i32 = (MAXDEG + 1);
const MSIZE: i32 = (MAXCOF * MAXCOF);
//$Procedure T_T13XMD ( Type 13 SPK record to extended MDA )
pub fn T_T13XMD(
T13REC: &[f64],
MDABEG: f64,
MDAEND: f64,
T21REC: &mut [f64],
FOUND: &mut bool,
ctx: &mut Context,
) -> f2rust_std::Result<()> {
let T13REC = DummyArray::new(T13REC, 1..);
let mut T21REC = DummyArrayMut::new(T21REC, 1..);
let mut ACCDER = StackArray::<f64, 25>::new(1..=MDASIZ);
let mut D: f64 = 0.0;
let mut DBUFF = StackArray::<f64, 72>::new(1..=(MAXCOF * 3));
let mut DERIVS = StackArray::<f64, 24>::new(1..=MAXCOF);
let mut DT = StackArray::<f64, 25>::new(1..=MDASIZ);
let mut MBUFF = ActualArray::<f64>::new(1..=MSIZE);
let mut RSYS = StackArray::<f64, 72>::new(1..=(MAXCOF * 3));
let mut S: f64 = 0.0;
let mut SPAN: f64 = 0.0;
let mut SHRINK: f64 = 0.0;
let mut TVALS = StackArray::<f64, 24>::new(1..=MAXCOF);
let mut WORK = ActualArray2D::<f64>::new(1..=MAXREC, 1..=MAXREC);
let mut X: f64 = 0.0;
let mut DEGP: i32 = 0;
let mut DLSIZE: i32 = 0;
let mut FROM: i32 = 0;
let mut LIDX: i32 = 0;
let mut MDALOC: i32 = 0;
let mut N: i32 = 0;
let mut TO: i32 = 0;
let mut TSTART: i32 = 0;
//
// SPICELIB functions
//
//
// Local parameters
//
//
// Local variables
//
if spicelib::RETURN(ctx) {
return Ok(());
}
spicelib::CHKIN(b"T_T13XMD", ctx)?;
//
// Nothing found yet.
//
*FOUND = false;
//
// For each position component, find the Taylor expansion of its
// polynomial representation at X. Convert the derivative set to a
// difference line. Store the difference line in the type 21 record.
//
// Get the type 13 polynomial degree from the state count.
//
N = intrinsics::IDNINT(T13REC[1]);
if spicelib::ODD(N) {
spicelib::SETMSG(b"Window size is #; must be even", ctx);
spicelib::ERRINT(b"#", N, ctx);
spicelib::SIGERR(b"SPICE(INVALIDSIZE)", ctx)?;
spicelib::CHKOUT(b"T_T13XMD", ctx)?;
return Ok(());
}
DEGP = ((2 * N) - 1);
if ((DEGP < 1) || (DEGP > MAXDEG)) {
spicelib::SETMSG(b"Polynomial degree is #; must be in range 1:#.", ctx);
spicelib::ERRINT(b"#", DEGP, ctx);
spicelib::ERRINT(b"#", MAXDEG, ctx);
spicelib::SIGERR(b"SPICE(VALUEOUTOFRANGE)", ctx)?;
spicelib::CHKOUT(b"T_T13XMD", ctx)?;
return Ok(());
}
//
// Let TSTART be the index in T13REC where the time values start.
//
TSTART = (2 + (6 * N));
//
// Find the span of the time values in the record.
//
SPAN = (T13REC[((TSTART + N) - 1)] - T13REC[TSTART]);
//
// Ensure that at least one time tag in the input record
// strictly precedes MDAEND.
//
LIDX = spicelib::LSTLTD(MDAEND, N, T13REC.subarray(TSTART));
if (LIDX == 0) {
spicelib::SETMSG(
b"Input time MDAEND = #; is not greater than first epoch in type 13 record #.",
ctx,
);
spicelib::ERRDP(b"#", MDAEND, ctx);
spicelib::ERRDP(b"#", T13REC[TSTART], ctx);
spicelib::SIGERR(b"SPICE(TIMEOUTOFRANGE)", ctx)?;
spicelib::CHKOUT(b"T_T13XMD", ctx)?;
return Ok(());
}
if (MDAEND > T13REC[((TSTART + N) - 1)]) {
spicelib::SETMSG(
b"Input time MDAEND = #; exceeds last epoch in type 13 record #.",
ctx,
);
spicelib::ERRDP(b"#", MDAEND, ctx);
spicelib::ERRDP(b"#", T13REC[((TSTART + N) - 1)], ctx);
spicelib::SIGERR(b"SPICE(TIMEOUTOFRANGE)", ctx)?;
spicelib::CHKOUT(b"T_T13XMD", ctx)?;
return Ok(());
}
//
// Transform the time tags by scaling their distance from
// the central point of the expansion. We pick the scale to
// make the width of the interval from first to last
// transformed tag equal to 1.
//
for I in 1..=N {
TVALS[I] = ((T13REC[((TSTART - 1) + I)] - MDAEND) / SPAN);
}
//
// Let X be the transformed center of the expansion.
//
X = 0.0;
//
// Let D be the step size for the difference line.
// D will be equal to the length of the interval
// over which the polynomial expansion is applicable.
//
D = (MDAEND - MDABEG);
//
// Rather than evaluating the derivatives of our expansion, we'll
// evaluate the derivatives of a related expansion that has support
// on a shorter interval.
//
// This shrinking operation was originally done to work around a
// numeric overflow problem in separate software run on a VAX and
// subject to configuration control restrictions that prevented
// correction of the problem.
//
// Since the algorithm works and since there is no strong
// reason to change it, it is left in its original form.
//
//
SHRINK = intrinsics::DMIN1(&[1.0, (1.0 / SPAN)]);
//
// Pack the function and derivative values.
//
for I in 1..=3 {
TO = (1 + ((2 * N) * (I - 1)));
for J in 1..=N {
FROM = ((1 + ((J - 1) * 6)) + I);
RSYS[TO] = T13REC[FROM];
FROM = (((1 + ((J - 1) * 6)) + I) + 3);
RSYS[(TO + N)] = (T13REC[FROM] * SPAN);
TO = (TO + 1);
}
}
//
//
// Construct a coefficient matrix.
//
T_TAYMAT(N, TVALS.as_slice(), X, MBUFF.as_slice_mut(), ctx)?;
//
// Solve for the Taylor coefficients at X, and compute derivatives
// for all three vector components.
//
T_TAYHRM(
N,
3,
MBUFF.as_slice_mut(),
RSYS.as_slice_mut(),
DBUFF.as_slice_mut(),
FOUND,
ctx,
)?;
if !*FOUND {
spicelib::CHKOUT(b"T_T13XMD", ctx)?;
return Ok(());
}
for I in 1..=3 {
//
// Unpack the derivatives for the Ith component.
//
FROM = (1 + ((2 * N) * (I - 1)));
spicelib::MOVED(DBUFF.subarray(FROM), (2 * N), DERIVS.as_slice_mut());
//
// Now that we have the derivatives, obtain the corresponding
// difference line and write it into the type 21 output record.
// The record description from SPKE21 is copied below.
//
// Name Dimension Description
// ------ --------- -------------------------------
// TL 1 Final epoch of record
// G MAXDIM Stepsize function vector
// REFPOS 3 Reference position vector
// REFVEL 3 Reference velocity vector
// DT MAXDIM,NTE Modified divided difference arrays
// KQMAX1 1 Maximum integration order plus 1
// KQ NTE Integration order array
//
//
// Scale velocity and acceleration to compensate for the
// shrinkage factor. The higher derivatives are scaled
// separately.
//
DERIVS[2] = (DERIVS[2] * SHRINK);
DERIVS[3] = (DERIVS[3] * f64::powi(SHRINK, 2));
//
// Compute the scaled step size S.
//
S = (D * SHRINK);
//
// We're going to scale the Jth element of the acceleration
// portion (starting with the derivative of acceleration) of our
// derivatives array by SHRINK**2 * S**J. Since S can be large,
// we must do this carefully. We arrange our multiplications so
// that we never compute a large power of S directly.
//
spicelib::CLEARD(MDASIZ, ACCDER.as_slice_mut());
spicelib::MOVED(DERIVS.subarray(4), (DEGP - 2), ACCDER.as_slice_mut());
for J in 1..=(DEGP - 2) {
ACCDER[J] = ((ACCDER[J] * S) * f64::powi(SHRINK, 2));
for K in 1..=(J - 1) {
ACCDER[J] = (ACCDER[J] * S);
}
}
spicelib::MOVED(ACCDER.as_slice(), (DEGP - 2), DERIVS.subarray_mut(4));
spicelib::CLEARD(MDASIZ, DT.as_slice_mut());
//
// Compute the difference table for the current polynomial:
//
T_PD2DT(
(DEGP - 2),
DERIVS.subarray_mut(3),
WORK.as_slice_mut(),
DT.as_slice_mut(),
ctx,
);
MDALOC = ((MDAOFF + 1) + ((I - 1) * MDASIZ));
spicelib::MOVED(DT.as_slice(), MDASIZ, T21REC.subarray_mut(MDALOC));
//
// Put into the output array the reference position and velocity
// values for the current state component.
//
MDALOC = ((2 + MDASIZ) + (2 * (I - 1)));
T21REC[MDALOC] = DERIVS[1];
MDALOC = (MDALOC + 1);
T21REC[MDALOC] = DERIVS[2];
}
//
// Fill in the rest of the type 21 record.
//
// Reference epoch. This is also the final epoch covered by
// the record:
//
T21REC[1] = MDAEND;
//
// Stepsize values:
//
spicelib::FILLD(D, MDASIZ, T21REC.subarray_mut(2));
//
// Maximum integration order plus 1:
//
MDALOC = ((((1 + MDASIZ) + (2 * 3)) + (3 * MDASIZ)) + 1);
T21REC[MDALOC] = (MDASIZ + 1) as f64;
//
// Integration orders for each component:
//
MDALOC = (MDALOC + 1);
spicelib::FILLD((MDASIZ as f64), 3, T21REC.subarray_mut(MDALOC));
//
// Shift the record to make room for the initial size value.
//
DLSIZE = ((4 * MDASIZ) + 11);
for I in intrinsics::range(DLSIZE, 1, -1) {
T21REC[(I + 1)] = T21REC[I];
}
T21REC[1] = (MAXDIM as f64);
//
// FOUND is set; it was set by TAYHRM.
//
spicelib::CHKOUT(b"T_T13XMD", ctx)?;
Ok(())
}