1 /*
2 *class++
3 * Name:
4 * UnitMap
5
6 * Purpose:
7 * Unit (null) Mapping.
8
9 * Constructor Function:
10 c astUnitMap
11 f AST_UNITMAP
12
13 * Description:
14 * A UnitMap is a unit (null) Mapping that has no effect on the
15 * coordinates supplied to it. They are simply copied. This can be
16 * useful if a Mapping is required (e.g. to pass to another
17 c function) but you do not want it to have any effect.
18 f routine) but you do not want it to have any effect.
19 * The Nin and Nout attributes of a UnitMap are always equal and
20 * are specified when it is created.
21
22 * Inheritance:
23 * The UnitMap class inherits from the Mapping class.
24
25 * Attributes:
26 * The UnitMap class does not define any new attributes beyond
27 * those which are applicable to all Mappings.
28
29 * Functions:
30 c The UnitMap class does not define any new functions beyond those
31 f The UnitMap class does not define any new routines beyond those
32 * which are applicable to all Mappings.
33
34 * Copyright:
35 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
36 * Research Councils
37
38 * Licence:
39 * This program is free software: you can redistribute it and/or
40 * modify it under the terms of the GNU Lesser General Public
41 * License as published by the Free Software Foundation, either
42 * version 3 of the License, or (at your option) any later
43 * version.
44 *
45 * This program is distributed in the hope that it will be useful,
46 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48 * GNU Lesser General Public License for more details.
49 *
50 * You should have received a copy of the GNU Lesser General
51 * License along with this program. If not, see
52 * <http://www.gnu.org/licenses/>.
53
54 * Authors:
55 * RFWS: R.F. Warren-Smith (Starlink)
56 * DSB: David S Berry (JAC, Hawaii)
57
58 * History:
59 * 7-FEB-1996 (RFWS):
60 * Original version.
61 * 13-DEC-1996 (RFWS):
62 * Over-ride the astMapMerge method.
63 * 8-JAN-2003 (DSB):
64 * Changed private InitVtab method to protected astInitUnitMapVtab
65 * method.
66 * 10-MAY-2006 (DSB):
67 * Override astEqual.
68 * 17-FEB-2012 (DSB):
69 * In Transform, do not copy the coordinate values if the input and
70 * output array are the same.
71 *class--
72 */
73
74 /* Module Macros. */
75 /* ============== */
76 /* Set the name of the class we are implementing. This indicates to
77 the header files that define class interfaces that they should make
78 "protected" symbols available. */
79 #define astCLASS UnitMap
80
81 /* Include files. */
82 /* ============== */
83 /* Interface definitions. */
84 /* ---------------------- */
85
86 #include "globals.h" /* Thread-safe global data access */
87 #include "error.h" /* Error reporting facilities */
88 #include "object.h" /* Base Object class */
89 #include "memory.h" /* AST memory management */
90 #include "pointset.h" /* Sets of points/coordinates */
91 #include "mapping.h" /* Coordinate mappings (parent class) */
92 #include "unitmap.h" /* Interface definition for this class */
93
94 /* Error code definitions. */
95 /* ----------------------- */
96 #include "ast_err.h" /* AST error codes */
97
98 /* C header files. */
99 /* --------------- */
100 #include <stdarg.h>
101 #include <stddef.h>
102 #include <string.h>
103
104 /* Module Variables. */
105 /* ================= */
106
107 /* Address of this static variable is used as a unique identifier for
108 member of this class. */
109 static int class_check;
110
111 /* Pointers to parent class methods which are extended by this class. */
112 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
113
114
115 #ifdef THREAD_SAFE
116 /* Define how to initialise thread-specific globals. */
117 #define GLOBAL_inits \
118 globals->Class_Init = 0;
119
120 /* Create the function that initialises global data for this module. */
121 astMAKE_INITGLOBALS(UnitMap)
122
123 /* Define macros for accessing each item of thread specific global data. */
124 #define class_init astGLOBAL(UnitMap,Class_Init)
125 #define class_vtab astGLOBAL(UnitMap,Class_Vtab)
126
127
128 #include <pthread.h>
129
130
131 #else
132
133
134 /* Define the class virtual function table and its initialisation flag
135 as static variables. */
136 static AstUnitMapVtab class_vtab; /* Virtual function table */
137 static int class_init = 0; /* Virtual function table initialised? */
138
139 #endif
140
141 /* External Interface Function Prototypes. */
142 /* ======================================= */
143 /* The following functions have public prototypes only (i.e. no
144 protected prototypes), so we must provide local prototypes for use
145 within this module. */
146 AstUnitMap *astUnitMapId_( int, const char *, ... );
147
148 /* Prototypes for Private Member Functions. */
149 /* ======================================== */
150 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
151 static double Rate( AstMapping *, double *, int, int, int * );
152 static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * );
153 static int Equal( AstObject *, AstObject *, int * );
154 static int GetIsLinear( AstMapping *, int * );
155 static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
156 static void Dump( AstObject *, AstChannel *, int * );
157
158 /* Member functions. */
159 /* ================= */
Equal(AstObject * this_object,AstObject * that_object,int * status)160 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
161 /*
162 * Name:
163 * Equal
164
165 * Purpose:
166 * Test if two UnitMaps are equivalent.
167
168 * Type:
169 * Private function.
170
171 * Synopsis:
172 * #include "unitmap.h"
173 * int Equal( AstObject *this, AstObject *that, int *status )
174
175 * Class Membership:
176 * UnitMap member function (over-rides the astEqual protected
177 * method inherited from the astMapping class).
178
179 * Description:
180 * This function returns a boolean result (0 or 1) to indicate whether
181 * two UnitMaps are equivalent.
182
183 * Parameters:
184 * this
185 * Pointer to the first Object (a UnitMap).
186 * that
187 * Pointer to the second Object.
188 * status
189 * Pointer to the inherited status variable.
190
191 * Returned Value:
192 * One if the UnitMaps are equivalent, zero otherwise.
193
194 * Notes:
195 * - A value of zero will be returned if this function is invoked
196 * with the global status set, or if it should fail for any reason.
197 */
198
199 /* Local Variables: */
200 AstUnitMap *that;
201 AstUnitMap *this;
202 int result;
203
204 /* Initialise. */
205 result = 0;
206
207 /* Check the global error status. */
208 if ( !astOK ) return result;
209
210 /* Obtain pointers to the two UnitMap structures. */
211 this = (AstUnitMap *) this_object;
212 that = (AstUnitMap *) that_object;
213
214 /* Check the second object is a UnitMap. We know the first is a
215 UnitMap since we have arrived at this implementation of the virtual
216 function. */
217 if( astIsAUnitMap( that ) ) {
218
219 /* Get the number of inputs check they are the same for both. */
220 result = ( astGetNin( this ) == astGetNin( that ) );
221
222 }
223
224 /* If an error occurred, clear the result value. */
225 if ( !astOK ) result = 0;
226
227 /* Return the result, */
228 return result;
229 }
230
GetIsLinear(AstMapping * this_mapping,int * status)231 static int GetIsLinear( AstMapping *this_mapping, int *status ){
232 /*
233 * Name:
234 * GetIsLinear
235
236 * Purpose:
237 * Return the value of the IsLinear attribute for a UnitMap.
238
239 * Type:
240 * Private function.
241
242 * Synopsis:
243 * #include "mapping.h"
244 * void GetIsLinear( AstMapping *this, int *status )
245
246 * Class Membership:
247 * UnitMap member function (over-rides the protected astGetIsLinear
248 * method inherited from the Mapping class).
249
250 * Description:
251 * This function returns the value of the IsLinear attribute for a
252 * Frame, which is always one.
253
254 * Parameters:
255 * this
256 * Pointer to the UnitMap.
257 * status
258 * Pointer to the inherited status variable.
259 */
260 return 1;
261 }
262
astInitUnitMapVtab_(AstUnitMapVtab * vtab,const char * name,int * status)263 void astInitUnitMapVtab_( AstUnitMapVtab *vtab, const char *name, int *status ) {
264 /*
265 *+
266 * Name:
267 * astInitUnitMapVtab
268
269 * Purpose:
270 * Initialise a virtual function table for a UnitMap.
271
272 * Type:
273 * Protected function.
274
275 * Synopsis:
276 * #include "unitmap.h"
277 * void astInitUnitMapVtab( AstUnitMapVtab *vtab, const char *name )
278
279 * Class Membership:
280 * UnitMap vtab initialiser.
281
282 * Description:
283 * This function initialises the component of a virtual function
284 * table which is used by the UnitMap class.
285
286 * Parameters:
287 * vtab
288 * Pointer to the virtual function table. The components used by
289 * all ancestral classes will be initialised if they have not already
290 * been initialised.
291 * name
292 * Pointer to a constant null-terminated character string which contains
293 * the name of the class to which the virtual function table belongs (it
294 * is this pointer value that will subsequently be returned by the Object
295 * astClass function).
296 *-
297 */
298
299 /* Local Variables: */
300 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
301 AstObjectVtab *object; /* Pointer to Object component of Vtab */
302 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
303
304 /* Check the local error status. */
305 if ( !astOK ) return;
306
307 /* Get a pointer to the thread specific global data structure. */
308 astGET_GLOBALS(NULL);
309
310 /* Initialize the component of the virtual function table used by the
311 parent class. */
312 astInitMappingVtab( (AstMappingVtab *) vtab, name );
313
314 /* Store a unique "magic" value in the virtual function table. This
315 will be used (by astIsAUnitMap) to determine if an object belongs
316 to this class. We can conveniently use the address of the (static)
317 class_check variable to generate this unique value. */
318 vtab->id.check = &class_check;
319 vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
320
321 /* Initialise member function pointers. */
322 /* ------------------------------------ */
323 /* Store pointers to the member functions (implemented here) that
324 provide virtual methods for this class. */
325
326 /* None. */
327
328 /* Save the inherited pointers to methods that will be extended, and
329 replace them with pointers to the new member functions. */
330 object = (AstObjectVtab *) vtab;
331 mapping = (AstMappingVtab *) vtab;
332
333 parent_transform = mapping->Transform;
334 mapping->Transform = Transform;
335
336 /* Store replacement pointers for methods which will be over-ridden by
337 new member functions implemented here. */
338 object->Equal = Equal;
339 mapping->MapMerge = MapMerge;
340 mapping->MapSplit = MapSplit;
341 mapping->Rate = Rate;
342 mapping->GetIsLinear = GetIsLinear;
343
344 /* Declare the class dump function. There is no copy constructor or
345 destructor. */
346 astSetDump( vtab, Dump, "UnitMap", "Unit (null) Mapping" );
347
348 /* If we have just initialised the vtab for the current class, indicate
349 that the vtab is now initialised, and store a pointer to the class
350 identifier in the base "object" level of the vtab. */
351 if( vtab == &class_vtab ) {
352 class_init = 1;
353 astSetVtabClassIdentifier( vtab, &(vtab->id) );
354 }
355 }
356
MapMerge(AstMapping * this,int where,int series,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)357 static int MapMerge( AstMapping *this, int where, int series, int *nmap,
358 AstMapping ***map_list, int **invert_list, int *status ) {
359 /*
360 * Name:
361 * MapMerge
362
363 * Purpose:
364 * Simplify a sequence of Mappings containing a UnitMap.
365
366 * Type:
367 * Private function.
368
369 * Synopsis:
370 * #include "mapping.h"
371 * int MapMerge( AstMapping *this, int where, int series, int *nmap,
372 * AstMapping ***map_list, int **invert_list, int *status )
373
374 * Class Membership:
375 * UnitMap method (over-rides the protected astMapMerge method
376 * inherited from the Mapping class).
377
378 * Description:
379 * This function attempts to simplify a sequence of Mappings by
380 * merging a nominated UnitMap in the sequence with its neighbours,
381 * so as to shorten the sequence if possible.
382 *
383 * In many cases, simplification will not be possible and the
384 * function will return -1 to indicate this, without further
385 * action.
386 *
387 * In most cases of interest, however, this function will either
388 * attempt to replace the nominated UnitMap with one which it
389 * considers simpler, or to merge it with the Mappings which
390 * immediately precede it or follow it in the sequence (both will
391 * normally be considered). This is sufficient to ensure the
392 * eventual simplification of most Mapping sequences by repeated
393 * application of this function.
394 *
395 * In some cases, the function may attempt more elaborate
396 * simplification, involving any number of other Mappings in the
397 * sequence. It is not restricted in the type or scope of
398 * simplification it may perform, but will normally only attempt
399 * elaborate simplification in cases where a more straightforward
400 * approach is not adequate.
401
402 * Parameters:
403 * this
404 * Pointer to the nominated UnitMap which is to be merged with
405 * its neighbours. This should be a cloned copy of the UnitMap
406 * pointer contained in the array element "(*map_list)[where]"
407 * (see below). This pointer will not be annulled, and the
408 * UnitMap it identifies will not be modified by this function.
409 * where
410 * Index in the "*map_list" array (below) at which the pointer
411 * to the nominated UnitMap resides.
412 * series
413 * A non-zero value indicates that the sequence of Mappings to
414 * be simplified will be applied in series (i.e. one after the
415 * other), whereas a zero value indicates that they will be
416 * applied in parallel (i.e. on successive sub-sets of the
417 * input/output coordinates).
418 * nmap
419 * Address of an int which counts the number of Mappings in the
420 * sequence. On entry this should be set to the initial number
421 * of Mappings. On exit it will be updated to record the number
422 * of Mappings remaining after simplification.
423 * map_list
424 * Address of a pointer to a dynamically allocated array of
425 * Mapping pointers (produced, for example, by the astMapList
426 * method) which identifies the sequence of Mappings. On entry,
427 * the initial sequence of Mappings to be simplified should be
428 * supplied.
429 *
430 * On exit, the contents of this array will be modified to
431 * reflect any simplification carried out. Any form of
432 * simplification may be performed. This may involve any of: (a)
433 * removing Mappings by annulling any of the pointers supplied,
434 * (b) replacing them with pointers to new Mappings, (c)
435 * inserting additional Mappings and (d) changing their order.
436 *
437 * The intention is to reduce the number of Mappings in the
438 * sequence, if possible, and any reduction will be reflected in
439 * the value of "*nmap" returned. However, simplifications which
440 * do not reduce the length of the sequence (but improve its
441 * execution time, for example) may also be performed, and the
442 * sequence might conceivably increase in length (but normally
443 * only in order to split up a Mapping into pieces that can be
444 * more easily merged with their neighbours on subsequent
445 * invocations of this function).
446 *
447 * If Mappings are removed from the sequence, any gaps that
448 * remain will be closed up, by moving subsequent Mapping
449 * pointers along in the array, so that vacated elements occur
450 * at the end. If the sequence increases in length, the array
451 * will be extended (and its pointer updated) if necessary to
452 * accommodate any new elements.
453 *
454 * Note that any (or all) of the Mapping pointers supplied in
455 * this array may be annulled by this function, but the Mappings
456 * to which they refer are not modified in any way (although
457 * they may, of course, be deleted if the annulled pointer is
458 * the final one).
459 * invert_list
460 * Address of a pointer to a dynamically allocated array which,
461 * on entry, should contain values to be assigned to the Invert
462 * attributes of the Mappings identified in the "*map_list"
463 * array before they are applied (this array might have been
464 * produced, for example, by the astMapList method). These
465 * values will be used by this function instead of the actual
466 * Invert attributes of the Mappings supplied, which are
467 * ignored.
468 *
469 * On exit, the contents of this array will be updated to
470 * correspond with the possibly modified contents of the
471 * "*map_list" array. If the Mapping sequence increases in
472 * length, the "*invert_list" array will be extended (and its
473 * pointer updated) if necessary to accommodate any new
474 * elements.
475 * status
476 * Pointer to the inherited status variable.
477
478 * Returned Value:
479 * If simplification was possible, the function returns the index
480 * in the "map_list" array of the first element which was
481 * modified. Otherwise, it returns -1 (and makes no changes to the
482 * arrays supplied).
483
484 * Notes:
485 * - A value of -1 will be returned if this function is invoked
486 * with the global error status set, or if it should fail for any
487 * reason.
488 */
489
490 /* Local Variables: */
491 AstMapping *new; /* Pointer to replacement UnitMap */
492 const char *class; /* Pointer to Mapping class string */
493 int i1; /* Index of first UnitMap to merge */
494 int i2; /* Index of last UnitMap to merge */
495 int i; /* Loop counter for Mappings */
496 int ngone; /* Number of UnitMaps eliminated */
497 int nin; /* Number of coordinates for UnitMap */
498 int result; /* Result value to return */
499
500 /* Initialise. */
501 result = -1;
502
503 /* Check the global error status. */
504 if ( !astOK ) return result;
505
506 /* If the Mapping sequence consists of a single UnitMap, simply check
507 if the asociated Invert flag is set, and clear it if necessary. */
508 if ( *nmap == 1 ) {
509 if ( ( *invert_list )[ 0 ] ) {
510 ( *invert_list )[ 0 ] = 0;
511
512 /* Note if the Mapping sequence was modified. */
513 result = 0;
514 }
515
516 /* In series. */
517 /* ========== */
518 /* If a UnitMap occurs in series with any other Mapping, it can simply
519 be eliminated, so annul its Mapping pointer. */
520 } else if ( *nmap > 1 ) {
521 if ( series ) {
522 ( *map_list )[ where ] = astAnnul( ( *map_list )[ where ] );
523
524 /* Loop to move any following pointers and their Invert flags down in
525 the array to fill the gap, and clear the vacated elements at the
526 end of the arrays. */
527 for ( i = where + 1; i < *nmap; i++ ) {
528 ( *map_list )[ i - 1 ] = ( *map_list )[ i ];
529 ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ];
530 }
531 ( *map_list )[ *nmap - 1 ] = NULL;
532 ( *invert_list )[ *nmap - 1 ] = 0;
533
534 /* Decrement the Mapping count and return the index of the first
535 modified element. */
536 ( *nmap )--;
537 result = where;
538
539 /* In parallel. */
540 /* ============ */
541 /* If a UnitMap occurs in parallel with other Mappings, it can be
542 merged with any UnitMaps on either side of itself. */
543 } else {
544
545 /* Initialise indices to identify any adjacent UnitMaps and the number
546 of coordinates to be handled by the replacement. */
547 i1 = i2 = where;
548 nin = astGetNin( ( *map_list )[ where ] );
549
550 /* Loop to inspect earlier Mappings, obtaining the Mapping Class name
551 and checking it is "UnitMap". Quit looping as soon as any other
552 class of Mapping is found. */
553 while ( i1 - 1 >= 0 ) {
554 class = astGetClass( ( *map_list )[ i1 - 1 ] );
555 if ( !astOK || strcmp( class, "UnitMap" ) ) break;
556
557 /* Update the index of the earliest UnitMap that is to be merged and
558 increment the total number of coordinates involved. */
559 i1--;
560 nin += astGetNin( ( *map_list )[ i1 ] );
561 }
562
563 /* Repeat the above process to inspect any later Mappings in the
564 sequence. */
565 while ( i2 + 1 < *nmap ) {
566 class = astGetClass( ( *map_list )[ i2 + 1 ] );
567 if ( !astOK || strcmp( class, "UnitMap" ) ) break;
568 i2++;
569 nin += astGetNin( ( *map_list )[ i2 ] );
570 }
571
572 /* Calculate the net number of Mappings that can be removed from the
573 sequence and check if this is zero, meaning that there were no
574 adjacent UnitMaps to merge with. */
575 if ( astOK ) {
576 ngone = i2 - i1;
577 if ( !ngone ) {
578
579 /* If so, simply check if the nominated UnitMap's Invert flag is set,
580 and clear it if necessary. */
581 if ( ( *invert_list )[ where ] ) {
582 ( *invert_list )[ where ] = 0;
583
584 /* Note if the Mapping sequence was modified. */
585 result = where;
586 }
587
588 /* If UnitMaps can be merged, create the replacement UnitMap. */
589 } else {
590 new = (AstMapping *) astUnitMap( nin, "", status );
591 if ( astOK ) {
592
593 /* Annul the pointers to all the UnitMaps that are being replaced. */
594 for ( i = i1; i <= i2; i++ ) {
595 ( *map_list )[ i ] = astAnnul( ( *map_list )[ i ] );
596 }
597
598 /* Insert the new pointer and the associated Invert flag. */
599 ( *map_list )[ i1 ] = new;
600 ( *invert_list )[ i1 ] = 0;
601
602 /* Loop to close the resulting gap by moving subsequent elements down
603 in the arrays. */
604 for ( i = i2 + 1; i < *nmap; i++ ) {
605 ( *map_list )[ i - ngone ] = ( *map_list )[ i ];
606 ( *invert_list )[ i - ngone ] = ( *invert_list )[ i ];
607 }
608
609 /* Clear the vacated elements at the end. */
610 for ( i = *nmap - ngone; i < *nmap; i++ ) {
611 ( *map_list )[ i ] = NULL;
612 ( *invert_list )[ i ] = 0;
613 }
614
615 /* Decrement the Mapping count and return the index of the first
616 modified element. */
617 ( *nmap ) -= ngone;
618 result = i1;
619 }
620 }
621 }
622 }
623 }
624
625 /* Return the result. */
626 return result;
627 }
628
MapSplit(AstMapping * this_map,int nin,const int * in,AstMapping ** map,int * status)629 static int *MapSplit( AstMapping *this_map, int nin, const int *in, AstMapping **map, int *status ){
630 /*
631 * Name:
632 * MapSplit
633
634 * Purpose:
635 * Create a Mapping representing a subset of the inputs of an existing
636 * UnitMap.
637
638 * Type:
639 * Private function.
640
641 * Synopsis:
642 * #include "unitmap.h"
643 * int *MapSplit( AstMapping *this, int nin, const int *in, AstMapping **map, int *status )
644
645 * Class Membership:
646 * UnitMap method (over-rides the protected astMapSplit method
647 * inherited from the Mapping class).
648
649 * Description:
650 * This function creates a new Mapping by picking specified inputs from
651 * an existing UnitMap. This is only possible if the specified inputs
652 * correspond to some subset of the UnitMap outputs. That is, there
653 * must exist a subset of the UnitMap outputs for which each output
654 * depends only on the selected UnitMap inputs, and not on any of the
655 * inputs which have not been selected. If this condition is not met
656 * by the supplied UnitMap, then a NULL Mapping is returned.
657
658 * Parameters:
659 * this
660 * Pointer to the UnitMap to be split (the UnitMap is not actually
661 * modified by this function).
662 * nin
663 * The number of inputs to pick from "this".
664 * in
665 * Pointer to an array of indices (zero based) for the inputs which
666 * are to be picked. This array should have "nin" elements. If "Nin"
667 * is the number of inputs of the supplied UnitMap, then each element
668 * should have a value in the range zero to Nin-1.
669 * map
670 * Address of a location at which to return a pointer to the new
671 * Mapping. This Mapping will have "nin" inputs (the number of
672 * outputs may be different to "nin"). A NULL pointer will be
673 * returned if the supplied UnitMap has no subset of outputs which
674 * depend only on the selected inputs.
675 * status
676 * Pointer to the inherited status variable.
677
678 * Returned Value:
679 * A pointer to a dynamically allocated array of ints. The number of
680 * elements in this array will equal the number of outputs for the
681 * returned Mapping. Each element will hold the index of the
682 * corresponding output in the supplied UnitMap. The array should be
683 * freed using astFree when no longer needed. A NULL pointer will
684 * be returned if no output Mapping can be created.
685
686 * Notes:
687 * - If this function is invoked with the global error status set,
688 * or if it should fail for any reason, then NULL values will be
689 * returned as the function value and for the "map" pointer.
690 */
691
692 /* Local Variables: */
693 AstUnitMap *this; /* Pointer to UnitMap structure */
694 int *result; /* Pointer to returned array */
695 int i; /* Loop count */
696 int iin; /* Mapping input index */
697 int mnin; /* No. of Mapping inputs */
698 int ok; /* Are input indices OK? */
699
700 /* Initialise */
701 result = NULL;
702 *map = NULL;
703
704 /* Check the global error status. */
705 if ( !astOK ) return result;
706
707 /* Get a pointer to the UnitMap structure. */
708 this = (AstUnitMap *) this_map;
709
710 /* Allocate memory for the returned array and create a UnitMap with the
711 required number of axes. */
712 result = astMalloc( sizeof( int )*(size_t) nin );
713 *map = (AstMapping *) astUnitMap( nin, "", status );
714
715 /* Check pointers can be used safely. */
716 if( astOK ) {
717
718 /* Store the required output axis indices. At the same time check that each
719 axis is valid. */
720 mnin = astGetNin( this );
721 ok = 1;
722 for( i = 0; i < nin; i++ ) {
723 iin = in[ i ];
724 if( iin >= 0 && iin < mnin ) {
725 result[ i ] = iin;
726 } else {
727 ok = 0;
728 break;
729 }
730 }
731
732 /* If the "in" array contained any invalid values, free the returned
733 resources. */
734 if( !ok ) {
735 result = astFree( result );
736 *map = astAnnul( *map );
737 }
738 }
739
740 /* Free returned resources if an error has occurred. */
741 if( !astOK ) {
742 result = astFree( result );
743 *map = astAnnul( *map );
744 }
745
746 /* Return the list of output indices. */
747 return result;
748 }
749
Rate(AstMapping * this,double * at,int ax1,int ax2,int * status)750 static double Rate( AstMapping *this, double *at, int ax1, int ax2, int *status ){
751 /*
752 * Name:
753 * Rate
754
755 * Purpose:
756 * Calculate the rate of change of a Mapping output.
757
758 * Type:
759 * Private function.
760
761 * Synopsis:
762 * #include "unitmap.h"
763 * result = Rate( AstMapping *this, double *at, int ax1, int ax2, int *status )
764
765 * Class Membership:
766 * UnitMap member function (overrides the astRate method inherited
767 * from the Mapping class ).
768
769 * Description:
770 * This function returns the rate of change of a specified output of
771 * the supplied Mapping with respect to a specified input, at a
772 * specified input position.
773
774 * Parameters:
775 * this
776 * Pointer to the Mapping to be applied.
777 * at
778 * The address of an array holding the axis values at the position
779 * at which the rate of change is to be evaluated. The number of
780 * elements in this array should equal the number of inputs to the
781 * Mapping.
782 * ax1
783 * The index of the Mapping output for which the rate of change is to
784 * be found (output numbering starts at 0 for the first output).
785 * ax2
786 * The index of the Mapping input which is to be varied in order to
787 * find the rate of change (input numbering starts at 0 for the first
788 * input).
789 * status
790 * Pointer to the inherited status variable.
791
792 * Returned Value:
793 * The rate of change of Mapping output "ax1" with respect to input
794 * "ax2", evaluated at "at", or AST__BAD if the value cannot be
795 * calculated.
796
797 */
798
799 return ( ax1 == ax2 ) ? 1.0 : 0.0;
800 }
801
Transform(AstMapping * this,AstPointSet * in,int forward,AstPointSet * out,int * status)802 static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
803 int forward, AstPointSet *out, int *status ) {
804 /*
805 * Name:
806 * Transform
807
808 * Purpose:
809 * Apply a UnitMap to transform a set of points.
810
811 * Type:
812 * Private function.
813
814 * Synopsis:
815 * #include "unitmap.h"
816 * AstPointSet *Transform( AstMapping *this, AstPointSet *in,
817 * int forward, AstPointSet *out, int *status )
818
819 * Class Membership:
820 * UnitMap member function (over-rides the astTransform method inherited
821 * from the Mapping class).
822
823 * Description:
824 * This function takes a UnitMap and a set of points encapsulated in a
825 * PointSet and transforms the points so as to perform the identity
826 * transformation (i.e. simply copies the coordinate values).
827
828 * Parameters:
829 * this
830 * Pointer to the UnitMap.
831 * in
832 * Pointer to the PointSet holding the input coordinate data.
833 * forward
834 * A non-zero value indicates that the forward coordinate transformation
835 * should be applied, while a zero value requests the inverse
836 * transformation. In this case, both transformations are equivalent.
837 * out
838 * Pointer to a PointSet which will hold the transformed (output)
839 * coordinate values. A NULL value may also be given, in which case a
840 * new PointSet will be created by this function.
841 * status
842 * Pointer to the inherited status variable.
843
844 * Returned Value:
845 * Pointer to the output (possibly new) PointSet.
846
847 * Notes:
848 * - A null pointer will be returned if this function is invoked with the
849 * global error status set, or if it should fail for any reason.
850 * - The number of coordinate values per point in the input PointSet must
851 * match the number of coordinates for the UnitMap being applied.
852 * - If an output PointSet is supplied, it must have space for sufficient
853 * number of points and coordinate values per point to accommodate the
854 * result. Any excess space will be ignored.
855 */
856
857 /* Local Variables: */
858 AstPointSet *result; /* Pointer to output PointSet */
859 AstUnitMap *map; /* Pointer to UnitMap to be applied */
860 double **ptr_in; /* Pointer to input coordinate data */
861 double **ptr_out; /* Pointer to output coordinate data */
862 int coord; /* Loop counter for coordinates */
863 int ncoord_in; /* Number of coordinates per input point */
864 int npoint; /* Number of points */
865
866 /* Check the global error status. */
867 if ( !astOK ) return NULL;
868
869 /* Obtain a pointer to the UnitMap. */
870 map = (AstUnitMap *) this;
871
872 /* Apply the parent mapping using the stored pointer to the Transform member
873 function inherited from the parent Mapping class. This function validates
874 all arguments and generates an output PointSet if necessary, but does not
875 actually transform any coordinate values. */
876 result = (*parent_transform)( this, in, forward, out, status );
877
878 /* We will now extend the parent astTransform method by performing the
879 coordinate copy needed to generate the output coordinate values. */
880
881 /* Determine the numbers of points and coordinates per point from the input
882 PointSet and obtain pointers for accessing the input and output coordinate
883 values. */
884 ncoord_in = astGetNcoord( in );
885 npoint = astGetNpoint( in );
886 ptr_in = astGetPoints( in );
887 ptr_out = astGetPoints( result );
888
889 /* We need not determine whether to apply the forward or inverse
890 transformation, as they are both the same. */
891
892 /* Copy the coordinate values. */
893 /* --------------------------- */
894 if ( astOK ) {
895
896 /* Loop to copy the values for each coordinate. Use a memory copy for speed.
897 Do not do the copy if the input and output arrays are the same. */
898 for ( coord = 0; coord < ncoord_in; coord++ ) {
899 if( ptr_out[ coord ] != ptr_in[ coord ] ) {
900 (void) memcpy( (void *) ptr_out[ coord ],
901 (const void *) ptr_in[ coord ],
902 sizeof( double ) * (size_t) npoint );
903 }
904 }
905 }
906
907 /* Return a pointer to the output PointSet. */
908 return result;
909 }
910
911 /* Copy constructor. */
912 /* ----------------- */
913 /* No copy constructor is needed, as a byte-by-byte copy suffices. */
914
915 /* Destructor. */
916 /* ----------- */
917 /* No destructor is needed as no memory, etc. needs freeing. */
918
919 /* Dump function. */
920 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)921 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
922 /*
923 * Name:
924 * Dump
925
926 * Purpose:
927 * Dump function for UnitMap objects.
928
929 * Type:
930 * Private function.
931
932 * Synopsis:
933 * void Dump( AstObject *this, AstChannel *channel, int *status )
934
935 * Description:
936 * This function implements the Dump function which writes out data
937 * for the UnitMap class to an output Channel.
938
939 * Parameters:
940 * this
941 * Pointer to the UnitMap whose data are being written.
942 * channel
943 * Pointer to the Channel to which the data are being written.
944 * status
945 * Pointer to the inherited status variable.
946 */
947
948 /* Local Variables: */
949 AstUnitMap *this; /* Pointer to the UnitMap structure */
950
951 /* Check the global error status. */
952 if ( !astOK ) return;
953
954 /* Obtain a pointer to the UnitMap structure. */
955 this = (AstUnitMap *) this_object;
956
957 /* Write out values representing the instance variables for the
958 UnitMap class. Accompany these with appropriate comment strings,
959 possibly depending on the values being written.*/
960
961 /* In the case of attributes, we first use the appropriate (private)
962 Test... member function to see if they are set. If so, we then use
963 the (private) Get... function to obtain the value to be written
964 out.
965
966 For attributes which are not set, we use the astGet... method to
967 obtain the value instead. This will supply a default value
968 (possibly provided by a derived class which over-rides this method)
969 which is more useful to a human reader as it corresponds to the
970 actual default attribute value. Since "set" will be zero, these
971 values are for information only and will not be read back. */
972
973 /* There are no values to write, so return without further action. */
974 }
975
976 /* Standard class functions. */
977 /* ========================= */
978 /* Implement the astIsAUnitMap and astCheckUnitMap functions using the macros
979 defined for this purpose in the "object.h" header file. */
astMAKE_ISA(UnitMap,Mapping)980 astMAKE_ISA(UnitMap,Mapping)
981 astMAKE_CHECK(UnitMap)
982
983 AstUnitMap *astUnitMap_( int ncoord, const char *options, int *status, ...) {
984 /*
985 *++
986 * Name:
987 c astUnitMap
988 f AST_UNITMAP
989
990 * Purpose:
991 * Create a UnitMap.
992
993 * Type:
994 * Public function.
995
996 * Synopsis:
997 c #include "unitmap.h"
998 c AstUnitMap *astUnitMap( int ncoord, const char *options, ... )
999 f RESULT = AST_UNITMAP( NCOORD, OPTIONS, STATUS )
1000
1001 * Class Membership:
1002 * UnitMap constructor.
1003
1004 * Description:
1005 * This function creates a new UnitMap and optionally initialises
1006 * its attributes.
1007 *
1008 * A UnitMap is a unit (null) Mapping that has no effect on the
1009 * coordinates supplied to it. They are simply copied. This can be
1010 * useful if a Mapping is required (e.g. to pass to another
1011 c function) but you do not want it to have any effect.
1012 f routine) but you do not want it to have any effect.
1013
1014 * Parameters:
1015 c ncoord
1016 f NCOORD = INTEGER (Given)
1017 * The number of input and output coordinates (these numbers are
1018 * necessarily the same).
1019 c options
1020 f OPTIONS = CHARACTER * ( * ) (Given)
1021 c Pointer to a null-terminated string containing an optional
1022 c comma-separated list of attribute assignments to be used for
1023 c initialising the new UnitMap. The syntax used is identical to
1024 c that for the astSet function and may include "printf" format
1025 c specifiers identified by "%" symbols in the normal way.
1026 f A character string containing an optional comma-separated
1027 f list of attribute assignments to be used for initialising the
1028 f new UnitMap. The syntax used is identical to that for the
1029 f AST_SET routine.
1030 c ...
1031 c If the "options" string contains "%" format specifiers, then
1032 c an optional list of additional arguments may follow it in
1033 c order to supply values to be substituted for these
1034 c specifiers. The rules for supplying these are identical to
1035 c those for the astSet function (and for the C "printf"
1036 c function).
1037 f STATUS = INTEGER (Given and Returned)
1038 f The global status.
1039
1040 * Returned Value:
1041 c astUnitMap()
1042 f AST_UNITMAP = INTEGER
1043 * A pointer to the new UnitMap.
1044
1045 * Notes:
1046 * - A null Object pointer (AST__NULL) will be returned if this
1047 c function is invoked with the AST error status set, or if it
1048 f function is invoked with STATUS set to an error value, or if it
1049 * should fail for any reason.
1050 *--
1051 */
1052
1053 /* Local Variables: */
1054 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1055 AstUnitMap *new; /* Pointer to new UnitMap */
1056 va_list args; /* Variable argument list */
1057
1058 /* Get a pointer to the thread specific global data structure. */
1059 astGET_GLOBALS(NULL);
1060
1061 /* Check the global status. */
1062 if ( !astOK ) return NULL;
1063
1064 /* Initialise the UnitMap, allocating memory and initialising the
1065 virtual function table as well if necessary. */
1066 new = astInitUnitMap( NULL, sizeof( AstUnitMap ), !class_init, &class_vtab,
1067 "UnitMap", ncoord );
1068
1069 /* If successful, note that the virtual function table has been
1070 initialised. */
1071 if ( astOK ) {
1072 class_init = 1;
1073
1074 /* Obtain the variable argument list and pass it along with the
1075 options string to the astVSet method to initialise the new
1076 UnitMap's attributes. */
1077 va_start( args, status );
1078 astVSet( new, options, NULL, args );
1079 va_end( args );
1080
1081 /* If an error occurred, clean up by deleting the new object. */
1082 if ( !astOK ) new = astDelete( new );
1083 }
1084
1085 /* Return a pointer to the new UnitMap. */
1086 return new;
1087 }
1088
astUnitMapId_(int ncoord,const char * options,...)1089 AstUnitMap *astUnitMapId_( int ncoord, const char *options, ... ) {
1090 /*
1091 * Name:
1092 * astUnitMapId_
1093
1094 * Purpose:
1095 * Create a UnitMap.
1096
1097 * Type:
1098 * Private function.
1099
1100 * Synopsis:
1101 * #include "unitmap.h"
1102 * AstUnitMap *astUnitMapId_( int ncoord, const char *options, ... )
1103
1104 * Class Membership:
1105 * UnitMap constructor.
1106
1107 * Description:
1108 * This function implements the external (public) interface to the
1109 * astUnitMap constructor function. It returns an ID value (instead
1110 * of a true C pointer) to external users, and must be provided
1111 * because astUnitMap_ has a variable argument list which cannot be
1112 * encapsulated in a macro (where this conversion would otherwise
1113 * occur).
1114 *
1115 * The variable argument list also prevents this function from
1116 * invoking astUnitMap_ directly, so it must be a re-implementation
1117 * of it in all respects, except for the final conversion of the
1118 * result to an ID value.
1119
1120 * Parameters:
1121 * As for astUnitMap_.
1122
1123 * Returned Value:
1124 * The ID value associated with the new UnitMap.
1125 */
1126
1127 /* Local Variables: */
1128 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1129 AstUnitMap *new; /* Pointer to new UnitMap */
1130 va_list args; /* Variable argument list */
1131
1132 int *status; /* Pointer to inherited status value */
1133
1134 /* Get a pointer to the inherited status value. */
1135 status = astGetStatusPtr;
1136
1137 /* Get a pointer to the thread specific global data structure. */
1138 astGET_GLOBALS(NULL);
1139
1140 /* Check the global status. */
1141 if ( !astOK ) return NULL;
1142
1143 /* Initialise the UnitMap, allocating memory and initialising the
1144 virtual function table as well if necessary. */
1145 new = astInitUnitMap( NULL, sizeof( AstUnitMap ), !class_init, &class_vtab,
1146 "UnitMap", ncoord );
1147
1148 /* If successful, note that the virtual function table has been
1149 initialised. */
1150 if ( astOK ) {
1151 class_init = 1;
1152
1153 /* Obtain the variable argument list and pass it along with the
1154 options string to the astVSet method to initialise the new
1155 UnitMap's attributes. */
1156 va_start( args, options );
1157 astVSet( new, options, NULL, args );
1158 va_end( args );
1159
1160 /* If an error occurred, clean up by deleting the new object. */
1161 if ( !astOK ) new = astDelete( new );
1162 }
1163
1164 /* Return an ID value for the new UnitMap. */
1165 return astMakeId( new );
1166 }
1167
astInitUnitMap_(void * mem,size_t size,int init,AstUnitMapVtab * vtab,const char * name,int ncoord,int * status)1168 AstUnitMap *astInitUnitMap_( void *mem, size_t size, int init,
1169 AstUnitMapVtab *vtab, const char *name,
1170 int ncoord, int *status ) {
1171 /*
1172 *+
1173 * Name:
1174 * astInitUnitMap
1175
1176 * Purpose:
1177 * Initialise a UnitMap.
1178
1179 * Type:
1180 * Protected function.
1181
1182 * Synopsis:
1183 * #include "unitmap.h"
1184 * AstUnitMap *astInitUnitMap( void *mem, size_t size, int init,
1185 * AstUnitMapVtab *vtab, const char *name,
1186 * int ncoord )
1187
1188 * Class Membership:
1189 * UnitMap initialiser.
1190
1191 * Description:
1192 * This function is provided for use by class implementations to initialise
1193 * a new UnitMap object. It allocates memory (if necessary) to accommodate
1194 * the UnitMap plus any additional data associated with the derived class.
1195 * It then initialises a UnitMap structure at the start of this memory. If
1196 * the "init" flag is set, it also initialises the contents of a virtual
1197 * function table for a UnitMap at the start of the memory passed via the
1198 * "vtab" parameter.
1199
1200 * Parameters:
1201 * mem
1202 * A pointer to the memory in which the UnitMap is to be initialised.
1203 * This must be of sufficient size to accommodate the UnitMap data
1204 * (sizeof(UnitMap)) plus any data used by the derived class. If a value
1205 * of NULL is given, this function will allocate the memory itself using
1206 * the "size" parameter to determine its size.
1207 * size
1208 * The amount of memory used by the UnitMap (plus derived class data).
1209 * This will be used to allocate memory if a value of NULL is given for
1210 * the "mem" parameter. This value is also stored in the UnitMap
1211 * structure, so a valid value must be supplied even if not required for
1212 * allocating memory.
1213 * init
1214 * A logical flag indicating if the UnitMap's virtual function table is
1215 * to be initialised. If this value is non-zero, the virtual function
1216 * table will be initialised by this function.
1217 * vtab
1218 * Pointer to the start of the virtual function table to be associated
1219 * with the new UnitMap.
1220 * name
1221 * Pointer to a constant null-terminated character string which contains
1222 * the name of the class to which the new object belongs (it is this
1223 * pointer value that will subsequently be returned by the Object
1224 * astClass function).
1225 * ncoord
1226 * The number of coordinate values per point.
1227
1228 * Returned Value:
1229 * A pointer to the new UnitMap.
1230
1231 * Notes:
1232 * - A null pointer will be returned if this function is invoked with the
1233 * global error status set, or if it should fail for any reason.
1234 *-
1235 */
1236
1237 /* Local Variables: */
1238 AstUnitMap *new; /* Pointer to new UnitMap */
1239
1240 /* Check the global status. */
1241 if ( !astOK ) return NULL;
1242
1243 /* If necessary, initialise the virtual function table. */
1244 if ( init ) astInitUnitMapVtab( vtab, name );
1245
1246 /* Initialise. */
1247 new = NULL;
1248
1249 /* Initialise a Mapping structure (the parent class) as the first component
1250 within the UnitMap structure, allocating memory if necessary. Specify that
1251 the Mapping should be defined in both the forward and inverse directions. */
1252 new = (AstUnitMap *) astInitMapping( mem, size, 0,
1253 (AstMappingVtab *) vtab, name,
1254 ncoord, ncoord, 1, 1 );
1255
1256 if ( astOK ) {
1257
1258 /* Initialise the UnitMap data. */
1259 /* ---------------------------- */
1260 /* There is nothing else to store. */
1261
1262 /* If an error occurred, clean up by deleting the new object (if any other
1263 resources had been allocated, we would free these first). */
1264 if ( !astOK ) new = astDelete( new );
1265 }
1266
1267 /* Return a pointer to the new object. */
1268 return new;
1269 }
1270
astLoadUnitMap_(void * mem,size_t size,AstUnitMapVtab * vtab,const char * name,AstChannel * channel,int * status)1271 AstUnitMap *astLoadUnitMap_( void *mem, size_t size,
1272 AstUnitMapVtab *vtab, const char *name,
1273 AstChannel *channel, int *status ) {
1274 /*
1275 *+
1276 * Name:
1277 * astLoadUnitMap
1278
1279 * Purpose:
1280 * Load a UnitMap.
1281
1282 * Type:
1283 * Protected function.
1284
1285 * Synopsis:
1286 * #include "unitmap.h"
1287 * AstUnitMap *astLoadUnitMap( void *mem, size_t size,
1288 * AstUnitMapVtab *vtab, const char *name,
1289 * AstChannel *channel )
1290
1291 * Class Membership:
1292 * UnitMap loader.
1293
1294 * Description:
1295 * This function is provided to load a new UnitMap using data read
1296 * from a Channel. It first loads the data used by the parent class
1297 * (which allocates memory if necessary) and then initialises a
1298 * UnitMap structure in this memory, using data read from the input
1299 * Channel.
1300 *
1301 * If the "init" flag is set, it also initialises the contents of a
1302 * virtual function table for a UnitMap at the start of the memory
1303 * passed via the "vtab" parameter.
1304
1305
1306 * Parameters:
1307 * mem
1308 * A pointer to the memory into which the UnitMap is to be
1309 * loaded. This must be of sufficient size to accommodate the
1310 * UnitMap data (sizeof(UnitMap)) plus any data used by derived
1311 * classes. If a value of NULL is given, this function will
1312 * allocate the memory itself using the "size" parameter to
1313 * determine its size.
1314 * size
1315 * The amount of memory used by the UnitMap (plus derived class
1316 * data). This will be used to allocate memory if a value of
1317 * NULL is given for the "mem" parameter. This value is also
1318 * stored in the UnitMap structure, so a valid value must be
1319 * supplied even if not required for allocating memory.
1320 *
1321 * If the "vtab" parameter is NULL, the "size" value is ignored
1322 * and sizeof(AstUnitMap) is used instead.
1323 * vtab
1324 * Pointer to the start of the virtual function table to be
1325 * associated with the new UnitMap. If this is NULL, a pointer
1326 * to the (static) virtual function table for the UnitMap class
1327 * is used instead.
1328 * name
1329 * Pointer to a constant null-terminated character string which
1330 * contains the name of the class to which the new object
1331 * belongs (it is this pointer value that will subsequently be
1332 * returned by the astGetClass method).
1333 *
1334 * If the "vtab" parameter is NULL, the "name" value is ignored
1335 * and a pointer to the string "UnitMap" is used instead.
1336
1337 * Returned Value:
1338 * A pointer to the new UnitMap.
1339
1340 * Notes:
1341 * - A null pointer will be returned if this function is invoked
1342 * with the global error status set, or if it should fail for any
1343 * reason.
1344 *-
1345 */
1346
1347 /* Local Variables: */
1348 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1349 AstUnitMap *new; /* Pointer to the new UnitMap */
1350
1351 /* Initialise. */
1352 new = NULL;
1353
1354 /* Check the global error status. */
1355 if ( !astOK ) return new;
1356
1357 /* Get a pointer to the thread specific global data structure. */
1358 astGET_GLOBALS(channel);
1359
1360 /* If a NULL virtual function table has been supplied, then this is
1361 the first loader to be invoked for this UnitMap. In this case the
1362 UnitMap belongs to this class, so supply appropriate values to be
1363 passed to the parent class loader (and its parent, etc.). */
1364 if ( !vtab ) {
1365 size = sizeof( AstUnitMap );
1366 vtab = &class_vtab;
1367 name = "UnitMap";
1368
1369 /* If required, initialise the virtual function table for this class. */
1370 if ( !class_init ) {
1371 astInitUnitMapVtab( vtab, name );
1372 class_init = 1;
1373 }
1374 }
1375
1376 /* Invoke the parent class loader to load data for all the ancestral
1377 classes of the current one, returning a pointer to the resulting
1378 partly-built UnitMap. */
1379 new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
1380 channel );
1381
1382 if ( astOK ) {
1383
1384 /* Read input data. */
1385 /* ================ */
1386 /* Request the input Channel to read all the input data appropriate to
1387 this class into the internal "values list". */
1388 astReadClassData( channel, "UnitMap" );
1389
1390 /* Now read each individual data item from this list and use it to
1391 initialise the appropriate instance variable(s) for this class. */
1392
1393 /* In the case of attributes, we first read the "raw" input value,
1394 supplying the "unset" value as the default. If a "set" value is
1395 obtained, we then use the appropriate (private) Set... member
1396 function to validate and set the value properly. */
1397
1398 /* There are no values to read. */
1399 /* ---------------------------- */
1400
1401 /* If an error occurred, clean up by deleting the new UnitMap. */
1402 if ( !astOK ) new = astDelete( new );
1403 }
1404
1405 /* Return the new UnitMap pointer. */
1406 return new;
1407 }
1408
1409 /* Virtual function interfaces. */
1410 /* ============================ */
1411 /* These provide the external interface to the virtual functions defined by
1412 this class. Each simply checks the global error status and then locates and
1413 executes the appropriate member function, using the function pointer stored
1414 in the object's virtual function table (this pointer is located using the
1415 astMEMBER macro defined in "object.h").
1416
1417 Note that the member function may not be the one defined here, as it may
1418 have been over-ridden by a derived class. However, it should still have the
1419 same interface. */
1420
1421 /* There are none of these. */
1422
1423
1424
1425
1426