PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ckr03.c

https://github.com/mattbornski/spice
C | 995 lines | 264 code | 245 blank | 486 comment | 69 complexity | c0fcb064f05fc2a10859fb16091867f3 MD5 | raw file
  1. /* ckr03.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. #include "f2c.h"
  6. /* Table of constant values */
  7. static integer c__2 = 2;
  8. static integer c__6 = 6;
  9. /* $Procedure CKR03 ( C-kernel, read pointing record, data type 3 ) */
  10. /* Subroutine */ int ckr03_(integer *handle, doublereal *descr, doublereal *
  11. sclkdp, doublereal *tol, logical *needav, doublereal *record, logical
  12. *found)
  13. {
  14. /* Initialized data */
  15. static doublereal prevs = -1.;
  16. static doublereal prevn = -1.;
  17. static integer lhand = 0;
  18. static integer lbeg = -1;
  19. static integer lend = -1;
  20. /* System generated locals */
  21. integer i__1, i__2;
  22. /* Builtin functions */
  23. integer i_dnnt(doublereal *), s_rnge(char *, integer, char *, integer);
  24. /* Local variables */
  25. integer addr__, skip, psiz, i__, n;
  26. doublereal ldiff;
  27. integer laddr;
  28. doublereal rdiff;
  29. integer raddr;
  30. extern /* Subroutine */ int chkin_(char *, ftnlen), dafus_(doublereal *,
  31. integer *, integer *, doublereal *, integer *);
  32. integer nidir;
  33. doublereal lsclk;
  34. extern doublereal dpmax_(void);
  35. extern /* Subroutine */ int moved_(doublereal *, integer *, doublereal *);
  36. integer nrdir;
  37. doublereal rsclk;
  38. integer group;
  39. doublereal start;
  40. extern /* Subroutine */ int dafgda_(integer *, integer *, integer *,
  41. doublereal *);
  42. extern logical failed_(void);
  43. integer grpadd;
  44. doublereal buffer[100];
  45. integer remain, dirloc;
  46. extern integer lstled_(doublereal *, integer *, doublereal *);
  47. integer numrec;
  48. extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *,
  49. ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *,
  50. ftnlen);
  51. extern integer lstltd_(doublereal *, integer *, doublereal *);
  52. integer numint;
  53. doublereal nstart;
  54. extern logical return_(void);
  55. doublereal dcd[2];
  56. integer beg, icd[6], end;
  57. logical fnd;
  58. /* $ Abstract */
  59. /* Read a pointing record from a CK segment, data type 3. */
  60. /* $ Disclaimer */
  61. /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
  62. /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
  63. /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
  64. /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
  65. /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
  66. /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
  67. /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
  68. /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
  69. /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
  70. /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
  71. /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
  72. /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
  73. /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
  74. /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
  75. /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
  76. /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
  77. /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
  78. /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
  79. /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
  80. /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
  81. /* $ Required_Reading */
  82. /* CK */
  83. /* DAF */
  84. /* $ Keywords */
  85. /* POINTING */
  86. /* $ Declarations */
  87. /* $ Brief_I/O */
  88. /* Variable I/O Description */
  89. /* -------- --- -------------------------------------------------- */
  90. /* HANDLE I File handle. */
  91. /* DESCR I Segment descriptor. */
  92. /* SCLKDP I Pointing request time. */
  93. /* TOL I Time tolerance. */
  94. /* NEEDAV I Angular velocity request flag. */
  95. /* RECORD O Pointing data record. */
  96. /* FOUND O True when data is found. */
  97. /* $ Detailed_Input */
  98. /* HANDLE is the integer handle of the CK file containing the */
  99. /* segment. */
  100. /* DESCR is the descriptor of the segment. */
  101. /* SCLKDP is the encoded spacecraft clock time for which */
  102. /* pointing is being requested. */
  103. /* TOL is a time tolerance, measured in the same units as */
  104. /* encoded spacecraft clock. */
  105. /* When SCLKDP falls within the bounds of one of the */
  106. /* interpolation intervals then the tolerance has no */
  107. /* effect because pointing will be returned at the */
  108. /* request time. */
  109. /* However, if the request time is not in one of the */
  110. /* intervals, then the tolerance is used to determine */
  111. /* if pointing at one of the interval endpoints should */
  112. /* be returned. */
  113. /* NEEDAV is true if angular velocity is requested. */
  114. /* $ Detailed_Output */
  115. /* RECORD is the record that CKE03 will evaluate to determine */
  116. /* the pointing. */
  117. /* When the request time falls within an interval for */
  118. /* which linear interpolation is valid, the values of */
  119. /* the two pointing instances that bracket the request */
  120. /* time are returned in RECORD as follows: */
  121. /* RECORD( 1 ) = Left bracketing SCLK time. */
  122. /* RECORD( 2 ) = lq0 \ */
  123. /* RECORD( 3 ) = lq1 \ Left bracketing */
  124. /* RECORD( 4 ) = lq2 / quaternion. */
  125. /* RECORD( 5 ) = lq3 / */
  126. /* RECORD( 6 ) = lav1 \ Left bracketing */
  127. /* RECORD( 7 ) = lav2 angular velocity */
  128. /* RECORD( 8 ) = lav3 / ( optional ) */
  129. /* RECORD( 9 ) = Right bracketing SCLK time. */
  130. /* RECORD( 10 ) = rq0 \ */
  131. /* RECORD( 11 ) = rq1 \ Right bracketing */
  132. /* RECORD( 12 ) = rq2 / quaternion. */
  133. /* RECORD( 13 ) = rq3 / */
  134. /* RECORD( 14 ) = rav1 \ Right bracketing */
  135. /* RECORD( 15 ) = rav2 angular velocity */
  136. /* RECORD( 16 ) = rav3 / ( optional ) */
  137. /* RECORD( 17 ) = pointing request time, SCLKDP. */
  138. /* The quantities lq0 - lq3 and rq0 - rq3 are the */
  139. /* components of the quaternions that represent the */
  140. /* C-matrices associated with the times that bracket */
  141. /* the requested time. */
  142. /* The quantities lav1, lav2, lav3 and rav1, rav2, rav3 */
  143. /* are the components of the angular velocity vectors at */
  144. /* the respective bracketing times. The components of the */
  145. /* angular velocity vectors are specified relative to */
  146. /* the inertial reference frame of the segment. */
  147. /* If the request time does not fall within an */
  148. /* interpolation interval, but is within TOL of an */
  149. /* interval endpoint, the values of that pointing */
  150. /* instance are returned in both parts of RECORD */
  151. /* ( i.e. RECORD(1-9) and RECORD(10-16) ). */
  152. /* FOUND is true if a record was found to satisfy the pointing */
  153. /* request. This occurs when the time for which pointing */
  154. /* is requested falls inside one of the interpolation */
  155. /* intervals, or when the request time is within the */
  156. /* tolerance of an interval endpoint. */
  157. /* $ Parameters */
  158. /* None. */
  159. /* $ Exceptions */
  160. /* 1) If the specified handle does not belong to an open DAF file, */
  161. /* an error is diagnosed by a routine that this routine calls. */
  162. /* 2) If DESCR is not a valid descriptor of a segment in the CK */
  163. /* file specified by HANDLE, the results of this routine are */
  164. /* unpredictable. */
  165. /* 3) If the segment is not of data type 3, as specified in the */
  166. /* third integer component of the segment descriptor, then */
  167. /* the error SPICE(WRONGDATATYPE) is signalled. */
  168. /* 4) If angular velocity data was requested but the segment */
  169. /* contains no such data, the error SPICE(NOAVDATA) is signalled. */
  170. /* $ Files */
  171. /* The file containing the segment is specified by its handle and */
  172. /* should be opened for read or write access, either by CKLPF, */
  173. /* DAFOPR, or DAFOPW. */
  174. /* $ Particulars */
  175. /* See the CK Required Reading file for a detailed description of */
  176. /* the structure of a type 3 pointing segment. */
  177. /* When the time for which pointing was requested falls within an */
  178. /* interpolation interval, then FOUND will be true and RECORD will */
  179. /* contain the pointing instances in the segment that bracket the */
  180. /* request time. CKE03 will evaluate RECORD to give pointing at */
  181. /* the request time. */
  182. /* However, when the request time is not within any of the */
  183. /* interpolation intervals, then FOUND will be true only if the */
  184. /* interval endpoint closest to the request time is within the */
  185. /* tolerance specified by the user. In this case both parts of */
  186. /* RECORD will contain this closest pointing instance, and CKE03 */
  187. /* will evaluate RECORD to give pointing at the time associated */
  188. /* with the returned pointing instance. */
  189. /* $ Examples */
  190. /* The CKRnn routines are usually used in tandem with the CKEnn */
  191. /* routines, which evaluate the record returned by CKRnn to give */
  192. /* the pointing information and output time. */
  193. /* The following code fragment searches through all of the segments */
  194. /* in a file applicable to the Mars Observer spacecraft bus that */
  195. /* are of data type 3, for a particular spacecraft clock time. */
  196. /* It then evaluates the pointing for that epoch and prints the */
  197. /* result. */
  198. /* CHARACTER*(20) SCLKCH */
  199. /* CHARACTER*(20) SCTIME */
  200. /* CHARACTER*(40) IDENT */
  201. /* INTEGER I */
  202. /* INTEGER SC */
  203. /* INTEGER INST */
  204. /* INTEGER HANDLE */
  205. /* INTEGER DTYPE */
  206. /* INTEGER ICD ( 6 ) */
  207. /* DOUBLE PRECISION SCLKDP */
  208. /* DOUBLE PRECISION TOL */
  209. /* DOUBLE PRECISION CLKOUT */
  210. /* DOUBLE PRECISION DESCR ( 5 ) */
  211. /* DOUBLE PRECISION DCD ( 2 ) */
  212. /* DOUBLE PRECISION RECORD ( 17 ) */
  213. /* DOUBLE PRECISION CMAT ( 3, 3 ) */
  214. /* DOUBLE PRECISION AV ( 3 ) */
  215. /* LOGICAL NEEDAV */
  216. /* LOGICAL FND */
  217. /* LOGICAL SFND */
  218. /* SC = -94 */
  219. /* INST = -94000 */
  220. /* DTYPE = 3 */
  221. /* NEEDAV = .FALSE. */
  222. /* C */
  223. /* C Load the MO SCLK kernel and the C-kernel. */
  224. /* C */
  225. /* CALL FURNSH ( 'MO_SCLK.TSC' ) */
  226. /* CALL DAFOPR ( 'MO_CK.BC', HANDLE ) */
  227. /* C */
  228. /* C Get the spacecraft clock time. Then encode it for use */
  229. /* C in the C-kernel. */
  230. /* C */
  231. /* WRITE (*,*) 'Enter spacecraft clock time string:' */
  232. /* READ (*,FMT='(A)') SCLKCH */
  233. /* CALL SCENCD ( SC, SCLKCH, SCLKDP ) */
  234. /* C */
  235. /* C Use a tolerance of 2 seconds ( half of the nominal */
  236. /* C separation between MO pointing instances ). */
  237. /* C */
  238. /* CALL SCTIKS ( SC, '0000000002:000', TOL ) */
  239. /* C */
  240. /* C Search from the beginning of the CK file through all */
  241. /* C of the segments. */
  242. /* C */
  243. /* CALL DAFBFS ( HANDLE ) */
  244. /* CALL DAFFNA ( SFND ) */
  245. /* FND = .FALSE. */
  246. /* DO WHILE ( ( SFND ) .AND. ( .NOT. FND ) ) */
  247. /* C */
  248. /* C Get the segment identifier and descriptor. */
  249. /* C */
  250. /* CALL DAFGN ( IDENT ) */
  251. /* CALL DAFGS ( DESCR ) */
  252. /* C */
  253. /* C Unpack the segment descriptor into its integer and */
  254. /* C double precision components. */
  255. /* C */
  256. /* CALL DAFUS ( DESCR, 2, 6, DCD, ICD ) */
  257. /* C */
  258. /* C Determine if this segment should be processed. */
  259. /* C */
  260. /* IF ( ( INST .EQ. ICD( 1 ) ) .AND. */
  261. /* . ( SCLKDP + TOL .GE. DCD( 1 ) ) .AND. */
  262. /* . ( SCLKDP - TOL .LE. DCD( 2 ) ) .AND. */
  263. /* . ( DTYPE .EQ. ICD( 3 ) ) ) THEN */
  264. /* CALL CKR03 ( HANDLE, DESCR, SCLKDP, TOL, NEEDAV, */
  265. /* . RECORD, FND ) */
  266. /* IF ( FND ) THEN */
  267. /* CALL CKE03 (NEEDAV,RECORD,CMAT,AV,CLKOUT) */
  268. /* CALL SCDECD ( SC, CLKOUT, SCTIME ) */
  269. /* WRITE (*,*) */
  270. /* WRITE (*,*) 'Segment identifier: ', IDENT */
  271. /* WRITE (*,*) */
  272. /* WRITE (*,*) 'Pointing returned for time: ', */
  273. /* . SCTIME */
  274. /* WRITE (*,*) */
  275. /* WRITE (*,*) 'C-matrix:' */
  276. /* WRITE (*,*) */
  277. /* WRITE (*,*) ( CMAT(1,I), I = 1, 3 ) */
  278. /* WRITE (*,*) ( CMAT(2,I), I = 1, 3 ) */
  279. /* WRITE (*,*) ( CMAT(3,I), I = 1, 3 ) */
  280. /* WRITE (*,*) */
  281. /* END IF */
  282. /* END IF */
  283. /* CALL DAFFNA ( SFND ) */
  284. /* END DO */
  285. /* $ Restrictions */
  286. /* 1) The file containing the segment should be opened for read */
  287. /* or write access either by CKLPF, DAFOPR, or DAFOPW. */
  288. /* 2) The record returned by this routine is intended to be */
  289. /* evaluated by CKE03. */
  290. /* $ Literature_References */
  291. /* None. */
  292. /* $ Author_and_Institution */
  293. /* J.M. Lynch (JPL) */
  294. /* $ Version */
  295. /* - SPICELIB Version 1.1.1, 22-AUG-2006 (EDW) */
  296. /* Replaced references to LDPOOL with references */
  297. /* to FURNSH. */
  298. /* - SPICELIB Version 1.1.0, 07-SEP-2001 (EDW) */
  299. /* Replaced DAFRDA call with DAFGDA. */
  300. /* Added IMPLICIT NONE. */
  301. /* - SPICELIB Version 1.0.0, 25-NOV-1992 (JML) */
  302. /* -& */
  303. /* $ Index_Entries */
  304. /* read ck type_3 pointing data record */
  305. /* -& */
  306. /* SPICELIB functions */
  307. /* Local parameters */
  308. /* DIRSIZ is the directory size. */
  309. /* BUFSIZ is the maximum number of double precision numbers */
  310. /* that we will read from the DAF file at one time. */
  311. /* BUFSIZ is normally set equal to DIRSIZ. */
  312. /* ND is the number of double precision components in an */
  313. /* unpacked C-kernel segment descriptor. */
  314. /* NI is the number of integer components in an unpacked */
  315. /* C-kernel segment descriptor. */
  316. /* QSIZ is the number of double precision numbers making up */
  317. /* the quaternion portion of a pointing record. */
  318. /* QAVSIZ is the number of double precision numbers making up */
  319. /* the quaternion and angular velocity portion of a */
  320. /* pointing record. */
  321. /* DTYPE is the data type of the segment that this routine */
  322. /* operates on. */
  323. /* Local variables */
  324. /* Saved variables. */
  325. /* Initial values. */
  326. /* Standard SPICE error handling. */
  327. if (return_()) {
  328. return 0;
  329. } else {
  330. chkin_("CKR03", (ftnlen)5);
  331. }
  332. /* Start off with FOUND equal to false just in case a SPICELIB error */
  333. /* is signalled and the return mode is not set to ABORT. */
  334. *found = FALSE_;
  335. /* We need to look at a few of the descriptor components. */
  336. /* The unpacked descriptor contains the following information */
  337. /* about the segment: */
  338. /* DCD(1) Initial encoded SCLK */
  339. /* DCD(2) Final encoded SCLK */
  340. /* ICD(1) Instrument */
  341. /* ICD(2) Inertial reference frame */
  342. /* ICD(3) Data type */
  343. /* ICD(4) Angular velocity flag */
  344. /* ICD(5) Initial address of segment data */
  345. /* ICD(6) Final address of segment data */
  346. dafus_(descr, &c__2, &c__6, dcd, icd);
  347. /* Check to make sure that the segment is type 3. */
  348. if (icd[2] != 3) {
  349. setmsg_("The segment is not a type 3 segment. Type is #", (ftnlen)47)
  350. ;
  351. errint_("#", &icd[2], (ftnlen)1);
  352. sigerr_("SPICE(WRONGDATATYPE)", (ftnlen)20);
  353. chkout_("CKR03", (ftnlen)5);
  354. return 0;
  355. }
  356. /* Does this segment contain angular velocity? */
  357. if (icd[3] == 1) {
  358. psiz = 7;
  359. } else {
  360. psiz = 4;
  361. if (*needav) {
  362. setmsg_("Segment does not contain angular velocity data.", (
  363. ftnlen)47);
  364. sigerr_("SPICE(NOAVDATA)", (ftnlen)15);
  365. chkout_("CKR03", (ftnlen)5);
  366. return 0;
  367. }
  368. }
  369. /* The beginning and ending addresses of the segment are in the */
  370. /* descriptor. */
  371. beg = icd[4];
  372. end = icd[5];
  373. /* The procedure used in finding a record to satisfy the request */
  374. /* for pointing is as follows: */
  375. /* 1) Find the two pointing instances in the segment that bracket */
  376. /* the request time. */
  377. /* The pointing instance that brackets the request time on the */
  378. /* left is defined to be the one associated with the largest */
  379. /* time in the segment that is less than or equal to SCLKDP. */
  380. /* The pointing instance that brackets the request time on the */
  381. /* right is defined to be the one associated with the first */
  382. /* time in the segment greater than SCLKDP. */
  383. /* Since the times in the segment are strictly increasing the */
  384. /* left and right bracketing pointing instances are always */
  385. /* adjacent. */
  386. /* 2) Determine if the bracketing times are in the same */
  387. /* interpolation interval. */
  388. /* 3) If they are, then pointing at the request time may be */
  389. /* linearly interpolated from the bracketing times. */
  390. /* 4) If the times that bracket the request time are not in the */
  391. /* same interval then, since they are adjacent in the segment */
  392. /* and since intervals begin and end at actual times, they must */
  393. /* both be interval endpoints. Return the pointing instance */
  394. /* associated with the endpoint closest to the request time, */
  395. /* provided that it is within the tolerance. */
  396. /* Get the number of intervals and pointing instances ( records ) */
  397. /* in this segment, and from that determine the number of respective */
  398. /* directory epochs. */
  399. i__1 = end - 1;
  400. dafgda_(handle, &i__1, &end, buffer);
  401. numint = i_dnnt(buffer);
  402. numrec = i_dnnt(&buffer[1]);
  403. nidir = (numint - 1) / 100;
  404. nrdir = (numrec - 1) / 100;
  405. /* Check the FAILED flag just in case HANDLE is not attached to */
  406. /* any DAF file and the error action is not set to ABORT. You need */
  407. /* need to do this only after the first call to DAFGDA. */
  408. if (failed_()) {
  409. chkout_("CKR03", (ftnlen)5);
  410. return 0;
  411. }
  412. /* To find the times that bracket the request time we will first */
  413. /* find the greatest directory time less than the request time. */
  414. /* This will narrow down the search to a group of DIRSIZ or fewer */
  415. /* times where the Jth group is defined to contain SCLK times */
  416. /* ((J-1)*DIRSIZ + 1) through (J*DIRSIZ). */
  417. /* For example if DIRSIZ = 100 then: */
  418. /* group first time # last time # */
  419. /* ----- --------------- ------------ */
  420. /* 1 1 100 */
  421. /* 2 101 200 */
  422. /* . . . */
  423. /* . . . */
  424. /* 10 901 1000 */
  425. /* . . . */
  426. /* . . . */
  427. /* NRDIR+1 (NRDIR)*100+1 NUMREC */
  428. /* Thus if the Ith directory time is the largest one less than */
  429. /* our request time SCLKDP, then we know that: */
  430. /* SCLKS ( DIRSIZ * I ) < SCLKDP <= SCLKS ( DIRSIZ * (I+1) ) */
  431. /* where SCLKS is taken to be the array of NUMREC times associated */
  432. /* with the pointing instances. */
  433. /* Therefore, at least one of the bracketing times will come from */
  434. /* the (I+1)th group. */
  435. /* There is only one group if there are no directory epochs. */
  436. if (nrdir == 0) {
  437. group = 1;
  438. } else {
  439. /* Compute the location of the first directory epoch. From the */
  440. /* beginning of the segment, we need to go through all of the */
  441. /* pointing numbers (PSIZ*NUMREC of them) and then through all of */
  442. /* the NUMREC SCLK times. */
  443. dirloc = beg + (psiz + 1) * numrec;
  444. /* Search through the directory times. Read in as many as BUFSIZ */
  445. /* directory epochs at a time for comparison. */
  446. fnd = FALSE_;
  447. remain = nrdir;
  448. group = 0;
  449. while(! fnd) {
  450. /* The number of records to read into the buffer. */
  451. n = min(remain,100);
  452. i__1 = dirloc + n - 1;
  453. dafgda_(handle, &dirloc, &i__1, buffer);
  454. remain -= n;
  455. /* Determine the last directory element in BUFFER that's less */
  456. /* than SCLKDP. */
  457. i__ = lstltd_(sclkdp, &n, buffer);
  458. if (i__ < n) {
  459. group = group + i__ + 1;
  460. fnd = TRUE_;
  461. } else if (remain == 0) {
  462. /* The request time is greater than the last directory time */
  463. /* so we want the last group in the segment. */
  464. group = nrdir + 1;
  465. fnd = TRUE_;
  466. } else {
  467. /* Need to read another block of directory times. */
  468. dirloc += n;
  469. group += n;
  470. }
  471. }
  472. }
  473. /* Now we know which group of DIRSIZ (or less) times to look at. */
  474. /* Out of the NUMREC SCLK times, the number that we should skip over */
  475. /* to get to the proper group is DIRSIZ * ( GROUP - 1 ). */
  476. skip = (group - 1) * 100;
  477. /* From this we can compute the address in the segment of the group */
  478. /* of times we want. From the beginning, we need to pass through */
  479. /* PSIZ * NUMREC pointing numbers to get to the first SCLK time. */
  480. /* Then we skip over the number just computed above. */
  481. grpadd = beg + numrec * psiz + skip;
  482. /* The number of times that we have to look at may be less than */
  483. /* DIRSIZ. However many there are, go ahead and read them into the */
  484. /* buffer. */
  485. /* Computing MIN */
  486. i__1 = 100, i__2 = numrec - skip;
  487. n = min(i__1,i__2);
  488. i__1 = grpadd + n - 1;
  489. dafgda_(handle, &grpadd, &i__1, buffer);
  490. /* Find the largest time in the group less than or equal to the input */
  491. /* time. */
  492. i__ = lstled_(sclkdp, &n, buffer);
  493. /* Find the pointing instances in the segment that bracket the */
  494. /* request time and calculate the addresses for the pointing data */
  495. /* associated with these times. For cases in which the request time */
  496. /* is equal to one of the times in the segment, that time will be */
  497. /* the left bracketing time of the returned pair. */
  498. /* Need to handle the cases when the request time is greater than */
  499. /* the last or less than the first time in the segment separately. */
  500. if (i__ == 0) {
  501. if (group == 1) {
  502. /* The time occurs before the first time in the segment. Since */
  503. /* this time cannot possibly be in any of the intervals, the */
  504. /* first time can satisfy the request for pointing only if it */
  505. /* is within the tolerance of the request time. */
  506. if (buffer[0] - *sclkdp <= *tol) {
  507. record[0] = buffer[0];
  508. record[8] = buffer[0];
  509. /* Calculate the address of the quaternion and angular */
  510. /* velocity data. Then read it from the file. */
  511. i__1 = beg + psiz - 1;
  512. dafgda_(handle, &beg, &i__1, buffer);
  513. moved_(buffer, &psiz, &record[1]);
  514. moved_(buffer, &psiz, &record[9]);
  515. record[16] = *sclkdp;
  516. *found = TRUE_;
  517. }
  518. chkout_("CKR03", (ftnlen)5);
  519. return 0;
  520. } else {
  521. /* The first time in the current group brackets the request */
  522. /* time on the right and the last time from the preceding */
  523. /* group brackets on the left. */
  524. rsclk = buffer[0];
  525. raddr = beg + skip * psiz;
  526. i__1 = grpadd - 1;
  527. i__2 = grpadd - 1;
  528. dafgda_(handle, &i__1, &i__2, &lsclk);
  529. laddr = raddr - psiz;
  530. }
  531. } else if (i__ == n) {
  532. /* There are two possible cases, but the same action can handle */
  533. /* both. */
  534. /* 1) If this is the last group ( NRDIR + 1 ) then the request */
  535. /* time occurs on or after the last time in the segment. */
  536. /* In either case this last time can satisfy the request for */
  537. /* pointing only if it is within the tolerance of the request */
  538. /* time. */
  539. /* 2) The request time is greater than or equal to the last time */
  540. /* in this group. Since this time is the same as the (I+1)th */
  541. /* directory time, and since the search on the directory times */
  542. /* used a strictly less than test, we know that the request */
  543. /* time must be equal to this time. Just return the pointing */
  544. /* instance associated with the request time. ( Note that */
  545. /* SCLKDP - BUFFER(N) will be zero in this case. ) */
  546. if (*sclkdp - buffer[(i__1 = n - 1) < 100 && 0 <= i__1 ? i__1 :
  547. s_rnge("buffer", i__1, "ckr03_", (ftnlen)826)] <= *tol) {
  548. record[0] = buffer[(i__1 = n - 1) < 100 && 0 <= i__1 ? i__1 :
  549. s_rnge("buffer", i__1, "ckr03_", (ftnlen)828)];
  550. record[8] = buffer[(i__1 = n - 1) < 100 && 0 <= i__1 ? i__1 :
  551. s_rnge("buffer", i__1, "ckr03_", (ftnlen)829)];
  552. /* Calculate the address of the quaternion and angular */
  553. /* velocity data. Then read it from the file. */
  554. addr__ = beg + psiz * (skip + n - 1);
  555. i__1 = addr__ + psiz - 1;
  556. dafgda_(handle, &addr__, &i__1, buffer);
  557. moved_(buffer, &psiz, &record[1]);
  558. moved_(buffer, &psiz, &record[9]);
  559. record[16] = *sclkdp;
  560. *found = TRUE_;
  561. }
  562. chkout_("CKR03", (ftnlen)5);
  563. return 0;
  564. } else {
  565. /* The bracketing times are contained in this group. */
  566. lsclk = buffer[(i__1 = i__ - 1) < 100 && 0 <= i__1 ? i__1 : s_rnge(
  567. "buffer", i__1, "ckr03_", (ftnlen)855)];
  568. rsclk = buffer[(i__1 = i__) < 100 && 0 <= i__1 ? i__1 : s_rnge("buff"
  569. "er", i__1, "ckr03_", (ftnlen)856)];
  570. laddr = beg + (skip + i__ - 1) * psiz;
  571. raddr = laddr + psiz;
  572. }
  573. /* At this point we have the two times in the segment that bracket */
  574. /* the request time. We also have the addresses of the pointing */
  575. /* data associated with those times. The task now is to determine */
  576. /* if the bracketing times fall in the same interval. If so then */
  577. /* we can interpolate between them. If they don't then return */
  578. /* pointing for whichever of the two times is closest to the */
  579. /* request time, provided that it is within the tolerance. */
  580. /* Find the interpolation interval that the request time is in and */
  581. /* determine if the bracketing SCLK's are both in it. */
  582. /* First check if the request time falls in the same interval as */
  583. /* it did last time. We need to make sure that we are dealing */
  584. /* with the same segment as well as the same time range. */
  585. /* PREVS is the start time of the interval that satisfied */
  586. /* the previous request for pointing. */
  587. /* PREVN is the start time of the interval that followed */
  588. /* the interval specified above. */
  589. /* LHAND is the handle of the file that PREVS and PREVN */
  590. /* were found in. */
  591. /* LBEG, are the beginning and ending addresses of the */
  592. /* LEND segment in the file LHAND that PREVS and PREVN */
  593. /* were found in. */
  594. if (*handle == lhand && beg == lbeg && end == lend && *sclkdp >= prevs &&
  595. *sclkdp < prevn) {
  596. start = prevs;
  597. nstart = prevn;
  598. } else {
  599. /* The START times of all of the intervals are stored in the */
  600. /* segment and a directory of every hundredth START is also */
  601. /* stored. The procedure to find the bracketing interval start */
  602. /* times is identical to the one used above for finding the */
  603. /* bracketing times. */
  604. /* The directory epochs narrow down the search for the times that */
  605. /* bracket the request time to a group of DIRSIZ or fewer records. */
  606. /* There is only one group if there are no directory epochs. */
  607. if (nidir == 0) {
  608. group = 1;
  609. } else {
  610. /* Compute the location of the first directory epoch. From the */
  611. /* beginning of the segment, we need to go through all of the */
  612. /* pointing numbers (PSIZ*NUMREC of them), then through all of */
  613. /* the NUMREC SCLK times and NRDIR directory times, and then */
  614. /* finally through the NUMINT interval start times. */
  615. dirloc = beg + (psiz + 1) * numrec + nrdir + numint;
  616. /* Locate the largest directory time less than the */
  617. /* request time SCLKDP. */
  618. /* Read in as many as BUFSIZ directory epochs at a time for */
  619. /* comparison. */
  620. fnd = FALSE_;
  621. remain = nidir;
  622. group = 0;
  623. while(! fnd) {
  624. /* The number of records to read into the buffer. */
  625. n = min(remain,100);
  626. i__1 = dirloc + n - 1;
  627. dafgda_(handle, &dirloc, &i__1, buffer);
  628. remain -= n;
  629. /* Determine the last directory element in BUFFER that's */
  630. /* less than SCLKDP. */
  631. i__ = lstltd_(sclkdp, &n, buffer);
  632. if (i__ < n) {
  633. group = group + i__ + 1;
  634. fnd = TRUE_;
  635. } else if (remain == 0) {
  636. /* The request time is greater than the last directory */
  637. /* time so we want the last group in the segment. */
  638. group = nidir + 1;
  639. fnd = TRUE_;
  640. } else {
  641. /* Need to read another block of directory times. */
  642. dirloc += n;
  643. group += n;
  644. }
  645. }
  646. }
  647. /* Now we know which group of DIRSIZ (or less) times to look at. */
  648. /* Out of the NUMINT SCLK START times, the number that we should */
  649. /* skip over to get to the proper group is DIRSIZ * ( GROUP - 1 ). */
  650. skip = (group - 1) * 100;
  651. /* From this we can compute the address in the segment of the */
  652. /* group of times we want. To get to the first interval start */
  653. /* time we must pass over PSIZ * NUMREC pointing numbers, NUMREC */
  654. /* SCLK times, and NRDIR SCLK directory times. Then we skip */
  655. /* over the number just computed above. */
  656. grpadd = beg + (psiz + 1) * numrec + nrdir + skip;
  657. /* The number of times that we have to look at may be less than */
  658. /* DIRSIZ. However many there are, go ahead and read them into */
  659. /* the buffer. */
  660. /* Computing MIN */
  661. i__1 = 100, i__2 = numint - skip;
  662. n = min(i__1,i__2);
  663. i__1 = grpadd + n - 1;
  664. dafgda_(handle, &grpadd, &i__1, buffer);
  665. /* Find the index of the largest time in the group that is less */
  666. /* than or equal to the input time. */
  667. i__ = lstled_(sclkdp, &n, buffer);
  668. if (i__ == 0) {
  669. /* The first start time in the buffer is the start of the */
  670. /* interval following the one containing the request time. */
  671. /* We don't need to check if GROUP = 1 because the case of */
  672. /* the request time occurring before the first time in the */
  673. /* segment has already been handled. */
  674. nstart = buffer[0];
  675. addr__ = grpadd - 1;
  676. dafgda_(handle, &addr__, &addr__, &start);
  677. } else if (i__ == n) {
  678. if (group == nidir + 1) {
  679. /* This is the last interval in the segment. */
  680. start = buffer[(i__1 = n - 1) < 100 && 0 <= i__1 ? i__1 :
  681. s_rnge("buffer", i__1, "ckr03_", (ftnlen)1040)];
  682. nstart = dpmax_();
  683. } else {
  684. /* The last START time in this group is equal to the */
  685. /* request time. */
  686. start = buffer[(i__1 = n - 1) < 100 && 0 <= i__1 ? i__1 :
  687. s_rnge("buffer", i__1, "ckr03_", (ftnlen)1049)];
  688. addr__ = grpadd + n;
  689. dafgda_(handle, &addr__, &addr__, &nstart);
  690. }
  691. } else {
  692. /* The bracketing START times are contained in this group. */
  693. start = buffer[(i__1 = i__ - 1) < 100 && 0 <= i__1 ? i__1 :
  694. s_rnge("buffer", i__1, "ckr03_", (ftnlen)1061)];
  695. nstart = buffer[(i__1 = i__) < 100 && 0 <= i__1 ? i__1 : s_rnge(
  696. "buffer", i__1, "ckr03_", (ftnlen)1062)];
  697. }
  698. /* Save the information about the interval and segment. */
  699. lhand = *handle;
  700. lbeg = beg;
  701. lend = end;
  702. prevs = start;
  703. prevn = nstart;
  704. }
  705. /* Check and see if the bracketing pointing instances belong */
  706. /* to the same interval. If they do then we can interpolate */
  707. /* between them, if not then check to see if the closer of */
  708. /* the two to the request time lies within the tolerance. */
  709. /* The left bracketing time will always belong to the same */
  710. /* interval as the request time, therefore we need to check */
  711. /* only that the right bracketing time is less than the start */
  712. /* time of the next interval. */
  713. if (rsclk < nstart) {
  714. record[0] = lsclk;
  715. i__1 = laddr + psiz - 1;
  716. dafgda_(handle, &laddr, &i__1, &record[1]);
  717. record[8] = rsclk;
  718. i__1 = raddr + psiz - 1;
  719. dafgda_(handle, &raddr, &i__1, &record[9]);
  720. record[16] = *sclkdp;
  721. *found = TRUE_;
  722. } else {
  723. ldiff = *sclkdp - lsclk;
  724. rdiff = rsclk - *sclkdp;
  725. if (ldiff <= *tol || rdiff <= *tol) {
  726. /* Return the pointing instance closest to the request time. */
  727. /* If the request time is midway between LSCLK and RSCLK then */
  728. /* grab the pointing instance associated with the greater time. */
  729. if (ldiff < rdiff) {
  730. record[0] = lsclk;
  731. record[8] = lsclk;
  732. i__1 = laddr + psiz - 1;
  733. dafgda_(handle, &laddr, &i__1, buffer);
  734. moved_(buffer, &psiz, &record[1]);
  735. moved_(buffer, &psiz, &record[9]);
  736. } else {
  737. record[0] = rsclk;
  738. record[8] = rsclk;
  739. i__1 = raddr + psiz - 1;
  740. dafgda_(handle, &raddr, &i__1, buffer);
  741. moved_(buffer, &psiz, &record[1]);
  742. moved_(buffer, &psiz, &record[9]);
  743. }
  744. record[16] = *sclkdp;
  745. *found = TRUE_;
  746. }
  747. }
  748. chkout_("CKR03", (ftnlen)5);
  749. return 0;
  750. } /* ckr03_ */