1 /*
2 *class++
3 * Name:
4 * SwitchMap
5
6 * Purpose:
7 * A Mapping that encapsulates a set of alternate Mappings.
8
9 * Constructor Function:
10 c astSwitchMap
11 f AST_SWITCHMAP
12
13 * Description:
14 * A SwitchMap is a Mapping which represents a set of alternate
15 * Mappings, each of which is used to transform positions within a
16 * particular region of the input or output coordinate system of the
17 * SwitchMap.
18 *
19 * A SwitchMap can encapsulate any number of Mappings, but they must
20 * all have the same number of inputs (Nin attribute value) and the
21 * same number of outputs (Nout attribute value). The SwitchMap itself
22 * inherits these same values for its Nin and Nout attributes. Each of
23 * these Mappings represents a "route" through the switch, and are
24 * referred to as "route" Mappings below. Each route Mapping transforms
25 * positions between the input and output coordinate space of the entire
26 * SwitchMap, but only one Mapping will be used to transform any given
27 * position. The selection of the appropriate route Mapping to use with
28 * any given input position is made by another Mapping, called the
29 * "selector" Mapping. Each SwitchMap encapsulates two selector
30 * Mappings in addition to its route Mappings; one for use with the
31 * SwitchMap's forward transformation (called the "forward selector
32 * Mapping"), and one for use with the SwitchMap's inverse transformation
33 * (called the "inverse selector Mapping"). The forward selector Mapping
34 * must have the same number of inputs as the route Mappings, but
35 * should have only one output. Likewise, the inverse selector Mapping
36 * must have the same number of outputs as the route Mappings, but
37 * should have only one input.
38 *
39 * When the SwitchMap is used to transform a position in the forward
40 * direction (from input to output), each supplied input position is
41 * first transformed by the forward transformation of the forward selector
42 * Mapping. This produces a single output value for each input position
43 * referred to as the selector value. The nearest integer to the selector
44 * value is found, and is used to index the array of route Mappings (the
45 * first supplied route Mapping has index 1, the second route Mapping has
46 * index 2, etc). If the nearest integer to the selector value is less
47 * than 1 or greater than the number of route Mappings, then the SwitchMap
48 * output position is set to a value of AST__BAD on every axis. Otherwise,
49 * the forward transformation of the selected route Mapping is used to
50 * transform the supplied input position to produce the SwitchMap output
51 * position.
52 *
53 * When the SwitchMap is used to transform a position in the inverse
54 * direction (from "output" to "input"), each supplied "output" position
55 * is first transformed by the inverse transformation of the inverse
56 * selector Mapping. This produces a selector value for each "output"
57 * position. Again, the nearest integer to the selector value is found,
58 * and is used to index the array of route Mappings. If this selector
59 * index value is within the bounds of the array of route Mappings, then
60 * the inverse transformation of the selected route Mapping is used to
61 * transform the supplied "output" position to produce the SwitchMap
62 * "input" position. If the selector index value is outside the bounds
63 * of the array of route Mappings, then the SwitchMap "input" position is
64 * set to a value of AST__BAD on every axis.
65 *
66 * In practice, appropriate selector Mappings should be chosen to
67 * associate a different route Mapping with each region of coordinate
68 * space. Note that the SelectorMap class of Mapping is particularly
69 * appropriate for this purpose.
70 *
71 * If a compound Mapping contains a SwitchMap in series with its own
72 * inverse, the combination of the two adjacent SwitchMaps will be
73 * replaced by a UnitMap when the compound Mapping is simplified using
74 c astSimplify.
75 f AST_SIMPLIFY.
76
77 * Inheritance:
78 * The SwitchMap class inherits from the Mapping class.
79
80 * Attributes:
81 * The SwitchMap class does not define any new attributes beyond those
82 * which are applicable to all Mappings.
83
84 * Functions:
85 c The SwitchMap class does not define any new functions beyond those
86 f The SwitchMap class does not define any new routines beyond those
87 * which are applicable to all Mappings.
88
89 * Copyright:
90 * Copyright (C) 1997-2006 Council for the Central Laboratory of the Research Councils
91
92 * Licence:
93 * This program is free software: you can redistribute it and/or
94 * modify it under the terms of the GNU Lesser General Public
95 * License as published by the Free Software Foundation, either
96 * version 3 of the License, or (at your option) any later
97 * version.
98 *
99 * This program is distributed in the hope that it will be useful,
100 * but WITHOUT ANY WARRANTY; without even the implied warranty of
101 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102 * GNU Lesser General Public License for more details.
103 *
104 * You should have received a copy of the GNU Lesser General
105 * License along with this program. If not, see
106 * <http://www.gnu.org/licenses/>.
107
108 * Authors:
109 * DSB: David S. Berry (Starlink)
110
111 * History:
112 * 13-MAR-2006 (DSB):
113 * Original version.
114 * 17-MAR-2006 (DSB):
115 * Guard against AST__BAD selector values.
116 * 9-MAY-2006 (DSB):
117 * Check selector Mapping pointers are not NULL before calling
118 * astEqual in Equal.
119 *class--
120 */
121
122 /* Module Macros. */
123 /* ============== */
124 /* Set the name of the class we are implementing. This indicates to
125 the header files that define class interfaces that they should make
126 "protected" symbols available. */
127 #define astCLASS SwitchMap
128
129 /* Include files. */
130 /* ============== */
131 /* Interface definitions. */
132 /* ---------------------- */
133
134 #include "globals.h" /* Thread-safe global data access */
135 #include "error.h" /* Error reporting facilities */
136 #include "memory.h" /* Memory allocation facilities */
137 #include "object.h" /* Base Object class */
138 #include "pointset.h" /* Sets of points/coordinates */
139 #include "mapping.h" /* Coordinate Mappings (parent class) */
140 #include "unitmap.h" /* Unit Mappings */
141 #include "channel.h" /* I/O channels */
142 #include "switchmap.h" /* Interface definition for this class */
143 #include "frame.h" /* Frames */
144
145 /* Error code definitions. */
146 /* ----------------------- */
147 #include "ast_err.h" /* AST error codes */
148
149 /* C header files. */
150 /* --------------- */
151 #include <stdarg.h>
152 #include <stddef.h>
153 #include <string.h>
154 #include <stdio.h>
155
156 /* Module Variables. */
157 /* ================= */
158
159 /* Address of this static variable is used as a unique identifier for
160 member of this class. */
161 static int class_check;
162
163 /* Pointers to parent class methods which are extended by this class. */
164 static int (* parent_getobjsize)( AstObject *, int * );
165 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
166
167 #if defined(THREAD_SAFE)
168 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
169 #endif
170
171
172
173 #ifdef THREAD_SAFE
174 /* Define how to initialise thread-specific globals. */
175 #define GLOBAL_inits \
176 globals->Class_Init = 0;
177
178 /* Create the function that initialises global data for this module. */
179 astMAKE_INITGLOBALS(SwitchMap)
180
181 /* Define macros for accessing each item of thread specific global data. */
182 #define class_init astGLOBAL(SwitchMap,Class_Init)
183 #define class_vtab astGLOBAL(SwitchMap,Class_Vtab)
184
185
186 #include <pthread.h>
187
188
189 #else
190
191
192 /* Define the class virtual function table and its initialisation flag
193 as static variables. */
194 static AstSwitchMapVtab class_vtab; /* Virtual function table */
195 static int class_init = 0; /* Virtual function table initialised? */
196
197 #endif
198
199 /* External Interface Function Prototypes. */
200 /* ======================================= */
201 /* The following functions have public prototypes only (i.e. no
202 protected prototypes), so we must provide local prototypes for use
203 within this module. */
204 AstSwitchMap *astSwitchMapId_( void *, void *, int, void **, const char *, ... );
205
206 /* Prototypes for Private Member Functions. */
207 /* ======================================== */
208 static AstMapping *RemoveRegions( AstMapping *, int * );
209 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
210 static double Rate( AstMapping *, double *, int, int, int * );
211 static int Equal( AstObject *, AstObject *, int * );
212 static int GetObjSize( AstObject *, int * );
213 static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
214 static void Copy( const AstObject *, AstObject *, int * );
215 static void Delete( AstObject *, int * );
216 static void Dump( AstObject *, AstChannel *, int * );
217 static AstMapping *GetSelector( AstSwitchMap *, int, int *, int * );
218 static AstMapping *GetRoute( AstSwitchMap *, double, int *, int * );
219
220 #if defined(THREAD_SAFE)
221 static int ManageLock( AstObject *, int, int, AstObject **, int * );
222 #endif
223
224 /* Member functions. */
225 /* ================= */
Equal(AstObject * this_object,AstObject * that_object,int * status)226 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
227 /*
228 * Name:
229 * Equal
230
231 * Purpose:
232 * Test if two SwitchMaps are equivalent.
233
234 * Type:
235 * Private function.
236
237 * Synopsis:
238 * #include "switchmap.h"
239 * int Equal( AstObject *this, AstObject *that, int *status )
240
241 * Class Membership:
242 * SwitchMap member function (over-rides the astEqual protected
243 * method inherited from the astMapping class).
244
245 * Description:
246 * This function returns a boolean result (0 or 1) to indicate whether
247 * two SwitchMaps are equivalent.
248
249 * Parameters:
250 * this
251 * Pointer to the first Object (a SwitchMap).
252 * that
253 * Pointer to the second Object.
254 * status
255 * Pointer to the inherited status variable.
256
257 * Returned Value:
258 * One if the SwitchMaps are equivalent, zero otherwise.
259
260 * Notes:
261 * - A value of zero will be returned if this function is invoked
262 * with the global status set, or if it should fail for any reason.
263 */
264
265 /* Local Variables: */
266 AstMapping *fsmap1;
267 AstMapping *fsmap2;
268 AstMapping *ismap1;
269 AstMapping *ismap2;
270 AstMapping *rmap1;
271 AstMapping *rmap2;
272 AstSwitchMap *that;
273 AstSwitchMap *this;
274 int fsinv1;
275 int fsinv2;
276 int isinv1;
277 int i;
278 int isinv2;
279 int nroute;
280 int result;
281 int rinv1;
282 int rinv2;
283
284 /* Initialise. */
285 result = 0;
286
287 /* Check the global error status. */
288 if ( !astOK ) return result;
289
290 /* Obtain pointers to the two SwitchMap structures. */
291 this = (AstSwitchMap *) this_object;
292 that = (AstSwitchMap *) that_object;
293
294 /* Check the second object is a SwitchMap. We know the first is a
295 SwitchMap since we have arrived at this implementation of the virtual
296 function. */
297 if( astIsASwitchMap( that ) ) {
298
299 /* Check they have the same number of route mappings. */
300 nroute = this->nroute;
301 if( that->nroute == nroute ) {
302
303 /* Get the forward selector Mappings from the two SwitchMaps. */
304 fsmap1 = GetSelector( this, 1, &fsinv1, status );
305 fsmap2 = GetSelector( that, 1, &fsinv2, status );
306
307 /* Are they equal? */
308 if( ( !fsmap1 && !fsmap2 ) ||
309 ( fsmap1 && fsmap2 && astEqual( fsmap1, fsmap2 ) ) ) {
310
311 /* Get the inverse selector Mappings from the two SwitchMaps. */
312 ismap1 = GetSelector( this, 0, &isinv1, status );
313 ismap2 = GetSelector( that, 0, &isinv2, status );
314
315 /* Are they equal? */
316 if( ( !ismap1 && !ismap2 ) ||
317 ( ismap1 && ismap2 && astEqual( ismap1, ismap2 ) ) ) {
318
319 /* Loop over the route mappings, breaking as soon as two unequal route
320 Mappings are found. Re-instate the original values for the route
321 Mapping Invert flag after testing the route Mappings for equality. */
322 result = 1;
323 for( i = 0; result && i < nroute; i++ ) {
324 rmap1 = GetRoute( this, (double) ( i + 1 ), &rinv1, status );
325 rmap2 = GetRoute( that, (double) ( i + 1 ), &rinv2, status );
326 if( !astEqual( rmap1, rmap2 ) ) result = 0;
327 astSetInvert( rmap2, rinv2 );
328 astSetInvert( rmap1, rinv1 );
329 }
330 }
331
332 /* Reinstate the invert flags for the inverse selector Mappings. Ensure
333 this is done in the opposite order to which the selector Mappings were
334 obtained (in case they are in fact the same Mapping). */
335 if( ismap2 ) astSetInvert( ismap2, isinv2 );
336 if( ismap1 ) astSetInvert( ismap1, isinv1 );
337 }
338
339 /* Reinstate the invert flags for the forward selector Mappings. Ensure
340 this is done in the oppsote order to which the selector Mappings were
341 obtained (in case they are in fact the same Mapping). */
342 if( fsmap2 ) astSetInvert( fsmap2, fsinv2 );
343 if( fsmap1 ) astSetInvert( fsmap1, fsinv1 );
344 }
345 }
346
347 /* If an error occurred, clear the result value. */
348 if ( !astOK ) result = 0;
349
350 /* Return the result, */
351 return result;
352 }
353
GetObjSize(AstObject * this_object,int * status)354 static int GetObjSize( AstObject *this_object, int *status ) {
355 /*
356 * Name:
357 * GetObjSize
358
359 * Purpose:
360 * Return the in-memory size of an Object.
361
362 * Type:
363 * Private function.
364
365 * Synopsis:
366 * #include "switchmap.h"
367 * int GetObjSize( AstObject *this, int *status )
368
369 * Class Membership:
370 * SwitchMap member function (over-rides the astGetObjSize protected
371 * method inherited from the parent class).
372
373 * Description:
374 * This function returns the in-memory size of the supplied SwitchMap,
375 * in bytes.
376
377 * Parameters:
378 * this
379 * Pointer to the SwitchMap.
380 * status
381 * Pointer to the inherited status variable.
382
383 * Returned Value:
384 * The Object size, in bytes.
385
386 * Notes:
387 * - A value of zero will be returned if this function is invoked
388 * with the global status set, or if it should fail for any reason.
389 */
390
391 /* Local Variables: */
392 AstSwitchMap *this;
393 int i;
394 int result;
395
396 /* Initialise. */
397 result = 0;
398
399 /* Check the global error status. */
400 if ( !astOK ) return result;
401
402 /* Obtain a pointers to the SwitchMap structure. */
403 this = (AstSwitchMap *) this_object;
404
405 /* Invoke the GetObjSize method inherited from the parent class, and then
406 add on any components of the class structure defined by this class
407 which are stored in dynamically allocated memory. */
408 result = (*parent_getobjsize)( this_object, status );
409
410 result += astGetObjSize( this->fsmap );
411 result += astGetObjSize( this->ismap );
412
413 for( i = 0; i < this->nroute; i++ ) {
414 result += astGetObjSize( this->routemap[ i ] );
415 }
416
417 result += astGetObjSize( this->routeinv );
418
419 /* If an error occurred, clear the result value. */
420 if ( !astOK ) result = 0;
421
422 /* Return the result, */
423 return result;
424 }
425
GetRoute(AstSwitchMap * this,double sel,int * inv,int * status)426 static AstMapping *GetRoute( AstSwitchMap *this, double sel, int *inv, int *status ){
427 /*
428 * Name:
429 * GetRoute
430
431 * Purpose:
432 * Return a pointer to a route Mapping, handling all Invert flags.
433
434 * Type:
435 * Private function.
436
437 * Synopsis:
438 * #include "switchmap.h"
439 * AstMapping *GetRoute( AstSwitchMap *this, double sel, int *inv, int *status )
440
441 * Class Membership:
442 * SwitchMap method.
443
444 * Description:
445 * This function returns a pointer to a route Mapping (specified by a
446 * floating point selector value) for the given SwitchMap, taking account
447 * of the state of the Invert flag of both the route Mapping and the
448 * SwitchMap.
449
450 * Parameters:
451 * this
452 * Pointer to the SwitchMap.
453 * sel
454 * The selector value. The nearest integer value (minus 1) is used
455 * to index the array of route Mappings stored in the SwitchMap. A
456 * NULL pointer is returned if the selector value is out of range.
457 * inv
458 * Pointer to an int in which to return the original value of the
459 * Invert flag of the returned Mapping. The astSetInvert method
460 * should be used to re-instate this value once all use of the Mapping
461 * has been completed.
462 * status
463 * Pointer to the inherited status variable.
464
465 * Returns:
466 * A pointer to the route Mapping to use. Note, the returned pointer
467 * should NOT be annulled when no longer needed. NULL is returned
468 * (without error) if the SwitchMap does not have a route Mapping for the
469 * requested selector value. The forward transformation of the
470 * returned Mapping will implenment the forward transformation of the
471 * required route Mapping (and vice-versa).
472
473 */
474
475 /* Local Variables: */
476 AstMapping *ret;
477 int rindex;
478
479 /* Initialise */
480 ret = NULL;
481
482 /* Check the global error status. */
483 if ( !astOK ) return ret;
484
485 /* Check selector value is good. */
486 if( sel != AST__BAD ) {
487
488 /* Convert the supplied floating point selector value into an integer
489 index into the array of route Mappings held in the supplied SwitchMap. */
490 rindex = (int)( sel + 0.5 ) - 1;
491
492 /* Return the null pointer if the index is out of range. */
493 if( rindex >= 0 && rindex < this->nroute ) {
494
495 /* Get the required route Mapping. */
496 ret = ( this->routemap )[ rindex ];
497
498 /* Return its original invert flag. */
499 *inv = astGetInvert( ret );
500
501 /* Set the Invert flag back to the value it had when the SwitchMap was
502 created. */
503 astSetInvert( ret, this->routeinv[ rindex ] );
504
505 /* If the SwitchMap has since been inverted, also invert the returned
506 route Mapping, so that the forward transformation of the returned
507 Mapping implements the forward transformation of the supplied
508 SwitchMap (and vice-versa). */
509 if( astGetInvert( this ) ) astInvert( ret );
510 }
511 }
512
513 /* Return the pointer. */
514 return ret;
515
516 }
517
GetSelector(AstSwitchMap * this,int fwd,int * inv,int * status)518 static AstMapping *GetSelector( AstSwitchMap *this, int fwd, int *inv, int *status ){
519 /*
520 * Name:
521 * GetSelector
522
523 * Purpose:
524 * Return a pointer to a selector Mapping, handling all Invert flags.
525
526 * Type:
527 * Private function.
528
529 * Synopsis:
530 * #include "switchmap.h"
531 * AstMapping *GetSelector( AstSwitchMap *this, int fwd, int *inv, int *status )
532
533 * Class Membership:
534 * SwitchMap method.
535
536 * Description:
537 * This function returns a pointer to either the forward or inverse
538 * selector Mapping for the given SwitchMap, taking account of the
539 * state of the Invert flag of bothe the selector Mapping and the
540 * SwitchMap.
541
542 * Parameters:
543 * this
544 * Pointer to the SwitchMap.
545 * fwd
546 * If non-zero, return the forward selector Mapping. Otherwise,
547 * return the inverse selector Mapping.
548 * inv
549 * Pointer to an int in which to return the original value of the
550 * Invert flag of the returned Mapping. The astSetInvert method
551 * should be used to re-instate this value once all use of the Mapping
552 * has been completed.
553 * status
554 * Pointer to the inherited status variable.
555
556 * Returns:
557 * A pointer to the selector Mapping to use. Note, the returned pointer
558 * should NOT be annulled when no longer needed. NULL is returned
559 * (without error) if the SwitchMap does not have a Mapping for the
560 * requested selector.
561
562 */
563
564 /* Local Variables: */
565 AstMapping *ret;
566 int swinv;
567
568 /* Initialise */
569 ret = NULL;
570
571 /* Check the global error status. */
572 if ( !astOK ) return ret;
573
574 /* See if the SwitchMap has been inverted. */
575 swinv = astGetInvert( this );
576
577 /* If the SwitchMap has been inverted, the forward and inverse selector
578 Mappings should be reversed. */
579 if( ( !swinv && !fwd ) || ( swinv && fwd ) ){
580 ret = this->ismap;
581 if( ret ) {
582 *inv = astGetInvert( ret );
583 astSetInvert( ret, this->isinv );
584 }
585
586 } else {
587 ret = this->fsmap;
588 if( ret ) {
589 *inv = astGetInvert( ret );
590 astSetInvert( ret, this->fsinv );
591 }
592 }
593
594 if( ret && swinv ) astInvert( ret );
595
596 /* Return the pointer. */
597 return ret;
598
599 }
600
astInitSwitchMapVtab_(AstSwitchMapVtab * vtab,const char * name,int * status)601 void astInitSwitchMapVtab_( AstSwitchMapVtab *vtab, const char *name, int *status ) {
602 /*
603 *+
604 * Name:
605 * astInitSwitchMapVtab
606
607 * Purpose:
608 * Initialise a virtual function table for a SwitchMap.
609
610 * Type:
611 * Protected function.
612
613 * Synopsis:
614 * #include "switchmap.h"
615 * void astInitSwitchMapVtab( AstSwitchMapVtab *vtab, const char *name )
616
617 * Class Membership:
618 * SwitchMap vtab initialiser.
619
620 * Description:
621 * This function initialises the component of a virtual function
622 * table which is used by the SwitchMap class.
623
624 * Parameters:
625 * vtab
626 * Pointer to the virtual function table. The components used by
627 * all ancestral classes will be initialised if they have not already
628 * been initialised.
629 * name
630 * Pointer to a constant null-terminated character string which contains
631 * the name of the class to which the virtual function table belongs (it
632 * is this pointer value that will subsequently be returned by the Object
633 * astClass function).
634 *-
635 */
636
637 /* Local Variables: */
638 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
639 AstObjectVtab *object; /* Pointer to Object component of Vtab */
640 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
641
642 /* Check the local error status. */
643 if ( !astOK ) return;
644
645 /* Get a pointer to the thread specific global data structure. */
646 astGET_GLOBALS(NULL);
647
648 /* Initialize the component of the virtual function table used by the
649 parent class. */
650 astInitMappingVtab( (AstMappingVtab *) vtab, name );
651
652 /* Store a unique "magic" value in the virtual function table. This
653 will be used (by astIsASwitchMap) to determine if an object belongs to
654 this class. We can conveniently use the address of the (static)
655 class_check variable to generate this unique value. */
656 vtab->id.check = &class_check;
657 vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
658
659 /* Initialise member function pointers. */
660 /* ------------------------------------ */
661 /* Store pointers to the member functions (implemented here) that
662 provide virtual methods for this class. */
663
664 /* None. */
665
666 /* Save the inherited pointers to methods that will be extended, and
667 replace them with pointers to the new member functions. */
668 object = (AstObjectVtab *) vtab;
669 mapping = (AstMappingVtab *) vtab;
670 parent_getobjsize = object->GetObjSize;
671 object->GetObjSize = GetObjSize;
672
673 #if defined(THREAD_SAFE)
674 parent_managelock = object->ManageLock;
675 object->ManageLock = ManageLock;
676 #endif
677
678 parent_transform = mapping->Transform;
679 mapping->Transform = Transform;
680
681 /* Store replacement pointers for methods which will be over-ridden by
682 new member functions implemented here. */
683 object->Equal = Equal;
684 mapping->MapMerge = MapMerge;
685 mapping->Rate = Rate;
686 mapping->RemoveRegions = RemoveRegions;
687
688 /* Declare the copy constructor, destructor and class dump function. */
689 astSetCopy( vtab, Copy );
690 astSetDelete( vtab, Delete );
691 astSetDump( vtab, Dump, "SwitchMap", "Alternate regionalised Mapping" );
692
693 /* If we have just initialised the vtab for the current class, indicate
694 that the vtab is now initialised, and store a pointer to the class
695 identifier in the base "object" level of the vtab. */
696 if( vtab == &class_vtab ) {
697 class_init = 1;
698 astSetVtabClassIdentifier( vtab, &(vtab->id) );
699 }
700 }
701
702 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)703 static int ManageLock( AstObject *this_object, int mode, int extra,
704 AstObject **fail, int *status ) {
705 /*
706 * Name:
707 * ManageLock
708
709 * Purpose:
710 * Manage the thread lock on an Object.
711
712 * Type:
713 * Private function.
714
715 * Synopsis:
716 * #include "object.h"
717 * AstObject *ManageLock( AstObject *this, int mode, int extra,
718 * AstObject **fail, int *status )
719
720 * Class Membership:
721 * SwitchMap member function (over-rides the astManageLock protected
722 * method inherited from the parent class).
723
724 * Description:
725 * This function manages the thread lock on the supplied Object. The
726 * lock can be locked, unlocked or checked by this function as
727 * deteremined by parameter "mode". See astLock for details of the way
728 * these locks are used.
729
730 * Parameters:
731 * this
732 * Pointer to the Object.
733 * mode
734 * An integer flag indicating what the function should do:
735 *
736 * AST__LOCK: Lock the Object for exclusive use by the calling
737 * thread. The "extra" value indicates what should be done if the
738 * Object is already locked (wait or report an error - see astLock).
739 *
740 * AST__UNLOCK: Unlock the Object for use by other threads.
741 *
742 * AST__CHECKLOCK: Check that the object is locked for use by the
743 * calling thread (report an error if not).
744 * extra
745 * Extra mode-specific information.
746 * fail
747 * If a non-zero function value is returned, a pointer to the
748 * Object that caused the failure is returned at "*fail". This may
749 * be "this" or it may be an Object contained within "this". Note,
750 * the Object's reference count is not incremented, and so the
751 * returned pointer should not be annulled. A NULL pointer is
752 * returned if this function returns a value of zero.
753 * status
754 * Pointer to the inherited status variable.
755
756 * Returned Value:
757 * A local status value:
758 * 0 - Success
759 * 1 - Could not lock or unlock the object because it was already
760 * locked by another thread.
761 * 2 - Failed to lock a POSIX mutex
762 * 3 - Failed to unlock a POSIX mutex
763 * 4 - Bad "mode" value supplied.
764
765 * Notes:
766 * - This function attempts to execute even if an error has already
767 * occurred.
768 */
769
770 /* Local Variables: */
771 AstSwitchMap *this; /* Pointer to SwitchMap structure */
772 int i; /* Loop count */
773 int result; /* Returned status value */
774
775 /* Initialise */
776 result = 0;
777
778 /* Check the supplied pointer is not NULL. */
779 if( !this_object ) return result;
780
781 /* Obtain a pointers to the SwitchMap structure. */
782 this = (AstSwitchMap *) this_object;
783
784 /* Invoke the ManageLock method inherited from the parent class. */
785 if( !result ) result = (*parent_managelock)( this_object, mode, extra,
786 fail, status );
787
788 /* Invoke the astManageLock method on any Objects contained within
789 the supplied Object. */
790 if( !result ) result = astManageLock( this->fsmap, mode, extra, fail );
791 if( !result ) result = astManageLock( this->ismap, mode, extra, fail );
792 for( i = 0; i < this->nroute; i++ ) {
793 if( !result ) result = astManageLock( this->routemap[ i ], mode,
794 extra, fail );
795 }
796
797 return result;
798
799 }
800 #endif
801
MapMerge(AstMapping * this,int where,int series,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)802 static int MapMerge( AstMapping *this, int where, int series, int *nmap,
803 AstMapping ***map_list, int **invert_list, int *status ) {
804 /*
805 * Name:
806 * MapMerge
807
808 * Purpose:
809 * Simplify a sequence of Mappings containing a SwitchMap.
810
811 * Type:
812 * Private function.
813
814 * Synopsis:
815 * #include "mapping.h"
816 * int MapMerge( AstMapping *this, int where, int series, int *nmap,
817 * AstMapping ***map_list, int **invert_list, int *status )
818
819 * Class Membership:
820 * SwitchMap method (over-rides the protected astMapMerge method
821 * inherited from the Mapping class).
822
823 * Description:
824 * This function attempts to simplify a sequence of Mappings by
825 * merging a nominated SwitchMap in the sequence with its neighbours,
826 * so as to shorten the sequence if possible.
827 *
828 * In many cases, simplification will not be possible and the
829 * function will return -1 to indicate this, without further
830 * action.
831 *
832 * In most cases of interest, however, this function will either
833 * attempt to replace the nominated SwitchMap with one which it
834 * considers simpler, or to merge it with the Mappings which
835 * immediately precede it or follow it in the sequence (both will
836 * normally be considered). This is sufficient to ensure the
837 * eventual simplification of most Mapping sequences by repeated
838 * application of this function.
839 *
840 * In some cases, the function may attempt more elaborate
841 * simplification, involving any number of other Mappings in the
842 * sequence. It is not restricted in the type or scope of
843 * simplification it may perform, but will normally only attempt
844 * elaborate simplification in cases where a more straightforward
845 * approach is not adequate.
846
847 * Parameters:
848 * this
849 * Pointer to the nominated SwitchMap which is to be merged with
850 * its neighbours. This should be a cloned copy of the SwitchMap
851 * pointer contained in the array element "(*map_list)[where]"
852 * (see below). This pointer will not be annulled, and the
853 * SwitchMap it identifies will not be modified by this function.
854 * where
855 * Index in the "*map_list" array (below) at which the pointer
856 * to the nominated SwitchMap resides.
857 * series
858 * A non-zero value indicates that the sequence of Mappings to
859 * be simplified will be applied in series (i.e. one after the
860 * other), whereas a zero value indicates that they will be
861 * applied in parallel (i.e. on successive sub-sets of the
862 * input/output coordinates).
863 * nmap
864 * Address of an int which counts the number of Mappings in the
865 * sequence. On entry this should be set to the initial number
866 * of Mappings. On exit it will be updated to record the number
867 * of Mappings remaining after simplification.
868 * map_list
869 * Address of a pointer to a dynamically allocated array of
870 * Mapping pointers (produced, for example, by the astMapList
871 * method) which identifies the sequence of Mappings. On entry,
872 * the initial sequence of Mappings to be simplified should be
873 * supplied.
874 *
875 * On exit, the contents of this array will be modified to
876 * reflect any simplification carried out. Any form of
877 * simplification may be performed. This may involve any of: (a)
878 * removing Mappings by annulling any of the pointers supplied,
879 * (b) replacing them with pointers to new Mappings, (c)
880 * inserting additional Mappings and (d) changing their order.
881 *
882 * The intention is to reduce the number of Mappings in the
883 * sequence, if possible, and any reduction will be reflected in
884 * the value of "*nmap" returned. However, simplifications which
885 * do not reduce the length of the sequence (but improve its
886 * execution time, for example) may also be performed, and the
887 * sequence might conceivably increase in length (but normally
888 * only in order to split up a Mapping into pieces that can be
889 * more easily merged with their neighbours on subsequent
890 * invocations of this function).
891 *
892 * If Mappings are removed from the sequence, any gaps that
893 * remain will be closed up, by moving subsequent Mapping
894 * pointers along in the array, so that vacated elements occur
895 * at the end. If the sequence increases in length, the array
896 * will be extended (and its pointer updated) if necessary to
897 * accommodate any new elements.
898 *
899 * Note that any (or all) of the Mapping pointers supplied in
900 * this array may be annulled by this function, but the Mappings
901 * to which they refer are not modified in any way (although
902 * they may, of course, be deleted if the annulled pointer is
903 * the final one).
904 * invert_list
905 * Address of a pointer to a dynamically allocated array which,
906 * on entry, should contain values to be assigned to the Invert
907 * attributes of the Mappings identified in the "*map_list"
908 * array before they are applied (this array might have been
909 * produced, for example, by the astMapList method). These
910 * values will be used by this function instead of the actual
911 * Invert attributes of the Mappings supplied, which are
912 * ignored.
913 *
914 * On exit, the contents of this array will be updated to
915 * correspond with the possibly modified contents of the
916 * "*map_list" array. If the Mapping sequence increases in
917 * length, the "*invert_list" array will be extended (and its
918 * pointer updated) if necessary to accommodate any new
919 * elements.
920 * status
921 * Pointer to the inherited status variable.
922
923 * Returned Value:
924 * If simplification was possible, the function returns the index
925 * in the "map_list" array of the first element which was
926 * modified. Otherwise, it returns -1 (and makes no changes to the
927 * arrays supplied).
928
929 * Notes:
930 * - A value of -1 will be returned if this function is invoked
931 * with the global error status set, or if it should fail for any
932 * reason.
933 */
934
935 /* Local Variables: */
936 AstSwitchMap *map;
937 AstMapping *new;
938 int i;
939 int nroute;
940 int result;
941 int fsinv_old;
942 int isinv_old;
943 int *rinv_old;
944 AstMapping *sfsmap;
945 AstMapping *sismap;
946 int simp;
947 AstMapping **srmap;
948 AstSwitchMap *swneb;
949 int ilo;
950 int equal;
951
952 /* Initialise.*/
953 result = -1;
954
955 /* Check the inherited status. */
956 if ( !astOK ) return result;
957
958 /* Get a pointer to this SwitchMap, and note the number of route Mappings. */
959 map = (AstSwitchMap *) this;
960 nroute = map->nroute;
961
962 /* Temporarily put the Invert flag of all encapsulated Mappings (both
963 route and selector) back to the values they had when the SwitchMap was
964 created, noting their current values so that they can be re-instated
965 later. If the SwitchMap itself has been inverted, swap all the original
966 invert flags. */
967 if( map->fsmap ) {
968 fsinv_old = astGetInvert( map->fsmap );
969 astSetInvert( map->fsmap, map->fsinv );
970 } else {
971 fsinv_old = 0;
972 }
973
974 if( map->ismap ) {
975 isinv_old = astGetInvert( map->ismap );
976 astSetInvert( map->ismap, map->isinv );
977 } else {
978 isinv_old = 0;
979 }
980
981 rinv_old = astMalloc( sizeof( int )*nroute );
982 if( astOK ) {
983 for( i = 0; i < nroute; i++ ) {
984 rinv_old[ i ] = astGetInvert( map->routemap[ i ] );
985 astSetInvert( map->routemap[ i ], map->routeinv[ i ] );
986 }
987 }
988
989 /* If possible, merge the SwitchMap with a neighbouring SwitchMap. */
990 /* =============================================================== */
991 /* Only do this if we are combining the Mappings in series. */
992 if( series ) {
993
994 /* Is the higher neighbour a SwitchMap? If so get a pointer to it, and
995 note the index of the lower of the two adjacent SwitchMaps. */
996 if( where < ( *nmap - 1 ) &&
997 astIsASwitchMap( ( *map_list )[ where + 1 ] ) ){
998 swneb = (AstSwitchMap *) ( *map_list )[ where + 1 ];
999 ilo = where;
1000
1001 /* If not, is the lower neighbour a SwitchMap? If so get a pointer to it, and
1002 note the index of the lower of the two adjacent SwitchMaps. */
1003 } else if( where > 0 &&
1004 astIsASwitchMap( ( *map_list )[ where - 1 ] ) ){
1005 swneb = (AstSwitchMap *) ( *map_list )[ where - 1 ];
1006 ilo = where - 1;
1007
1008 } else {
1009 swneb = NULL;
1010 }
1011
1012 /* If a neighbouring SwitchMap was found, we can replace the pair by a
1013 UnitMap if the two SwitchMaps are equal but have opposite values for
1014 their Invert flags. Temporarily invert the neighbour, then compare
1015 the two SwitchMaps for equality, then re-invert the neighbour. */
1016 if( swneb ) {
1017 astInvert( swneb );
1018 equal = astEqual( map, swneb );
1019 astInvert( swneb );
1020
1021 /* If the two SwitchMaps are equal but opposite, annul the first of the two
1022 Mappings, and replace it with a UnitMap. Also set the invert flag. */
1023 if( equal ) {
1024 new = (AstMapping *) astUnitMap( astGetNin( ( *map_list )[ ilo ] ), "", status );
1025 (void) astAnnul( ( *map_list )[ ilo ] );
1026 ( *map_list )[ ilo ] = new;
1027 ( *invert_list )[ ilo ] = 0;
1028
1029 /* Annul the second of the two Mappings, and shuffle down the rest of the
1030 list to fill the gap. */
1031 (void) astAnnul( ( *map_list )[ ilo + 1 ] );
1032 for ( i = ilo + 2; i < *nmap; i++ ) {
1033 ( *map_list )[ i - 1 ] = ( *map_list )[ i ];
1034 ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ];
1035 }
1036
1037 /* Clear the vacated element at the end. */
1038 ( *map_list )[ *nmap - 1 ] = NULL;
1039 ( *invert_list )[ *nmap - 1 ] = 0;
1040
1041 /* Decrement the Mapping count and return the index of the first
1042 modified element. */
1043 ( *nmap )--;
1044 result = where;
1045 }
1046 }
1047 }
1048
1049 /* Attempt to simplify the SwitchMap on its own. */
1050 /* ============================================= */
1051 /* Only do this if no change was made above. */
1052 if( result == -1 ) {
1053
1054 /* If the SwitchMap is inverted, create an equal SwitchMap which is not
1055 inverted. To do this, invert and swap the selector Mappings, and
1056 invert all the route Mappings. We use astSetInvert rather than astInvert
1057 because two or more more stored pointers may point to the same Mapping
1058 in which case that Mapping would be inverted more than once with
1059 unpredictable results. */
1060 if( ( *invert_list )[ where ] ) {
1061 if( map->fsmap ) astSetInvert( map->fsmap, !(map->fsinv) );
1062 if( map->ismap ) astSetInvert( map->ismap, !(map->isinv) );
1063 for( i = 0; i < nroute; i++ ) {
1064 astSetInvert( map->routemap[ i ], !(map->routeinv[ i ]) );
1065 }
1066
1067 new = (AstMapping *) astSwitchMap( map->ismap, map->fsmap, nroute, (void **) map->routemap, "", status );
1068
1069 (void) astAnnul( ( *map_list )[ where ] );
1070 ( *map_list )[ where ] = (AstMapping *) new;
1071 ( *invert_list )[ where ] = 0;
1072 result = where;
1073
1074 /* Otherwise, try to simplify each of the encapsulated Mappings, noting
1075 if any simplification takes place. */
1076 } else {
1077 sfsmap = ( map->fsmap ) ? astSimplify( map->fsmap ) : NULL;
1078 sismap = ( map->ismap ) ? astSimplify( map->ismap ) : NULL;
1079 simp = ( sfsmap != map->fsmap ) || ( sismap != map->ismap );
1080
1081 srmap = astMalloc( sizeof( AstMapping * )*nroute );
1082 if( astOK ) {
1083 for( i = 0; i < nroute; i++ ) {
1084 srmap[ i ] = astSimplify( map->routemap[ i ] );
1085 simp = simp || ( srmap[ i ] != map->routemap[ i ] );
1086 }
1087 }
1088
1089 /* If any simplification took place, construct a new SwitchMap from these
1090 simplified Mappings. */
1091 if( simp ) {
1092 (void) astAnnul( ( *map_list )[ where ] );
1093 ( *map_list )[ where ] = (AstMapping *) astSwitchMap( sfsmap, sismap,
1094 nroute, (void **) srmap, "", status );
1095 result = where;
1096 }
1097
1098 /* Release resources. */
1099 if( sfsmap ) sfsmap = astAnnul( sfsmap );
1100 if( sismap ) sismap = astAnnul( sismap );
1101 if( srmap ) {
1102 for( i = 0; i < nroute; i++ ) srmap[ i ] = astAnnul( srmap[ i ] );
1103 srmap = astFree( srmap );
1104 }
1105 }
1106 }
1107
1108 /* Re-instate the original Invert values for the encapsulated Mappings. */
1109 if( map->fsmap ) astSetInvert( map->fsmap, fsinv_old );
1110 if( map->ismap ) astSetInvert( map->ismap, isinv_old );
1111 if( rinv_old ) {
1112 for( i = 0; i < nroute; i++ ) {
1113 astSetInvert( map->routemap[ i ], rinv_old[ i ] );
1114 }
1115 rinv_old = astFree( rinv_old );
1116 }
1117
1118 /* If an error occurred, clear the result value. */
1119 if ( !astOK ) result = -1;
1120
1121 /* Return the result. */
1122 return result;
1123 }
1124
Rate(AstMapping * this,double * at,int ax1,int ax2,int * status)1125 static double Rate( AstMapping *this, double *at, int ax1, int ax2, int *status ){
1126 /*
1127 * Name:
1128 * Rate
1129
1130 * Purpose:
1131 * Calculate the rate of change of a Mapping output.
1132
1133 * Type:
1134 * Private function.
1135
1136 * Synopsis:
1137 * #include "switchmap.h"
1138 * result = Rate( AstMapping *this, double *at, int ax1, int ax2, int *status )
1139
1140 * Class Membership:
1141 * SwitchMap member function (overrides the astRate method inherited
1142 * from the Mapping class ).
1143
1144 * Description:
1145 * This function returns the rate of change of a specified output of
1146 * the supplied Mapping with respect to a specified input, at a
1147 * specified input position. Also evaluates the second derivative.
1148
1149 * Parameters:
1150 * this
1151 * Pointer to the Mapping to be applied.
1152 * at
1153 * The address of an array holding the axis values at the position
1154 * at which the rate of change is to be evaluated. The number of
1155 * elements in this array should equal the number of inputs to the
1156 * Mapping.
1157 * ax1
1158 * The index of the Mapping output for which the rate of change is to
1159 * be found (output numbering starts at 0 for the first output).
1160 * ax2
1161 * The index of the Mapping input which is to be varied in order to
1162 * find the rate of change (input numbering starts at 0 for the first
1163 * input).
1164 * status
1165 * Pointer to the inherited status variable.
1166
1167 * Returned Value:
1168 * The rate of change of Mapping output "ax1" with respect to input
1169 * "ax2", evaluated at "at", or AST__BAD if the value cannot be
1170 * calculated.
1171
1172 */
1173
1174 /* Local Variables: */
1175 AstSwitchMap *map;
1176 AstMapping *smap;
1177 AstMapping *rmap;
1178 double result;
1179 double sel;
1180 int fsinv;
1181 int rinv;
1182 int nin;
1183
1184 /* Initialise. */
1185 result = AST__BAD;
1186
1187 /* Check inherited status */
1188 if( !astOK ) return result;
1189
1190 /* Get a pointer to the SwitchMap structure. */
1191 map = (AstSwitchMap *) this;
1192
1193 /* Get a pointer to the effective foward selector Mapping, and its current
1194 invert flag (this takes account of whether the SwtichMap has been
1195 inverted or not). This call resets the selector's invert flag temporarily
1196 back to the value it had when the SwitchMap was created. */
1197 smap = GetSelector( map, 1, &fsinv, status );
1198
1199 /* If the SwitchMap has no forward selector Mapping, return AST__BAD. */
1200 if( smap ) {
1201
1202 /* Get the number of inputs */
1203 nin = astGetNin( smap );
1204
1205 /* Transform the supplied position using the selector Mapping. The output
1206 value is the selector value that indicates which route Mapping to use. */
1207 astTranN( smap, 1, nin, 1, at, 1, 1, 1, &sel );
1208
1209 /* Get the index of the route Mapping to use, and check it is valid (if
1210 not, return AST__BAD if not). This takes account of whether the
1211 SwitchMap has been inverted, and also temporarily re-instates the
1212 original value of the route Mapping's Invert flag . */
1213 rmap = GetRoute( map, sel, &rinv, status );
1214 if( rmap ) {
1215
1216 /* Use the astRate method of the route Mapping. */
1217 result = astRate( rmap, at, ax1, ax2 );
1218
1219 /* Reset the Invert flag for the route Mapping. */
1220 astSetInvert( rmap, rinv );
1221 }
1222
1223 /* Reset the Invert flag for the selector Mapping. */
1224 astSetInvert( smap, fsinv );
1225 }
1226
1227 /* Return the result. */
1228 return result;
1229 }
1230
RemoveRegions(AstMapping * this_mapping,int * status)1231 static AstMapping *RemoveRegions( AstMapping *this_mapping, int *status ) {
1232 /*
1233 * Name:
1234 * RemoveRegions
1235
1236 * Purpose:
1237 * Remove any Regions from a Mapping.
1238
1239 * Type:
1240 * Private function.
1241
1242 * Synopsis:
1243 * #include "switchmap.h"
1244 * AstMapping *RemoveRegions( AstMapping *this, int *status )
1245
1246 * Class Membership:
1247 * SwitchMap method (over-rides the astRemoveRegions method inherited
1248 * from the Mapping class).
1249
1250 * Description:
1251 * This function searches the supplied Mapping (which may be a
1252 * compound Mapping such as a SwitchMap) for any component Mappings
1253 * that are instances of the AST Region class. It then creates a new
1254 * Mapping from which all Regions have been removed. If a Region
1255 * cannot simply be removed (for instance, if it is a component of a
1256 * parallel SwitchMap), then it is replaced with an equivalent UnitMap
1257 * in the returned Mapping.
1258 *
1259 * The implementation provided by the SwitchMap class invokes the
1260 * astRemoveRegions method on all the component Mappings, and joins
1261 * the results together into a new SwitchMap.
1262
1263 * Parameters:
1264 * this
1265 * Pointer to the original Region.
1266 * status
1267 * Pointer to the inherited status variable.
1268
1269 * Returned Value:
1270 * A pointer to the modified mapping.
1271
1272 * Notes:
1273 * - A NULL pointer value will be returned if this function is
1274 * invoked with the AST error status set, or if it should fail for
1275 * any reason.
1276 */
1277
1278 /* Local Variables: */
1279 AstMapping **temp; /* Array of new route Mappings */
1280 AstMapping *newfsmap; /* New forward selector Mapping */
1281 AstMapping *newismap; /* New inverse selector Mapping */
1282 AstMapping *result; /* Result pointer to return */
1283 AstSwitchMap *new; /* Pointer to new SwitchMap */
1284 AstSwitchMap *this; /* Pointer to SwitchMap structure */
1285 int changed; /* Has any mapping been changed? */
1286 int i; /* Loop count */
1287 int nax; /* Number of Frame axes */
1288
1289 /* Initialise. */
1290 result = NULL;
1291
1292 /* Check the global error status. */
1293 if ( !astOK ) return result;
1294
1295 /* Get a pointer to the SwitchMap. */
1296 this = (AstSwitchMap *) this_mapping;
1297
1298 /* Allocate an array to hold the modified Mapping pointers. */
1299 temp = astMalloc( sizeof( AstMapping *)*( this->nroute ) );
1300 if( astOK ) {
1301
1302 /* Invoke the astRemoveRegions method on all the component Mappings. */
1303 changed = 0;
1304 for( i = 0; i < this->nroute; i++ ) {
1305 temp[ i ] = astRemoveRegions( this->routemap[ i ] );
1306
1307 /* Note if any Mapping was changed. */
1308 if( temp[ i ] != this->routemap[ i ] ) {
1309 changed = 1;
1310
1311 /* The implementation of the astRemoveRegions method provided by the
1312 Region class returns a Frame rather than a UnitMap. But we need
1313 Mappings here, not Frames. So if the new Mapping is a Frame, replace
1314 it with an equivalent UnitMap. */
1315 if( astIsAFrame( temp[ i ] ) ) {
1316 nax = astGetNin( temp[ i ] );
1317 (void) astAnnul( temp[ i ] );
1318 temp[ i ] = (AstMapping *) astUnitMap( nax, " ", status );
1319 }
1320 }
1321 }
1322
1323 /* And on the other ancillary Mappings */
1324 if( this->fsmap ) {
1325 newfsmap = astRemoveRegions( this->fsmap );
1326 if( newfsmap != this->fsmap ) {
1327 changed = 1;
1328 if( astIsAFrame( newfsmap ) ) {
1329 nax = astGetNin( newfsmap );
1330 (void) astAnnul( newfsmap );
1331 newfsmap = (AstMapping *) astUnitMap( nax, " ", status );
1332 }
1333 }
1334
1335 } else {
1336 newfsmap = NULL;
1337 }
1338
1339 if( this->ismap ) {
1340 newismap = astRemoveRegions( this->ismap );
1341 if( newismap != this->ismap ) {
1342 changed = 1;
1343 if( astIsAFrame( newismap ) ) {
1344 nax = astGetNin( newismap );
1345 (void) astAnnul( newismap );
1346 newismap = (AstMapping *) astUnitMap( nax, " ", status );
1347 }
1348 }
1349
1350 } else {
1351 newismap = NULL;
1352 }
1353
1354 /* If no component was modified, just return a clone of the supplied
1355 pointer. */
1356 if( ! changed ) {
1357 result = astClone( this );
1358
1359 /* Otherwise, we need to create a new Mapping to return. We take a deep
1360 copy of the supplied SwitchMap and then modify the Mappings so that
1361 we retain any extra information in the supplied SwitchMap. */
1362 } else {
1363 new = astCopy( this );
1364
1365 for( i = 0; i < this->nroute; i++ ) {
1366 (void) astAnnul( new->routemap[ i ] );
1367 new->routemap[ i ] = astClone( temp[ i ] );
1368 }
1369
1370 if( newfsmap ) {
1371 (void) astAnnul( new->fsmap );
1372 new->fsmap = astClone( newfsmap );
1373 }
1374
1375 if( newismap ) {
1376 (void) astAnnul( new->ismap );
1377 new->ismap = astClone( newismap );
1378 }
1379
1380 result = (AstMapping *) new;
1381 }
1382
1383 /* Free resources. */
1384 for( i = 0; i < this->nroute; i++ ) {
1385 temp[ i ] = astAnnul( temp[ i ] );
1386 }
1387
1388 if( newfsmap ) newfsmap = astAnnul( newfsmap );
1389 if( newismap ) newismap = astAnnul( newismap );
1390 }
1391
1392 temp = astFree( temp );
1393
1394 /* Annul the returned Mapping if an error has occurred. */
1395 if( !astOK ) result = astAnnul( result );
1396
1397 /* Return the result. */
1398 return result;
1399 }
1400
astSwitchList_(AstSwitchMap * this,int invert,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)1401 int astSwitchList_( AstSwitchMap *this, int invert, int *nmap,
1402 AstMapping ***map_list, int **invert_list, int *status ) {
1403 /*
1404 *+
1405 * Name:
1406 * astSwitchList
1407
1408 * Purpose:
1409 * Extract the selector and route Mappings from a SwitchMap.
1410
1411 * Type:
1412 * Protected function.
1413
1414 * Synopsis:
1415 * #include "switchmap.h"
1416 * int astSwitchList( AstSwitchMap *this, int invert, int *nmap,
1417 * AstMapping ***map_list, int **invert_list )
1418
1419 * Class Membership:
1420 * SwitchMap member function.
1421
1422 * Description:
1423 * This function extracts the route and selector Mappings form a
1424 * SwitchMap.
1425
1426 * Parameters:
1427 * this
1428 * Pointer to the SwitchMap to be decomposed (it is not actually
1429 * modified by this function).
1430 * invert
1431 * The value to which the SwitchMap's Invert attribute is to be
1432 * (notionally) set before performing the decomposition. Normally,
1433 * the value supplied here will be the actual Invert value obtained
1434 * from the SwitchMap (e.g. using astGetInvert). Sometimes, however,
1435 * when a SwitchMap is encapsulated within another structure, that
1436 * structure may retain an Invert value (in order to prevent external
1437 * interference) which should be used instead.
1438 *
1439 * Note that the actual Invert value of the SwitchMap supplied is
1440 * not used (or modified) by this function.
1441 * nmap
1442 * The address of an int in which to return a count of the number of
1443 * individual Mappings in the decomposition. The supplied value is
1444 * ignored.
1445 * map_list
1446 * Address of a pointer to an array of Mapping pointers. The value
1447 * supplied on entry is ignored. On exit, it points at a dynamically
1448 * allocated array containing Mapping pointers ("*nmap" in number) that
1449 * result from the decomposition requested.
1450 *
1451 * The returned Mapping pointers returned will identify the following
1452 * sequence of Mappings; forward selector mapping (or NULL if the
1453 * SwitchMap has no forward selector Mapping), inverse selector
1454 * mapping (or NULL if the SwitchMap has no inverse selector Mapping),
1455 * the route Mappings in the order they were supplied when the
1456 * SwitchMap was constructed.
1457 *
1458 * All the Mapping pointers returned by this function should be
1459 * annulled by the caller, using astAnnul, when no longer
1460 * required. The dynamic array holding these pointers should
1461 * also be freed, using astFree.
1462 * invert_list
1463 * Address of a pointer to an array of int. The value supplied on
1464 * entry is ignored. On exit, it points at a dynamically allocated
1465 * array containing Invert attribute values ("*nmap" in number) that
1466 * result from the decomposition requested.
1467 *
1468 * The returned Invert values returned identify the values which must
1469 * be assigned to the Invert attributes of the corresponding
1470 * Mappings (whose pointers are in the "*map_list" array) before
1471 * they are applied. Note that these values may differ from the
1472 * actual Invert attribute values of these Mappings, which are
1473 * not relevant.
1474 *
1475 * The dynamic array holding these values should be freed by the
1476 * caller, using astFree, when no longer required.
1477
1478 * Returned Value:
1479 * The number of route Mappings stored in the SwitchMap.
1480
1481 * Notes:
1482 * - It is unspecified to what extent the original SwitchMap and the
1483 * individual (decomposed) Mappings are inter-dependent. Consequently,
1484 * the individual Mappings cannot be modified without risking
1485 * modification of the original SwitchMap.
1486 * - If this function is invoked with the global error status set,
1487 * or if it should fail for any reason, then the *nmap value, the
1488 * list of Mapping pointers and the list of Invert values will all
1489 * be returned unchanged.
1490 *-
1491 */
1492
1493 /* Local Variables: */
1494 AstMapping *map; /* Pointer to Mapping to return */
1495 int inv; /* Original Invert flag for Mapping */
1496 int i; /* Route Mapping index */
1497 int oldinv; /* Original Invert flag for SwitchMap */
1498 int result; /* Returned value */
1499
1500 /* Check the global error status. */
1501 if ( !astOK ) return 0;
1502
1503 /* Store the numbe of route Mappings */
1504 result = this->nroute;
1505 *nmap = result + 2;
1506
1507 /* Allocate the required arrays. */
1508 *map_list = astMalloc( sizeof( AstMapping * )*(size_t) *nmap );
1509 *invert_list = astMalloc( sizeof( int )*(size_t) *nmap );
1510
1511 /* Check the pointers can be used safely. */
1512 if( astOK ) {
1513
1514 /* Temporaily set the requested Invert flag for the SwitchMap. */
1515 oldinv = astGetInvert( this );
1516 astSetInvert( this, invert );
1517
1518 /* Get the forward selector Mapping. */
1519 map = GetSelector( this, 1, &inv, status );
1520
1521 /* If the SwitchMap has a forward selector Mapping, return a clone of the
1522 Mapping pointer, and the invert flag to be used with it, then
1523 re-instate the original invert flag value (which was modified by
1524 GetSelector). */
1525 if( map ) {
1526 ( *map_list )[ 0 ] = astClone( map );
1527 ( *invert_list )[ 0 ] = astGetInvert( map );
1528 astSetInvert( map, inv );
1529
1530 /* If the SwitchMap does not has a forward selector Mapping, return a
1531 NULL pointer. */
1532 } else {
1533 ( *map_list )[ 0 ] = NULL;
1534 ( *invert_list )[ 0 ] = 0;
1535 }
1536
1537 /* Likewise, get and return the inverse selector Mapping.*/
1538 map = GetSelector( this, 0, &inv, status );
1539 if( map ) {
1540 ( *map_list )[ 1 ] = astClone( map );
1541 ( *invert_list )[ 1 ] = astGetInvert( map );
1542 astSetInvert( map, inv );
1543 } else {
1544 ( *map_list )[ 1 ] = NULL;
1545 ( *invert_list )[ 1 ] = 0;
1546 }
1547
1548 /* Loop round all route Mappings. */
1549 for( i = 0; i < result; i++ ){
1550
1551 /* Get the next route Mapping. */
1552 map = GetRoute( this, (double) i + 1.0, &inv, status );
1553
1554 /* If the SwitchMap has a route Mapping for the current selector value,
1555 return a clone of the Mapping pointer, and the invert flag to be used
1556 with it, then re-instate the original invert flag value (which was
1557 modified by GetRoute). */
1558 if( map ) {
1559 ( *map_list )[ i + 2 ] = astClone( map );
1560 ( *invert_list )[ i + 2 ] = astGetInvert( map );
1561 astSetInvert( map, inv );
1562
1563 /* If the SwitchMap does not has a route Mapping for the current selector
1564 value, return a NULL pointer. */
1565 } else {
1566 ( *map_list )[ i + 2 ] = NULL;
1567 ( *invert_list )[ i + 2 ] = 0;
1568 }
1569
1570 }
1571
1572 /* Re-instate the original Ivert flag for the SwitchMap. */
1573 astSetInvert( this, oldinv );
1574
1575 }
1576
1577 /* If an error has occurred, free the returned arrays. */
1578 if( !astOK ) {
1579 *map_list = astFree( *map_list );
1580 *invert_list= astFree( *invert_list );
1581 result= 0;
1582 *nmap = 0;
1583 }
1584
1585 /* Return the result */
1586 return result;
1587 }
1588
Transform(AstMapping * this,AstPointSet * in,int forward,AstPointSet * out,int * status)1589 static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
1590 int forward, AstPointSet *out, int *status ) {
1591 /*
1592 * Name:
1593 * Transform
1594
1595 * Purpose:
1596 * Apply a SwitchMap to transform a set of points.
1597
1598 * Type:
1599 * Private function.
1600
1601 * Synopsis:
1602 * #include "switchmap.h"
1603 * AstPointSet *Transform( AstMapping *this, AstPointSet *in,
1604 * int forward, AstPointSet *out, int *status )
1605
1606 * Class Membership:
1607 * SwitchMap member function (over-rides the astTransform method inherited
1608 * from the Mapping class).
1609
1610 * Description:
1611 * This function takes a SwitchMap and a set of points encapsulated in a
1612 * PointSet and transforms the points so as to apply the required Mapping.
1613 * This implies applying each of the SwitchMap's component Mappings in turn,
1614 * either in series or in parallel.
1615
1616 * Parameters:
1617 * this
1618 * Pointer to the SwitchMap.
1619 * in
1620 * Pointer to the PointSet associated with the input coordinate values.
1621 * forward
1622 * A non-zero value indicates that the forward coordinate transformation
1623 * should be applied, while a zero value requests the inverse
1624 * transformation.
1625 * out
1626 * Pointer to a PointSet which will hold the transformed (output)
1627 * coordinate values. A NULL value may also be given, in which case a
1628 * new PointSet will be created by this function.
1629 * status
1630 * Pointer to the inherited status variable.
1631
1632 * Returned Value:
1633 * Pointer to the output (possibly new) PointSet.
1634
1635 * Notes:
1636 * - A null pointer will be returned if this function is invoked with the
1637 * global error status set, or if it should fail for any reason.
1638 * - The number of coordinate values per point in the input PointSet must
1639 * match the number of coordinates for the SwitchMap being applied.
1640 * - If an output PointSet is supplied, it must have space for sufficient
1641 * number of points and coordinate values per point to accommodate the
1642 * result. Any excess space will be ignored.
1643 */
1644
1645 /* Local Variables: */
1646 AstMapping *rmap;
1647 AstMapping *selmap;
1648 AstPointSet *ps1;
1649 AstPointSet *ps1a;
1650 AstPointSet *ps2;
1651 AstPointSet *ps2a;
1652 AstPointSet *result;
1653 AstPointSet *selps;
1654 AstSwitchMap *map;
1655 double **in_ptr;
1656 double **out_ptr;
1657 double **ptr1;
1658 double **ptr2;
1659 double **sel_ptr;
1660 double *outv;
1661 double *sel;
1662 int *popmap;
1663 int iroute;
1664 int ipoint;
1665 int j;
1666 int k;
1667 int maxpop;
1668 int ncin;
1669 int ncout;
1670 int npoint;
1671 int nroute;
1672 int rindex;
1673 int rinv;
1674 int selinv;
1675 int totpop;
1676
1677 /* Check the global error status. */
1678 if ( !astOK ) return NULL;
1679
1680 /* Obtain a pointer to the SwitchMap. */
1681 map = (AstSwitchMap *) this;
1682
1683 /* Apply the parent Mapping using the stored pointer to the Transform member
1684 function inherited from the parent Mapping class. This function validates
1685 all arguments and generates an output PointSet if necessary, but does not
1686 actually transform any coordinate values. */
1687 result = (*parent_transform)( this, in, forward, out, status );
1688
1689 /* We now extend the parent astTransform method by applying the component
1690 Mappings of the SwitchMap to generate the output coordinate values. */
1691
1692 /* Get the number of input and output coords. */
1693 if( forward ) {
1694 ncin = astGetNin( this );
1695 ncout = astGetNout( this );
1696 } else {
1697 ncin = astGetNout( this );
1698 ncout = astGetNin( this );
1699 }
1700
1701 /* Get the appropriate selector Mapping. */
1702 selmap = GetSelector( map, forward, &selinv, status );
1703
1704 /* Transform the supplied positions using the above selector Mapping. */
1705 selps = astTransform( selmap, in, forward, NULL );
1706
1707 /* Get a pointer to the array holding the selector value. */
1708 sel_ptr = astGetPoints( selps );
1709
1710 /* Get a pointer to the array holding the input values. */
1711 in_ptr = astGetPoints( in );
1712
1713 /* Get a pointer to the array in which to store the results, and the total
1714 number of points being transformed. */
1715 out_ptr = astGetPoints( result );
1716 npoint = astGetNpoint( result );
1717
1718 /* We now count how many positions are to be tranformed by each of the
1719 route Mappings. */
1720 nroute = map->nroute;
1721 popmap = astMalloc( sizeof( int )*nroute );
1722 if( astOK ) {
1723 for( iroute = 0; iroute < nroute; iroute++ ) popmap[ iroute ] = 0;
1724
1725 sel = sel_ptr[ 0 ];
1726 for( ipoint = 0; ipoint < npoint; ipoint++,sel++ ) {
1727 if( *sel != AST__BAD ) {
1728 rindex = (int)( *sel + 0.5 ) - 1;
1729 if( rindex >= 0 && rindex < nroute ) ( popmap[ rindex ] )++;
1730 }
1731 }
1732
1733 /* Find the number of points transformed by the most popular route Mapping.
1734 Also find the total number of points transformed by any route Mapping. */
1735 totpop = 0;
1736 maxpop = 0;
1737 for( iroute = 0; iroute < nroute; iroute++ ) {
1738 if( popmap[ iroute ] > maxpop ) maxpop = popmap[ iroute ];
1739 totpop += popmap[ iroute ];
1740 }
1741 if( maxpop == 0 ) maxpop = 1;
1742
1743 /* If some of the points are not transformed by any route Mapping.
1744 Initialise the whole output array to hold AST__BAD at every point. */
1745 if( totpop < npoint ) {
1746 for( j = 0; j < ncout; j++ ) {
1747 outv = out_ptr[ j ];
1748 for( ipoint = 0; ipoint < npoint; ipoint++ ) *(outv++) = AST__BAD;
1749 }
1750 }
1751
1752 /* Create a PointSet large enough to hold all the supplied positions
1753 which are to be transformed by the most popular route Mapping. */
1754 ps1 = astPointSet( maxpop, ncin, "", status );
1755 ptr1 = astGetPoints( ps1 );
1756
1757 /* Create a PointSet large enough to hold all the output positions
1758 created by the most popular route Mapping. */
1759 ps2 = astPointSet( maxpop, ncout, "", status );
1760 ptr2 = astGetPoints( ps2 );
1761 if( astOK ) {
1762
1763 /* Loop round each route Mapping which is used by at least 1 point. */
1764 for( iroute = 0; iroute < nroute; iroute++ ) {
1765 if( popmap[ iroute ] >0 ) {
1766 rmap = GetRoute( map, (double)( iroute + 1 ), &rinv, status );
1767
1768 /* Construct two PointSets of the correct size to hold the input and
1769 output points to be processed with the current route Mapping. We
1770 re-use the memory allocated for the largest route Mapping's PointSet. */
1771 if( popmap[ iroute ] != maxpop ) {
1772 ps1a = astPointSet( popmap[ iroute ], ncin, "", status );
1773 astSetPoints( ps1a, ptr1 );
1774 ps2a = astPointSet( popmap[ iroute ], ncout, "", status );
1775 astSetPoints( ps2a, ptr2 );
1776 } else {
1777 ps1a = astClone( ps1 );
1778 ps2a = astClone( ps2 );
1779 }
1780
1781 /* Fill the input PointSet with the input positions which are to be
1782 transformed using the current route Mapping. */
1783 sel = sel_ptr[ 0 ];
1784 k = 0;
1785 for( ipoint = 0; ipoint < npoint; ipoint++,sel++ ) {
1786 if( *sel != AST__BAD ) {
1787 rindex = (int)( *sel + 0.5 ) - 1;
1788 if( rindex == iroute ) {
1789 for( j = 0; j < ncin; j++ ) {
1790 ptr1[ j ][ k ] = in_ptr[ j ][ ipoint ];
1791 }
1792 k++;
1793 }
1794 }
1795 }
1796
1797 /* Use the route Mapping to transform this PointSet. */
1798 (void) astTransform( rmap, ps1a, forward, ps2a );
1799
1800 /* Copy the axis values from the resulting PointSet back into the results
1801 array. */
1802 sel = sel_ptr[ 0 ];
1803 k = 0;
1804 for( ipoint = 0; ipoint < npoint; ipoint++,sel++ ) {
1805 if( *sel != AST__BAD ) {
1806 rindex = (int)( *sel + 0.5 ) - 1;
1807 if( rindex == iroute ) {
1808 for( j = 0; j < ncout; j++ ) {
1809 out_ptr[ j ][ ipoint ] = ptr2[ j ][ k ];
1810 }
1811 k++;
1812 }
1813 }
1814 }
1815
1816 /* Free resources. */
1817 ps1a = astAnnul( ps1a );
1818 ps2a = astAnnul( ps2a );
1819
1820 /* Re-instate the Invert flag for the route Mapping. */
1821 astSetInvert( rmap, rinv );
1822 }
1823 }
1824 }
1825
1826 /* Free resources. */
1827 ps1 = astAnnul( ps1 );
1828 ps2 = astAnnul( ps2 );
1829 }
1830
1831 selps = astAnnul( selps );
1832 popmap = astFree( popmap );
1833
1834 /* Re-instate the Invert flag of the selector Mapping. */
1835 astSetInvert( selmap, selinv );
1836
1837 /* If an error occurred, clean up by deleting the output PointSet (if
1838 allocated by this function) and setting a NULL result pointer. */
1839 if ( !astOK ) {
1840 if ( !out ) result = astDelete( result );
1841 result = NULL;
1842 }
1843
1844 /* Return a pointer to the output PointSet. */
1845 return result;
1846 }
1847
1848 /* Copy constructor. */
1849 /* ----------------- */
Copy(const AstObject * objin,AstObject * objout,int * status)1850 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
1851 /*
1852 * Name:
1853 * Copy
1854
1855 * Purpose:
1856 * Copy constructor for SwitchMap objects.
1857
1858 * Type:
1859 * Private function.
1860
1861 * Synopsis:
1862 * void Copy( const AstObject *objin, AstObject *objout, int *status )
1863
1864 * Description:
1865 * This function implements the copy constructor for SwitchMap objects.
1866
1867 * Parameters:
1868 * objin
1869 * Pointer to the object to be copied.
1870 * objout
1871 * Pointer to the object being constructed.
1872 * status
1873 * Pointer to the inherited status variable.
1874
1875 * Returned Value:
1876 * void
1877
1878 * Notes:
1879 * - This constructor makes a deep copy, including a copy of the component
1880 * Mappings within the SwitchMap.
1881 */
1882
1883 /* Local Variables: */
1884 AstSwitchMap *in; /* Pointer to input SwitchMap */
1885 AstSwitchMap *out; /* Pointer to output SwitchMap */
1886 int i; /* Loop count */
1887
1888 /* Check the global error status. */
1889 if ( !astOK ) return;
1890
1891 /* Obtain pointers to the input and output SwitchMaps. */
1892 in = (AstSwitchMap *) objin;
1893 out = (AstSwitchMap *) objout;
1894
1895 /* For safety, start by clearing any references to the input component
1896 Mappings,etc, from the output SwitchMap. */
1897 out->fsmap = NULL;
1898 out->ismap = NULL;
1899 out->routemap = NULL;
1900 out->routeinv = NULL;
1901
1902 /* Make copies of these Mappings, etc, and store pointers to them in the output
1903 SwitchMap structure. */
1904 if( in->fsmap ) out->fsmap = astCopy( in->fsmap );
1905 if( in->ismap ) out->ismap = astCopy( in->ismap );
1906
1907 out->routemap = astMalloc( sizeof( AstMapping * )*( in->nroute ) );
1908 out->routeinv = astMalloc( sizeof( int )*( in->nroute ) );
1909 if( astOK ) {
1910 for( i = 0; i < in->nroute; i++ ) {
1911 out->routemap[ i ] = astCopy( in->routemap[ i ] );
1912 out->routeinv[ i ] = in->routeinv[ i ];
1913 }
1914 }
1915
1916 }
1917
1918 /* Destructor. */
1919 /* ----------- */
Delete(AstObject * obj,int * status)1920 static void Delete( AstObject *obj, int *status ) {
1921 /*
1922 * Name:
1923 * Delete
1924
1925 * Purpose:
1926 * Destructor for SwitchMap objects.
1927
1928 * Type:
1929 * Private function.
1930
1931 * Synopsis:
1932 * void Delete( AstObject *obj, int *status )
1933
1934 * Description:
1935 * This function implements the destructor for SwitchMap objects.
1936
1937 * Parameters:
1938 * obj
1939 * Pointer to the object to be deleted.
1940 * status
1941 * Pointer to the inherited status variable.
1942
1943 * Returned Value:
1944 * void
1945
1946 * Notes:
1947 * This function attempts to execute even if the global error status is
1948 * set.
1949 */
1950
1951 /* Local Variables: */
1952 AstSwitchMap *this; /* Pointer to SwitchMap */
1953 int i;
1954
1955 /* Obtain a pointer to the SwitchMap structure. */
1956 this = (AstSwitchMap *) obj;
1957
1958 /* Free dynamically allocated resources. */
1959 if( this->fsmap ) this->fsmap = astAnnul( this->fsmap );
1960 if( this->ismap ) this->ismap = astAnnul( this->ismap );
1961 for( i = 0; i < this->nroute; i++ ) {
1962 this->routemap[ i ] = astAnnul( this->routemap[ i ] );
1963 }
1964 this->routemap = astFree( this->routemap );
1965 this->routeinv = astFree( this->routeinv );
1966
1967 /* Clear the remaining SwitchMap variables. */
1968 this->nroute = 0;
1969 this->fsinv = 0;
1970 this->isinv = 0;
1971 }
1972
1973 /* Dump function. */
1974 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)1975 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
1976 /*
1977 * Name:
1978 * Dump
1979
1980 * Purpose:
1981 * Dump function for SwitchMap objects.
1982
1983 * Type:
1984 * Private function.
1985
1986 * Synopsis:
1987 * void Dump( AstObject *this, AstChannel *channel, int *status )
1988
1989 * Description:
1990 * This function implements the Dump function which writes out data
1991 * for the SwitchMap class to an output Channel.
1992
1993 * Parameters:
1994 * this
1995 * Pointer to the SwitchMap whose data are being written.
1996 * channel
1997 * Pointer to the Channel to which the data are being written.
1998 * status
1999 * Pointer to the inherited status variable.
2000 */
2001
2002 /* Local Variables: */
2003 AstSwitchMap *this;
2004 int ival;
2005 int set;
2006 int i;
2007 char buf[ 20 ];
2008
2009 /* Check the global error status. */
2010 if ( !astOK ) return;
2011
2012 /* Obtain a pointer to the SwitchMap structure. */
2013 this = (AstSwitchMap *) this_object;
2014
2015 /* Write out values representing the instance variables for the SwitchMap
2016 class. Accompany these with appropriate comment strings, possibly
2017 depending on the values being written.*/
2018
2019 /* In the case of attributes, we first use the appropriate (private)
2020 Test... member function to see if they are set. If so, we then use
2021 the (private) Get... function to obtain the value to be written
2022 out.
2023
2024 For attributes which are not set, we use the astGet... method to
2025 obtain the value instead. This will supply a default value
2026 (possibly provided by a derived class which over-rides this method)
2027 which is more useful to a human reader as it corresponds to the
2028 actual default attribute value. Since "set" will be zero, these
2029 values are for information only and will not be read back. */
2030
2031 /* Forward selector Mapping */
2032 /* ------------------------ */
2033 if( this->fsmap ) {
2034 astWriteObject( channel, "FSMap", 1, 1, this->fsmap,
2035 "Forward selector Mapping" );
2036
2037 /* Forward selector Invert flag. */
2038 /* ----------------------------- */
2039 ival = this->fsinv;
2040 set = ( ival != 0 );
2041 astWriteInt( channel, "FSInv", set, 0, ival,
2042 ival ? "Fwd selector used in inverse direction" :
2043 "Fwd selector used in forward direction" );
2044 }
2045
2046
2047 /* Inverse selector Mapping */
2048 /* ------------------------ */
2049 if( this->ismap ) {
2050 astWriteObject( channel, "ISMap", 1, 1, this->ismap,
2051 "Inverse selector Mapping" );
2052
2053 /* Forward selector Invert flag. */
2054 /* ----------------------------- */
2055 ival = this->isinv;
2056 set = ( ival != 0 );
2057 astWriteInt( channel, "ISInv", set, 0, ival,
2058 ival ? "Inv selector used in inverse direction" :
2059 "Inv selector used in forward direction" );
2060 }
2061
2062 /* Loop to dump each route Mapping and its invert flag. */
2063 /* ---------------------------------------------------- */
2064 for( i = 0; i < this->nroute; i++ ) {
2065 sprintf( buf, "RMap%d", i + 1 );
2066 astWriteObject( channel, buf, 1, 1, this->routemap[ i ],
2067 "Route Mapping" );
2068
2069 ival = this->routeinv[ i ];
2070 set = ( ival != 0 );
2071 sprintf( buf, "RInv%d", i + 1 );
2072 astWriteInt( channel, buf, set, 0, ival,
2073 ival ? "Route Mapping used in inverse direction" :
2074 "Route Mapping used in forward direction" );
2075 }
2076
2077 }
2078
2079 /* Standard class functions. */
2080 /* ========================= */
2081 /* Implement the astIsASwitchMap and astCheckSwitchMap functions using the
2082 macros defined for this purpose in the "object.h" header file. */
astMAKE_ISA(SwitchMap,Mapping)2083 astMAKE_ISA(SwitchMap,Mapping)
2084 astMAKE_CHECK(SwitchMap)
2085
2086 AstSwitchMap *astSwitchMap_( void *fsmap_void, void *ismap_void, int nroute,
2087 void **routemaps_void, const char *options, int *status, ...) {
2088 /*
2089 *+
2090 * Name:
2091 * astSwitchMap
2092
2093 * Purpose:
2094 * Create a SwitchMap.
2095
2096 * Type:
2097 * Protected function.
2098
2099 * Synopsis:
2100 * #include "switchmap.h"
2101 * AstSwitchMap *astSwitchMap( AstMapping *fsmap, AstMapping *ismap,
2102 * int nroute, AstMapping **routemaps,
2103 * const char *options, ... )
2104
2105 * Class Membership:
2106 * SwitchMap constructor.
2107
2108 * Description:
2109 * This function creates a new SwitchMap and optionally initialises its
2110 * attributes.
2111
2112 * Parameters:
2113 * fsmap
2114 * Pointer to the forward selector Mapping
2115 * ismap
2116 * Pointer to the inverse selector Mapping
2117 * nroute
2118 * The number of route Mappings.
2119 * routemaps
2120 * An array of pointers to the route Mappings.
2121 * options
2122 * Pointer to a null terminated string containing an optional
2123 * comma-separated list of attribute assignments to be used for
2124 * initialising the new SwitchMap. The syntax used is the same as for the
2125 * astSet method and may include "printf" format specifiers identified
2126 * by "%" symbols in the normal way.
2127 * ...
2128 * If the "options" string contains "%" format specifiers, then an
2129 * optional list of arguments may follow it in order to supply values to
2130 * be substituted for these specifiers. The rules for supplying these
2131 * are identical to those for the astSet method (and for the C "printf"
2132 * function).
2133
2134 * Returned Value:
2135 * A pointer to the new SwitchMap.
2136
2137 * Notes:
2138 * - A null pointer will be returned if this function is invoked
2139 * with the global error status set, or if it should fail for any
2140 * reason.
2141 *-
2142
2143 * Implementation Notes:
2144 * - This function implements the basic SwitchMap constructor which is
2145 * available via the protected interface to the SwitchMap class. A
2146 * public interface is provided by the astSwitchMapId_ function.
2147 * - Because this function has a variable argument list, it is
2148 * invoked by a macro that evaluates to a function pointer (not a
2149 * function invocation) and no checking or casting of arguments is
2150 * performed before the function is invoked. Because of this, the
2151 * "map1" and "map2" parameters are of type (void *) and are
2152 * converted and validated within the function itself.
2153 */
2154
2155 /* Local Variables: */
2156 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2157 AstSwitchMap *new; /* Pointer to new SwitchMap */
2158 AstMapping *fsmap; /* Pointer to fwd selector Mapping */
2159 AstMapping *ismap; /* Pointer to inv selector Mapping */
2160 AstMapping **routemaps; /* Array of route Mapping pointers */
2161 int i; /* Route Mappings index */
2162 va_list args; /* Variable argument list */
2163
2164 /* Initialise. */
2165 new = NULL;
2166
2167 /* Get a pointer to the thread specific global data structure. */
2168 astGET_GLOBALS(NULL);
2169
2170 /* Check the global status. */
2171 if ( !astOK ) return new;
2172
2173 /* Report an error if no route Mappings have been supplied. */
2174 if( nroute <= 0 ) astError( AST__BDPAR, "astSwitchMap(SwitchMap): "
2175 "Bad number of route Mappings (%d) specified.", status,
2176 nroute );
2177
2178 /* Otherwise create an array to hold the route Mapping pointers. */
2179 routemaps = astMalloc( sizeof( AstMapping * )*nroute );
2180
2181 /* Obtain and validate pointers to the Mapping structures provided. */
2182 if( astOK ) {
2183 fsmap = fsmap_void ? astCheckMapping( fsmap_void ) : NULL;
2184 ismap = ismap_void ? astCheckMapping( ismap_void ) : NULL;
2185 for( i = 0; i < nroute; i++ ) {
2186 routemaps[ i ] = astCheckMapping( routemaps_void[ i ] );
2187 }
2188 }
2189
2190 if ( astOK ) {
2191
2192 /* Initialise the SwitchMap, allocating memory and initialising the
2193 virtual function table as well if necessary. */
2194 new = astInitSwitchMap( NULL, sizeof( AstSwitchMap ), !class_init, &class_vtab,
2195 "SwitchMap", fsmap, ismap, nroute, routemaps );
2196
2197 /* If successful, note that the virtual function table has been
2198 initialised. */
2199 if ( astOK ) {
2200 class_init = 1;
2201
2202 /* Obtain the variable argument list and pass it along with the
2203 options string to the astVSet method to initialise the new SwitchMap's
2204 attributes. */
2205 va_start( args, status );
2206 astVSet( new, options, NULL, args );
2207 va_end( args );
2208
2209 /* If an error occurred, clean up by deleting the new object. */
2210 if ( !astOK ) new = astDelete( new );
2211 }
2212 }
2213
2214 /* Free memory used to hold the route Mapping pointers. */
2215 routemaps = astFree( routemaps );
2216
2217 /* Return a pointer to the new SwitchMap. */
2218 return new;
2219 }
2220
astSwitchMapId_(void * fsmap_void,void * ismap_void,int nroute,void ** routemaps_void,const char * options,...)2221 AstSwitchMap *astSwitchMapId_( void *fsmap_void, void *ismap_void, int nroute,
2222 void **routemaps_void, const char *options, ... ) {
2223 /*
2224 *++
2225 * Name:
2226 c astSwitchMap
2227 f AST_SWITCHMAP
2228
2229 * Purpose:
2230 * Create a SwitchMap.
2231
2232 * Type:
2233 * Public function.
2234
2235 * Synopsis:
2236 c #include "switchmap.h"
2237 c AstSwitchMap *astSwitchMap( AstMapping *fsmap, AstMapping *ismap,
2238 c int nroute, AstMapping *routemaps[],
2239 c const char *options, ... )
2240 f RESULT = AST_SWITCHMAP( FSMAP, ISMAP, NROUTE, ROUTEMAPS, OPTIONS,
2241 f STATUS )
2242
2243 * Class Membership:
2244 * SwitchMap constructor.
2245
2246 * Description:
2247 * This function creates a new SwitchMap and optionally initialises
2248 * its attributes.
2249 *
2250 * A SwitchMap is a Mapping which represents a set of alternate
2251 * Mappings, each of which is used to transform positions within a
2252 * particular region of the input or output coordinate system of the
2253 * SwitchMap.
2254 *
2255 * A SwitchMap can encapsulate any number of Mappings, but they must
2256 * all have the same number of inputs (Nin attribute value) and the
2257 * same number of outputs (Nout attribute value). The SwitchMap itself
2258 * inherits these same values for its Nin and Nout attributes. Each of
2259 * these Mappings represents a "route" through the switch, and are
2260 * referred to as "route" Mappings below. Each route Mapping transforms
2261 * positions between the input and output coordinate space of the entire
2262 * SwitchMap, but only one Mapping will be used to transform any given
2263 * position. The selection of the appropriate route Mapping to use with
2264 * any given input position is made by another Mapping, called the
2265 * "selector" Mapping. Each SwitchMap encapsulates two selector
2266 * Mappings in addition to its route Mappings; one for use with the
2267 * SwitchMap's forward transformation (called the "forward selector
2268 * Mapping"), and one for use with the SwitchMap's inverse transformation
2269 * (called the "inverse selector Mapping"). The forward selector Mapping
2270 * must have the same number of inputs as the route Mappings, but
2271 * should have only one output. Likewise, the inverse selector Mapping
2272 * must have the same number of outputs as the route Mappings, but
2273 * should have only one input.
2274 *
2275 * When the SwitchMap is used to transform a position in the forward
2276 * direction (from input to output), each supplied input position is
2277 * first transformed by the forward transformation of the forward selector
2278 * Mapping. This produces a single output value for each input position
2279 * referred to as the selector value. The nearest integer to the selector
2280 * value is found, and is used to index the array of route Mappings (the
2281 * first supplied route Mapping has index 1, the second route Mapping has
2282 * index 2, etc). If the nearest integer to the selector value is less
2283 * than 1 or greater than the number of route Mappings, then the SwitchMap
2284 * output position is set to a value of AST__BAD on every axis. Otherwise,
2285 * the forward transformation of the selected route Mapping is used to
2286 * transform the supplied input position to produce the SwitchMap output
2287 * position.
2288 *
2289 * When the SwitchMap is used to transform a position in the inverse
2290 * direction (from "output" to "input"), each supplied "output" position
2291 * is first transformed by the inverse transformation of the inverse
2292 * selector Mapping. This produces a selector value for each "output"
2293 * position. Again, the nearest integer to the selector value is found,
2294 * and is used to index the array of route Mappings. If this selector
2295 * index value is within the bounds of the array of route Mappings, then
2296 * the inverse transformation of the selected route Mapping is used to
2297 * transform the supplied "output" position to produce the SwitchMap
2298 * "input" position. If the selector index value is outside the bounds
2299 * of the array of route Mappings, then the SwitchMap "input" position is
2300 * set to a value of AST__BAD on every axis.
2301 *
2302 * In practice, appropriate selector Mappings should be chosen to
2303 * associate a different route Mapping with each region of coordinate
2304 * space. Note that the SelectorMap class of Mapping is particularly
2305 * appropriate for this purpose.
2306 *
2307 * If a compound Mapping contains a SwitchMap in series with its own
2308 * inverse, the combination of the two adjacent SwitchMaps will be
2309 * replaced by a UnitMap when the compound Mapping is simplified using
2310 c astSimplify.
2311 f AST_SIMPLIFY.
2312
2313 * Parameters:
2314 c fsmap
2315 f FSMAP = INTEGER (Given)
2316 * Pointer to the forward selector Mapping. This must have a
2317 * defined forward transformation, but need not have a defined
2318 * inverse transformation. It must have one output, and the number of
2319 * inputs must match the number of inputs of each of the supplied
2320 * route Mappings.
2321 c NULL
2322 f AST__NULL
2323 * may be supplied, in which case the SwitchMap will have an undefined
2324 * forward Mapping.
2325 c ismap
2326 f ISMAP = INTEGER (Given)
2327 * Pointer to the inverse selector Mapping. This must have a
2328 * defined inverse transformation, but need not have a defined
2329 * forward transformation. It must have one input, and the number of
2330 * outputs must match the number of outputs of each of the supplied
2331 * route Mappings.
2332 c NULL
2333 f AST__NULL
2334 * may be supplied, in which case the SwitchMap will have an undefined
2335 * inverse Mapping.
2336 c nroute
2337 f NROUTE = INTEGER (Given)
2338 * The number of supplied route Mappings.
2339 c routemaps
2340 f ROUTEMAPS( NROUTE ) = INTEGER (Given)
2341 * An array of pointers to the route Mappings. All the supplied
2342 * route Mappings must have common values for the Nin and Nout
2343 * attributes, and these values define the number of inputs and
2344 * outputs of the SwitchMap.
2345 c options
2346 f OPTIONS = CHARACTER * ( * ) (Given)
2347 c Pointer to a null-terminated string containing an optional
2348 c comma-separated list of attribute assignments to be used for
2349 c initialising the new SwitchMap. The syntax used is identical to
2350 c that for the astSet function and may include "printf" format
2351 c specifiers identified by "%" symbols in the normal way.
2352 f A character string containing an optional comma-separated
2353 f list of attribute assignments to be used for initialising the
2354 f new SwitchMap. The syntax used is identical to that for the
2355 f AST_SET routine.
2356 c ...
2357 c If the "options" string contains "%" format specifiers, then
2358 c an optional list of additional arguments may follow it in
2359 c order to supply values to be substituted for these
2360 c specifiers. The rules for supplying these are identical to
2361 c those for the astSet function (and for the C "printf"
2362 c function).
2363 f STATUS = INTEGER (Given and Returned)
2364 f The global status.
2365
2366 * Returned Value:
2367 c astSwitchMap()
2368 f AST_SWITCHMAP = INTEGER
2369 * A pointer to the new SwitchMap.
2370
2371 * Notes:
2372 c - Note that the component Mappings supplied are not copied by
2373 c astSwitchMap (the new SwitchMap simply retains a reference to
2374 c them). They may continue to be used for other purposes, but
2375 c should not be deleted. If a SwitchMap containing a copy of its
2376 c component Mappings is required, then a copy of the SwitchMap should
2377 c be made using astCopy.
2378 f - Note that the component Mappings supplied are not copied by
2379 f AST_SWITCHMAP (the new SwitchMap simply retains a reference to
2380 f them). They may continue to be used for other purposes, but
2381 f should not be deleted. If a SwitchMap containing a copy of its
2382 f component Mappings is required, then a copy of the SwitchMap should
2383 f be made using AST_COPY.
2384 * - A null Object pointer (AST__NULL) will be returned if this
2385 c function is invoked with the AST error status set, or if it
2386 f function is invoked with STATUS set to an error value, or if it
2387 * should fail for any reason.
2388 *--
2389
2390 * Implementation Notes:
2391 * - This function implements the external (public) interface to
2392 * the astSwitchMap constructor function. It returns an ID value
2393 * (instead of a true C pointer) to external users, and must be
2394 * provided because astSwitchMap_ has a variable argument list which
2395 * cannot be encapsulated in a macro (where this conversion would
2396 * otherwise occur).
2397 * - Because no checking or casting of arguments is performed
2398 * before the function is invoked, the "map1" and "map2" parameters
2399 * are of type (void *) and are converted from an ID value to a
2400 * pointer and validated within the function itself.
2401 * - The variable argument list also prevents this function from
2402 * invoking astSwitchMap_ directly, so it must be a re-implementation
2403 * of it in all respects, except for the conversions between IDs
2404 * and pointers on input/output of Objects.
2405 */
2406
2407 /* Local Variables: */
2408 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2409 AstSwitchMap *new; /* Pointer to new SwitchMap */
2410 AstMapping *fsmap; /* Pointer to fwd selector Mapping */
2411 AstMapping *ismap; /* Pointer to inv selector Mapping */
2412 AstMapping **routemaps; /* Array of route Mapping pointers */
2413 int i; /* Route Mappings index */
2414 va_list args; /* Variable argument list */
2415
2416 int *status; /* Pointer to inherited status value */
2417
2418 /* Get a pointer to the thread specific global data structure. */
2419 astGET_GLOBALS(NULL);
2420
2421 /* Initialise. */
2422 new = NULL;
2423
2424 /* Get a pointer to the inherited status value. */
2425 status = astGetStatusPtr;
2426
2427 /* Check the global status. */
2428 if ( !astOK ) return new;
2429
2430 /* Report an error if no route Mappings have been supplied. */
2431 if( nroute <= 0 ) astError( AST__BDPAR, "astSwitchMap(SwitchMap): "
2432 " Bad number of route Mappings (%d) specified.", status,
2433 nroute );
2434
2435 /* Otherwise create an array to hold the route Mapping pointers. */
2436 routemaps = astMalloc( sizeof( AstMapping * )*nroute );
2437
2438 /* Obtain and validate pointers to the Mapping structures provided. */
2439 if( astOK ) {
2440 fsmap = fsmap_void ? astCheckMapping( astMakePointer(fsmap_void) ) : NULL;
2441 ismap = ismap_void ? astCheckMapping( astMakePointer(ismap_void) ) : NULL;
2442 for( i = 0; i < nroute; i++ ) {
2443 routemaps[ i ] = astVerifyMapping( astMakePointer(routemaps_void[ i ]) );
2444 }
2445 }
2446
2447 if ( astOK ) {
2448
2449 /* Initialise the SwitchMap, allocating memory and initialising the
2450 virtual function table as well if necessary. */
2451 new = astInitSwitchMap( NULL, sizeof( AstSwitchMap ), !class_init, &class_vtab,
2452 "SwitchMap", fsmap, ismap, nroute, routemaps );
2453
2454 /* If successful, note that the virtual function table has been
2455 initialised. */
2456 if ( astOK ) {
2457 class_init = 1;
2458
2459 /* Obtain the variable argument list and pass it along with the
2460 options string to the astVSet method to initialise the new SwitchMap's
2461 attributes. */
2462 va_start( args, options );
2463 astVSet( new, options, NULL, args );
2464 va_end( args );
2465
2466 /* If an error occurred, clean up by deleting the new object. */
2467 if ( !astOK ) new = astDelete( new );
2468 }
2469 }
2470
2471 /* Free memory used to hold the route Mapping pointers. */
2472 routemaps = astFree( routemaps );
2473
2474 /* Return an ID value for the new SwitchMap. */
2475 return astMakeId( new );
2476 }
2477
astInitSwitchMap_(void * mem,size_t size,int init,AstSwitchMapVtab * vtab,const char * name,AstMapping * fsmap,AstMapping * ismap,int nroute,AstMapping ** routemaps,int * status)2478 AstSwitchMap *astInitSwitchMap_( void *mem, size_t size, int init,
2479 AstSwitchMapVtab *vtab, const char *name,
2480 AstMapping *fsmap, AstMapping *ismap,
2481 int nroute, AstMapping **routemaps, int *status ) {
2482 /*
2483 *+
2484 * Name:
2485 * astInitSwitchMap
2486
2487 * Purpose:
2488 * Initialise a SwitchMap.
2489
2490 * Type:
2491 * Protected function.
2492
2493 * Synopsis:
2494 * #include "switchmap.h"
2495 * AstSwitchMap *astInitSwitchMap( void *mem, size_t size, int init,
2496 * AstSwitchMapVtab *vtab, const char *name,
2497 * AstMapping *fsmap, AstMapping *ismap,
2498 * int nroute, AstMapping **routemaps )
2499
2500 * Class Membership:
2501 * SwitchMap initialiser.
2502
2503 * Description:
2504 * This function is provided for use by class implementations to initialise
2505 * a new SwitchMap object. It allocates memory (if necessary) to
2506 * accommodate the SwitchMap plus any additional data associated with the
2507 * derived class. It then initialises a SwitchMap structure at the start
2508 * of this memory. If the "init" flag is set, it also initialises the
2509 * contents of a virtual function table for a SwitchMap at the start of
2510 * the memory passed via the "vtab" parameter.
2511
2512 * Parameters:
2513 * mem
2514 * A pointer to the memory in which the SwitchMap is to be initialised.
2515 * This must be of sufficient size to accommodate the SwitchMap data
2516 * (sizeof(SwitchMap)) plus any data used by the derived class. If a
2517 * value of NULL is given, this function will allocate the memory itself
2518 * using the "size" parameter to determine its size.
2519 * size
2520 * The amount of memory used by the SwitchMap (plus derived class
2521 * data). This will be used to allocate memory if a value of NULL is
2522 * given for the "mem" parameter. This value is also stored in the
2523 * SwitchMap structure, so a valid value must be supplied even if not
2524 * required for allocating memory.
2525 * init
2526 * A logical flag indicating if the SwitchMap's virtual function table
2527 * is to be initialised. If this value is non-zero, the virtual function
2528 * table will be initialised by this function.
2529 * vtab
2530 * Pointer to the start of the virtual function table to be associated
2531 * with the new SwitchMap.
2532 * name
2533 * Pointer to a constant null-terminated character string which contains
2534 * the name of the class to which the new object belongs (it is this
2535 * pointer value that will subsequently be returned by the Object
2536 * astClass function).
2537 * fsmap
2538 * Pointer to the forward selector Mapping.
2539 * ismap
2540 * Pointer to the inverse selector Mapping.
2541 * nroute
2542 * The number of route Mappings supplied.
2543 * routemaps
2544 * An array holdiong pointers to the route Mappings.
2545
2546 * Returned Value:
2547 * A pointer to the new SwitchMap.
2548
2549 * Notes:
2550 * - A null pointer will be returned if this function is invoked with the
2551 * global error status set, or if it should fail for any reason.
2552 *-
2553 */
2554
2555 /* Local Variables: */
2556 AstSwitchMap *new; /* Pointer to new SwitchMap */
2557 int i; /* Loop count */
2558 int nin; /* No. input coordinates for SwitchMap */
2559 int nout; /* No. output coordinates for SwitchMap */
2560
2561 /* Check the global status. */
2562 if ( !astOK ) return NULL;
2563
2564 /* If necessary, initialise the virtual function table. */
2565 if ( init ) astInitSwitchMapVtab( vtab, name );
2566
2567 /* Initialise. */
2568 new = NULL;
2569
2570 /* Check that all route Mappings have common values for Nin and Nout.*/
2571 nin = astGetNin( routemaps[ 0 ] );
2572 nout = astGetNout( routemaps[ 0 ] );
2573 for( i = 1; i < nroute; i++ ) {
2574 if( nin != astGetNin( routemaps[ i ] ) ){
2575 if( astOK ) {
2576 astError( AST__BADNI, "astInitSwitchMap(%s): Route Mapping "
2577 "number %d has %d input(s) but the first route "
2578 "Mapping has %d input(s).", status, name, i + 1,
2579 astGetNin( routemaps[ i ] ), nin );
2580 }
2581
2582 } else if( nout != astGetNout( routemaps[ i ] ) ){
2583 if( astOK ) {
2584 astError( AST__BADNO, "astInitSwitchMap(%s): Route Mapping "
2585 "number %d has %d output(s) but the first route "
2586 "Mapping has %d output(s).", status, name, i + 1,
2587 astGetNin( routemaps[ i ] ), nin );
2588 }
2589 }
2590 }
2591
2592 /* If supplied, report an error if fsmap has no forward transformation,
2593 or if it has an incorrect number of inputs or output. */
2594 if( fsmap && astOK ) {
2595 if( !astGetTranForward( fsmap ) ) {
2596 astError( AST__INTRD, "astInitSwitchMap(%s): The forward selector Mapping "
2597 "is not able to transform coordinates in the forward direction.", status,
2598 name );
2599
2600 } else if( astGetNin( fsmap ) != nin ){
2601 astError( AST__BADNI, "astInitSwitchMap(%s): The forward selector "
2602 "Mapping has %d input(s) but the SwitchMap has %d "
2603 "input(s).", status, name, astGetNin( fsmap ), nin );
2604
2605 } else if( astGetNout( fsmap ) != 1 ){
2606 astError( AST__BADNO, "astInitSwitchMap(%s): The forward selector "
2607 "Mapping has %d outputs but should only have 1.", status, name,
2608 astGetNout( fsmap ) );
2609 }
2610 }
2611
2612 /* If supplied, report an error if ismap has no inverse transformation,
2613 or if it has an incorrect number of inputs or outputs. */
2614 if( ismap && astOK ) {
2615 if( !astGetTranInverse( ismap ) ) {
2616 astError( AST__INTRD, "astInitSwitchMap(%s): The inverse selector Mapping "
2617 "is not able to transform coordinates in the inverse direction.", status,
2618 name );
2619 } else if( nout != astGetNout( ismap ) ){
2620 astError( AST__BADNO, "astInitSwitchMap(%s): The inverse selector "
2621 "Mapping has %d output(s) but the SwitchMap has %d "
2622 "output(s).", status, name, astGetNout( ismap ), nout );
2623
2624 } else if( astGetNin( ismap ) != 1 ){
2625 astError( AST__BADNI, "astInitSwitchMap(%s): The inverse selector "
2626 "Mapping has %d inputs but should only have 1.", status, name,
2627 astGetNin( ismap ) );
2628
2629 }
2630 }
2631
2632 /* Report an error if neither ismap nor fsmap were supplied. */
2633 if( !fsmap && !ismap && astOK ) {
2634 astError( AST__INTRD, "astInitSwitchMap(%s): No selector Mappings "
2635 "supplied.", status, name );
2636 }
2637
2638 /* Initialise a Mapping structure (the parent class) as the first component
2639 within the SwitchMap structure, allocating memory if necessary. Specify
2640 the number of input and output coordinates and in which directions the
2641 Mapping should be defined. */
2642 if ( astOK ) {
2643 new = (AstSwitchMap *) astInitMapping( mem, size, 0,
2644 (AstMappingVtab *) vtab, name,
2645 nin, nout,
2646 ( fsmap != NULL ),
2647 ( ismap != NULL ) );
2648 if ( astOK ) {
2649
2650 /* Initialise the SwitchMap data. */
2651 /* --------------------------- */
2652 /* Store pointers to the selector Mappings. */
2653 new->fsmap = fsmap ? astClone( fsmap ) : NULL;
2654 new->ismap = ismap ? astClone( ismap ) : NULL;
2655
2656 /* Save the initial values of the inversion flags for these Mappings. */
2657 new->fsinv = fsmap ? astGetInvert( fsmap ) : 0;
2658 new->isinv = ismap ? astGetInvert( ismap ) : 0;
2659
2660 /* Create arrays for the route Mappings. */
2661 new->routemap = astMalloc( sizeof( AstMapping * )*nroute );
2662 new->routeinv = astMalloc( sizeof( int )*nroute );
2663
2664 /* Store pointers to the route Mappings and their invert flags. */
2665 if( astOK ) {
2666 new->nroute = nroute;
2667 for( i = 0; i < nroute; i++ ) {
2668 new->routemap[ i ] = astClone( routemaps[ i ] );
2669 new->routeinv[ i ] = astGetInvert( routemaps[ i ] );
2670 }
2671 } else {
2672 new->nroute = 0;
2673 }
2674
2675 /* If an error occurred, clean up by deleting the new object. */
2676 if ( !astOK ) new = astDelete( new );
2677 }
2678 }
2679
2680 /* Return a pointer to the new object. */
2681 return new;
2682 }
2683
astLoadSwitchMap_(void * mem,size_t size,AstSwitchMapVtab * vtab,const char * name,AstChannel * channel,int * status)2684 AstSwitchMap *astLoadSwitchMap_( void *mem, size_t size,
2685 AstSwitchMapVtab *vtab, const char *name,
2686 AstChannel *channel, int *status ) {
2687 /*
2688 *+
2689 * Name:
2690 * astLoadSwitchMap
2691
2692 * Purpose:
2693 * Load a SwitchMap.
2694
2695 * Type:
2696 * Protected function.
2697
2698 * Synopsis:
2699 * #include "switchmap.h"
2700 * AstSwitchMap *astLoadSwitchMap( void *mem, size_t size,
2701 * AstSwitchMapVtab *vtab, const char *name,
2702 * AstChannel *channel )
2703
2704 * Class Membership:
2705 * SwitchMap loader.
2706
2707 * Description:
2708 * This function is provided to load a new SwitchMap using data read
2709 * from a Channel. It first loads the data used by the parent class
2710 * (which allocates memory if necessary) and then initialises a
2711 * SwitchMap structure in this memory, using data read from the input
2712 * Channel.
2713 *
2714 * If the "init" flag is set, it also initialises the contents of a
2715 * virtual function table for a SwitchMap at the start of the memory
2716 * passed via the "vtab" parameter.
2717
2718
2719 * Parameters:
2720 * mem
2721 * A pointer to the memory into which the SwitchMap is to be
2722 * loaded. This must be of sufficient size to accommodate the
2723 * SwitchMap data (sizeof(SwitchMap)) plus any data used by derived
2724 * classes. If a value of NULL is given, this function will
2725 * allocate the memory itself using the "size" parameter to
2726 * determine its size.
2727 * size
2728 * The amount of memory used by the SwitchMap (plus derived class
2729 * data). This will be used to allocate memory if a value of
2730 * NULL is given for the "mem" parameter. This value is also
2731 * stored in the SwitchMap structure, so a valid value must be
2732 * supplied even if not required for allocating memory.
2733 *
2734 * If the "vtab" parameter is NULL, the "size" value is ignored
2735 * and sizeof(AstSwitchMap) is used instead.
2736 * vtab
2737 * Pointer to the start of the virtual function table to be
2738 * associated with the new SwitchMap. If this is NULL, a pointer to
2739 * the (static) virtual function table for the SwitchMap class is
2740 * used instead.
2741 * name
2742 * Pointer to a constant null-terminated character string which
2743 * contains the name of the class to which the new object
2744 * belongs (it is this pointer value that will subsequently be
2745 * returned by the astGetClass method).
2746 *
2747 * If the "vtab" parameter is NULL, the "name" value is ignored
2748 * and a pointer to the string "SwitchMap" is used instead.
2749
2750 * Returned Value:
2751 * A pointer to the new SwitchMap.
2752
2753 * Notes:
2754 * - A null pointer will be returned if this function is invoked
2755 * with the global error status set, or if it should fail for any
2756 * reason.
2757 *-
2758 */
2759
2760 /* Local Variables: */
2761 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2762 AstSwitchMap *new;
2763 AstMapping *rmap;
2764 int i;
2765 char buf[ 20 ];
2766
2767 /* Initialise. */
2768 new = NULL;
2769
2770 /* Check the global error status. */
2771 if ( !astOK ) return new;
2772
2773 /* Get a pointer to the thread specific global data structure. */
2774 astGET_GLOBALS(channel);
2775
2776 /* If a NULL virtual function table has been supplied, then this is
2777 the first loader to be invoked for this SwitchMap. In this case the
2778 SwitchMap belongs to this class, so supply appropriate values to be
2779 passed to the parent class loader (and its parent, etc.). */
2780 if ( !vtab ) {
2781 size = sizeof( AstSwitchMap );
2782 vtab = &class_vtab;
2783 name = "SwitchMap";
2784
2785 /* If required, initialise the virtual function table for this class. */
2786 if ( !class_init ) {
2787 astInitSwitchMapVtab( vtab, name );
2788 class_init = 1;
2789 }
2790 }
2791
2792 /* Invoke the parent class loader to load data for all the ancestral
2793 classes of the current one, returning a pointer to the resulting
2794 partly-built SwitchMap. */
2795 new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
2796 channel );
2797 if ( astOK ) {
2798
2799 /* Read input data. */
2800 /* ================ */
2801 /* Request the input Channel to read all the input data appropriate to
2802 this class into the internal "values list". */
2803 astReadClassData( channel, "SwitchMap" );
2804
2805 /* Now read each individual data item from this list and use it to
2806 initialise the appropriate instance variable(s) for this class. */
2807
2808 /* In the case of attributes, we first read the "raw" input value,
2809 supplying the "unset" value as the default. If a "set" value is
2810 obtained, we then use the appropriate (private) Set... member
2811 function to validate and set the value properly. */
2812
2813 /* Forward Selector Mapping and its Invert flag. */
2814 /* --------------------------------------------- */
2815 new->fsmap = astReadObject( channel, "fsmap", NULL );
2816 new->fsinv = astReadInt( channel, "fsinv", 0 );
2817 new->fsinv = ( new->fsinv != 0 );
2818
2819 /* Inverse Selector Mapping and its Invert flag. */
2820 /* --------------------------------------------- */
2821 new->ismap = astReadObject( channel, "ismap", NULL );
2822 new->isinv = astReadInt( channel, "isinv", new->fsinv );
2823 new->isinv = ( new->isinv != 0 );
2824
2825 /* Loop to load each route Mapping and its invert flag. */
2826 /* ---------------------------------------------------- */
2827 new->routemap = NULL;
2828 new->routeinv = NULL;
2829 i = 0;
2830 while( astOK ) {
2831 sprintf( buf, "rmap%d", i + 1 );
2832 rmap = astReadObject( channel, buf, NULL );
2833 if( rmap ) {
2834 new->routemap = astGrow( new->routemap, i + 1, sizeof( AstMapping *) );
2835 new->routeinv = astGrow( new->routeinv, i + 1, sizeof( int ) );
2836 if( astOK ) {
2837 new->routemap[ i ] = rmap;
2838 sprintf( buf, "rinv%d", i + 1 );
2839 new->routeinv[ i ] = astReadInt( channel, buf, 0 );
2840 new->routeinv[ i ] = ( new->routeinv[ i ] != 0 );
2841 i++;
2842 }
2843 } else {
2844 break;
2845 }
2846 }
2847
2848 /* Number of route Mappings. */
2849 new->nroute = i;
2850
2851 /* If an error occurred, clean up by deleting the new SwitchMap. */
2852 if ( !astOK ) new = astDelete( new );
2853 }
2854
2855 /* Return the new SwitchMap pointer. */
2856 return new;
2857 }
2858
2859 /* Virtual function interfaces. */
2860 /* ============================ */
2861 /* These provide the external interface to the virtual functions defined by
2862 this class. Each simply checks the global error status and then locates and
2863 executes the appropriate member function, using the function pointer stored
2864 in the object's virtual function table (this pointer is located using the
2865 astMEMBER macro defined in "object.h").
2866
2867 Note that the member function may not be the one defined here, as it may
2868 have been over-ridden by a derived class. However, it should still have the
2869 same interface. */
2870
2871 /* None. */
2872
2873
2874
2875
2876