1 /* spkr19.f -- translated by f2c (version 19980913).
2 You must link the resulting object file with the libraries:
3 -lf2c -lm (in that order)
4 */
5
6 #include "f2c.h"
7
8 /* Table of constant values */
9
10 static integer c__198 = 198;
11 static integer c__2 = 2;
12 static integer c__6 = 6;
13
14 /* $Procedure SPKR19 ( SPK, read record from segment, type 19 ) */
spkr19_(integer * handle,doublereal * descr,doublereal * et,doublereal * record)15 /* Subroutine */ int spkr19_(integer *handle, doublereal *descr, doublereal *
16 et, doublereal *record)
17 {
18 /* Initialized data */
19
20 static integer mxwnsz[3] = { 14,28,28 };
21 static integer svminb = -1;
22 static integer svn = -1;
23 static integer svnpkt = -1;
24 static logical svok = FALSE_;
25 static integer svpkdb = -1;
26 static integer svpknd = -1;
27 static integer svpksz = -1;
28 static integer svstyp = -1;
29 static integer svwnsz = -1;
30 static logical pass1 = TRUE_;
31 static integer pktszs[3] = { 12,6,6 };
32 static integer svbeg = -1;
33 static doublereal svbtim = 0.;
34 static doublereal svetim = -1.;
35 static integer svhan = 0;
36 static logical svlast = FALSE_;
37 static integer svmiix = -1;
38
39 /* System generated locals */
40 integer i__1, i__2;
41
42 /* Builtin functions */
43 integer i_dnnt(doublereal *), s_rnge(char *, integer, char *, integer);
44
45 /* Local variables */
46 integer high, isel, ndir, last, npkt, type__, i__, baddr, n, eaddr, nread;
47 extern /* Subroutine */ int chkin_(char *, ftnlen);
48 integer minib, minie;
49 extern /* Subroutine */ int dafus_(doublereal *, integer *, integer *,
50 doublereal *, integer *);
51 integer ivbas;
52 extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen);
53 integer ivbix, iveix, lsize, first, group, rsize;
54 logical prvok;
55 extern /* Subroutine */ int dafgda_(integer *, integer *, integer *,
56 doublereal *);
57 doublereal dc[2];
58 integer ic[6];
59 extern logical failed_(void);
60 integer begidx, bufbas, dirbas, pkdbas;
61 doublereal buffer[101];
62 integer endidx, remain, timbas;
63 logical samseg;
64 extern integer lstled_(doublereal *, integer *, doublereal *);
65 integer npkdir;
66 logical samivl;
67 extern /* Subroutine */ int sigerr_(char *, ftnlen);
68 doublereal mintim[2];
69 integer maxwnd, miniix;
70 doublereal contrl[3];
71 integer nrcpkt;
72 extern integer lstltd_(doublereal *, integer *, doublereal *);
73 logical ivlsel;
74 extern /* Subroutine */ int setmsg_(char *, ftnlen), errint_(char *,
75 integer *, ftnlen), chkout_(char *, ftnlen);
76 integer wndsiz;
77 extern logical return_(void);
78 integer pktsiz, subtyp;
79 extern logical odd_(integer *);
80 integer low;
81
82 /* $ Abstract */
83
84 /* Read a single SPK data record from a segment of type 19 */
85 /* (ESOC/DDID Piecewise Interpolation). */
86
87 /* $ Disclaimer */
88
89 /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
90 /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
91 /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
92 /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
93 /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
94 /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
95 /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
96 /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
97 /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
98 /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
99
100 /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
101 /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
102 /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
103 /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
104 /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
105 /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
106
107 /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
108 /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
109 /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
110 /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
111
112 /* $ Required_Reading */
113
114 /* SPK */
115
116 /* $ Keywords */
117
118 /* EPHEMERIS */
119
120 /* $ Declarations */
121 /* $ Abstract */
122
123 /* Declare parameters specific to SPK type 19. */
124
125 /* $ Disclaimer */
126
127 /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
128 /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
129 /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
130 /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
131 /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
132 /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
133 /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
134 /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
135 /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
136 /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
137
138 /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
139 /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
140 /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
141 /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
142 /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
143 /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
144
145 /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
146 /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
147 /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
148 /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
149
150 /* $ Required_Reading */
151
152 /* SPK */
153
154 /* $ Keywords */
155
156 /* SPK */
157
158 /* $ Restrictions */
159
160 /* None. */
161
162 /* $ Author_and_Institution */
163
164 /* N.J. Bachman (JPL) */
165 /* B.V. Semenov (JPL) */
166
167 /* $ Literature_References */
168
169 /* None. */
170
171 /* $ Version */
172
173 /* - SPICELIB Version 2.0.0, 11-MAY-2015 (NJB) */
174
175 /* Updated to support subtype 2. */
176
177 /* - SPICELIB Version 1.0.0, 07-MAR-2014 (NJB) (BVS) */
178
179 /* -& */
180
181 /* Maximum polynomial degree supported by the current */
182 /* implementation of this SPK type. */
183
184 /* The degree is compatible with the maximum degrees */
185 /* supported by types 13 and 21. */
186
187
188 /* Integer code indicating `true': */
189
190
191 /* Integer code indicating `false': */
192
193
194 /* SPK type 19 subtype codes: */
195
196
197 /* Subtype 0: Hermite interpolation, 12-element packets. */
198
199
200 /* Subtype 1: Lagrange interpolation, 6-element packets. */
201
202
203 /* Subtype 2: Hermite interpolation, 6-element packets. */
204
205
206 /* Packet sizes associated with the various subtypes: */
207
208
209 /* Number of subtypes: */
210
211
212 /* Maximum packet size for type 19: */
213
214
215 /* Minimum packet size for type 19: */
216
217
218 /* The SPKPVN record size declared in spkrec.inc must be at least as */
219 /* large as the maximum possible size of an SPK type 19 record. */
220
221 /* The largest possible SPK type 19 record has subtype 1 (note that */
222 /* records of subtype 0 have half as many epochs as those of subtype */
223 /* 1, for a given polynomial degree). A type 1 record contains */
224
225 /* - The subtype and packet count */
226 /* - MAXDEG+1 packets of size S19PS1 */
227 /* - MAXDEG+1 time tags */
228
229
230 /* End of include file spk19.inc. */
231
232 /* $ Abstract */
233
234 /* Declare SPK data record size. This record is declared in */
235 /* SPKPVN and is passed to SPK reader (SPKRxx) and evaluator */
236 /* (SPKExx) routines. */
237
238 /* $ Disclaimer */
239
240 /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
241 /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
242 /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
243 /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
244 /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
245 /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
246 /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
247 /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
248 /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
249 /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
250
251 /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
252 /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
253 /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
254 /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
255 /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
256 /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
257
258 /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
259 /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
260 /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
261 /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
262
263 /* $ Required_Reading */
264
265 /* SPK */
266
267 /* $ Keywords */
268
269 /* SPK */
270
271 /* $ Restrictions */
272
273 /* 1) If new SPK types are added, it may be necessary to */
274 /* increase the size of this record. The header of SPKPVN */
275 /* should be updated as well to show the record size */
276 /* requirement for each data type. */
277
278 /* $ Author_and_Institution */
279
280 /* N.J. Bachman (JPL) */
281
282 /* $ Literature_References */
283
284 /* None. */
285
286 /* $ Version */
287
288 /* - SPICELIB Version 2.0.0, 05-OCT-2012 (NJB) */
289
290 /* Updated to support increase of maximum degree to 27 for types */
291 /* 2, 3, 8, 9, 12, 13, 18, and 19. See SPKPVN for a list */
292 /* of record size requirements as a function of data type. */
293
294 /* - SPICELIB Version 1.0.0, 16-AUG-2002 (NJB) */
295
296 /* -& */
297
298 /* End include file spkrec.inc */
299
300 /* $ Brief_I/O */
301
302 /* Variable I/O Description */
303 /* -------- --- -------------------------------------------------- */
304 /* HANDLE I File handle. */
305 /* DESCR I Segment descriptor. */
306 /* ET I Target epoch. */
307 /* RECORD O Data record. */
308
309 /* $ Detailed_Input */
310
311 /* HANDLE, */
312 /* DESCR are the file handle and segment descriptor for an SPK */
313 /* segment of type 19. The SPK file designated by HANDLE */
314 /* must be open for read access. */
315
316 /* ET is an epoch for which a data record from a specific */
317 /* segment is required. ET is expressed as seconds past */
318 /* J2000 TDB. */
319
320 /* $ Detailed_Output */
321
322 /* RECORD is an array of data from the specified segment which, */
323 /* when evaluated at epoch ET, will give the state */
324 /* (position and velocity) of the target body identified */
325 /* by the input segment descriptor. The descriptor */
326 /* specifies the center of motion and reference frame of */
327 /* the state. */
328
329 /* The structure of the record is as follows: */
330
331 /* +----------------------+ */
332 /* | subtype code | */
333 /* +----------------------+ */
334 /* | number of packets (n)| */
335 /* +----------------------+ */
336 /* | packet 1 | */
337 /* +----------------------+ */
338 /* | packet 2 | */
339 /* +----------------------+ */
340 /* . */
341 /* . */
342 /* . */
343 /* +----------------------+ */
344 /* | packet n | */
345 /* +----------------------+ */
346 /* | epochs 1--n | */
347 /* +----------------------+ */
348
349 /* The packet size is a function of the type 19 subtype. */
350 /* All packets in a record have the same size. */
351
352 /* $ Parameters */
353
354 /* See the Fortran INCLUDE file spk19.inc. */
355
356 /* $ Exceptions */
357
358 /* 1) If the input HANDLE does not designate a loaded SPK file, the */
359 /* error will be diagnosed by routines called by this routine. */
360
361 /* 2) If the segment specified by DESCR is not of data type 19, */
362 /* the error 'SPICE(WRONGSPKTYPE)' is signaled. */
363
364 /* 3) If the input ET value is not within the range specified */
365 /* in the segment descriptor, the error SPICE(TIMEOUTOFBOUNDS) */
366 /* is signaled. */
367
368 /* 4) If the window size is non-positive or greater than the */
369 /* maximum allowed value, the error SPICE(INVALIDVALUE) is */
370 /* signaled. */
371
372 /* 5) If the window size is not compatible with the segment */
373 /* subtype, the error SPICE(INVALIDVALUE) is signaled. */
374
375 /* 6) If the segment subtype is not recognized, the error */
376 /* SPICE(NOTSUPPORTED) is signaled. */
377
378 /* $ Files */
379
380 /* See argument HANDLE. */
381
382 /* $ Particulars */
383
384 /* SPICE user applications normally will have no need to call this */
385 /* routine directly. For further information, see the headers of the */
386 /* SPICE SPK APIs */
387
388 /* SPKEZR */
389 /* SPKPOS */
390
391 /* the SPK Required Reading file spk.req, and the SPICE SPK */
392 /* tutorial. */
393
394 /* See the SPK Required Reading file for a description of the */
395 /* structure of a data type 19 segment. */
396
397 /* $ Examples */
398
399 /* The data returned by the SPKRnn routine is in its rawest form, */
400 /* taken directly from the segment. As such, it will be meaningless */
401 /* to a user unless he/she understands the structure of the data type */
402 /* completely. Given that understanding, however, the SPKRxx */
403 /* routines might be used to "dump" and check segment data for a */
404 /* particular epoch. */
405
406
407 /* C */
408 /* C Get a segment applicable to a specified body and epoch. */
409 /* C */
410 /* CALL SPKSFS ( BODY, ET, HANDLE, DESCR, IDENT, FOUND ) */
411
412 /* C */
413 /* C Look at parts of the descriptor. */
414 /* C */
415 /* CALL DAFUS ( DESCR, 2, 6, DCD, ICD ) */
416 /* CENTER = ICD( 2 ) */
417 /* REF = ICD( 3 ) */
418 /* TYPE = ICD( 4 ) */
419
420 /* IF ( TYPE .EQ. 19 ) THEN */
421 /* CALL SPKR19 ( HANDLE, DESCR, ET, RECORD ) */
422 /* . */
423 /* . Look at the RECORD data. */
424 /* . */
425 /* END IF */
426
427 /* $ Restrictions */
428
429 /* 1) Correctness of inputs must be ensured by the caller of */
430 /* this routine. */
431
432 /* $ Literature_References */
433
434 /* None. */
435
436 /* $ Author_and_Institution */
437
438 /* N.J. Bachman (JPL) */
439 /* B.V. Semenov (JPL) */
440
441 /* $ Version */
442
443 /* - SPICELIB Version 2.0.0, 11-MAY-2015 (NJB) */
444
445 /* Updated to support subtype 2. */
446
447 /* - SPICELIB Version 1.0.0, 14-MAR-2014 (NJB) (BVS) */
448
449 /* -& */
450 /* $ Index_Entries */
451
452 /* read record from type_19 spk segment */
453
454 /* -& */
455 /* $ Revisions */
456
457 /* None. */
458
459 /* -& */
460
461 /* SPICELIB functions */
462
463
464 /* Local parameters */
465
466
467 /* Maximum window sizes, based on subtypes: */
468
469
470 /* Local variables */
471
472
473 /* Saved variables */
474
475
476 /* Initial values */
477
478 if (return_()) {
479 return 0;
480 }
481 chkin_("SPKR19", (ftnlen)6);
482
483 /* Before any error checks are done, copy the status from */
484 /* the previous call. Set the saved status variable to */
485 /* .FALSE. here so it will be .FALSE. on exit unless this */
486 /* call is successful. */
487
488 prvok = svok;
489 svok = FALSE_;
490
491 /* Terminology: below, the phrase "base address of 'X'" refers to */
492 /* the DAF address immediately preceding X. Base addresses simplify */
493 /* mapping DAF array (here "array" means an array stored in */
494 /* consecutive DAF addresses, not "segment") indices to DAF */
495 /* addresses, since the DAF address of the Ith array element is */
496 /* obtained by adding I to the DAF array's base address. */
497
498 /* Key variables: */
499
500 /* Name Meaning */
501 /* ---- ------- */
502 /* BADDR Segment begin DAF address. */
503
504 /* DIRBAS Base address of interpolation interval directory. */
505
506 /* EADDR Segment end DAF address. */
507
508 /* FIRST Index (mini-segment-relative) of first time tag in */
509 /* sequence transferred to to output record. */
510
511 /* HIGH Index (mini-segment-relative) of time tag following */
512 /* the tag at index LOW (see description below). */
513
514 /* IVBIX Index in the interpolation interval bounds array of */
515 /* the start time of the applicable interval. */
516
517 /* IVLBAS Base address of interpolation interval time bounds. */
518
519 /* IVLSEL Interval selection flag: this routine selects the */
520 /* last applicable interval if true; otherwise it */
521 /* selects the first applicable interval. */
522
523 /* LAST Index (mini-segment-relative) of last time tag in */
524 /* sequence transferred to the output record. */
525
526 /* LOW Index (mini-segment-relative) of last time tag less */
527 /* than the request time, or of the first time tag if */
528 /* this tag equals the request time. */
529
530 /* MINIB, */
531 /* MINIE Mini-segment begin and end DAF addresses. These */
532 /* addresses are absolute, not segment-relative. */
533
534 /* MINIIX Interpolation interval/mini-segment index. */
535
536 /* N Count of interpolation intervals/mini-segments. */
537
538 /* NDIR Number of interpolation interval time bounds */
539 /* directories. */
540
541 /* NPKDIR Number of packet directory entries for current */
542 /* mini-segment. */
543
544 /* NPKT Packet count for current mini-segment. */
545
546 /* NRCPKT Output record packet count. Note that this count, */
547 /* due to reduction of order at mini-segment */
548 /* boundaries, may be smaller than the window size */
549 /* stored in the current mini-segment. */
550
551 /* PKDBAS Base address of packet directory for current */
552 /* mini-segment. */
553
554 /* PKTSIZ Size of packets of current mini-segment. */
555
556 /* SUBTYP Subtype of current mini-segment. */
557
558 /* TIMBAS Base address of time tags of current mini-segment. */
559
560 /* WNDSIZ Interpolation window size of current mini-segment. */
561
562
563 /* Re-used variables: the variables shown in the list below */
564 /* are used as short-duration variables, much like loop index */
565 /* variables; they are re-used as needed. */
566
567 /* BUFBAS */
568 /* BUFFER */
569 /* GROUP */
570 /* NREAD */
571 /* REMAIN */
572
573 /* Start with a parameter compatibility check on the first */
574 /* pass. */
575
576 if (pass1) {
577 if (FALSE_) {
578 setmsg_("SPK type 19 record size may be as large as #, but SPKPV"
579 "N record size (defined in spkrec.inc) is #.", (ftnlen)98);
580 errint_("#", &c__198, (ftnlen)1);
581 errint_("#", &c__198, (ftnlen)1);
582 sigerr_("SPICE(BUG)", (ftnlen)10);
583 }
584
585 /* Indicate the first pass was completed. */
586
587 pass1 = FALSE_;
588 }
589
590 /* Unpack the segment descriptor, and get the start and end */
591 /* addresses of the segment. */
592
593 dafus_(descr, &c__2, &c__6, dc, ic);
594 type__ = ic[3];
595 baddr = ic[4];
596 eaddr = ic[5];
597
598 /* Check the request time against the bounds in the segment */
599 /* descriptor. */
600
601 if (*et < dc[0] || *et > dc[1]) {
602 setmsg_("Request time # is outside of descriptor bounds # : #.", (
603 ftnlen)53);
604 errdp_("#", et, (ftnlen)1);
605 errdp_("#", dc, (ftnlen)1);
606 errdp_("#", &dc[1], (ftnlen)1);
607 sigerr_("SPICE(TIMEOUTOFBOUNDS)", (ftnlen)22);
608 chkout_("SPKR19", (ftnlen)6);
609 return 0;
610 }
611
612 /* Decide whether we're looking at the same segment we saw on the */
613 /* previous call, and whether the interpolation interval used on */
614 /* that call is still applicable. */
615
616 /* Re-use of data from a previous call requires that the saved */
617 /* data were set on a successful call. */
618
619 samseg = *handle == svhan && baddr == svbeg && prvok;
620
621 /* Give SAMIVL an initial value. If we do have the */
622 /* same interval, update SAMIVL to indicate this. */
623
624 samivl = FALSE_;
625 if (samseg) {
626
627 /* We now assume that all data saved from the last */
628 /* read of this segment are valid. */
629
630 if (svlast) {
631
632 /* We pick the last interval containing ET. For */
633 /* all intervals but the last, ET must be */
634 /* less than the interval end time. */
635
636 if (svmiix < svn) {
637 samivl = *et >= svbtim && *et < svetim;
638 } else {
639 samivl = *et >= svbtim && *et <= svetim;
640 }
641 } else {
642
643 /* We pick the first interval containing ET. For */
644 /* all intervals but the first, ET must be */
645 /* greater than the interval start time. */
646
647 if (svmiix > 1) {
648 samivl = *et > svbtim && *et <= svetim;
649 } else {
650 samivl = *et >= svbtim && *et <= svetim;
651 }
652 }
653 }
654 if (samseg && samivl) {
655
656 /* We're looking at the same segment as last time, and the */
657 /* interpolation interval we looked up last time is applicable */
658 /* for the input time ET. */
659
660 /* Simply restore the segment and interval parameters we */
661 /* saved from the previous lookup. */
662
663 /* We don't need to restore the segment start DAF address */
664 /* BADDR, since we've already extracted it from DESCR. */
665
666 /* Restore */
667
668 /* - The mini-segment's packet directory count */
669 /* - The mini-segment's packet directory base address */
670
671 npkdir = svpknd;
672 pkdbas = svpkdb;
673
674 /* Restore */
675
676 /* - The mini-segment/interval count */
677 /* - The mini-segment/interval index */
678 /* - The mini-segment/interval start pointer */
679
680 n = svn;
681 miniix = svmiix;
682 minib = svminb;
683
684 /* Restore */
685
686 /* - The mini-segment subtype */
687 /* - The mini-segment packet size */
688 /* - The mini-segment packet count */
689 /* - The mini-segment window size */
690
691 subtyp = svstyp;
692 pktsiz = svpksz;
693 npkt = svnpkt;
694 wndsiz = svwnsz;
695 } else {
696
697 /* The segment and interval information for the current segment */
698 /* must be looked up. */
699
700 /* Perform checks on this segment. */
701
702 /* Make sure that this really is a type 19 data segment. */
703
704 if (type__ != 19) {
705 setmsg_("You are attempting to locate type * data in a type 19 d"
706 "ata segment.", (ftnlen)67);
707 errint_("*", &type__, (ftnlen)1);
708 sigerr_("SPICE(WRONGSPKTYPE)", (ftnlen)19);
709 chkout_("SPKR19", (ftnlen)6);
710 return 0;
711 }
712
713 /* Locate the interpolation interval that contains the request */
714 /* time. */
715
716 /* Before getting started, we need to determine which interval to */
717 /* use if the request time lies on a boundary between two */
718 /* intervals. The segment's interval selection flag tells us how */
719 /* to resolve this. */
720
721 i__1 = eaddr - 1;
722 dafgda_(handle, &i__1, &eaddr, contrl);
723 if (failed_()) {
724 chkout_("SPKR19", (ftnlen)6);
725 return 0;
726 }
727 isel = i_dnnt(contrl);
728 n = i_dnnt(&contrl[1]);
729 ivlsel = isel == 1;
730
731 /* Determine the number of interval directory entries in the */
732 /* segment. Note that for most SPK types, this computation is */
733 /* performed by computing */
734
735 /* ( N - 1 ) / DIRSIZ */
736
737 /* where N is the segment's epoch count. */
738
739 /* However the set of items in this case is a sequence */
740 /* of N start times followed by a final stop time, so */
741 /* the epoch count is */
742
743 /* N + 1 */
744
745 /* and the numerator in the ratio above is incremented by 1. */
746
747 ndir = n / 100;
748
749 /* Note that the directory placement scheme always leaves */
750 /* a non-empty set of epochs following the last directory */
751 /* entry. */
752
753 /* Let DIRBAS be the base address of the interval directory. */
754 /* We'll compute DIRBAS whether or not the interval directory */
755 /* is non-empty. */
756
757 /* If the interval directory is non-empty, it spans the address */
758 /* range */
759
760 /* DIRBAS+1 : DIRBAS+NDIR */
761
762 /* We compute DIRBAS by starting at the end of the segment */
763 /* and skipping over the control area, the mini-segment */
764 /* start/stop pointers, and the interval directory itself. */
765
766 dirbas = eaddr - 2 - (n + 1) - ndir;
767
768 /* The way we search the directory depends on the treatment */
769 /* of request times that lie on interval boundaries. */
770
771 if (ivlsel) {
772
773 /* If there is an interval directory, search it to determine */
774 /* the group of interval times to search next. */
775
776 if (ndir > 0) {
777
778 /* Find the last directory entry *less than or equal to* */
779 /* the request time. The directory entry *after* that one, */
780 /* if such exists, is the one to pick. */
781
782 nread = min(ndir,101);
783 bufbas = dirbas;
784
785 /* Fetch the current batch of directory entries. */
786
787 i__1 = bufbas + 1;
788 i__2 = bufbas + nread;
789 dafgda_(handle, &i__1, &i__2, buffer);
790 if (failed_()) {
791 chkout_("SPKR19", (ftnlen)6);
792 return 0;
793 }
794 remain = ndir - nread;
795
796 /* The variable NREAD always contains a positive value at */
797 /* this point, so we can use it as an array index. */
798
799 while(remain > 0 && buffer[(i__1 = nread - 1) < 101 && 0 <=
800 i__1 ? i__1 : s_rnge("buffer", i__1, "spkr19_", (
801 ftnlen)742)] <= *et) {
802 bufbas += nread;
803 nread = min(remain,101);
804
805 /* Fetch the current batch of directory entries. */
806
807 i__1 = bufbas + 1;
808 i__2 = bufbas + nread;
809 dafgda_(handle, &i__1, &i__2, buffer);
810 if (failed_()) {
811 chkout_("SPKR19", (ftnlen)6);
812 return 0;
813 }
814 remain -= nread;
815 }
816
817 /* Count the directory entries that are less than or equal */
818 /* to ET. The number we skipped over before the final loop */
819 /* iteration is BUFBAS-DIRBAS. The index of the group of */
820 /* epochs containing ET exceeds the skipped directory count */
821 /* by 1. */
822
823 group = bufbas - dirbas + lstled_(et, &nread, buffer) + 1;
824 } else {
825
826 /* There's no question about which group of epochs to */
827 /* search. */
828
829 group = 1;
830 }
831
832 /* Let IVBAS be the base address of the sequence of interval */
833 /* time bounds. */
834
835 ivbas = dirbas - (n + 1);
836
837 /* Now find the index of the last interval boundary less than */
838 /* or equal to ET. We'll need to read the current group of */
839 /* epochs first, so compute the base of the range of addresses */
840 /* containing this group. */
841 bufbas = ivbas + (group - 1) * 100;
842
843 /* Compute the number of epochs to read. Note that all groups */
844 /* of epochs except the last have DIRSIZ elements. */
845
846 remain = n + 1 - (group - 1) * 100;
847
848 /* Note that REMAIN is always non-zero, since there's always */
849 /* at least one epoch that exceeds the last directory entry. */
850
851 nread = min(100,remain);
852 i__1 = bufbas + 1;
853 i__2 = bufbas + nread;
854 dafgda_(handle, &i__1, &i__2, buffer);
855 if (failed_()) {
856 chkout_("SPKR19", (ftnlen)6);
857 return 0;
858 }
859
860 /* Find the index of the first epoch greater than ET. The case */
861 /* where ET matches the final epoch must be handled here, */
862 /* since in this case no epoch exceeds ET. */
863
864 iveix = bufbas - ivbas + lstled_(et, &nread, buffer) + 1;
865 /* Computing MIN */
866 i__1 = iveix, i__2 = n + 1;
867 iveix = min(i__1,i__2);
868
869 /* Backstop test: */
870
871 if (iveix < 2) {
872 setmsg_("IVEIX = #.", (ftnlen)10);
873 errint_("#", &iveix, (ftnlen)1);
874 sigerr_("SPICE(BUG)", (ftnlen)10);
875 chkout_("SPKR19", (ftnlen)6);
876 return 0;
877 }
878
879 /* The epoch at index IVEIX is the end time of the */
880 /* interpolation interval we'll use. The index of */
881 /* the interval itself is IVEIX - 1. */
882
883 miniix = iveix - 1;
884 } else {
885
886 /* IVLSEL is .FALSE., meaning we must pick the first interval */
887 /* containing the request time. */
888
889 /* If there is an interval directory, search it to determine */
890 /* the group of interval times to search next. */
891
892 if (ndir > 0) {
893
894 /* Find the last directory entry *less than* the request */
895 /* time. The directory entry *after* that one, if such */
896 /* exists, is the one to pick. */
897
898 nread = min(ndir,101);
899 bufbas = dirbas;
900 remain = ndir - nread;
901
902 /* Fetch the current batch of directory entries. */
903
904 i__1 = bufbas + 1;
905 i__2 = bufbas + nread;
906 dafgda_(handle, &i__1, &i__2, buffer);
907 if (failed_()) {
908 chkout_("SPKR19", (ftnlen)6);
909 return 0;
910 }
911
912 /* The variable NREAD always contains a positive value at */
913 /* this point, so we can use it as an array index. */
914
915 while(remain > 0 && buffer[(i__1 = nread - 1) < 101 && 0 <=
916 i__1 ? i__1 : s_rnge("buffer", i__1, "spkr19_", (
917 ftnlen)877)] < *et) {
918 bufbas += nread;
919 nread = min(remain,101);
920
921 /* Fetch the current batch of directory entries. */
922
923 i__1 = bufbas + 1;
924 i__2 = bufbas + nread;
925 dafgda_(handle, &i__1, &i__2, buffer);
926 if (failed_()) {
927 chkout_("SPKR19", (ftnlen)6);
928 return 0;
929 }
930 remain -= nread;
931 }
932
933 /* Count the directory entries that are less than ET. The */
934 /* number we skipped over before the final loop iteration */
935 /* is BUFBAS-DIRBAS. The index of the group of epochs */
936 /* containing ET exceeds the skipped directory count by 1. */
937
938 group = bufbas - dirbas + lstltd_(et, &nread, buffer) + 1;
939 } else {
940
941 /* There's no question about which group of epochs to */
942 /* search. */
943
944 group = 1;
945 }
946
947 /* Let IVBAS be the base address of the sequence of interval */
948 /* time bounds. */
949
950 ivbas = dirbas - (n + 1);
951
952 /* Now find the index of the last interval epoch less than ET. */
953 /* We'll need to read the current group of epochs first, so */
954 /* compute the base of the range of addresses containing this */
955 /* group. */
956 bufbas = ivbas + (group - 1) * 100;
957
958 /* Compute the number of epochs to read. Note that all groups */
959 /* of epochs except the last have DIRSIZ elements. */
960
961 remain = n + 1 - (group - 1) * 100;
962
963 /* Note that REMAIN is always non-zero, since there's always */
964 /* at least one epoch that exceeds the last directory entry. */
965
966 nread = min(100,remain);
967 i__1 = bufbas + 1;
968 i__2 = bufbas + nread;
969 dafgda_(handle, &i__1, &i__2, buffer);
970 if (failed_()) {
971 chkout_("SPKR19", (ftnlen)6);
972 return 0;
973 }
974
975 /* Find the index of the last epoch less than ET. The case */
976 /* where ET matches the first epoch must be handled here, */
977 /* since in this case no epoch precedes ET. */
978
979 ivbix = bufbas - ivbas + lstltd_(et, &nread, buffer);
980 ivbix = max(ivbix,1);
981
982 /* Backstop test: */
983
984 if (ivbix > n) {
985 setmsg_("IVBIX = #.", (ftnlen)10);
986 errint_("#", &ivbix, (ftnlen)1);
987 sigerr_("SPICE(BUG)", (ftnlen)10);
988 chkout_("SPKR19", (ftnlen)6);
989 return 0;
990 }
991
992 /* The epoch at index IVBIX is the begin time of the */
993 /* interpolation interval we'll use. The index of the interval */
994 /* itself is also IVBIX. */
995
996 miniix = ivbix;
997 }
998
999 /* This is the end of the IF block that handles mini-segment */
1000 /* selection for the two possible values of IVLSEL. */
1001
1002 /* Look up the begin and end pointers of the mini-segment at index */
1003 /* MINIIX. For the first N-1 mini-segments, the "end pointer" */
1004 /* of one mini-segment is the "begin" pointer of the next. */
1005
1006 bufbas = eaddr - 2 - (n + 1) + (miniix - 1);
1007 i__1 = bufbas + 1;
1008 i__2 = bufbas + 2;
1009 dafgda_(handle, &i__1, &i__2, buffer);
1010 if (failed_()) {
1011 chkout_("SPKR19", (ftnlen)6);
1012 return 0;
1013 }
1014 minib = i_dnnt(buffer) + baddr - 1;
1015
1016 /* Note that the end of the current mini-segment */
1017 /* precedes the start of the next mini-segment by */
1018 /* one address. */
1019
1020 minie = i_dnnt(&buffer[1]) + baddr - 2;
1021
1022 /* Look up the time bounds of the mini-segment at index MINIIX. */
1023 /* These bounds are used quite a bit farther on, when we save */
1024 /* them for future use. */
1025
1026 i__1 = ivbas + miniix;
1027 i__2 = ivbas + miniix + 1;
1028 dafgda_(handle, &i__1, &i__2, mintim);
1029 if (failed_()) {
1030 chkout_("SPKR19", (ftnlen)6);
1031 return 0;
1032 }
1033
1034 /* From this point onward, we'll work with the mini-segment */
1035 /* that occupies the address range MINIB : MINIE. */
1036
1037 /* Look up the control area of the mini-segment. */
1038
1039 i__1 = minie - 2;
1040 dafgda_(handle, &i__1, &minie, contrl);
1041 if (failed_()) {
1042 chkout_("SPKR19", (ftnlen)6);
1043 return 0;
1044 }
1045
1046 /* Fetch the control area parameters for the mini-segment. */
1047
1048 subtyp = i_dnnt(contrl);
1049 wndsiz = i_dnnt(&contrl[1]);
1050 npkt = i_dnnt(&contrl[2]);
1051 if (subtyp < 0 || subtyp >= 3) {
1052 setmsg_("Unexpected SPK type 19 subtype # found in type 19 segme"
1053 "nt within mini-segment #.", (ftnlen)80);
1054 errint_("#", &subtyp, (ftnlen)1);
1055 errint_("#", &miniix, (ftnlen)1);
1056 sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19);
1057 chkout_("SPKR19", (ftnlen)6);
1058 return 0;
1059 }
1060 pktsiz = pktszs[(i__1 = subtyp) < 3 && 0 <= i__1 ? i__1 : s_rnge(
1061 "pktszs", i__1, "spkr19_", (ftnlen)1047)];
1062 maxwnd = mxwnsz[(i__1 = subtyp) < 3 && 0 <= i__1 ? i__1 : s_rnge(
1063 "mxwnsz", i__1, "spkr19_", (ftnlen)1048)];
1064
1065 /* Check the window size. */
1066
1067 if (wndsiz < 2 || wndsiz > maxwnd) {
1068 setmsg_("Window size in type 19 segment was #; must be in the ra"
1069 "nge 2:# for subtype #. Mini-segment index is #.", (ftnlen)
1070 102);
1071 errint_("#", &wndsiz, (ftnlen)1);
1072 errint_("#", &maxwnd, (ftnlen)1);
1073 errint_("#", &subtyp, (ftnlen)1);
1074 errint_("#", &miniix, (ftnlen)1);
1075 sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19);
1076 chkout_("SPKR19", (ftnlen)6);
1077 return 0;
1078 }
1079 if (odd_(&wndsiz)) {
1080 setmsg_("Window size in type 19 segment was #; must be even for "
1081 "subtype #. Mini-segment index is #.", (ftnlen)90);
1082 errint_("#", &wndsiz, (ftnlen)1);
1083 errint_("#", &subtyp, (ftnlen)1);
1084 errint_("#", &miniix, (ftnlen)1);
1085 sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19);
1086 chkout_("SPKR19", (ftnlen)6);
1087 return 0;
1088 }
1089
1090 /* Compute the number of packet directory entries for */
1091 /* the current mini-segment/interval. */
1092
1093 npkdir = (npkt - 1) / 100;
1094
1095 /* Compute the base address of the sequence of packet */
1096 /* directory entries for the current mini-segment/interval. */
1097
1098 pkdbas = minib - 1 + npkt * (pktsiz + 1);
1099
1100 /* The test below is done for safety. No SPICE error s */
1101 /* should ever be detected at this point. */
1102
1103 if (failed_()) {
1104 chkout_("SPKR19", (ftnlen)6);
1105 return 0;
1106 }
1107
1108 /* If we made it this far, we did so without a SPICE error. We */
1109 /* have valid segment parameters which can be saved for the next */
1110 /* call. */
1111
1112 /* Save */
1113
1114 /* - The DAF handle */
1115 /* - The segment begin DAF address */
1116 /* - The segment's "select last/first interval" flag */
1117
1118 svhan = *handle;
1119 svbeg = baddr;
1120 svlast = ivlsel;
1121
1122 /* Save the time bounds of the applicable mini-segment/interval. */
1123
1124 svbtim = mintim[0];
1125 svetim = mintim[1];
1126
1127 /* Save */
1128
1129 /* - The mini-segment/interval directory count */
1130 /* - The mini-segment/interval directory base address */
1131
1132 svpknd = npkdir;
1133 svpkdb = pkdbas;
1134
1135 /* Save */
1136
1137 /* - The mini-segment/interval count */
1138 /* - The mini-segment/interval index */
1139 /* - The mini-segment/interval start pointer */
1140
1141 svn = n;
1142 svmiix = miniix;
1143 svminb = minib;
1144
1145 /* Save */
1146
1147 /* - The mini-segment subtype */
1148 /* - The mini-segment packet size */
1149 /* - The mini-segment packet count */
1150 /* - The mini-segment window size */
1151
1152 svstyp = subtyp;
1153 svpksz = pktsiz;
1154 svnpkt = npkt;
1155 svwnsz = wndsiz;
1156 }
1157
1158 /* We're ready to construct the output record. The first step is to */
1159 /* identify the indices of the packets and epochs corresponding to */
1160 /* the request. */
1161
1162 /* We'll now select the set of packets that define the interpolating */
1163 /* polynomials. We'll start out by finding the first directory */
1164 /* entry that is greater than or equal to the request epoch. We'll */
1165 /* use the variable GROUP to indicate the set of epochs to search */
1166 /* within, once we've found the right directory entry. */
1167
1168 if (npkdir == 0) {
1169
1170 /* There's no mystery about which group of epochs to search. */
1171
1172 group = 1;
1173 } else {
1174
1175 /* There's at least one directory entry. Find the first directory */
1176 /* entry whose time is greater than or equal to the request time, */
1177 /* if there is such an entry. We'll search linearly through the */
1178 /* directory entries, reading up to DIRSIZ of them at a time. */
1179 /* Having found the correct set of directory entries, we'll */
1180 /* perform a binary search within that set for the desired entry. */
1181
1182 bufbas = pkdbas;
1183 nread = min(npkdir,100);
1184 remain = npkdir - nread;
1185 i__1 = bufbas + 1;
1186 i__2 = bufbas + nread;
1187 dafgda_(handle, &i__1, &i__2, buffer);
1188 if (failed_()) {
1189 chkout_("SPKR19", (ftnlen)6);
1190 return 0;
1191 }
1192 while(buffer[(i__1 = nread - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge(
1193 "buffer", i__1, "spkr19_", (ftnlen)1196)] < *et && remain > 0)
1194 {
1195 bufbas += nread;
1196 nread = min(remain,100);
1197 remain -= nread;
1198
1199 /* Note: NREAD is always > 0 here. */
1200
1201 i__1 = bufbas + 1;
1202 i__2 = bufbas + nread;
1203 dafgda_(handle, &i__1, &i__2, buffer);
1204 if (failed_()) {
1205 chkout_("SPKR19", (ftnlen)6);
1206 return 0;
1207 }
1208 }
1209
1210 /* At this point, BUFBAS - PKDBAS is the number of directory */
1211 /* entries preceding the one contained in BUFFER(1). */
1212
1213 group = bufbas - pkdbas + lstltd_(et, &nread, buffer) + 1;
1214 }
1215
1216 /* GROUP now indicates the set of epochs in which to search for the */
1217 /* request epoch. If GROUP is 1, the request time lies within the */
1218 /* inclusive time interval bounded by the first and last epochs of */
1219 /* the first group. Otherwise, the request time lies in the time */
1220 /* interval bounded by the last element of the preceding group and */
1221 /* the last element of the current group. */
1222
1223 /* We'll use the variable names BEGIDX and ENDIDX to refer to */
1224 /* the indices, relative to the set of time tags, of the first */
1225 /* and last time tags in the set we're going to look up. */
1226
1227 if (group == 1) {
1228 begidx = 1;
1229 endidx = min(npkt,100);
1230 } else {
1231
1232 /* If the group index is greater than 1, we'll include the last */
1233 /* time tag of the previous group in the set of time tags we look */
1234 /* up. That way, the request time is bracketed by the time tag */
1235 /* set we look up. */
1236
1237 begidx = (group - 1) * 100;
1238 /* Computing MIN */
1239 i__1 = begidx + 100;
1240 endidx = min(i__1,npkt);
1241 }
1242 timbas = pkdbas - npkt;
1243 i__1 = timbas + begidx;
1244 i__2 = timbas + endidx;
1245 dafgda_(handle, &i__1, &i__2, buffer);
1246 if (failed_()) {
1247 chkout_("SPKR19", (ftnlen)6);
1248 return 0;
1249 }
1250
1251 /* Find two adjacent epochs bounding the request epoch. The request */
1252 /* time cannot be greater than all of epochs in the group, and it */
1253 /* cannot precede the first element of the group. */
1254
1255 i__1 = endidx - begidx + 1;
1256 i__ = lstltd_(et, &i__1, buffer);
1257
1258 /* The variables LOW and high are the indices of a pair of time */
1259 /* tags that bracket the request time. */
1260
1261 if (i__ == 0) {
1262 low = 1;
1263 } else {
1264 low = begidx + i__ - 1;
1265 }
1266 high = low + 1;
1267
1268 /* Now select the set of packets used for interpolation. Note */
1269 /* that the window size is known to be even. */
1270
1271 /* Unlike SPK types 8, 9, 12, and 13, for type 19 we allow the */
1272 /* window size to shrink when the window must be truncated due to */
1273 /* proximity to an interval boundary. */
1274
1275 /* The nominal bracketing epochs we've found are the (WNDSIZ/2)nd */
1276 /* and (WNDSIZ/2 + 1)st of the interpolating set. If the */
1277 /* request time is too close to one end of the coverage interval, */
1278 /* we reduce the window size, after which one endpoint of the */
1279 /* window will coincide with an endpoint of the coverage interval. */
1280
1281 /* Let LSIZE be the size of the "left half" of the window: the */
1282 /* size set of window epochs to the left of the request time. */
1283 /* We want this size to be WNDSIZ/2, but if not enough states are */
1284 /* available, the set ranges from index 1 to index LOW. */
1285
1286 /* Computing MIN */
1287 i__1 = wndsiz / 2;
1288 lsize = min(i__1,low);
1289
1290 /* RSIZE is defined analogously for the right half of the window. */
1291
1292 /* Computing MIN */
1293 i__1 = wndsiz / 2, i__2 = npkt - high + 1;
1294 rsize = min(i__1,i__2);
1295
1296 /* The actual window size is simply the sum of LSIZE and RSIZE. */
1297
1298 nrcpkt = lsize + rsize;
1299
1300 /* FIRST and LAST are the endpoints of the range of indices of */
1301 /* time tags (and packets) we'll collect in the output record. */
1302
1303 first = low - lsize + 1;
1304 last = first + nrcpkt - 1;
1305
1306 /* We're ready to construct the output record. */
1307
1308 /* Put the subtype and window size into the output record. */
1309
1310 record[0] = (doublereal) subtyp;
1311 record[1] = (doublereal) nrcpkt;
1312
1313 /* Read the packets. */
1314
1315 i__1 = minib + (first - 1) * pktsiz;
1316 i__2 = minib + last * pktsiz - 1;
1317 dafgda_(handle, &i__1, &i__2, &record[2]);
1318
1319 /* Finally, add the epochs to the output record. */
1320 /* Read the sequence of time tags. */
1321
1322 bufbas = minib - 1 + npkt * pktsiz + (first - 1);
1323 i__1 = bufbas + 1;
1324 i__2 = bufbas + nrcpkt;
1325 dafgda_(handle, &i__1, &i__2, &record[nrcpkt * pktsiz + 2]);
1326 if (failed_()) {
1327 chkout_("SPKR19", (ftnlen)6);
1328 return 0;
1329 }
1330
1331 /* The call was successful. Record this fact so that saved */
1332 /* interval data are available for re-use. */
1333
1334 svok = TRUE_;
1335 chkout_("SPKR19", (ftnlen)6);
1336 return 0;
1337 } /* spkr19_ */
1338
1339