1 /*
2 -Procedure gfudb_c ( GF, user defined boolean )
3 
4 -Abstract
5 
6    Perform a GF search on a user defined boolean quantity.
7 
8 -Disclaimer
9 
10    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
11    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
12    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
13    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
14    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
15    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
16    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
17    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
18    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
19    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
20 
21    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
22    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
23    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
24    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
25    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
26    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
27 
28    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
29    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
30    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
31    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
32 
33 -Required_Reading
34 
35    GF
36    WINDOWS
37 
38 -Keywords
39 
40    EVENT
41    GEOMETRY
42    SEARCH
43    WINDOW
44 */
45 
46 
47    #include <signal.h>
48    #include "SpiceUsr.h"
49    #include "SpiceZmc.h"
50    #include "SpiceZfc.h"
51    #include "SpiceZad.h"
52    #undef   gfudb_c
53 
gfudb_c(void (* udfuns)(SpiceDouble et,SpiceDouble * value),void (* udfunb)(void (* udfuns)(SpiceDouble et,SpiceDouble * value),SpiceDouble et,SpiceBoolean * xbool),SpiceDouble step,SpiceCell * cnfine,SpiceCell * result)54    void gfudb_c (  void             ( * udfuns ) ( SpiceDouble       et,
55                                                    SpiceDouble     * value ),
56 
57                    void             ( * udfunb ) ( void ( * udfuns )
58                                                         ( SpiceDouble   et,
59                                                           SpiceDouble * value ),
60 
61                                                    SpiceDouble       et,
62                                                    SpiceBoolean    * xbool ),
63 
64                    SpiceDouble          step,
65                    SpiceCell          * cnfine,
66                    SpiceCell          * result )
67 
68 /*
69 -Brief_I/O
70 
71    VARIABLE  I/O  DESCRIPTION
72    --------  ---  --------------------------------------------------
73    udfuns     I   Name of the routine that computes a scalar quantity of
74                   interest corresponding to an `et'.
75    udfunb     I   Name of the routine returning the boolean value
76                   corresponding to an `et'.
77    step       I   Step size used for locating extrema and roots.
78    cnfine    I-O  SPICE window to which the search is restricted.
79    result     O   SPICE window containing results.
80 
81 -Detailed_Input
82 
83    udfuns     the name of the external routine that returns the
84               value of the scalar quantity of interest at time `et'.
85               The calling sequence for "udfuns" is:
86 
87                  udfuns ( et, &value )
88 
89               where:
90 
91                  et      a double precision value representing
92                          ephemeris time, expressed as seconds past
93                          J2000 TDB at which to evaluate "udfuns."
94 
95                  value   is the value of the geometric quantity
96                          at `et'.
97 
98    udfunb     the user defined routine returning a boolean value
99               for an epoch ET. The calling sequence for "udfunb" is:
100 
101                  udfunb ( udfuns, et, xbool )
102 
103               where:
104 
105                  udfuns   the name of the scalar function as defined above.
106 
107                  et       a double precision value representing
108                           ephemeris time, expressed as seconds past
109                           J2000 TDB, at which to evaluate "udfunb."
110 
111                  xbool     the boolean value at `et'.
112 
113               gfudb_c will correctly operate only for boolean
114               functions with true conditions defining non zero
115               measure time intervals.
116 
117               Note, "udfunb" need not call "udfuns." The use of "udfuns"
118               is determined by the needs of the calculation and
119               the user's design.
120 
121    step       the double precision time step size to use in
122               the search.
123 
124               `step' must be shorter than any interval, within the
125               confinement window, over which the user defined boolean
126               function is met. In other words, `step' must be shorter
127               than the shortest time interval for which the boolean
128               function is true; `step' must also be shorter than the
129               shortest time interval between two boolean function true events
130               occurring within the confinement window (see below).
131               However, `step' must not be *too* short, or the search
132               will take an unreasonable amount of time.
133 
134               The choice of `step' affects the completeness but not
135               the precision of solutions found by this routine; the
136               precision is controlled by the convergence tolerance.
137               See the discussion of the parameter SPICE_GF_CNVTOL for
138               details.
139 
140               `step' has units of TDB seconds.
141 
142    cnfine     a double precision SPICE window that confines the time
143               period over which the specified search is conducted.
144               cnfine may consist of a single interval or a collection
145               of intervals.
146 
147               In some cases the confinement window can be used to
148               greatly reduce the time period that must be searched
149               for the desired solution. See the Particulars section
150               below for further discussion.
151 
152               See the Examples section below for a code example
153               that shows how to create a confinement window.
154 
155 -Detailed_Output
156 
157    cnfine     is the input confinement window, updated if necessary
158               so the control area of its data array indicates the
159               window's size and cardinality. The window data are
160               unchanged.
161 
162    result     is a SPICE window representing the set of time
163               intervals, within the confinement period, when the
164               specified geometric event occurs.
165 
166               If `result' is non-empty on input, its contents
167               will be discarded before gfuds_c conducts its
168               search.
169 
170 -Parameters
171 
172    SPICE_GF_CNVTOL
173 
174                is the convergence tolerance used for finding endpoints
175                of the intervals comprising the result window.
176                SPICE_GF_CNVTOL is used to determine when binary
177                searches for roots should terminate: when a root is
178                bracketed within an interval of length SPICE_GF_CNVTOL,
179                the root is considered to have been found.
180 
181                The accuracy, as opposed to precision, of roots found by
182                this routine depends on the accuracy of the input data.
183                In most cases, the accuracy of solutions will be
184                inferior to their precision.
185 
186                SPICE_GF_CNVTOL is declared in the header file
187                SpiceGF.h.
188 
189 -Exceptions
190 
191    1)  In order for this routine to produce correct results,
192        the step size must be appropriate for the problem at hand.
193        Step sizes that are too large may cause this routine to miss
194        roots; step sizes that are too small may cause this routine
195        to run unacceptably slowly and in some cases, find spurious
196        roots.
197 
198        This routine does not diagnose invalid step sizes, except
199        that if the step size is non-positive, an error is signaled
200        by a routine in the call tree of this routine.
201 
202    2)  Due to numerical errors, in particular,
203 
204           - Truncation error in time values
205           - Finite tolerance value
206           - Errors in computed geometric quantities
207 
208        it is *normal* for the condition of interest to not always be
209        satisfied near the endpoints of the intervals comprising the
210        result window.
211 
212        The result window may need to be contracted slightly by the
213        caller to achieve desired results. The SPICE window routine
214        wncond_c can be used to contract the result window.
215 
216    3)  If an error (typically cell overflow) occurs while performing
217        window arithmetic, the error will be diagnosed by a routine
218        in the call tree of this routine.
219 
220    4)  If required ephemerides or other kernel data are not
221        available, an error is signaled by a routine in the call tree
222        of this routine.
223 
224    5) If the output SPICE window `result' has insufficient capacity to
225       contain the number of intervals on which the specified geometric
226       condition is met, the error will be diagnosed by a routine in
227       the call tree of this routine. If the result window has size
228       less than 2, the error SPICE(INVALIDDIMENSION) will signal.
229 
230    6) If either input cell has type other than SpiceDouble,
231       the error SPICE(TYPEMISMATCH) will signaled from a routine
232       in the call tree of this routine.
233 
234 -Files
235 
236    Appropriate kernels must be loaded by the calling program before
237    this routine is called.
238 
239    If the user defined function requires access to ephemeris data:
240 
241       - SPK data: ephemeris data for any body over the
242         time period defined by the confinement window must be
243         loaded. If aberration corrections are used, the states of
244         target and observer relative to the solar system barycenter
245         must be calculable from the available ephemeris data.
246         Typically ephemeris data are made available by loading one
247         or more SPK files via furnsh_c.
248 
249       - If non-inertial reference frames are used, then PCK
250         files, frame kernels, C-kernels, and SCLK kernels may be
251         needed.
252 
253    In all cases, kernel data are normally loaded once per program
254    run, NOT every time this routine is called.
255 
256 -Particulars
257 
258    This routine determines a set of one or more time intervals
259    within the confinement window when the boolean function
260    evaluates to true. The resulting set of intervals is returned
261    as a SPICE window.
262 
263    Below we discuss in greater detail aspects of this routine's
264    solution process that are relevant to correct and efficient
265    use of this routine in user applications.
266 
267 
268    udfuns Default Template
269    =======================
270 
271    The boolean function includes an argument for an input scalar
272    function. Use of a scalar function during the evaluation of
273    the boolean function is not required. SPICE provides a no-op
274    scalar routine, udf_c, as a dummy argument for instances when
275    the boolean function does not need to call the scalar function.
276 
277 
278    The Search Process
279    ==================
280 
281    The search for boolean events is treated as a search for state
282    transitions: times are sought when the boolean function value
283    changes from true to false or vice versa.
284 
285 
286    Step Size
287    =========
288 
289    Each interval of the confinement window is searched as follows:
290    first, the input step size is used to determine the time
291    separation at which the boolean function will be sampled.
292    Starting at the left endpoint of the interval, samples of the
293    boolean function will be taken at each step. If a state change
294    is detected, a root has been bracketed; at that point, the
295    "root"--the time at which the state change occurs---is found by a
296    refinement process, for example, via binary search.
297 
298    Note that the optimal choice of step size depends on the lengths
299    of the intervals over which the boolean function is constant:
300    the step size should be shorter than the shortest such interval
301    and the shortest separation between the intervals, within
302    the confinement window.
303 
304    Having some knowledge of the relative geometry of the targets and
305    observer can be a valuable aid in picking a reasonable step size.
306    In general, the user can compensate for lack of such knowledge by
307    picking a very short step size; the cost is increased computation
308    time.
309 
310    Note that the step size is not related to the precision with which
311    the endpoints of the intervals of the result window are computed.
312    That precision level is controlled by the convergence tolerance.
313 
314 
315    Convergence Tolerance
316    =====================
317 
318    Once a root has been bracketed, a refinement process is used to
319    narrow down the time interval within which the root must lie.
320    This refinement process terminates when the location of the root
321    has been determined to within an error margin called the
322    "convergence tolerance." The convergence tolerance used by this
323    routine is set via the parameter SPICE_GF_CNVTOL.
324 
325    The value of SPICE_GF_CNVTOL is set to a "tight" value so that the
326    tolerance doesn't limit the accuracy of solutions found by this
327    routine. In general the accuracy of input data will be the limiting
328    factor.
329 
330    The user may change the convergence tolerance from the default
331    SPICE_GF_CNVTOL value by calling the routine gfstol_c, e.g.
332 
333       gfstol_c( tolerance value )
334 
335    Call gfstol_c prior to calling this routine. All subsequent
336    searches will use the updated reference value.
337 
338    Setting the tolerance tighter than SPICE_GF_CNVTOL is unlikely to be
339    useful, since the results are unlikely to be more accurate.
340    Making the tolerance looser will speed up searches somewhat,
341    since a few convergence steps will be omitted. However, in most
342    cases, the step size is likely to have a much greater effect
343    on processing time than would the convergence tolerance.
344 
345 
346    The Confinement Window
347    ======================
348 
349    The simplest use of the confinement window is to specify a time
350    interval within which a solution is sought.
351 
352    The confinement window also can be used to restrict a search to
353    a time window over which required data are known to be
354    available.
355 
356    In some cases, the confinement window can be used to make searches
357    more efficient. Sometimes it's possible to do an efficient search
358    to reduce the size of the time period over which a relatively
359    slow search of interest must be performed. See the "CASCADE"
360    example program in gf.req for a demonstration.
361 
362 -Examples
363 
364    The numerical results shown for these examples may differ across
365    platforms. The results depend on the SPICE kernels used as
366    input, the compiler and supporting libraries, and the machine
367    specific arithmetic implementation.
368 
369    Use the meta-kernel shown below to load the required SPICE
370    kernels.
371 
372          KPL/MK
373 
374          File name: standard.tm
375 
376          This meta-kernel is intended to support operation of SPICE
377          example programs. The kernels shown here should not be
378          assumed to contain adequate or correct versions of data
379          required by SPICE-based user applications.
380 
381          In order for an application to use this meta-kernel, the
382          kernels referenced here must be present in the user's
383          current working directory.
384 
385 
386          \begindata
387 
388             KERNELS_TO_LOAD = ( 'de418.bsp',
389                                 'pck00008.tpc',
390                                 'naif0009.tls'  )
391 
392          \begintext
393 
394    Example(1):
395 
396    Calculate the time intervals when the position of the moon relative
397    to the earth in the IAU_EARTH frame has a positive value in for
398    the Z position component, with also a positive value for the Vz
399    velocity component.
400 
401       #include <stdio.h>
402       #include <stdlib.h>
403       #include <string.h>
404 
405       #include "SpiceUsr.h"
406       #include "SpiceZfc.h"
407       #include "SpiceZad.h"
408 
409 
410       #define       MAXWIN    20000
411       #define       TIMFMT    "YYYY-MON-DD HR:MN:SC.###"
412       #define       TIMLEN    41
413       #define       NLOOPS    7
414 
415       void gfq ( void ( * udfunc ) ( SpiceDouble    et,
416                                      SpiceDouble  * value ),
417                  SpiceDouble et,
418                  SpiceBoolean * xbool );
419 
420       int main( int argc, char **argv )
421          {
422 
423          /.
424          Create the needed windows. Note, one interval
425          consists of two values, so the total number
426          of cell values to allocate is twice
427          the number of intervals.
428          ./
429          SPICEDOUBLE_CELL ( result, 2*MAXWIN );
430          SPICEDOUBLE_CELL ( cnfine, 2        );
431 
432          SpiceDouble       begtim;
433          SpiceDouble       endtim;
434          SpiceDouble       left;
435          SpiceDouble       right;
436          SpiceDouble       step;
437          SpiceDouble       ltime;
438          SpiceDouble       state  [6];
439 
440          SpiceChar         begstr [ TIMLEN ];
441          SpiceChar         endstr [ TIMLEN ];
442 
443          SpiceInt          count;
444          SpiceInt          i;
445 
446          printf( "Compile date %s, %s\n\n", __DATE__, __TIME__ );
447 
448          /.
449          Load kernels.
450          ./
451          furnsh_c( "standard.tm" );
452 
453          /.
454          Store the time bounds of our search interval in the 'cnfine'
455          confinement window.
456          ./
457          str2et_c ( "Jan 1 2011", &begtim );
458          str2et_c ( "Jan 1 2012", &endtim );
459 
460          wninsd_c ( begtim, endtim, &cnfine );
461 
462 
463          /.
464          The moon orbit about the earth-moon barycenter is
465          twenty-eight days. The event condition occurs
466          during (very) approximately a quarter of the orbit. Use
467          a step of five days.
468          ./
469 
470          step = 5.0 * spd_c();
471 
472          gfudb_c ( udf_c,
473                    gfq,
474                    step,
475                    &cnfine,
476                    &result );
477 
478          count = wncard_c( &result );
479 
480          /.
481          Display the results.
482          ./
483          if (count == 0 )
484             {
485             printf ( "Result window is empty.\n\n" );
486             }
487          else
488             {
489             for ( i = 0;  i < count;  i++ )
490                {
491 
492                /.
493                Fetch the endpoints of the Ith interval
494                of the result window.
495                ./
496                wnfetd_c ( &result, i, &left, &right );
497 
498                printf ( "Interval %d\n", (int)i );
499 
500                timout_c ( left, TIMFMT, TIMLEN, begstr );
501                printf   ( "   Interval start: %s \n", begstr );
502                spkez_c  ( 301, left, "IAU_EARTH", "NONE", 399, state, &ltime);
503                printf   ( "                Z= %.12g \n", state[2] );
504                printf   ( "               Vz= %.12g \n", state[5] );
505 
506                timout_c ( right, TIMFMT, TIMLEN, endstr );
507                printf   ( "   Interval end  : %s \n", endstr );
508                spkez_c  ( 301, right, "IAU_EARTH", "NONE", 399, state, &ltime);
509                printf   ( "                Z= %.12g \n",   state[2] );
510                printf   ( "               Vz= %.12g \n\n", state[5] );
511                }
512 
513             }
514 
515          kclear_c();
516          return( 0 );
517          }
518 
519 
520 
521       /.
522       The user defined functions required by gfudb_c.
523 
524          udf_c   for udfuns
525          gfq     for udfunb
526       ./
527 
528 
529 
530       /.
531       -Procedure Procedure gfq
532       ./
533 
534       void gfq ( void ( * udfuns ) ( SpiceDouble    et,
535                                      SpiceDouble  * value ),
536                  SpiceDouble et,
537                  SpiceBoolean * xbool )
538 
539       /.
540       -Abstract
541 
542         User defined geometric boolean function:
543 
544            Z >= 0 with dZ/dt > 0.
545 
546       ./
547          {
548 
549          /.
550          Initialization. Retrieve the vector from the earth to
551          the moon in the IAU_EARTH frame, without aberration
552          correction.
553          ./
554          SpiceInt             targ   = 301;
555          SpiceInt             obs    = 399;
556 
557          SpiceChar          * ref    = "IAU_EARTH";
558          SpiceChar          * abcorr = "NONE";
559 
560          SpiceDouble          state [6];
561          SpiceDouble          lt;
562 
563          /.
564          Evaluate the state of TARG from OBS at ET with
565          correction ABCORR.
566          ./
567          spkez_c ( targ, et, ref, abcorr, obs, state, &lt );
568 
569          /.
570          Calculate the boolean value.
571          ./
572 
573          *xbool = (state[2] >= 0.0) && (state[5] > 0.0);
574 
575          return;
576          }
577 
578    The program outputs:
579 
580       Interval 0
581          Interval start: 2011-JAN-09 15:24:23.415
582                       Z= -3.67969050785e-08
583                      Vz= 0.396984084929
584          Interval end  : 2011-JAN-16 16:08:28.563
585                       Z= 156247.488202
586                      Vz= 3.76859567858e-13
587 
588       Interval 1
589          Interval start: 2011-FEB-05 23:17:57.359
590                       Z= -3.98442807636e-08
591                      Vz= 0.396781283223
592          Interval end  : 2011-FEB-13 01:38:28.425
593                       Z= 157016.055162
594                      Vz= 3.2238816651e-13
595 
596       Interval 2
597          Interval start: 2011-MAR-05 06:08:17.667
598                       Z= -1.16190221888e-08
599                      Vz= 0.393990253999
600          Interval end  : 2011-MAR-12 10:27:45.188
601                       Z= 157503.773934
602                      Vz= -3.41879302646e-13
603 
604                         ...
605 
606       Interval 11
607          Interval start: 2011-NOV-05 18:43:39.742
608                       Z= -1.80199890565e-08
609                      Vz= 0.373937629543
610          Interval end  : 2011-NOV-13 03:50:17.153
611                       Z= 153172.086618
612                      Vz= -3.62962481251e-13
613 
614       Interval 12
615          Interval start: 2011-DEC-03 01:16:40.817
616                       Z= 1.30391470066e-07
617                      Vz= 0.374257845032
618          Interval end  : 2011-DEC-10 09:51:07.718
619                       Z= 152511.720377
620                      Vz= 2.11386680729e-13
621 
622       Interval 13
623          Interval start: 2011-DEC-30 09:48:57.409
624                       Z= 9.79434844339e-09
625                      Vz= 0.377333201453
626          Interval end  : 2012-JAN-01 00:00:00.000
627                       Z= 50793.0833127
628                      Vz= 0.354549969268
629 
630 
631    Example(2):
632 
633    Calculate the time intervals when the Z component of the earth
634    to moon position vector in the IAU_EARTH frame has value
635    between -1000 km and 1000 km (e.g. above and below the equatorial
636    plane).
637 
638 
639       Code:
640 
641       #include <stdio.h>
642       #include <stdlib.h>
643       #include <string.h>
644 
645       #include "SpiceUsr.h"
646 
647 
648       #define       MAXWIN    20000
649       #define       TIMFMT    "YYYY-MON-DD HR:MN:SC.###"
650       #define       TIMLEN    41
651       #define       NLOOPS    7
652 
653 
654       void gfq ( SpiceDouble    et,
655                  SpiceDouble  * value );
656 
657       void gfb ( void ( * udfuns ) ( SpiceDouble    et,
658                                      SpiceDouble  * value ),
659                  SpiceDouble    et,
660                  SpiceBoolean * xbool );
661 
662       int main( int argc, char **argv )
663          {
664 
665          /.
666          Create the needed windows. Note, one interval
667          consists of two values, so the total number
668          of cell values to allocate is twice
669          the number of intervals.
670          ./
671          SPICEDOUBLE_CELL ( result, 2*MAXWIN );
672          SPICEDOUBLE_CELL ( cnfine, 2        );
673 
674          SpiceDouble       begtim;
675          SpiceDouble       endtim;
676          SpiceDouble       left;
677          SpiceDouble       right;
678          SpiceDouble       step;
679          SpiceDouble       ltime;
680          SpiceDouble       state  [6];
681 
682          SpiceChar         begstr [ TIMLEN ];
683          SpiceChar         endstr [ TIMLEN ];
684 
685          SpiceInt          count;
686          SpiceInt          i;
687 
688          printf( "Compile date %s, %s\n\n", __DATE__, __TIME__ );
689 
690          /.
691          Load kernels.
692          ./
693          furnsh_c( "standard.tm" );
694 
695          /.
696          Store the time bounds of our search interval in the 'cnfine'
697          confinement window.
698          ./
699          str2et_c ( "Jan 1 2011", &begtim );
700          str2et_c ( "Jan 1 2012", &endtim );
701 
702          wninsd_c ( begtim, endtim, &cnfine );
703 
704 
705          /.
706          The duration of the event is approximately ninety minutes.
707          Use a step of one hour.
708          ./
709 
710          step = 60.*60.;
711 
712          gfudb_c ( gfq,
713                    gfb,
714                    step,
715                    &cnfine,
716                    &result );
717 
718          count = wncard_c( &result );
719 
720          /.
721          Display the results.
722          ./
723          if (count == 0 )
724             {
725             printf ( "Result window is empty.\n\n" );
726             }
727          else
728             {
729             for ( i = 0;  i < count;  i++ )
730                {
731 
732                /.
733                Fetch the endpoints of the Ith interval
734                of the result window.
735                ./
736                wnfetd_c ( &result, i, &left, &right );
737 
738                printf ( "Interval %d\n", (int)i );
739 
740                timout_c ( left, TIMFMT, TIMLEN, begstr );
741                printf   ( "   Interval start: %s \n", begstr );
742                spkez_c  ( 301, left, "IAU_EARTH", "NONE", 399, state, &ltime);
743                printf   ( "                Z= %.12g \n", state[2] );
744 
745                timout_c ( right, TIMFMT, TIMLEN, endstr );
746                printf   ( "   Interval end  : %s \n", endstr );
747                spkez_c  ( 301, right, "IAU_EARTH", "NONE", 399, state, &ltime);
748                printf   ( "                Z= %.12g \n",   state[2] );
749                }
750 
751             }
752 
753          kclear_c();
754          return( 0 );
755          }
756 
757 
758 
759       /.
760       The user defined functions required by gfudb_c.
761 
762          gfq     for udfuns
763          gfb     for udfunb
764       ./
765 
766 
767 
768       /.
769       -Procedure Procedure gfq
770       ./
771 
772       void gfq ( SpiceDouble    et,
773                  SpiceDouble  * value )
774 
775       /.
776       -Abstract
777 
778         User defined scalar function:
779 
780       ./
781          {
782 
783          /.
784          Initialization. Retrieve the vector from the earth to
785          the moon in the IAU_EARTH frame, without aberration
786          correction.
787          ./
788          SpiceInt             targ   = 301;
789          SpiceInt             obs    = 399;
790 
791          SpiceChar          * ref    = "IAU_EARTH";
792          SpiceChar          * abcorr = "NONE";
793 
794          SpiceDouble          pos [3];
795          SpiceDouble          lt;
796 
797          /.
798          Evaluate the state of TARG from OBS at ET with
799          correction ABCORR.
800          ./
801          spkezp_c ( targ, et, ref, abcorr, obs, pos, &lt );
802 
803          *value = pos[2];
804 
805          return;
806          }
807 
808 
809       /.
810       -Procedure Procedure gfb
811       ./
812 
813       void gfb ( void ( * udfuns ) ( SpiceDouble    et,
814                                      SpiceDouble  * value ),
815                  SpiceDouble    et,
816                  SpiceBoolean * xbool )
817 
818       /.
819       -Abstract
820 
821         User defined boolean function:
822 
823 
824       ./
825          {
826          SpiceDouble          value;
827          SpiceDouble          lim1   = -1000.;
828          SpiceDouble          lim2   = 1000.;
829 
830          udfuns( et, &value );
831 
832          /.
833          Calculate the boolean value.
834          ./
835 
836          *xbool = (value >= lim1) && (value <= lim2);
837 
838          return;
839          }
840 
841    The program outputs:
842 
843       Interval 0
844          Interval start: 2011-JAN-09 14:42:24.484
845                       Z= -999.999999903
846          Interval end  : 2011-JAN-09 16:06:22.502
847                       Z= 1000.00000009
848       Interval 1
849          Interval start: 2011-JAN-23 04:07:44.455
850                       Z= 1000.00000012
851          Interval end  : 2011-JAN-23 05:23:06.243
852                       Z= -1000.00000011
853       Interval 2
854          Interval start: 2011-FEB-05 22:35:57.156
855                       Z= -999.999999975
856          Interval end  : 2011-FEB-05 23:59:57.748
857                       Z= 999.999999891
858 
859                         ...
860 
861       Interval 24
862          Interval start: 2011-DEC-03 00:32:08.820
863                       Z= -999.99999988
864          Interval end  : 2011-DEC-03 02:01:12.769
865                       Z= 999.999999876
866       Interval 25
867          Interval start: 2011-DEC-17 10:17:24.039
868                       Z= 1000.00000008
869          Interval end  : 2011-DEC-17 11:40:37.223
870                       Z= -999.999999975
871       Interval 26
872          Interval start: 2011-DEC-30 09:04:47.275
873                       Z= -1000.00000005
874          Interval end  : 2011-DEC-30 10:33:07.670
875                       Z= 999.999999868
876 
877    Recall the default convergence tolerance for the GF system has
878    value 10^-6 seconds.
879 
880 -Restrictions
881 
882    1) Any kernel files required by this routine must be loaded
883       before this routine is called.
884 
885 -Literature_References
886 
887    None.
888 
889 -Author_and_Institution
890 
891    N.J. Bachman   (JPL)
892    E.D. Wright    (JPL)
893 
894 -Version
895 
896    -CSPICE Version 1.0.1, 28-JUN-2016 (EDW)
897 
898       Edit to Example code, SpiceInts output as ints using
899       explicit casting.
900 
901    -CSPICE Version 1.0.0, 23-OCT-2013 (EDW) (NJB)
902 
903 -Index_Entries
904 
905    GF user defined boolean function search
906 
907 -&
908 */
909    { /* Begin gfudb_c */
910 
911    /*
912    Participate in error tracing.
913    */
914    if ( return_c() )
915      {
916       return;
917       }
918    chkin_c ( "gfudb_c" );
919 
920 
921    /*
922    Make sure cell data types are d.p.
923    */
924    CELLTYPECHK2 ( CHK_STANDARD, "gfudb_c", SPICE_DP, cnfine, result );
925 
926    /*
927    Initialize the input cells if necessary.
928    */
929    CELLINIT2 ( cnfine, result );
930 
931    /*
932    Store the input function pointers so these functions can be
933    called by the GF adapters.
934    */
935    zzadsave_c ( UDFUNC,  (void *)(udfuns)  );
936    zzadsave_c ( UDQDEC,  (void *)(udfunb)  );
937 
938 
939    /*
940    Let the f2c'd routine do the work.
941 
942    We pass the adapter functions, not those provided as inputs,
943    to the f2c'd routine:
944 
945       zzadfunc_c  adapter for  udfuns
946       zzadqdec_c     ''        udfunb
947 
948    */
949 
950    (void) gfudb_( ( U_fp            ) zzadfunc_c,
951                   ( U_fp            ) zzadqdec_c,
952                   ( doublereal    * ) &step,
953                   ( doublereal    * ) (cnfine->base),
954                   ( doublereal    * ) (result->base)  );
955 
956 
957    /*
958    Sync the output cell.
959    */
960    if ( !failed_c() )
961      {
962      zzsynccl_c ( F2C, result );
963      }
964 
965    chkout_c ( "gfudb_c" );
966 
967    } /* End gfudb_c */
968