1 /*
2 *class++
3 * Name:
4 * TranMap
5
6 * Purpose:
7 * Mapping with specified forward and inverse transformations.
8
9 * Constructor Function:
10 c astTranMap
11 f AST_TRANMAP
12
13 * Description:
14 * A TranMap is a Mapping which combines the forward transformation of
15 * a supplied Mapping with the inverse transformation of another
16 * supplied Mapping, ignoring the un-used transformation in each
17 * Mapping (indeed the un-used transformation need not exist).
18 *
19 * When the forward transformation of the TranMap is referred to, the
20 * transformation actually used is the forward transformation of the
21 * first Mapping supplied when the TranMap was constructed. Likewise,
22 * when the inverse transformation of the TranMap is referred to, the
23 * transformation actually used is the inverse transformation of the
24 * second Mapping supplied when the TranMap was constructed.
25
26 * Inheritance:
27 * The TranMap class inherits from the Mapping class.
28
29 * Attributes:
30 * The TranMap class does not define any new attributes beyond those
31 * which are applicable to all Mappings.
32
33 * Functions:
34 c The TranMap class does not define any new functions beyond those
35 f The TranMap class does not define any new routines beyond those
36 * which are applicable to all Mappings.
37
38 * Copyright:
39 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
40 * Research Councils
41
42 * Licence:
43 * This program is free software: you can redistribute it and/or
44 * modify it under the terms of the GNU Lesser General Public
45 * License as published by the Free Software Foundation, either
46 * version 3 of the License, or (at your option) any later
47 * version.
48 *
49 * This program is distributed in the hope that it will be useful,
50 * but WITHOUT ANY WARRANTY; without even the implied warranty of
51 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52 * GNU Lesser General Public License for more details.
53 *
54 * You should have received a copy of the GNU Lesser General
55 * License along with this program. If not, see
56 * <http://www.gnu.org/licenses/>.
57
58 * Authors:
59 * DSB: David S. Berry (Starlink)
60
61 * History:
62 * 10-FEB-2004 (DSB):
63 * Original version.
64 * 19-JAN-2005 (DSB):
65 * Fix memory leak.
66 * 14-FEB-2006 (DSB):
67 * - Over-ride the astDecompose method.
68 * - Fix bug in MapSplit related to use of invert flags.
69 * 14-FEB-2006 (DSB):
70 * Override astGetObjSize.
71 * 10-MAY-2006 (DSB):
72 * Override astEqual.
73 *class--
74 */
75
76 /* Module Macros. */
77 /* ============== */
78 /* Set the name of the class we are implementing. This indicates to
79 the header files that define class interfaces that they should make
80 "protected" symbols available. */
81 #define astCLASS TranMap
82
83 /* Include files. */
84 /* ============== */
85 /* Interface definitions. */
86 /* ---------------------- */
87
88 #include "globals.h" /* Thread-safe global data access */
89 #include "error.h" /* Error reporting facilities */
90 #include "memory.h" /* Memory allocation facilities */
91 #include "object.h" /* Base Object class */
92 #include "pointset.h" /* Sets of points/coordinates */
93 #include "mapping.h" /* Coordinate Mappings (parent class) */
94 #include "channel.h" /* I/O channels */
95 #include "permmap.h" /* Coordinate permutation Mappings */
96 #include "cmpmap.h" /* Compound Mappings */
97 #include "unitmap.h" /* Unit Mappings */
98 #include "tranmap.h" /* Interface definition for this class */
99 #include "frame.h" /* Frames */
100
101 /* Error code definitions. */
102 /* ----------------------- */
103 #include "ast_err.h" /* AST error codes */
104
105 /* C header files. */
106 /* --------------- */
107 #include <stdarg.h>
108 #include <stddef.h>
109 #include <string.h>
110 #include <stdio.h>
111
112 /* Module Variables. */
113 /* ================= */
114
115 /* Address of this static variable is used as a unique identifier for
116 member of this class. */
117 static int class_check;
118
119 /* Pointers to parent class methods which are extended by this class. */
120 static int (* parent_getobjsize)( AstObject *, int * );
121 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
122 static int *(* parent_mapsplit)( AstMapping *, int, const int *, AstMapping **, int * );
123
124 #if defined(THREAD_SAFE)
125 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
126 #endif
127
128
129
130 #ifdef THREAD_SAFE
131 /* Define how to initialise thread-specific globals. */
132 #define GLOBAL_inits \
133 globals->Class_Init = 0;
134
135 /* Create the function that initialises global data for this module. */
136 astMAKE_INITGLOBALS(TranMap)
137
138 /* Define macros for accessing each item of thread specific global data. */
139 #define class_init astGLOBAL(TranMap,Class_Init)
140 #define class_vtab astGLOBAL(TranMap,Class_Vtab)
141
142
143 #include <pthread.h>
144
145
146 #else
147
148
149 /* Define the class virtual function table and its initialisation flag
150 as static variables. */
151 static AstTranMapVtab class_vtab; /* Virtual function table */
152 static int class_init = 0; /* Virtual function table initialised? */
153
154 #endif
155
156 /* External Interface Function Prototypes. */
157 /* ======================================= */
158 /* The following functions have public prototypes only (i.e. no
159 protected prototypes), so we must provide local prototypes for use
160 within this module. */
161 AstTranMap *astTranMapId_( void *, void *, const char *, ... );
162
163 /* Prototypes for Private Member Functions. */
164 /* ======================================== */
165 static AstMapping *RemoveRegions( AstMapping *, int * );
166 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
167 static double Rate( AstMapping *, double *, int, int, int * );
168 static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * );
169 static int Equal( AstObject *, AstObject *, int * );
170 static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
171 static void Copy( const AstObject *, AstObject *, int * );
172 static void Delete( AstObject *, int * );
173 static void Dump( AstObject *, AstChannel *, int * );
174 static void Decompose( AstMapping *, AstMapping **, AstMapping **, int *, int *, int *, int * );
175 static int GetObjSize( AstObject *, int * );
176
177 #if defined(THREAD_SAFE)
178 static int ManageLock( AstObject *, int, int, AstObject **, int * );
179 #endif
180
181
182 /* Member functions. */
183 /* ================= */
Equal(AstObject * this_object,AstObject * that_object,int * status)184 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
185 /*
186 * Name:
187 * Equal
188
189 * Purpose:
190 * Test if two TranMaps are equivalent.
191
192 * Type:
193 * Private function.
194
195 * Synopsis:
196 * #include "tranmap.h"
197 * int Equal( AstObject *this, AstObject *that, int *status )
198
199 * Class Membership:
200 * TranMap member function (over-rides the astEqual protected
201 * method inherited from the astMapping class).
202
203 * Description:
204 * This function returns a boolean result (0 or 1) to indicate whether
205 * two TranMaps are equivalent.
206
207 * Parameters:
208 * this
209 * Pointer to the first Object (a TranMap).
210 * that
211 * Pointer to the second Object.
212 * status
213 * Pointer to the inherited status variable.
214
215 * Returned Value:
216 * One if the TranMaps are equivalent, zero otherwise.
217
218 * Notes:
219 * - A value of zero will be returned if this function is invoked
220 * with the global status set, or if it should fail for any reason.
221 */
222
223 /* Local Variables: */
224 AstTranMap *that;
225 AstTranMap *this;
226 int nin;
227 int nout;
228 int result;
229 int that_inv1;
230 int that_inv2;
231 int this_inv1;
232 int this_inv2;
233
234 /* Initialise. */
235 result = 0;
236
237 /* Check the global error status. */
238 if ( !astOK ) return result;
239
240 /* Obtain pointers to the two TranMap structures. */
241 this = (AstTranMap *) this_object;
242 that = (AstTranMap *) that_object;
243
244 /* Check the second object is a TranMap. We know the first is a
245 TranMap since we have arrived at this implementation of the virtual
246 function. */
247 if( astIsATranMap( that ) ) {
248
249 /* Get the number of inputs and outputs and check they are the same for both. */
250 nin = astGetNin( this );
251 nout = astGetNout( this );
252 if( astGetNin( that ) == nin && astGetNout( that ) == nout ) {
253
254 /* Temporarily re-instate the original Invert flag values. */
255 that_inv1 = astGetInvert( that->map1 );
256 that_inv2 = astGetInvert( that->map2 );
257 this_inv1 = astGetInvert( this->map1 );
258 this_inv2 = astGetInvert( this->map2 );
259
260 astSetInvert( this->map1, this->invert1 );
261 astSetInvert( this->map2, this->invert2 );
262 astSetInvert( that->map1, that->invert1 );
263 astSetInvert( that->map2, that->invert2 );
264
265 /* If the Invert flags for the two TranMaps differ, it may still be possible
266 for them to be equivalent. First compare the TranMaps if their Invert
267 flags are the same. In this case all the attributes of the two TranMaps
268 must be identical. */
269 if( astGetInvert( this ) == astGetInvert( that ) ) {
270 if( astEqual( this->map1, that->map1 ) &&
271 astEqual( this->map2, that->map2 ) ) {
272 result = 1;
273 }
274
275 /* If the Invert flags for the two TranMaps differ, the attributes of the two
276 TranMaps must be inversely related to each other. */
277 } else {
278
279 astInvert( that->map1 );
280 astInvert( that->map2 );
281
282 if( astEqual( this->map1, that->map2 ) &&
283 astEqual( this->map2, that->map1 ) ) {
284 result = 1;
285 }
286
287 }
288
289 /* Restore the original Invert flag values. */
290 astSetInvert( this->map1, this_inv1 );
291 astSetInvert( this->map2, this_inv2 );
292 astSetInvert( that->map1, that_inv1 );
293 astSetInvert( that->map2, that_inv2 );
294 }
295 }
296
297 /* If an error occurred, clear the result value. */
298 if ( !astOK ) result = 0;
299
300 /* Return the result, */
301 return result;
302 }
303
GetObjSize(AstObject * this_object,int * status)304 static int GetObjSize( AstObject *this_object, int *status ) {
305 /*
306 * Name:
307 * GetObjSize
308
309 * Purpose:
310 * Return the in-memory size of an Object.
311
312 * Type:
313 * Private function.
314
315 * Synopsis:
316 * #include "tranmap.h"
317 * int GetObjSize( AstObject *this, int *status )
318
319 * Class Membership:
320 * TranMap member function (over-rides the astGetObjSize protected
321 * method inherited from the parent class).
322
323 * Description:
324 * This function returns the in-memory size of the supplied TranMap,
325 * in bytes.
326
327 * Parameters:
328 * this
329 * Pointer to the TranMap.
330 * status
331 * Pointer to the inherited status variable.
332
333 * Returned Value:
334 * The Object size, in bytes.
335
336 * Notes:
337 * - A value of zero will be returned if this function is invoked
338 * with the global status set, or if it should fail for any reason.
339 */
340
341 /* Local Variables: */
342 AstTranMap *this; /* Pointer to TranMap structure */
343 int result; /* Result value to return */
344
345 /* Initialise. */
346 result = 0;
347
348 /* Check the global error status. */
349 if ( !astOK ) return result;
350
351 /* Obtain a pointers to the TranMap structure. */
352 this = (AstTranMap *) this_object;
353
354 /* Invoke the GetObjSize method inherited from the parent class, and then
355 add on any components of the class structure defined by thsi class
356 which are stored in dynamically allocated memory. */
357 result = (*parent_getobjsize)( this_object, status );
358 result += astGetObjSize( this->map1 );
359 result += astGetObjSize( this->map2 );
360
361 /* If an error occurred, clear the result value. */
362 if ( !astOK ) result = 0;
363
364 /* Return the result, */
365 return result;
366 }
367
Decompose(AstMapping * this_mapping,AstMapping ** map1,AstMapping ** map2,int * series,int * invert1,int * invert2,int * status)368 static void Decompose( AstMapping *this_mapping, AstMapping **map1,
369 AstMapping **map2, int *series, int *invert1,
370 int *invert2, int *status ) {
371 /*
372 *
373 * Name:
374 * Decompose
375
376 * Purpose:
377 * Decompose a Mapping into two component Mappings.
378
379 * Type:
380 * Private function.
381
382 * Synopsis:
383 * #include "tranmap.h"
384 * void Decompose( AstMapping *this, AstMapping **map1,
385 * AstMapping **map2, int *series,
386 * int *invert1, int *invert2, int *status )
387
388 * Class Membership:
389 * TranMap member function (over-rides the protected astDecompose
390 * method inherited from the Mapping class).
391
392 * Description:
393 * This function returns pointers to the two Mappings encapsulated by
394 * a TranMap.
395
396 * Parameters:
397 * this
398 * Pointer to the Mapping.
399 * map1
400 * Address of a location to receive a pointer to first component
401 * Mapping (the forward Mapping).
402 * map2
403 * Address of a location to receive a pointer to second component
404 * Mapping (the inverse Mapping).
405 * series
406 * Address of a location to receive a value indicating if the
407 * component Mappings are applied in series or parallel. A non-zero
408 * value means that the supplied Mapping is equivalent to applying map1
409 * followed by map2 in series. A zero value means that the supplied
410 * Mapping is equivalent to applying map1 to the lower numbered axes
411 * and map2 to the higher numbered axes, in parallel. Zero is
412 * returned for a TranMap.
413 * invert1
414 * The value of the Invert attribute to be used with map1.
415 * invert2
416 * The value of the Invert attribute to be used with map2.
417 * status
418 * Pointer to the inherited status variable.
419
420 * Notes:
421 * - Any changes made to the component Mappings using the returned
422 * pointers will be reflected in the supplied Mapping.
423
424 *-
425 */
426
427
428 /* Local Variables: */
429 AstTranMap *this; /* Pointer to TranMap structure */
430
431 /* Check the global error status. */
432 if ( !astOK ) return;
433
434 /* Obtain a pointer to the TranMap structure. */
435 this = (AstTranMap *) this_mapping;
436
437 /* If the TranMap has been inverted, return the Mappings in reverse
438 order with inverted Invert falgs. */
439 if( astGetInvert( this ) ) {
440 if( map1 ) *map1 = astClone( this->map2 );
441 if( map2 ) *map2 = astClone( this->map1 );
442 if( invert1 ) *invert1 = this->invert2 ? 0 : 1;
443 if( invert2 ) *invert2 = this->invert1 ? 0 : 1;
444
445 /* If the TranMap has not been inverted, return the Mappings in their
446 original order with their original Invert flags. */
447 } else {
448 if( map1 ) *map1 = astClone( this->map1 );
449 if( map2 ) *map2 = astClone( this->map2 );
450 if( invert1 ) *invert1 = this->invert1;
451 if( invert2 ) *invert2 = this->invert2;
452 }
453 }
454
astInitTranMapVtab_(AstTranMapVtab * vtab,const char * name,int * status)455 void astInitTranMapVtab_( AstTranMapVtab *vtab, const char *name, int *status ) {
456 /*
457 *+
458 * Name:
459 * astInitTranMapVtab
460
461 * Purpose:
462 * Initialise a virtual function table for a TranMap.
463
464 * Type:
465 * Protected function.
466
467 * Synopsis:
468 * #include "tranmap.h"
469 * void astInitTranMapVtab( AstTranMapVtab *vtab, const char *name )
470
471 * Class Membership:
472 * TranMap vtab initialiser.
473
474 * Description:
475 * This function initialises the component of a virtual function
476 * table which is used by the TranMap class.
477
478 * Parameters:
479 * vtab
480 * Pointer to the virtual function table. The components used by
481 * all ancestral classes will be initialised if they have not already
482 * been initialised.
483 * name
484 * Pointer to a constant null-terminated character string which contains
485 * the name of the class to which the virtual function table belongs (it
486 * is this pointer value that will subsequently be returned by the Object
487 * astClass function).
488 *-
489 */
490
491 /* Local Variables: */
492 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
493 AstObjectVtab *object; /* Pointer to Object component of Vtab */
494 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
495
496 /* Check the local error status. */
497 if ( !astOK ) return;
498
499 /* Get a pointer to the thread specific global data structure. */
500 astGET_GLOBALS(NULL);
501
502 /* Initialize the component of the virtual function table used by the
503 parent class. */
504 astInitMappingVtab( (AstMappingVtab *) vtab, name );
505
506 /* Store a unique "magic" value in the virtual function table. This
507 will be used (by astIsATranMap) to determine if an object belongs to
508 this class. We can conveniently use the address of the (static)
509 class_check variable to generate this unique value. */
510 vtab->id.check = &class_check;
511 vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
512
513 /* Initialise member function pointers. */
514 /* ------------------------------------ */
515 /* Store pointers to the member functions (implemented here) that
516 provide virtual methods for this class. */
517
518 /* None. */
519
520 /* Save the inherited pointers to methods that will be extended, and
521 replace them with pointers to the new member functions. */
522 object = (AstObjectVtab *) vtab;
523 mapping = (AstMappingVtab *) vtab;
524 parent_getobjsize = object->GetObjSize;
525 object->GetObjSize = GetObjSize;
526
527 mapping->RemoveRegions = RemoveRegions;
528
529 #if defined(THREAD_SAFE)
530 parent_managelock = object->ManageLock;
531 object->ManageLock = ManageLock;
532 #endif
533
534 parent_transform = mapping->Transform;
535 mapping->Transform = Transform;
536
537 parent_mapsplit = mapping->MapSplit;
538 mapping->MapSplit = MapSplit;
539
540 /* Store replacement pointers for methods which will be over-ridden by
541 new member functions implemented here. */
542 object->Equal = Equal;
543 mapping->Decompose = Decompose;
544 mapping->MapMerge = MapMerge;
545 mapping->Rate = Rate;
546
547 /* Declare the copy constructor, destructor and class dump function. */
548 astSetCopy( vtab, Copy );
549 astSetDelete( vtab, Delete );
550 astSetDump( vtab, Dump, "TranMap", "Compound Transformation Mapping" );
551
552 /* If we have just initialised the vtab for the current class, indicate
553 that the vtab is now initialised, and store a pointer to the class
554 identifier in the base "object" level of the vtab. */
555 if( vtab == &class_vtab ) {
556 class_init = 1;
557 astSetVtabClassIdentifier( vtab, &(vtab->id) );
558 }
559 }
560
561 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)562 static int ManageLock( AstObject *this_object, int mode, int extra,
563 AstObject **fail, int *status ) {
564 /*
565 * Name:
566 * ManageLock
567
568 * Purpose:
569 * Manage the thread lock on an Object.
570
571 * Type:
572 * Private function.
573
574 * Synopsis:
575 * #include "object.h"
576 * AstObject *ManageLock( AstObject *this, int mode, int extra,
577 * AstObject **fail, int *status )
578
579 * Class Membership:
580 * TranMap member function (over-rides the astManageLock protected
581 * method inherited from the parent class).
582
583 * Description:
584 * This function manages the thread lock on the supplied Object. The
585 * lock can be locked, unlocked or checked by this function as
586 * deteremined by parameter "mode". See astLock for details of the way
587 * these locks are used.
588
589 * Parameters:
590 * this
591 * Pointer to the Object.
592 * mode
593 * An integer flag indicating what the function should do:
594 *
595 * AST__LOCK: Lock the Object for exclusive use by the calling
596 * thread. The "extra" value indicates what should be done if the
597 * Object is already locked (wait or report an error - see astLock).
598 *
599 * AST__UNLOCK: Unlock the Object for use by other threads.
600 *
601 * AST__CHECKLOCK: Check that the object is locked for use by the
602 * calling thread (report an error if not).
603 * extra
604 * Extra mode-specific information.
605 * fail
606 * If a non-zero function value is returned, a pointer to the
607 * Object that caused the failure is returned at "*fail". This may
608 * be "this" or it may be an Object contained within "this". Note,
609 * the Object's reference count is not incremented, and so the
610 * returned pointer should not be annulled. A NULL pointer is
611 * returned if this function returns a value of zero.
612 * status
613 * Pointer to the inherited status variable.
614
615 * Returned Value:
616 * A local status value:
617 * 0 - Success
618 * 1 - Could not lock or unlock the object because it was already
619 * locked by another thread.
620 * 2 - Failed to lock a POSIX mutex
621 * 3 - Failed to unlock a POSIX mutex
622 * 4 - Bad "mode" value supplied.
623
624 * Notes:
625 * - This function attempts to execute even if an error has already
626 * occurred.
627 */
628
629 /* Local Variables: */
630 AstTranMap *this; /* Pointer to TranMap structure */
631 int result; /* Returned status value */
632
633 /* Initialise */
634 result = 0;
635
636 /* Check the supplied pointer is not NULL. */
637 if( !this_object ) return result;
638
639 /* Obtain a pointers to the TranMap structure. */
640 this = (AstTranMap *) this_object;
641
642 /* Invoke the ManageLock method inherited from the parent class. */
643 if( !result ) result = (*parent_managelock)( this_object, mode, extra,
644 fail, status );
645
646 /* Invoke the astManageLock method on any Objects contained within
647 the supplied Object. */
648 if( !result ) result = astManageLock( this->map1, mode, extra, fail );
649 if( !result ) result = astManageLock( this->map2, mode, extra, fail );
650
651 return result;
652
653 }
654 #endif
655
MapMerge(AstMapping * this,int where,int series,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)656 static int MapMerge( AstMapping *this, int where, int series, int *nmap,
657 AstMapping ***map_list, int **invert_list, int *status ) {
658 /*
659 * Name:
660 * MapMerge
661
662 * Purpose:
663 * Simplify a sequence of Mappings containing a TranMap.
664
665 * Type:
666 * Private function.
667
668 * Synopsis:
669 * #include "mapping.h"
670 * int MapMerge( AstMapping *this, int where, int series, int *nmap,
671 * AstMapping ***map_list, int **invert_list, int *status )
672
673 * Class Membership:
674 * TranMap method (over-rides the protected astMapMerge method
675 * inherited from the Mapping class).
676
677 * Description:
678 * This function attempts to simplify a sequence of Mappings by
679 * merging a nominated TranMap in the sequence with its neighbours,
680 * so as to shorten the sequence if possible.
681 *
682 * In many cases, simplification will not be possible and the
683 * function will return -1 to indicate this, without further
684 * action.
685 *
686 * In most cases of interest, however, this function will either
687 * attempt to replace the nominated TranMap with one which it
688 * considers simpler, or to merge it with the Mappings which
689 * immediately precede it or follow it in the sequence (both will
690 * normally be considered). This is sufficient to ensure the
691 * eventual simplification of most Mapping sequences by repeated
692 * application of this function.
693 *
694 * In some cases, the function may attempt more elaborate
695 * simplification, involving any number of other Mappings in the
696 * sequence. It is not restricted in the type or scope of
697 * simplification it may perform, but will normally only attempt
698 * elaborate simplification in cases where a more straightforward
699 * approach is not adequate.
700
701 * Parameters:
702 * this
703 * Pointer to the nominated TranMap which is to be merged with
704 * its neighbours. This should be a cloned copy of the TranMap
705 * pointer contained in the array element "(*map_list)[where]"
706 * (see below). This pointer will not be annulled, and the
707 * TranMap it identifies will not be modified by this function.
708 * where
709 * Index in the "*map_list" array (below) at which the pointer
710 * to the nominated TranMap resides.
711 * series
712 * A non-zero value indicates that the sequence of Mappings to
713 * be simplified will be applied in series (i.e. one after the
714 * other), whereas a zero value indicates that they will be
715 * applied in parallel (i.e. on successive sub-sets of the
716 * input/output coordinates).
717 * nmap
718 * Address of an int which counts the number of Mappings in the
719 * sequence. On entry this should be set to the initial number
720 * of Mappings. On exit it will be updated to record the number
721 * of Mappings remaining after simplification.
722 * map_list
723 * Address of a pointer to a dynamically allocated array of
724 * Mapping pointers (produced, for example, by the astMapList
725 * method) which identifies the sequence of Mappings. On entry,
726 * the initial sequence of Mappings to be simplified should be
727 * supplied.
728 *
729 * On exit, the contents of this array will be modified to
730 * reflect any simplification carried out. Any form of
731 * simplification may be performed. This may involve any of: (a)
732 * removing Mappings by annulling any of the pointers supplied,
733 * (b) replacing them with pointers to new Mappings, (c)
734 * inserting additional Mappings and (d) changing their order.
735 *
736 * The intention is to reduce the number of Mappings in the
737 * sequence, if possible, and any reduction will be reflected in
738 * the value of "*nmap" returned. However, simplifications which
739 * do not reduce the length of the sequence (but improve its
740 * execution time, for example) may also be performed, and the
741 * sequence might conceivably increase in length (but normally
742 * only in order to split up a Mapping into pieces that can be
743 * more easily merged with their neighbours on subsequent
744 * invocations of this function).
745 *
746 * If Mappings are removed from the sequence, any gaps that
747 * remain will be closed up, by moving subsequent Mapping
748 * pointers along in the array, so that vacated elements occur
749 * at the end. If the sequence increases in length, the array
750 * will be extended (and its pointer updated) if necessary to
751 * accommodate any new elements.
752 *
753 * Note that any (or all) of the Mapping pointers supplied in
754 * this array may be annulled by this function, but the Mappings
755 * to which they refer are not modified in any way (although
756 * they may, of course, be deleted if the annulled pointer is
757 * the final one).
758 * invert_list
759 * Address of a pointer to a dynamically allocated array which,
760 * on entry, should contain values to be assigned to the Invert
761 * attributes of the Mappings identified in the "*map_list"
762 * array before they are applied (this array might have been
763 * produced, for example, by the astMapList method). These
764 * values will be used by this function instead of the actual
765 * Invert attributes of the Mappings supplied, which are
766 * ignored.
767 *
768 * On exit, the contents of this array will be updated to
769 * correspond with the possibly modified contents of the
770 * "*map_list" array. If the Mapping sequence increases in
771 * length, the "*invert_list" array will be extended (and its
772 * pointer updated) if necessary to accommodate any new
773 * elements.
774 * status
775 * Pointer to the inherited status variable.
776
777 * Returned Value:
778 * If simplification was possible, the function returns the index
779 * in the "map_list" array of the first element which was
780 * modified. Otherwise, it returns -1 (and makes no changes to the
781 * arrays supplied).
782
783 * Notes:
784 * - A value of -1 will be returned if this function is invoked
785 * with the global error status set, or if it should fail for any
786 * reason.
787 */
788
789 /* Local Variables: */
790 AstCmpMap *cmap; /* Pointer to compound Mapping */
791 AstMapping *cmap_f; /* Pointer to compound Mapping */
792 AstMapping *cmap_i; /* Pointer to compound Mapping */
793 AstMapping *hmap1; /* Pointer to 1st comp of higher TranMap */
794 AstMapping *hmap2; /* Pointer to 2nd comp of higher TranMap */
795 AstMapping *hmap_f; /* Pointer to fwd Mapping of higher TranMap */
796 AstMapping *hmap_i; /* Pointer to inv Mapping of higher TranMap */
797 AstMapping *map1; /* Pointer to 1st comp of nominated TranMap */
798 AstMapping *map2; /* Pointer to 2nd comp of nominated TranMap */
799 AstMapping *map_f; /* Pointer to fwd Mapping of nominated TranMap */
800 AstMapping *map_i; /* Pointer to inv Mapping of nominated TranMap */
801 AstMapping *smap; /* Pointer to simplified Mapping */
802 AstMapping *smap_f; /* Pointer to simplified Mapping */
803 AstMapping *smap_i; /* Pointer to simplified Mapping */
804 AstTranMap *hmap; /* Pointer to higher TranMap */
805 AstTranMap *map; /* Pointer to this TranMap */
806 AstTranMap *new; /* Pointer to merged TranMap */
807 int i; /* Loop count */
808 int old_hinv1; /* Original Invert flag for hmap->map1 */
809 int old_hinv2; /* Original Invert flag for hmap->map2 */
810 int old_inv1; /* Original Invert flag for this->map1 */
811 int old_inv2; /* Original Invert flag for this->map2 */
812 int result; /* The value to return */
813
814 /* Initialise.*/
815 result = -1;
816
817 /* Check the inherited status. */
818 if ( !astOK ) return result;
819
820 /* Get a pointer to this TranMap. */
821 map = (AstTranMap *) this;
822
823 /* Get the two component Mappings,and temporarily set their Invert
824 attributes back to the values they had when the TranMap was created,
825 saving their current Invert values so that they can be re-instated later. */
826 map1 = map->map1;
827 old_inv1 = astGetInvert( map1 );
828 astSetInvert( map1, map->invert1 );
829
830 map2 = map->map2;
831 old_inv2 = astGetInvert( map2 );
832 astSetInvert( map2, map->invert2 );
833
834 /* Simplify the TranMap on its own. */
835 /* ================================ */
836
837 /* If the TranMap is inverted, creat an equal TranMap which is not inverted.
838 To do this, invert and swap the component Mappings. */
839 if( ( *invert_list )[ where ] ) {
840 astInvert( map1 );
841 astInvert( map2 );
842 new = astTranMap( map2, map1, "", status );
843 astInvert( map1 );
844 astInvert( map2 );
845
846 (void) astAnnul( ( *map_list )[ where ] );
847 ( *map_list )[ where ] = (AstMapping *) new;
848 ( *invert_list )[ where ] = 0;
849 result = where;
850
851 /* Otherwise, try to simplify each of the component Mappings. */
852 } else {
853 smap_f = astSimplify( map1 );
854 smap_i = astSimplify( map2 );
855
856 /* Assume some simplification took place if the pointers have changed. */
857 if( smap_f != map1 || smap_i != map2 ) {
858
859 /* Construct a new TranMap from these simplifgied Mappings. */
860 (void) astAnnul( ( *map_list )[ where ] );
861 ( *map_list )[ where ] = (AstMapping *) astTranMap( smap_f, smap_i, "", status );
862 result = where;
863
864 /* Otherwise, if the both component Mappings are defined in both directions... */
865 } else if( astGetTranForward( map1 ) && astGetTranInverse( map1 ) &&
866 astGetTranForward( map2 ) && astGetTranInverse( map2 ) ) {
867
868 /* Form a series CmpMap from the two component Mappings, with the second
869 Mapping inverted. */
870 astInvert( map2 );
871 cmap = astCmpMap( map1, map2, 1, "", status );
872 astInvert( map2 );
873
874 /* If this CmpMap simplifies to a UnitMap, then the two components of the
875 TranMap are equal, and so we can replace the entire TranMap with either
876 of its components. Note, we leave the supplied invert flag unchanged,
877 since the copycreated below refers to the Mapping as it was when the
878 TranMap was created. However, we invert the returned Mapping if
879 necessary. */
880 smap = astSimplify( cmap );
881 if( astIsAUnitMap( smap ) ) {
882 (void) astAnnul( ( *map_list )[ where ] );
883 ( *map_list )[ where ] = astCopy( map1 );
884 if( ( *invert_list )[ where ] ) astInvert( ( *map_list )[ where ] );
885 result = where;
886 }
887
888 /* Release resources. */
889 smap = astAnnul( smap );
890 cmap = astAnnul( cmap );
891 }
892
893 /* Release resources. */
894 smap_f = astAnnul( smap_f );
895 smap_i = astAnnul( smap_i );
896 }
897
898 /* Merge the TranMap with a neighbouring TranMap. */
899 /* ============================================== */
900 /* Only do this if no change was made above, and we are combining the
901 Mappings in series. */
902 if( result == -1 && series ) {
903
904 /* Is the higher neighbour a TranMap? */
905 if( where < ( *nmap - 1 ) &&
906 astIsATranMap( ( *map_list )[ where + 1 ] ) ){
907
908 /* Get the two component Mappings of the higher TranMap, and temporarily set
909 their Invert attributes back to the values they had when the TranMap was
910 created, saving their current Invert values so that they can be re-instated
911 later. */
912 hmap = (AstTranMap *) ( *map_list )[ where + 1 ];
913
914 hmap1 = hmap->map1;
915 old_hinv1 = astGetInvert( hmap1 );
916 astSetInvert( hmap1, hmap->invert1 );
917
918 hmap2 = hmap->map2;
919 old_hinv2 = astGetInvert( hmap2 );
920 astSetInvert( hmap2, hmap->invert2 );
921
922 /* Get the Mappings which defines the forward and inverse transformation of
923 the lower TranMap ("this"). Then, map_f and map_i are pointers to
924 Mappings which could be used to construct a new TranMap which would be
925 equivalent to "this" with the supplied invert setting. */
926 if( ( *invert_list )[ where ] ) {
927 map_f = map2;
928 map_i = map1;
929 astInvert( map_f );
930 astInvert( map_i );
931 } else {
932 map_f = map1;
933 map_i = map2;
934 }
935
936 /* Likewise, get the Mappings which defines the forward and inverse
937 transformation of the higher TranMap. */
938 if( ( *invert_list )[ where + 1 ] ) {
939 hmap_f = hmap2;
940 hmap_i = hmap1;
941 astInvert( hmap_f );
942 astInvert( hmap_i );
943 } else {
944 hmap_f = hmap1;
945 hmap_i = hmap2;
946 }
947
948 /* Combine the two forward Mappings together into a series CmpMap, and
949 simplify it. */
950 cmap_f = (AstMapping *) astCmpMap( map_f, hmap_f, 1, "", status );
951 smap_f = astSimplify( cmap_f );
952
953 /* Do the same for the inverse Mappings */
954 cmap_i = (AstMapping *) astCmpMap( map_i, hmap_i, 1, "", status );
955 smap_i = astSimplify( cmap_i );
956
957 /* Was any simplification performed? We assume this is the case if the
958 either of the simplied pointer differs from the original pointer. */
959 if( cmap_f != smap_f || cmap_i != smap_i ) {
960
961 /* In which case,construct a new TranMap from the simplified Mappings. */
962 new = astTranMap( smap_f, smap_i, "", status );
963
964 } else {
965 new = NULL;
966 }
967
968 /* Free resources.*/
969 cmap_f = astAnnul( cmap_f );
970 smap_f = astAnnul( smap_f );
971 cmap_i = astAnnul( cmap_i );
972 smap_i = astAnnul( smap_i );
973
974 /* Re-instate the original Invert values for the component Mappings of
975 the higher TranMap. */
976 astSetInvert( hmap1, old_hinv1 );
977 astSetInvert( hmap2, old_hinv2 );
978
979 /* If we have a new TranMap, annul the first of the two Mappings, and replace
980 it with the merged TranMap. Also set the invert flag. */
981 if( new ) {
982 (void) astAnnul( ( *map_list )[ where ] );
983 ( *map_list )[ where ] = (AstMapping *) new;
984 ( *invert_list )[ where ] = 0;
985
986 /* Annul the second of the two Mappings, and shuffle down the rest of the
987 list to fill the gap. */
988 (void) astAnnul( ( *map_list )[ where + 1 ] );
989 for ( i = where + 2; i < *nmap; i++ ) {
990 ( *map_list )[ i - 1 ] = ( *map_list )[ i ];
991 ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ];
992 }
993
994 /* Clear the vacated element at the end. */
995 ( *map_list )[ *nmap - 1 ] = NULL;
996 ( *invert_list )[ *nmap - 1 ] = 0;
997
998 /* Decrement the Mapping count and return the index of the first
999 modified element. */
1000 ( *nmap )--;
1001 result = where;
1002 }
1003 }
1004 }
1005
1006 /* Re-instate the original Invert values for the component Mappings. */
1007 astSetInvert( map1, old_inv1 );
1008 astSetInvert( map2, old_inv2 );
1009
1010 /* If an error occurred, clear the result value. */
1011 if ( !astOK ) result = -1;
1012
1013 /* Return the result. */
1014 return result;
1015 }
1016
MapSplit(AstMapping * this_map,int nin,const int * in,AstMapping ** map,int * status)1017 static int *MapSplit( AstMapping *this_map, int nin, const int *in, AstMapping **map, int *status ){
1018 /*
1019 * Name:
1020 * MapSplit
1021
1022 * Purpose:
1023 * Create a Mapping representing a subset of the inputs of an existing
1024 * TranMap.
1025
1026 * Type:
1027 * Private function.
1028
1029 * Synopsis:
1030 * #include "tranmap.h"
1031 * int *MapSplit( AstMapping *this, int nin, const int *in, AstMapping **map, int *status )
1032
1033 * Class Membership:
1034 * TranMap method (over-rides the protected astMapSplit method
1035 * inherited from the Mapping class).
1036
1037 * Description:
1038 * This function creates a new Mapping by picking specified inputs from
1039 * an existing TranMap. This is only possible if the specified inputs
1040 * correspond to some subset of the TranMap outputs. That is, there
1041 * must exist a subset of the TranMap outputs for which each output
1042 * depends only on the selected TranMap inputs, and not on any of the
1043 * inputs which have not been selected. If this condition is not met
1044 * by the supplied TranMap, then a NULL Mapping is returned.
1045
1046 * Parameters:
1047 * this
1048 * Pointer to the TranMap to be split (the TranMap is not actually
1049 * modified by this function).
1050 * nin
1051 * The number of inputs to pick from "this".
1052 * in
1053 * Pointer to an array of indices (zero based) for the inputs which
1054 * are to be picked. This array should have "nin" elements. If "Nin"
1055 * is the number of inputs of the supplied TranMap, then each element
1056 * should have a value in the range zero to Nin-1.
1057 * map
1058 * Address of a location at which to return a pointer to the new
1059 * Mapping. This Mapping will have "nin" inputs (the number of
1060 * outputs may be different to "nin"). A NULL pointer will be
1061 * returned if the supplied TranMap has no subset of outputs which
1062 * depend only on the selected inputs.
1063 * status
1064 * Pointer to the inherited status variable.
1065
1066 * Returned Value:
1067 * A pointer to a dynamically allocated array of ints. The number of
1068 * elements in this array will equal the number of outputs for the
1069 * returned Mapping. Each element will hold the index of the
1070 * corresponding output in the supplied TranMap. The array should be
1071 * freed using astFree when no longer needed. A NULL pointer will
1072 * be returned if no output Mapping can be created.
1073
1074 * Notes:
1075 * - If this function is invoked with the global error status set,
1076 * or if it should fail for any reason, then NULL values will be
1077 * returned as the function value and for the "map" pointer.
1078 */
1079
1080 /* Local Variables: */
1081 AstMapping *fmap; /* Pointer to forward Mapping in supplied TranMap */
1082 AstMapping *imap; /* Pointer to inverse Mapping in supplied TranMap */
1083 AstMapping *rfmap; /* Pointer to split forward Mapping */
1084 AstMapping *rimap; /* Pointer to split inverse Mapping */
1085 AstTranMap *this; /* Pointer to TranMap structure */
1086 int *ires; /* I/ps of inv Mapping dependent on selected o/ps */
1087 int *out; /* O/ps of fwd Mapping dependent on selected i/ps */
1088 int *result; /* Pointer to returned array */
1089 int finv; /* Invert flag to use with fmap */
1090 int i; /* Loop count */
1091 int iinv; /* Invert flag to use with imap */
1092 int nout; /* No. of outputs dependent on selected inputs */
1093 int ok; /* Can required Mapping be created? */
1094 int old_finv; /* Original Invert flag for fmap */
1095 int old_iinv; /* Original Invert flag for imap */
1096
1097 /* Initialise */
1098 result = NULL;
1099 *map = NULL;
1100
1101 /* Check the global error status. */
1102 if ( !astOK ) return result;
1103
1104 /* Invoke the parent astMapSplit method to see if it can do the job. */
1105 result = (*parent_mapsplit)( this_map, nin, in, map, status );
1106
1107 /* If not, we provide a special implementation here. */
1108 if( !result ) {
1109
1110 /* Get a pointer to the TranMap structure. */
1111 this = (AstTranMap *) this_map;
1112
1113 /* Get pointers to the forward and inverse Mappings, taking into account
1114 whether the TranMap has been inverted. */
1115 if( !astGetInvert( this ) ) {
1116 fmap = this->map1;
1117 finv = this->invert1;
1118 imap = this->map2;
1119 iinv = this->invert2;
1120 } else {
1121 imap = this->map1;
1122 iinv = !( this->invert1 );
1123 fmap = this->map2;
1124 finv = !( this->invert2 );
1125 }
1126
1127 /* Temporarily set the Invert flag of both Mappings back to their
1128 original values. */
1129 old_finv = astGetInvert( fmap );
1130 astSetInvert( fmap, finv );
1131 old_iinv = astGetInvert( imap );
1132 astSetInvert( imap, iinv );
1133
1134 /* Try to split the forward Mapping. */
1135 out = astMapSplit( fmap, nin, in, &rfmap );
1136
1137 /* Check the split could be done. */
1138 if( out ) {
1139
1140 /* Get the number of outputs which are fed by the selected inputs. */
1141 nout = astGetNout( rfmap );
1142
1143 /* See if the inverse Mapping can be split using these outputs as inputs. */
1144 astInvert( imap );
1145 ires = astMapSplit( imap, nout, out, &rimap );
1146 astInvert( imap );
1147 if( ires ) {
1148 astInvert( rimap );
1149
1150 /* Check that the resulting inputs are the same as the supplied inputs. */
1151 if( astGetNin( rimap ) == nin ) {
1152 ok = 1;
1153 for( i = 0; i < nin; i++ ) {
1154 if( in[ i ] != ires[ i ] ) {
1155 ok = 0;
1156 break;
1157 }
1158 }
1159
1160 /* If so create the required new TranMap. */
1161 if( ok ) {
1162 *map = (AstMapping *) astTranMap( rfmap, rimap, "", status );
1163 result = out;
1164 }
1165 }
1166
1167 /* Free resources. */
1168 ires = astFree( ires );
1169 rimap = astAnnul( rimap );
1170 }
1171
1172 if( !result ) out = astFree( out );
1173 rfmap = astAnnul( rfmap );
1174 }
1175
1176 /* Re-instate the Invert flags of the component Mappings. */
1177 astSetInvert( fmap, old_finv );
1178 astSetInvert( imap, old_iinv );
1179 }
1180
1181 /* Free returned resources if an error has occurred. */
1182 if( !astOK ) {
1183 result = astFree( result );
1184 *map = astAnnul( *map );
1185 }
1186
1187 /* Return the list of output indices. */
1188 return result;
1189 }
1190
Rate(AstMapping * this,double * at,int ax1,int ax2,int * status)1191 static double Rate( AstMapping *this, double *at, int ax1, int ax2, int *status ){
1192 /*
1193 * Name:
1194 * Rate
1195
1196 * Purpose:
1197 * Calculate the rate of change of a Mapping output.
1198
1199 * Type:
1200 * Private function.
1201
1202 * Synopsis:
1203 * #include "tranmap.h"
1204 * result = Rate( AstMapping *this, double *at, int ax1, int ax2, int *status )
1205
1206 * Class Membership:
1207 * TranMap member function (overrides the astRate method inherited
1208 * from the Mapping class ).
1209
1210 * Description:
1211 * This function returns the rate of change of a specified output of
1212 * the supplied Mapping with respect to a specified input, at a
1213 * specified input position. Also evaluates the second derivative.
1214
1215 * Parameters:
1216 * this
1217 * Pointer to the Mapping to be applied.
1218 * at
1219 * The address of an array holding the axis values at the position
1220 * at which the rate of change is to be evaluated. The number of
1221 * elements in this array should equal the number of inputs to the
1222 * Mapping.
1223 * ax1
1224 * The index of the Mapping output for which the rate of change is to
1225 * be found (output numbering starts at 0 for the first output).
1226 * ax2
1227 * The index of the Mapping input which is to be varied in order to
1228 * find the rate of change (input numbering starts at 0 for the first
1229 * input).
1230 * status
1231 * Pointer to the inherited status variable.
1232
1233 * Returned Value:
1234 * The rate of change of Mapping output "ax1" with respect to input
1235 * "ax2", evaluated at "at", or AST__BAD if the value cannot be
1236 * calculated.
1237
1238 */
1239
1240 /* Local Variables: */
1241 AstTranMap *map;
1242 AstMapping *cmap;
1243 double result;
1244 int cinv;
1245 int old_inv;
1246
1247 /* Check inherited status */
1248 if( !astOK ) return AST__BAD;
1249
1250 /* Get a pointer to the TranMap structure. */
1251 map = (AstTranMap *) this;
1252
1253 /* Choose the component Mapping to use, and get its original Invert
1254 value. Invert this if the TranMap itself has been inverted (this is
1255 because the astRate function has no "invert" argument so we need to
1256 invert the Mapping before calling astRate). */
1257 if( astGetInvert( this ) ) {
1258 cmap = map->map2;
1259 cinv = !(map->invert2);
1260 } else {
1261 cmap = map->map1;
1262 cinv = map->invert1;
1263 }
1264
1265 /* Temporarily set the Invert flag of the component Mapping back to its
1266 original value. */
1267 old_inv = astGetInvert( cmap );
1268 astSetInvert( cmap, cinv );
1269
1270 /* Use the astRate method of the component Mapping. */
1271 result = astRate( cmap, at, ax1, ax2 );
1272
1273 /* Re-instate the Invert flag of the component Mapping. */
1274 astSetInvert( cmap, old_inv );
1275
1276 /* Return the result. */
1277 return result;
1278 }
1279
RemoveRegions(AstMapping * this_mapping,int * status)1280 static AstMapping *RemoveRegions( AstMapping *this_mapping, int *status ) {
1281 /*
1282 * Name:
1283 * RemoveRegions
1284
1285 * Purpose:
1286 * Remove any Regions from a Mapping.
1287
1288 * Type:
1289 * Private function.
1290
1291 * Synopsis:
1292 * #include "tranmap.h"
1293 * AstMapping *RemoveRegions( AstMapping *this, int *status )
1294
1295 * Class Membership:
1296 * TranMap method (over-rides the astRemoveRegions method inherited
1297 * from the Mapping class).
1298
1299 * Description:
1300 * This function searches the supplied Mapping (which may be a
1301 * compound Mapping such as a TranMap) for any component Mappings
1302 * that are instances of the AST Region class. It then creates a new
1303 * Mapping from which all Regions have been removed. If a Region
1304 * cannot simply be removed (for instance, if it is a component of a
1305 * parallel TranMap), then it is replaced with an equivalent UnitMap
1306 * in the returned Mapping.
1307 *
1308 * The implementation provided by the TranMap class invokes the
1309 * astRemoveRegions method on the two component Mappings, and joins
1310 * the results together into a new TranMap.
1311
1312 * Parameters:
1313 * this
1314 * Pointer to the original Region.
1315 * status
1316 * Pointer to the inherited status variable.
1317
1318 * Returned Value:
1319 * A pointer to the modified mapping.
1320
1321 * Notes:
1322 * - A NULL pointer value will be returned if this function is
1323 * invoked with the AST error status set, or if it should fail for
1324 * any reason.
1325 */
1326
1327 /* Local Variables: */
1328 AstTranMap *new; /* Pointer to new TranMap */
1329 AstTranMap *this; /* Pointer to TranMap structure */
1330 AstMapping *newmap1; /* New first component Mapping */
1331 AstMapping *newmap2; /* New second component Mapping */
1332 AstMapping *result; /* Result pointer to return */
1333 int nax; /* Number of Frame axes */
1334 int unit1; /* Is new first Mapping a UnitMap? */
1335 int unit2; /* Is new second Mapping a UnitMap? */
1336
1337 /* Initialise. */
1338 result = NULL;
1339
1340 /* Check the global error status. */
1341 if ( !astOK ) return result;
1342
1343 /* Get a pointer to the TranMap. */
1344 this = (AstTranMap *) this_mapping;
1345
1346 /* Invoke the astRemoveRegions method on the two component Mappings. */
1347 newmap1 = astRemoveRegions( this->map1 );
1348 newmap2 = astRemoveRegions( this->map2 );
1349
1350 /* If neither component was modified, just return a clone of the supplied
1351 pointer. */
1352 if( this->map1 == newmap1 && this->map2 == newmap2 ) {
1353 result = astClone( this );
1354
1355 /* Otherwise, we need to create a new Mapping to return. */
1356 } else {
1357
1358 /* The implementation of the astRemoveRegions method provided by the
1359 Region class returns a Frame rather than a UnitMap. But we need
1360 Mappings here, not Frames. So if either of these new Mappings is
1361 a Frame, replace it with an equivalent UnitMap. Also, get flags
1362 indicating if either Mapping is a UnitMap.*/
1363 if( astIsAFrame( newmap1 ) ) {
1364 nax = astGetNin( newmap1 );
1365 (void) astAnnul( newmap1 );
1366 newmap1 = (AstMapping *) astUnitMap( nax, " ", status );
1367 unit1 = 1;
1368 } else {
1369 unit1 = astIsAUnitMap( newmap1 );
1370 }
1371
1372 if( astIsAFrame( newmap2 ) ) {
1373 nax = astGetNin( newmap2 );
1374 (void) astAnnul( newmap2 );
1375 newmap2 = (AstMapping *) astUnitMap( nax, " ", status );
1376 unit2 = 1;
1377 } else {
1378 unit2 = astIsAUnitMap( newmap2 );
1379 }
1380
1381 /* If both new Mappings are UnitMaps, return an equivalent UnitMap. */
1382 if( unit1 && unit2 ) {
1383 result = (AstMapping *) astUnitMap( astGetNin( newmap1 ) +
1384 astGetNin( newmap2 ), " ",
1385 status );
1386
1387 /* Otherwise, return a new TranMap containing the two new Mappings. */
1388 } else {
1389 new = astCopy( this );
1390 (void) astAnnul( new->map1 );
1391 (void) astAnnul( new->map2 );
1392 new->map1 = astClone( newmap1 );
1393 new->map2 = astClone( newmap2 );
1394 result = (AstMapping *) new;
1395 }
1396 }
1397
1398 /* Free resources. */
1399 newmap1 = astAnnul( newmap1 );
1400 newmap2 = astAnnul( newmap2 );
1401
1402 /* Annul the returned Mapping if an error has occurred. */
1403 if( !astOK ) result = astAnnul( result );
1404
1405 /* Return the result. */
1406 return result;
1407 }
1408
Transform(AstMapping * this,AstPointSet * in,int forward,AstPointSet * out,int * status)1409 static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
1410 int forward, AstPointSet *out, int *status ) {
1411 /*
1412 * Name:
1413 * Transform
1414
1415 * Purpose:
1416 * Apply a TranMap to transform a set of points.
1417
1418 * Type:
1419 * Private function.
1420
1421 * Synopsis:
1422 * #include "tranmap.h"
1423 * AstPointSet *Transform( AstMapping *this, AstPointSet *in,
1424 * int forward, AstPointSet *out, int *status )
1425
1426 * Class Membership:
1427 * TranMap member function (over-rides the astTransform method inherited
1428 * from the Mapping class).
1429
1430 * Description:
1431 * This function takes a TranMap and a set of points encapsulated in a
1432 * PointSet and transforms the points so as to apply the required Mapping.
1433 * This implies applying each of the TranMap's component Mappings in turn,
1434 * either in series or in parallel.
1435
1436 * Parameters:
1437 * this
1438 * Pointer to the TranMap.
1439 * in
1440 * Pointer to the PointSet associated with the input coordinate values.
1441 * forward
1442 * A non-zero value indicates that the forward coordinate transformation
1443 * should be applied, while a zero value requests the inverse
1444 * transformation.
1445 * out
1446 * Pointer to a PointSet which will hold the transformed (output)
1447 * coordinate values. A NULL value may also be given, in which case a
1448 * new PointSet will be created by this function.
1449 * status
1450 * Pointer to the inherited status variable.
1451
1452 * Returned Value:
1453 * Pointer to the output (possibly new) PointSet.
1454
1455 * Notes:
1456 * - A null pointer will be returned if this function is invoked with the
1457 * global error status set, or if it should fail for any reason.
1458 * - The number of coordinate values per point in the input PointSet must
1459 * match the number of coordinates for the TranMap being applied.
1460 * - If an output PointSet is supplied, it must have space for sufficient
1461 * number of points and coordinate values per point to accommodate the
1462 * result. Any excess space will be ignored.
1463 */
1464
1465 /* Local Variables: */
1466 AstMapping *cmap; /* Mapping which defines the required transformation */
1467 AstPointSet *result; /* Pointer to output PointSet */
1468 AstTranMap *map; /* Pointer to TranMap to be applied */
1469 int cinv; /* Invert flag when TranMap was created */
1470 int old_inv; /* Invert flag on entry to this function */
1471
1472 /* Check the global error status. */
1473 if ( !astOK ) return NULL;
1474
1475 /* Obtain a pointer to the TranMap. */
1476 map = (AstTranMap *) this;
1477
1478 /* Apply the parent Mapping using the stored pointer to the Transform member
1479 function inherited from the parent Mapping class. This function validates
1480 all arguments and generates an output PointSet if necessary, but does not
1481 actually transform any coordinate values. */
1482 result = (*parent_transform)( this, in, forward, out, status );
1483
1484 /* We now extend the parent astTransform method by applying the component
1485 Mappings of the TranMap to generate the output coordinate values. */
1486
1487 /* Determine whether to apply the forward or inverse Mapping, according to the
1488 direction specified and whether the Mapping has been inverted. */
1489 if ( astGetInvert( map ) ) forward = !forward;
1490
1491 /* Choose the component Mapping to use, and get its original Invert value. */
1492 if( forward ) {
1493 cmap = map->map1;
1494 cinv = map->invert1;
1495 }else {
1496 cmap = map->map2;
1497 cinv = map->invert2;
1498 }
1499
1500 /* Temporarily set the Invert flag of the component Mapping back to its
1501 original value. */
1502 old_inv = astGetInvert( cmap );
1503 astSetInvert( cmap, cinv );
1504
1505 /* Use the Transform method of the component Mapping. */
1506 result = astTransform( cmap, in, forward, out );
1507
1508 /* Re-instate the Invert flag of the component Mapping. */
1509 astSetInvert( cmap, old_inv );
1510
1511 /* If an error occurred, clean up by deleting the output PointSet (if
1512 allocated by this function) and setting a NULL result pointer. */
1513 if ( !astOK ) {
1514 if ( !out ) result = astDelete( result );
1515 result = NULL;
1516 }
1517
1518 /* Return a pointer to the output PointSet. */
1519 return result;
1520 }
1521
1522 /* Copy constructor. */
1523 /* ----------------- */
Copy(const AstObject * objin,AstObject * objout,int * status)1524 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
1525 /*
1526 * Name:
1527 * Copy
1528
1529 * Purpose:
1530 * Copy constructor for TranMap objects.
1531
1532 * Type:
1533 * Private function.
1534
1535 * Synopsis:
1536 * void Copy( const AstObject *objin, AstObject *objout, int *status )
1537
1538 * Description:
1539 * This function implements the copy constructor for TranMap objects.
1540
1541 * Parameters:
1542 * objin
1543 * Pointer to the object to be copied.
1544 * objout
1545 * Pointer to the object being constructed.
1546 * status
1547 * Pointer to the inherited status variable.
1548
1549 * Returned Value:
1550 * void
1551
1552 * Notes:
1553 * - This constructor makes a deep copy, including a copy of the component
1554 * Mappings within the TranMap.
1555 */
1556
1557 /* Local Variables: */
1558 AstTranMap *in; /* Pointer to input TranMap */
1559 AstTranMap *out; /* Pointer to output TranMap */
1560
1561 /* Check the global error status. */
1562 if ( !astOK ) return;
1563
1564 /* Obtain pointers to the input and output TranMaps. */
1565 in = (AstTranMap *) objin;
1566 out = (AstTranMap *) objout;
1567
1568 /* For safety, start by clearing any references to the input component
1569 Mappings from the output TranMap. */
1570 out->map1 = NULL;
1571 out->map2 = NULL;
1572
1573 /* Make copies of these Mappings and store pointers to them in the output
1574 TranMap structure. */
1575 out->map1 = astCopy( in->map1 );
1576 out->map2 = astCopy( in->map2 );
1577 }
1578
1579 /* Destructor. */
1580 /* ----------- */
Delete(AstObject * obj,int * status)1581 static void Delete( AstObject *obj, int *status ) {
1582 /*
1583 * Name:
1584 * Delete
1585
1586 * Purpose:
1587 * Destructor for TranMap objects.
1588
1589 * Type:
1590 * Private function.
1591
1592 * Synopsis:
1593 * void Delete( AstObject *obj, int *status )
1594
1595 * Description:
1596 * This function implements the destructor for TranMap objects.
1597
1598 * Parameters:
1599 * obj
1600 * Pointer to the object to be deleted.
1601 * status
1602 * Pointer to the inherited status variable.
1603
1604 * Returned Value:
1605 * void
1606
1607 * Notes:
1608 * This function attempts to execute even if the global error status is
1609 * set.
1610 */
1611
1612 /* Local Variables: */
1613 AstTranMap *this; /* Pointer to TranMap */
1614
1615 /* Obtain a pointer to the TranMap structure. */
1616 this = (AstTranMap *) obj;
1617
1618 /* Annul the pointers to the component Mappings. */
1619 this->map1 = astAnnul( this->map1 );
1620 this->map2 = astAnnul( this->map2 );
1621
1622 /* Clear the remaining TranMap variables. */
1623 this->invert1 = 0;
1624 this->invert2 = 0;
1625 }
1626
1627 /* Dump function. */
1628 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)1629 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
1630 /*
1631 * Name:
1632 * Dump
1633
1634 * Purpose:
1635 * Dump function for TranMap objects.
1636
1637 * Type:
1638 * Private function.
1639
1640 * Synopsis:
1641 * void Dump( AstObject *this, AstChannel *channel, int *status )
1642
1643 * Description:
1644 * This function implements the Dump function which writes out data
1645 * for the TranMap class to an output Channel.
1646
1647 * Parameters:
1648 * this
1649 * Pointer to the TranMap whose data are being written.
1650 * channel
1651 * Pointer to the Channel to which the data are being written.
1652 * status
1653 * Pointer to the inherited status variable.
1654 */
1655
1656 /* Local Variables: */
1657 AstTranMap *this; /* Pointer to the TranMap structure */
1658 int ival; /* Integer value */
1659 int set; /* Attribute value set? */
1660
1661 /* Check the global error status. */
1662 if ( !astOK ) return;
1663
1664 /* Obtain a pointer to the TranMap structure. */
1665 this = (AstTranMap *) this_object;
1666
1667 /* Write out values representing the instance variables for the TranMap
1668 class. Accompany these with appropriate comment strings, possibly
1669 depending on the values being written.*/
1670
1671 /* In the case of attributes, we first use the appropriate (private)
1672 Test... member function to see if they are set. If so, we then use
1673 the (private) Get... function to obtain the value to be written
1674 out.
1675
1676 For attributes which are not set, we use the astGet... method to
1677 obtain the value instead. This will supply a default value
1678 (possibly provided by a derived class which over-rides this method)
1679 which is more useful to a human reader as it corresponds to the
1680 actual default attribute value. Since "set" will be zero, these
1681 values are for information only and will not be read back. */
1682
1683 /* First Invert flag. */
1684 /* ------------------ */
1685 ival = this->invert1;
1686 set = ( ival != 0 );
1687 astWriteInt( channel, "InvA", set, 0, ival,
1688 ival ? "First Mapping used in inverse direction" :
1689 "First Mapping used in forward direction" );
1690
1691 /* Second Invert flag. */
1692 /* ------------------- */
1693 ival = this->invert2;
1694 set = ( ival != 0 );
1695 astWriteInt( channel, "InvB", set, 0, ival,
1696 ival ? "Second Mapping used in inverse direction" :
1697 "Second Mapping used in forward direction" );
1698
1699 /* First Mapping. */
1700 /* -------------- */
1701 astWriteObject( channel, "MapA", 1, 1, this->map1,
1702 "Mapping for forward transformation" );
1703
1704 /* Second Mapping. */
1705 /* --------------- */
1706 astWriteObject( channel, "MapB", 1, 1, this->map2,
1707 "Mapping for inverse transformation" );
1708 }
1709
1710 /* Standard class functions. */
1711 /* ========================= */
1712 /* Implement the astIsATranMap and astCheckTranMap functions using the
1713 macros defined for this purpose in the "object.h" header file. */
astMAKE_ISA(TranMap,Mapping)1714 astMAKE_ISA(TranMap,Mapping)
1715 astMAKE_CHECK(TranMap)
1716
1717 AstTranMap *astTranMap_( void *map1_void, void *map2_void, const char *options, int *status, ...) {
1718 /*
1719 *+
1720 * Name:
1721 * astTranMap
1722
1723 * Purpose:
1724 * Create a TranMap.
1725
1726 * Type:
1727 * Protected function.
1728
1729 * Synopsis:
1730 * #include "tranmap.h"
1731 * AstTranMap *astTranMap( AstMapping *map1, AstMapping *map2, const char *options, int *status, ... )
1732
1733 * Class Membership:
1734 * TranMap constructor.
1735
1736 * Description:
1737 * This function creates a new TranMap and optionally initialises its
1738 * attributes.
1739
1740 * Parameters:
1741 * map1
1742 * Pointer to the first Mapping (which deinfes the forward
1743 * transformation).
1744 * map2
1745 * Pointer to the second Mapping (which deinfes the inverse
1746 * transformation).
1747 * options
1748 * Pointer to a null terminated string containing an optional
1749 * comma-separated list of attribute assignments to be used for
1750 * initialising the new TranMap. The syntax used is the same as for the
1751 * astSet method and may include "printf" format specifiers identified
1752 * by "%" symbols in the normal way.
1753 * status
1754 * Pointer to the inherited status variable.
1755 * ...
1756 * If the "options" string contains "%" format specifiers, then an
1757 * optional list of arguments may follow it in order to supply values to
1758 * be substituted for these specifiers. The rules for supplying these
1759 * are identical to those for the astSet method (and for the C "printf"
1760 * function).
1761
1762 * Returned Value:
1763 * A pointer to the new TranMap.
1764
1765 * Notes:
1766 * - A null pointer will be returned if this function is invoked
1767 * with the global error status set, or if it should fail for any
1768 * reason.
1769 *-
1770
1771 * Implementation Notes:
1772 * - This function implements the basic TranMap constructor which is
1773 * available via the protected interface to the TranMap class. A
1774 * public interface is provided by the astTranMapId_ function.
1775 * - Because this function has a variable argument list, it is
1776 * invoked by a macro that evaluates to a function pointer (not a
1777 * function invocation) and no checking or casting of arguments is
1778 * performed before the function is invoked. Because of this, the
1779 * "map1" and "map2" parameters are of type (void *) and are
1780 * converted and validated within the function itself.
1781 */
1782
1783 /* Local Variables: */
1784 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1785 AstTranMap *new; /* Pointer to new TranMap */
1786 AstMapping *map1; /* Pointer to first Mapping structure */
1787 AstMapping *map2; /* Pointer to second Mapping structure */
1788 va_list args; /* Variable argument list */
1789
1790 /* Initialise. */
1791 new = NULL;
1792
1793 /* Get a pointer to the thread specific global data structure. */
1794 astGET_GLOBALS(NULL);
1795
1796 /* Check the global status. */
1797 if ( !astOK ) return new;
1798
1799 /* Obtain and validate pointers to the Mapping structures provided. */
1800 map1 = astCheckMapping( map1_void );
1801 map2 = astCheckMapping( map2_void );
1802 if ( astOK ) {
1803
1804 /* Initialise the TranMap, allocating memory and initialising the
1805 virtual function table as well if necessary. */
1806 new = astInitTranMap( NULL, sizeof( AstTranMap ), !class_init, &class_vtab,
1807 "TranMap", map1, map2 );
1808
1809 /* If successful, note that the virtual function table has been
1810 initialised. */
1811 if ( astOK ) {
1812 class_init = 1;
1813
1814 /* Obtain the variable argument list and pass it along with the
1815 options string to the astVSet method to initialise the new TranMap's
1816 attributes. */
1817 va_start( args, status );
1818 astVSet( new, options, NULL, args );
1819 va_end( args );
1820
1821 /* If an error occurred, clean up by deleting the new object. */
1822 if ( !astOK ) new = astDelete( new );
1823 }
1824 }
1825
1826 /* Return a pointer to the new TranMap. */
1827 return new;
1828 }
1829
astTranMapId_(void * map1_void,void * map2_void,const char * options,...)1830 AstTranMap *astTranMapId_( void *map1_void, void *map2_void,
1831 const char *options, ... ) {
1832 /*
1833 *++
1834 * Name:
1835 c astTranMap
1836 f AST_TRANMAP
1837
1838 * Purpose:
1839 * Create a TranMap.
1840
1841 * Type:
1842 * Public function.
1843
1844 * Synopsis:
1845 c #include "tranmap.h"
1846 c AstTranMap *astTranMap( AstMapping *map1, AstMapping *map2,
1847 c const char *options, ... )
1848 f RESULT = AST_TRANMAP( MAP1, MAP2, OPTIONS, STATUS )
1849
1850 * Class Membership:
1851 * TranMap constructor.
1852
1853 * Description:
1854 * This function creates a new TranMap and optionally initialises
1855 * its attributes.
1856 *
1857 * A TranMap is a Mapping which combines the forward transformation of
1858 * a supplied Mapping with the inverse transformation of another
1859 * supplied Mapping, ignoring the un-used transformation in each
1860 * Mapping (indeed the un-used transformation need not exist).
1861 *
1862 * When the forward transformation of the TranMap is referred to, the
1863 * transformation actually used is the forward transformation of the
1864 * first Mapping supplied when the TranMap was constructed. Likewise,
1865 * when the inverse transformation of the TranMap is referred to, the
1866 * transformation actually used is the inverse transformation of the
1867 * second Mapping supplied when the TranMap was constructed.
1868
1869 * Parameters:
1870 c map1
1871 f MAP1 = INTEGER (Given)
1872 * Pointer to the first component Mapping, which defines the
1873 * forward transformation.
1874 c map2
1875 f MAP2 = INTEGER (Given)
1876 * Pointer to the second component Mapping, which defines the
1877 * inverse transformation.
1878 c options
1879 f OPTIONS = CHARACTER * ( * ) (Given)
1880 c Pointer to a null-terminated string containing an optional
1881 c comma-separated list of attribute assignments to be used for
1882 c initialising the new TranMap. The syntax used is identical to
1883 c that for the astSet function and may include "printf" format
1884 c specifiers identified by "%" symbols in the normal way.
1885 f A character string containing an optional comma-separated
1886 f list of attribute assignments to be used for initialising the
1887 f new TranMap. The syntax used is identical to that for the
1888 f AST_SET routine.
1889 c ...
1890 c If the "options" string contains "%" format specifiers, then
1891 c an optional list of additional arguments may follow it in
1892 c order to supply values to be substituted for these
1893 c specifiers. The rules for supplying these are identical to
1894 c those for the astSet function (and for the C "printf"
1895 c function).
1896 f STATUS = INTEGER (Given and Returned)
1897 f The global status.
1898
1899 * Returned Value:
1900 c astTranMap()
1901 f AST_TRANMAP = INTEGER
1902 * A pointer to the new TranMap.
1903
1904 * Notes:
1905 * - The number of output coordinates generated by the two Mappings
1906 * (their Nout attribute) must be equal, as must the number of input
1907 * coordinates accepted by each Mapping (their Nin attribute).
1908 * - The forward transformation of the first Mapping must exist.
1909 * - The inverse transformation of the second Mapping must exist.
1910 c - Note that the component Mappings supplied are not copied by
1911 c astTranMap (the new TranMap simply retains a reference to
1912 c them). They may continue to be used for other purposes, but
1913 c should not be deleted. If a TranMap containing a copy of its
1914 c component Mappings is required, then a copy of the TranMap should
1915 c be made using astCopy.
1916 f - Note that the component Mappings supplied are not copied by
1917 f AST_TRANMAP (the new TranMap simply retains a reference to
1918 f them). They may continue to be used for other purposes, but
1919 f should not be deleted. If a TranMap containing a copy of its
1920 f component Mappings is required, then a copy of the TranMap should
1921 f be made using AST_COPY.
1922 * - A null Object pointer (AST__NULL) will be returned if this
1923 c function is invoked with the AST error status set, or if it
1924 f function is invoked with STATUS set to an error value, or if it
1925 * should fail for any reason.
1926
1927 * Status Handling:
1928 * The protected interface to this function includes an extra
1929 * parameter at the end of the parameter list descirbed above. This
1930 * parameter is a pointer to the integer inherited status
1931 * variable: "int *status".
1932
1933 *--
1934
1935 * Implementation Notes:
1936 * - This function implements the external (public) interface to
1937 * the astTranMap constructor function. It returns an ID value
1938 * (instead of a true C pointer) to external users, and must be
1939 * provided because astTranMap_ has a variable argument list which
1940 * cannot be encapsulated in a macro (where this conversion would
1941 * otherwise occur).
1942 * - Because no checking or casting of arguments is performed
1943 * before the function is invoked, the "map1" and "map2" parameters
1944 * are of type (void *) and are converted from an ID value to a
1945 * pointer and validated within the function itself.
1946 * - The variable argument list also prevents this function from
1947 * invoking astTranMap_ directly, so it must be a re-implementation
1948 * of it in all respects, except for the conversions between IDs
1949 * and pointers on input/output of Objects.
1950 */
1951
1952 /* Local Variables: */
1953 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1954 AstTranMap *new; /* Pointer to new TranMap */
1955 AstMapping *map1; /* Pointer to first Mapping structure */
1956 AstMapping *map2; /* Pointer to second Mapping structure */
1957 va_list args; /* Variable argument list */
1958
1959 int *status; /* Pointer to inherited status value */
1960
1961 /* Get a pointer to the thread specific global data structure. */
1962 astGET_GLOBALS(NULL);
1963
1964 /* Initialise. */
1965 new = NULL;
1966
1967 /* Get a pointer to the inherited status value. */
1968 status = astGetStatusPtr;
1969
1970 /* Check the global status. */
1971 if ( !astOK ) return new;
1972
1973 /* Obtain the Mapping pointers from the ID's supplied and validate the
1974 pointers to ensure they identify valid Mappings. */
1975 map1 = astVerifyMapping( astMakePointer( map1_void ) );
1976 map2 = astVerifyMapping( astMakePointer( map2_void ) );
1977 if ( astOK ) {
1978
1979 /* Initialise the TranMap, allocating memory and initialising the
1980 virtual function table as well if necessary. */
1981 new = astInitTranMap( NULL, sizeof( AstTranMap ), !class_init, &class_vtab,
1982 "TranMap", map1, map2 );
1983
1984 /* If successful, note that the virtual function table has been initialised. */
1985 if ( astOK ) {
1986 class_init = 1;
1987
1988 /* Obtain the variable argument list and pass it along with the
1989 options string to the astVSet method to initialise the new TranMap's
1990 attributes. */
1991 va_start( args, options );
1992 astVSet( new, options, NULL, args );
1993 va_end( args );
1994
1995 /* If an error occurred, clean up by deleting the new object. */
1996 if ( !astOK ) new = astDelete( new );
1997 }
1998 }
1999
2000 /* Return an ID value for the new TranMap. */
2001 return astMakeId( new );
2002 }
2003
astInitTranMap_(void * mem,size_t size,int init,AstTranMapVtab * vtab,const char * name,AstMapping * map1,AstMapping * map2,int * status)2004 AstTranMap *astInitTranMap_( void *mem, size_t size, int init,
2005 AstTranMapVtab *vtab, const char *name,
2006 AstMapping *map1, AstMapping *map2, int *status ) {
2007 /*
2008 *+
2009 * Name:
2010 * astInitTranMap
2011
2012 * Purpose:
2013 * Initialise a TranMap.
2014
2015 * Type:
2016 * Protected function.
2017
2018 * Synopsis:
2019 * #include "tranmap.h"
2020 * AstTranMap *astInitTranMap( void *mem, size_t size, int init,
2021 * AstTranMapVtab *vtab, const char *name,
2022 * AstMapping *map1, AstMapping *map2 )
2023
2024 * Class Membership:
2025 * TranMap initialiser.
2026
2027 * Description:
2028 * This function is provided for use by class implementations to initialise
2029 * a new TranMap object. It allocates memory (if necessary) to
2030 * accommodate the TranMap plus any additional data associated with the
2031 * derived class. It then initialises a TranMap structure at the start
2032 * of this memory. If the "init" flag is set, it also initialises the
2033 * contents of a virtual function table for a TranMap at the start of
2034 * the memory passed via the "vtab" parameter.
2035
2036 * Parameters:
2037 * mem
2038 * A pointer to the memory in which the TranMap is to be initialised.
2039 * This must be of sufficient size to accommodate the TranMap data
2040 * (sizeof(TranMap)) plus any data used by the derived class. If a
2041 * value of NULL is given, this function will allocate the memory itself
2042 * using the "size" parameter to determine its size.
2043 * size
2044 * The amount of memory used by the TranMap (plus derived class
2045 * data). This will be used to allocate memory if a value of NULL is
2046 * given for the "mem" parameter. This value is also stored in the
2047 * TranMap structure, so a valid value must be supplied even if not
2048 * required for allocating memory.
2049 * init
2050 * A logical flag indicating if the TranMap's virtual function table
2051 * is to be initialised. If this value is non-zero, the virtual function
2052 * table will be initialised by this function.
2053 * vtab
2054 * Pointer to the start of the virtual function table to be associated
2055 * with the new TranMap.
2056 * name
2057 * Pointer to a constant null-terminated character string which contains
2058 * the name of the class to which the new object belongs (it is this
2059 * pointer value that will subsequently be returned by the Object
2060 * astClass function).
2061 * map1
2062 * Pointer to the first Mapping.
2063 * map2
2064 * Pointer to the second Mapping.
2065
2066 * Returned Value:
2067 * A pointer to the new TranMap.
2068
2069 * Notes:
2070 * - A null pointer will be returned if this function is invoked with the
2071 * global error status set, or if it should fail for any reason.
2072 *-
2073 */
2074
2075 /* Local Variables: */
2076 AstTranMap *new; /* Pointer to new TranMap */
2077 int nin; /* No. input coordinates for TranMap */
2078 int nout; /* No. output coordinates for TranMap */
2079
2080 /* Check the global status. */
2081 if ( !astOK ) return NULL;
2082
2083 /* If necessary, initialise the virtual function table. */
2084 if ( init ) astInitTranMapVtab( vtab, name );
2085
2086 /* Initialise. */
2087 new = NULL;
2088
2089 /* Report an error if map1 has no forward transformation. */
2090 if( !astGetTranForward( map1 ) && astOK ) {
2091 astError( AST__INTRD, "astInitTranMap(%s): The first supplied Mapping "
2092 "is not able to transform coordinates in the forward direction.", status,
2093 name );
2094 }
2095
2096 /* Report an error if map2 has no inverse transformation. */
2097 if( !astGetTranInverse( map2 ) && astOK ) {
2098 astError( AST__INTRD, "astInitTranMap(%s): The second supplied Mapping "
2099 "is not able to transform coordinates in the inverse direction.", status,
2100 name );
2101 }
2102
2103 /* Check that the number of coordinates are compatible and report an error if
2104 they are not. */
2105 nout = astGetNout( map1 );
2106 if ( astGetNout( map2 ) != nout && astOK ) {
2107 astError( AST__INNCO, "astInitTranMap(%s): The number of output "
2108 "coordinates per point (%d) for the first Mapping "
2109 "supplied does not match the number of output "
2110 "coordinates (%d) for the second Mapping.", status, name, nout,
2111 astGetNout( map2 ) );
2112 }
2113
2114 nin = astGetNin( map1 );
2115 if ( astGetNin( map2 ) != nin && astOK ) {
2116 astError( AST__INNCO, "astInitTranMap(%s): The number of input "
2117 "coordinates per point (%d) for the first Mapping "
2118 "supplied does not match the number of input "
2119 "coordinates (%d) for the second Mapping.", status, name, nin,
2120 astGetNin( map2 ) );
2121 }
2122
2123 /* Initialise a Mapping structure (the parent class) as the first component
2124 within the TranMap structure, allocating memory if necessary. Specify
2125 the number of input and output coordinates and in which directions the
2126 Mapping should be defined. */
2127 if ( astOK ) {
2128 new = (AstTranMap *) astInitMapping( mem, size, 0,
2129 (AstMappingVtab *) vtab, name,
2130 nin, nout, 1, 1 );
2131
2132 if ( astOK ) {
2133
2134 /* Initialise the TranMap data. */
2135 /* --------------------------- */
2136 /* Store pointers to the component Mappings. */
2137 new->map1 = astClone( map1 );
2138 new->map2 = astClone( map2 );
2139
2140 /* Save the initial values of the inversion flags for these Mappings. */
2141 new->invert1 = astGetInvert( map1 );
2142 new->invert2 = astGetInvert( map2 );
2143
2144 /* If an error occurred, clean up by annulling the Mapping pointers and
2145 deleting the new object. */
2146 if ( !astOK ) {
2147 new->map1 = astAnnul( new->map1 );
2148 new->map2 = astAnnul( new->map2 );
2149 new = astDelete( new );
2150 }
2151 }
2152 }
2153
2154 /* Return a pointer to the new object. */
2155 return new;
2156 }
2157
astLoadTranMap_(void * mem,size_t size,AstTranMapVtab * vtab,const char * name,AstChannel * channel,int * status)2158 AstTranMap *astLoadTranMap_( void *mem, size_t size,
2159 AstTranMapVtab *vtab, const char *name,
2160 AstChannel *channel, int *status ) {
2161 /*
2162 *+
2163 * Name:
2164 * astLoadTranMap
2165
2166 * Purpose:
2167 * Load a TranMap.
2168
2169 * Type:
2170 * Protected function.
2171
2172 * Synopsis:
2173 * #include "tranmap.h"
2174 * AstTranMap *astLoadTranMap( void *mem, size_t size,
2175 * AstTranMapVtab *vtab, const char *name,
2176 * AstChannel *channel )
2177
2178 * Class Membership:
2179 * TranMap loader.
2180
2181 * Description:
2182 * This function is provided to load a new TranMap using data read
2183 * from a Channel. It first loads the data used by the parent class
2184 * (which allocates memory if necessary) and then initialises a
2185 * TranMap structure in this memory, using data read from the input
2186 * Channel.
2187 *
2188 * If the "init" flag is set, it also initialises the contents of a
2189 * virtual function table for a TranMap at the start of the memory
2190 * passed via the "vtab" parameter.
2191
2192
2193 * Parameters:
2194 * mem
2195 * A pointer to the memory into which the TranMap is to be
2196 * loaded. This must be of sufficient size to accommodate the
2197 * TranMap data (sizeof(TranMap)) plus any data used by derived
2198 * classes. If a value of NULL is given, this function will
2199 * allocate the memory itself using the "size" parameter to
2200 * determine its size.
2201 * size
2202 * The amount of memory used by the TranMap (plus derived class
2203 * data). This will be used to allocate memory if a value of
2204 * NULL is given for the "mem" parameter. This value is also
2205 * stored in the TranMap structure, so a valid value must be
2206 * supplied even if not required for allocating memory.
2207 *
2208 * If the "vtab" parameter is NULL, the "size" value is ignored
2209 * and sizeof(AstTranMap) is used instead.
2210 * vtab
2211 * Pointer to the start of the virtual function table to be
2212 * associated with the new TranMap. If this is NULL, a pointer to
2213 * the (static) virtual function table for the TranMap class is
2214 * used instead.
2215 * name
2216 * Pointer to a constant null-terminated character string which
2217 * contains the name of the class to which the new object
2218 * belongs (it is this pointer value that will subsequently be
2219 * returned by the astGetClass method).
2220 *
2221 * If the "vtab" parameter is NULL, the "name" value is ignored
2222 * and a pointer to the string "TranMap" is used instead.
2223
2224 * Returned Value:
2225 * A pointer to the new TranMap.
2226
2227 * Notes:
2228 * - A null pointer will be returned if this function is invoked
2229 * with the global error status set, or if it should fail for any
2230 * reason.
2231 *-
2232 */
2233
2234 /* Local Variables: */
2235 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2236 AstTranMap *new; /* Pointer to the new TranMap */
2237
2238 /* Initialise. */
2239 new = NULL;
2240
2241 /* Check the global error status. */
2242 if ( !astOK ) return new;
2243
2244 /* Get a pointer to the thread specific global data structure. */
2245 astGET_GLOBALS(channel);
2246
2247 /* If a NULL virtual function table has been supplied, then this is
2248 the first loader to be invoked for this TranMap. In this case the
2249 TranMap belongs to this class, so supply appropriate values to be
2250 passed to the parent class loader (and its parent, etc.). */
2251 if ( !vtab ) {
2252 size = sizeof( AstTranMap );
2253 vtab = &class_vtab;
2254 name = "TranMap";
2255
2256 /* If required, initialise the virtual function table for this class. */
2257 if ( !class_init ) {
2258 astInitTranMapVtab( vtab, name );
2259 class_init = 1;
2260 }
2261 }
2262
2263 /* Invoke the parent class loader to load data for all the ancestral
2264 classes of the current one, returning a pointer to the resulting
2265 partly-built TranMap. */
2266 new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
2267 channel );
2268
2269 if ( astOK ) {
2270
2271 /* Read input data. */
2272 /* ================ */
2273 /* Request the input Channel to read all the input data appropriate to
2274 this class into the internal "values list". */
2275 astReadClassData( channel, "TranMap" );
2276
2277 /* Now read each individual data item from this list and use it to
2278 initialise the appropriate instance variable(s) for this class. */
2279
2280 /* In the case of attributes, we first read the "raw" input value,
2281 supplying the "unset" value as the default. If a "set" value is
2282 obtained, we then use the appropriate (private) Set... member
2283 function to validate and set the value properly. */
2284
2285 /* First Invert flag. */
2286 /* ------------------ */
2287 new->invert1 = astReadInt( channel, "inva", 0 );
2288 new->invert1 = ( new->invert1 != 0 );
2289
2290 /* Second Invert flag. */
2291 /* ------------------- */
2292 new->invert2 = astReadInt( channel, "invb", 0 );
2293 new->invert2 = ( new->invert2 != 0 );
2294
2295 /* First Mapping. */
2296 /* -------------- */
2297 new->map1 = astReadObject( channel, "mapa", NULL );
2298
2299 /* Second Mapping. */
2300 /* --------------- */
2301 new->map2 = astReadObject( channel, "mapb", NULL );
2302
2303 /* If an error occurred, clean up by deleting the new TranMap. */
2304 if ( !astOK ) new = astDelete( new );
2305 }
2306
2307 /* Return the new TranMap pointer. */
2308 return new;
2309 }
2310
2311 /* Virtual function interfaces. */
2312 /* ============================ */
2313 /* These provide the external interface to the virtual functions defined by
2314 this class. Each simply checks the global error status and then locates and
2315 executes the appropriate member function, using the function pointer stored
2316 in the object's virtual function table (this pointer is located using the
2317 astMEMBER macro defined in "object.h").
2318
2319 Note that the member function may not be the one defined here, as it may
2320 have been over-ridden by a derived class. However, it should still have the
2321 same interface. */
2322
2323 /* None. */
2324
2325
2326
2327
2328