1 /*
2 *class++
3 *  Name:
4 *     SelectorMap
5 
6 *  Purpose:
7 *     A Mapping that locates positions within one of a set of alternate
8 *     Regions.
9 
10 *  Constructor Function:
11 c     astSelectorMap
12 f     AST_SELECTORMAP
13 
14 *  Description:
15 *     A SelectorMap is a Mapping that identifies which Region contains
16 *     a given input position.
17 *
18 *     A SelectorMap encapsulates a number of Regions that all have the same
19 *     number of axes and represent the same coordinate Frame. The number of
20 *     inputs (Nin attribute) of the SelectorMap equals the number of axes
21 *     spanned by one of the encapsulated Region. All SelectorMaps have only
22 *     a single output. SelectorMaps do not define an inverse transformation.
23 *
24 *     For each input position, the forward transformation of a SelectorMap
25 *     searches through the encapsulated Regions (in the order supplied when
26 *     the SelectorMap was created) until a Region is found which contains
27 *     the input position. The index associated with this Region is
28 *     returned as the SelectorMap output value (the index value is the
29 *     position of the Region within the list of Regions supplied when the
30 *     SelectorMap was created, starting at 1 for the first Region). If an
31 *     input position is not contained within any Region, a value of zero is
32 *     returned by the forward transformation.
33 *
34 *     If a compound Mapping contains a SelectorMap in series with its own
35 *     inverse, the combination of the two adjacent SelectorMaps will be
36 *     replaced by a UnitMap when the compound Mapping is simplified using
37 c     astSimplify.
38 f     AST_SIMPLIFY.
39 *
40 *     In practice, SelectorMaps are often used in conjunction with SwitchMaps.
41 
42 *  Inheritance:
43 *     The SelectorMap class inherits from the Mapping class.
44 
45 *  Attributes:
46 *     The SelectorMap class does not define any new attributes beyond those
47 *     which are applicable to all Mappings.
48 
49 *  Functions:
50 c     The SelectorMap class does not define any new functions beyond those
51 f     The SelectorMap class does not define any new routines beyond those
52 *     which are applicable to all Mappings.
53 
54 *  Copyright:
55 *     Copyright (C) 1997-2006 Council for the Central Laboratory of the
56 *     Research Councils
57 
58 *  Licence:
59 *     This program is free software: you can redistribute it and/or
60 *     modify it under the terms of the GNU Lesser General Public
61 *     License as published by the Free Software Foundation, either
62 *     version 3 of the License, or (at your option) any later
63 *     version.
64 *
65 *     This program is distributed in the hope that it will be useful,
66 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
67 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
68 *     GNU Lesser General Public License for more details.
69 *
70 *     You should have received a copy of the GNU Lesser General
71 *     License along with this program.  If not, see
72 *     <http://www.gnu.org/licenses/>.
73 
74 *  Authors:
75 *     DSB: David S. Berry (Starlink)
76 
77 *  History:
78 *     15-MAR-2006 (DSB):
79 *        Original version.
80 *     18-MAY-2006 (DSB):
81 *        - Change logic for detecting interior points in function Transform.
82 *        - Added BADVAL to contructor argument list.
83 *class--
84 */
85 
86 /* Module Macros. */
87 /* ============== */
88 /* Set the name of the class we are implementing. This indicates to
89    the header files that define class interfaces that they should make
90    "protected" symbols available. */
91 #define astCLASS SelectorMap
92 
93 /* Include files. */
94 /* ============== */
95 /* Interface definitions. */
96 /* ---------------------- */
97 
98 #include "globals.h"             /* Thread-safe global data access */
99 #include "error.h"               /* Error reporting facilities */
100 #include "memory.h"              /* Memory allocation facilities */
101 #include "object.h"              /* Base Object class */
102 #include "pointset.h"            /* Sets of points/coordinates */
103 #include "mapping.h"             /* Coordinate Mappings (parent class) */
104 #include "unitmap.h"             /* Unit Mappings */
105 #include "channel.h"             /* I/O channels */
106 #include "selectormap.h"         /* Interface definition for this class */
107 
108 /* Error code definitions. */
109 /* ----------------------- */
110 #include "ast_err.h"             /* AST error codes */
111 
112 /* C header files. */
113 /* --------------- */
114 #include <stdarg.h>
115 #include <stddef.h>
116 #include <string.h>
117 #include <stdio.h>
118 
119 /* Module Variables. */
120 /* ================= */
121 
122 /* Address of this static variable is used as a unique identifier for
123    member of this class. */
124 static int class_check;
125 
126 /* Pointers to parent class methods which are extended by this class. */
127 static int (* parent_getobjsize)( AstObject *, int * );
128 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
129 
130 #if defined(THREAD_SAFE)
131 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
132 #endif
133 
134 
135 #ifdef THREAD_SAFE
136 /* Define how to initialise thread-specific globals. */
137 #define GLOBAL_inits \
138    globals->Class_Init = 0;
139 
140 /* Create the function that initialises global data for this module. */
141 astMAKE_INITGLOBALS(SelectorMap)
142 
143 /* Define macros for accessing each item of thread specific global data. */
144 #define class_init astGLOBAL(SelectorMap,Class_Init)
145 #define class_vtab astGLOBAL(SelectorMap,Class_Vtab)
146 
147 
148 #include <pthread.h>
149 
150 
151 #else
152 
153 
154 /* Define the class virtual function table and its initialisation flag
155    as static variables. */
156 static AstSelectorMapVtab class_vtab;   /* Virtual function table */
157 static int class_init = 0;       /* Virtual function table initialised? */
158 
159 #endif
160 
161 /* External Interface Function Prototypes. */
162 /* ======================================= */
163 /* The following functions have public prototypes only (i.e. no
164    protected prototypes), so we must provide local prototypes for use
165    within this module. */
166 AstSelectorMap *astSelectorMapId_( int, void **, double, const char *, ... );
167 
168 /* Prototypes for Private Member Functions. */
169 /* ======================================== */
170 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
171 static int Equal( AstObject *, AstObject *, int * );
172 static int GetObjSize( AstObject *, int * );
173 static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
174 static void Copy( const AstObject *, AstObject *, int * );
175 static void Delete( AstObject *, int * );
176 static void Dump( AstObject *, AstChannel *, int * );
177 
178 #if defined(THREAD_SAFE)
179 static int ManageLock( AstObject *, int, int, AstObject **, int * );
180 #endif
181 
182 /* Member functions. */
183 /* ================= */
Equal(AstObject * this_object,AstObject * that_object,int * status)184 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
185 /*
186 *  Name:
187 *     Equal
188 
189 *  Purpose:
190 *     Test if two SelectorMaps are equivalent.
191 
192 *  Type:
193 *     Private function.
194 
195 *  Synopsis:
196 *     #include "selectormap.h"
197 *     int Equal( AstObject *this, AstObject *that, int *status )
198 
199 *  Class Membership:
200 *     SelectorMap member function (over-rides the astEqual protected
201 *     method inherited from the astMapping class).
202 
203 *  Description:
204 *     This function returns a boolean result (0 or 1) to indicate whether
205 *     two SelectorMaps are equivalent.
206 
207 *  Parameters:
208 *     this
209 *        Pointer to the first Object (a SelectorMap).
210 *     that
211 *        Pointer to the second Object.
212 *     status
213 *        Pointer to the inherited status variable.
214 
215 *  Returned Value:
216 *     One if the SelectorMaps are equivalent, zero otherwise.
217 
218 *  Notes:
219 *     - A value of zero will be returned if this function is invoked
220 *     with the global status set, or if it should fail for any reason.
221 */
222 
223 /* Local Variables: */
224    AstSelectorMap *that;
225    AstSelectorMap *this;
226    int i;
227    int nin;
228    int nreg;
229    int result;
230 
231 /* Initialise. */
232    result = 0;
233 
234 /* Check the global error status. */
235    if ( !astOK ) return result;
236 
237 /* Obtain pointers to the two SelectorMap structures. */
238    this = (AstSelectorMap *) this_object;
239    that = (AstSelectorMap *) that_object;
240 
241 /* Check the second object is a SelectorMap. We know the first is a
242    SelectorMap since we have arrived at this implementation of the virtual
243    function. */
244    if( astIsASelectorMap( that ) ) {
245 
246 /* Check they have the same number of inputs. */
247       nin = astGetNin( this );
248       if( astGetNin( that ) == nin ) {
249 
250 /* Check they contain the same number of Regions, and have the same badval. */
251          nreg = this->nreg;
252          if( that->nreg == nreg ||
253              astEQUAL( that->badval, this->badval) ) {
254 
255 /* Loop over the Regions, breaking as soon as two unequal Regions are
256    found. */
257             result = 1;
258             for( i = 0; i < nreg; i++ ) {
259                if( !astEqual( this->reg[ i ], that->reg[ i ] ) ) {
260                   result = 0;
261                   break;
262                }
263             }
264          }
265       }
266    }
267 
268 /* If an error occurred, clear the result value. */
269    if ( !astOK ) result = 0;
270 
271 /* Return the result, */
272    return result;
273 }
274 
GetObjSize(AstObject * this_object,int * status)275 static int GetObjSize( AstObject *this_object, int *status ) {
276 /*
277 *  Name:
278 *     GetObjSize
279 
280 *  Purpose:
281 *     Return the in-memory size of an Object.
282 
283 *  Type:
284 *     Private function.
285 
286 *  Synopsis:
287 *     #include "selectormap.h"
288 *     int GetObjSize( AstObject *this, int *status )
289 
290 *  Class Membership:
291 *     SelectorMap member function (over-rides the astGetObjSize protected
292 *     method inherited from the parent class).
293 
294 *  Description:
295 *     This function returns the in-memory size of the supplied SelectorMap,
296 *     in bytes.
297 
298 *  Parameters:
299 *     this
300 *        Pointer to the SelectorMap.
301 *     status
302 *        Pointer to the inherited status variable.
303 
304 *  Returned Value:
305 *     The Object size, in bytes.
306 
307 *  Notes:
308 *     - A value of zero will be returned if this function is invoked
309 *     with the global status set, or if it should fail for any reason.
310 */
311 
312 /* Local Variables: */
313    AstSelectorMap *this;
314    int i;
315    int result;
316 
317 /* Initialise. */
318    result = 0;
319 
320 /* Check the global error status. */
321    if ( !astOK ) return result;
322 
323 /* Obtain a pointers to the SelectorMap structure. */
324    this = (AstSelectorMap *) this_object;
325 
326 /* Invoke the GetObjSize method inherited from the parent class, and then
327    add on any components of the class structure defined by this class
328    which are stored in dynamically allocated memory. */
329    result = (*parent_getobjsize)( this_object, status );
330 
331    for( i = 0; i < this->nreg; i++ ) {
332       result += astGetObjSize( this->reg[ i ] );
333    }
334 
335 /* If an error occurred, clear the result value. */
336    if ( !astOK ) result = 0;
337 
338 /* Return the result, */
339    return result;
340 }
341 
astInitSelectorMapVtab_(AstSelectorMapVtab * vtab,const char * name,int * status)342 void astInitSelectorMapVtab_(  AstSelectorMapVtab *vtab, const char *name, int *status ) {
343 /*
344 *+
345 *  Name:
346 *     astInitSelectorMapVtab
347 
348 *  Purpose:
349 *     Initialise a virtual function table for a SelectorMap.
350 
351 *  Type:
352 *     Protected function.
353 
354 *  Synopsis:
355 *     #include "selectormap.h"
356 *     void astInitSelectorMapVtab( AstSelectorMapVtab *vtab, const char *name )
357 
358 *  Class Membership:
359 *     SelectorMap vtab initialiser.
360 
361 *  Description:
362 *     This function initialises the component of a virtual function
363 *     table which is used by the SelectorMap class.
364 
365 *  Parameters:
366 *     vtab
367 *        Pointer to the virtual function table. The components used by
368 *        all ancestral classes will be initialised if they have not already
369 *        been initialised.
370 *     name
371 *        Pointer to a constant null-terminated character string which contains
372 *        the name of the class to which the virtual function table belongs (it
373 *        is this pointer value that will subsequently be returned by the Object
374 *        astClass function).
375 *-
376 */
377 
378 /* Local Variables: */
379    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
380    AstObjectVtab *object;        /* Pointer to Object component of Vtab */
381    AstMappingVtab *mapping;      /* Pointer to Mapping component of Vtab */
382 
383 /* Check the local error status. */
384    if ( !astOK ) return;
385 
386 /* Get a pointer to the thread specific global data structure. */
387    astGET_GLOBALS(NULL);
388 
389 /* Initialize the component of the virtual function table used by the
390    parent class. */
391    astInitMappingVtab( (AstMappingVtab *) vtab, name );
392 
393 /* Store a unique "magic" value in the virtual function table. This
394    will be used (by astIsASelectorMap) to determine if an object belongs to
395    this class.  We can conveniently use the address of the (static)
396    class_check variable to generate this unique value. */
397    vtab->id.check = &class_check;
398    vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
399 
400 /* Initialise member function pointers. */
401 /* ------------------------------------ */
402 /* Store pointers to the member functions (implemented here) that
403    provide virtual methods for this class. */
404 
405 /* None. */
406 
407 /* Save the inherited pointers to methods that will be extended, and
408    replace them with pointers to the new member functions. */
409    object = (AstObjectVtab *) vtab;
410    mapping = (AstMappingVtab *) vtab;
411    parent_getobjsize = object->GetObjSize;
412    object->GetObjSize = GetObjSize;
413 
414 #if defined(THREAD_SAFE)
415    parent_managelock = object->ManageLock;
416    object->ManageLock = ManageLock;
417 #endif
418 
419    parent_transform = mapping->Transform;
420    mapping->Transform = Transform;
421 
422 /* Store replacement pointers for methods which will be over-ridden by
423    new member functions implemented here. */
424    object->Equal = Equal;
425    mapping->MapMerge = MapMerge;
426 
427 /* Declare the copy constructor, destructor and class dump function. */
428    astSetCopy( vtab, Copy );
429    astSetDelete( vtab, Delete );
430    astSetDump( vtab, Dump, "SelectorMap", "Region identification Mapping" );
431 
432 /* If we have just initialised the vtab for the current class, indicate
433    that the vtab is now initialised, and store a pointer to the class
434    identifier in the base "object" level of the vtab. */
435    if( vtab == &class_vtab ) {
436       class_init = 1;
437       astSetVtabClassIdentifier( vtab, &(vtab->id) );
438    }
439 }
440 
441 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)442 static int ManageLock( AstObject *this_object, int mode, int extra,
443                        AstObject **fail, int *status ) {
444 /*
445 *  Name:
446 *     ManageLock
447 
448 *  Purpose:
449 *     Manage the thread lock on an Object.
450 
451 *  Type:
452 *     Private function.
453 
454 *  Synopsis:
455 *     #include "object.h"
456 *     AstObject *ManageLock( AstObject *this, int mode, int extra,
457 *                            AstObject **fail, int *status )
458 
459 *  Class Membership:
460 *     SelectorMap member function (over-rides the astManageLock protected
461 *     method inherited from the parent class).
462 
463 *  Description:
464 *     This function manages the thread lock on the supplied Object. The
465 *     lock can be locked, unlocked or checked by this function as
466 *     deteremined by parameter "mode". See astLock for details of the way
467 *     these locks are used.
468 
469 *  Parameters:
470 *     this
471 *        Pointer to the Object.
472 *     mode
473 *        An integer flag indicating what the function should do:
474 *
475 *        AST__LOCK: Lock the Object for exclusive use by the calling
476 *        thread. The "extra" value indicates what should be done if the
477 *        Object is already locked (wait or report an error - see astLock).
478 *
479 *        AST__UNLOCK: Unlock the Object for use by other threads.
480 *
481 *        AST__CHECKLOCK: Check that the object is locked for use by the
482 *        calling thread (report an error if not).
483 *     extra
484 *        Extra mode-specific information.
485 *     fail
486 *        If a non-zero function value is returned, a pointer to the
487 *        Object that caused the failure is returned at "*fail". This may
488 *        be "this" or it may be an Object contained within "this". Note,
489 *        the Object's reference count is not incremented, and so the
490 *        returned pointer should not be annulled. A NULL pointer is
491 *        returned if this function returns a value of zero.
492 *     status
493 *        Pointer to the inherited status variable.
494 
495 *  Returned Value:
496 *    A local status value:
497 *        0 - Success
498 *        1 - Could not lock or unlock the object because it was already
499 *            locked by another thread.
500 *        2 - Failed to lock a POSIX mutex
501 *        3 - Failed to unlock a POSIX mutex
502 *        4 - Bad "mode" value supplied.
503 
504 *  Notes:
505 *     - This function attempts to execute even if an error has already
506 *     occurred.
507 */
508 
509 /* Local Variables: */
510    AstSelectorMap *this;       /* Pointer to SelectorMap structure */
511    int i;                      /* Loop count */
512    int result;                 /* Returned status value */
513 
514 /* Initialise */
515    result = 0;
516 
517 /* Check the supplied pointer is not NULL. */
518    if( !this_object ) return result;
519 
520 /* Obtain a pointers to the SelectorMap structure. */
521    this = (AstSelectorMap *) this_object;
522 
523 /* Invoke the ManageLock method inherited from the parent class. */
524    if( !result ) result = (*parent_managelock)( this_object, mode, extra,
525                                                 fail, status );
526 
527 /* Invoke the astManageLock method on any Objects contained within
528    the supplied Object. */
529    for( i = 0; i < this->nreg; i++ ) {
530       if( !result ) result = astManageLock( this->reg[ i ], mode, extra, fail );
531    }
532 
533    return result;
534 
535 }
536 #endif
537 
MapMerge(AstMapping * this,int where,int series,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)538 static int MapMerge( AstMapping *this, int where, int series, int *nmap,
539                      AstMapping ***map_list, int **invert_list, int *status ) {
540 /*
541 *  Name:
542 *     MapMerge
543 
544 *  Purpose:
545 *     Simplify a sequence of Mappings containing a SelectorMap.
546 
547 *  Type:
548 *     Private function.
549 
550 *  Synopsis:
551 *     #include "mapping.h"
552 *     int MapMerge( AstMapping *this, int where, int series, int *nmap,
553 *                   AstMapping ***map_list, int **invert_list, int *status )
554 
555 *  Class Membership:
556 *     SelectorMap method (over-rides the protected astMapMerge method
557 *     inherited from the Mapping class).
558 
559 *  Description:
560 *     This function attempts to simplify a sequence of Mappings by
561 *     merging a nominated SelectorMap in the sequence with its neighbours,
562 *     so as to shorten the sequence if possible.
563 *
564 *     In many cases, simplification will not be possible and the
565 *     function will return -1 to indicate this, without further
566 *     action.
567 *
568 *     In most cases of interest, however, this function will either
569 *     attempt to replace the nominated SelectorMap with one which it
570 *     considers simpler, or to merge it with the Mappings which
571 *     immediately precede it or follow it in the sequence (both will
572 *     normally be considered). This is sufficient to ensure the
573 *     eventual simplification of most Mapping sequences by repeated
574 *     application of this function.
575 *
576 *     In some cases, the function may attempt more elaborate
577 *     simplification, involving any number of other Mappings in the
578 *     sequence. It is not restricted in the type or scope of
579 *     simplification it may perform, but will normally only attempt
580 *     elaborate simplification in cases where a more straightforward
581 *     approach is not adequate.
582 
583 *  Parameters:
584 *     this
585 *        Pointer to the nominated SelectorMap which is to be merged with
586 *        its neighbours. This should be a cloned copy of the SelectorMap
587 *        pointer contained in the array element "(*map_list)[where]"
588 *        (see below). This pointer will not be annulled, and the
589 *        SelectorMap it identifies will not be modified by this function.
590 *     where
591 *        Index in the "*map_list" array (below) at which the pointer
592 *        to the nominated SelectorMap resides.
593 *     series
594 *        A non-zero value indicates that the sequence of Mappings to
595 *        be simplified will be applied in series (i.e. one after the
596 *        other), whereas a zero value indicates that they will be
597 *        applied in parallel (i.e. on successive sub-sets of the
598 *        input/output coordinates).
599 *     nmap
600 *        Address of an int which counts the number of Mappings in the
601 *        sequence. On entry this should be set to the initial number
602 *        of Mappings. On exit it will be updated to record the number
603 *        of Mappings remaining after simplification.
604 *     map_list
605 *        Address of a pointer to a dynamically allocated array of
606 *        Mapping pointers (produced, for example, by the astMapList
607 *        method) which identifies the sequence of Mappings. On entry,
608 *        the initial sequence of Mappings to be simplified should be
609 *        supplied.
610 *
611 *        On exit, the contents of this array will be modified to
612 *        reflect any simplification carried out. Any form of
613 *        simplification may be performed. This may involve any of: (a)
614 *        removing Mappings by annulling any of the pointers supplied,
615 *        (b) replacing them with pointers to new Mappings, (c)
616 *        inserting additional Mappings and (d) changing their order.
617 *
618 *        The intention is to reduce the number of Mappings in the
619 *        sequence, if possible, and any reduction will be reflected in
620 *        the value of "*nmap" returned. However, simplifications which
621 *        do not reduce the length of the sequence (but improve its
622 *        execution time, for example) may also be performed, and the
623 *        sequence might conceivably increase in length (but normally
624 *        only in order to split up a Mapping into pieces that can be
625 *        more easily merged with their neighbours on subsequent
626 *        invocations of this function).
627 *
628 *        If Mappings are removed from the sequence, any gaps that
629 *        remain will be closed up, by moving subsequent Mapping
630 *        pointers along in the array, so that vacated elements occur
631 *        at the end. If the sequence increases in length, the array
632 *        will be extended (and its pointer updated) if necessary to
633 *        accommodate any new elements.
634 *
635 *        Note that any (or all) of the Mapping pointers supplied in
636 *        this array may be annulled by this function, but the Mappings
637 *        to which they refer are not modified in any way (although
638 *        they may, of course, be deleted if the annulled pointer is
639 *        the final one).
640 *     invert_list
641 *        Address of a pointer to a dynamically allocated array which,
642 *        on entry, should contain values to be assigned to the Invert
643 *        attributes of the Mappings identified in the "*map_list"
644 *        array before they are applied (this array might have been
645 *        produced, for example, by the astMapList method). These
646 *        values will be used by this function instead of the actual
647 *        Invert attributes of the Mappings supplied, which are
648 *        ignored.
649 *
650 *        On exit, the contents of this array will be updated to
651 *        correspond with the possibly modified contents of the
652 *        "*map_list" array.  If the Mapping sequence increases in
653 *        length, the "*invert_list" array will be extended (and its
654 *        pointer updated) if necessary to accommodate any new
655 *        elements.
656 *     status
657 *        Pointer to the inherited status variable.
658 
659 *  Returned Value:
660 *     If simplification was possible, the function returns the index
661 *     in the "map_list" array of the first element which was
662 *     modified. Otherwise, it returns -1 (and makes no changes to the
663 *     arrays supplied).
664 
665 *  Notes:
666 *     - A value of -1 will be returned if this function is invoked
667 *     with the global error status set, or if it should fail for any
668 *     reason.
669 */
670 
671 /* Local Variables: */
672    AstMapping *new;
673    AstRegion **sreg;
674    AstSelectorMap *map;
675    AstSelectorMap *slneb;
676    int equal;
677    int i;
678    int ilo;
679    int nreg;
680    int result;
681    int simp;
682 
683 /* Initialise.*/
684    result = -1;
685 
686 /* Check the inherited status. */
687    if ( !astOK ) return result;
688 
689 /* Get a pointer to this SelectorMap, and note the number of Regions. */
690    map = (AstSelectorMap *) this;
691    nreg = map->nreg;
692 
693 /* Attempt to simplify the SelectorMap on its own. */
694 /* ============================================= */
695 
696 /* Try to simplify each of the encapsulated Regions, noting if any
697    simplification takes place. */
698    simp = 0;
699    sreg = astMalloc( sizeof( AstRegion * )*nreg );
700    if( astOK ) {
701       for( i = 0; i < nreg; i++ ) {
702          sreg[ i ] = astSimplify( map->reg[ i ] );
703          simp = simp || ( sreg[ i ] != map->reg[ i ] );
704       }
705 
706 /* If any simplification took place, construct a new SelectorMap from these
707    simplified Mappings. */
708       if( simp ) {
709          (void) astAnnul( ( *map_list )[ where ] );
710          ( *map_list )[ where ] = (AstMapping *) astSelectorMap( nreg,
711                                                           (void **) sreg,
712                                                           map->badval, "", status );
713          result = where;
714       }
715 
716 /* Release resources. */
717       if( sreg ) {
718          for( i = 0; i < nreg; i++ ) sreg[ i ] = astAnnul( sreg[ i ] );
719          sreg = astFree( sreg );
720       }
721    }
722 
723 /* If possible, merge the SelectorMap with a neighbouring SelectorMap. */
724 /* =============================================================== */
725 /* Only do this if no change was made above, and we are combining the
726    Mappings in series. */
727    if( result == -1 && series ) {
728 
729 /* Is the higher neighbour a SelectorMap? If so get a pointer to it, and
730    note the index of the lower of the two adjacent SelectorMaps. */
731       if( where < ( *nmap - 1 ) &&
732           astIsASelectorMap( ( *map_list )[ where + 1 ] ) ){
733          slneb = (AstSelectorMap *) ( *map_list )[ where + 1 ];
734          ilo = where;
735 
736 /* If not, is the lower neighbour a SelectorMap? If so get a pointer to it, and
737    note the index of the lower of the two adjacent SelectorMaps. */
738       } else if( where > 0 &&
739                  astIsASelectorMap( ( *map_list )[ where - 1 ] ) ){
740          slneb = (AstSelectorMap *) ( *map_list )[ where - 1 ];
741          ilo =  where - 1;
742 
743       } else {
744          slneb = NULL;
745       }
746 
747 /* If a neighbouring SelectorMap was found, we can replace the pair by a
748    UnitMap if the two SelectorMaps are equal but have opposite values for
749    their Invert flags. Temporarily invert the neighbour, then compare
750    the two SelectorMaps for equality, then re-invert the neighbour. */
751       if( slneb ) {
752          astInvert( slneb );
753          equal = astEqual( map, slneb );
754          astInvert( slneb );
755 
756 /* If the two SelectorMaps are equal but opposite, annul the first of the two
757    Mappings, and replace it with a UnitMap. Also set the invert flag. */
758          if( equal ) {
759             new = (AstMapping *) astUnitMap( astGetNin( ( *map_list )[ ilo ] ), "", status );
760             (void) astAnnul( ( *map_list )[ ilo ] );
761             ( *map_list )[ ilo ] = new;
762             ( *invert_list )[ ilo ] = 0;
763 
764 /* Annul the second of the two Mappings, and shuffle down the rest of the
765    list to fill the gap. */
766             (void) astAnnul( ( *map_list )[ ilo + 1 ] );
767             for ( i = ilo + 2; i < *nmap; i++ ) {
768                ( *map_list )[ i - 1 ] = ( *map_list )[ i ];
769                ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ];
770             }
771 
772 /* Clear the vacated element at the end. */
773             ( *map_list )[ *nmap - 1 ] = NULL;
774             ( *invert_list )[ *nmap - 1 ] = 0;
775 
776 /* Decrement the Mapping count and return the index of the first
777    modified element. */
778             ( *nmap )--;
779             result = where;
780          }
781       }
782    }
783 
784 /* If an error occurred, clear the result value. */
785    if ( !astOK ) result = -1;
786 
787 /* Return the result. */
788    return result;
789 }
790 
Transform(AstMapping * this,AstPointSet * in,int forward,AstPointSet * out,int * status)791 static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
792                                int forward, AstPointSet *out, int *status ) {
793 /*
794 *  Name:
795 *     Transform
796 
797 *  Purpose:
798 *     Apply a SelectorMap to transform a set of points.
799 
800 *  Type:
801 *     Private function.
802 
803 *  Synopsis:
804 *     #include "selectormap.h"
805 *     AstPointSet *Transform( AstMapping *this, AstPointSet *in,
806 *                             int forward, AstPointSet *out, int *status )
807 
808 *  Class Membership:
809 *     SelectorMap member function (over-rides the astTransform method inherited
810 *     from the Mapping class).
811 
812 *  Description:
813 *     This function takes a SelectorMap and a set of points encapsulated in a
814 *     PointSet and transforms the points so as to apply the required Mapping.
815 *     This implies applying each of the SelectorMap's component Mappings in turn,
816 *     either in series or in parallel.
817 
818 *  Parameters:
819 *     this
820 *        Pointer to the SelectorMap.
821 *     in
822 *        Pointer to the PointSet associated with the input coordinate values.
823 *     forward
824 *        A non-zero value indicates that the forward coordinate transformation
825 *        should be applied, while a zero value requests the inverse
826 *        transformation.
827 *     out
828 *        Pointer to a PointSet which will hold the transformed (output)
829 *        coordinate values. A NULL value may also be given, in which case a
830 *        new PointSet will be created by this function.
831 *     status
832 *        Pointer to the inherited status variable.
833 
834 *  Returned Value:
835 *     Pointer to the output (possibly new) PointSet.
836 
837 *  Notes:
838 *     -  A null pointer will be returned if this function is invoked with the
839 *     global error status set, or if it should fail for any reason.
840 *     -  The number of coordinate values per point in the input PointSet must
841 *     match the number of coordinates for the SelectorMap being applied.
842 *     -  If an output PointSet is supplied, it must have space for sufficient
843 *     number of points and coordinate values per point to accommodate the
844 *     result. Any excess space will be ignored.
845 */
846 
847 /* Local Variables: */
848    AstPointSet *ps1;
849    AstPointSet *ps2;
850    AstPointSet *result;
851    AstPointSet *tps;
852    AstRegion *reg;
853    AstSelectorMap *map;
854    double **ptr_out;
855    double **ptr1;
856    double **ptr2;
857    double **tptr;
858    double *p2;
859    double *pout;
860    double badval;
861    int bad;
862    int closed;
863    int icoord;
864    int ipoint;
865    int ireg;
866    int ncoord;
867    int npoint;
868 
869 /* Check the global error status. */
870    if ( !astOK ) return NULL;
871 
872 /* Obtain a pointer to the SelectorMap. */
873    map = (AstSelectorMap *) this;
874 
875 /* Apply the parent Mapping using the stored pointer to the Transform member
876    function inherited from the parent Mapping class. This function validates
877    all arguments and generates an output PointSet if necessary, but does not
878    actually transform any coordinate values. */
879    result = (*parent_transform)( this, in, forward, out, status );
880 
881 /* We now extend the parent astTransform method by applying the component
882    Mappings of the SelectorMap to generate the output coordinate values. */
883 
884 /* Check we are implementing the original forward transformation (the
885    inverse transformation is not defined). */
886    if( forward != astGetInvert( this ) ) {
887 
888 /* Get the number of input axes and the number of points. */
889       ncoord = astGetNcoord( in );
890       npoint = astGetNpoint( in );
891 
892 /* Create two temporary PointSets to hold copies of the input points. */
893       ps1 = astCopy( in );
894       ptr1 = astGetPoints( ps1 );
895       ps2 = astPointSet( npoint, ncoord, "", status );
896       ptr2 = astGetPoints( ps2 );
897 
898 /* Get a pointer to the output data */
899       ptr_out = astGetPoints( result );
900       if( astOK ) {
901 
902 /* Initialise the output array to hold -1 at any points that have
903    bad input axis values, and zero at all other points. */
904          pout = ptr_out[ 0 ];
905          for( ipoint = 0; ipoint < npoint; ipoint++ ) {
906             bad = 0;
907             for( icoord = 0; icoord < ncoord; icoord++ ) {
908                if( ptr1[ icoord ][ ipoint ] == AST__BAD ) {
909                   bad = 1;
910                   break;
911                }
912             }
913             *(pout++) = bad ? -1 : 0;
914          }
915 
916 /* Loop round all Regions. */
917          for( ireg = 1; ireg <= map->nreg; ireg++ ) {
918             reg = map->reg[ ireg - 1 ];
919 
920 /* Temporarily Negate the Region. */
921             astNegate( reg );
922             closed = astGetClosed( reg );
923             astSetClosed( reg, !closed );
924 
925 /* Transform the remaining input positions. Good input positions which
926    are within the Region will be bad in the output. */
927             ps2 = astTransform( reg, ps1, 1, ps2 );
928 
929 /* Loop round all positions. */
930             p2 = ptr2[ 0 ];
931             pout = ptr_out[ 0 ];
932             for( ipoint = 0; ipoint < npoint; ipoint++, p2++, pout++ ) {
933 
934 /* Any position that has not already been assigned to a Region and is bad
935    in the output PointSet must be contained within the current Region, so
936    assign the (one-based) index of the current Region to the output element. */
937                if( *pout == 0 && *p2 == AST__BAD ) *pout = ireg;
938             }
939 
940 /* Negate the Region to get it back to its original state. */
941             astSetClosed( reg, closed );
942             astNegate( reg );
943 
944 /* Swap the input and output PointSets. */
945             tps = ps1;
946             ps1 = ps2;
947             ps2 = tps;
948             tptr = ptr1;
949             ptr1 = ptr2;
950             ptr2 = tptr;
951          }
952 
953 /* Replace -1 values in the output (that indicate that the input position
954    had at least one bad axis value) with the "badval".*/
955          badval = map->badval;
956          pout = ptr_out[ 0 ];
957          for( ipoint = 0; ipoint < npoint; ipoint++, pout++ ) {
958             if( *pout == -1 ) *pout = badval;
959          }
960       }
961 
962 /* Free resources. */
963       ps1 = astAnnul( ps1 );
964       ps2 = astAnnul( ps2 );
965    }
966 
967 /* If an error occurred, clean up by deleting the output PointSet (if
968    allocated by this function) and setting a NULL result pointer. */
969    if ( !astOK ) {
970       if ( !out ) result = astDelete( result );
971       result = NULL;
972    }
973 
974 /* Return a pointer to the output PointSet. */
975    return result;
976 }
977 
978 /* Copy constructor. */
979 /* ----------------- */
Copy(const AstObject * objin,AstObject * objout,int * status)980 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
981 /*
982 *  Name:
983 *     Copy
984 
985 *  Purpose:
986 *     Copy constructor for SelectorMap objects.
987 
988 *  Type:
989 *     Private function.
990 
991 *  Synopsis:
992 *     void Copy( const AstObject *objin, AstObject *objout, int *status )
993 
994 *  Description:
995 *     This function implements the copy constructor for SelectorMap objects.
996 
997 *  Parameters:
998 *     objin
999 *        Pointer to the object to be copied.
1000 *     objout
1001 *        Pointer to the object being constructed.
1002 *     status
1003 *        Pointer to the inherited status variable.
1004 
1005 *  Returned Value:
1006 *     void
1007 
1008 *  Notes:
1009 *     -  This constructor makes a deep copy, including a copy of the
1010 *     Regions within the SelectorMap.
1011 */
1012 
1013 /* Local Variables: */
1014    AstSelectorMap *in;                /* Pointer to input SelectorMap */
1015    AstSelectorMap *out;               /* Pointer to output SelectorMap */
1016    int i;                             /* Loop count */
1017 
1018 /* Check the global error status. */
1019    if ( !astOK ) return;
1020 
1021 /* Obtain pointers to the input and output SelectorMaps. */
1022    in = (AstSelectorMap *) objin;
1023    out = (AstSelectorMap *) objout;
1024 
1025 /* For safety, start by clearing any references to the input Regions. */
1026    out->reg = NULL;
1027    out->nreg = 0;
1028 
1029 /* Make copies of the Regions, and store pointers to them in the output
1030    SelectorMap structure. */
1031    out->reg = astMalloc( sizeof( AstRegion * )*( in->nreg ) );
1032    if( astOK ) {
1033       for( i = 0; i < in->nreg; i++ ) {
1034          out->reg[ i ] = astCopy( in->reg[ i ] );
1035       }
1036       out->nreg = in->nreg;
1037    }
1038 
1039 }
1040 
1041 /* Destructor. */
1042 /* ----------- */
Delete(AstObject * obj,int * status)1043 static void Delete( AstObject *obj, int *status ) {
1044 /*
1045 *  Name:
1046 *     Delete
1047 
1048 *  Purpose:
1049 *     Destructor for SelectorMap objects.
1050 
1051 *  Type:
1052 *     Private function.
1053 
1054 *  Synopsis:
1055 *     void Delete( AstObject *obj, int *status )
1056 
1057 *  Description:
1058 *     This function implements the destructor for SelectorMap objects.
1059 
1060 *  Parameters:
1061 *     obj
1062 *        Pointer to the object to be deleted.
1063 *     status
1064 *        Pointer to the inherited status variable.
1065 
1066 *  Returned Value:
1067 *     void
1068 
1069 *  Notes:
1070 *     This function attempts to execute even if the global error status is
1071 *     set.
1072 */
1073 
1074 /* Local Variables: */
1075    AstSelectorMap *this;              /* Pointer to SelectorMap */
1076    int i;
1077 
1078 /* Obtain a pointer to the SelectorMap structure. */
1079    this = (AstSelectorMap *) obj;
1080 
1081 /* Free dynamically allocated resources. */
1082    for( i = 0; i < this->nreg; i++ ) {
1083       this->reg[ i ] = astAnnul( this->reg[ i ] );
1084    }
1085    this->reg = astFree( this->reg );
1086 
1087 /* Clear the remaining SelectorMap variables. */
1088    this->nreg = 0;
1089 }
1090 
1091 /* Dump function. */
1092 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)1093 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
1094 /*
1095 *  Name:
1096 *     Dump
1097 
1098 *  Purpose:
1099 *     Dump function for SelectorMap objects.
1100 
1101 *  Type:
1102 *     Private function.
1103 
1104 *  Synopsis:
1105 *     void Dump( AstObject *this, AstChannel *channel, int *status )
1106 
1107 *  Description:
1108 *     This function implements the Dump function which writes out data
1109 *     for the SelectorMap class to an output Channel.
1110 
1111 *  Parameters:
1112 *     this
1113 *        Pointer to the SelectorMap whose data are being written.
1114 *     channel
1115 *        Pointer to the Channel to which the data are being written.
1116 *     status
1117 *        Pointer to the inherited status variable.
1118 */
1119 
1120 /* Local Variables: */
1121    AstSelectorMap *this;
1122    int i;
1123    char buf[ 20 ];
1124 
1125 /* Check the global error status. */
1126    if ( !astOK ) return;
1127 
1128 /* Obtain a pointer to the SelectorMap structure. */
1129    this = (AstSelectorMap *) this_object;
1130 
1131 /* Write out values representing the instance variables for the SelectorMap
1132    class.  Accompany these with appropriate comment strings, possibly
1133    depending on the values being written.*/
1134 
1135 /* In the case of attributes, we first use the appropriate (private)
1136    Test...  member function to see if they are set. If so, we then use
1137    the (private) Get... function to obtain the value to be written
1138    out.
1139 
1140    For attributes which are not set, we use the astGet... method to
1141    obtain the value instead. This will supply a default value
1142    (possibly provided by a derived class which over-rides this method)
1143    which is more useful to a human reader as it corresponds to the
1144    actual default attribute value.  Since "set" will be zero, these
1145    values are for information only and will not be read back. */
1146 
1147 /* Loop to dump each Region. */
1148 /* ------------------------- */
1149 /* The coordinate Frame of the Regions is defined by the first Region.
1150    The Frame information is omitted from the second and subsequent
1151    Regions by setting the protected RegionFS attribute to zero. */
1152    for( i = 0; i < this->nreg; i++ ) {
1153       sprintf( buf, "Reg%d", i + 1 );
1154       if( i > 0 ) astSetRegionFS( this->reg[ i ], 0 );
1155       astWriteObject( channel, buf, 1, 1, this->reg[ i ],
1156                       "Region of input space" );
1157       if( i > 0 ) astClearRegionFS( this->reg[ i ] );
1158    }
1159 
1160 /* BadVal. */
1161 /* ------- */
1162    if( this->badval != AST__BAD ) {
1163       astWriteDouble( channel, "BadVal", 1, 1, this->badval,
1164                       "Output value for bad input positions" );
1165    }
1166 
1167 }
1168 
1169 /* Standard class functions. */
1170 /* ========================= */
1171 /* Implement the astIsASelectorMap and astCheckSelectorMap functions using the
1172    macros defined for this purpose in the "object.h" header file. */
astMAKE_ISA(SelectorMap,Mapping)1173 astMAKE_ISA(SelectorMap,Mapping)
1174 astMAKE_CHECK(SelectorMap)
1175 
1176 AstSelectorMap *astSelectorMap_( int nreg, void **regs_void, double badval,
1177                                  const char *options, int *status, ...) {
1178 /*
1179 *+
1180 *  Name:
1181 *     astSelectorMap
1182 
1183 *  Purpose:
1184 *     Create a SelectorMap.
1185 
1186 *  Type:
1187 *     Protected function.
1188 
1189 *  Synopsis:
1190 *     #include "selectormap.h"
1191 *     AstSelectorMap *astSelectorMap( int nreg, AstRegion **regs,
1192 *                                     double badval, const char *options, ... )
1193 
1194 *  Class Membership:
1195 *     SelectorMap constructor.
1196 
1197 *  Description:
1198 *     This function creates a new SelectorMap and optionally initialises its
1199 *     attributes.
1200 
1201 *  Parameters:
1202 *     nreg
1203 *        The number of Regions supplied.
1204 *     regs
1205 *        An array of pointers to the Regions. Deep copies of these
1206 *        Regions are taken.
1207 *     badval
1208 *        The value to be returned by the forward transformation of the
1209 *        SelectorMap for any input positions that have a bad (AST__BAD)
1210 *        value on any axis.
1211 *     options
1212 *        Pointer to a null terminated string containing an optional
1213 *        comma-separated list of attribute assignments to be used for
1214 *        initialising the new SelectorMap. The syntax used is the same as for the
1215 *        astSet method and may include "printf" format specifiers identified
1216 *        by "%" symbols in the normal way.
1217 *     ...
1218 *        If the "options" string contains "%" format specifiers, then an
1219 *        optional list of arguments may follow it in order to supply values to
1220 *        be substituted for these specifiers. The rules for supplying these
1221 *        are identical to those for the astSet method (and for the C "printf"
1222 *        function).
1223 
1224 *  Returned Value:
1225 *     A pointer to the new SelectorMap.
1226 
1227 *  Notes:
1228 *     - A null pointer will be returned if this function is invoked
1229 *     with the global error status set, or if it should fail for any
1230 *     reason.
1231 *-
1232 
1233 *  Implementation Notes:
1234 *     - This function implements the basic SelectorMap constructor which is
1235 *     available via the protected interface to the SelectorMap class.  A
1236 *     public interface is provided by the astSelectorMapId_ function.
1237 *     - Because this function has a variable argument list, it is
1238 *     invoked by a macro that evaluates to a function pointer (not a
1239 *     function invocation) and no checking or casting of arguments is
1240 *     performed before the function is invoked. Because of this, the
1241 *     "map1" and "map2" parameters are of type (void *) and are
1242 *     converted and validated within the function itself.
1243 */
1244 
1245 /* Local Variables: */
1246    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
1247    AstSelectorMap *new;          /* Pointer to new SelectorMap */
1248    AstRegion **regs;             /* Array of Region pointers */
1249    int i;                        /* Region index */
1250    va_list args;                 /* Variable argument list */
1251 
1252 /* Initialise. */
1253    new = NULL;
1254 
1255 /* Get a pointer to the thread specific global data structure. */
1256    astGET_GLOBALS(NULL);
1257 
1258 /* Check the global status. */
1259    if ( !astOK ) return new;
1260 
1261 /* Report an error if no Regions have been supplied. */
1262    if( nreg <= 0 ) astError( AST__BDPAR, "astSelectorMap(SelectorMap): "
1263                             "Bad number of Regions (%d) specified.", status, nreg );
1264 
1265 /* Otherwise create an array to hold the Region pointers. */
1266    regs = astMalloc( sizeof( AstRegion * )*nreg );
1267 
1268 /* Obtain and validate pointers to the Region structures provided. */
1269    if( astOK ) {
1270       for( i = 0; i < nreg; i++ ) {
1271          regs[ i ] = astCheckRegion( regs_void[ i ] );
1272       }
1273    }
1274 
1275    if ( astOK ) {
1276 
1277 /* Initialise the SelectorMap, allocating memory and initialising the
1278    virtual function table as well if necessary. */
1279       new = astInitSelectorMap( NULL, sizeof( AstSelectorMap ), !class_init, &class_vtab,
1280                               "SelectorMap", nreg, regs, badval );
1281 
1282 /* If successful, note that the virtual function table has been
1283    initialised. */
1284       if ( astOK ) {
1285          class_init = 1;
1286 
1287 /* Obtain the variable argument list and pass it along with the
1288    options string to the astVSet method to initialise the new SelectorMap's
1289    attributes. */
1290          va_start( args, status );
1291          astVSet( new, options, NULL, args );
1292          va_end( args );
1293 
1294 /* If an error occurred, clean up by deleting the new object. */
1295          if ( !astOK ) new = astDelete( new );
1296       }
1297    }
1298 
1299 /* Free memory used to hold the Regions pointers. */
1300    regs = astFree( regs );
1301 
1302 /* Return a pointer to the new SelectorMap. */
1303    return new;
1304 }
1305 
astSelectorMapId_(int nreg,void ** regs_void,double badval,const char * options,...)1306 AstSelectorMap *astSelectorMapId_( int nreg, void **regs_void, double badval,
1307                                    const char *options, ... ) {
1308 /*
1309 *++
1310 *  Name:
1311 c     astSelectorMap
1312 f     AST_SELECTORMAP
1313 
1314 *  Purpose:
1315 *     Create a SelectorMap.
1316 
1317 *  Type:
1318 *     Public function.
1319 
1320 *  Synopsis:
1321 c     #include "selectormap.h"
1322 c     AstSelectorMap *astSelectorMap( int nreg, AstRegion *regs[],
1323 c                                     double badval, const char *options, ... )
1324 f     RESULT = AST_SELECTORMAP( NREG, REGS, BADVAL, OPTIONS, STATUS )
1325 
1326 *  Class Membership:
1327 *     SelectorMap constructor.
1328 
1329 *  Description:
1330 *     This function creates a new SelectorMap and optionally initialises
1331 *     its attributes.
1332 *
1333 *     A SelectorMap is a Mapping that identifies which Region contains
1334 *     a given input position.
1335 *
1336 *     A SelectorMap encapsulates a number of Regions that all have the same
1337 *     number of axes and represent the same coordinate Frame. The number of
1338 *     inputs (Nin attribute) of the SelectorMap equals the number of axes
1339 *     spanned by one of the encapsulated Region. All SelectorMaps have only
1340 *     a single output. SelectorMaps do not define an inverse transformation.
1341 *
1342 *     For each input position, the forward transformation of a SelectorMap
1343 *     searches through the encapsulated Regions (in the order supplied when
1344 *     the SelectorMap was created) until a Region is found which contains
1345 *     the input position. The index associated with this Region is
1346 *     returned as the SelectorMap output value (the index value is the
1347 *     position of the Region within the list of Regions supplied when the
1348 *     SelectorMap was created, starting at 1 for the first Region). If an
1349 *     input position is not contained within any Region, a value of zero is
1350 *     returned by the forward transformation.
1351 *
1352 *     If a compound Mapping contains a SelectorMap in series with its own
1353 *     inverse, the combination of the two adjacent SelectorMaps will be
1354 *     replaced by a UnitMap when the compound Mapping is simplified using
1355 c     astSimplify.
1356 f     AST_SIMPLIFY.
1357 *
1358 *     In practice, SelectorMaps are often used in conjunction with SwitchMaps.
1359 
1360 *  Parameters:
1361 c     nreg
1362 f     NREG = INTEGER (Given)
1363 *        The number of supplied Regions.
1364 c     regs
1365 f     REGS( NREG ) = INTEGER (Given)
1366 *        An array of pointers to the Regions. All the supplied Regions must
1367 *        relate to the same coordinate Frame. The number of axes in this
1368 *        coordinate Frame defines the number of inputs for the SelectorMap.
1369 c     badval
1370 f     BADVAL = DOUBLE PRECISION (Given)
1371 *        The value to be returned by the forward transformation of the
1372 *        SelectorMap for any input positions that have a bad (AST__BAD)
1373 *        value on any axis.
1374 c     options
1375 f     OPTIONS = CHARACTER * ( * ) (Given)
1376 c        Pointer to a null-terminated string containing an optional
1377 c        comma-separated list of attribute assignments to be used for
1378 c        initialising the new SelectorMap. The syntax used is identical to
1379 c        that for the astSet function and may include "printf" format
1380 c        specifiers identified by "%" symbols in the normal way.
1381 f        A character string containing an optional comma-separated
1382 f        list of attribute assignments to be used for initialising the
1383 f        new SelectorMap. The syntax used is identical to that for the
1384 f        AST_SET routine.
1385 c     ...
1386 c        If the "options" string contains "%" format specifiers, then
1387 c        an optional list of additional arguments may follow it in
1388 c        order to supply values to be substituted for these
1389 c        specifiers. The rules for supplying these are identical to
1390 c        those for the astSet function (and for the C "printf"
1391 c        function).
1392 f     STATUS = INTEGER (Given and Returned)
1393 f        The global status.
1394 
1395 *  Returned Value:
1396 c     astSelectorMap()
1397 f     AST_SELECTORMAP = INTEGER
1398 *        A pointer to the new SelectorMap.
1399 
1400 *  Notes:
1401 *     - Deep copies are taken of the supplied Regions. This means that
1402 *     any subsequent changes made to the component Regions using the
1403 *     supplied pointers will have no effect on the SelectorMap.
1404 *     - A null Object pointer (AST__NULL) will be returned if this
1405 c     function is invoked with the AST error status set, or if it
1406 f     function is invoked with STATUS set to an error value, or if it
1407 *     should fail for any reason.
1408 *--
1409 
1410 *  Implementation Notes:
1411 *     - This function implements the external (public) interface to
1412 *     the astSelectorMap constructor function. It returns an ID value
1413 *     (instead of a true C pointer) to external users, and must be
1414 *     provided because astSelectorMap_ has a variable argument list which
1415 *     cannot be encapsulated in a macro (where this conversion would
1416 *     otherwise occur).
1417 *     - Because no checking or casting of arguments is performed
1418 *     before the function is invoked, the "map1" and "map2" parameters
1419 *     are of type (void *) and are converted from an ID value to a
1420 *     pointer and validated within the function itself.
1421 *     - The variable argument list also prevents this function from
1422 *     invoking astSelectorMap_ directly, so it must be a re-implementation
1423 *     of it in all respects, except for the conversions between IDs
1424 *     and pointers on input/output of Objects.
1425 */
1426 
1427 /* Local Variables: */
1428    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
1429    AstSelectorMap *new;          /* Pointer to new SelectorMap */
1430    AstRegion **regs;             /* Array of Region pointers */
1431    int i;                        /* Region index */
1432    va_list args;                 /* Variable argument list */
1433 
1434    int *status;                  /* Pointer to inherited status value */
1435 
1436 /* Get a pointer to the thread specific global data structure. */
1437    astGET_GLOBALS(NULL);
1438 
1439 /* Initialise. */
1440    new = NULL;
1441 
1442 /* Get a pointer to the inherited status value. */
1443    status = astGetStatusPtr;
1444 
1445 /* Check the global status. */
1446    if ( !astOK ) return new;
1447 
1448 /* Report an error if no Regions have been supplied. */
1449    if( nreg <= 0 ) astError( AST__BDPAR, "astSelectorMap(SelectorMap): "
1450                              "Bad number of Regions (%d) specified.", status, nreg );
1451 
1452 /* Create an array to hold the Region pointers. */
1453    regs = astMalloc( sizeof( AstRegion * )*nreg );
1454 
1455 /* Obtain and validate pointers to the Region structures provided. */
1456    if( astOK ) {
1457       for( i = 0; i < nreg; i++ ) {
1458          regs[ i ] = astVerifyRegion( astMakePointer(regs_void[ i ]) );
1459       }
1460    }
1461 
1462    if ( astOK ) {
1463 
1464 /* Initialise the SelectorMap, allocating memory and initialising the
1465    virtual function table as well if necessary. */
1466       new = astInitSelectorMap( NULL, sizeof( AstSelectorMap ), !class_init,
1467                                 &class_vtab, "SelectorMap", nreg, regs,
1468                                 badval );
1469 
1470 /* If successful, note that the virtual function table has been
1471    initialised. */
1472       if ( astOK ) {
1473          class_init = 1;
1474 
1475 /* Obtain the variable argument list and pass it along with the
1476    options string to the astVSet method to initialise the new SelectorMap's
1477    attributes. */
1478          va_start( args, options );
1479          astVSet( new, options, NULL, args );
1480          va_end( args );
1481 
1482 /* If an error occurred, clean up by deleting the new object. */
1483          if ( !astOK ) new = astDelete( new );
1484       }
1485    }
1486 
1487 /* Free memory used to hold the Regions pointers. */
1488    regs = astFree( regs );
1489 
1490 /* Return an ID value for the new SelectorMap. */
1491    return astMakeId( new );
1492 }
1493 
astInitSelectorMap_(void * mem,size_t size,int init,AstSelectorMapVtab * vtab,const char * name,int nreg,AstRegion ** regs,double badval,int * status)1494 AstSelectorMap *astInitSelectorMap_( void *mem, size_t size, int init,
1495                                      AstSelectorMapVtab *vtab, const char *name,
1496                                      int nreg, AstRegion **regs, double badval, int *status ) {
1497 /*
1498 *+
1499 *  Name:
1500 *     astInitSelectorMap
1501 
1502 *  Purpose:
1503 *     Initialise a SelectorMap.
1504 
1505 *  Type:
1506 *     Protected function.
1507 
1508 *  Synopsis:
1509 *     #include "selectormap.h"
1510 *     AstSelectorMap *astInitSelectorMap( void *mem, size_t size, int init,
1511 *                                         AstSelectorMapVtab *vtab, const char *name,
1512 *                                         int nreg, AstRegion **regs, double badval )
1513 
1514 *  Class Membership:
1515 *     SelectorMap initialiser.
1516 
1517 *  Description:
1518 *     This function is provided for use by class implementations to initialise
1519 *     a new SelectorMap object. It allocates memory (if necessary) to
1520 *     accommodate the SelectorMap plus any additional data associated with the
1521 *     derived class. It then initialises a SelectorMap structure at the start
1522 *     of this memory. If the "init" flag is set, it also initialises the
1523 *     contents of a virtual function table for a SelectorMap at the start of
1524 *     the memory passed via the "vtab" parameter.
1525 
1526 *  Parameters:
1527 *     mem
1528 *        A pointer to the memory in which the SelectorMap is to be initialised.
1529 *        This must be of sufficient size to accommodate the SelectorMap data
1530 *        (sizeof(SelectorMap)) plus any data used by the derived class. If a
1531 *        value of NULL is given, this function will allocate the memory itself
1532 *        using the "size" parameter to determine its size.
1533 *     size
1534 *        The amount of memory used by the SelectorMap (plus derived class
1535 *        data). This will be used to allocate memory if a value of NULL is
1536 *        given for the "mem" parameter. This value is also stored in the
1537 *        SelectorMap structure, so a valid value must be supplied even if not
1538 *        required for allocating memory.
1539 *     init
1540 *        A logical flag indicating if the SelectorMap's virtual function table
1541 *        is to be initialised. If this value is non-zero, the virtual function
1542 *        table will be initialised by this function.
1543 *     vtab
1544 *        Pointer to the start of the virtual function table to be associated
1545 *        with the new SelectorMap.
1546 *     name
1547 *        Pointer to a constant null-terminated character string which contains
1548 *        the name of the class to which the new object belongs (it is this
1549 *        pointer value that will subsequently be returned by the Object
1550 *        astClass function).
1551 *     nreg
1552 *        The number of Regions supplied.
1553 *     regs
1554 *        An array holdiong pointers to the Regions. Deep copies are taken
1555 *        of these Regions.
1556 *     badval
1557 *        The value to be returned by the forward transformation of the
1558 *        SelectorMap for any input positions that have a bad (AST__BAD)
1559 *        value on any axis.
1560 
1561 *  Returned Value:
1562 *     A pointer to the new SelectorMap.
1563 
1564 *  Notes:
1565 *     -  A null pointer will be returned if this function is invoked with the
1566 *     global error status set, or if it should fail for any reason.
1567 *-
1568 */
1569 
1570 /* Local Variables: */
1571    AstFrame *f0;                 /* Frame from first Region */
1572    AstFrame *f1;                 /* Frame from current Region */
1573    AstSelectorMap *new;          /* Pointer to new SelectorMap */
1574    int equal;                    /* Are Frames equal? */
1575    int i;                        /* Loop count */
1576    int nin;                      /* No. input coordinates for SelectorMap */
1577 
1578 /* Check the global status. */
1579    if ( !astOK ) return NULL;
1580 
1581 /* If necessary, initialise the virtual function table. */
1582    if ( init ) astInitSelectorMapVtab( vtab, name );
1583 
1584 /* Initialise. */
1585    new = NULL;
1586 
1587 /* Check that all Regions refer to the same Frame. */
1588    f0 = astRegFrame( regs[ 0 ] );
1589    for( i = 1; i < nreg; i++ ) {
1590       f1 = astRegFrame( regs[ i ] );
1591       equal = astEqual( f1, f0 );
1592       f1 = astAnnul( f1 );
1593 
1594       if( !equal ) {
1595          if( astOK ) {
1596             astError( AST__BADNI, "astInitSelectorMap(%s): Region "
1597                       "number %d does not refer to the same coordinate "
1598                       "Frame as the first Region.", status, name, i + 1 );
1599          }
1600       }
1601    }
1602 
1603    nin = astGetNin( regs[ 0 ] );
1604    f0 = astAnnul( f0 );
1605 
1606 /* Initialise a Mapping structure (the parent class) as the first component
1607    within the SelectorMap structure, allocating memory if necessary. Specify
1608    the number of input and output coordinates and in which directions the
1609    Mapping should be defined. */
1610    if ( astOK ) {
1611       new = (AstSelectorMap *) astInitMapping( mem, size, 0,
1612                                              (AstMappingVtab *) vtab, name,
1613                                              nin, 1, 1, 0 );
1614       if ( astOK ) {
1615 
1616 /* Initialise the SelectorMap data. */
1617 /* -------------------------------- */
1618 
1619 /* Create an array for the Region pointers. */
1620          new->reg = astMalloc( sizeof( AstRegion * )*nreg );
1621 
1622 /* Store pointers to deep copies of the Regions. */
1623          if( astOK ) {
1624             new->nreg = nreg;
1625             for( i = 0; i < nreg; i++ ) {
1626                new->reg[ i ] = astCopy( regs[ i ] );
1627             }
1628          } else {
1629             new->nreg = 0;
1630          }
1631 
1632 /* Store other items */
1633          new->badval = badval;
1634 
1635 /* If an error occurred, clean up by deleting the new object. */
1636          if ( !astOK ) new = astDelete( new );
1637       }
1638    }
1639 
1640 /* Return a pointer to the new object. */
1641    return new;
1642 }
1643 
astLoadSelectorMap_(void * mem,size_t size,AstSelectorMapVtab * vtab,const char * name,AstChannel * channel,int * status)1644 AstSelectorMap *astLoadSelectorMap_( void *mem, size_t size,
1645                                      AstSelectorMapVtab *vtab, const char *name,
1646                                      AstChannel *channel, int *status ) {
1647 /*
1648 *+
1649 *  Name:
1650 *     astLoadSelectorMap
1651 
1652 *  Purpose:
1653 *     Load a SelectorMap.
1654 
1655 *  Type:
1656 *     Protected function.
1657 
1658 *  Synopsis:
1659 *     #include "selectormap.h"
1660 *     AstSelectorMap *astLoadSelectorMap( void *mem, size_t size,
1661 *                                         AstSelectorMapVtab *vtab, const char *name,
1662 *                                         AstChannel *channel )
1663 
1664 *  Class Membership:
1665 *     SelectorMap loader.
1666 
1667 *  Description:
1668 *     This function is provided to load a new SelectorMap using data read
1669 *     from a Channel. It first loads the data used by the parent class
1670 *     (which allocates memory if necessary) and then initialises a
1671 *     SelectorMap structure in this memory, using data read from the input
1672 *     Channel.
1673 *
1674 *     If the "init" flag is set, it also initialises the contents of a
1675 *     virtual function table for a SelectorMap at the start of the memory
1676 *     passed via the "vtab" parameter.
1677 
1678 
1679 *  Parameters:
1680 *     mem
1681 *        A pointer to the memory into which the SelectorMap is to be
1682 *        loaded.  This must be of sufficient size to accommodate the
1683 *        SelectorMap data (sizeof(SelectorMap)) plus any data used by derived
1684 *        classes. If a value of NULL is given, this function will
1685 *        allocate the memory itself using the "size" parameter to
1686 *        determine its size.
1687 *     size
1688 *        The amount of memory used by the SelectorMap (plus derived class
1689 *        data).  This will be used to allocate memory if a value of
1690 *        NULL is given for the "mem" parameter. This value is also
1691 *        stored in the SelectorMap structure, so a valid value must be
1692 *        supplied even if not required for allocating memory.
1693 *
1694 *        If the "vtab" parameter is NULL, the "size" value is ignored
1695 *        and sizeof(AstSelectorMap) is used instead.
1696 *     vtab
1697 *        Pointer to the start of the virtual function table to be
1698 *        associated with the new SelectorMap. If this is NULL, a pointer to
1699 *        the (static) virtual function table for the SelectorMap class is
1700 *        used instead.
1701 *     name
1702 *        Pointer to a constant null-terminated character string which
1703 *        contains the name of the class to which the new object
1704 *        belongs (it is this pointer value that will subsequently be
1705 *        returned by the astGetClass method).
1706 *
1707 *        If the "vtab" parameter is NULL, the "name" value is ignored
1708 *        and a pointer to the string "SelectorMap" is used instead.
1709 
1710 *  Returned Value:
1711 *     A pointer to the new SelectorMap.
1712 
1713 *  Notes:
1714 *     - A null pointer will be returned if this function is invoked
1715 *     with the global error status set, or if it should fail for any
1716 *     reason.
1717 *-
1718 */
1719 
1720 /* Local Variables: */
1721    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
1722    AstSelectorMap *new;
1723    AstFrameSet *fs;
1724    AstRegion *reg;
1725    int i;
1726    char buf[ 20 ];
1727 
1728 /* Initialise. */
1729    new = NULL;
1730 
1731 /* Check the global error status. */
1732    if ( !astOK ) return new;
1733 
1734 /* Get a pointer to the thread specific global data structure. */
1735    astGET_GLOBALS(channel);
1736 
1737 /* If a NULL virtual function table has been supplied, then this is
1738    the first loader to be invoked for this SelectorMap. In this case the
1739    SelectorMap belongs to this class, so supply appropriate values to be
1740    passed to the parent class loader (and its parent, etc.). */
1741    if ( !vtab ) {
1742       size = sizeof( AstSelectorMap );
1743       vtab = &class_vtab;
1744       name = "SelectorMap";
1745 
1746 /* If required, initialise the virtual function table for this class. */
1747       if ( !class_init ) {
1748          astInitSelectorMapVtab( vtab, name );
1749          class_init = 1;
1750       }
1751    }
1752 
1753 /* Invoke the parent class loader to load data for all the ancestral
1754    classes of the current one, returning a pointer to the resulting
1755    partly-built SelectorMap. */
1756    new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
1757                          channel );
1758    if ( astOK ) {
1759 
1760 /* Read input data. */
1761 /* ================ */
1762 /* Request the input Channel to read all the input data appropriate to
1763    this class into the internal "values list". */
1764       astReadClassData( channel, "SelectorMap" );
1765 
1766 /* Now read each individual data item from this list and use it to
1767    initialise the appropriate instance variable(s) for this class. */
1768 
1769 /* In the case of attributes, we first read the "raw" input value,
1770    supplying the "unset" value as the default. If a "set" value is
1771    obtained, we then use the appropriate (private) Set... member
1772    function to validate and set the value properly. */
1773 
1774 
1775 /* Loop to load each Region. */
1776 /* ------------------------- */
1777       new->reg = NULL;
1778       i = 0;
1779       fs = NULL;
1780       while( astOK ) {
1781          sprintf( buf, "reg%d", i + 1 );
1782          reg = astReadObject( channel, buf, NULL );
1783          if( reg ) {
1784             new->reg = astGrow( new->reg, i + 1, sizeof( AstRegion *) );
1785             if( astOK ) {
1786                new->reg[ i ] = reg;
1787 
1788 /* All but the first Region may have a dummy FrameSet rather than the
1789    correct FrameSet. The correct FrameSet will be a copy of the FrameSet
1790    from the first Region. */
1791                if( i == 0 ) {
1792                   fs = astGetRegFS( reg );
1793                } else if( astRegDummyFS( reg ) ){
1794                   astSetRegFS( reg, fs );
1795                }
1796 
1797                i++;
1798             }
1799          } else {
1800             break;
1801          }
1802       }
1803 
1804       fs = astAnnul( fs );
1805 
1806 /* Number of Regions. */
1807       new->nreg = i;
1808 
1809 
1810 /* BadVal. */
1811 /* ------- */
1812       new->badval = astReadDouble( channel, "badval", AST__BAD );
1813 
1814 /* If an error occurred, clean up by deleting the new SelectorMap. */
1815       if ( !astOK ) new = astDelete( new );
1816    }
1817 
1818 /* Return the new SelectorMap pointer. */
1819    return new;
1820 }
1821 
1822 /* Virtual function interfaces. */
1823 /* ============================ */
1824 /* These provide the external interface to the virtual functions defined by
1825    this class. Each simply checks the global error status and then locates and
1826    executes the appropriate member function, using the function pointer stored
1827    in the object's virtual function table (this pointer is located using the
1828    astMEMBER macro defined in "object.h").
1829 
1830    Note that the member function may not be the one defined here, as it may
1831    have been over-ridden by a derived class. However, it should still have the
1832    same interface. */
1833 
1834 /* None. */
1835 
1836 
1837 
1838 
1839