diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 19:01:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 19:01:49 (GMT) |
commit | beb90b7d3f526440250bba67e5ab07bb7eb7bbc3 (patch) | |
tree | 8d0d428ac62291f834ea8927bfa82c115ff1689d /ast/mapping.c | |
parent | a213dadabce2b2e02eca8376765fa425f01792f5 (diff) | |
download | blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.zip blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.tar.gz blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.tar.bz2 |
upgrade ast 8.7.1
Diffstat (limited to 'ast/mapping.c')
-rw-r--r-- | ast/mapping.c | 24759 |
1 files changed, 0 insertions, 24759 deletions
diff --git a/ast/mapping.c b/ast/mapping.c deleted file mode 100644 index 6bcf058..0000000 --- a/ast/mapping.c +++ /dev/null @@ -1,24759 +0,0 @@ -/* -*class++ -* Name: -* Mapping - -* Purpose: -* Inter-relate two coordinate systems. - -* Constructor Function: -* None. - -* Description: -* This class provides the basic facilities for transforming a set -* of coordinates (representing "input" points) to give a new set -* of coordinates (representing "output" points). It is used to -* describe the relationship which exists between two different -* coordinate systems and to implement operations which make use of -* this (such as transforming coordinates and resampling grids of -* data). However, the Mapping class does not have a constructor -* function of its own, as it is simply a container class for a -* family of specialised Mappings which implement particular types -* of coordinate transformation. - -* Inheritance: -* The Mapping class inherits from the Object class. - -* Attributes: -* In addition to those attributes common to all Objects, every -* Mapping also has the following attributes: -* -* - Invert: Mapping inversion flag -* - IsLinear: Is the Mapping linear? -* - IsSimple: Has the Mapping been simplified? -* - Nin: Number of input coordinates for a Mapping -* - Nout: Number of output coordinates for a Mapping -* - Report: Report transformed coordinates? -* - TranForward: Forward transformation defined? -* - TranInverse: Inverse transformation defined? - -* Functions: -c In addition to those functions applicable to all Objects, the -c following functions may also be applied to all Mappings: -f In addition to those routines applicable to all Objects, the -f following routines may also be applied to all Mappings: -* -c - astDecompose: Decompose a Mapping into two component Mappings -c - astTranGrid: Transform a grid of positions -c - astInvert: Invert a Mapping -c - astLinearApprox: Calculate a linear approximation to a Mapping -c - astMapBox: Find a bounding box for a Mapping -c - astMapSplit: Split a Mapping up into parallel component Mappings -c - astQuadApprox: Calculate a quadratic approximation to a 2D Mapping -c - astRate: Calculate the rate of change of a Mapping output -c - astRebin<X>: Rebin a region of a data grid -c - astRebinSeq<X>: Rebin a region of a sequence of data grids -c - astResample<X>: Resample a region of a data grid -c - astRemoveRegions: Remove any Regions from a Mapping -c - astSimplify: Simplify a Mapping -c - astTran1: Transform 1-dimensional coordinates -c - astTran2: Transform 2-dimensional coordinates -c - astTranN: Transform N-dimensional coordinates -c - astTranP: Transform N-dimensional coordinates held in separate arrays -f - AST_DECOMPOSE: Decompose a Mapping into two component Mappings -f - AST_TRANGRID: Transform a grid of positions -f - AST_INVERT: Invert a Mapping -f - AST_LINEARAPPROX: Calculate a linear approximation to a Mapping -f - AST_QUADAPPROX: Calculate a quadratic approximation to a 2D Mapping -f - AST_MAPBOX: Find a bounding box for a Mapping -f - AST_MAPSPLIT: Split a Mapping up into parallel component Mappings -f - AST_RATE: Calculate the rate of change of a Mapping output -f - AST_REBIN<X>: Rebin a region of a data grid -f - AST_REBINSEQ<X>: Rebin a region of a sequence of data grids -f - AST_REMOVEREGIONS: Remove any Regions from a Mapping -f - AST_RESAMPLE<X>: Resample a region of a data grid -f - AST_SIMPLIFY: Simplify a Mapping -f - AST_TRAN1: Transform 1-dimensional coordinates -f - AST_TRAN2: Transform 2-dimensional coordinates -f - AST_TRANN: Transform N-dimensional coordinates - -* Copyright: -* Copyright (C) 1997-2006 Council for the Central Laboratory of the -* Research Councils - -* Licence: -* This program is free software: you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation, either -* version 3 of the License, or (at your option) any later -* version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General -* License along with this program. If not, see -* <http://www.gnu.org/licenses/>. - -* Authors: -* RFWS: R.F. Warren-Smith (Starlink) -* MBT: Mark Taylor (Starlink) -* DSB: David S. Berry (Starlink) - -* History: -* 1-FEB-1996 (RFWS): -* Original version. -* 29-FEB-1996 (RFWS): -* Minor improvements to error messages. -* 15-JUL-1996 (RFWS): -* Support external interface. -* 13-DEC-1996 (RFWS): -* Added the astMapMerge method. -* 13-DEC-1996 (RFWS): -* Added the astSimplify method. -* 27-MAY-1997 (RFWS): -* Improved the astSimplify method to use astMapMerge to -* simplify a single Mapping where possible. -* 29-MAY-1998 (RFWS): -* Added the MapBox method. -* 13-NOV-1998 (RFWS): -* Made default MapBox convergence accuracy larger (i.e. less -* accurate). -* 10-DEC-1998 (RFWS): -* First useful implementation of astResample<X>. -* 16-AUG-1999 (RFWS): -* Fixed bug in SpecialBounds - wrong number of coordinates being used -* when checking for bad output coordinate values. -* 17-AUG-1999 (RFWS): -* Improved the convergence security of MapBox (return to older but -* less efficient setting). -* 24-NOV-2000 (MBT): -* Fixed bug (function being invoked as wrong type) in AST__UINTERP -* scheme, and added new AST__BLOCKAVE scheme, in astResample<X>. -* 9-JAN-2001 (DSB): -* Changed in and out arguments for TranN from type "double (*)[]" -* to "double *". -* 8-JAN-2003 (DSB): -* Changed private InitVtab method to protected astInitMappingVtab -* method. -* 10-JUL-2003 (DSB): -* Added method astRate. -* 2-SEP-2004 (DSB): -* Free resources before leaving astRate. -* 31-AUG-2004 (DSB): -* Make the LinearApprox function protected rather than private, -* rename it to astLinearApprox, and make the bounds parameters of -* type double rather than int. Also, correct the size of the fit -* coefficient array (was "(nin+1)*nout", now is "(nout+1)*nin"). -* Also correct the index of the first gradient coefficient from -* "fit+nout" to "fit+nin". These errors have probably never been -* noticed because they make no difference if nin=nout, which is -* usually the case. -* 6-SEP-2004 (DSB): -* Make astRate more robust by adding checks for unusal conditions. -* 20-SEP-2004 (DSB): -* Make the LinearApprox function public and change its interface -* to be more appropriate for public use. This involved swapping the -* direction of the fit (the original astLinearApprox fitted the -* inverse transformation, but the public version now fits the forwrd -* transformation). -* 4-OCT-2004 (DSB): -* Modify astMapList to return flag indicating presence of inverted -* CmpMaps in supplied Mapping. -* 9-NOV-2004 (DSB): -* Override astEqual method. -* 6-DEC-2004 (DSB): -* Remove the second derivative estimate from the astRate function -* since CmpMap has trouble calculating it. -* 17-DEC-2004 (DSB): -* Added astMapSplit -* 22-APR-2005 (DSB): -* Modified SpecialBounds to handle cases where some irrelevant -* output always produces bad values (e.g. a PermMap may do this). -* 30-JUN-2005 (DSB): -* Added astRebin. -* 7-JUL-2005 (DSB): -* Make MapSplit public rather than protected. -* 11-AUG-2005 (DSB): -* Added the AST__CONSERVEFLUX flag (used by astResampleX). -* 17-AUG-2005 (DSB): -* Added the AST__SOMBCOS kernel. -* 31-AUG-2005 (DSB): -* Added astRebinSeq. -* 9-SEP-2005 (DSB): -* Corrected axis indices returned by public interface for astMapSplit. -* 31-JAN-2006 (DSB): -* Added IsSimple attribute. -* 2-FEB-2006 (DSB): -* Corrections to prologue of astLinearApprox. -* 16-FEB-2006 (DSB): -* Some speed optimisations to rebinning code. -* 2-MAR-2006 (DSB): -* Use HAVE_LONG_DOUBLE in place of AST_LONG_DOUBLE -* 7-MAR-2006 (DSB): -* Added astTranGrid. -* 14-MAR-2006 (DSB): -* - The constructor no longer reports an error if the resulting -* Mapping cannot transform points in either direction. This is -* because it may be possible to simplify such a Mapping and the -* simplified Mapping may have defined transformations. E.g. if a -* Mapping which has only a forward transformation is combined in -* series with its own inverse, the combination CmpMap will simplify -* to a UnitMap (usually). -* - Reset the "issimple" flag when the Invert flag is changed. -* 9-MAY-2006 (DSB): -* Correct upper bounds for idim in RebinWithblocking. Also, remove -* the single precision "F" instantiation of the MAKE_REBINSEQ macro. -* Also correct the "nout = astGetNin" line in the MAKE_REBINSEQ -* macro to "nout = astGetNout". -* 12-MAY-2006 (DSB): -* Modify SpecialBounds to include points slightly inside the -* corners. This is because some Mappings may have singularies at -* the the edges. -* 17-MAY-2006 (DSB): -* Correct the "nout = astGetNin" line in the MAKE_RESAMPLE -* and MAKE_REBIN macros to "nout = astGetNout". -* 7-JUL-2006 (DSB): -* Change -CHAR_MAX value (used as a "not set" value for boolean -* attributes) to +CHAR_MAX, since some compilers do not allow -* chars to have negative values. -* 23-AUG-2006 (DSB): -* Change the Equal function so that it reports an error when -* called, rather than using astSimplify to determine if two Mappings -* are equal. All concrete Mapping classes should now provide -* their own implementation of astEqual, avoiding the use of -* astSimplify. This is so that astSimplify can use astEqual safely -* (i.e. without danger of entering an infinite loop). -* 24-NOV-2006 (DSB): -* Allow astRebinSeq to be called with a NULL pointer for the input -* data array. -* 14-MAR-2007 (DSB): -* Modify astRebinSeq to allow input variances to be used as weights. -* 19-MAR-2007 (DSB): -* Fix bug in LINEAR_2D macro that caused bad input pixel values to be -* treated as good. -* 16-APR-2007 (DSB): -* Account for reduction in number of degrees of freedom when -* calculating output variances on the basis of spread of input values in -* astReinSeq. -* 28-APR-2007 (DSB): -* Correct code within Rebin... and Resample... functions that provides -* optimal handling for 1- and 2- dimensional mappings. Previously, the -* check for whether or not to use these optimisations was based only on -* the dimensionality of either input (Rebin) or output (Resample). This -* could cause the optimised code to be used at inappropriate times, -* leading to an incorrect effective Mapping between input and output. The -* checks now check both input and output dimensionality in all cases. -* 3-MAY-2007 (DSB): -* An extra parameter ("nused") has been added to astRebinSeq, and -* all the rebinning stuff has been modified to keep "nused" up to date. -* This is needed to correct a fault in the generation of GENVAR -* variances. -* 12-DEC-2007 (DSB): -* Some rebinning kernels (e.g. SINCSINC) have negative values and -* can result in overall negative output weights. Therefore do not -* set output pixels with negative weights bad. -* 6-MAR-2008 (DSB): -* Add an option for astResample to leave unchanged any output pixels -* for which an interpolated value cannot be obtained. This is -* controlled by the new AST__NOBAD flag. -* 7-MAY-2008 (DSB): -* Clarified meaning of AST__GENVAR, AST__USEVAR and AST__VARWGT flags -* in astRebinSeq. -* 9-MAY-2008 (DSB): -* Prevent memory over-run in RebinSeq<X>. -* 5-MAY-2009 (DSB): -* Added astRemoveRegions. -* 11-NOV-2009 (DSB): -* In astRebinSeq initialise "*nused" to zero (as documented) if the -* AST__REBININIT flag is supplied. -* 17-NOV-2009 (DSB): -* Added AST_DISVAR flag for use with astRebinSeq. -* 15-DEC-2009 (DSB): -* Ensure that all axes span at least one pixel when calling -* astLinearApprox. -* 18-DEC-2009 (DSB): -* When using a 1D spreading kernel (in astRebin(Seq)), if the kernel -* is not contained completely within the output array, reflect the -* section of the kernel that falls outside the output array back into -* the output array so that no flux is lost. Also discovered that the -* n-D code (i.e. the KERNEL_ND macro) incorrectly uses the first -* user-supplied parameter as the full kernel width rather than the -* half-width. This has been fixed. -* 26-FEB-2010 (DSB): -* Add astQuadApprox. -* 27-FEB-2010 (DSB): -* - Make astQuadApprox faster, and fix a bug in the calculation of -* the matrix. -* 7-JUN-2010 (DSB): -* In the KERNEL_<x>D rebinning macros, correct the test for the -* central point being outside the bounds of the output image. -* 13-AUG-2010 (DSB): -* In astRebinSeq<X>, scale WLIM to take account of weighting by -* input variances. -* 13-DEC-2010 (DSB): -* Ensure that astMapSplit returns a Mapping that is independent of -* the supplied Mapping (i.e. return a deep copy). This means that -* subsequent changes to the supplied Mapping cannot affect the returned -* Mapping. -* 10-FEB-2011 (DSB): -* When rebinning (in macros NEAR_1/2/ND, KERNEL_1/2/ND, LINEAR_1/2/ND), -* do not treat a zero variance as bad unless the reciprocals of the -* variances are being used as weights. -* 16-JUN-2011 (DSB): -* Allow a check for NaNs to be performed as a debugging tool after -* every invocation of astTransform. This is controlled by the -* AST_REPLACE_NAN environment variable: if unset, no check is -* performed, if set to "1" NaNs are changed to AST__BAD but no -* error is reported, if set to anything else NaNs are changed to -* AST__BAD and an error is reported. -* 6-JUL-2012 (DSB): -* The astRebinSeq<X> family was normalising the returned data and -* variances values incorrectly, when the AST__REBINEND flag was -* supplied. The exact size of the error depended on the nature of -* the Mapping and the spreading method, and so is hard to predict. -* 20-JUL-2012 (DSB): -* Major re-structuring of astRebinSeq<X> to add further -* corrections to the normalisation. The model is now that each -* input array is first rebinned and then scaled to preserve the -* total data sum, and then each final output pixel is the weighed -* mean of all the aligned rebinned pixels. -* 13-AUG-2012 (DSB): -* Added AST__NONORM flag for asstRebuinSeq<X>. -* 30-AUG_2012 (DSB): -* Added AST__CONSERVEFLUX flag for astRebinSeq<X>. -* 10-SEP-2012 (DSB): -* Cater for Mappings that have different numbers of inputs and -* outputs when finding the flux conservation factor within -* astRebinSeq and astResample. -* 1-OCT-2012 (DSB): -* Ensure astRebinSeq<X> does not create any negative output -* variances. -* 2-OCT-2012 (DSB): -* - Check for Infs as well as NaNs. -* - In Rate, break out of the loop if the RMS is very small, not -* just if it is exactly zero. -* 5-OCT-2012 (DSB): -* Complete re-write of Rate. It's now much simpler, faster and -* more reliable. -* 16-OCT-2012 (DSB): -* In MatrixDet, ignore rows/columns filled with AST_BAD as well as -* rows/columns filled with zeros. -* 26-APR-2013 (DSB): -* Change the "nused" parameter of astRebinSeq<X> from "int *" to -* "size_t *" to allow greater amounts of data to be pasted into -* the output array. -* 29-APR-2013 (DSB): -* Do not simplify Mappings that have a set value for their Ident -* attribute. If an Ident value has been set then it means that we -* should be trying to preserve the identify of the Mapping. This -* is implemented via a new protected method (astDoNotSimplify) which -* is overridden by the Frame class so that this restriction applies -* only to genuine Mappings, not Frames. -* 9-MAY-2013 (DSB): -* Change the "nused" parameter of astRebinSeq<X> from "size_t *" to -* "int64_t *" to cater for systems where "size_t" is only 32 bits long. -* 20-MAY-2013 (DSB): -* Always perform a linear fit in RebinAdaptively if flux -* conservation is requested. -* 18-JUL-2013 (DSB): -* Correct logic for determining whether to divide or not in -* RebinAdaptively. The old logic could lead to infinite recursion. -* 1-SEP-2014 (DSB): -* Modify astLinearApprox to avoid using regularly placed -* test points, as such regular placement may result in -* non-representative behaviour. -* 25-SEP-2014 (DSB): -* Add support for B and UB data types to astRebin and astRebinSeq. -* 23-OCT-2014 (DSB): -* Report an error if arrays have too many pixels to count in a 32 -* bit int (astTranGrid, astResample, astRebin and astRebinSeq). -* 23-APR-2015 (DSB): -* Use one bit of this->flags to store the "IsSimple" attribute -* rather using a whole char (this->issimple). -* 16-JUN-2017 (DSB): -* If a simplification fails because the simplification process makes -* an inappropriate assumption about the supplied Mapping (e.g. that -* it has a defined inverse transformation) - thus causing an error to -* be reported, then clear the error status and return a clone of the -* unmodified supplied Mapping. Putting this check in the astSimplify_ -* wrapper function in the base Mapping class is much simpler and less -* error prone than performing tests on the appropriateness of the -* mapping in teh astMapMerge method of each and every mapping class. -* 9-JAN-2018 (DSB): -* Modify astLinearApprox so that a linear mapping in parallel with a -* mapping that generates bad values is considered linear. The returned -* coeffs for the bad outputs are set bad. -* 9-MAR-2018 (DSB): -* Added the AST__PARWGT flag in astRebinSeq. -* -*class-- -*/ - -/* Module Macros. */ -/* ============== */ -/* Set the name of the class we are implementing. This indicates to the header - files that define class interfaces that they should make "protected" - symbols available. */ -#define astCLASS Mapping - -/* Define numerical constants for use in thie module. */ -#define GETATTRIB_BUFF_LEN 50 -#define RATEFUN_MAX_CACHE 5 -#define RATE_ORDER 8 - -/* Include files. */ -/* ============== */ - -/* Configuration results */ -/* ---------------------- */ -#if HAVE_CONFIG_H -#include <config.h> -#endif - -/* Interface definitions. */ -/* ---------------------- */ - -#include "globals.h" /* Thread-safe global data access */ -#include "error.h" /* Error reporting facilities */ -#include "memory.h" /* Memory allocation facilities */ -#include "object.h" /* Base Object class */ -#include "pointset.h" /* Sets of points/coordinates */ -#include "channel.h" /* I/O channels */ -#include "mapping.h" /* Interface definition for this class */ -#include "cmpmap.h" /* Compund Mappings */ -#include "unitmap.h" /* Unit Mappings */ -#include "permmap.h" /* Axis permutations */ -#include "winmap.h" /* Window scalings */ -#include "pal.h" /* SLALIB interface */ -#include "globals.h" /* Thread-safe global data access */ - -/* Error code definitions. */ -/* ----------------------- */ -#include "ast_err.h" /* AST error codes */ - -/* C header files. */ -/* --------------- */ -#include <float.h> -#include <limits.h> -#include <math.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -/* Module type definitions. */ -/* ======================== */ -/* Enum to represent the data type when resampling a grid of data. */ -typedef enum DataType { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - TYPE_LD, -#endif - TYPE_D, - TYPE_F, - TYPE_L, - TYPE_UL, - TYPE_K, - TYPE_UK, - TYPE_I, - TYPE_UI, - TYPE_S, - TYPE_US, - TYPE_B, - TYPE_UB -} DataType; - -/* Data structure to hold information about a Mapping for use by - optimisation algorithms. */ -typedef struct MapData { - AstMapping *mapping; /* Pointer to the Mapping */ - AstPointSet *pset_in; /* Pointer to input PointSet */ - AstPointSet *pset_out; /* Pointer to output PointSet */ - double *lbnd; /* Pointer to lower constraints on input */ - double *ubnd; /* Pointer to upper constraints on input */ - double **ptr_in; /* Pointer to input PointSet coordinates */ - double **ptr_out; /* Pointer to output PointSet coordinates */ - int coord; /* Index of output coordinate to optimise */ - int forward; /* Use forward transformation? */ - int negate; /* Negate the output value? */ - int nin; /* Number of input coordinates per point */ - int nout; /* Number of output coordinates per point */ -} MapData; - -/* Convert from floating point to floating point or integer */ -#define CONV(IntType,val) ( ( IntType ) ? (int) ( (val) + (((val)>0)?0.5:-0.5) ) : (val) ) - -/* Module Variables. */ -/* ================= */ - -/* Address of this static variable is used as a unique identifier for - member of this class. */ -static int class_check; - -/* Pointers to parent class methods which are extended by this class. */ -static const char *(* parent_getattrib)( AstObject *, const char *, int * ); -static int (* parent_testattrib)( AstObject *, const char *, int * ); -static void (* parent_clearattrib)( AstObject *, const char *, int * ); -static void (* parent_setattrib)( AstObject *, const char *, int * ); -static int (* parent_equal)( AstObject *, AstObject *, int * ); - - -/* Define macros for accessing each item of thread specific global data. */ -#ifdef THREAD_SAFE - -/* Define how to initialise thread-specific globals. */ -#define GLOBAL_inits \ - globals->Class_Init = 0; \ - globals->GetAttrib_Buff[ 0 ] = 0; \ - globals->Unsimplified_Mapping = NULL; \ - globals->Rate_Disabled = 0; - - -/* Create the function that initialises global data for this module. */ -astMAKE_INITGLOBALS(Mapping) - -/* Define macros for accessing each item of thread specific global data. */ -#define class_init astGLOBAL(Mapping,Class_Init) -#define class_vtab astGLOBAL(Mapping,Class_Vtab) -#define getattrib_buff astGLOBAL(Mapping,GetAttrib_Buff) -#define unsimplified_mapping astGLOBAL(Mapping,Unsimplified_Mapping) -#define rate_disabled astGLOBAL(Mapping,Rate_Disabled) -#define ratefun_pset1_cache astGLOBAL(Mapping,RateFun_Pset1_Cache) -#define ratefun_pset2_cache astGLOBAL(Mapping,RateFun_Pset2_Cache) -#define ratefun_next_slot astGLOBAL(Mapping,RateFun_Next_Slot) -#define ratefun_pset_size astGLOBAL(Mapping,RateFun_Pset_Size) - - - -/* If thread safety is not needed, declare and initialise globals at static - variables. */ -#else - -/* Buffer returned by GetAttrib. */ -static char getattrib_buff[ GETATTRIB_BUFF_LEN + 1 ]; - -/* Pointer to origin (unsimplified) Mapping, only used for reporting - error messages. */ -static AstMapping *unsimplified_mapping = NULL; - -/* A flag which indicates if the astRate method should be disabled in - order to improve algorithm speed in cases where the rate value is not - significant. If astRate is disabled then it always returns a constant - value of 1.0. */ -static int rate_disabled = 0; - -/* static values used in function "RateFun". */ -static AstPointSet *ratefun_pset1_cache[ RATEFUN_MAX_CACHE ]; -static AstPointSet *ratefun_pset2_cache[ RATEFUN_MAX_CACHE ]; -static int ratefun_next_slot; -static int ratefun_pset_size[ RATEFUN_MAX_CACHE ]; - - -/* Define the class virtual function table and its initialisation flag - as static variables. */ -static AstMappingVtab class_vtab; /* Virtual function table */ -static int class_init = 0; /* Virtual function table initialised? */ - -#endif - -/* Prototypes for private member functions. */ -/* ======================================== */ - -#define DECLARE_GENERIC(X,Xtype) \ -static int InterpolateKernel1##X( AstMapping *, int, const int *, const int *, \ - const Xtype *, const Xtype *, int, \ - const int *, const double *const *, \ - void (*)( double, const double *, int, \ - double *, int * ), \ - void (*)( double, const double *, int, \ - double * ), \ - int, const double *, int, Xtype, \ - Xtype *, Xtype *, int * );\ -\ -static int InterpolateLinear##X( int, const int *, const int *, const Xtype *, \ - const Xtype *, int, const int *, \ - const double *const *, int, Xtype, Xtype *, \ - Xtype *, int * ); \ -\ -static int InterpolateNearest##X( int, const int *, const int *, const Xtype *, \ - const Xtype *, int, const int *, \ - const double *const *, int, Xtype, Xtype *, \ - Xtype *, int * ); \ -\ -static int Resample##X( AstMapping *, int, const int [], const int [], \ - const Xtype [], const Xtype [], int, \ - void (*)( void ), const double [], int, double, int, \ - Xtype, int, const int [], const int [], \ - const int [], const int [], Xtype [], Xtype [], int * ); \ -\ -static void ConserveFlux##X( double, int, const int *, Xtype, Xtype *, Xtype *, \ - int * ); \ -\ -static void InterpolateBlockAverage##X( int, const int[], const int[], \ - const Xtype [], const Xtype [], int, const int[], \ - const double *const[], const double[], int, \ - Xtype, Xtype *, Xtype *, int * ); - -DECLARE_GENERIC(B,signed char) -DECLARE_GENERIC(D,double) -DECLARE_GENERIC(F,float) -DECLARE_GENERIC(I,int) -DECLARE_GENERIC(K,INT_BIG) -DECLARE_GENERIC(L,long int) -DECLARE_GENERIC(S,short int) -DECLARE_GENERIC(UB,unsigned char) -DECLARE_GENERIC(UI,unsigned int) -DECLARE_GENERIC(UK,UINT_BIG) -DECLARE_GENERIC(UL,unsigned long int) -DECLARE_GENERIC(US,unsigned short int) - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -DECLARE_GENERIC(LD,long double) -#endif - -#undef DECLARE_GENERIC - -#define DECLARE_GENERIC(X,Xtype) \ -static void Rebin##X( AstMapping *, double, int, const int [], const int [], \ - const Xtype [], const Xtype [], int, const double [], int, \ - double, int, Xtype, int, const int [], const int [], \ - const int [], const int [], Xtype [], Xtype [], int * ); \ -\ -static void RebinSeq##X( AstMapping *, double, int, const int [], const int [], \ - const Xtype [], const Xtype [], int, const double [], \ - int, double, int, Xtype, int, const int [], \ - const int [], const int [], const int [], Xtype [], \ - Xtype [], double [], int64_t *, int * ); \ -\ -static void SpreadKernel1##X( AstMapping *, int, const int *, const int *, \ - const Xtype *, const Xtype *, double, int, const int *, \ - const double *const *, \ - void (*)( double, const double *, int, double *, int * ), \ - int, const double *, double, int, Xtype, int, Xtype *, \ - Xtype *, double *, int64_t *, int * ); \ -\ -static void SpreadLinear##X( int, const int *, const int *, const Xtype *, \ - const Xtype *, double, int, const int *, const double *const *, \ - double, int, Xtype, int, Xtype *, Xtype *, double *, int64_t *, \ - int * ); \ -\ -static void SpreadNearest##X( int, const int *, const int *, const Xtype *, \ - const Xtype *, double, int, const int *, const double *const *, \ - double, int, Xtype, int, Xtype *, Xtype *, double *, \ - int64_t *, int * ); - -DECLARE_GENERIC(D,double) -DECLARE_GENERIC(F,float) -DECLARE_GENERIC(I,int) -DECLARE_GENERIC(UB,unsigned char) -DECLARE_GENERIC(B,signed char) - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -DECLARE_GENERIC(LD,long double) -#endif - -#undef DECLARE_GENERIC - - - - - - -static AstMapping *RemoveRegions( AstMapping *, int * ); -static AstMapping *Simplify( AstMapping *, int * ); -static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * ); -static const char *GetAttrib( AstObject *, const char *, int * ); -static double FindGradient( AstMapping *, double *, int, int, double, double, double *, int * ); -static double J1Bessel( double, int * ); -static double LocalMaximum( const MapData *, double, double, double [], int * ); -static double MapFunction( const MapData *, const double [], int *, int * ); -static double MatrixDet( int, int, const double *, int * ); -static double MaxD( double, double, int * ); -static double NewVertex( const MapData *, int, double, double [], double [], int *, double [], int * ); -static double Random( long int *, int * ); -static double Rate( AstMapping *, double *, int, int, int * ); -static double UphillSimplex( const MapData *, double, int, const double [], double [], double *, int *, int * ); -static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * ); -static int Equal( AstObject *, AstObject *, int * ); -static int GetInvert( AstMapping *, int * ); -static int GetIsLinear( AstMapping *, int * ); -static int GetIsSimple( AstMapping *, int * ); -static int GetNin( AstMapping *, int * ); -static int GetNout( AstMapping *, int * ); -static int GetReport( AstMapping *, int * ); -static int GetTranForward( AstMapping *, int * ); -static int GetTranInverse( AstMapping *, int * ); -static int LinearApprox( AstMapping *, const double *, const double *, double, double *, int * ); -static int MapList( AstMapping *, int, int, int *, AstMapping ***, int **, int * ); -static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * ); -static int MaxI( int, int, int * ); -static int MinI( int, int, int * ); -static int DoNotSimplify( AstMapping *, int * ); -static int QuadApprox( AstMapping *, const double[2], const double[2], int, int, double *, double *, int * ); -static int RebinAdaptively( AstMapping *, int, const int *, const int *, const void *, const void *, DataType, int, const double *, int, double, int, const void *, int, const int *, const int *, const int *, const int *, int, void *, void *, double *, int64_t *, int * ); -static int RebinWithBlocking( AstMapping *, const double *, int, const int *, const int *, const void *, const void *, DataType, int, const double *, int, const void *, int, const int *, const int *, const int *, const int *, int, void *, void *, double *, int64_t *, int * ); -static int ResampleAdaptively( AstMapping *, int, const int *, const int *, const void *, const void *, DataType, int, void (*)( void ), const double *, int, double, int, const void *, int, const int *, const int *, const int *, const int *, void *, void *, int * ); -static int ResampleSection( AstMapping *, const double *, int, const int *, const int *, const void *, const void *, DataType, int, void (*)( void ), const double *, double, int, const void *, int, const int *, const int *, const int *, const int *, void *, void *, int * ); -static int ResampleWithBlocking( AstMapping *, const double *, int, const int *, const int *, const void *, const void *, DataType, int, void (*)( void ), const double *, int, const void *, int, const int *, const int *, const int *, const int *, void *, void *, int * ); -static int SpecialBounds( const MapData *, double *, double *, double [], double [], int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static int TestInvert( AstMapping *, int * ); -static int TestReport( AstMapping *, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void ClearInvert( AstMapping *, int * ); -static void ClearReport( AstMapping *, int * ); -static void Copy( const AstObject *, AstObject *, int * ); -static void Decompose( AstMapping *, AstMapping **, AstMapping **, int *, int *, int *, int * ); -static void Delete( AstObject *, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void Gauss( double, const double [], int, double *, int * ); -static void GlobalBounds( MapData *, double *, double *, double [], double [], int * ); -static void Invert( AstMapping *, int * ); -static void MapBox( AstMapping *, const double [], const double [], int, int, double *, double *, double [], double [], int * ); -static void RateFun( AstMapping *, double *, int, int, int, double *, double *, int * ); -static void RebinSection( AstMapping *, const double *, int, const int *, const int *, const void *, const void *, double, DataType, int, const double *, int, const void *, int, const int *, const int *, const int *, const int *, int, void *, void *, double *, int64_t *, int * ); -static void ReportPoints( AstMapping *, int, AstPointSet *, AstPointSet *, int * ); -static void SetAttrib( AstObject *, const char *, int * ); -static void SetInvert( AstMapping *, int, int * ); -static void SetReport( AstMapping *, int, int * ); -static void Sinc( double, const double [], int, double *, int * ); -static void SincCos( double, const double [], int, double *, int * ); -static void SincGauss( double, const double [], int, double *, int * ); -static void SincSinc( double, const double [], int, double *, int * ); -static void Somb( double, const double [], int, double *, int * ); -static void SombCos( double, const double [], int, double *, int * ); -static void Tran1( AstMapping *, int, const double [], int, double [], int * ); -static void Tran2( AstMapping *, int, const double [], const double [], int, double [], double [], int * ); -static void TranGrid( AstMapping *, int, const int[], const int[], double, int, int, int, int, double *, int * ); -static void TranGridAdaptively( AstMapping *, int, const int[], const int[], const int[], const int[], double, int, int, double *[], int * ); -static void TranGridSection( AstMapping *, const double *, int, const int *, const int *, const int *, const int *, int, double *[], int * ); -static void TranGridWithBlocking( AstMapping *, const double *, int, const int *, const int *, const int *, const int *, int, double *[], int * ); -static void TranN( AstMapping *, int, int, int, const double *, int, int, int, double *, int * ); -static void TranP( AstMapping *, int, int, const double *[], int, int, double *[], int * ); -static void ValidateMapping( AstMapping *, int, int, int, int, const char *, int * ); - - - -/* Member functions. */ -/* ================= */ -static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* ClearAttrib - -* Purpose: -* Clear an attribute value for a Mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void ClearAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* Mapping member function (over-rides the astClearAttrib protected -* method inherited from the Object class). - -* Description: -* This function clears the value of a specified attribute for a -* Mapping, so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the Mapping. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstMapping *this; /* Pointer to the Mapping structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the Mapping structure. */ - this = (AstMapping *) this_object; - -/* Check the attribute name and clear the appropriate attribute. */ - -/* Invert. */ -/* ------- */ - if ( !strcmp( attrib, "invert" ) ) { - astClearInvert( this ); - -/* Report. */ -/* ------- */ - } else if ( !strcmp( attrib, "report" ) ) { - astClearReport( this ); - -/* If the name was not recognised, test if it matches any of the - read-only attributes of this class. If it does, then report an - error. */ - } else if ( !strcmp( attrib, "nin" ) || - !strcmp( attrib, "nout" ) || - !strcmp( attrib, "issimple" ) || - !strcmp( attrib, "islinear" ) || - !strcmp( attrib, "tranforward" ) || - !strcmp( attrib, "traninverse" ) ) { - astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" " - "value for a %s.", status, attrib, astGetClass( this ) ); - astError( AST__NOWRT, "This is a read-only attribute." , status); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - (*parent_clearattrib)( this_object, attrib, status ); - } -} - -/* -* Name: -* ConserveFlux<X> - -* Purpose: -* Scale the output data and variance values produced by ResampleSection -* by the given flux conservation factor. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void ConserveFlux<X>( double factor, int npoint, const int *offset, -* <Xtype> badval, <Xtype> *out, -* <Xtype> *out_var ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which scale the supplied resampled data -* values by the given flux conservation factor. It also scales any -* variances by the square of the factor. - -* Parameters: -* factor -* The flux conservation factor. This should be the ratio of the -* output pixel size to the input pixel size, in the locality of -* the supplied data values. -* npoint -* The number of points at which the input grid was resampled. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each output point, this array should contain the zero-based -* offset in the output array(s) (i.e. the "out" and, -* optionally, the "out_var" arrays) at which the resampled -* output value(s) is stored. -* badval -* This parameter specifies the value which is used to identify -* bad data and/or variance values in the output array(s). -* out -* Pointer to an array in which the resampled data is supplied. Note -* that details of how the output grid maps on to this array -* (e.g. the storage order, number of dimensions, etc.) is -* arbitrary and is specified entirely by means of the "offset" -* array. The "out" array should therefore contain sufficient -* elements to accommodate the "offset" values supplied. There -* is no requirement that all elements of the "out" array should -* be assigned values, and any which are not addressed by the -* contents of the "offset" array will be left unchanged. -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, in which variance estimates for -* the resampled values are supplied. If no output variance estimates -* are available, a NULL pointer should be given. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -*/ -/* Define a macro to implement the function for a specific data - type. */ -#define MAKE_CONSERVEFLUX(X,Xtype) \ -static void ConserveFlux##X( double factor, int npoint, const int *offset, \ - Xtype badval, Xtype *out, Xtype *out_var, int *status ) { \ -\ -/* Local Variables: */ \ - int off_out; /* Pixel offset into output array */ \ - int point; /* Loop counter for output points */ \ -\ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ - for ( point = 0; point < npoint; point++ ) { \ - off_out = offset[ point ]; \ - if( out[ off_out ] != badval ) out[ off_out ] *= factor; \ - } \ -\ - if( out_var ) { \ - factor *= factor; \ - for ( point = 0; point < npoint; point++ ) { \ - off_out = offset[ point ]; \ - if( out_var[ off_out ] != badval ) out_var[ off_out ] *= factor; \ - } \ - } \ -} - - -/* Expand the macro above to generate a function for each required - data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_CONSERVEFLUX(LD,long double) -#endif -MAKE_CONSERVEFLUX(D,double) -MAKE_CONSERVEFLUX(F,float) -MAKE_CONSERVEFLUX(K,INT_BIG) -MAKE_CONSERVEFLUX(L,long int) -MAKE_CONSERVEFLUX(I,int) -MAKE_CONSERVEFLUX(S,short int) -MAKE_CONSERVEFLUX(B,signed char) -MAKE_CONSERVEFLUX(UL,unsigned long int) -MAKE_CONSERVEFLUX(UI,unsigned int) -MAKE_CONSERVEFLUX(UK,UINT_BIG) -MAKE_CONSERVEFLUX(US,unsigned short int) -MAKE_CONSERVEFLUX(UB,unsigned char) - -/* Undefine the macros used above. */ -#undef MAKE_CONSERVEFLUX - -static void Decompose( AstMapping *this, AstMapping **map1, AstMapping **map2, - int *series, int *invert1, int *invert2, int *status ) { -/* -*+ -* Name: -* astDecompose - -* Purpose: -* Decompose a Mapping into two component Mappings. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* void astDecompose( AstMapping *this, AstMapping **map1, -* AstMapping **map2, int *series, int *invert1, -* int *invert2 ) - -* Class Membership: -* Mapping method. - -* Description: -* This function returns pointers to two Mappings which, when applied -* either in series or parallel, are equivalent to the supplied Mapping. -* -* Since the Frame class inherits from the Mapping class, Frames can -* be considered as special types of Mappings and so this method can -* be used to decompose CmpMaps, CmpFrames, CmpRegions or Prisms. - -* Parameters: -* this -* Pointer to the Mapping. -* map1 -* Address of a location to receive a pointer to first component -* Mapping. -* map2 -* Address of a location to receive a pointer to second component -* Mapping. -* series -* Address of a location to receive a value indicating if the -* component Mappings are applied in series or parallel. A non-zero -* value means that the supplied Mapping is equivalent to applying map1 -* followed by map2 in series. A zero value means that the supplied -* Mapping is equivalent to applying map1 to the lower numbered axes -* and map2 to the higher numbered axes, in parallel. -* invert1 -* The value of the Invert attribute to be used with map1. -* invert2 -* The value of the Invert attribute to be used with map2. - -* Applicability: -* CmpMap -* If the supplied Mapping is a CmpMap, then map1 and map2 will be -* returned holding pointers to the component Mappings used to -* create the CmpMap, either in series or parallel. -* Mapping -* For any class of Mapping other than a CmpMap, map1 will be -* returned holding a clone of the supplied Mapping pointer, and map2 -* will be returned holding a NULL pointer. -* CmpFrame -* If the supplied Mapping is a CmpFrame, then map1 and map2 will be -* returned holding pointers to the component Frames used to -* create the CmpFrame. The component Frames are considered to be in -* applied in parallel. -* Frame -* For any class of Frame other than a CmpFrame, map1 will be -* returned holding a clone of the supplied Frame pointer, and map2 -* will be returned holding a NULL pointer. - -* Notes: -* - Any changes made to the component Mappings using the returned -* pointers will be reflected in the supplied Mapping. -* - The returned Invert values should be used in preference to the -* current values of the Invert attribute in map1 and map2. This is -* because the attributes may have changed value since the Mappings -* were combined. - -* Implementation Notes: -* - This function implements the basic astDecompose method -* available via the protected interface to the Frame class. The -* public interface to this method is provided by the -* astDecomposeId_ function. - -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* The basic Mapping class returns a clone of the supplied Mapping as - map1 and a NULL pointer as map2. */ - if( map1 ) *map1 = astClone( this ); - if( map2 ) *map2 = NULL; - if( series ) *series = 1; - if( invert1 ) *invert1 = astGetInvert( this ); - if( invert2 ) *invert2 = 0; -} - -static int DoNotSimplify( AstMapping *this, int *status ) { -/* -*+ -* Name: -* astMapMerge - -* Purpose: -* Check if a Mapping is appropriate for simplification. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astDoNotSImplify( AstMapping *this ); - -* Class Membership: -* Mapping method. - -* Description: -* This function returns a flag indivating if the supplied Mapping is -* appropriate for simplification. - -* Parameters: -* this -* Pointer to the Mapping. - -* Returned Value: -* Non-zero if the supplied Mapping is not appropriate for -* simplification, and zero otherwise. - -* Notes: -* - A value of 0 will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Check inherited status. */ - if( !astOK ) return 0; - -/* Mappings that have a set value for the Ident attribute should not be - simplified since we want to preserve their individual identify (otherwise - why would the user have given them an Ident value?). */ - return astTestIdent( this ); -} - -int astRateState_( int disabled, int *status ) { -/* -*+ -* Name: -* astRateState - -* Purpose: -* Control whether the astRate method is disabled or not. - -* Type: -* Protected function. - -* Synopsis: -* #include "mapping.h" -* int astRateState( int disabled ) - -* Class Membership: -* Mapping member function - -* Description: -* Some algorithms which use use the astRate method do not actually need -* to know what the Rate value is. For instance, when the Plot class draws -* a border it evaluates the GRAPHICS->Current Mapping hundreds of time. -* If the Mapping includes a RateMap then this can be very very slow -* (depending on how the astRate method is implemented). In fact the -* border drawing algorithm onlyneeds to know if the result is bad or -* not - the actual value produced by the Mappign does not matter. -* -* Such algorithms can be speeded up by forcing the astRate method to -* return a constant value rather than actually doing the numerical -* differentiation. This can be accomplised by calling this method prior -* to implementing the algorithm. It should be called at the end in -* order to re-instate the original disabled flag. - -* Parameters: -* disabled -* The new value for the astRate disabled flag. - -* Returned Value: -* The original value of the astRate disabled flag. - -*- -*/ - astDECLARE_GLOBALS - int result; - astGET_GLOBALS(NULL); - - result = rate_disabled; - rate_disabled = disabled; - return result; -} - -static int Equal( AstObject *this_object, AstObject *that_object, int *status ) { -/* -* Name: -* Equal - -* Purpose: -* Test if two Mappings are equivalent. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int Equal( AstObject *this, AstObject *that, int *status ) - -* Class Membership: -* Mapping member function (over-rides the astEqual protected -* method inherited from the Object class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* two Mappings are equivalent. -* -* The implementation provided by this class (the base Mapping class) -* simply reports an error when called, since all concrete Mapping -* subclasses should provide their own implementation. -* -* Note, sub-class implementations should not use astSimplify (e.g. -* combining the two Mapping and then simplifying it), since the -* astSimplify method for certain classes (e.g. CmpMap) may use -* astEqual. Consequently, if astEqual called astSimplify, there would -* be possibilities for infinite loops. - -* Parameters: -* this -* Pointer to the first Object (a Mapping). -* that -* Pointer to the second Object. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if the Frames are equivalent, zero otherwise. - -* Notes: -* - The two Mappings are considered equivalent if the combination of -* the first in series with the inverse of the second simplifies to a -* UnitMap. -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Invoke the Equal method inherited from the parent Object class. This checks - that the Objects are both of the same class (amongst other things). */ - if( (*parent_equal)( this_object, that_object, status ) ) { - -/* Report an error since the concrete sub-class should have over-riden - this method. */ - astError( AST__INTER, "astEqual(Mapping): The %s class does " - "not override the abstract astEqual method inherited " - "from the base Mapping class (internal AST programming " - "error).", status, astGetClass( this_object ) ); - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result, */ - return result; -} - -static double FindGradient( AstMapping *map, double *at, int ax1, int ax2, - double x0, double h, double *range, int *status ){ -/* -* Name: -* FindGradient - -* Purpose: -* Find the mean gradient in an interval, and the range of gradients -* within the interval. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double FindGradient( AstMapping *map, double *at, int ax1, int ax2, -* double x0, double h, double *range, int *status ) - -* Class Membership: -* Mapping method. - -* Description: -* This function finds the mean gradient in an interval, and the range -* of gradients within the interval. - -* Parameters: -* map -* Pointer to a Mapping which yields the value of the function at x. -* The Mapping may have any number of inputs and outputs; the specific -* output representing the function value, f, is specified by ax1 and -* the specific input representing the argument, x, is specified by ax2. -* at -* A pointer to an array holding axis values at the position at which -* the function is to be evaluated. The number of values supplied -* must equal the number of inputs to the Mapping. The value supplied -* for axis "ax2" is ignored (the value of "x" is used for axis "ax2"). -* ax1 -* The zero-based index of the Mapping output which is to be -* differentiated. Set this to -1 to allocate, or -2 to release, -* the static resources used by this function. -* ax2 -* The zero-based index of the Mapping input which is to be varied. -* x0 -* The central axis value at which the function is to be evaluated. -* h -* The interval over which the fitting is to be performed. -* range -* A pointer to a location at which to return the range of -* gradients found within the interval. -* status -* Pointer to the inherited status variable. - -* Returns: -* The mean gradient, or AST__BAD if the mean gradient cannot be -* calculated. -*/ - -/* Local Variables: */ - double dh; - double g; - double gmax; - double gmin; - double ret; - double x1; - double x2; - double x[ RATE_ORDER + 2 ]; - double y1; - double y2; - double y[ RATE_ORDER + 2 ]; - int i0; - int i; - int ngood; - -/* Initialise */ - ret = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Store the x values at (RATE_ORDER+1) evenly spaced points over the interval - "h" centred on "x0". */ - i0 = RATE_ORDER/2; - dh = h/RATE_ORDER; - - for( i = 0; i <= RATE_ORDER; i++ ) { - x[ i ] = x0 + ( i - i0 )*dh; - } - -/* Get the function values at these positions. */ - RateFun( map, at, ax1, ax2, RATE_ORDER + 1, x, y, status ); - -/* Find the maximum and minimum mean gradient within any sub-interval, and - note the (x,y) values at the first and last good point within the - interval. */ - y1 = AST__BAD; - y2 = AST__BAD; - gmax = AST__BAD; - gmin = AST__BAD; - ngood = 0; - - for( i = 0; i < RATE_ORDER; i++ ) { - if( y[ i + 1 ] !=AST__BAD && y[ i ] != AST__BAD && - x[ i + 1 ] != x[ i ] ) { - ngood++; - - g = ( y[ i + 1 ] - y[ i ] )/( x[ i + 1 ] - x[ i ] ); - - if( ngood == 1 ) { - gmax = gmin = g; - } else if( g < gmin ) { - gmin = g; - } else if( g > gmax) { - gmax = g; - } - if( y1 == AST__BAD ) { - y1 = y[ i ]; - x1 = x[ i ]; - } - y2 = y[ i + 1 ]; - x2 = x[ i + 1 ]; - } - } - -/* If two or more sub-intervals were usable, return the range of - gradients found, and the mean gradient. */ - if( ngood > 1 ) { - ret = ( y2 - y1 )/( x2 - x1 ); - if( range ) *range = ( gmax - gmin ); - } - - return ret; -} - -static void Gauss( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* Gauss - -* Purpose: -* 1-dimensional Gaussian spreading kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void Gauss( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* spreading kernel. The function used is exp(-k*x*x). - -* Parameters: -* offset -* The offset of a pixel from the central output point, measured -* in pixels. -* params -* The first element of this array should give a value for "k" -* in the exp(-k*x*x) term. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Calculate the result. */ - *value = exp( -params[ 0 ] * offset * offset ); -} - -static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* GetAttrib - -* Purpose: -* Get the value of a specified attribute for a Mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* Mapping member function (over-rides the protected astGetAttrib -* method inherited from the Object class). - -* Description: -* This function returns a pointer to the value of a specified -* attribute for a Mapping, formatted as a character string. - -* Parameters: -* this -* Pointer to the Mapping. -* attrib -* Pointer to a null terminated string containing the name of -* the attribute whose value is required. This name should be in -* lower case, with all white space removed. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a null terminated string containing the attribute -* value. - -* Notes: -* - The returned string pointer may point at memory allocated -* within the Mapping, or at static memory. The contents of the -* string may be over-written or the pointer may become invalid -* following a further invocation of the same function or any -* modification of the Mapping. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstMapping *this; /* Pointer to the Mapping structure */ - const char *result; /* Pointer value to return */ - int invert; /* Invert attribute value */ - int islinear; /* IsLinear attribute value */ - int issimple; /* IsSimple attribute value */ - int nin; /* Nin attribute value */ - int nout; /* Nout attribute value */ - int report; /* Report attribute value */ - int tran_forward; /* TranForward attribute value */ - int tran_inverse; /* TranInverse attribute value */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(this_object); - -/* Obtain a pointer to the Mapping structure. */ - this = (AstMapping *) this_object; - -/* Compare "attrib" with each recognised attribute name in turn, - obtaining the value of the required attribute. If necessary, write - the value into "getattrib_buff" as a null terminated string in an appropriate - format. Set "result" to point at the result string. */ - -/* Invert. */ -/* ------- */ - if ( !strcmp( attrib, "invert" ) ) { - invert = astGetInvert( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", invert ); - result = getattrib_buff; - } - -/* IsLinear. */ -/* --------- */ - } else if ( !strcmp( attrib, "islinear" ) ) { - islinear = astGetIsLinear( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", islinear ); - result = getattrib_buff; - } - -/* IsSimple. */ -/* --------- */ - } else if ( !strcmp( attrib, "issimple" ) ) { - issimple = astGetIsSimple( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", issimple ); - result = getattrib_buff; - } - -/* Nin. */ -/* ---- */ - } else if ( !strcmp( attrib, "nin" ) ) { - nin = astGetNin( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", nin ); - result = getattrib_buff; - } - -/* Nout. */ -/* ----- */ - } else if ( !strcmp( attrib, "nout" ) ) { - nout = astGetNout( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", nout ); - result = getattrib_buff; - } - -/* Report. */ -/* ------- */ - } else if ( !strcmp( attrib, "report" ) ) { - report = astGetReport( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", report ); - result = getattrib_buff; - } - -/* TranForward. */ -/* ------------ */ - } else if ( !strcmp( attrib, "tranforward" ) ) { - tran_forward = astGetTranForward( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", tran_forward ); - result = getattrib_buff; - } - -/* TranInverse. */ -/* ------------ */ - } else if ( !strcmp( attrib, "traninverse" ) ) { - tran_inverse = astGetTranInverse( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", tran_inverse ); - result = getattrib_buff; - } - -/* If the attribute name was not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_getattrib)( this_object, attrib, status ); - } - -/* Return the result. */ - return result; -} - -static int GetIsLinear( AstMapping *this, int *status ) { -/* -*+ -* Name: -* astGetIsLinear - -* Purpose: -* Determine if a Mapping is an instance of a linear Mapping class. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astGetIsLinear( AstMapping *this ) - -* Class Membership: -* Mapping method. - -* Description: -* This function returns a value indicating whether a Mapping is -* a member of a class of linear Mappings. The base Mapping class -* returns a value of zero. Linear Mapping classes should over-ride -* this function to return a non-zero value. - -* Parameters: -* this -* Pointer to the Mapping. - -* Returned Value: -* One if the Mapping is a member of a linear Mapping class. Zero -* otherwise. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - return 0; -} - -static int GetNin( AstMapping *this, int *status ) { -/* -*+ -* Name: -* astGetNin - -* Purpose: -* Get the number of input coordinates for a Mapping. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astGetNin( AstMapping *this ) - -* Class Membership: -* Mapping method. - -* Description: -* This function returns the number of input coordinate values -* required per point by a Mapping (i.e. the number of dimensions -* of the space in which input points reside). - -* Parameters: -* this -* Pointer to the Mapping. - -* Returned Value: -* Number of coordinate values required. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - int invert; /* Invert attribute value */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Determine if the Mapping has been inverted. */ - invert = astGetInvert( this ); - -/* Obtain the Nin value. */ - if ( astOK ) result = invert ? this->nout : this->nin; - -/* Return the result. */ - return result; -} - -static int GetNout( AstMapping *this, int *status ) { -/* -*+ -* Name: -* astGetNout - -* Purpose: -* Get the number of output coordinates for a Mapping. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astGetNout( AstMapping *this ) - -* Class Membership: -* Mapping method. - -* Description: -* This function returns the number of output coordinate values -* generated per point by a Mapping (i.e. the number of dimensions -* of the space in which output points reside). - -* Parameters: -* this -* Pointer to the Mapping. - -* Returned Value: -* Number of coordinate values generated. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - int invert; /* Invert attribute value */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Determine if the Mapping has been inverted. */ - invert = astGetInvert( this ); - -/* Obtain the Nout value. */ - if ( astOK ) result = invert ? this->nin : this->nout; - -/* Return the result. */ - return result; -} - -static int GetTranForward( AstMapping *this, int *status ) { -/* -*+ -* Name: -* astGetTranForward - -* Purpose: -* Determine if a Mapping defines a forward coordinate transformation. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astGetTranForward( AstMapping *this ) - -* Class Membership: -* Mapping method. - -* Description: -* This function returns a value indicating whether a Mapping is -* able to perform a coordinate transformation in the "forward" -* direction. - -* Parameters: -* this -* Pointer to the Mapping. - -* Returned Value: -* Zero if the forward coordinate transformation is not defined, or -* 1 if it is. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - int invert; /* Mapping inverted? */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Determine if the Mapping has been inverted. */ - invert = astGetInvert( this ); - -/* If OK, obtain the result. */ - if ( astOK ) result = invert ? this->tran_inverse : this->tran_forward; - -/* Return the result. */ - return result; -} - -static int GetTranInverse( AstMapping *this, int *status ) { -/* -*+ -* Name: -* astGetTranInverse - -* Purpose: -* Determine if a Mapping defines an inverse coordinate transformation. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astGetTranInverse( AstMapping *this ) - -* Class Membership: -* Mapping method. - -* Description: -* This function returns a value indicating whether a Mapping is -* able to perform a coordinate transformation in the "inverse" -* direction. - -* Parameters: -* this -* Pointer to the Mapping. - -* Returned Value: -* Zero if the inverse coordinate transformation is not defined, or -* 1 if it is. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - int invert; /* Mapping inverted? */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Determine if the Mapping has been inverted. */ - invert = astGetInvert( this ); - -/* If OK, obtain the result. */ - if ( astOK ) result = invert ? this->tran_forward : this->tran_inverse; - -/* Return the result. */ - return result; -} - -static void GlobalBounds( MapData *mapdata, double *lbnd, double *ubnd, - double xl[], double xu[], int *status ) { -/* -* Name: -* GlobalBounds - -* Purpose: -* Estimate global coordinate bounds for a Mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void GlobalBounds( MapData *mapdata, double *lbnd, double *ubnd, -* double xl[], double xu[], int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function estimates the global lower and upper bounds of a -* Mapping function within a constrained region of its input -* coordinate space. It uses a robust global optimisation algorithm -* based on the selection of pseudo-random starting positions, -* followed by the location of local minima and maxima using the -* downhill (or uphill) simplex method. The algorithm will cope -* with the case where there are several competing minima (or -* maxima) with nearly equal values. It attempts to locate the -* global bounds to full machine precision when possible. - -* Parameters: -* mapdata -* Pointer to a MapData structure describing the Mapping -* function, its coordinate constraints, etc. -* lbnd -* Pointer to a double. On entry, this should contain a -* previously-obtained upper limit on the global lower bound, or -* AST__BAD if no such limit is available. On exit, it will be -* updated with a new estimate of the global lower bound, if a -* better one has been found. -* ubnd -* Pointer to a double. On entry, this should contain a -* previously-obtained lower limit on the global upper bound, or -* AST__BAD if no such limit is available. On exit, it will be -* updated with a new estimate of the global upper bound, if a -* better one has been found. -* xl -* Pointer to an array of double, with one element for each -* input coordinate. On entry, if *lbnd is not equal to AST__OK, -* this should contain the input coordinates of a point at which -* the Mapping function takes the value *lbnd. On exit, this -* function returns the position of a (not necessarily unique) -* input point at which the Mapping function takes the value of -* the new global lower bound. This array is not altered if an -* improved estimate of the global lower bound cannot be found. -* xu -* Pointer to an array of double, with one element for each -* input coordinate. On entry, if *ubnd is not equal to AST__OK, -* this should contain the input coordinates of a point at which -* the Mapping function takes the value *ubnd. On exit, this -* function returns the position of a (not necessarily unique) -* input point at which the Mapping function takes the value of -* the new global upper bound. This array is not altered if an -* improved estimate of the global upper bound cannot be found. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The efficiency of this function will usually be improved if -* previously-obtained estimates of the extrema and their locations -* are provided. -* - The values returned via "lbnd", "ubnd", "xl" and "xu" will be -* set to the value AST__BAD if this function should fail for any -* reason. Their initial values on entry will not be altered if the -* function is invoked with the global error status set. -*/ - -/* Local Constants: */ - const double default_acc = 3.0e-5; /* Default convergence accuracy */ - const int maxiter = 10000; /* Maximum number of iterations */ - const int minsame = 5; /* Minimum no. consistent extrema required */ - const int nbatch = 32; /* No. function samples obtained per batch */ - -/* Local Variables: */ - AstPointSet *pset_in; /* Input PointSet for batch transformation */ - AstPointSet *pset_out; /* Output PointSet for batch transformation */ - double **ptr_in; /* Pointer to batch input coordinates */ - double **ptr_out; /* Pointer to batch output coordinates */ - double *active_hi; /* Estimated upper limits of active region */ - double *active_lo; /* Estimated lower limits of active region */ - double *sample_hi; /* Upper limits of sampled region */ - double *sample_lo; /* Lower limits of sampled region */ - double *sample_width; /* Nominal widths of sampled region */ - double *x; /* Pointer to array of coordinates */ - double acc; /* Convergence accuracy for finding maximum */ - double active_width; /* Estimated width of active region */ - double new_max; /* Value of new local maximum */ - double new_min; /* Value of new local minimum */ - double oversize; /* Over-size factor for sampled region */ - double random; /* Pseudo-random number */ - int bad; /* Transformed position is bad? */ - int batch; /* Next element to use in position batch */ - int coord; /* Loop counter for coordinates */ - int done_max; /* Satisfactory global maximum found? */ - int done_min; /* Satisfactory global minimum found? */ - int iter; /* Loop counter for iterations */ - int ncoord; /* Number of coordinates in search space */ - int nmax; /* Number of local maxima found */ - int nmin; /* Number of local minima found */ - int nsame_max; /* Number of equivalent local maxima found */ - int nsame_min; /* Number of equivalent local minima found */ - long int seed = 1776655449; /* Arbitrary pseudo-random number seed */ - -/* Check the global error status */ - if ( !astOK ) return; - -/* Initialise. */ - done_max = 0; - done_min = 0; - nmax = 0; - nmin = 0; - nsame_max = 0; - nsame_min = 0; - pset_in = NULL; - pset_out = NULL; - ptr_in = NULL; - ptr_out = NULL; - oversize = 0; - bad = 0; - -/* Extract the number of input coordinates for the Mapping function - and allocate workspace. */ - ncoord = mapdata->nin; - active_hi = astMalloc( sizeof( double ) * (size_t) ncoord ); - active_lo = astMalloc( sizeof( double ) * (size_t) ncoord ); - sample_hi = astMalloc( sizeof( double ) * (size_t) ncoord ); - sample_lo = astMalloc( sizeof( double ) * (size_t) ncoord ); - sample_width = astMalloc( sizeof( double ) * (size_t) ncoord ); - x = astMalloc( sizeof( double ) * (size_t) ncoord ); - if ( astOK ) { - -/* Calculate the factor by which the size of the region we sample will - exceed the size of the Mapping function's active region (the region - where the transformed coordinates are non-bad) in each - dimension. This is chosen so that the volume ratio will be 2. */ - oversize = pow( 2.0, 1.0 / (double) ncoord ); - -/* Initialise the limits of the active region to unknown. */ - for ( coord = 0; coord < ncoord; coord++ ) { - active_lo[ coord ] = DBL_MAX;; - active_hi[ coord ] = -DBL_MAX; - -/* Initialise the nominal widths of the sampled region to be the - actual widths of the search region times the over-size factor. */ - sample_width[ coord ] = ( mapdata->ubnd[ coord ] - - mapdata->lbnd[ coord ] ) * oversize; - -/* Initialise the sampled region to match the search region. */ - sample_lo[ coord ] = mapdata->lbnd[ coord ]; - sample_hi[ coord ] = mapdata->ubnd[ coord ]; - } - -/* Set up position buffer. */ -/* ======================= */ -/* Create two PointSets to act as buffers to hold a complete batch of - input and output coordinates. Obtain pointers to their coordinate - arrays. */ - pset_in = astPointSet( nbatch, ncoord, "", status ); - pset_out = astPointSet( nbatch, mapdata->nout, "", status ); - ptr_in = astGetPoints( pset_in ); - ptr_out = astGetPoints( pset_out ); - -/* Initialise the next element to be used in the position buffer to - indicate that the buffer is initially empty. */ - batch = nbatch; - } - -/* Define a macro to fill the position buffer with a set of - pseudo-random positions and to transform them. */ -#define FILL_POSITION_BUFFER {\ -\ -/* We first generate a suitable volume over which to distribute the\ - batch of pseudo-random positions. Initially, this will be the\ - entire search volume, but if we find that the only non-bad\ - transformed coordinates we obtain are restricted to a small\ - sub-region of this input volume, then we reduce the sampled volume\ - so as to concentrate more on the active region. */\ -\ -/* Loop through each input coordinate, checking that at least one\ - non-bad transformed point has been obtained. If not, we do not\ - adjust the sampled volume, as we do not yet know where the active\ - region lies. */\ - for ( coord = 0; coord < ncoord; coord++ ) {\ - if ( active_hi[ coord ] >= active_lo[ coord ] ) {\ -\ -/* Estimate the width of the active region from the range of input\ - coordinates that have so far produced non-bad transformed\ - coordinates. */\ - active_width = active_hi[ coord ] - active_lo[ coord ];\ -\ -/* If the current width of the sampled volume exceeds this estimate by\ - more than the required factor, then reduce the width of the sampled\ - volume. The rate of reduction is set so that the volume of the\ - sampled region can halve with every fourth batch of positions. */\ - if ( ( active_width * oversize ) < sample_width[ coord ] ) {\ - sample_width[ coord ] /= pow( oversize, 0.25 );\ -\ -/* If the width of the sampled volume does not exceed that of the\ - known active region by the required factor, then adjust it so that\ - it does. Note that we must continue to sample some points outside\ - the known active region in case we have missed any (in which case\ - the sampled region will expand again to include them). */\ - } else if ( ( active_width * oversize ) > sample_width[ coord ] ) {\ - sample_width[ coord ] = active_width * oversize;\ - }\ -\ -/* Calculate the lower and upper bounds on the sampled volume, using\ - the new width calculated above and centring it on the active\ - region, as currently known. */\ - sample_lo[ coord ] = ( active_lo[ coord ] + active_hi[ coord ] -\ - sample_width[ coord ] ) * 0.5;\ - sample_hi[ coord ] = ( active_lo[ coord ] + active_hi[ coord ] +\ - sample_width[ coord ] ) * 0.5;\ -\ -/* Ensure that the sampled region does not extend beyond the original\ - search region. */\ - if ( sample_lo[ coord ] < mapdata->lbnd[ coord ] ) {\ - sample_lo[ coord ] = mapdata->lbnd[ coord ];\ - }\ - if ( sample_hi[ coord ] > mapdata->ubnd[ coord ] ) {\ - sample_hi[ coord ] = mapdata->ubnd[ coord ];\ - }\ - }\ - }\ -\ -/* Having determined the size of the sampled volume, create a batch of\ - pseudo-random positions uniformly distributed within it. */\ - for ( batch = 0; batch < nbatch; batch++ ) {\ - for ( coord = 0; coord < ncoord; coord++ ) {\ - random = Random( &seed, status );\ - ptr_in[ coord ][ batch ] = sample_lo[ coord ] * random +\ - sample_hi[ coord ] * ( 1.0 - random );\ - }\ - }\ -\ -/* Transform these positions. We process them in a single batch in\ - order to minimise the overheads in doing this. */\ - (void) astTransform( mapdata->mapping, pset_in, mapdata->forward,\ - pset_out );\ -\ -/* Indicate that the position buffer is now full. */\ - batch = 0;\ -} - -/* Fill the position buffer using the above macro. (Note that because - we do not yet have an estimate of the size of the active region, - this does not change the sampled region size from our earlier - initialised values. */ - FILL_POSITION_BUFFER; - -/* Iterate. */ -/* ======== */ -/* Loop to perform up to "maxiter" iterations to estimate the global - minimum and maximum. */ - for ( iter = 0; astOK && ( iter < maxiter ); iter++ ) { - -/* Determine the search accuracy. */ -/* ============================== */ -/* Decide the accuracy to which local extrema should be found. The - intention here is to optimise performance, especially where one - extremum lies near zero and so could potentially be found to - unnecessarily high precision. If we make a mis-assumption (the code - below is not fool-proof), we will slow things down for this - iteration, but the error will be corrected in future iterations - once better estimates are available. */ - -/* If we have no current estimate of either global extremum, we assume - the values we eventually obtain will be of order unity and required - to the default accuracy. */ - acc = default_acc; - -/* If we already have an estimate of both global extrema, we set the - accuracy level so that the difference between them will be known to - the default accuracy. */ - if ( ( *lbnd != AST__BAD ) && ( *ubnd != AST__BAD ) ) { - acc = fabs( *ubnd - *lbnd ) * default_acc; - -/* If we have an estimate of only one global extremum, we assume that - the difference between the two global extrema will eventually be of - the same order as the estimate we currently have, so long as this - is not less than unity. */ - } else if ( *lbnd != AST__BAD ) { - if ( fabs( *lbnd ) > 1.0 ) acc = fabs( *lbnd) * default_acc; - } else if ( *ubnd != AST__BAD ) { - if ( fabs( *ubnd ) > 1.0 ) acc = fabs( *ubnd) * default_acc; - } - -/* Search for a new local minimum. */ -/* =============================== */ -/* If we are still searching for the global minimum, then obtain a set - of starting coordinates from which to find a new local minimum. */ - if ( !done_min ) { - -/* On the first iteration, start searching at the position where the - best estimate of the global minimum (if any) has previously been - found. We know that this produces non-bad transformed - coordinates. */ - bad = 0; - if ( !iter && ( *lbnd != AST__BAD ) ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ coord ] = xl[ coord ]; - } - -/* Otherwise, if no estimate of the global minimum is available, then - start searching at the position where the best estimate of the - global maximum (if any) has been found. This may be a long way from - a local minimum, but at least it will yield a non-bad value for the - Mapping function, so some sort of estimate of the global minimum - will be obtained. This is important in cases where finding the - active region of the function is the main problem. Note that this - condition can only occur once, since the global minimum will have - an estimate on the next iteration. */ - } else if ( ( *lbnd == AST__BAD ) && ( *ubnd != AST__BAD ) ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ coord ] = xu[ coord ]; - } - -/* Having exhausted the above possibilities, we use pseudo-random - starting positions which are uniformly distributed throughout the - search volume. First check to see if the buffer containing such - positions is empty and refill it if necessary. */ - } else { - if ( batch >= nbatch ) FILL_POSITION_BUFFER; - -/* Test the next available set of output (transformed) coordinates in - the position buffer to see if they are bad. */ - if ( astOK ) { - for ( coord = 0; coord < mapdata->nout; coord++ ) { - bad = ( ptr_out[ coord ][ batch ] == AST__BAD ); - if ( bad ) break; - } - -/* If not, we have a good starting position for finding a local - minimum, so extract the corresponding input coordinates. */ - if ( !bad ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ coord ] = ptr_in[ coord ][ batch ]; - } - } - -/* Increment the position buffer location. */ - batch++; - } - } - -/* If we do not have a good starting position, we can't do anything - more on this iteration. A new position will be obtained and tested - on the next iteration and this (we hope) will eventually identify a - suitable starting point. */ - if ( astOK && !bad ) { - -/* Form estimates of the lower and upper limits of the active region - from the starting positions used. */ - for ( coord = 0; coord < ncoord; coord++ ) { - if ( x[ coord ] < active_lo[ coord ] ) { - active_lo[ coord ] = x[ coord ]; - } - if ( x[ coord ] > active_hi[ coord ] ) { - active_hi[ coord ] = x[ coord ]; - } - } - -/* Indicate that the Mapping function should be negated (because we - want a local minimum) and then search for a local maximum in this - negated function. If the result is non-bad (as it should always be, - barring an error), then negate it to obtain the value of the local - minimum found. */ - mapdata->negate = 1; - new_min = LocalMaximum( mapdata, acc, 0.01, x, status ); - if ( new_min != AST__BAD ) { - new_min = -new_min; - -/* Update the estimates of the lower and upper bounds of the active - region to take account of where the minimum was found. */ - for ( coord = 0; coord < ncoord; coord++ ) { - if ( x[ coord ] < active_lo[ coord ] ) { - active_lo[ coord ] = x[ coord ]; - } - if ( x[ coord ] > active_hi[ coord ] ) { - active_hi[ coord ] = x[ coord ]; - } - } - -/* Count the number of times we successfully locate a local minimum - (ignoring the fact they might all be the same one). */ - nmin++; - -/* Update the global minimum. */ -/* ========================== */ -/* If this is the first estimate of the global minimum, then set to - one the count of the number of consecutive iterations where this - estimate remains unchanged. Store the minimum value and its - position. */ - if ( *lbnd == AST__BAD ) { - nsame_min = 1; - *lbnd = new_min; - for ( coord = 0; coord < ncoord; coord++ ) { - xl[ coord ] = x[ coord ]; - } - -/* Otherwise, test if this local minimum is lower than the previous - estimate of the global minimum. If so, then reset the count of - unchanged estimates of the global mimimum to one if the difference - exceeds the accuracy with which the minimum was found (i.e. if we - have found a significantly different minimum). Otherwise, just - increment this count (because we have found the same minimum but by - chance with slightly improved accuracy). Store the new minimum and - its position. */ - } else if ( new_min < *lbnd ) { - nsame_min = ( ( *lbnd - new_min ) > acc ) ? 1 : - nsame_min + 1; - *lbnd = new_min; - for ( coord = 0; coord < ncoord; coord++ ) { - xl[ coord ] = x[ coord ]; - } - -/* If the latest local minimum is no improvement on previous estimates - of the global minimum, then increment the count of unchanged - estimates of the global mimimum, but do not save the new one. */ - } else { - nsame_min++; - } - -/* Determine if a satisfactory estimate of the global minimum has been - obtained. It has if the number of consecutive local minima which - have not significantly improved the estimate is at least equal to - "minsame", and at least 30% of the total number of local minima - found. */ - if ( ( nsame_min >= minsame ) && - ( nsame_min >= (int) ( 0.3f * (float) nmin + 0.5f ) ) ) { - done_min = 1; - } - } - } - } - -/* Search for a new local maximum. */ -/* =============================== */ -/* Now repeat all of the above to find a new local maximum which - estimates the global maximum. */ - if ( !done_max ) { - -/* Choose a suitable starting position, based on one already available - if appropriate. */ - if ( !iter && ( *ubnd != AST__BAD ) ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ coord ] = xu[ coord ]; - } - - } else if ( ( *ubnd == AST__BAD ) && ( *lbnd != AST__BAD ) ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ coord ] = xl[ coord ]; - } - -/* Otherwise use a pseudo-random position, refilling the position - buffer if necessary. Check if the transformed coordinates are - bad. */ - } else { - if ( batch >= nbatch ) FILL_POSITION_BUFFER; - if ( astOK ) { - for ( coord = 0; coord < mapdata->nout; coord++ ) { - bad = ( ptr_out[ coord ][ batch ] == AST__BAD ); - if ( bad ) break; - } - if ( !bad ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ coord ] = ptr_in[ coord ][ batch ]; - } - } - batch++; - } - } - -/* If the coordinates are OK, update the active region limits. */ - if ( astOK && !bad ) { - for ( coord = 0; coord < ncoord; coord++ ) { - if ( x[ coord ] < active_lo[ coord ] ) { - active_lo[ coord ] = x[ coord ]; - } - if ( x[ coord ] > active_hi[ coord ] ) { - active_hi[ coord ] = x[ coord ]; - } - } - -/* Find a local maximum in the Mapping function. */ - mapdata->negate = 0; - new_max = LocalMaximum( mapdata, acc, 0.01, x, status ); - if ( new_max != AST__BAD ) { - -/* Use the result to further update the active region limits. */ - for ( coord = 0; coord < ncoord; coord++ ) { - if ( x[ coord ] < active_lo[ coord ] ) { - active_lo[ coord ] = x[ coord ]; - } - if ( x[ coord ] > active_hi[ coord ] ) { - active_hi[ coord ] = x[ coord ]; - } - } - -/* Count the number of local maxima found. */ - nmax++; - -/* Update the estimate of the global maximum. */ - if ( *ubnd == AST__BAD ) { - nsame_max = 1; - *ubnd = new_max; - for ( coord = 0; coord < ncoord; coord++ ) { - xu[ coord ] = x[ coord ]; - } - - } else if ( new_max > *ubnd ) { - nsame_max = ( ( new_max - *ubnd ) > acc ) ? 1 : - nsame_max + 1; - *ubnd = new_max; - for ( coord = 0; coord < ncoord; coord++ ) { - xu[ coord ] = x[ coord ]; - } - - } else { - nsame_max++; - } - -/* Test for a satisfactory global maximum estimate. */ - if ( ( nsame_max >= minsame ) && - ( nsame_max >= (int) ( 0.3f * (float) nmax + 0.5 ) ) ) { - done_max = 1; - } - } - } - } - -/* Quit iterating once both the global minimum and the global maximum - have been found. */ - if ( done_min && done_max ) break; - } - -/* Free workspace. */ - active_hi = astFree( active_hi ); - active_lo = astFree( active_lo ); - sample_hi = astFree( sample_hi ); - sample_lo = astFree( sample_lo ); - sample_width = astFree( sample_width ); - x = astFree( x ); - -/* Annul temporary PointSets. */ - pset_in = astAnnul( pset_in ); - pset_out = astAnnul( pset_out ); - -/* If the global minimum has been found, attempt to polish the result - to machine precision by requesting that it be found with an - accuracy tolerance of zero (subject to the maximum number of - iterations that LocalMaximum will perform,). */ - if ( astOK ) { - if ( *lbnd != AST__BAD ) { - mapdata->negate = 1; - *lbnd = LocalMaximum( mapdata, 0.0, sqrt( DBL_EPSILON ), xl, status ); - if ( *lbnd != AST__BAD ) *lbnd = - *lbnd; - } - -/* Similarly polish the estimate of the global maximum. */ - if ( *ubnd != AST__BAD ) { - mapdata->negate = 0; - *ubnd = LocalMaximum( mapdata, 0.0, sqrt( DBL_EPSILON ), xu, status ); - } - -/* If either extremum could not be found, then report an error. */ - if ( ( *lbnd == AST__BAD ) || ( *ubnd == AST__BAD ) ) { - astError( AST__MBBNF, "astMapBox(%s): No valid output coordinates " - "(after %d test points).", status, astGetClass( mapdata->mapping ), - 2 * maxiter ); - } - -/* If an error occurred, then return bad extremum values and - coordinates. */ - if ( !astOK ) { - *lbnd = AST__BAD; - *ubnd = AST__BAD; - for ( coord = 0; coord < ncoord; coord++ ) { - xl[ coord ] = AST__BAD; - xu[ coord ] = AST__BAD; - } - } - } - -/* Undefine macros local to this function. */ -#undef FILL_POSITION_BUFFER -} - -void astInitMappingVtab_( AstMappingVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitMappingVtab - -* Purpose: -* Initialise a virtual function table for a Mapping. - -* Type: -* Protected function. - -* Synopsis: -* #include "mapping.h" -* void astInitMappingVtab( AstMappingVtab *vtab, const char *name ) - -* Class Membership: -* Mapping vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the Mapping class. - -* Parameters: -* vtab -* Pointer to the virtual function table. The components used by -* all ancestral classes will be initialised if they have not already -* been initialised. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the virtual function table belongs (it -* is this pointer value that will subsequently be returned by the Object -* astClass function). -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstObjectVtab *object; /* Pointer to Object component of Vtab */ - -/* Check the local error status. */ - if ( !astOK ) return; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Initialize the component of the virtual function table used by the - parent class. */ - astInitObjectVtab( (AstObjectVtab *) vtab, name ); - -/* Store a unique "magic" value in the virtual function table. This - will be used (by astIsAMapping) to determine if an object belongs - to this class. We can conveniently use the address of the (static) - class_check variable to generate this unique value. */ - vtab->id.check = &class_check; - vtab->id.parent = &(((AstObjectVtab *) vtab)->id); - -/* Initialise member function pointers. */ -/* ------------------------------------ */ -/* Store pointers to the member functions (implemented here) that provide - virtual methods for this class. */ -#define VTAB_GENERIC(X) \ - vtab->Resample##X = Resample##X; - -VTAB_GENERIC(B) -VTAB_GENERIC(D) -VTAB_GENERIC(F) -VTAB_GENERIC(I) -VTAB_GENERIC(K) -VTAB_GENERIC(L) -VTAB_GENERIC(S) -VTAB_GENERIC(UB) -VTAB_GENERIC(UI) -VTAB_GENERIC(UK) -VTAB_GENERIC(UL) -VTAB_GENERIC(US) - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -VTAB_GENERIC(LD) -#endif - -#undef VTAB_GENERIC - -#define VTAB_GENERIC(X) \ - vtab->Rebin##X = Rebin##X; \ - vtab->RebinSeq##X = RebinSeq##X; - -VTAB_GENERIC(D) -VTAB_GENERIC(F) -VTAB_GENERIC(I) -VTAB_GENERIC(B) -VTAB_GENERIC(UB) - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -VTAB_GENERIC(LD) -#endif - -#undef VTAB_GENERIC - - - vtab->ClearInvert = ClearInvert; - vtab->ClearReport = ClearReport; - vtab->Decompose = Decompose; - vtab->DoNotSimplify = DoNotSimplify; - vtab->GetInvert = GetInvert; - vtab->GetIsLinear = GetIsLinear; - vtab->GetIsSimple = GetIsSimple; - vtab->GetNin = GetNin; - vtab->GetNout = GetNout; - vtab->GetReport = GetReport; - vtab->GetTranForward = GetTranForward; - vtab->GetTranInverse = GetTranInverse; - vtab->Invert = Invert; - vtab->LinearApprox = LinearApprox; - vtab->MapBox = MapBox; - vtab->MapList = MapList; - vtab->MapMerge = MapMerge; - vtab->MapSplit = MapSplit; - vtab->QuadApprox = QuadApprox; - vtab->Rate = Rate; - vtab->ReportPoints = ReportPoints; - vtab->RemoveRegions = RemoveRegions; - vtab->SetInvert = SetInvert; - vtab->SetReport = SetReport; - vtab->Simplify = Simplify; - vtab->TestInvert = TestInvert; - vtab->TestReport = TestReport; - vtab->Tran1 = Tran1; - vtab->Tran2 = Tran2; - vtab->TranGrid = TranGrid; - vtab->TranN = TranN; - vtab->TranP = TranP; - vtab->Transform = Transform; - -/* Save the inherited pointers to methods that will be extended, and - replace them with pointers to the new member functions. */ - object = (AstObjectVtab *) vtab; - - parent_clearattrib = object->ClearAttrib; - object->ClearAttrib = ClearAttrib; - parent_getattrib = object->GetAttrib; - object->GetAttrib = GetAttrib; - parent_setattrib = object->SetAttrib; - object->SetAttrib = SetAttrib; - parent_testattrib = object->TestAttrib; - object->TestAttrib = TestAttrib; - parent_equal = object->Equal; - object->Equal = Equal; - -/* Declare the destructor, copy constructor and dump function. */ - astSetDelete( vtab, Delete ); - astSetCopy( vtab, Copy ); - astSetDump( vtab, Dump, "Mapping", "Mapping between coordinate systems" ); - -/* If we have just initialised the vtab for the current class, indicate - that the vtab is now initialised, and store a pointer to the class - identifier in the base "object" level of the vtab. */ - if( vtab == &class_vtab ) { - class_init = 1; - astSetVtabClassIdentifier( vtab, &(vtab->id) ); - } -} - -/* -* Name: -* InterpolateKernel1<X> - -* Purpose: -* Resample a data grid, using a 1-d interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int InterpolateKernel1<X>( AstMapping *this, int ndim_in, -* const int *lbnd_in, const int *ubnd_in, -* const <Xtype> *in, const <Xtype> *in_var, -* int npoint, const int *offset, -* const double *const *coords, -* void (* kernel)( double, const double [], int, -* double *, int * ), -* void (* fkernel)( double, const double [], int, -* double * ), -* int neighb, const double *params, int flags, -* <Xtype> badval, -* <Xtype> *out, <Xtype> *out_var ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which resample a rectangular input -* grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. Each output -* grid point may be mapped on to a position in the input grid in -* an arbitrary way. The input and output grids may have any number -* of dimensions, not necessarily equal. -* -* Where the positions given do not correspond with a pixel centre -* in the input grid, interpolation is performed using a weighted -* sum of the surrounding pixel values. The weights are determined -* by a separable kernel which is the product of a 1-dimensional -* kernel function evaluated along each input dimension. A pointer -* should be supplied to the 1-dimensional kernel function to be -* used. - -* Parameters: -* this -* Pointer to the Mapping being used in the resampling operation -* (this is only used for constructing error messages). -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input grid, its extent along a particular -* (i'th) dimension being ubnd_in[i]-lbnd_in[i]+1 (assuming "i" -* is zero-based). They also define the input grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be resampled (with an element -* for each pixel in the input grid). The numerical type of -* these data should match the function used, as given by the -* suffix on the function name. The storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -* (i.e. Fortran array storage order). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* npoint -* The number of points at which the input grid is to be -* resampled. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each output point, this array should contain the zero-based -* offset in the output array(s) (i.e. the "out" and, -* optionally, the "out_var" arrays) at which the resampled -* output value(s) should be stored. -* coords -* An array of pointers to double, with "ndim_in" -* elements. Element "coords[coord]" should point at the first -* element of an array of double (with "npoint" elements) which -* contains the values of coordinate number "coord" for each -* interpolation point. The value of coordinate number "coord" -* for interpolation point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices to be -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding output data (and -* variance) will be set to the value given by "badval" (unles the -* AST__NOBAD flag is specified). -* kernel -* Pointer to the 1-dimensional kernel function to be used. -* fkernel -* Pointer to the 1-dimensional kernel function to be used with no -* trailing status argument. This is only used if "kernel" is NULL. -* neighb -* The number of neighbouring pixels in each dimension (on each -* side of the interpolation position) which are to contribute -* to the interpolated value. This value should be at least 1. -* params -* Pointer to an optional array of parameter values to be passed -* to the interpolation kernel function. If no parameters are -* required by this function, then a NULL pointer may be -* supplied. -* flags -* The bitwise OR of a set of flag values which provide -* additional control over the resampling operation. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. Unles the AST__NOBAD flag is specified in "flags", the -* same value will also be used to flag any output array elements -* for which resampled values could not be obtained. The output -* arrays(s) may be flagged with this value whether or not the -* AST__USEBAD flag is set (the function return value indicates -* whether any such values have been produced). -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. Note -* that details of how the output grid maps on to this array -* (e.g. the storage order, number of dimensions, etc.) is -* arbitrary and is specified entirely by means of the "offset" -* array. The "out" array should therefore contain sufficient -* elements to accommodate the "offset" values supplied. There -* is no requirement that all elements of the "out" array should -* be assigned values, and any which are not addressed by the -* contents of the "offset" array will be left unchanged. -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. It is addressed in -* exactly the same way (via the "offset" array) as the "out" -* array. The values returned are estimates of the statistical -* variance of the corresponding values in the "out" array, on -* the assumption that all errors in input grid values (in the -* "in" array) are statistically independent and that their -* variance estimates (in the "in_var" array) may simply be -* summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. - -* Returned Value: -* The number of output grid points for which no valid output value -* could be obtained. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -* - A value of zero will be returned if any of these functions is -* invoked with the global error status set, or if it should fail -* for any reason. -*/ -/* Define macros to implement the function for a specific data - type. */ -#define MAKE_INTERPOLATE_KERNEL1(X,Xtype,Xfloating,Xfloattype,Xsigned) \ -static int InterpolateKernel1##X( AstMapping *this, int ndim_in, \ - const int *lbnd_in, const int *ubnd_in, \ - const Xtype *in, const Xtype *in_var, \ - int npoint, const int *offset, \ - const double *const *coords, \ - void (* kernel)( double, const double [], \ - int, double *, int * ), \ - void (* fkernel)( double, const double [], \ - int, double * ), \ - int neighb, const double *params, \ - int flags, Xtype badval, \ - Xtype *out, Xtype *out_var, int *status ) { \ -\ -/* Local Variables: */ \ - astDECLARE_GLOBALS /* Thread-specific data */ \ - Xfloattype hi_lim; /* Upper limit on output values */ \ - Xfloattype lo_lim; /* Lower limit on output values */ \ - Xfloattype sum; /* Weighted sum of pixel data values */ \ - Xfloattype sum_var; /* Weighted sum of pixel variance values */ \ - Xfloattype val; /* Data value to be assigned to output */ \ - Xfloattype val_var; /* Variance to be assigned to output */ \ - Xfloattype wtsum; /* Sum of weight values */ \ - Xfloattype wtsum_sq; /* Square of sum of weights */ \ - Xtype var; /* Variance value */ \ - double **wtptr; /* Pointer to array of weight pointers */ \ - double **wtptr_last; /* Array of highest weight pointer values */ \ - double *kval; /* Pointer to array of kernel values */ \ - double *wtprod; /* Accumulated weight value array pointer */ \ - double *xn_max; /* Pointer to upper limits array (n-d) */ \ - double *xn_min; /* Pointer to lower limits array (n-d) */ \ - double pixwt; /* Weight to apply to individual pixel */ \ - double wt_y; /* Value of y-dependent pixel weight */ \ - double x; /* x coordinate value */ \ - double xmax; /* x upper limit */ \ - double xmin; /* x lower limit */ \ - double xn; /* Coordinate value (n-d) */ \ - double y; /* y coordinate value */ \ - double ymax; /* y upper limit */ \ - double ymin; /* y lower limit */ \ - int *hi; /* Pointer to array of upper indices */ \ - int *lo; /* Pointer to array of lower indices */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int bad_var; /* Output variance bad? */ \ - int done; /* All pixel indices done? */ \ - int hi_x; /* Upper pixel index (x dimension) */ \ - int hi_y; /* Upper pixel index (y dimension) */ \ - int idim; /* Loop counter for dimensions */ \ - int ii; /* Loop counter for dimensions */ \ - int ix; /* Pixel index in input grid x dimension */ \ - int ixn; /* Pixel index in input grid (n-d) */ \ - int iy; /* Pixel index in input grid y dimension */ \ - int kerror; /* Error signalled by kernel function? */ \ - int lo_x; /* Lower pixel index (x dimension) */ \ - int lo_y; /* Lower pixel index (y dimension) */ \ - int nobad; /* Was the AST__NOBAD flag set? */ \ - int off1; /* Input pixel offset due to y index */ \ - int off_in; /* Offset to input pixel */ \ - int off_out; /* Offset to output pixel */ \ - int pixel; /* Offset to input pixel containing point */ \ - int point; /* Loop counter for output points */ \ - int result; /* Result value to return */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int ystride; /* Stride along input grid y dimension */ \ -\ -/* Initialise. */ \ - result = 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Get a pointer to a structure holding thread-specific global data values */ \ - astGET_GLOBALS(this); \ -\ -/* Further initialisation. */ \ - kerror = 0; \ - sum_var = 0; \ - val = 0; \ - val_var = 0; \ - wtsum = 0; \ - bad = 0; \ - bad_var = 0; \ - sum = 0.0; \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - nobad = flags & AST__NOBAD; \ - usebad = flags & AST__USEBAD; \ - usevar = in_var && out_var; \ -\ -/* Set up limits for checking output values to ensure that they do not \ - overflow the range of the data type being used. */ \ - lo_lim = LO_##X; \ - hi_lim = HI_##X; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_in == 1 ) { \ -\ -/* Calculate the coordinate limits of the input grid. */ \ - xmin = (double) lbnd_in[ 0 ] - 0.5; \ - xmax = (double) ubnd_in[ 0 ] + 0.5; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,1) \ - } \ - } \ - } \ -\ -/* Four more cases as above, but this time with the AST__NOBAD flag \ - un-set. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Exit point on error in kernel function */ \ - Kernel_Error_1d: ; \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_in == 2 ) { \ -\ -/* Allocate workspace. */ \ - kval = astMalloc( sizeof( double ) * (size_t) ( 2 * neighb ) ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along the y dimension of the input grid. */ \ - ystride = ubnd_in[ 0 ] - lbnd_in[ 0 ] + 1; \ -\ -/* Calculate the coordinate limits of the input grid in each \ - dimension. */ \ - xmin = (double) lbnd_in[ 0 ] - 0.5; \ - xmax = (double) ubnd_in[ 0 ] + 0.5; \ - ymin = (double) lbnd_in[ 1 ] - 0.5; \ - ymax = (double) ubnd_in[ 1 ] + 0.5; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,1) \ - } \ - } \ - } \ -\ -/* Another four cases, as above, but this time without the AST__NOBAD \ - flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Exit point on error in kernel function */ \ - Kernel_Error_2d: ; \ - } \ -\ -/* Free the workspace. */ \ - kval = astFree( kval ); \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - hi = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - lo = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - xn_max = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - xn_min = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - kval = astMalloc( sizeof( double ) * (size_t) \ - ( 2 * neighb * ndim_in ) ); \ - wtprod = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - wtptr = astMalloc( sizeof( double * ) * (size_t) ndim_in ); \ - wtptr_last = astMalloc( sizeof( double * ) * (size_t) ndim_in ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the input grid. */ \ - for ( s = 1, idim = 0; idim < ndim_in; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ -\ -/* Calculate the coordinate limits of the input grid in each \ - dimension. */ \ - xn_min[ idim ] = (double) lbnd_in[ idim ] - 0.5; \ - xn_max[ idim ] = (double) ubnd_in[ idim ] + 0.5; \ - } \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,1) \ - } \ - } \ - } \ -\ -/* Another 4 cases as above, but this time with the AST__NOBAD flag \ - un-set. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Exit point on error in kernel function */ \ - Kernel_Error_Nd: ;\ - } \ -\ -/* Free the workspace. */ \ - hi = astFree( hi ); \ - lo = astFree( lo ); \ - stride = astFree( stride ); \ - xn_max = astFree( xn_max ); \ - xn_min = astFree( xn_min ); \ - kval = astFree( kval ); \ - wtprod = astFree( wtprod ); \ - wtptr = astFree( wtptr ); \ - wtptr_last = astFree( wtptr_last ); \ - } \ -\ -/* If an error occurred in the kernel function, then report a \ - contextual error message. */ \ - if ( kerror ) { \ - astError( astStatus, "astResample"#X"(%s): Error signalled by " \ - "user-supplied 1-d interpolation kernel.", status, \ - astGetClass( unsimplified_mapping ) ); \ - } \ -\ -/* If an error has occurred, clear the returned result. */ \ - if ( !astOK ) result = 0; \ -\ -/* Return the result. */ \ - return result; \ -} - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 1-dimensional - case. */ -#define ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the input grid, or is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If input bad pixels must be detected, then obtain the offset along \ - the input grid x dimension of the input pixel which contains the \ - current coordinate, and calculate this pixel's offset from the \ - start of the input array. */ \ - if ( Usebad ) { \ - pixel = (int) floor( x + 0.5 ) - lbnd_in[ 0 ]; \ -\ -/* Test if the pixel is bad. */ \ - bad = ( in[ pixel ] == badval ); \ - } \ -\ -/* If OK, calculate the lowest and highest indices (in the x \ - dimension) of the region of neighbouring pixels that will \ - contribute to the interpolated result. Constrain these values to \ - lie within the input grid. */ \ - if ( !bad ) { \ - ix = (int) floor( x ); \ - lo_x = MaxI( ix - neighb + 1, lbnd_in[ 0 ], status ); \ - hi_x = MinI( ix + neighb, ubnd_in[ 0 ], status ); \ -\ -/* Initialise sums for forming the interpolated result. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - bad_var = 0; \ - } \ -\ -/* Loop to inspect all the contributing pixels, calculating the offset \ - of each pixel from the start of the input array. */ \ - off_in = lo_x - lbnd_in[ 0 ]; \ - for ( ix = lo_x; ix <= hi_x; ix++, off_in++ ) { \ -\ -/* If necessary, test if the input pixel is bad. If not, calculate its \ - weight by evaluating the kernel function. */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ - if( kernel ) { \ - ( *kernel )( (double) ix - x, params, flags, &pixwt, status ); \ - } else { \ - ( *fkernel )( (double) ix - x, params, flags, &pixwt ); \ - } \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_Error_1d; \ - } \ -\ -/* Form the weighted sums required for finding the interpolated \ - value. */ \ - sum += ( (Xfloattype) pixwt ) * ( (Xfloattype) in[ off_in ] ); \ - wtsum += (Xfloattype) pixwt; \ -\ -/* If a variance estimate is required and it still seems possible to \ - obtain one, then obtain the variance value associated with the \ - current input pixel. */ \ - if ( Usevar ) { \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - var = in_var[ off_in ]; \ -\ -/* If necessary, test if this value is bad (if the data type is \ - signed, also check that it is not negative). */ \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If any bad input variance value is obtained, we cannot generate a \ - valid output variance estimate. Otherwise, form the sum needed to \ - calculate this estimate. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - sum_var += ( (Xfloattype) ( pixwt * pixwt ) ) * \ - ( (Xfloattype) var ); \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 2-dimensional - case. */ -#define ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the input grid, or is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If not, then similarly obtain and test the y coordinate. */ \ - y = coords[ 1 ][ point ]; \ - bad = ( y < ymin ) || ( y >= ymax ) || ( y == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If input bad pixels must be detected, then obtain the offsets along \ - each input grid dimension of the input pixel which contains the \ - current coordinates, and calculate this pixel's offset from the \ - start of the input array. */ \ - if ( Usebad ) { \ - ix = (int) floor( x + 0.5 ); \ - iy = (int) floor( y + 0.5 ); \ - pixel = ix - lbnd_in[ 0 ] + ystride * ( iy - lbnd_in[ 1 ] ); \ -\ -/* Test if the pixel is bad. */ \ - bad = ( in[ pixel ] == badval ); \ - } \ -\ -/* If OK, calculate the lowest and highest indices (in each dimension) \ - of the region of neighbouring pixels that will contribute to the \ - interpolated result. Constrain these values to lie within the input \ - grid. */ \ - if ( !bad ) { \ - ix = (int) floor( x ); \ - lo_x = MaxI( ix - neighb + 1, lbnd_in[ 0 ], status ); \ - hi_x = MinI( ix + neighb, ubnd_in[ 0 ], status ); \ - iy = (int) floor( y ); \ - lo_y = MaxI( iy - neighb + 1, lbnd_in[ 1 ], status ); \ - hi_y = MinI( iy + neighb, ubnd_in[ 1 ], status ); \ -\ -/* Loop to evaluate the kernel function along the x dimension, storing \ - the resulting values. The function's argument is the offset of the \ - contributing pixel (along this dimension) from the input \ - position. */ \ - for ( ix = lo_x; ix <= hi_x; ix++ ) { \ - if( kernel ) { \ - ( *kernel )( (double) ix - x, params, flags, \ - kval + ix - lo_x, status ); \ - } else { \ - ( *fkernel )( (double) ix - x, params, flags, \ - kval + ix - lo_x ); \ - } \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_Error_2d; \ - } \ - } \ -\ -/* Initialise sums for forming the interpolated result. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - bad_var = 0; \ - } \ -\ -/* Loop over the y index to inspect all the contributing pixels, while \ - keeping track of their offset within the input array. Evaluate the \ - kernel function for each y index value. */ \ - off1 = lo_x - lbnd_in[ 0 ] + ystride * ( lo_y - lbnd_in[ 1 ] ); \ - for ( iy = lo_y; iy <= hi_y; iy++, off1 += ystride ) { \ - if( kernel ) { \ - ( *kernel )( (double) iy - y, params, flags, &wt_y, status ); \ - } else { \ - ( *fkernel )( (double) iy - y, params, flags, &wt_y ); \ - } \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_Error_2d; \ - } \ -\ -/* Loop over the x index, calculating the pixel offset in the input \ - array. */ \ - off_in = off1; \ - for ( ix = lo_x; ix <= hi_x; ix++, off_in++ ) { \ -\ -/* If necessary, test if the input pixel is bad. If not, calculate its \ - weight as the product of the kernel function's value for the x and \ - y dimensions. */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ - pixwt = kval[ ix - lo_x ] * wt_y; \ -\ -/* Form the weighted sums required for finding the interpolated \ - value. */ \ - sum += ( (Xfloattype) pixwt ) * \ - ( (Xfloattype) in[ off_in ] ); \ - wtsum += (Xfloattype) pixwt; \ -\ -/* If a variance estimate is required and it still seems possible to \ - obtain one, then obtain the variance value associated with the \ - current input pixel. */ \ - if ( Usevar ) { \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - var = in_var[ off_in ]; \ -\ -/* If necessary, test if this value is bad (if the data type is \ - signed, also check that it is not negative). */ \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If any bad input variance value is obtained, we cannot generate a \ - valid output variance estimate. Otherwise, form the sum needed to \ - calculate this estimate. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || \ - !bad_var ) { \ - sum_var += ( (Xfloattype) ( pixwt * pixwt ) ) * \ - ( (Xfloattype) var ); \ - } \ - } \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the n-dimensional - case. */ -#define ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Initialise offsets into the input array. Then loop to obtain each \ - coordinate associated with the current output point. */ \ - pixel = 0; \ - off_in = 0; \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate lies outside the input grid, or is bad. If \ - either is true, the corresponding output pixel value will be bad, \ - so give up on this point. */ \ - bad = ( xn < xn_min[ idim ] ) || ( xn >= xn_max[ idim ] ) || \ - ( xn == AST__BAD ); \ - if ( bad ) break; \ -\ -/* If input bad pixels must be detected, then obtain the index along \ - the current input grid dimension of the pixel which contains this \ - coordinate and accumulate the pixel's offset from the start of the \ - input array. */ \ - if ( Usebad ) { \ - pixel += stride[ idim ] * \ - ( (int) floor( xn + 0.5 ) - lbnd_in[ idim ] ); \ - } \ -\ -/* Calculate the lowest and highest indices (in the current dimension) \ - of the region of neighbouring pixels that will contribute to the \ - interpolated result. Constrain these values to lie within the input \ - grid. */ \ - ixn = (int) floor( xn ); \ - lo[ idim ] = MaxI( ixn - neighb + 1, lbnd_in[ idim ], status ); \ - hi[ idim ] = MinI( ixn + neighb, ubnd_in[ idim ], status ); \ -\ -/* Accumulate the offset (from the start of the input array) of the \ - contributing pixel which has the lowest index in each dimension. */ \ - off_in += stride[ idim ] * ( lo[ idim ] - lbnd_in[ idim ] ); \ - } \ -\ -/* Once the input pixel which contains the required coordinates has \ - been identified, test if it is bad, if necessary. */ \ - if ( Usebad ) bad = bad || ( in[ pixel ] == badval ); \ -\ -/* If OK, loop to evaluate the kernel function which will be used to \ - weight the contributions from surrounding pixels. */ \ - if ( !bad ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ -\ -/* Set up an array of pointers to locate kernel values (stored in the \ - "kval" array) for each dimension. Initially, each of these pointers \ - locates the first weight value which applies to the contributing \ - pixel with the lowest index in each dimension. */ \ - wtptr[ idim ] = kval + ( 2 * neighb * idim ); \ -\ -/* Also set up pointers to the last weight value in each dimension. */ \ - wtptr_last[ idim ] = wtptr[ idim ] + ( hi[ idim ] - lo[ idim ] ); \ -\ -/* Loop to evaluate the kernel function along each dimension, storing \ - the resulting values. The function's argument is the offset of the \ - contributing pixel (along the relevant dimension) from the input \ - point. */ \ - xn = coords[ idim ][ point ]; \ - for ( ixn = lo[ idim ]; ixn <= hi[ idim ]; ixn++ ) { \ - if( kernel ) { \ - ( *kernel )( (double) ixn - xn, params, flags, \ - wtptr[ idim ] + ixn - lo[ idim ], status ); \ - } else { \ - ( *fkernel )( (double) ixn - xn, params, flags, \ - wtptr[ idim ] + ixn - lo[ idim ] ); \ - } \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_Error_Nd; \ - } \ - } \ - } \ -\ -/* Initialise, and loop over the neighbouring input pixels to obtain \ - an interpolated value. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - bad_var = 0; \ - } \ - idim = ndim_in - 1; \ - wtprod[ idim ] = 1.0; \ - done = 0; \ - do { \ -\ -/* Each contributing pixel is weighted by the product of the kernel \ - weight factors evaluated along each input dimension. However, since \ - we typically only change the index of one dimension at a time, we \ - can avoid forming this product repeatedly by retaining an array of \ - accumulated products for all higher dimensions. We need then only \ - update the lower elements in this array, corresponding to those \ - dimensions whose index has changed. We do this here, "idim" being \ - the index of the most significant dimension to have changed. Note \ - that on the first pass, all dimensions are considered changed, \ - causing this array to be initialised. */ \ - for ( ii = idim; ii >= 1; ii-- ) { \ - wtprod[ ii - 1 ] = wtprod[ ii ] * *( wtptr[ ii ] ); \ - } \ -\ -/* If necessary, test each pixel which may contribute to the result to \ - see if it is bad. If not, obtain its weight from the accumulated \ - product of weights. Also multiply by the weight for dimension zero, \ - which is not included in the "wtprod" array). */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ - pixwt = wtprod[ 0 ] * *( wtptr[ 0 ] ); \ -\ -/* Form the weighted sums required for finding the interpolated \ - value. */ \ - sum += ( (Xfloattype) pixwt ) * ( (Xfloattype) in[ off_in ] ); \ - wtsum += (Xfloattype) pixwt; \ -\ -/* If a variance estimate is required and it still seems possible to \ - obtain one, then obtain the variance value associated with the \ - current input pixel. */ \ - if ( Usevar ) { \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - var = in_var[ off_in ]; \ -\ -/* If necessary, test if this value is bad (if the data type is \ - signed, also check that it is not negative). */ \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If any bad input variance value is obtained, we cannot generate a \ - valid output variance estimate. Otherwise, form the sum needed to \ - calculate this estimate. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - sum_var += ( (Xfloattype) ( pixwt * pixwt ) ) * \ - ( (Xfloattype) var ); \ - } \ - } \ - } \ - } \ -\ -/* Now update the weight value pointers and pixel offset to refer to \ - the next input pixel to be considered. */ \ - idim = 0; \ - do { \ -\ -/* The first input dimension whose weight value pointer has not yet \ - reached its final value has this pointer incremented, and the pixel \ - offset into the input array is updated accordingly. */ \ - if ( wtptr[ idim ] != wtptr_last[ idim ] ) { \ - wtptr[ idim ]++; \ - off_in += stride[ idim ]; \ - break; \ -\ -/* Any earlier dimensions (which have reached the final pointer value) \ - have this pointer returned to its lowest value. Again, the pixel \ - offset into the input image is updated accordingly. */ \ - } else { \ - wtptr[ idim ] -= ( hi[ idim ] - lo[ idim ] ); \ - off_in -= stride[ idim ] * \ - ( hi[ idim ] - lo[ idim ] ); \ - done = ( ++idim == ndim_in ); \ - } \ - } while ( !done ); \ - } while ( !done ); \ - } - -/* This subsidiary macro calculates the interpolated output value (and - variance) from the sums over contributing pixels, checks the - results for validity, and assigns them to the output array(s). */ -#define CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Usebad,Usevar,Nobad) \ -\ -/* If the output data value has not yet been flagged as bad, then \ - check that an interpolated value can actually be produced. First \ - check that the sum of weights is not zero. */ \ - if ( !bad ) { \ - bad = ( wtsum == (Xfloattype) 0.0 ); \ -\ -/* If OK, calculate the interpolated value. Then, if the output data \ - type is not floating point, check that this value will not overflow \ - the available output range. */ \ - if ( !bad ) { \ - val = sum / wtsum; \ - if ( !( Xfloating ) ) { \ - bad = ( val <= lo_lim ) || ( val >= hi_lim ); \ - } \ - } \ -\ -/* If no interpolated data value can be produced, then no associated \ - variance will be required either. */ \ - if ( ( Usevar ) && bad ) bad_var = 1; \ - } \ -\ -/* Now perform similar checks on the output variance value (if \ - required). This time we check that the square of the sum of \ - weights is not zero (since this might underflow before the sum of \ - weights). Again we also check to prevent the result overflowing the \ - output data type. */ \ - if ( ( Usevar ) && !bad_var ) { \ - wtsum_sq = wtsum * wtsum; \ - bad_var = ( wtsum_sq == (Xfloattype) 0.0 ); \ - if ( !bad_var ) { \ - val_var = sum_var / wtsum_sq; \ - if ( !( Xfloating ) ) { \ - bad_var = ( val_var <= lo_lim ) || ( val_var >= hi_lim ); \ - } \ - } \ - } \ -\ -/* Obtain the pixel offset into the output array. */ \ - off_out = offset[ point ]; \ -\ -/* Assign a bad output value (and variance) if required and count it. */ \ - if ( bad ) { \ - if( !Nobad ) { \ - out[ off_out ] = badval; \ - if ( Usevar ) out_var[ off_out ] = badval; \ - } \ - result++; \ -\ -/* Otherwise, assign the interpolated value. If the output data type \ - is floating point, the result can be stored directly, otherwise we \ - must round to the nearest integer. */ \ - } else { \ - if ( Xfloating ) { \ - out[ off_out ] = (Xtype) val; \ - } else { \ - out[ off_out ] = (Xtype) ( val + ( ( val >= (Xfloattype) 0.0 ) ? \ - ( (Xfloattype) 0.5 ) : \ - ( (Xfloattype) -0.5 ) ) ); \ - } \ -\ -/* If a variance estimate is required but none can be obtained, then \ - store a bad output variance value and count it. */ \ - if ( Usevar ) { \ - if ( bad_var ) { \ - if( !Nobad ) { \ - out_var[ off_out ] = badval; \ - } \ - result++; \ -\ -/* Otherwise, store the variance estimate, rounding to the nearest \ - integer if necessary. */ \ - } else { \ - if ( Xfloating ) { \ - out_var[ off_out ] = (Xtype) val_var; \ - } else { \ - out_var[ off_out ] = (Xtype) ( val_var + \ - ( ( val_var >= (Xfloattype) 0.0 ) ? \ - ( (Xfloattype) 0.5 ) : \ - ( (Xfloattype) -0.5 ) ) ); \ - } \ - } \ - } \ - } - -/* These subsidiary macros define limits for range checking of results - before conversion to the final data type. For each data type code - <X>, HI_<X> gives the least positive floating point value which - just overflows that data type towards plus infinity, while LO_<X> - gives the least negative floating point value which just overflows - that data type towards minus infinity. Thus, a floating point value - must satisfy LO<flt_value<HI if overflow is not to occur when it is - converted to that data type. - - The data type of each limit should be that of the smallest - precision floating point type which will accommodate the full range - of values that the target type may take. */ - -/* If <X> is a floating point type, the limits are not actually used, - but must be present to permit error-free compilation. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -#define HI_LD ( 0.0L ) -#define LO_LD ( 0.0L ) -#endif -#define HI_D ( 0.0 ) -#define LO_D ( 0.0 ) -#define HI_F ( 0.0f ) -#define LO_F ( 0.0f ) - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -#define HI_K ( 0.5L + (long double) LONG_MAX ) -#define LO_K ( -0.5L + (long double) LONG_MIN ) -#define HI_UK ( 0.5L + (long double) ULONG_MAX ) -#define LO_UK ( -0.5L ) -#define HI_L ( 0.5L + (long double) LONG_MAX ) -#define LO_L ( -0.5L + (long double) LONG_MIN ) -#define HI_UL ( 0.5L + (long double) ULONG_MAX ) -#define LO_UL ( -0.5L ) -#else -#define HI_K ( 0.5 + (double) LONG_MAX ) -#define LO_K ( -0.5 + (double) LONG_MIN ) -#define HI_UK ( 0.5 + (double) ULONG_MAX ) -#define LO_UK ( -0.5 ) -#define HI_L ( 0.5 + (double) LONG_MAX ) -#define LO_L ( -0.5 + (double) LONG_MIN ) -#define HI_UL ( 0.5 + (double) ULONG_MAX ) -#define LO_UL ( -0.5 ) -#endif - -#define HI_I ( 0.5 + (double) INT_MAX ) -#define LO_I ( -0.5 + (double) INT_MIN ) -#define HI_UI ( 0.5 + (double) UINT_MAX ) -#define LO_UI ( -0.5 ) -#define HI_S ( 0.5f + (float) SHRT_MAX ) -#define LO_S ( -0.5f + (float) SHRT_MIN ) -#define HI_US ( 0.5f + (float) USHRT_MAX ) -#define LO_US ( -0.5f ) -#define HI_B ( 0.5f + (float) SCHAR_MAX ) -#define LO_B ( -0.5f + (float) SCHAR_MIN ) -#define HI_UB ( 0.5f + (float) UCHAR_MAX ) -#define LO_UB ( -0.5f ) - -/* This subsidiary macro tests for negative variance values. This - check is required only for signed data types. */ -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ - bad_var = bad_var || ( var < ( (Xtype) 0 ) ); - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_KERNEL1(LD,long double,1,long double,1) -MAKE_INTERPOLATE_KERNEL1(L,long int,0,long double,1) -MAKE_INTERPOLATE_KERNEL1(K,INT_BIG,0,long double,1) -#else -MAKE_INTERPOLATE_KERNEL1(L,long int,0,double,1) -MAKE_INTERPOLATE_KERNEL1(K,INT_BIG,0,double,1) -#endif -MAKE_INTERPOLATE_KERNEL1(D,double,1,double,1) -MAKE_INTERPOLATE_KERNEL1(F,float,1,float,1) -MAKE_INTERPOLATE_KERNEL1(I,int,0,double,1) -MAKE_INTERPOLATE_KERNEL1(S,short int,0,float,1) -MAKE_INTERPOLATE_KERNEL1(B,signed char,0,float,1) - -/* Re-define the macro for testing for negative variances to do - nothing. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) - -/* Expand the main macro above to generate a function for each - required unsigned data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_KERNEL1(UL,unsigned long int,0,long double,0) -MAKE_INTERPOLATE_KERNEL1(UK,UINT_BIG,0,long double,0) -#else -MAKE_INTERPOLATE_KERNEL1(UL,unsigned long int,0,double,0) -MAKE_INTERPOLATE_KERNEL1(UK,UINT_BIG,0,double,0) -#endif -MAKE_INTERPOLATE_KERNEL1(UI,unsigned int,0,double,0) -MAKE_INTERPOLATE_KERNEL1(US,unsigned short int,0,float,0) -MAKE_INTERPOLATE_KERNEL1(UB,unsigned char,0,float,0) - -/* Undefine the macros used above. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -#undef HI_LD -#undef LO_LD -#endif -#undef HI_D -#undef LO_D -#undef HI_F -#undef LO_F -#undef HI_L -#undef LO_L -#undef HI_UL -#undef LO_UL -#undef HI_K -#undef LO_K -#undef HI_UK -#undef LO_UK -#undef HI_I -#undef LO_I -#undef HI_UI -#undef LO_UI -#undef HI_S -#undef LO_S -#undef HI_US -#undef LO_US -#undef HI_B -#undef LO_B -#undef HI_UB -#undef LO_UB -#undef CALC_AND_ASSIGN_OUTPUT -#undef ASSEMBLE_INPUT_ND -#undef ASSEMBLE_INPUT_2D -#undef ASSEMBLE_INPUT_1D -#undef MAKE_INTERPOLATE_KERNEL1 - -/* -* Name: -* InterpolateLinear<X> - -* Purpose: -* Resample a data grid, using the linear interpolation scheme. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int InterpolateLinear<X>( int ndim_in, -* const int *lbnd_in, const int *ubnd_in, -* const <Xtype> *in, const <Xtype> *in_var, -* int npoint, const int *offset, -* const double *const *coords, -* int flags, <Xtype> badval, -* <Xtype> *out, <Xtype> *out_var ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which resample a rectangular input -* grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. Each output -* grid point may be mapped on to a position in the input grid in -* an arbitrary way. Where the positions given do not correspond -* with a pixel centre in the input grid, the interpolation scheme -* used is linear interpolation between the centres of the nearest -* neighbouring pixels in each dimension (there are 2 nearest -* neighbours in 1 dimension, 4 in 2 dimensions, 8 in 3 dimensions, -* etc.). - -* Parameters: -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input grid, its extent along a particular -* (i'th) dimension being ubnd_in[i]-lbnd_in[i]+1 (assuming "i" -* is zero-based). They also define the input grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be resampled (with an element -* for each pixel in the input grid). The numerical type of -* these data should match the function used, as given by the -* suffix on the function name. The storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -* (i.e. Fortran array storage order). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* npoint -* The number of points at which the input grid is to be -* resampled. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each output point, this array should contain the zero-based -* offset in the output array(s) (i.e. the "out" and, -* optionally, the "out_var" arrays) at which the resampled -* output value(s) should be stored. -* coords -* An array of pointers to double, with "ndim_in" -* elements. Element "coords[coord]" should point at the first -* element of an array of double (with "npoint" elements) which -* contains the values of coordinate number "coord" for each -* interpolation point. The value of coordinate number "coord" -* for interpolation point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices to be -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding output data (and -* variance) will be set to the value given by "badval" (unles the -* AST__NOBAD flag is specified). -* flags -* The bitwise OR of a set of flag values which control the -* operation of the function. Currently, only the flag -* AST__USEBAD is significant and indicates whether there are -* "bad" (i.e. missing) data in the input array(s) which must be -* recognised and propagated to the output array(s). If this -* flag is not set, all input values are treated literally. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. Unles the AST__NOBAD flag is specified in "flags", the -* same value will also be used to flag any output array elements -* for which resampled values could not be obtained. The output -* arrays(s) may be flagged with this value whether or not the -* AST__USEBAD flag is set (the function return value indicates -* whether any such values have been produced). -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. Note -* that details of how the output grid maps on to this array -* (e.g. the storage order, number of dimensions, etc.) is -* arbitrary and is specified entirely by means of the "offset" -* array. The "out" array should therefore contain sufficient -* elements to accommodate the "offset" values supplied. There -* is no requirement that all elements of the "out" array should -* be assigned values, and any which are not addressed by the -* contents of the "offset" array will be left unchanged. -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. It is addressed in -* exactly the same way (via the "offset" array) as the "out" -* array. The values returned are estimates of the statistical -* variance of the corresponding values in the "out" array, on -* the assumption that all errors in input grid values (in the -* "in" array) are statistically independent and that their -* variance estimates (in the "in_var" array) may simply be -* summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. - -* Returned Value: -* The number of output grid points to which a data value (or a -* variance value if relevant) equal to "badval" has been assigned -* because no valid output value could be obtained. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -* - A value of zero will be returned if any of these functions is -* invoked with the global error status set, or if it should fail -* for any reason. -*/ -/* Define macros to implement the function for a specific data - type. */ -#define MAKE_INTERPOLATE_LINEAR(X,Xtype,Xfloating,Xfloattype,Xsigned) \ -static int InterpolateLinear##X( int ndim_in, \ - const int *lbnd_in, const int *ubnd_in, \ - const Xtype *in, const Xtype *in_var, \ - int npoint, const int *offset, \ - const double *const *coords, \ - int flags, Xtype badval, \ - Xtype *out, Xtype *out_var, int *status ) { \ -\ -/* Local Variables: */ \ - Xfloattype sum; /* Weighted sum of pixel data values */ \ - Xfloattype sum_var; /* Weighted sum of pixel variance values */ \ - Xfloattype val; /* Value to be asigned to output pixel */ \ - Xfloattype wtsum; /* Sum of weight values */ \ - Xtype var; /* Variance value */ \ - double *frac_hi; /* Pointer to array of weights */ \ - double *frac_lo; /* Pointer to array of weights */ \ - double *wt; /* Pointer to array of weights */ \ - double *wtprod; /* Array of accumulated weights pointer */ \ - double *xn_max; /* Pointer to upper limits array (n-d) */ \ - double *xn_min; /* Pointer to lower limits array (n-d) */ \ - double frac_hi_x; /* Pixel weight (x dimension) */ \ - double frac_hi_y; /* Pixel weight (y dimension) */ \ - double frac_lo_x; /* Pixel weight (x dimension) */ \ - double frac_lo_y; /* Pixel weight (y dimension) */ \ - double pixwt; /* Weight to apply to individual pixel */ \ - double x; /* x coordinate value */ \ - double xmax; /* x upper limit */ \ - double xmin; /* x lower limit */ \ - double xn; /* Coordinate value (n-d) */ \ - double y; /* y coordinate value */ \ - double ymax; /* y upper limit */ \ - double ymin; /* y lower limit */ \ - int *dim; /* Pointer to array of pixel indices */ \ - int *hi; /* Pointer to array of upper indices */ \ - int *lo; /* Pointer to array of lower indices */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int bad_var; /* Output variance bad? */ \ - int done; /* All pixel indices done? */ \ - int hi_x; /* Upper pixel index (x dimension) */ \ - int hi_y; /* Upper pixel index (y dimension) */ \ - int idim; /* Loop counter for dimensions */ \ - int ii; /* Loop counter for weights */ \ - int ix; /* Pixel index in input grid x dimension */ \ - int ixn; /* Pixel index (n-d) */ \ - int iy; /* Pixel index in input grid y dimension */ \ - int lo_x; /* Lower pixel index (x dimension) */ \ - int lo_y; /* Lower pixel index (y dimension) */ \ - int nobad; /* Was the AST__NOBAD flag set? */ \ - int off_in; /* Offset to input pixel */ \ - int off_lo; /* Offset to "first" input pixel */ \ - int off_out; /* Offset to output pixel */ \ - int pixel; /* Offset to input pixel containing point */ \ - int point; /* Loop counter for output points */ \ - int result; /* Result value to return */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int ystride; /* Stride along input grid y dimension */ \ -\ -/* Initialise. */ \ - result = 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Initialise variables to avoid "used of uninitialised variable" \ - messages from dumb compilers. */ \ - sum = 0; \ - sum_var = 0; \ - wtsum = 0; \ - bad = 0; \ - bad_var = 0; \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - nobad = flags & AST__NOBAD; \ - usebad = flags & AST__USEBAD; \ - usevar = in_var && out_var; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_in == 1 ) { \ -\ -/* Calculate the coordinate limits of the input grid. */ \ - xmin = (double) lbnd_in[ 0 ] - 0.5; \ - xmax = (double) ubnd_in[ 0 ] + 0.5; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,0,1) \ - } \ - } \ - } \ -\ -/* Four more cases as above, but this time with the AST__NOBAD flag \ - un-set. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_in == 2 ) { \ -\ -/* Calculate the stride along the y dimension of the input grid. */ \ - ystride = ubnd_in[ 0 ] - lbnd_in[ 0 ] + 1; \ -\ -/* Calculate the coordinate limits of the input grid in each \ - dimension. */ \ - xmin = (double) lbnd_in[ 0 ] - 0.5; \ - xmax = (double) ubnd_in[ 0 ] + 0.5; \ - ymin = (double) lbnd_in[ 1 ] - 0.5; \ - ymax = (double) ubnd_in[ 1 ] + 0.5; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,0,1) \ - } \ - } \ - } \ -\ -/* Four more case as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - 0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - dim = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - frac_hi = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - frac_lo = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - hi = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - lo = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - wt = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - wtprod = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - xn_max = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - xn_min = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the input grid. */ \ - for ( s = 1, idim = 0; idim < ndim_in; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ -\ -/* Calculate the coordinate limits of the input grid in each \ - dimension. */ \ - xn_min[ idim ] = (double) lbnd_in[ idim ] - 0.5; \ - xn_max[ idim ] = (double) ubnd_in[ idim ] + 0.5; \ - } \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,0,0,1) \ - } \ - } \ - } \ -\ -/* Four more case as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype, \ - Xsigned,0,0,0) \ - } \ - } \ - } \ - } \ - } \ -\ -/* Free the workspace. */ \ - dim = astFree( dim ); \ - frac_hi = astFree( frac_hi ); \ - frac_lo = astFree( frac_lo ); \ - hi = astFree( hi ); \ - lo = astFree( lo ); \ - stride = astFree( stride ); \ - wt = astFree( wt ); \ - wtprod = astFree( wtprod ); \ - xn_max = astFree( xn_max ); \ - xn_min = astFree( xn_min ); \ - } \ -\ -/* If an error has occurred, clear the returned result. */ \ - if ( !astOK ) result = 0; \ -\ -/* Return the result. */ \ - return result; \ -} - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 1-dimensional - case. */ -#define ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the input grid. Also test if it is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If input bad pixels must be detected, then obtain the offset along \ - the input grid x dimension of the input pixel which contains the \ - current coordinate and calculate this pixel's offset from the start \ - of the input array. */ \ - if ( Usebad ) { \ - pixel = (int) floor( x + 0.5 ) - lbnd_in[ 0 ]; \ -\ -/* Test if the pixel is bad. */ \ - bad = ( in[ pixel ] == badval ); \ - } \ -\ -/* If OK, obtain the indices along the input grid x dimension of the \ - two adjacent pixels which will contribute to the interpolated \ - result. Also obtain the fractional weight to be applied to each of \ - these pixels. */ \ - if ( !bad ) { \ - lo_x = (int) floor( x ); \ - hi_x = lo_x + 1; \ - frac_lo_x = (double) hi_x - x; \ - frac_hi_x = 1.0 - frac_lo_x; \ -\ -/* Obtain the offset within the input array of the first pixel to be \ - used for interpolation (the one with the smaller index). */ \ - off_lo = lo_x - lbnd_in[ 0 ]; \ -\ -/* Initialise sums for forming the interpolated result. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - if ( ( Xsigned ) || ( Usebad ) ) bad_var = 0; \ - } \ -\ -/* For each of the two pixels which may contribute to the result, \ - test if the pixel index lies within the input grid. Where it does, \ - accumulate the sums required for forming the interpolated \ - result. In each case, we supply the pixel's offset within the input \ - array and the weight to be applied to it. */ \ - if ( lo_x >= lbnd_in[ 0 ] ) { \ - FORM_LINEAR_INTERPOLATION_SUM(off_lo,frac_lo_x,Xtype, \ - Xfloattype,Xsigned,Usebad,Usevar) \ - } \ - if ( hi_x <= ubnd_in[ 0 ] ) { \ - FORM_LINEAR_INTERPOLATION_SUM(off_lo + 1,frac_hi_x,Xtype, \ - Xfloattype,Xsigned,Usebad,Usevar) \ - } \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 2-dimensional - case. */ -#define ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the input grid. Also test if it is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If OK, then similarly obtain and test the y coordinate. */ \ - y = coords[ 1 ][ point ]; \ - bad = ( y < ymin ) || ( y >= ymax ) || ( y == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If input bad pixels must be detected, then obtain the offsets along \ - each input grid dimension of the input pixel which contains the \ - current coordinates. */ \ - if ( Usebad ) { \ - ix = (int) floor( x + 0.5 ); \ - iy = (int) floor( y + 0.5 ); \ -\ -/* Calculate this pixel's offset from the start of the input array. */ \ - pixel = ix - lbnd_in[ 0 ] + ystride * ( iy - lbnd_in[ 1 ] ); \ -\ -/* Test if the pixel is bad. */ \ - bad = ( in[ pixel ] == badval ); \ - } \ -\ -/* If OK, obtain the indices along the input grid x dimension of the \ - two adjacent pixels which will contribute to the interpolated \ - result. Also obtain the fractional weight to be applied to each of \ - these pixels. */ \ - if ( !bad ) { \ - lo_x = (int) floor( x ); \ - hi_x = lo_x + 1; \ - frac_lo_x = (double) hi_x - x; \ - frac_hi_x = 1.0 - frac_lo_x; \ -\ -/* Repeat this process for the y dimension. */ \ - lo_y = (int) floor( y ); \ - hi_y = lo_y + 1; \ - frac_lo_y = (double) hi_y - y; \ - frac_hi_y = 1.0 - frac_lo_y; \ -\ -/* Obtain the offset within the input array of the first pixel to be \ - used for interpolation (the one with the smaller index along both \ - dimensions). */ \ - off_lo = lo_x - lbnd_in[ 0 ] + ystride * ( lo_y - lbnd_in[ 1 ] ); \ -\ -/* Initialise sums for forming the interpolated result. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - if ( ( Xsigned ) || ( Usebad ) ) bad_var = 0; \ - } \ -\ -/* For each of the four pixels which may contribute to the result, \ - test if the pixel indices lie within the input grid. Where they do, \ - accumulate the sums required for forming the interpolated \ - result. In each case, we supply the pixel's offset within the input \ - array and the weight to be applied to it. */ \ - if ( lo_y >= lbnd_in[ 1 ] ) { \ - if ( lo_x >= lbnd_in[ 0 ] ) { \ - FORM_LINEAR_INTERPOLATION_SUM(off_lo, \ - frac_lo_x * frac_lo_y,Xtype, \ - Xfloattype, Xsigned, \ - Usebad,Usevar) \ - } \ - if ( hi_x <= ubnd_in[ 0 ] ) { \ - FORM_LINEAR_INTERPOLATION_SUM(off_lo + 1, \ - frac_hi_x * frac_lo_y,Xtype, \ - Xfloattype,Xsigned, \ - Usebad,Usevar) \ - } \ - } \ - if ( hi_y <= ubnd_in[ 1 ] ) { \ - if ( lo_x >= lbnd_in[ 0 ] ) { \ - FORM_LINEAR_INTERPOLATION_SUM(off_lo + ystride, \ - frac_lo_x * frac_hi_y,Xtype, \ - Xfloattype,Xsigned, \ - Usebad,Usevar) \ - } \ - if ( hi_x <= ubnd_in[ 0 ] ) { \ - FORM_LINEAR_INTERPOLATION_SUM(off_lo + ystride + 1, \ - frac_hi_x * frac_hi_y,Xtype, \ - Xfloattype,Xsigned, \ - Usebad,Usevar) \ - } \ - } \ - } \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the n-dimensional - case. */ -#define ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Initialise offsets into the input array. Then loop to obtain each - coordinate associated with the current output point. */ \ - off_in = 0; \ - if ( Usebad ) pixel = 0; \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate lies outside the input grid. Also test if \ - it is bad. If either is true, the corresponding output pixel value \ - will be bad, so give up on this point. */ \ - bad = ( xn < xn_min[ idim ] ) || ( xn >= xn_max[ idim ] ) || \ - ( xn == AST__BAD ); \ - if ( bad ) break; \ -\ -/* If input bad pixels must be detected, obtain the index along the \ - current input grid dimension of the pixel which contains this \ - coordinate and accumulate the pixel's offset from the start of the \ - input array. */ \ - if ( Usebad ) { \ - pixel += stride[ idim ] * \ - ( (int) floor( xn + 0.5 ) - lbnd_in[ idim ] ); \ - } \ -\ -/* Obtain the indices along the current dimension of the input grid of \ - the two (usually adjacent) pixels which will contribute to the \ - output value. If necessary, however, restrict each index to ensure \ - it does not lie outside the input grid. Also calculate the \ - fractional weight to be given to each pixel in order to interpolate \ - linearly between them. */ \ - ixn = (int) floor( xn ); \ - lo[ idim ] = MaxI( ixn, lbnd_in[ idim ], status ); \ - hi[ idim ] = MinI( ixn + 1, ubnd_in[ idim ], status ); \ - frac_lo[ idim ] = 1.0 - fabs( xn - (double) lo[ idim ] ); \ - frac_hi[ idim ] = 1.0 - fabs( xn - (double) hi[ idim ] ); \ -\ -/* Store the lower index involved in interpolation along each \ - dimension and accumulate the offset from the start of the input \ - array of the pixel which has these indices. */ \ - dim[ idim ] = lo[ idim ]; \ - off_in += stride[ idim ] * ( lo[ idim ] - lbnd_in[ idim ] ); \ -\ -/* Also store the fractional weight associated with the lower pixel \ - along each dimension. */ \ - wt[ idim ] = frac_lo[ idim ]; \ - } \ -\ -/* If the input pixel which contains the required coordinates has \ - been identified, test if it is bad. */ \ - if ( Usebad ) bad = bad || ( in[ pixel ] == badval ); \ -\ -/* If OK, initialise and loop over adjacent input pixels to obtain an \ - interpolated value. */ \ - if ( !bad ) { \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - if ( ( Xsigned ) || ( Usebad ) ) bad_var = 0; \ - } \ - idim = ndim_in - 1; \ - wtprod[ idim ] = 1.0; \ - done = 0; \ - do { \ -\ -/* Each contributing pixel is weighted by the product of the weights \ - which account for the displacement of its centre from the required \ - position along each dimension. However, since we typically only \ - change the index of one dimension at a time, we can avoid forming \ - this product repeatedly by retaining an array of accumulated weight \ - products for all higher dimensions. We need then only update the \ - lower elements in this array, corresponding to those dimensions \ - whose index has changed. We do this here, "idim" being the index of \ - the most significant dimension to have changed. Note that on the \ - first pass, all dimensions are considered changed, causing this \ - array to be initialised. */ \ - for ( ii = idim; ii >= 1; ii-- ) { \ - wtprod[ ii - 1 ] = wtprod[ ii ] * wt[ ii ]; \ - } \ -\ -/* Accumulate the sums required for forming the interpolated \ - result. We supply the pixel's offset within the input array and the \ - weight to be applied to it. The pixel weight is formed by including \ - the weight factor for dimension zero, since this is not included in \ - the "wtprod" array. */ \ - FORM_LINEAR_INTERPOLATION_SUM(off_in,wtprod[ 0 ] * wt[ 0 ], \ - Xtype,Xfloattype,Xsigned, \ - Usebad,Usevar) \ -\ -/* Now update the indices, offset and weight factors to refer to the \ - next input pixel to be considered. */ \ - idim = 0; \ - do { \ -\ -/* The first input dimension which still refers to the pixel with the \ - lower of the two possible indices is switched to refer to the other \ - pixel (with the higher index). The offset into the input array and \ - the fractional weight factor for this dimension are also updated \ - accordingly. */ \ - if ( dim[ idim ] != hi[ idim ] ) { \ - dim[ idim ] = hi[ idim ]; \ - off_in += stride[ idim ]; \ - wt[ idim ] = frac_hi[ idim ]; \ - break; \ -\ -/* Any earlier dimensions (referring to the higher index) are switched \ - back to the lower index, if not already there, before going on to \ - consider the next dimension. (This process is the same as \ - incrementing a binary number and propagating overflows up through \ - successive digits, except that dimensions where the "lo" and "hi" \ - values are the same can only take one value.) The process stops at \ - the first attempt to return the final dimension to the lower \ - index. */ \ - } else { \ - if ( dim[ idim ] != lo[ idim ] ) { \ - dim[ idim ] = lo[ idim ]; \ - off_in -= stride[ idim ]; \ - wt[ idim ] = frac_lo[ idim ]; \ - } \ - done = ( ++idim == ndim_in ); \ - } \ - } while ( !done ); \ - } while ( !done ); \ - } - -/* This subsidiary macro adds the contribution from a specified input - pixel to the accumulated sums for forming the linearly interpolated - value. */ -#define FORM_LINEAR_INTERPOLATION_SUM(off,wt,Xtype,Xfloattype,Xsigned, \ - Usebad,Usevar) \ -\ -/* Obtain the offset of the input pixel to use. */ \ - off_in = ( off ); \ -\ -/* If necessary, test if this pixel is bad. If not, then obtain the \ - weight to apply to it. */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ - pixwt = ( wt ); \ -\ -/* Increment the weighted sum of pixel values and the sum of weights. */ \ - sum += ( (Xfloattype) in[ off_in ] ) * ( (Xfloattype) pixwt ); \ - wtsum += (Xfloattype) pixwt; \ -\ -/* If an output variance estimate is to be generated, and it still \ - seems possible to produce one, then obtain the input variance \ - value. */ \ - if ( Usevar ) { \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - var = in_var[ off_in ]; \ -\ -/* Test if the variance value is bad (if the data type is signed, also \ - check that it is not negative). */ \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If OK, increment the weighted sum of variance values. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - sum_var += ( (Xfloattype) ( pixwt * pixwt ) ) * \ - ( (Xfloattype) var ); \ - } \ - } \ - } \ - } - -/* This subsidiary macro calculates the interpolated output value (and - variance) from the sums over contributing pixels and assigns them - to the output array(s). */ -#define CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Xsigned, \ - Usebad,Usevar,Nobad) \ -\ -/* Obtain the pixel offset into the output array. */ \ - off_out = offset[ point ]; \ -\ -/* Assign a bad output value (and variance) if required and count it. */ \ - if ( bad ) { \ - if( !Nobad ) { \ - out[ off_out ] = badval; \ - if ( Usevar ) out_var[ off_out ] = badval; \ - } \ - result++; \ -\ -/* Otherwise, calculate the interpolated value. If the output data \ - type is floating point, this result can be stored directly, \ - otherwise we must round to the nearest integer. */ \ - } else { \ - val = sum / wtsum; \ - if ( Xfloating ) { \ - out[ off_out ] = (Xtype) val; \ - } else { \ - out[ off_out ] = (Xtype) ( val + ( ( val >= (Xfloattype) 0.0 ) ? \ - ( (Xfloattype) 0.5 ) : \ - ( (Xfloattype) -0.5 ) ) ); \ - } \ -\ -/* If a variance estimate is required but none can be obtained, then \ - store a bad output variance value and count it. */ \ - if ( Usevar ) { \ - if ( ( ( Xsigned ) || ( Usebad ) ) && bad_var ) { \ - if( !Nobad ) out_var[ off_out ] = badval; \ - result++; \ -\ -/* Otherwise, calculate the variance estimate and store it, rounding \ - to the nearest integer if necessary. */ \ - } else { \ - val = sum_var / ( wtsum * wtsum ); \ - if ( Xfloating ) { \ - out_var[ off_out ] = (Xtype) val; \ - } else { \ - out_var[ off_out ] = (Xtype) ( val + \ - ( ( val >= (Xfloattype) 0.0 ) ? \ - ( (Xfloattype) 0.5 ) : \ - ( (Xfloattype) -0.5 ) ) ); \ - } \ - } \ - } \ - } - -/* This subsidiary macro tests for negative variance values in the - macros above. This check is required only for signed data types. */ -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ - bad_var = bad_var || ( var < ( (Xtype) 0 ) ); - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_LINEAR(LD,long double,1,long double,1) -MAKE_INTERPOLATE_LINEAR(L,long int,0,long double,1) -MAKE_INTERPOLATE_LINEAR(K,INT_BIG,0,long double,1) -#else -MAKE_INTERPOLATE_LINEAR(L,long int,0,double,1) -MAKE_INTERPOLATE_LINEAR(K,INT_BIG,0,double,1) -#endif -MAKE_INTERPOLATE_LINEAR(D,double,1,double,1) -MAKE_INTERPOLATE_LINEAR(F,float,1,float,1) -MAKE_INTERPOLATE_LINEAR(I,int,0,double,1) -MAKE_INTERPOLATE_LINEAR(S,short int,0,float,1) -MAKE_INTERPOLATE_LINEAR(B,signed char,0,float,1) - -/* Re-define the macro for testing for negative variances to do - nothing. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) - -/* Expand the main macro above to generate a function for each - required unsigned data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_LINEAR(UL,unsigned long int,0,long double,0) -MAKE_INTERPOLATE_LINEAR(UK,UINT_BIG,0,long double,0) -#else -MAKE_INTERPOLATE_LINEAR(UL,unsigned long int,0,double,0) -MAKE_INTERPOLATE_LINEAR(UK,UINT_BIG,0,double,0) -#endif -MAKE_INTERPOLATE_LINEAR(UI,unsigned int,0,double,0) -MAKE_INTERPOLATE_LINEAR(US,unsigned short int,0,float,0) -MAKE_INTERPOLATE_LINEAR(UB,unsigned char,0,float,0) - -/* Undefine the macros uxsed above. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#undef CALC_AND_ASSIGN_OUTPUT -#undef FORM_LINEAR_INTERPOLATION_SUM -#undef ASSEMBLE_INPUT_ND -#undef ASSEMBLE_INPUT_2D -#undef ASSEMBLE_INPUT_1D -#undef MAKE_INTERPOLATE_LINEAR - -/* -* Name: -* InterpolateNearest<X> - -* Purpose: -* Resample a data grid, using the nearest-pixel interpolation scheme. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int InterpolateNearest<X>( int ndim_in, -* const int *lbnd_in, const int *ubnd_in, -* const <Xtype> *in, const <Xtype> *in_var, -* int npoint, const int *offset, -* const double *const *coords, -* int flags, <Xtype> badval, -* <Xtype> *out, <Xtype> *out_var ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which resample a rectangular input -* grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. Each output -* grid point may be mapped on to a position in the input grid in -* an arbitrary way. Where the positions given do not correspond -* with a pixel centre in the input grid, the interpolation scheme -* used is simply to select the nearest pixel (i.e. the one whose -* bounds contain the supplied position). - -* Parameters: -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input grid, its extent along a particular -* (i'th) dimension being ubnd_in[i]-lbnd_in[i]+1 (assuming "i" -* is zero-based). They also define the input grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be resampled (with an element -* for each pixel in the input grid). The numerical type of -* these data should match the function used, as given by the -* suffix on the function name. The storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -* (i.e. Fortran array storage order). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* npoint -* The number of points at which the input grid is to be -* resampled. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each output point, this array should contain the zero-based -* offset in the output array(s) (i.e. the "out" and, -* optionally, the "out_var" arrays) at which the resampled -* output value(s) should be stored. -* coords -* An array of pointers to double, with "ndim_in" -* elements. Element "coords[coord]" should point at the first -* element of an array of double (with "npoint" elements) which -* contains the values of coordinate number "coord" for each -* interpolation point. The value of coordinate number "coord" -* for interpolation point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices to be -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding output data (and -* variance) will be set to the value given by "badval" (unles the -* AST__NOBAD flag is specified). -* flags -* The bitwise OR of a set of flag values which control the -* operation of the function. Currently, only the flag -* AST__USEBAD is significant and indicates whether there are -* "bad" (i.e. missing) data in the input array(s) which must be -* recognised and propagated to the output array(s). If this -* flag is not set, all input values are treated literally. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. Unles the AST__NOBAD flag is specified in "flags", the -* same value will also be used to flag any output array elements -* for which resampled values could not be obtained. The output -* arrays(s) may be flagged with this value whether or not the -* AST__USEBAD flag is set (the function return value indicates -* whether any such values have been produced). -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. Note -* that details of how the output grid maps on to this array -* (e.g. the storage order, number of dimensions, etc.) is -* arbitrary and is specified entirely by means of the "offset" -* array. The "out" array should therefore contain sufficient -* elements to accommodate the "offset" values supplied. There -* is no requirement that all elements of the "out" array should -* be assigned values, and any which are not addressed by the -* contents of the "offset" array will be left unchanged. -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. It is addressed in -* exactly the same way (via the "offset" array) as the "out" -* array. The values returned are estimates of the statistical -* variance of the corresponding values in the "out" array, on -* the assumption that all errors in input grid values (in the -* "in" array) are statistically independent and that their -* variance estimates (in the "in_var" array) may simply be -* summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. - -* Returned Value: -* The number of output grid points to which a data value (or a -* variance value if relevant) equal to "badval" has been assigned -* because no valid output value could be obtained. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -* - A value of zero will be returned if any of these functions is -* invoked with the global error status set, or if it should fail -* for any reason. -*/ -/* Define a macro to implement the function for a specific data - type. */ -#define MAKE_INTERPOLATE_NEAREST(X,Xtype,Xsigned) \ -static int InterpolateNearest##X( int ndim_in, \ - const int *lbnd_in, const int *ubnd_in, \ - const Xtype *in, const Xtype *in_var, \ - int npoint, const int *offset, \ - const double *const *coords, \ - int flags, Xtype badval, \ - Xtype *out, Xtype *out_var, int *status ) { \ -\ -/* Local Variables: */ \ - Xtype var; /* Variance value */ \ - double *xn_max; /* Pointer to upper limits array (n-d) */ \ - double *xn_min; /* Pointer to lower limits array (n-d) */ \ - double x; /* x coordinate value */ \ - double xmax; /* x upper limit */ \ - double xmin; /* x lower limit */ \ - double xn; /* Coordinate value (n-d) */ \ - double y; /* y coordinate value */ \ - double ymax; /* y upper limit */ \ - double ymin; /* y lower limit */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int idim; /* Loop counter for dimensions */ \ - int ix; /* Number of pixels offset in x direction */ \ - int ixn; /* Number of pixels offset (n-d) */ \ - int iy; /* Number of pixels offset in y direction */ \ - int nobad; /* Was the AST__NOBAD flag set? */ \ - int off_in; /* Pixel offset into input array */ \ - int off_out; /* Pixel offset into output array */ \ - int point; /* Loop counter for output points */ \ - int result; /* Returned result value */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int ystride; /* Stride along input grid y direction */ \ -\ -/* Initialise. */ \ - result = 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Initialise variables to avoid "used of uninitialised variable" \ - messages from dumb compilers. */ \ - bad = 0; \ - off_in = 0; \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - nobad = flags & AST__NOBAD; \ - usebad = flags & AST__USEBAD; \ - usevar = in_var && out_var; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_in == 1 ) { \ -\ -/* Calculate the coordinate limits of the input array. */ \ - xmin = (double) lbnd_in[ 0 ] - 0.5; \ - xmax = (double) ubnd_in[ 0 ] + 0.5; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,0,1) \ - } \ - } \ - } \ -\ -/* Four more cases as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_in == 2 ) { \ -\ -/* Calculate the stride along the y dimension of the input grid. */ \ - ystride = ubnd_in[ 0 ] - lbnd_in[ 0 ] + 1; \ -\ -/* Calculate the coordinate limits of the input array in each \ - dimension. */ \ - xmin = (double) lbnd_in[ 0 ] - 0.5; \ - xmax = (double) ubnd_in[ 0 ] + 0.5; \ - ymin = (double) lbnd_in[ 1 ] - 0.5; \ - ymax = (double) ubnd_in[ 1 ] + 0.5; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,0,1) \ - } \ - } \ - } \ -\ -/* Four more cases as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - xn_max = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - xn_min = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the input grid. */ \ - for ( s = 1, idim = 0; idim < ndim_in; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ -\ -/* Calculate the coordinate limits of the input grid in each \ - dimension. */ \ - xn_min[ idim ] = (double) lbnd_in[ idim ] - 0.5; \ - xn_max[ idim ] = (double) ubnd_in[ idim ] + 0.5; \ - } \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,0,1) \ - } \ - } \ - } \ -\ -/* Another 4 cases as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,0,0,0) \ - } \ - } \ - } \ - } \ - } \ -\ -/* Free the workspace. */ \ - stride = astFree( stride ); \ - xn_max = astFree( xn_max ); \ - xn_min = astFree( xn_min ); \ - } \ -\ -/* If an error has occurred, clear the returned result. */ \ - if ( !astOK ) result = 0; \ -\ -/* Return the result. */ \ - return result; \ -} - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 1-dimensional - case. */ -#define ASSEMBLE_INPUT_1D(X,Xtype,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the input grid, or is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If not, then obtain the offset within the input grid of the pixel \ - which contains the current point. */ \ - off_in = (int) floor( x + 0.5 ) - lbnd_in[ 0 ]; \ -\ -/* If necessary, test if the input pixel is bad. */ \ - if ( Usebad ) bad = ( in[ off_in ] == badval ); \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 2-dimensional - case. */ -#define ASSEMBLE_INPUT_2D(X,Xtype,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the input grid, or is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If not, then similarly obtain and test the y coordinate. */ \ - y = coords[ 1 ][ point ]; \ - bad = ( y < ymin ) || ( y >= ymax ) || ( y == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Obtain the offsets along each input grid dimension of the input \ - pixel which contains the current point. */ \ - ix = (int) floor( x + 0.5 ) - lbnd_in[ 0 ]; \ - iy = (int) floor( y + 0.5 ) - lbnd_in[ 1 ]; \ -\ -/* Calculate this pixel's offset from the start of the input array. */ \ - off_in = ix + ystride * iy; \ -\ -/* If necessary, test if the input pixel is bad. */ \ - if ( Usebad ) bad = ( in[ off_in ] == badval ); \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the n-dimensional - case. */ -#define ASSEMBLE_INPUT_ND(X,Xtype,Usebad,Usevar) \ -\ -/* Initialise the offset into the input array. Then loop to obtain \ - each coordinate associated with the current output point. */ \ - off_in = 0; \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate lies outside the input grid, or is bad. If \ - either is true, the corresponding output pixel value will be bad, \ - so give up on this point. */ \ - bad = ( xn < xn_min[ idim ] ) || ( xn >= xn_max[ idim ] ) || \ - ( xn == AST__BAD ); \ - if ( bad ) break; \ -\ -/* Obtain the offset along the current input grid dimension of the \ - input pixel which contains the current point. */ \ - ixn = (int) floor( xn + 0.5 ) - lbnd_in[ idim ]; \ -\ -/* Accumulate this pixel's offset from the start of the input \ - array. */ \ - off_in += ixn * stride[ idim ]; \ - } \ -\ -/* Once the required input pixel has been located, test if it is \ - bad, if necessary. */ \ - if ( Usebad ) bad = bad || ( in[ off_in ] == badval ); - -/* This subsidiary macro assigns the output value (and variance) to - the output array(s). */ -#define CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xsigned,Usebad,Usevar,Nobad) \ -\ -/* Obtain the pixel offset into the output array. */ \ - off_out = offset[ point ]; \ -\ -/* If the input data value is bad, assign a bad output value (and \ - variance, if required) and count it. */ \ - if ( bad ) { \ - if( !Nobad ) { \ - out[ off_out ] = badval; \ - if ( Usevar ) out_var[ off_out ] = badval; \ - } \ - result++; \ -\ -/* Otherwise, assign the value obtained from the input grid. */ \ - } else { \ - out[ off_out ] = in[ off_in ]; \ -\ -/* If required, obtain the associated variance value. If necessary, \ - test if it is bad (if the data type is signed, also check that it \ - is not negative). */ \ - if ( Usevar ) { \ - var = in_var[ off_in ]; \ - if ( Usebad ) bad = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If the variance value can be bad, and is, then store a bad value in \ - the output array and count it. Otherwise, store the variance \ - value. */ \ - if ( ( ( Xsigned ) || ( Usebad ) ) && bad ) { \ - if( !Nobad ) out_var[ off_out ] = badval; \ - result++; \ - } else { \ - out_var[ off_out ] = var; \ - } \ - } \ - } - -/* This subsidiary macro tests for negative variance values in the - macros above. This check is required only for signed data - types. */ -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ - bad = bad || ( var < ( (Xtype) 0 ) ); - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_NEAREST(LD,long double,1) -#endif -MAKE_INTERPOLATE_NEAREST(D,double,1) -MAKE_INTERPOLATE_NEAREST(F,float,1) -MAKE_INTERPOLATE_NEAREST(L,long int,1) -MAKE_INTERPOLATE_NEAREST(K,INT_BIG,1) -MAKE_INTERPOLATE_NEAREST(I,int,1) -MAKE_INTERPOLATE_NEAREST(S,short int,1) -MAKE_INTERPOLATE_NEAREST(B,signed char,1) - -/* Re-define the macro for testing for negative variances to do - nothing. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) - -/* Expand the main macro above to generate a function for each - required unsigned data type. */ -MAKE_INTERPOLATE_NEAREST(UK,UINT_BIG,0) -MAKE_INTERPOLATE_NEAREST(UL,unsigned long int,0) -MAKE_INTERPOLATE_NEAREST(UI,unsigned int,0) -MAKE_INTERPOLATE_NEAREST(US,unsigned short int,0) -MAKE_INTERPOLATE_NEAREST(UB,unsigned char,0) - -/* Undefine the macros used above. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#undef CALC_AND_ASSIGN_OUTPUT -#undef ASSEMBLE_INPUT_ND -#undef ASSEMBLE_INPUT_2D -#undef ASSEMBLE_INPUT_1D -#undef MAKE_INTERPOLATE_NEAREST - -/* -* Name: -* InterpolateBlockAverage<X> - -* Purpose: -* Resample a data grid, using multidimensional block averaging. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void InterpolateBlockAverage<X>( int ndim_in, -* const int lbnd_in[], -* const int ubnd_in[], -* const <Xtype> in[], -* const <Xtype> in_var[], -* int npoint, const int offset[], -* const double *const coords[], -* const double params[], int flags, -* <Xtype> badval, <Xtype> *out, -* <Xtype> *out_var, int *nbad ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which resample a rectangular input -* grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. To generate -* an output grid pixel, a block average is taken over an ndim- -* dimensional hypercube of pixels in the input grid. If variances -* are being used then the input pixels will be weighted according -* to the reciprocals of the corresponding variance values, and -* input pixels without a valid variance will be ignored; -* otherwise an unweighted average will be taken over -* all non-bad pixels in the cube. The size of the cube over which -* the average is taken is determined by the first element of the -* params array. -* -* This "interpolation" scheme is appropriate where an input grid -* is to be resampled onto a much coarser output grid. - -* Parameters: -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input grid, its extent along a particular -* (i'th) dimension being ubnd_in[i]-lbnd_in[i]+1 (assuming "i" -* is zero-based). They also define the input grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be resampled (with an element -* for each pixel in the input grid). The numerical type of -* these data should match the function used, as given by the -* suffix on the function name. The storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -* (i.e. Fortran array storage order). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* npoint -* The number of points at which the input grid is to be -* resampled. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each output point, this array should contain the zero-based -* offset in the output array(s) (i.e. the "out" and, -* optionally, the "out_var" arrays) at which the resampled -* output value(s) should be stored. -* coords -* An array of pointers to double, with "ndim_in" -* elements. Element "coords[coord]" should point at the first -* element of an array of double (with "npoint" elements) which -* contains the values of coordinate number "coord" for each -* interpolation point. The value of coordinate number "coord" -* for interpolation point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices to be -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding output data (and -* variance) will be set to the value given by "badval" (unles the -* AST__NOBAD flag is specified). -* params -* A pointer to an array of doubles giving further information -* about how the resampling is to proceed. Only the first -* element is significant; the nearest integer to this gives -* the number of pixels on either side of the central input -* grid pixel to use in each dimension. Therefore -* (1 + 2*params[0])**ndim_in pixels will be averaged over to -* generate each output pixel. -* flags -* The bitwise OR of a set of flag values which control the -* operation of the function. Currently, only the flag -* AST__USEBAD is significant and indicates whether there are -* "bad" (i.e. missing) data in the input array(s) which must be -* recognised and propagated to the output array(s). If this -* flag is not set, all input values are treated literally. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. Unles the AST__NOBAD flag is specified in "flags", the -* same value will also be used to flag any output array elements -* for which resampled values could not be obtained. The output -* arrays(s) may be flagged with this value whether or not the -* AST__USEBAD flag is set (the function return value indicates -* whether any such values have been produced). -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. Note -* that details of how the output grid maps on to this array -* (e.g. the storage order, number of dimensions, etc.) is -* arbitrary and is specified entirely by means of the "offset" -* array. The "out" array should therefore contain sufficient -* elements to accommodate the "offset" values supplied. There -* is no requirement that all elements of the "out" array should -* be assigned values, and any which are not addressed by the -* contents of the "offset" array will be left unchanged. -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. It is addressed in -* exactly the same way (via the "offset" array) as the "out" -* array. The values returned are estimates of the statistical -* variance of the corresponding values in the "out" array, on -* the assumption that all errors in input grid values (in the -* "in" array) are statistically independent and that their -* variance estimates (in the "in_var" array) may simply be -* summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* nbad -* Pointer to an int in which to return the number of -* interpolation points at which an output data value (and/or a -* variance value if relevant) equal to "badval" has been -* assigned because no valid interpolated value could be -* obtained. The maximum value that will be returned is -* "npoint" and the minimum is zero (indicating that all output -* values were successfully obtained). - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -*/ -/* Define a macro to implement the function for a specific data - type. */ -#define MAKE_INTERPOLATE_BLOCKAVE(X,Xtype,Xfloating,Xfloattype,Xsigned) \ -static void InterpolateBlockAverage##X( int ndim_in, \ - const int lbnd_in[], \ - const int ubnd_in[], \ - const Xtype in[], \ - const Xtype in_var[], \ - int npoint, const int offset[], \ - const double *const coords[], \ - const double params[], int flags, \ - Xtype badval, Xtype *out, \ - Xtype *out_var, int *nbad ) { \ -\ -/* Local Variables: */ \ - Xfloattype hi_lim; /* Upper limit on output values */ \ - Xfloattype lo_lim; /* Lower limit on output values */ \ - Xfloattype pixwt; /* Weight to apply to individual pixel */ \ - Xfloattype sum; /* Weighted sum of pixel data values */ \ - Xfloattype sum_var; /* Weighted sum of pixel variance values */ \ - Xfloattype val; /* Data value to be assigned to output */ \ - Xfloattype val_var; /* Variance to be assigned to output */ \ - Xfloattype wtsum; /* Sum of weight values */ \ - Xfloattype wtsum_sq; /* Square of sum of weights */ \ - Xtype var; /* Variance value */ \ - double *xn_max; /* Pointer to upper limits array (n-d) */ \ - double *xn_min; /* Pointer to lower limits array (n-d) */ \ - double x; /* x coordinate value */ \ - double xn; /* Coordinate value (n-d) */ \ - double y; /* y coordinate value */ \ - int *hi; /* Pointer to array of upper indices */ \ - int *ixm; /* Pointer to array of current indices */ \ - int *lo; /* Pointer to array of lower indices */ \ - int *status; /* Pointer to inherited status value */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int bad_var; /* Output variance bad? */ \ - int done; /* All pixel indices done? */ \ - int hi_x; /* Upper pixel index (x dimension) */ \ - int hi_y; /* Upper pixel index (y dimension) */ \ - int idim; /* Loop counter for dimensions */ \ - int ix; /* Pixel index in input grid x dimension */ \ - int ixn; /* Pixel index in input grid (n-d) */ \ - int iy; /* Pixel index in input grid y dimension */ \ - int lo_x; /* Lower pixel index (x dimension) */ \ - int lo_y; /* Lower pixel index (y dimension) */ \ - int neighb; /* Number of adjacent pixels on each side */ \ - int nobad; /* Was the AST__NOBAD flag set? */ \ - int off1; /* Input pixel offset due to y index */ \ - int off_in; /* Offset to input pixel */ \ - int off_out; /* Offset to output pixel */ \ - int point; /* Loop counter for output points */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int ystride; /* Stride along input grid y dimension */ \ -\ -/* Initialise. */ \ - *nbad = 0; \ -\ -/* Get a pointer to the inherited status argument. */ \ - status = astGetStatusPtr; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Initialise variables to avoid "used of uninitialised variable" \ - messages from dumb compilers. */ \ - val = 0; \ - val_var = 0; \ - sum_var = 0; \ - wtsum = 0; \ - bad = 0; \ - bad_var = 0; \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - nobad = flags & AST__NOBAD; \ - usebad = flags & AST__USEBAD; \ - usevar = in_var && out_var; \ -\ -/* Set the number of pixels each side of central pixel to use. */ \ - neighb = (int) floor( params[ 0 ] + 0.5 ); \ -\ -/* Set up limits for checking output values to ensure that they do not \ - overflow the range of the data type being used. */ \ - lo_lim = LO_##X; \ - hi_lim = HI_##X; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_in == 1 ) { \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,1) \ - } \ - } \ - } \ -\ -/* Another 4 cases as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_in == 2 ) { \ -\ -/* Calculate the stride along the y dimension of the input grid. */ \ - ystride = ubnd_in[ 0 ] - lbnd_in[ 0 ] + 1; \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,1) \ - } \ - } \ - } \ -\ -/* Another 4 cases as above, but without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,0) \ - } \ - } \ - } \ - } \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - hi = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - lo = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - ixm = astMalloc( sizeof( int ) * (size_t) ndim_in ); \ - xn_max = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - xn_min = astMalloc( sizeof( double ) * (size_t) ndim_in ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the input grid. */ \ - for ( s = 1, idim = 0; idim < ndim_in; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ -\ -/* Calculate the coordinate limits of the input grid in each \ - dimension. */ \ - xn_min[ idim ] = (double) lbnd_in[ idim ] - 0.5; \ - xn_max[ idim ] = (double) ubnd_in[ idim ] + 0.5; \ - } \ -\ -/* Identify four cases, according to whether bad pixels and/or \ - variances are being processed. In each case, loop through all the \ - output points to (a) assemble the input data needed to form the \ - interpolated value, and (b) calculate the result and assign it to \ - the output arrays(s). In each case we assign constant values (0 or \ - 1) to the "Usebad" and "Usevar" flags so that code for handling bad \ - pixels and variances can be eliminated when not required. */ \ - if ( nobad ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,1) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,1) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,1) \ - } \ - } \ - } \ -\ -/* Another 4 cases as above, but this time without the AST__NOBAD flag. */ \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,1,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,1,0,0) \ - } \ - } \ - } else { \ - if ( usevar ) { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,1) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,1,0) \ - } \ - } else { \ - for ( point = 0; point < npoint; point++ ) { \ - ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,0,0) \ - CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,0,0,0) \ - } \ - } \ - } \ - } \ - } \ -\ -/* Free the workspace. */ \ - hi = astFree( hi ); \ - lo = astFree( lo ); \ - stride = astFree( stride ); \ - ixm = astFree( ixm ); \ - xn_max = astFree( xn_max ); \ - xn_min = astFree( xn_min ); \ - } \ -\ -/* If an error has occurred, clear the returned result. */ \ - if ( !astOK ) *nbad = 0; \ -\ -/* Return. */ \ -} - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 1-dimensional - case. */ -#define ASSEMBLE_INPUT_1D(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x == AST__BAD ); \ -\ -/* Note we do not need to check here whether the pixel in this position is \ - bad; if any pixels in the cube are good we can form an average. */ \ -\ -/* If OK, calculate the lowest and highest indices (in the x \ - dimension) of the region of neighbouring pixels that will \ - contribute to the interpolated result. Constrain these values to \ - lie within the input grid. */ \ - if ( !bad ) { \ - ix = (int) floor( x ); \ - lo_x = MaxI( ix - neighb + 1, lbnd_in[ 0 ], status ); \ - hi_x = MinI( ix + neighb, ubnd_in[ 0 ], status ); \ -\ -/* Initialise sums for forming the interpolated result. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - bad_var = 0; \ - } \ -\ -/* Loop to inspect all the contributing pixels, calculating the offset \ - of each pixel from the start of the input array. */ \ - off_in = lo_x - lbnd_in[ 0 ]; \ - for ( ix = lo_x; ix <= hi_x; ix++, off_in++ ) { \ -\ -/* If necessary, test if the input pixel is bad. */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ -\ -/* If we are using variances, then check that the variance is valid; \ - if it is invalid then ignore this pixel altogether. */ \ - if ( Usevar ) { \ - var = in_var[ off_in ]; \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If variance is valid then accumulate suitably weighted values into \ - the totals. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - pixwt = (Xfloattype) 1.0 / var; \ - sum += pixwt * ( (Xfloattype) in[ off_in ] ); \ - wtsum += pixwt; \ - sum_var += pixwt; \ - } \ -\ -/* If we are not using variances, then accumulate values into the \ - totals with a weighting of unity. */ \ - } else { \ - sum += (Xfloattype) in[ off_in ]; \ - wtsum++; \ - } \ - } \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the 2-dimensional - case. */ -#define ASSEMBLE_INPUT_2D(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Obtain the x coordinate of the current point and test if it is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If not, then similarly obtain and test the y coordinate. */ \ - y = coords[ 1 ][ point ]; \ - bad = ( y == AST__BAD ); \ -\ -/* Note we do not need to check here whether the pixel in this position is \ - bad; if any pixels in the cube are good we can form an average. */ \ -\ -/* If OK, calculate the lowest and highest indices (in each dimension) \ - of the region of neighbouring pixels that will contribute to the \ - interpolated result. Constrain these values to lie within the input \ - grid. */ \ - if ( !bad ) { \ - ix = (int) floor( x ); \ - lo_x = MaxI( ix - neighb + 1, lbnd_in[ 0 ], status ); \ - hi_x = MinI( ix + neighb, ubnd_in[ 0 ], status ); \ - iy = (int) floor( y ); \ - lo_y = MaxI( iy - neighb + 1, lbnd_in[ 1 ], status ); \ - hi_y = MinI( iy + neighb, ubnd_in[ 1 ], status ); \ -\ -/* Initialise sums for forming the interpolated result. */ \ - sum = (Xfloattype) 0.0; \ - wtsum = (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - bad_var = 0; \ - } \ -\ -/* Loop to inspect all the contributing pixels, calculating the offset \ - of each pixel from the start of the input array. */ \ - off1 = lo_x - lbnd_in[ 0 ] + ystride * ( lo_y - lbnd_in[ 1 ] ); \ - for ( iy = lo_y; iy <= hi_y; iy++, off1 += ystride ) { \ - off_in = off1; \ - for ( ix = lo_x; ix <= hi_x; ix++, off_in++ ) { \ -\ -/* If necessary, test if the input pixel is bad. */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ -\ -/* If we are using variances, then check that the variance is valid; \ - if it is invalid then ignore this pixel altogether. */ \ - if ( Usevar ) { \ - var = in_var[ off_in ]; \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If variance is valid then accumulate suitably weighted values into \ - the totals. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - pixwt = (Xfloattype) 1.0 / var; \ - sum += pixwt * ( (Xfloattype) in[ off_in ] ); \ - wtsum += pixwt; \ - sum_var += pixwt; \ - } \ -\ -/* If we are not using variances, then accumulate values into the \ - totals with a weighting of unity. */ \ - } else { \ - sum += (Xfloattype) in[ off_in ]; \ - wtsum++; \ - } \ - } \ - } \ - } \ - } \ - } - -/* This subsidiary macro assembles the input data needed in - preparation for forming the interpolated value in the n-dimensional - case. */ -#define ASSEMBLE_INPUT_ND(X,Xtype,Xfloating,Xfloattype,Xsigned,Usebad,Usevar) \ -\ -/* Initialise offsets into the input array. then loop to obtain each \ - coordinate associated with the current output poitn. */ \ - off_in = 0; \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate is bad. If so give up on this point. */ \ - bad = ( xn == AST__BAD ); \ - if ( bad ) break; \ -\ -/* Calculate the lowest and highest indices (in the current dimension) \ - of the region of neighbouring pixels that will contribute to the \ - interpolated result. Constrain these values to lie within the input \ - grid. */ \ - ixn = (int) floor( xn ); \ - lo[ idim ] = MaxI( ixn - neighb + 1, lbnd_in[ idim ], status ); \ - hi[ idim ] = MinI( ixn + neighb, ubnd_in[ idim ], status ); \ -\ -/* If the cube has a zero dimension then no data can come from it. */ \ - bad = ( lo[ idim ] > hi[ idim ] ); \ - if ( bad ) break; \ -\ -/* Accumulate the offset (from the start of the input array) of the \ - contributing pixel which has the lowest index in each dimension. */ \ - off_in += stride[ idim ] * ( lo[ idim ] - lbnd_in[ idim ] ); \ -\ -/* Initialise an array to keep track of the current position in the \ - input cube. */ \ - ixm[ idim ] = lo[ idim ]; \ - } \ -\ -/* Note we do not need to check here whether the pixel in this position is \ - bad; if any pixels in the cube are good we can form an average. */ \ -\ -/* If OK, initialise sums for forming the interpolated result. */ \ - if ( !bad ) { \ - sum = (Xfloattype) 0.0; \ - wtsum= (Xfloattype) 0.0; \ - if ( Usevar ) { \ - sum_var = (Xfloattype) 0.0; \ - bad_var = 0; \ - } \ -\ -/* Loop to inspect all the contributing pixels, calculating the offset \ - of each pixel from the start of the input array. */ \ - do { \ -\ -/* If necessary, test if the input pixel is bad. */ \ - if ( !( Usebad ) || ( in[ off_in ] != badval ) ) { \ -\ -/* If we are using variances, then check that the variance is valid; \ - if it is invalid then ignore this pixel altogether. */ \ - if ( Usevar ) { \ - var = in_var[ off_in ]; \ - if ( Usebad ) bad_var = ( var == badval ); \ - CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ -\ -/* If variance is valid then accumulate suitably weighted values into \ - the totals. */ \ - if ( !( ( Xsigned ) || ( Usebad ) ) || !bad_var ) { \ - pixwt = (Xfloattype) 1.0 / var; \ - sum += pixwt * ( (Xfloattype) in[ off_in ] ); \ - wtsum += pixwt; \ - sum_var += pixwt; \ - } \ -\ -/* If we are not using variances, then accumulate values into the \ - totals with a weighting of unity. */ \ - } else { \ - sum += (Xfloattype) in[ off_in ]; \ - wtsum++; \ - } \ - } \ -\ -/* Locate the next pixel in the input cube; try incrementing the lowest \ - dimension index first, if that rolls over increment the next \ - dimension index, and so on. */ \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - if ( ixm[ idim ] < hi[ idim ] ) { \ - off_in += stride[ idim ]; \ - ixm[ idim ]++; \ - break; \ - } else { \ - off_in -= stride[ idim ] * ( hi[ idim ] - lo[ idim ] ); \ - ixm[ idim ] = lo[ idim ]; \ - } \ - } \ -\ -/* If the highest dimension index has rolled over, we have done all \ - the pixels in the cube. */ \ - done = ( idim == ndim_in ); \ - } while ( !done ); \ - } - -/* This subsidiary macro calculates the interpolated output value (and - variance) from the sums over contributing pixels, checks the - results for validity, and assigns them to the output array(s). */ -#define CALC_AND_ASSIGN_OUTPUT(X,Xtype,Xfloating,Xfloattype,Usebad,Usevar,Nobad) \ -\ -/* If the output data value has not yet been flagged as bad, then \ - check that an interpolated value can actually be produced. First \ - check that the sum of weights is not zero. */ \ - if ( !bad ) { \ - bad = ( wtsum == (Xfloattype) 0.0 ); \ -\ -/* If OK, calculate the interpolated value. Then, if the output data \ - type is not floating point, check that this value will not overflow \ - the available output range. */ \ - if ( !bad ) { \ - val = sum / wtsum; \ - if ( !( Xfloating ) ) { \ - bad = ( val <= lo_lim ) || ( val >= hi_lim ); \ - } \ - } \ -\ -/* If no interpolated data value can be produced, then no associated \ - variance will be required either. */ \ - if ( ( Usevar ) && bad ) bad_var = 1; \ - } \ -\ -/* Now perform similar checks on the output variance value (if \ - required). This time we check that the square of the sum of \ - weights is not zero (since this might underflow before the sum of \ - weights). Again we also check to prevent the result overflowing the \ - output data type. */ \ - if ( ( Usevar ) && !bad_var ) { \ - wtsum_sq = wtsum * wtsum; \ - bad_var = ( wtsum_sq == (Xfloattype) 0.0 ); \ - if ( !bad_var ) { \ - val_var = sum_var / wtsum_sq; \ - if ( !( Xfloating ) ) { \ - bad_var = ( val_var <= lo_lim ) || ( val_var >= hi_lim ); \ - } \ - } \ - } \ -\ -/* Obtain the pixel offset into the output array. */ \ - off_out = offset[ point ]; \ -\ -/* Assign a bad output value (and variance) if required and count it. */ \ - if ( bad ) { \ - if( !Nobad ) { \ - out[ off_out ] = badval; \ - if ( Usevar ) out_var[ off_out ] = badval; \ - } \ - (*nbad)++; \ -\ -/* Otherwise, assign the interpolated value. If the output data type \ - is floating point, the result can be stored directly, otherwise we \ - must round to the nearest integer. */ \ - } else { \ - if ( Xfloating ) { \ - out[ off_out ] = (Xtype) val; \ - } else { \ - out[ off_out ] = (Xtype) ( val + ( ( val >= (Xfloattype) 0.0 ) ? \ - ( (Xfloattype) 0.5 ) : \ - ( (Xfloattype) -0.5 ) ) ); \ - } \ -\ -/* If a variance estimate is required but none can be obtained, then \ - store a bad output variance value and count it. */ \ - if ( Usevar ) { \ - if ( bad_var ) { \ - if( !Nobad ) out_var[ off_out ] = badval; \ - (*nbad)++; \ -\ -/* Otherwise, store the variance estimate, rounding to the nearest \ - integer if necessary. */ \ - } else { \ - if ( Xfloating ) { \ - out_var[ off_out ] = (Xtype) val_var; \ - } else { \ - out_var[ off_out ] = (Xtype) ( val_var + \ - ( ( val_var >= (Xfloattype) 0.0 ) ? \ - ( (Xfloattype) 0.5 ) : \ - ( (Xfloattype) -0.5 ) ) ); \ - } \ - } \ - } \ - } - -/* These subsidiary macros define limits for range checking of results - before conversion to the final data type. For each data type code - <X>, HI_<X> gives the least positive floating point value which - just overflows that data type towards plus infinity, while LO_<X> - gives the least negative floating point value which just overflows - that data type towards minus infinity. Thus, a floating point value - must satisfy LO<flt_value<HI if overflow is not to occur when it is - converted to that data type. - - The data type of each limit should be that of the smallest - precision floating point type which will accommodate the full range - of values that the target type may take. */ - -/* If <X> is a floating point type, the limits are not actually used, - but must be present to permit error-free compilation. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -#define HI_LD ( 0.0L ) -#define LO_LD ( 0.0L ) -#endif -#define HI_D ( 0.0 ) -#define LO_D ( 0.0 ) -#define HI_F ( 0.0f ) -#define LO_F ( 0.0f ) - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -#define HI_L ( 0.5L + (long double) LONG_MAX ) -#define LO_L ( -0.5L + (long double) LONG_MIN ) -#define HI_UL ( 0.5L + (long double) ULONG_MAX ) -#define LO_UL ( -0.5L ) -#define HI_K ( 0.5L + (long double) LONG_MAX ) -#define LO_K ( -0.5L + (long double) LONG_MIN ) -#define HI_UK ( 0.5L + (long double) ULONG_MAX ) -#define LO_UK ( -0.5L ) -#else -#define HI_L ( 0.5 + (double) LONG_MAX ) -#define LO_L ( -0.5 + (double) LONG_MIN ) -#define HI_UL ( 0.5 + (double) ULONG_MAX ) -#define LO_UL ( -0.5 ) -#define HI_K ( 0.5 + (double) LONG_MAX ) -#define LO_K ( -0.5 + (double) LONG_MIN ) -#define HI_UK ( 0.5 + (double) ULONG_MAX ) -#define LO_UK ( -0.5 ) -#endif -#define HI_I ( 0.5 + (double) INT_MAX ) -#define LO_I ( -0.5 + (double) INT_MIN ) -#define HI_UI ( 0.5 + (double) UINT_MAX ) -#define LO_UI ( -0.5 ) -#define HI_S ( 0.5f + (float) SHRT_MAX ) -#define LO_S ( -0.5f + (float) SHRT_MIN ) -#define HI_US ( 0.5f + (float) USHRT_MAX ) -#define LO_US ( -0.5f ) -#define HI_B ( 0.5f + (float) SCHAR_MAX ) -#define LO_B ( -0.5f + (float) SCHAR_MIN ) -#define HI_UB ( 0.5f + (float) UCHAR_MAX ) -#define LO_UB ( -0.5f ) - -/* This subsidiary macro tests for negative variance values. This - check is required only for signed data types. */ -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) \ - bad_var = bad_var || ( var < ( (Xtype) 0 ) ); - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_BLOCKAVE(LD,long double,1,long double,1) -MAKE_INTERPOLATE_BLOCKAVE(L,long int,0,long double,1) -MAKE_INTERPOLATE_BLOCKAVE(K,INT_BIG,0,long double,1) -#else -MAKE_INTERPOLATE_BLOCKAVE(L,long int,0,double,1) -MAKE_INTERPOLATE_BLOCKAVE(K,INT_BIG,0,double,1) -#endif -MAKE_INTERPOLATE_BLOCKAVE(D,double,1,double,1) -MAKE_INTERPOLATE_BLOCKAVE(F,float,1,float,1) -MAKE_INTERPOLATE_BLOCKAVE(I,int,0,double,1) -MAKE_INTERPOLATE_BLOCKAVE(S,short int,0,float,1) -MAKE_INTERPOLATE_BLOCKAVE(B,signed char,0,float,1) - -/* Re-define the macro for testing for negative variances to do - nothing. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#define CHECK_FOR_NEGATIVE_VARIANCE(Xtype) - -/* Expand the main macro above to generate a function for each - required unsigned data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_INTERPOLATE_BLOCKAVE(UL,unsigned long int,0,long double,0) -MAKE_INTERPOLATE_BLOCKAVE(UK,UINT_BIG,0,long double,0) -#else -MAKE_INTERPOLATE_BLOCKAVE(UL,unsigned long int,0,double,0) -MAKE_INTERPOLATE_BLOCKAVE(UK,UINT_BIG,0,double,0) -#endif -MAKE_INTERPOLATE_BLOCKAVE(UI,unsigned int,0,double,0) -MAKE_INTERPOLATE_BLOCKAVE(US,unsigned short int,0,float,0) -MAKE_INTERPOLATE_BLOCKAVE(UB,unsigned char,0,float,0) - -/* Undefine the macros used above. */ -#undef CHECK_FOR_NEGATIVE_VARIANCE -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -#undef HI_LD -#undef LO_LD -#endif -#undef HI_D -#undef LO_D -#undef HI_F -#undef LO_F -#undef HI_L -#undef LO_L -#undef HI_UL -#undef LO_UL -#undef HI_K -#undef LO_K -#undef HI_UK -#undef LO_UK -#undef HI_I -#undef LO_I -#undef HI_UI -#undef LO_UI -#undef HI_S -#undef LO_S -#undef HI_US -#undef LO_US -#undef HI_B -#undef LO_B -#undef HI_UB -#undef LO_UB -#undef CALC_AND_ASSIGN_OUTPUT -#undef ASSEMBLE_INPUT_ND -#undef ASSEMBLE_INPUT_2D -#undef ASSEMBLE_INPUT_1D -#undef MAKE_INTERPOLATE_BLOCKAVE - - -static void Invert( AstMapping *this, int *status ) { -/* -*++ -* Name: -c astInvert -f AST_INVERT - -* Purpose: -* Invert a Mapping. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astInvert( AstMapping *this ) -f CALL AST_INVERT( THIS, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function inverts a Mapping by reversing the boolean sense -f This routine inverts a Mapping by reversing the boolean sense -* of its Invert attribute. If this attribute is zero (the -* default), the Mapping will transform coordinates in the way -* specified when it was created. If it is non-zero, the input and -* output coordinates will be inter-changed so that the direction -* of the Mapping is reversed. This will cause it to display the -* inverse of its original behaviour. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping. -f STATUS = INTEGER (Given and Returned) -f The global status. -*-- -*/ - -/* Local Variables: */ - int invert; /* New Invert attribute value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Determine the new Invert attribute value. */ - invert = !astGetInvert( this ); - -/* Clear the old value. */ - astClearInvert( this ); - -/* If the resulting default value is not the one required, then set a - new value explicitly. */ - if ( astGetInvert( this ) != invert ) astSetInvert( this, invert ); -} - -static double J1Bessel( double x, int *status ) { -/* -* Name: -* J1Bessel - -* Purpose: -* Calculates the first-order Bessel function of the first kind. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double J1Bessel( double x, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of the first-order Bessel function -* of the first kind. - -* Parameters: -* x -* The argument for J1. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The calculated J1(x) value. - -* Notes: -* - The algorithm is taken from the SCUBA routine SCULIB_BESSJ1, by -* J.Lightfoot. -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - static double p1 = 1.0; - static double p2 = 0.183105E-2; - static double p3 = -0.3516396496E-4; - static double p4 = 0.2457520174E-5; - static double p5 = -0.240337019E-6; - - static double q1 = 0.04687499995; - static double q2 = -0.2002690873E-3; - static double q3 = 0.8449199096E-5; - static double q4 = -0.88228987E-6; - static double q5 = 0.105787412E-6; - - static double r1 = 72362614232.0; - static double r2 = -7895059235.0; - static double r3 = 242396853.1; - static double r4 = -2972611.439; - static double r5 = 15704.48260; - static double r6 = -30.16036606; - - static double s1 = 144725228442.0; - static double s2 = 2300535178.0; - static double s3 = 18583304.74; - static double s4 = 99447.43394; - static double s5 = 376.9991397; - static double s6 = 1.0; - - double ax; - double xx; - double z; - double y; - double value; - int s; - -/* Calculate the value */ - ax = fabs( x ); - if( ax < 8.0 ) { - y = x*x; - value = x*( r1 + y*( r2 + y*( r3 + y*( r4 + y*( r5 + y*r6 ) ) ) ) ) / - ( s1 + y*( s2 + y*( s3 + y*( s4 + y*( s5 + y*s6 ) ) ) ) ); - } else { - s = ( x >= 0.0 ) ? 1 : -1; - z = 8.0 / ax; - y = z*z; - xx = ax - 2.356194491; - value = sqrt ( 0.636619772/ax )*( cos( xx )*( p1 + y*( p2 + y* - ( p3 + y*( p4 + y*p5 ) ) ) )-z*sin( xx )*( q1 + y*( q2 + y*( q3 + y* - ( q4 + y*q5 ) ) ) ) )*s; - } - - return value; - -} - -static int LinearApprox( AstMapping *this, const double *lbnd, - const double *ubnd, double tol, double *fit, int *status ) { -/* -*++ -* Name: -c astLinearApprox -f AST_LINEARAPPROX - -* Purpose: -* Obtain a linear approximation to a Mapping, if appropriate. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c int astLinearApprox( AstMapping *this, const double *lbnd, -c const double *ubnd, double tol, double *fit ) -f RESULT = AST_LINEARAPPROX( THIS, LBND, UBND, TOL, FIT, STATUS ) - -* Class Membership: -* Mapping function. - -* Description: -* This function tests the forward coordinate transformation -* implemented by a Mapping over a given range of input coordinates. If -* the transformation is found to be linear to a specified level of -* accuracy, then an array of fit coefficients is returned. These -* may be used to implement a linear approximation to the Mapping's -* forward transformation within the specified range of output coordinates. -* If the transformation is not sufficiently linear, no coefficients -* are returned. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping. -c lbnd -f LBND( * ) = DOUBLE PRECISION (Given) -c Pointer to an array of doubles -f An array -* containing the lower bounds of a box defined within the input -* coordinate system of the Mapping. The number of elements in this -* array should equal the value of the Mapping's Nin attribute. This -* box should specify the region over which linearity is required. -c ubnd -f UBND( * ) = DOUBLE PRECISION (Given) -c Pointer to an array of doubles -f An array -* containing the upper bounds of the box specifying the region over -* which linearity is required. -c tol -f TOL = DOUBLE PRECISION (Given) -* The maximum permitted deviation from linearity, expressed as -* a positive Cartesian displacement in the output coordinate -* space of the Mapping. If a linear fit to the forward -* transformation of the Mapping deviates from the true transformation -* by more than this amount at any point which is tested, then no fit -* coefficients will be returned. -c fit -f FIT( * ) = DOUBLE PRECISION (Returned) -c Pointer to an array of doubles -f An array -* in which to return the co-efficients of the linear -* approximation to the specified transformation. This array should -* have at least "( Nin + 1 ) * Nout", elements. The first Nout elements -* hold the constant offsets for the transformation outputs. The -* remaining elements hold the gradients. So if the Mapping has 2 inputs -* and 3 outputs the linear approximation to the forward transformation -* is: -* -c X_out = fit[0] + fit[3]*X_in + fit[4]*Y_in -f X_out = fit(1) + fit(4)*X_in + fit(5)*Y_in -* -c Y_out = fit[1] + fit[5]*X_in + fit[6]*Y_in -f Y_out = fit(2) + fit(6)*X_in + fit(7)*Y_in -* -c Z_out = fit[2] + fit[7]*X_in + fit[8]*Y_in -f Z_out = fit(3) + fit(8)*X_in + fit(9)*Y_in -* -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astLinearApprox() -f AST_LINEARAPPROX = LOGICAL -* If the forward transformation is sufficiently linear, -c a non-zero value is returned. Otherwise zero is returned -f .TRUE is returned. Otherwise .FALSE. is returned -* and the fit co-efficients are set to AST__BAD. - -* Notes: -* - This function fits the Mapping's forward transformation. To fit -* the inverse transformation, the Mapping should be inverted using -c astInvert -f AST_INVERT -* before invoking this function. -* - If a Mapping output is found to have a bad value (AST__BAD) at -* one or more of the test points used in the linearity test, then all -* the values in the returned fit that correspond to that output are -* set to AST__BAD. However, this does not affect the linearity tests -* on the other Mapping outputs - if they are all found to be linear -* then usable coefficients will be returned for them in the fit, and -* the function will return a -c non-zero value. -f .TRUE. value. -* Consequently, it may be necessary to check that the values in the -* returned fit are not AST__BAD before using them. If all Mapping -* outputs generate bad values, then -c zero is returned as the function value. -f .FALSE. is returned as the function value. -c - A value of zero -f - A value of .FALSE. -* will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -* - If all tested positions within the supplied box generate bad -* output positions, then the returned function value will be -c zero. -f .FALSE. -* However, the returned coefficients will represent a unit -* transformation, except that the constant term for each output -* will be set to AST__BAD. - -*-- - -* Implementation Deficiencies: -* Sub-classes which implement linear mappings should probably -* over-ride this function to get better accuracy and faster execution, -* but currently they do not. - -*/ - -/* Local Variables: */ - AstPointSet *pset_in_f; /* PointSet for input fitting points */ - AstPointSet *pset_in_t; /* PointSet for input test points */ - AstPointSet *pset_out_f; /* PointSet for output fitting points */ - AstPointSet *pset_out_t; /* PointSet for output test points */ - double **ptr_in_f; /* Input coordinate array pointers */ - double **ptr_in_t; /* Input coordinate array pointers */ - double **ptr_out_f; /* Output coordinate array pointers */ - double **ptr_out_t; /* Output coordinate array pointers */ - double *grad; /* Pointer to matrix of gradients */ - double *zero; /* Pointer to array of zero point values */ - double diff; /* Difference in coordinate values */ - double err; /* Sum of squared error */ - double frac; /* Fraction of input coordinate range */ - double in1; /* Input coordinate value */ - double in2; /* Input coordinate value */ - double indiff; /* Difference in input coordinate values */ - double out1; /* Output coordinate value */ - double out2; /* Output coordinate value */ - double x0; /* Coordinate of grid centre */ - double y; /* Output coordinate (transformed) */ - double yfit; /* Coordinate resulting from fit */ - double z; /* Sum for calculating zero points */ - int *vertex; /* Pointer to flag array for vertices */ - int bad_output; /* Does the Mapping output generate bad values? */ - int coord_in; /* Loop counter for input coordinates */ - int coord_out; /* Loop counter for output coordinates. */ - int done; /* All vertices visited? */ - int face1; /* Index of first face coordinates */ - int face2; /* Index of second face coordinates */ - int face; /* Loop counter for faces */ - int ii; /* Index into gradient matrix */ - int linear; /* Mapping is linear? */ - int nc; /* Number of coeffs in fit */ - int ndim_in; /* Number of Mapping inputs */ - int ndim_out; /* Number of Mapping outputs */ - int npoint; /* Number of test points required */ - int point; /* Counter for points */ - int result; /* Returned flag */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialisation. */ - linear = 1; - grad = NULL; - zero = NULL; - -/* Get the number of Mapping output and inputs. */ - ndim_in = astGetNin( this ); - ndim_out = astGetNout( this ); - -/* Store the number of coefficients in the fit.*/ - nc = ( ndim_in + 1 ) * ndim_out; - -/* Initialise the supplied array to hold bad values. */ - for( ii = 0; ii < nc; ii++ ) fit[ ii ] = AST__BAD; - -/* Create a PointSet to hold input coordinates and obtain a pointer - to its coordinate arrays. */ - pset_in_f = astPointSet( 2 * ndim_in, ndim_in, "", status ); - ptr_in_f = astGetPoints( pset_in_f ); - if ( astOK ) { - -/* Set up and transform an initial set of points. */ -/* ---------------------------------------------- */ -/* Loop to set up input coordinates at the centre of each face of the - input grid, storing them in the PointSet created above. */ - point = 0; - for ( face = 0; face < ( 2 * ndim_in ); face++ ) { - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - ptr_in_f[ coord_in ][ point ] = - 0.5 * ( lbnd[ coord_in ] + ubnd[ coord_in ] ); - } - ptr_in_f[ face / 2 ][ point ] = ( face % 2 ) ? - ubnd[ face / 2 ] : lbnd[ face / 2 ]; - point++; - } - } - -/* Transform these coordinates into the output grid's coordinate system - and obtain an array of pointers to the resulting coordinate - data. */ - pset_out_f = astTransform( this, pset_in_f, 1, NULL ); - ptr_out_f = astGetPoints( pset_out_f ); - if ( astOK ) { - -/* Fit a linear approximation to the points. */ -/* ----------------------------------------- */ -/* Obtain pointers to the locations in the fit coefficients array - where the gradients and zero points should be stored. */ - grad = fit + ndim_out; - zero = fit; - -/* On the assumption that the transformation applied above is - approximately linear, loop to determine the matrix of gradients and - the zero points which describe it. */ - ii = 0; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - bad_output = 0; - z = 0.0; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - -/* Find the indices of opposite faces in each input dimension. */ - face1 = 2 * coord_in; - face2 = face1 + 1; - -/* Obtain the input and output coordinates at these face centres. */ - in1 = ptr_in_f[ coord_in ][ face1 ]; - in2 = ptr_in_f[ coord_in ][ face2 ]; - out1 = ptr_out_f[ coord_out ][ face1 ]; - out2 = ptr_out_f[ coord_out ][ face2 ]; - -/* Check whether any transformed coordinates are bad. Mapping outputs - that are bad at one or more test points have bad values stored for the - corresponding coefficients in the returned fit, but do not invalidate - the linearity of the fit to other outputs. */ - if ( ( out1 == AST__BAD ) || ( out2 == AST__BAD ) ) { - bad_output = 1; - break; - } - -/* If possible, determine the gradient along this dimension, storing - it in the appropriate element of the gradient matrix. */ - indiff = in2 - in1; - if ( indiff != 0.0 ) { - grad[ ii++ ] = ( out2 - out1 ) / indiff; - } else { - grad[ ii++ ] = 0.0; - } - -/* Accumulate the sum used to determine the zero point. */ - z += ( out1 + out2 ); - } - -/* Determine the average zero point from all dimensions. */ - if( !bad_output ) zero[ coord_out ] = z / (double) ( 2 * ndim_in ); - } - -/* The zero points of the above fit will be appropriate to an input - coordinate system with an origin at the centre of the input grid - (we assume this to simplify the calculations above). To correct - for this, we transform the actual input coordinates of the - grid's centre through the matrix of gradients and subtract the - resulting coordinates from the zero point values. The zero points - are then correct for the actual output and input coordinate systems - we are using. Also, if all Mapping outputs generate bad values, flag - that we do not have a linear fit. */ - linear = 0; - ii = 0; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - if( zero[ coord_out ] != AST__BAD ) { - linear = 1; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - x0 = 0.5 * ( lbnd[ coord_in ] + ubnd[ coord_in ] ); - zero[ coord_out ] -= grad[ ii++ ] * x0; - } - } else { - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - grad[ ii++ ] = AST__BAD; - } - } - } - } - -/* Annul the pointers to the PointSets used above. */ - pset_out_f = astAnnul( pset_out_f ); - pset_in_f = astAnnul( pset_in_f ); - -/* Calculate the number of test points required. */ -/* --------------------------------------------- */ -/* The linear fit obtained above, will (by construction) be exact - at the centre of each face of the input grid. However, it may - not fit anywhere else. We therefore set up some test points to - determine if it is an adequate approximation elsewhere. */ - if( astOK && linear ) { - -/* Calculate the number of test points required to place one at each - vertex of the grid. */ - npoint = 1; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - npoint *= 2; - } - -/* Now calculate the total number of test points required, also - allowing one at the centre, one at half the distance to each face, - and one at half the distance to each vertex. */ - npoint = 1 + 2 * ( ndim_in + npoint ); - -/* Set up test points in the input coordinate system. */ -/* --------------------------------------------------- */ -/* Create a PointSet to hold the test coordinates and obtain an array - of pointers to its coordinate data. */ - pset_in_t = astPointSet( npoint, ndim_in, "", status ); - ptr_in_t = astGetPoints( pset_in_t ); - if ( astOK ) { - -/* If the input array is 1-dimensional, the face and vertex positions - calculated below will co-incide. Therefore, we simply distribute - the required number of test points uniformly throughout the input - coordinate range (avoiding the end-points, where the fit has been - obtained). The coordinates are stored in the PointSet created - above. */ - if ( ndim_in == 1 ) { - for ( point = 0; point < npoint; point++ ) { - frac = ( (double) ( point + 1 ) ) / (double) ( npoint + 1 ); - ptr_in_t[ 0 ][ point ] = ( 1.0 - frac ) * lbnd[ 0 ] + - frac * ubnd[ 0 ]; - } - -/* Otherwise, generate one point at the grid centre (offset slightly - since the exact centre may not be very representative). */ - } else { - point = 0; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - ptr_in_t[ coord_in ][ point ] = - 0.49 * lbnd[ coord_in ] + 0.51 * ubnd[ coord_in ]; - } - point++; - -/* Similarly generate a point half way between the grid centre and the - centre of each face. Again introduce some small random offsets to break - any regularity in the grid. */ - for ( face = 0; face < ( 2 * ndim_in ); face++ ) { - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - ptr_in_t[ coord_in ][ point ] = - 0.48 * lbnd[ coord_in ] + 0.52 * ubnd[ coord_in ]; - } - ptr_in_t[ face / 2 ][ point ] = - ( 0.51 * ( ( ( face % 2 ) ? ubnd[ face / 2 ] : - lbnd[ face / 2 ] ) ) + - 0.49 * ptr_in_t[ face / 2 ][ 0 ] ); - point++; - } - -/* Allocate workspace and initialise flags for identifying the - vertices. */ - vertex = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - vertex[ coord_in ] = 0; - } - -/* Now loop to visit each input grid vertex. */ - done = 0; - do { - -/* Generate a test point at each vertex. */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - ptr_in_t[ coord_in ][ point ] = vertex[ coord_in ] ? - ubnd[ coord_in ] : - lbnd[ coord_in ]; - -/* Also place one half way between the grid centre and each vertex. */ - ptr_in_t[ coord_in ][ point + 1 ] = - ( 0.52 * ptr_in_t[ coord_in ][ point ] + - 0.48 * ptr_in_t[ coord_in ][ 0 ] ); - } - point += 2; - -/* Now update the array of vertex flags to identify the next vertex. */ - coord_in = 0; - do { - -/* The least significant dimension which does not have its upper bound - as one of the vertex coordinates is changed to use its upper bound - in the next vertex. */ - if ( !vertex[ coord_in ] ) { - vertex[ coord_in ] = 1; - break; - -/* Any less significant dimensions whose upper bounds are already - being used are changed to use their lower bounds in the next - vertex. */ - } else { - vertex[ coord_in ] = 0; - -/* All vertices have been visited when the most significant dimension - is changed back to using its lower bound. */ - done = ( ++coord_in == ndim_in ); - } - } while ( !done ); - } while ( !done ); - } - -/* Free the workspace used for vertex flags. */ - vertex = astFree( vertex ); - } - -/* Transform the test points. */ -/* -------------------------- */ -/* Use the Mapping to transform the test points into the output grid's - coordinate system, obtaining a pointer to the resulting arrays of - output coordinates. */ - pset_out_t = astTransform( this, pset_in_t, 1, NULL ); - ptr_out_t = astGetPoints( pset_out_t ); - -/* Test the linear fit for accuracy. */ -/* --------------------------------- */ -/* If OK so far, then loop to use this fit to transform each test - point and compare the result with the result of applying the - Mapping. */ - if ( astOK ) { - for ( point = 0; point < npoint; point++ ) { - -/* Initialise the fitting error for the current point. */ - err = 0.0; - -/* Obtain each output coordinate (produced by using the Mapping) in - turn and check that it is not bad. If it is, then store bad values for - the output's coefficients and pass on to the next output. */ - bad_output = 0; - ii = 0; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - y = ptr_out_t[ coord_out ][ point ]; - if ( y == AST__BAD || zero[ coord_out ] == AST__BAD ) { - zero[ coord_out ] = AST__BAD; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - grad[ ii++ ] = AST__BAD; - } - bad_output++; - break; - } - -/* Apply the fitted transformation to the input coordinates to obtain - the approximate output coordinate value. */ - yfit = zero[ coord_out ]; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - yfit += grad[ ii++ ] * ptr_in_t[ coord_in ][ point ]; - } - -/* Form the sum of squared differences between the Mapping's - transformation and the fit. */ - diff = ( y - yfit ); - err += diff * diff; - } - -/* Test if the Cartesian distance between the true output coordinate - and the approximate one exceeds the accuracy tolerance. If this - happens for any test point, we declare the Mapping non-linear and - give up. Reduce the allowed tolerance in proproprtion to the number of - bad Mapping outputs that were found. */ - if ( sqrt( err ) > (tol*(ndim_out - bad_output))/ndim_out ) { - linear = 0; - break; - } - } - } - -/* Annul the pointers to the PointSets used above. */ - pset_out_t = astAnnul( pset_out_t ); - } - pset_in_t = astAnnul( pset_in_t ); - -/* If all Mapping outputs generate bad values, return the coefficients of - a unit transformation, but put a bad value into the constant term for each - output. */ - } else if( astOK ){ - grad = fit + ndim_out; - zero = fit; - - ii = 0; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - if ( coord_out == coord_in ) { - grad[ ii++ ] = 1.0; - } else { - grad[ ii++ ] = 0.0; - } - } - zero[ coord_out ] = AST__BAD; - } - } - -/* If an error occurred, or the Mapping was found to be non-linear, - then set the coefficients to AST_BAD. Otherwise, set the returned flag - to indicate that the fit was succesful. */ - if ( !astOK || !linear ) { - for( ii = 0; ii < nc; ii++ ) fit[ ii ] = AST__BAD; - } else { - result = 1; - } - -/* Return the result. */ - return result; -} - -static double LocalMaximum( const MapData *mapdata, double acc, double fract, - double x[], int *status ) { -/* -* Name: -* LocalMaximum - -* Purpose: -* Find a local maximum in a Mapping function. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double LocalMaximum( const MapData *mapdata, double acc, double fract, -* double x[], int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function finds a local maximum in the Mapping function -* supplied. It employs the modified simplex method (as -* implemented by UphillSimplex), but repeatedly re-starts the -* simplex algorithm and tests for convergence of successive -* maxima, so as to further improve robustness on difficult -* problems. - -* Parameters: -* mapdata -* Pointer to a MapData structure describing the Mapping -* function, its coordinate constraints, etc. -* acc -* The required accuracy with which the maximum is to be found. -* fract -* A value between 0.0 and 1.0 which determines the initial step -* length along each coordinate axis. It should be given as a -* fraction of the difference between the upper and lower -* constraint values for each axis (as specified in the -* "mapdata" structure). -* x -* Pointer to an array of double containing the coordinates of -* an initial estimate of the position of the maximum. On exit, -* this will be updated to contain the best estimate of the -* maximum's position, as found by this function. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The best estimate of the Mapping function's maximum value. - -* Notes: -* - A value of AST__BAD will be returned, and no useful -* information about a solution will be produced, if this function -* is invoked with the global error status set or if it should fail -* for any reason. -*/ - -/* Local Constants: */ - const int maxcall = 1500; /* Maximum number of function evaluations */ - const int maxiter = 5; /* Maximum number of iterations */ - -/* Local Variables: */ - double *dx; /* Pointer to array of step lengths */ - double err; /* Simplex error estimate */ - double maximum; /* Simplex maximum value */ - double middle; /* Middle coordinate between bounds */ - double result; /* Result value to return */ - int coord; /* Loop counter for coordinates */ - int done; /* Iterations complete? */ - int iter; /* Loop counter for iterations */ - int ncall; /* Number of function calls (junk) */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialise to avoid compiler warnings. */ - err = 0.0; - -/* Allocate workspace. */ - dx = astMalloc( sizeof( double ) * (size_t) mapdata->nin ); - -/* Perform iterations to repeatedly identify a local maximum. */ - for ( iter = 0; astOK && ( iter < maxiter ); iter++ ) { - -/* Set up initial step lengths along each coordinate axis, adjusting - their signs to avoid placing points outside the coordinate - constraints (i.e. step away from the closer boundary on each - axis). */ - for ( coord = 0; coord < mapdata->nin; coord++ ) { - middle = 0.5 * ( mapdata->lbnd[ coord ] + mapdata->ubnd[ coord ] ); - dx[ coord ] = fract * ( mapdata->ubnd[ coord ] - - mapdata->lbnd[ coord ] ); - if ( x[ coord ] > middle ) dx[ coord ] = -dx[ coord ]; - } - -/* Find an approximation to a local maximum using the simplex method - and check for errors. */ - maximum = UphillSimplex( mapdata, acc, maxcall, dx, x, &err, &ncall, status ); - if ( astOK ) { - -/* Use this maximum value if no previous maximum has been found. */ - if ( result == AST__BAD ) { - result = maximum; - -/* Otherwise use it only if it improves on the previous maximum. */ - } else if ( maximum >= result ) { - -/* We iterate, re-starting the simplex algorithm from its previous - best position so as to guard against premature false - convergence. Iterations continue until the improvement in the - maximum is no greater than the required accuracy (and the simplex - algorithm itself has converged to the required accuracy). Note when - iterations should cease. */ - done = ( ( ( maximum - result ) <= acc ) && ( err <= acc ) ); - -/* Store the best maximum and quit iterating if appropriate. */ - result = maximum; - if ( done ) break; - } - -/* Otherwise, decrement the initial step size for the next iteration. */ - fract /= 1000.0; - } - } - -/* Free the workspace. */ - dx = astFree( dx ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = AST__BAD; - -/* return the result. */ - return result; -} - -static void MapBox( AstMapping *this, - const double lbnd_in[], const double ubnd_in[], - int forward, int coord_out, - double *lbnd_out, double *ubnd_out, - double xl[], double xu[], int *status ) { -/* -*+ -* Name: -* astMapBox - -* Purpose: -* Find a bounding box for a Mapping. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* void astMapBox( AstMapping *this, -* const double lbnd_in[], const double ubnd_in[], -* int forward, int coord_out, -* double *lbnd_out, double *ubnd_out, -* double xl[], double xu[] ); - -* Class Membership: -* Mapping method. - -* Description: -* This function allows you to find the "bounding box" which just -* encloses another box after it has been transformed by a Mapping -* (using either its forward or inverse transformation). A typical -* use might be to calculate the size which an image would have -* after being transformed by the Mapping. -* -* The function works on one dimension at a time. When supplied -* with the lower and upper bounds of a rectangular region (box) of -* input coordinate space, it finds the lowest and highest values -* taken by a nominated output coordinate within that -* region. Optionally, it also returns the input coordinates where -* these bounding values are attained. It should be used repeatedly -* if the extent of the bounding box is required in more than one -* dimension. - -* Parameters: -* this -* Pointer to the Mapping. -* lbnd_in -* Pointer to an array of double, with one element for each -* Mapping input coordinate. This should contain the lower bound -* of the input box in each dimension. -* ubnd_in -* Pointer to an array of double, with one element for each -* Mapping input coordinate. This should contain the upper bound -* of the input box in each dimension. -* -* Note that it is permissible for the lower bound to exceed the -* corresponding upper bound, as the values will simply be -* swapped before use. -* forward -* If this value is non-zero, then the Mapping's forward -* transformation will be used to transform the input -* box. Otherwise, its inverse transformation will be used. -* -* (If the inverse transformation is selected, then references -* to "input" and "output" coordinates in this description -* should be transposed. For example, the size of the "lbnd_in" -* and "ubnd_in" arrays should match the number of output -* coordinates, as given by the Mapping's Nout attribute.) -* coord_out -* The (zero-based) index of the output coordinate for which the -* lower and upper bounds are required. -* lbnd_out -* Pointer to a double in which to return the lowest value taken -* by the nominated output coordinate within the specified -* region of input coordinate space. -* ubnd_out -* Pointer to a double in which to return the highest value -* taken by the nominated output coordinate within the specified -* region of input coordinate space. -* xl -* An optional pointer to an array of double, with one element -* for each Mapping input coordinate. If given, this array will -* be filled with the coordinates of an input point (although -* not necessarily a unique one) for which the nominated output -* coordinate takes the lower bound value returned in -* "*lbnd_out". -* -* If these coordinates are not required, a NULL pointer may be -* supplied. -* xu -* An optional pointer to an array of double, with one element -* for each Mapping input coordinate. If given, this array will -* be filled with the coordinates of an input point (although -* not necessarily a unique one) for which the nominated output -* coordinate takes the upper bound value returned in -* "*ubnd_out". -* -* If these coordinates are not required, a NULL pointer may be -* supplied. - -* Notes: -* - Any input points which are transformed by the Mapping to give -* output coordinates containing the value AST__BAD are regarded as -* invalid and are ignored, They will make no contribution to -* determining the output bounds, even although the nominated -* output coordinate might still have a valid value at such points. -* - An error will occur if the required output bounds cannot be -* found. Typically, this might occur if all the input points which -* the function considers turn out to be invalid (see above). The -* number of points considered before generating such an error is -* quite large, however, so this is unlikely to occur by accident -* unless valid points are restricted to a very small subset of the -* input coordinate space. -* - The values returned via "lbnd_out", "ubnd_out", "xl" and "xu" -* will be set to the value AST__BAD if this function should fail -* for any reason. Their initial values on entry will not be -* altered if the function is invoked with the global error status -* set. -*- - -* Implementation Notes: -* - This function implements the basic astMapBox method available -* via the protected interface to the Mapping class. The public -* interface to this method is provided by the astMapBoxId_ -* function. -*/ - -/* Local Variables: */ - MapData mapdata; /* Structure to describe Mapping function */ - double *x_l; /* Pointer to coordinate workspace */ - double *x_u; /* Pointer to coordinate workspace */ - double lbnd; /* Required lower bound */ - double ubnd; /* Required upper bound */ - int coord; /* Loop counter for coordinates. */ - int nin; /* Effective number of input coordinates */ - int nout; /* Effective number of output coordinates */ - int refine; /* Can bounds be refined? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Initialisation to avoid compiler warnings. */ - lbnd = AST__BAD; - ubnd = AST__BAD; - -/* Obtain the effective numbers of input and output coordinates for - the Mapping, taking account of which transformation is to be - used. */ - nin = forward ? astGetNin( this ) : astGetNout( this ); - nout = forward ? astGetNout( this ) : astGetNin( this ); - -/* Check that the output coordinate index supplied is valid and report - an error if it is not. Use public (one-based) coordinate numbering - in the error message. */ - if ( astOK ) { - if ( ( coord_out < 0 ) || ( coord_out >= nout ) ) { - astError( AST__BADCI, "astMapBox(%s): Output coordinate index (%d) " - "invalid - it should be in the range 1 to %d.", status, - astGetClass( this ), coord_out + 1, nout ); - } - } - -/* Initialise a MapData structure to describe the Mapping function - whose limits are to be found. Since it may be evaluated many - times, we attempt to simplify the Mapping supplied. */ - if ( astOK ) { - mapdata.mapping = astSimplify( this ); - -/* Store the number of input/output coordinates and the index of the - output coordinate in which we are interested. */ - mapdata.nin = nin; - mapdata.nout = nout; - mapdata.coord = coord_out; - -/* Note which Mapping transformation is being used. */ - mapdata.forward = forward; - -/* Store pointers to arrays which will contain the input coordinate - bounds. */ - mapdata.lbnd = astMalloc( sizeof( double ) * (size_t) nin ); - mapdata.ubnd = astMalloc( sizeof( double ) * (size_t) nin ); - -/* Create PointSets for passing coordinate data to and from the - Mapping. */ - mapdata.pset_in = astPointSet( 1, nin, "", status ); - mapdata.pset_out = astPointSet( 1, nout, "", status ); - -/* Obtain pointers to these PointSets' coordinate arrays. */ - mapdata.ptr_in = astGetPoints( mapdata.pset_in ); - mapdata.ptr_out = astGetPoints( mapdata.pset_out ); - -/* Allocate workspace for the returned input coordinates. */ - x_l = astMalloc( sizeof( double ) * (size_t) nin ); - x_u = astMalloc( sizeof( double ) * (size_t) nin ); - if ( astOK ) { - -/* Initialise the output bounds and corresponding input coordinates to - "unknown". */ - for ( coord = 0; coord < nin; coord++ ) { - x_l[ coord ] = AST__BAD; - x_u[ coord ] = AST__BAD; - -/* Initialise the input bounds, ensuring they are the correct way - around (if not already supplied this way). */ - mapdata.lbnd[ coord ] = ( lbnd_in[ coord ] < ubnd_in[ coord ] ) ? - lbnd_in[ coord ] : ubnd_in[ coord ]; - mapdata.ubnd[ coord ] = ( ubnd_in[ coord ] > lbnd_in[ coord ] ) ? - ubnd_in[ coord ] : lbnd_in[ coord ]; - } - -/* First examine a set of special input points to obtain an initial - estimate of the required output bounds. Do this only so long as the - number of points involved is not excessive. */ - if ( nin <= 12 ) { - refine = SpecialBounds( &mapdata, &lbnd, &ubnd, x_l, x_u, status ); - } else { - refine = 1; - } - -/* Then attempt to refine this estimate using a global search - algorithm. */ - if( refine ) GlobalBounds( &mapdata, &lbnd, &ubnd, x_l, x_u, status ); - -/* If an error occurred, generate a contextual error message. */ - if ( !astOK ) { - astError( astStatus, "Unable to find a bounding box for a %s.", status, - astGetClass( this ) ); - } - } - -/* Return the output bounds and, if required, the input coordinate - values which correspond with them. */ - if ( astOK ) { - *lbnd_out = lbnd; - *ubnd_out = ubnd; - for ( coord = 0; coord < nin; coord++ ) { - if ( xl ) xl[ coord ] = x_l[ coord ]; - if ( xu ) xu[ coord ] = x_u[ coord ]; - } - } - -/* Annul the simplified Mapping pointer and the temporary - PointSets. Also free the workspace. */ - mapdata.mapping = astAnnul( mapdata.mapping ); - mapdata.lbnd = astFree( mapdata.lbnd ); - mapdata.ubnd = astFree( mapdata.ubnd ); - mapdata.pset_in = astAnnul( mapdata.pset_in ); - mapdata.pset_out = astAnnul( mapdata.pset_out ); - x_l = astFree( x_l ); - x_u = astFree( x_u ); - } - -/* If an error occurred, then return bad bounds values and - coordinates. */ - if ( !astOK ) { - *lbnd_out = AST__BAD; - *ubnd_out = AST__BAD; - for ( coord = 0; coord < nin; coord++ ) { - if ( xl ) xl[ coord ] = AST__BAD; - if ( xu ) xu[ coord ] = AST__BAD; - } - } -} - -static double MapFunction( const MapData *mapdata, const double in[], - int *ncall, int *status ) { -/* -* Name: -* MapFunction - -* Purpose: -* Return the value of a selected transformed coordinate. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double MapFunction( const MapData *mapdata, const double in[], -* int *ncall, int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function takes a set of input coordinates and applies a -* Mapping's coordinate transformation to them. It then returns the -* value of one of the transformed coordinates. -* -* It is provided for use by optimisation functions (e.g. those -* used for finding bounding boxes). The Mapping to be used and -* associated parameters (such as constraints on the range of input -* coordinates and the index of the output coordinate to be -* returned) are supplied in a MapData structure. The value -* returned will be negated if the "negate" component of this -* structure is non-zero. -* -* The value AST__BAD will be returned by this function if the -* input coordinates lie outside the constrained range given in -* the MapData structure, or if any of the transformed output -* coordinates is bad. - -* Parameters: -* mapdata -* Pointer to a MapData structure which describes the Mapping to -* be used. -* in -* A double array containing the input coordinates of a single point. -* ncall -* Pointer to an int containing a count of the number of times -* the Mapping's coordinate transformation has been used. This -* value will be updated to reflect any use made by this -* function. Normally, this means incrementing the value by 1, -* but this will be omitted if the input coordinates supplied -* are outside the constrained range so that no transformation -* is performed. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The selected output coordinate value, or AST__BAD, as appropriate. - -* Notes: -* - A value of AST__BAD will be returned if this function is -* invoked with the global error status set, or if it should fail -* for any reason. -*/ - -/* Local Variables: */ - double result; /* Result to be returned */ - int bad; /* Output coordinates invalid? */ - int coord_in; /* Loop counter for input coordinates */ - int coord_out; /* Loop counter for output coordinates */ - int outside; /* Input point outside bounds? */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* See if the input point lies outside the required bounds. */ - outside = 0; - for ( coord_in = 0; coord_in < mapdata->nin; coord_in++ ) { - if ( ( in[ coord_in ] < mapdata->lbnd[ coord_in ] ) || - ( in[ coord_in ] > mapdata->ubnd[ coord_in ] ) ) { - outside = 1; - break; - } - -/* Also store the input coordinates in the memory associated with the - Mapping's input PointSet. */ - mapdata->ptr_in[ coord_in ][ 0 ] = in[ coord_in ]; - } - -/* If the input coordinates are within bounds, transform them, using the - PointSets identified in the "mapdata" structure. */ - if ( !outside ) { - (void) astTransform( mapdata->mapping, mapdata->pset_in, - mapdata->forward, mapdata->pset_out ); - -/* Increment the number of calls to astTransform and check the error - status. */ - ( *ncall )++; - if ( astOK ) { - -/* If OK, test if any of the output coordinates is bad. */ - bad = 0; - for ( coord_out = 0; coord_out < mapdata->nout; coord_out++ ) { - if ( mapdata->ptr_out[ coord_out ][ 0 ] == AST__BAD ) { - bad = 1; - break; - } - } - -/* If not, then extract the required output coordinate, negating it if - necessary. */ - if ( !bad ) { - result = mapdata->ptr_out[ mapdata->coord ][ 0 ]; - if ( mapdata->negate ) result = -result; - } - } - } - -/* Return the result. */ - return result; -} - -static int MapList( AstMapping *this, int series, int invert, int *nmap, - AstMapping ***map_list, int **invert_list, int *status ) { -/* -*+ -* Name: -* astMapList - -* Purpose: -* Decompose a Mapping into a sequence of simpler Mappings. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astMapList( AstMapping *this, int series, int invert, int *nmap, -* AstMapping ***map_list, int **invert_list ) - -* Class Membership: -* Mapping method. - -* Description: -* This function decomposes a Mapping (which, in derived classes, -* may be a compound Mapping) into a sequence of simpler Mappings -* which may be applied in sequence to achieve the same effect. The -* Mapping is decomposed as far as possible, but it is not -* guaranteed that this will necessarily yield any more than one -* Mapping, which may actually be the original one supplied. -* -* This function is provided to support both the simplification of -* compound Mappings, and the analysis of Mapping structure so that -* particular forms can be recognised. - -* Parameters: -* this -* Pointer to the Mapping to be decomposed (the Mapping is not -* actually modified by this function). -* series -* If this value is non-zero, an attempt will be made to -* decompose the Mapping into a sequence of equivalent Mappings -* which can be applied in series (i.e. one after the other). If -* it is zero, the decomposition will instead yield Mappings -* which can be applied in parallel (i.e. on successive sub-sets -* of the input/output coordinates). -* invert -* The value to which the Mapping's Invert attribute is to be -* (notionally) set before performing the -* decomposition. Normally, the value supplied here will be the -* actual Invert value obtained from the Mapping (e.g. using -* astGetInvert). Sometimes, however, when a Mapping is -* encapsulated within another structure, that structure may -* retain an Invert value (in order to prevent external -* interference) which should be used instead. -* -* Note that the actual Invert value of the Mapping supplied is -* not used (or modified) by this function. -* nmap -* The address of an int which holds a count of the number of -* individual Mappings in the decomposition. On entry, this -* should count the number of Mappings already in the -* "*map_list" array (below). On exit, it is updated to include -* any new Mappings appended by this function. -* map_list -* Address of a pointer to an array of Mapping pointers. On -* entry, this array pointer should either be NULL (if no -* Mappings have yet been obtained) or should point at a -* dynamically allocated array containing Mapping pointers -* ("*nmap" in number) which have been obtained from a previous -* invocation of this function. -* -* On exit, the dynamic array will be enlarged to contain any -* new Mapping pointers that result from the decomposition -* requested. These pointers will be appended to any previously -* present, and the array pointer will be updated as necessary -* to refer to the enlarged array (any space released by the -* original array will be freed automatically). -* -* The new Mapping pointers returned will identify a sequence of -* Mappings which, when applied in order, will perform a forward -* transformation equivalent to that of the original Mapping -* (after its Invert flag has first been set to the value -* requested above). The Mappings should be applied in series or -* in parallel according to the type of decomposition requested. -* -* All the Mapping pointers returned by this function should be -* annulled by the caller, using astAnnul, when no longer -* required. The dynamic array holding these pointers should -* also be freed, using astFree. -* invert_list -* Address of a pointer to an array of int. On entry, this array -* pointer should either be NULL (if no Mappings have yet been -* obtained) or should point at a dynamically allocated array -* containing Invert attribute values ("*nmap" in number) which -* have been obtained from a previous invocation of this -* function. -* -* On exit, the dynamic array will be enlarged to contain any -* new Invert attribute values that result from the -* decomposition requested. These values will be appended to any -* previously present, and the array pointer will be updated as -* necessary to refer to the enlarged array (any space released -* by the original array will be freed automatically). -* -* The new Invert values returned identify the values which must -* be assigned to the Invert attributes of the corresponding -* Mappings (whose pointers are in the "*map_list" array) before -* they are applied. Note that these values may differ from the -* actual Invert attribute values of these Mappings, which are -* not relevant. -* -* The dynamic array holding these values should be freed by the -* caller, using astFree, when no longer required. - -* Returned Value: -* A non-zero value is returned if the supplied Mapping contained any -* inverted CmpMaps. - -* Notes: -* - It is unspecified to what extent the original Mapping and the -* individual (decomposed) Mappings are -* inter-dependent. Consequently, the individual Mappings cannot be -* modified without risking modification of the original. -* - If this function is invoked with the global error status set, -* or if it should fail for any reason, then the *nmap value, the -* list of Mapping pointers and the list of Invert values will all -* be returned unchanged. -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Since we are dealing with a basic Mapping, only one new Mapping - pointer will be returned. Extend the dynamic arrays to accommodate - this Mapping. */ - *map_list = astGrow( *map_list, *nmap + 1, sizeof( AstMapping * ) ); - *invert_list = astGrow( *invert_list, *nmap + 1, sizeof( int ) ); - if ( astOK ) { - -/* Return the invert flag value for the Mapping and a clone of the - Mapping pointer. */ - ( *invert_list )[ *nmap ] = ( invert != 0 ); - ( *map_list )[ *nmap ] = astClone( this ); - -/* If OK, return the new Mapping count. */ - if ( astOK ) ( *nmap )++; - } - - return 0; -} - -static int MapMerge( AstMapping *this, int where, int series, int *nmap, - AstMapping ***map_list, int **invert_list, int *status ) { -/* -*+ -* Name: -* astMapMerge - -* Purpose: -* Simplify a sequence of Mappings. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int astMapMerge( AstMapping *this, int where, int series, int *nmap, -* AstMapping ***map_list, int **invert_list ) - -* Class Membership: -* Mapping method. - -* Description: -* This function attempts to simplify a sequence of Mappings by -* merging a nominated Mapping in the sequence with its neighbours, -* so as to shorten the sequence if possible. -* -* In many cases, simplification will not be possible and the -* function will return -1 to indicate this, without further -* action. -* -* In most cases of interest, however, this function will either -* attempt to replace the nominated Mapping with one which it -* considers simpler, or to merge it with the Mappings which -* immediately precede it or follow it in the sequence (both will -* normally be considered). This is sufficient to ensure the -* eventual simplification of most Mapping sequences by repeated -* application of this function. -* -* In some cases, the function may attempt more elaborate -* simplification, involving any number of other Mappings in the -* sequence. It is not restricted in the type or scope of -* simplification it may perform, but will normally only attempt -* elaborate simplification in cases where a more straightforward -* approach is not adequate. - -* Parameters: -* this -* Pointer to the nominated Mapping which is to be merged with -* its neighbours. This should be a cloned copy of the Mapping -* pointer contained in the array element "(*map_list)[where]" -* (see below). This pointer will not be annulled, and the -* Mapping it identifies will not be modified by this function. -* where -* Index in the "*map_list" array (below) at which the pointer -* to the nominated Mapping resides. -* series -* A non-zero value indicates that the sequence of Mappings to -* be simplified will be applied in series (i.e. one after the -* other), whereas a zero value indicates that they will be -* applied in parallel (i.e. on successive sub-sets of the -* input/output coordinates). -* nmap -* Address of an int which counts the number of Mappings in the -* sequence. On entry this should be set to the initial number -* of Mappings. On exit it will be updated to record the number -* of Mappings remaining after simplification. -* map_list -* Address of a pointer to a dynamically allocated array of -* Mapping pointers (produced, for example, by the astMapList -* method) which identifies the sequence of Mappings. On entry, -* the initial sequence of Mappings to be simplified should be -* supplied. -* -* On exit, the contents of this array will be modified to -* reflect any simplification carried out. Any form of -* simplification may be performed. This may involve any of: (a) -* removing Mappings by annulling any of the pointers supplied, -* (b) replacing them with pointers to new Mappings, (c) -* inserting additional Mappings and (d) changing their order. -* -* The intention is to reduce the number of Mappings in the -* sequence, if possible, and any reduction will be reflected in -* the value of "*nmap" returned. However, simplifications which -* do not reduce the length of the sequence (but improve its -* execution time, for example) may also be performed, and the -* sequence might conceivably increase in length (but normally -* only in order to split up a Mapping into pieces that can be -* more easily merged with their neighbours on subsequent -* invocations of this function). -* -* If Mappings are removed from the sequence, any gaps that -* remain will be closed up, by moving subsequent Mapping -* pointers along in the array, so that vacated elements occur -* at the end. If the sequence increases in length, the array -* will be extended (and its pointer updated) if necessary to -* accommodate any new elements. -* -* Note that any (or all) of the Mapping pointers supplied in -* this array may be annulled by this function, but the Mappings -* to which they refer are not modified in any way (although -* they may, of course, be deleted if the annulled pointer is -* the final one). -* invert_list -* Address of a pointer to a dynamically allocated array which, -* on entry, should contain values to be assigned to the Invert -* attributes of the Mappings identified in the "*map_list" -* array before they are applied (this array might have been -* produced, for example, by the astMapList method). These -* values will be used by this function instead of the actual -* Invert attributes of the Mappings supplied, which are -* ignored. -* -* On exit, the contents of this array will be updated to -* correspond with the possibly modified contents of the -* "*map_list" array. If the Mapping sequence increases in -* length, the "*invert_list" array will be extended (and its -* pointer updated) if necessary to accommodate any new -* elements. - -* Returned Value: -* If simplification was possible, the function returns the index -* in the "map_list" array of the first element which was -* modified. Otherwise, it returns -1 (and makes no changes to the -* arrays supplied). - -* Notes: -* - A value of -1 will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* This is the default method which is inherited by all Mappings which - do not explicitly provide their own simplification method. Return - -1 to indicate that no simplification is provided. */ - return -1; -} - -static int *MapSplit( AstMapping *this, int nin, const int *in, - AstMapping **map, int *status ){ -/* -*+ -* Name: -* astMapSplit - -* Purpose: -* Create a Mapping representing a subset of the inputs of an existing -* Mapping. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* int *astMapSplit( AstMapping *this, int nin, const int *in, -* AstMapping **map ) - -* Class Membership: -* Mapping method. - -* Description: -* This function creates a new Mapping by picking specified inputs from -* an existing Mapping. This is only possible if the specified inputs -* correspond to some subset of the Mapping outputs. That is, there -* must exist a subset of the Mapping outputs for which each output -* depends only on the selected Mapping inputs, and not on any of the -* inputs which have not been selected. Also, any output which is not in -* this subset must not depend on any of the selected inputs. If these -* conditions are not met by the supplied Mapping, then a NULL Mapping -* is returned. - -* Parameters: -* this -* Pointer to the Mapping to be split (the Mapping is not -* actually modified by this function). -* nin -* The number of inputs to pick from "this". -* in -* Pointer to an array of indices (zero based) for the inputs which -* are to be picked. This array should have "nin" elements. If "Nin" -* is the number of inputs of the supplied Mapping, then each element -* should have a value in the range zero to Nin-1. -* map -* Address of a location at which to return a pointer to the new -* Mapping. This Mapping will have "nin" inputs (the number of -* outputs may be differetn to "nin"). A NULL pointer will be -* returned if the supplied Mapping has no subset of outputs which -* depend only on the selected inputs. The returned Mapping is a -* deep copy of the required parts of the supplied Mapping. - -* Returned Value: -* A pointer to a dynamically allocated array of ints. The number of -* elements in this array will equal the number of outputs for the -* returned Mapping. Each element will hold the index of the -* corresponding output in the supplied Mapping. The array should be -* freed using astFree when no longer needed. A NULL pointer will -* be returned if no output Mapping can be created. - -* Notes: -* - If this function is invoked with the global error status set, -* or if it should fail for any reason, then NULL values will be -* returned as the function value and for the "map" pointer. -*- - -* Implementation Notes: -* - This function implements the basic astMapSplit method available -* via the protected interface to the Mapping class. The public -* interface to this method is provided by the astMapSplitId_ -* function. -*/ - -/* Local Variables: */ - AstCmpMap *rmap; /* Unsimplified result mapping */ - AstPermMap *pm; /* PermMap which rearranges the inputs */ - int *outperm; /* PermMap output axis permutation array */ - int *result; /* Pointer to returned array */ - int iin; /* Input index */ - int iout; /* Output index */ - int mapnin; /* Number of Mapping inputs */ - int nout; /* No of outputs */ - int ok; /* Can the supplied "in" array be used? */ - int perm; /* Are the inputs permuted? */ - -/* Initialise */ - result = NULL; - *map = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Verify the input axis indices.*/ - mapnin = astGetNin( this ); - for( iin = 0; iin < nin; iin++ ){ - if( in[ iin ] < 0 || in[ iin ] >= mapnin ) { - astError( AST__AXIIN, "astMapSplit(%s): One of the supplied Mapping " - "input indices has value %d which is invalid; it should " - "be in the range 1 to %d.", status, astGetClass( this ), - in[ iin ] + 1, mapnin ); - break; - } - } - -/* Since we are dealing with a basic Mapping, we can only create the - required output Mapping if all inputs are being selected. */ - if( nin == mapnin ) { - -/* The inputs may have been selected in a different order to that in - which they occur in the supplied Mapping. We therefore create a - PermMap which rearranges the inputs into the order they have in the - supplied Mapping. The supplied "in" array can act as the PermMap's - "inperm" array. Allocate memory for the "outperm" array. */ - outperm = astMalloc( sizeof(int)*(size_t) nin ); - if( astOK ) { - -/* Store the input index for each output in the outperm array and check that - each input has been selected once and only once. Also set a flag - indicating if a PermMap is needed. */ - perm = 0; - ok = 1; - for( iout = 0; iout < nin; iout++ ) outperm[ iout ] = -1; - for( iin = 0; iin < nin; iin++ ) { - iout = in[ iin ]; - if( outperm[ iout ] != -1 ) { - ok = 0; - break; - } else { - outperm[ iout ] = iin; - } - } - for( iout = 0; iout < nin; iout++ ) { - if( outperm[ iout ] == -1 ) { - ok = 0; - break; - } else if( outperm[ iout ] != iout ) { - perm = 1; - } - } - if( ok ) { - -/* Allocate the array to hold the returned output indices. */ - nout = astGetNout( this ); - result = astMalloc( sizeof(int)*(size_t) nout ); - if( astOK ) { - -/* The outputs are copied from the supplied Mapping. */ - for( iout = 0; iout < nout; iout++ ) result[ iout ] = iout; - -/* If the inputs are to be permuted, create the PermMap. */ - if( perm ) { - pm = astPermMap( nin, in, nin, outperm, NULL, "", status ); - -/* The returned Mapping is a series CmpMap containing this PermMap - followed by the supplied Mapping. */ - rmap = astCmpMap( pm, this, 1, "", status ); - *map = astSimplify( rmap ); - rmap = astAnnul( rmap ); - -/* Annul the PermMap pointer. */ - pm = astAnnul( pm ); - -/* If no input permutation is needed, the resturned Mapping is just the - supplied Mapping. */ - } else { - *map = astClone( this ); - } - } - } - -/* Free resources. */ - outperm = astFree( outperm ); - } - } - -/* Free resources if an error has occurred. */ - if( !astOK ) { - result = astFree( result ); - *map = astAnnul( *map ); - } - -/* Return the list of output indices. */ - return result; -} - -static double MatrixDet( int nrow, int ncol, const double *matrix, int *status ){ -/* -* Name: -* MatrixDet - -* Purpose: -* Return the determinant of a matrix. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double MatrixDet( int nrow, int ncol, const double *matrix, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function returns the determinant of the supplied matrix. Any -* rows or columns that hold only zeros or AST_BAD values are first -* removed from the matrix. If the resulting matrix is not square, a -* value of AST__BAD is returned for the determinant. - -* Parameters: -* nrow -* The number of rows in the matrix. -* ncol -* The number of columns in the matrix. -* matrix -* The matrix element values. The first row of "ncol" elements -* should be supplied first, followed by the second row, etc. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The determinant, or AST__BAD if the determinant could not be -* caclculated. -*/ - -/* Local Variables: */ - const double *sqmat; - const double *m; - double *a; - double *y; - double result; - int *iw; - int *usecol; - int *userow; - int i; - int icol; - int irow; - int jf; - int ncoluse; - int ndim; - int nrowuse; - -/* Initialise */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Initialise... */ - sqmat = NULL; - nrowuse = 0; - ncoluse = 0; - -/* Flag any rows and columns that should be ignored because they contain - only bad values or zeros. */ - userow = astCalloc( nrow, sizeof( *userow ) ); - usecol = astCalloc( ncol, sizeof( *userow ) ); - if( astOK ) { - m = matrix; - for( irow = 0; irow < nrow; irow++ ) { - for( icol = 0; icol < ncol; icol++,m++ ) { - if( *m != AST__BAD && *m != 0.0 ) { - usecol[ icol ] = 1; - userow[ irow ] = 1; - } - } - } - -/* Find the number of usable rows and columns. */ - for( irow = 0; irow < nrow; irow++ ) { - if( userow[ irow ] ) nrowuse++; - } - - for( icol = 0; icol < ncol; icol++ ) { - if( usecol[ icol ] ) ncoluse++; - } - } - -/* Return AST__BAD if the resulting matrix is not square. */ - if( ncoluse == nrowuse ) { - ndim = ncoluse; - -/* If any rows or columns contained just bad or zero values, create a new - matrix that excludes them. */ - if( ncol > ndim || nrow > ndim ) { - sqmat = astMalloc( ndim*ndim*sizeof(*sqmat) ); - if( astOK ) { - m = matrix; - a = (double *) sqmat; - for( irow = 0; irow < nrow; irow++ ) { - if( userow[ irow ] ) { - for( icol = 0; icol < ncol; icol++,m++ ) { - if( usecol[ icol ] ) *(a++) = *m; - } - } else { - m += ncol; - } - } - } - -/* If no rows or columns contained just bad values, use the supplied - matrix. */ - } else { - sqmat = matrix; - } - -/* Calculate the determinant of the modified matrix */ - if( ndim == 1 ) { - result = sqmat[ 0 ]; - - } else if( ndim == 2 ) { - result = sqmat[ 0 ]*sqmat[ 3 ] - sqmat[ 1 ]*sqmat[ 2 ]; - - } else { - a = astStore( NULL, sqmat, sizeof( double )*(size_t) (ndim*ndim) ); - iw = astMalloc( sizeof( int )*(size_t) ndim ); - y = astMalloc( sizeof( double )*(size_t) ndim ); - if( y ) { - for( i = 0; i < ndim; i++ ) y[ i ] = 1.0; - palDmat( ndim, a, y, &result, &jf, iw ); - } - y = astFree( y ); - iw = astFree( iw ); - a = astFree( a ); - } - - } - -/* Free the square matrix if it was allocated here. */ - if( sqmat != matrix ) sqmat = astFree( (void *) sqmat ); - -/* Free the usable row/column flags. */ - userow = astFree( userow ); - usecol = astFree( usecol ); - - return result; -} - -static double MaxD( double a, double b, int *status ) { -/* -* Name: -* MaxD - -* Purpose: -* Return the maximum of two double values. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double MaxD( double a, double b, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function returns the maximum of two double values. - -* Parameters: -* a -* The first value. -* b -* The second value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The maximum. -*/ - -/* Return the larger value. */ - return ( a > b ) ? a : b; -} - -static int MaxI( int a, int b, int *status ) { -/* -* Name: -* MaxI - -* Purpose: -* Return the maximum of two integer values. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int MaxI( int a, int b, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function returns the maximum of two integer values. - -* Parameters: -* a -* The first value. -* b -* The second value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The maximum. -*/ - -/* Return the larger value. */ - return ( a > b ) ? a : b; -} - -static int MinI( int a, int b, int *status ) { -/* -* Name: -* MinI - -* Purpose: -* Return the minimum of two integer values. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int MinI( int a, int b, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function returns the minimum of two integer values. - -* Parameters: -* a -* The first value. -* b -* The second value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The minimum. -*/ - -/* Return the smaller value. */ - return ( a < b ) ? a : b; -} - -static double NewVertex( const MapData *mapdata, int lo, double scale, - double x[], double f[], int *ncall, double xnew[], int *status ) { -/* -* Name: -* NewVertex - -* Purpose: -* Locate a new vertex for a simplex. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double NewVertex( const MapData *mapdata, int lo, double scale, -* double x[], double f[], int *ncall, double xnew[], int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function is provided for use during optimisation of a -* Mapping function using the simplex method. It generates the -* coordinates of a new simplex vertex and evaluates the Mapping -* function at that point. If the function's value is better then -* (i.e. larger than) the value at the previously worst vertex, -* then it is used to replace that vertex. - -* Parameters: -* mapdata -* Pointer to a MapData structure which describes the Mapping -* function to be used. -* lo -* The (zero-based) index of the simplex vertex which initially -* has the worst (lowest) value. -* scale -* The scale factor to be used to generate the new vertex. The -* distance of the worst vertex from the centre of the face -* opposite it is scaled by this factor to give the new vertex -* position. Negative factors result in reflection through this -* opposite face. -* x -* An array of double containing the coordinates of the vertices -* of the simplex. The coordinates of the first vertex are -* stored first, then those of the second vertex, etc. This -* array will be updated by this function if the new vertex is -* used to replace an existing one. -* f -* An array of double containing the Mapping function values at -* each vertex of the simplex. This array will be updated by -* this function if the new vertex is used to replace an -* existing one. -* ncall -* Pointer to an int containing a count of the number of times -* the Mapping function has been invoked. This value will be -* updated to reflect the actions of this function. -* xnew -* An array of double with one element for each input coordinate -* of the Mapping function. This is used as workspace. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Mapping function value at the new vertex. This value is -* returned whether or not the new vertex replaces an existing one. - -* Notes: -* - A value of AST__BAD will be returned by this function if it is -* invoked with the global error status set, or if it should fail -* for any reason. -* - A value of AST__BAD will also be returned if the new vertex -* lies outside the constrained range of input coordinates -* associated with the Mapping function (as specified in the -* MapData structure supplied) or if any of the transformed output -* coordinates produced by the underlying Mapping is bad. In either -* case the new vertex will not be used to replace an existing one. -*/ - -/* Local Variables: */ - double fnew; /* Function value at new vertex */ - double xface; /* Coordinate of centre of magnification */ - int coord; /* Loop counter for coordinates */ - int ncoord; /* Number of coordinates */ - int nvertex; /* Number of simplex vertices */ - int vertex; /* Loop counter for vertices */ - -/* Initialise. */ - fnew = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return fnew; - -/* Obtain the number of Mapping input coordinates from the MapData - structure and calculate the number of simplex vertices. */ - ncoord = mapdata->nin; - nvertex = ncoord + 1; - -/* Loop to obtain each coordinate of the new vertex. */ - for ( coord = 0; coord < ncoord; coord++ ) { - -/* Loop over all vertices except the lowest one and average their - coordinates. This gives the coordinate of the centre of the face - opposite the lowest vertex, which will act as the centre of - magnification. */ - xface = 0.0; - for ( vertex = 0; vertex < nvertex; vertex++ ) { - if ( vertex != lo ) { - -/* Divide each coordinate by the number of vertices as the sum is - accumulated in order to minimise the risk of overflow. */ - xface += x[ vertex * ncoord + coord ] / - ( (double ) ( nvertex - 1 ) ); - } - } - -/* Magnify the lowest vertex's distance from this point by the - required factor to give the coordinates of the new vertex. */ - xnew[ coord ] = xface + ( x[ lo * ncoord + coord ] - xface ) * scale; - } - -/* Evaluate the Mapping function at the new vertex. */ - fnew = MapFunction( mapdata, xnew, ncall, status ); - -/* If the result is not bad and exceeds the previous value at the - lowest vertex, then replace the lowest vertex with this new one. */ - if ( astOK && ( fnew != AST__BAD ) && ( fnew > f[ lo ] ) ) { - for ( coord = 0; coord < ncoord; coord++ ) { - x[ lo * ncoord + coord ] = xnew[ coord ]; - } - f[ lo ] = fnew; - } - -/* Return the value at the new vertex. */ - return fnew; -} - -static int QuadApprox( AstMapping *this, const double lbnd[2], - const double ubnd[2], int nx, int ny, double *fit, - double *rms, int *status ){ -/* -*++ -* Name: -c astQuadApprox -f AST_QUADAPPROX - -* Purpose: -* Obtain a quadratic approximation to a 2D Mapping. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c int QuadApprox( AstMapping *this, const double lbnd[2], -c const double ubnd[2], int nx, int ny, double *fit, -c double *rms ) -f RESULT = AST_QUADAPPROX( THIS, LBND, UBND, NX, NY, FIT, RMS, STATUS ) - -* Class Membership: -* Mapping function. - -* Description: -* This function returns the co-efficients of a quadratic fit to the -* supplied Mapping over the input area specified by -c "lbnd" and "ubnd". -f LBND and UBND. -* The Mapping must have 2 inputs, but may have any number of outputs. -* The i'th Mapping output is modelled as a quadratic function of the -* 2 inputs (x,y): -* -* output_i = a_i_0 + a_i_1*x + a_i_2*y + a_i_3*x*y + a_i_4*x*x + -* a_i_5*y*y -* -c The "fit" -f The FIT -* array is returned holding the values of the co-efficients a_0_0, -* a_0_1, etc. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping. -c lbnd -f LBND( * ) = DOUBLE PRECISION (Given) -c Pointer to an array of doubles -f An array -* containing the lower bounds of a box defined within the input -* coordinate system of the Mapping. The number of elements in this -* array should equal the value of the Mapping's Nin attribute. This -* box should specify the region over which the fit is to be -* performed. -c ubnd -f UBND( * ) = DOUBLE PRECISION (Given) -c Pointer to an array of doubles -f An array -* containing the upper bounds of the box specifying the region over -* which the fit is to be performed. -c nx -f NX = INTEGER (Given) -* The number of points to place along the first Mapping input. The -* first point is at -c "lbnd[0]" and the last is at "ubnd[0]". -f LBND( 1 ) and the last is at UBND( 1 ). -* If a value less than three is supplied a value of three will be used. -c ny -f NY = INTEGER (Given) -* The number of points to place along the second Mapping input. The -* first point is at -c "lbnd[1]" and the last is at "ubnd[1]". -f LBND( 2 ) and the last is at UBND( 2 ). -* If a value less than three is supplied a value of three will be used. -c fit -f FIT( * ) = DOUBLE PRECISION (Returned) -c Pointer to an array of doubles -f An array -* in which to return the co-efficients of the quadratic -* approximation to the specified transformation. This array should -* have at least "6*Nout", elements. The first 6 elements hold the -* fit to the first Mapping output. The next 6 elements hold the -* fit to the second Mapping output, etc. So if the Mapping has 2 -* inputs and 2 outputs the quadratic approximation to the forward -* transformation is: -* -c X_out = fit[0] + fit[1]*X_in + fit[2]*Y_in + fit[3]*X_in*Y_in + -c fit[4]*X_in*X_in + fit[5]*Y_in*Y_in -c Y_out = fit[6] + fit[7]*X_in + fit[8]*Y_in + fit[9]*X_in*Y_in + -c fit[10]*X_in*X_in + fit[11]*Y_in*Y_in -f X_out = fit(1) + fit(2)*X_in + fit(3)*Y_in + fit(4)*X_in*Y_in + -f fit(5)*X_in*X_in + fit(6)*Y_in*Y_in -f Y_out = fit(7) + fit(8)*X_in + fit(9)*Y_in + fit(10)*X_in*Y_in + -f fit(11)*X_in*X_in + fit(12)*Y_in*Y_in -* -c rms -f RMS = DOUBLE PRECISION (Returned) -c Pointer to a double in which to return the -f The -* RMS residual between the fit and the Mapping, summed over all -* Mapping outputs. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astQuadApprox() -f AST_QUADAPPROX = LOGICAL -* If a quadratic approximation was created, -c a non-zero value is returned. Otherwise zero is returned -f .TRUE is returned. Otherwise .FALSE. is returned -* and the fit co-efficients are set to AST__BAD. - -* Notes: -* - This function fits the Mapping's forward transformation. To fit -* the inverse transformation, the Mapping should be inverted using -c astInvert -f AST_INVERT -* before invoking this function. -c - A value of zero -f - A value of .FALSE. -* will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*-- - -*/ - -/* Local Variables: */ - AstPointSet *pset1; - AstPointSet *pset2; - double **pdat1; - double **pdat2; - double *ofit; - double *px; - double *py; - double *pz; - double det; - double dx; - double dy; - double mat[ 6*6 ]; - double sx2; - double sx2y2; - double sx2y; - double sx3; - double sx3y; - double sx4; - double sx; - double sxy2; - double sxy3; - double sxy; - double sy2; - double sy3; - double sy4; - double sy; - double sz; - double sz2; - double szx2; - double szx; - double szxy; - double szy2; - double szy; - double x; - double xx; - double xy; - double y; - double yy; - double z; - int i; - int iout; - int iw[ 6 ]; - int ix; - int iy; - int n; - int nin; - int nout; - int np; - int ntot; - int result; - int sing; - -/* Initialise the returned values. */ - result = 0; - fit[ 0 ] = AST__BAD; - *rms = AST__BAD; - ntot = 0; - -/* Check the global error status. */ - if( !astOK ) return result; - -/* Get the number of Mapping inputs and outputs. Report an error if not - correct. */ - nin = astGetI( this, "Nin" ); - nout = astGetI( this, "Nout" ); - if( nin != 2 && astOK ) { - astError( AST__BADNI, "astQuadApprox(%s): Input Mapping has %d %s - " - "it must have 2 inputs.", status, astGetClass( this ), nin, - (nin==1)?"input":"inputs" ); - } - -/* Ensure we are using at least 3 points on each of the two input axes. */ - if( nx < 3 ) nx = 3; - if( ny < 3 ) ny = 3; - -/* Get the total number of grid points. */ - np = nx*ny; - -/* Create a PointSet to hold the 2D grid of input positions. */ - pset1 = astPointSet( np, 2, " ", status ); - pdat1 = astGetPoints( pset1 ); - -/* Create a PointSet to hold the N-D grid of output positions. */ - pset2 = astPointSet( np, nout, " ", status ); - pdat2 = astGetPoints( pset2 ); - -/* Check the memory allocation (and everything else) was succesful. */ - if( astOK ) { - -/* Find the cell dimensions on X and Y input axes. */ - dx = ( ubnd[ 0 ] - lbnd[ 0 ] )/( nx - 1 ); - dy = ( ubnd[ 1 ] - lbnd[ 1 ] )/( ny - 1 ); - -/* Create a regular grid of input positions. */ - px = pdat1[ 0 ]; - py = pdat1[ 1 ]; - for( iy = 0; iy < ny; iy++ ) { - x = lbnd[ 0 ]; - y = lbnd[ 1 ] + iy*dy; - for( ix = 0; ix < nx; ix++ ) { - *(px++) = x; - *(py++) = y; - x += dx; - } - } - -/* Use the supplied Mapping to transform this grid into the output space. */ - (void) astTransform( this, pset1, 1, pset2 ); - -/* Assume the approximation can be created. */ - result = 1; - *rms = 0.0; - -/* Loop round each Mapping output. */ - for( iout = 0; iout < nout && astOK; iout++ ) { - -/* Get a pointer to the first element of the fit array for this output. */ - ofit = fit + 6*iout; - -/* Form the required sums. */ - n = 0; - sx = 0.0; - sy = 0.0; - sxy = 0.0; - sx2 = 0.0; - sy2 = 0.0; - sx2y = 0.0; - sx3 = 0.0; - sxy2 = 0.0; - sy3 = 0.0; - sx2y2 = 0.0; - sx3y = 0.0; - sxy3 = 0.0; - sx4 = 0.0; - sy4 = 0.0; - sz = 0.0; - sz2 = 0.0; - szx = 0.0; - szy = 0.0; - szxy = 0.0; - szx2 = 0.0; - szy2 = 0.0; - - px = pdat1[ 0 ]; - py = pdat1[ 1 ]; - pz = pdat2[ iout ]; - - for( i = 0; i < np; i++ ) { - x = *(px++); - y = *(py++); - z = *(pz++); - - if( z != AST__BAD ) { - xx = x*x; - yy = y*y; - xy = x*y; - - n++; - sx += x; - sy += y; - sxy += xy; - sx2 += xx; - sy2 += yy; - sx2y += xx*y; - sx3 += xx*x; - sxy2 += x*yy; - sy3 += yy*y; - sx2y2 += xx*yy; - sx3y += xx*xy; - sxy3 += xy*yy; - sx4 += xx*xx; - sy4 += yy*yy; - sz += z; - sz2 += z*z; - szx += z*x; - szy += z*y; - szxy += z*xy; - szx2 += z*xx; - szy2 += z*yy; - } - } - -/* Form a matrix (M) and vector (V) such that M.X = V, where X is the - solution vector holding the required best fit parameter values (V is - stored in ofit). */ - mat[ 0 ] = n; - mat[ 1 ] = sx; - mat[ 2 ] = sy; - mat[ 3 ] = sxy; - mat[ 4 ] = sx2; - mat[ 5 ] = sy2; - - mat[ 6 ] = sx; - mat[ 7 ] = sx2; - mat[ 8 ] = sxy; - mat[ 9 ] = sx2y; - mat[ 10 ] = sx3; - mat[ 11 ] = sxy2; - - mat[ 12 ] = sy; - mat[ 13 ] = sxy; - mat[ 14 ] = sy2; - mat[ 15 ] = sxy2; - mat[ 16 ] = sx2y; - mat[ 17 ] = sy3; - - mat[ 18 ] = sxy; - mat[ 19 ] = sx2y; - mat[ 20 ] = sxy2; - mat[ 21 ] = sx2y2; - mat[ 22 ] = sx3y; - mat[ 23 ] = sxy3; - - mat[ 24 ] = sx2; - mat[ 25 ] = sx3; - mat[ 26 ] = sx2y; - mat[ 27 ] = sx3y; - mat[ 28 ] = sx4; - mat[ 29 ] = sx2y2; - - mat[ 30 ] = sy2; - mat[ 31 ] = sxy2; - mat[ 32 ] = sy3; - mat[ 33 ] = sxy3; - mat[ 34 ] = sx2y2; - mat[ 35 ] = sy4; - - ofit[ 0 ] = sz; - ofit[ 1 ] = szx; - ofit[ 2 ] = szy; - ofit[ 3 ] = szxy; - ofit[ 4 ] = szx2; - ofit[ 5 ] = szy2; - -/* Now find the solution vector (the solution over-writes teh current - contents of "ofit"). */ - palDmat( 6, mat, ofit, &det, &sing, iw ); - -/* If the fit failed, fill the coefficient array with bad values. */ - if( sing != 0 ) { - for( i = 0; i < 6; i++ ) ofit[ i ] = AST__BAD; - result = 0; - break; - -/* If the fit succeeded, update the summ of the squared residuals. */ - } else { - ntot += n; - *rms += ofit[ 0 ]*ofit[ 0 ]*n + - 2*ofit[ 0 ]*ofit[ 1 ]*sx + - 2*ofit[ 0 ]*ofit[ 2 ]*sy + - 2*( ofit[ 0 ]*ofit[ 3 ] + ofit[ 1 ]*ofit[ 2 ] )*sxy + - ( 2*ofit[ 0 ]*ofit[ 4 ] + ofit[ 1 ]*ofit[ 1 ] )*sx2 + - ( 2*ofit[ 0 ]*ofit[ 5 ] + ofit[ 2 ]*ofit[ 2 ] )*sy2 + - 2*ofit[ 1 ]*ofit[ 4 ]*sx3 + - 2*( ofit[ 1 ]*ofit[ 3 ] + ofit[ 2 ]*ofit[ 4 ] )*sx2y + - 2*( ofit[ 1 ]*ofit[ 5 ] + ofit[ 2 ]*ofit[ 3 ] )*sxy2 + - 2*ofit[ 2 ]*ofit[ 5 ]*sy3 + - ofit[ 4 ]*ofit[ 4 ]*sx4 + - 2*ofit[ 3 ]*ofit[ 4 ]*sx3y + - ( 2*ofit[ 4 ]*ofit[ 5 ] + ofit[ 3 ]*ofit[ 3 ] )*sx2y2 + - 2*ofit[ 3 ]*ofit[ 5 ]*sxy3 + - ofit[ 5 ]*ofit[ 5 ]*sy4 + - sz2 - 2*( - ofit[ 0 ]*sz + - ofit[ 1 ]*szx + - ofit[ 2 ]*szy + - ofit[ 3 ]*szxy + - ofit[ 4 ]*szx2 + - ofit[ 5 ]*szy2 - ); - } - } - } - -/* Free resources. */ - pset1 = astAnnul( pset1 ); - pset2 = astAnnul( pset2 ); - -/* Return AST__BAD if anything went wrong. */ - if( !astOK || ntot == 0 ) { - result = 0; - fit[ 0 ] = AST__BAD; - *rms = AST__BAD; - -/* Otherwise normalise the returned RMS. */ - } else { - if( *rms > 0.0 ) { - *rms = sqrt( *rms/ntot ); - } else { - *rms = 0.0; - } - } - -/* Return result */ - return result; -} - -static double Random( long int *seed, int *status ) { -/* -* Name: -* Random - -* Purpose: -* Return a pseudo-random value in the range 0 to 1. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double Random( long int *seed, int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function returns a pseudo-random double value from a PDF -* uniformly distributed in the range 0 to 1. It also updates a -* seed value so that a sequence of pseudo-random values may be -* obtained with successive invocations. - -* Parameters: -* seed -* Pointer to a long int which should initially contain a -* non-zero seed value. This will be updated with a new seed -* which may be supplied on the next invocation in order to -* obtain a different pseudo-random value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The pseudo-random value. -*/ - -/* Local Variables: */ - long int i; /* Temporary storage */ - -/* This a basic random number generator using constants given in - Numerical Recipes (Press et al.). */ - i = *seed / 127773; - *seed = ( *seed - i * 127773 ) * 16807 - i * 2836; - if ( *seed < 0 ) *seed += 2147483647; - -/* Return the result as a double value in the range 0 to 1. */ - return ( (double) ( *seed - 1 ) ) / (double) 2147483646; -} - -static double Rate( AstMapping *this, double *at, int ax1, int ax2, - int *status ){ -/* -*+ -* Name: -* astRate - -* Purpose: -* Calculate the rate of change of a Mapping output. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* result = astRate( AstMapping *this, double *at, int ax1, int ax2 ) - -* Class Membership: -* Mapping method. - -* Description: -* This function evaluates the rate of change of a specified output of -* the supplied Mapping with respect to a specified input, at a -* specified input position. -* -* The result is the mean gradient within a small interval centred on -* the supplied position. The interval size is selected automatically -* to minimise the error on the returned value. For large intervals, -* the error is dominated by changes in the gradient of the -* transformation. For small intervals, the error is dominated by -* rounding errors. The best interval is the one that gives the most -* consistent measure of the gradient within the interval. To find this -* consistency, each candidate interval is subdivided into eight -* sub-intervals, the mean gradient within each sub-interval is found, -* and the associated consistency measure is then the difference between -* the maximum and minimum sub-interval gradient found within the interval. - -* Parameters: -* this -* Pointer to the Mapping to be applied. -* at -* The address of an array holding the axis values at the position -* at which the rate of change is to be evaluated. The number of -* elements in this array should equal the number of inputs to the -* Mapping. -* ax1 -* The index of the Mapping output for which the rate of change is to -* be found (output numbering starts at 0 for the first output). -* ax2 -* The index of the Mapping input which is to be varied in order to -* find the rate of change (input numbering starts at 0 for the first -* input). - -* Returned Value: -* astRate() -* The rate of change of Mapping output "ax1" with respect to input -* "ax2", evaluated at "at", or AST__BAD if the value cannot be -* calculated. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- - -* Implementation Notes: -* - This function implements the basic astRate method available -* via the protected interface to the Mapping class. The public -* interface to this method is provided by the astRateId_ -* function. -*/ - -#define NN 50 - -/* Local Variables: */ - double h0; - double h; - double mean; - double minrange; - double range0; - double range; - double ret; - double x0; - double y[2*NN+1]; - double z[2*NN+1]; - int ibot; - int iin; - int iret; - int itop; - int nin; - int nout; - -/* Initialise */ - ret = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Allocate resources */ - RateFun( NULL, NULL, -1, 0, 0, NULL, NULL, status ); - -/* Obtain the numbers of input and output coordinates for the Mapping. */ - nin = astGetNin( this ); - nout = astGetNout( this ); - -/* Validate the output index. */ - if ( astOK && ( ax1 < 0 || ax1 >= nout ) ) { - astError( AST__AXIIN, "astRate(%s): The supplied Mapping output " - "index (%d) is invalid; it should be in the range 1 to %d.", status, - astGetClass( this ), ax1 + 1, nout ); - } - -/* Validate the input index. */ - if ( astOK && ( ax2 < 0 || ax2 >= nin ) ) { - astError( AST__AXIIN, "astRate(%s): The supplied Mapping input " - "index (%d) is invalid; it should be in the range 1 to %d.", status, - astGetClass( this ), ax2 + 1, nin ); - } - -/* Check the Mapping has a forward transformation. */ - if ( astOK && !astGetTranForward( this ) ) { - astError( AST__NODEF, "astRate(%s): The supplied Mapping does not " - "have a defined forward transformation.", status, - astGetClass( this ) ); - } - -/* Save the central value on the Mapping input which is to be varied. */ - x0 = at[ ax2 ]; - -/* If it is bad, return bad values. */ - if( astOK && x0 != AST__BAD ) { - -/* The required derivative is formed by evaluating the transformation at - two positions close to "x0", and dividing the change in y by the - change in x. The complexity comes in deciding how close to "x0" the - two points should be. If the points are too far apart, the gradient of - the function may vary significantly between the two points and so we - have little confidence that he mean gradient in the interval is a good - estimate of the gradient at "x0". On the other hand if the points are - too close together, rounding errors will make the gradient value - unreliable. The optimal interval is found by testing a number of - different intervals as follows. Each interval is split into NDIV equal - sub-intervals, and the gradient in each sub-interval is found. The max - and min gradient for any of these sub-intervals is found, and the - difference between them is used as an estimate of the reliability of the - mean gradient within the whole interval. The interval with the - greatest reliability is used to define the returned gradient. - - The initial estimate of the interval size is a fixed small fraction of - the supplied "x0" value, or 1.0 if "x0" is zero. */ - h0 = ( x0 != 0.0 ) ? DBL_EPSILON*1.0E9*fabs( x0 ) : 1.0; - -/* Attempt to find the mean gradient, and the range of gradients, within - an interval of size "h0" centred on "x0". If this cannot be done, - increase "h0" by a factor fo ten repeatedly until it can be done, or a - silly large interval size is reached. */ - mean = AST__BAD; - while( mean == AST__BAD && h0 < 1.0E-10*DBL_MAX ) { - h0 *= 10; - mean = FindGradient( this, at, ax1, ax2, x0, h0, &range0, status ); - } - -/* If this was not successful, return AST__BAD as the function value. */ - if( mean != AST__BAD ) { - -/* We now search through a range of larger interval sizes, to see if any - produce a more reliable mean gradient estimate (i.e. have a smaller range - of gradients within the interval ). After that we search through a range - of smaller interval sizes. The gradient range and mean gradient for - each interval size are stored in arrays "y" and "z" respectively. "iret" - is the index of the most reliable interval found so far (i.e. the one - with the smallest range of sub-interval gradients). The original interval - "h0" is stored in the middle element of these arrays (index "NN"). - Intervals are stored in monotonic order of interval size in the arrays. */ - iret = NN; - y[ NN ] = range0; - z[ NN ] = mean; - minrange = range0; - -/* itop is the index of the last array elements to store calculated values. */ - itop = NN; - -/* Loop round increasing the interval size by a factor of four each time - round. */ - h = h0; - for( iin = NN + 1; iin <= 2*NN && astOK; iin++ ){ - h *= 4.0; - -/* Calculate the mean gradient, and the range of gradients, using the - current interval size. */ - mean = FindGradient( this, at, ax1, ax2, x0, h, &range, status ); - -/* If it could be done, store the values in the arrays. */ - if( mean != AST__BAD ) { - itop++; - z[ itop ] = mean; - y[ itop ] = range; - -/* Look for the smallest range, and note its index in the arrays. */ - if( range < minrange ) { - minrange = range; - iret = itop; - -/* If a range of zero is encountered, we only believe it if the previous - interval also had zero range. Otherwise, it's probably just a numerical - fluke. If the previous interval also had a range of zero, we can forget - the rest of the algorithm since the supplied transformation is linear - and we now have its gradient. So leave the loop. */ - } else if( range == 0.0 && y[ iin - 1 ] == 0 ) { - iret = itop; - break; - } - -/* Stop looping when the interval range is 100 times the original - interval range. */ - if( range > 100*range0 ) break; - } - } - -/* Record the minimum range found so far. */ - range0 = minrange; - -/* ibot is the index of the first array elements to store calculated values. */ - ibot = NN; - -/* Loop round decreasing the interval size by a factor of four each time - round. This is just like the last loop, but goes the other way, to - lower indices. */ - h = h0; - for( iin = NN - 1; iin >= 0 && astOK; iin-- ){ - h /= 4.0; - - mean = FindGradient( this, at, ax1, ax2, x0, h, &range, status ); - if( mean != AST__BAD ) { - ibot--; - z[ ibot ] = mean; - y[ ibot ] = range; - - if( range < minrange ) { - minrange = range; - iret = ibot; - } else if( range == 0.0 && y[ iin + 1 ] == 0 ) { - iret = ibot; - break; - } - - if( range > 100*range0 ) break; - } - } - -/* If the smallest gradient range in any interval was zero, we only - believe it if the adjacent interval size also had zero range. */ - if( minrange == 0.0 ) { - if( ( iret > ibot && y[ iret - 1 ] == 0 ) || - ( iret < itop && y[ iret + 1 ] == 0 ) ) { - ret = z[ iret ]; - -/* Otherwise, search for the smallest gradient range, ignoring values - exactly equal to zero, and return the corresponding mean interval - gradient. */ - } else { - for( iin = ibot; iin <= itop; iin++ ){ - if( y[ iin ] > 0.0 ){ - if( minrange == 0 || y[ iin ] < minrange ) { - minrange = y[ iin ]; - ret = z[ iin ]; - } - } - } - } - -/* If the minimum range was non-zero, we can just return the - corresponding mean gradient. */ - } else { - ret = z[ iret ]; - } - } - } - -/* Free resources */ - RateFun( NULL, NULL, -2, 0, 0, NULL, NULL, status ); - -/* Return the result. */ - return ret; - -#undef NN -} - -static void RateFun( AstMapping *map, double *at, int ax1, int ax2, - int n, double *x, double *y, int *status ) { -/* -* Name: -* RateFun - -* Purpose: -* Find the value of the function currently being differentiated by the -* astRate method. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void RateFun( AstMapping *map, double *at, int ax1, int ax2, -* int n, double *x, double *y, int *status ) - -* Class Membership: -* Mapping method. - -* Description: -* This is a service function for the astRate method. It evaluates the -* function being differentiated at specified axis values. -* -* This function uses static resources in order to avoid the overhead -* of creating new PointSets each time this function is called. These -* static resources which must be initialised before the first invocation -* with a given Mapping, and must be released after the final invocation. -* See "ax1". - -* Parameters: -* map -* Pointer to a Mapping which yields the value of the function at x. -* The Mapping may have any number of inputs and outputs; the specific -* output representing the function value, f, is specified by ax1 and -* the specific input representing the argument, x, is specified by ax2. -* at -* A pointer to an array holding axis values at the position at which -* the function is to be evaluated. The number of values supplied -* must equal the number of inputs to the Mapping. The value supplied -* for axis "ax2" is ignored (the value of "x" is used for axis "ax2"). -* ax1 -* The zero-based index of the Mapping output which is to be -* differentiated. Set this to -1 to allocate, or -2 to release, -* the static resources used by this function. -* ax2 -* The zero-based index of the Mapping input which is to be varied. -* n -* The number of elements in the "x" and "y" arrays. This should not -* be greater than 2*RATE_ORDER. -* x -* The value of the Mapping input specified by ax2 at which the -* function is to be evaluated. If "ax2" is set to -1, then the -* supplied value is used as flag indicating if the static resources -* used by this function should be initialised (if x >= 0 ) or -* freed (if x < 0). -* y -* An array in which to return the function values at the positions -* given in "x". -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS - AstPointSet *pset1; - AstPointSet *pset2; - double **ptr1; - double **ptr2; - double *oldx; - double *oldy; - double *p; - double xx; - int i; - int k; - int nin; - int nout; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(map); - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - pset2 = NULL; - -/* If required, initialise things. */ - if( ax1 == -1 ) { - for( i = 0; i < RATEFUN_MAX_CACHE; i++ ) { - ratefun_pset_size[ i ] = 0; - ratefun_pset1_cache[ i ] = NULL; - ratefun_pset2_cache[ i ] = NULL; - } - ratefun_next_slot = 0; - -/* If required, clean up. */ - } else if( ax1 == -2 ) { - for( i = 0; i < RATEFUN_MAX_CACHE; i++ ) { - ratefun_pset_size[ i ] = 0; - if( ratefun_pset1_cache[ i ] ) ratefun_pset1_cache[ i ] = astAnnul( ratefun_pset1_cache[ i ] ); - if( ratefun_pset2_cache[ i ] ) ratefun_pset2_cache[ i ] = astAnnul( ratefun_pset2_cache[ i ] ); - } - ratefun_next_slot = 0; - -/* Otherwise do the transformations. */ - } else { - -/* See if we have already created PointSets of the correct size. */ - pset1 = NULL; - for( i = 0; i < RATEFUN_MAX_CACHE; i++ ) { - if( ratefun_pset_size[ i ] == n ) { - pset1 = ratefun_pset1_cache[ i ]; - pset2 = ratefun_pset2_cache[ i ]; - break; - } - } - -/* If we have not, create new PointSets now. */ - if( pset1 == NULL ) { - nin = astGetNin( map ); - pset1 = astPointSet( n, nin, "", status ); - ptr1 = astGetPoints( pset1 ); - - nout = astGetNout( map ); - pset2 = astPointSet( n, nout, "", status ); - ptr2 = astGetPoints( pset2 ); - -/* Store the input position in the input PointSet. */ - for( i = 0; i < nin; i++ ) { - xx = at[ i ]; - p = ptr1[ i ]; - for( k = 0; k < n; k++, p++ ) *p = xx; - } - -/* Add these new PointSets to the cache, removing any existing - PointSets. */ - if( ratefun_pset_size[ ratefun_next_slot ] > 0 ) { - (void) astAnnul( ratefun_pset1_cache[ ratefun_next_slot ] ); - (void) astAnnul( ratefun_pset2_cache[ ratefun_next_slot ] ); - } - ratefun_pset1_cache[ ratefun_next_slot ] = pset1; - ratefun_pset2_cache[ ratefun_next_slot ] = pset2; - ratefun_pset_size[ ratefun_next_slot ] = n; - if( ++ratefun_next_slot == RATEFUN_MAX_CACHE ) ratefun_next_slot = 0; - -/* If existing PointSets were found, get there data arrays. */ - } else { - ptr1 = astGetPoints( pset1 ); - ptr2 = astGetPoints( pset2 ); - } - -/* Store the input X values in the input PointSet data array. */ - oldx = ptr1[ ax2 ]; - ptr1[ ax2 ] = x; - -/* Store the output Y values in the output PointSet data array. */ - oldy = ptr2[ ax1 ]; - ptr2[ ax1 ] = y; - -/* Transform the positions. */ - (void) astTransform( map, pset1, 1, pset2 ); - -/* Re-instate the original arrays in the PointSets. */ - ptr1[ ax2 ] = oldx; - ptr2[ ax1 ] = oldy; - - } -} - -/* -*++ -* Name: -c astRebin<X> -f AST_REBIN<X> - -* Purpose: -* Rebin a region of a data grid. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astRebin<X>( AstMapping *this, double wlim, int ndim_in, -c const int lbnd_in[], const int ubnd_in[], -c const <Xtype> in[], const <Xtype> in_var[], -c int spread, const double params[], int flags, -c double tol, int maxpix, -c <Xtype> badval, int ndim_out, -c const int lbnd_out[], const int ubnd_out[], -c const int lbnd[], const int ubnd[], -c <Xtype> out[], <Xtype> out_var[] ); -f CALL AST_REBIN<X>( THIS, WLIM, NDIM_IN, LBND_IN, UBND_IN, IN, IN_VAR, -f SPREAD, PARAMS, FLAGS, -f TOL, MAXPIX, BADVAL, -f NDIM_OUT, LBND_OUT, UBND_OUT, -f LBND, UBND, OUT, OUT_VAR, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -* This is a set of functions for rebinning gridded data (e.g. an -* image) under the control of a geometrical transformation, which -* is specified by a Mapping. The functions operate on a pair of -* data grids (input and output), each of which may have any number -* of dimensions. Rebinning may be restricted to a specified -* region of the input grid. An associated grid of error estimates -* associated with the input data may also be supplied (in the form -* of variance values), so as to produce error estimates for the -* rebined output data. Propagation of missing data (bad pixels) -* is supported. -* -* Note, if you will be rebining a sequence of input arrays and then -* co-adding them into a single array, the alternative -c astRebinSeq<X> functions -f AST_REBINSEQ<X> routines -* will in general be more efficient. -* -* You should use a rebinning function which matches the numerical -* type of the data you are processing by replacing <X> in -c the generic function name astRebin<X> by an appropriate 1- or -f the generic function name AST_REBIN<X> by an appropriate 1- or -* 2-character type code. For example, if you are rebinning data -c with type "float", you should use the function astRebinF (see -f with type REAL, you should use the function AST_REBINR (see -* the "Data Type Codes" section below for the codes appropriate to -* other numerical types). -* -* Rebinning of the grid of input data is performed by transforming -* the coordinates of the centre of each input grid element (or pixel) -* into the coordinate system of the output grid. The input pixel -* value is then divided up and assigned to the output pixels in the -* neighbourhood of the central output coordinates. A choice of -* schemes are provided for determining how each input pixel value is -* divided up between the output pixels. In general, each output pixel -* may be assigned values from more than one input pixel. All -* contributions to a given output pixel are summed to produce the -* final output pixel value. Output pixels can be set to the supplied -* bad value if they receive contributions from an insufficient number -* of input pixels. This is controlled by the -c "wlim" parameter. -f WLIM argument. -* -* Input pixel coordinates are transformed into the coordinate -* system of the output grid using the forward transformation of the -* Mapping which is supplied. This means that geometrical features -* in the input data are subjected to the Mapping's forward -* transformation as they are transferred from the input to the -* output grid. -* -* In practice, transforming the coordinates of every pixel of a -* large data grid can be time-consuming, especially if the Mapping -* involves complicated functions, such as sky projections. To -* improve performance, it is therefore possible to approximate -* non-linear Mappings by a set of linear transformations which are -* applied piece-wise to separate sub-regions of the data. This -* approximation process is applied automatically by an adaptive -* algorithm, under control of an accuracy criterion which -* expresses the maximum tolerable geometrical distortion which may -* be introduced, as a fraction of a pixel. -* -* This algorithm first attempts to approximate the Mapping with a -* linear transformation applied over the whole region of the -* input grid which is being used. If this proves to be -* insufficiently accurate, the input region is sub-divided into -* two along its largest dimension and the process is repeated -* within each of the resulting sub-regions. This process of -* sub-division continues until a sufficiently good linear -* approximation is found, or the region to which it is being -* applied becomes too small (in which case the original Mapping is -* used directly). - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to a Mapping, whose forward transformation will be -* used to transform the coordinates of pixels in the input -* grid into the coordinate system of the output grid. -* -* The number of input coordinates used by this Mapping (as -* given by its Nin attribute) should match the number of input -c grid dimensions given by the value of "ndim_in" -f grid dimensions given by the value of NDIM_IN -* below. Similarly, the number of output coordinates (Nout -* attribute) should match the number of output grid dimensions -c given by "ndim_out". -f given by NDIM_OUT. -c wlim -f WLIM = DOUBLE PRECISION (Given) -* Gives the required number of input pixel values which must contribute -* to an output pixel in order for the output pixel value to be -* considered valid. If the sum of the input pixel weights contributing -* to an output pixel is less than the supplied -c "wlim" -f WLIM -* value, then the output pixel value is returned set to the -* supplied bad value. -c ndim_in -f NDIM_IN = INTEGER (Given) -* The number of dimensions in the input grid. This should be at -* least one. -c lbnd_in -f LBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the input grid along each dimension. -c ubnd_in -f UBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the input grid along each dimension. -* -c Note that "lbnd_in" and "ubnd_in" together define the shape -f Note that LBND_IN and UBND_IN together define the shape -* and size of the input grid, its extent along a particular -c (j'th) dimension being ubnd_in[j]-lbnd_in[j]+1 (assuming the -c index "j" to be zero-based). They also define -f (J'th) dimension being UBND_IN(J)-LBND_IN(J)+1. They also define -* the input grid's coordinate system, each pixel having unit -* extent along each dimension with integral coordinate values -* at its centre. -c in -f IN( * ) = <Xtype> (Given) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* input grid, containing the input data to be rebined. The -* numerical type of this array should match the 1- or -* 2-character type code appended to the function name (e.g. if -c you are using astRebinF, the type of each array element -c should be "float"). -f you are using AST_REBINR, the type of each array element -f should be REAL). -* -* The storage order of data within this array should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c in_var -f IN_VAR( * ) = <Xtype> (Given) -c An optional pointer to a second array with the same size and -c type as the "in" array. If given, this should contain a set -c of non-negative values which represent estimates of the -c statistical variance associated with each element of the "in" -c array. If this array is supplied (together with the -c corresponding "out_var" array), then estimates of the -c variance of the rebined output data will be calculated. -c -c If no input variance estimates are being provided, a NULL -c pointer should be given. -f An optional second array with the same size and type as the -f IN array. If the AST__USEVAR flag is set via the FLAGS -f argument (below), this array should contain a set of -f non-negative values which represent estimates of the -f statistical variance associated with each element of the IN -f array. Estimates of the variance of the rebined output data -f will then be calculated. -f -f If the AST__USEVAR flag is not set, no input variance -f estimates are required and this array will not be used. A -f dummy (e.g. one-element) array may then be supplied. -c spread -f SPREAD = INTEGER (Given) -c This parameter specifies the scheme to be used for dividing -f This argument specifies the scheme to be used for dividing -* each input data value up amongst the corresponding output pixels. -* It may be used to select -* from a set of pre-defined schemes by supplying one of the -* values described in the "Pixel Spreading Schemes" -* section below. If a value of zero is supplied, then the -* default linear spreading scheme is used (equivalent to -* supplying the value AST__LINEAR). -c params -f PARAMS( * ) = DOUBLE PRECISION (Given) -c An optional pointer to an array of double which should contain -f An optional array which should contain -* any additional parameter values required by the pixel -* spreading scheme. If such parameters are required, this -* will be noted in the "Pixel Spreading Schemes" -* section below. -* -c If no additional parameters are required, this array is not -c used and a NULL pointer may be given. -f If no additional parameters are required, this array is not -f used. A dummy (e.g. one-element) array may then be supplied. -c flags -f FLAGS = INTEGER (Given) -c The bitwise OR of a set of flag values which may be used to -f The sum of a set of flag values which may be used to -* provide additional control over the rebinning operation. See -* the "Control Flags" section below for a description of the -* options available. If no flag values are to be set, a value -* of zero should be given. -c tol -f TOL = DOUBLE PRECISION (Given) -* The maximum tolerable geometrical distortion which may be -* introduced as a result of approximating non-linear Mappings -* by a set of piece-wise linear transformations. This should be -* expressed as a displacement in pixels in the output grid's -* coordinate system. -* -* If piece-wise linear approximation is not required, a value -* of zero may be given. This will ensure that the Mapping is -* used without any approximation, but may increase execution -* time. -* -* If the value is too high, discontinuities between the linear -* approximations used in adjacent panel will be higher, and may -* cause the edges of the panel to be visible when viewing the output -* image at high contrast. If this is a problem, reduce the -* tolerance value used. -c maxpix -f MAXPIX = INTEGER (Given) -* A value which specifies an initial scale size (in pixels) for -* the adaptive algorithm which approximates non-linear Mappings -* with piece-wise linear transformations. Normally, this should -* be a large value (larger than any dimension of the region of -* the input grid being used). In this case, a first attempt to -* approximate the Mapping by a linear transformation will be -* made over the entire input region. -* -* If a smaller value is used, the input region will first be -c divided into sub-regions whose size does not exceed "maxpix" -f divided into sub-regions whose size does not exceed MAXPIX -* pixels in any dimension. Only at this point will attempts at -* approximation commence. -* -* This value may occasionally be useful in preventing false -* convergence of the adaptive algorithm in cases where the -* Mapping appears approximately linear on large scales, but has -* irregularities (e.g. holes) on smaller scales. A value of, -* say, 50 to 100 pixels can also be employed as a safeguard in -* general-purpose software, since the effect on performance is -* minimal. -* -* If too small a value is given, it will have the effect of -* inhibiting linear approximation altogether (equivalent to -c setting "tol" to zero). Although this may degrade -f setting TOL to zero). Although this may degrade -* performance, accurate results will still be obtained. -c badval -f BADVAL = <Xtype> (Given) -* This argument should have the same type as the elements of -c the "in" array. It specifies the value used to flag missing -f the IN array. It specifies the value used to flag missing -* data (bad pixels) in the input and output arrays. -* -c If the AST__USEBAD flag is set via the "flags" parameter, -f If the AST__USEBAD flag is set via the FLAGS argument, -c then this value is used to test for bad pixels in the "in" -c (and "in_var") array(s). -f then this value is used to test for bad pixels in the IN -f (and IN_VAR) array(s). -* -* In all cases, this value is also used to flag any output -c elements in the "out" (and "out_var") array(s) for which -f elements in the OUT (and OUT_VAR) array(s) for which -* rebined values could not be obtained (see the "Propagation -* of Missing Data" section below for details of the -* circumstances under which this may occur). -c ndim_out -f NDIM_OUT = INTEGER (Given) -* The number of dimensions in the output grid. This should be -* at least one. It need not necessarily be equal to the number -* of dimensions in the input grid. -c lbnd_out -f LBND_OUT( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the output grid along each dimension. -c ubnd_out -f UBND_OUT( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the output grid along each dimension. -* -c Note that "lbnd_out" and "ubnd_out" together define the -f Note that LBND_OUT and UBND_OUT together define the -* shape, size and coordinate system of the output grid in the -c same way as "lbnd_in" and "ubnd_in" define the shape, size -f same way as LBND_IN and UBND_IN define the shape, size -* and coordinate system of the input grid. -c lbnd -f LBND( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the first pixel in the region -* of the input grid which is to be included in the rebined output -* array. -c ubnd -f UBND( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the last pixel in the region of -* the input grid which is to be included in the rebined output -* array. -* -c Note that "lbnd" and "ubnd" together define the shape and -f Note that LBND and UBND together define the shape and -* position of a (hyper-)rectangular region of the input grid -* which is to be included in the rebined output array. This region -* should lie wholly within the extent of the input grid (as -c defined by the "lbnd_in" and "ubnd_in" arrays). Regions of -f defined by the LBND_IN and UBND_IN arrays). Regions of -* the input grid lying outside this region will not be used. -c out -f OUT( * ) = <Xtype> (Returned) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* output grid, in which the rebined data values will be -* returned. The numerical type of this array should match that -c of the "in" array, and the data storage order should be such -f of the IN array, and the data storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c out_var -f OUT_VAR( * ) = <Xtype> (Returned) -c An optional pointer to an array with the same type and size -c as the "out" array. If given, this array will be used to -c return variance estimates for the rebined data values. This -c array will only be used if the "in_var" array has also been -c supplied. -f An optional array with the same type and size as the OUT -f array. If the AST__USEVAR flag is set via the FLAGS argument, -f this array will be used to return variance estimates for the -f rebined data values. -* -* The output variance values will be calculated on the -* assumption that errors on the input data values are -* statistically independent and that their variance estimates -* may simply be summed (with appropriate weighting factors) -* when several input pixels contribute to an output data -* value. If this assumption is not valid, then the output error -* estimates may be biased. In addition, note that the -* statistical errors on neighbouring output data values (as -* well as the estimates of those errors) may often be -* correlated, even if the above assumption about the input data -* is correct, because of the pixel spreading schemes -* employed. -* -c If no output variance estimates are required, a NULL pointer -c should be given. -f If the AST__USEVAR flag is not set, no output variance -f estimates will be calculated and this array will not be -f used. A dummy (e.g. one-element) array may then be supplied. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Data Type Codes: -* To select the appropriate rebinning function, you should -c replace <X> in the generic function name astRebin<X> with a -f replace <X> in the generic function name AST_REBIN<X> with a -* 1- or 2-character data type code, so as to match the numerical -* type <Xtype> of the data you are processing, as follows: -c - D: double -c - F: float -c - I: int -c - B: byte (signed char) -c - UB: unsigned byte (unsigned char) -f - D: DOUBLE PRECISION -f - R: REAL -f - I: INTEGER -f - B: BYTE (treated as signed) -f - UB: BYTE (treated as unsigned) -* -c For example, astRebinD would be used to process "double" -c data, while astRebinI would be used to process "int" -c data, etc. -f For example, AST_REBIND would be used to process DOUBLE -f PRECISION data, while AST_REBINI would be used to process -f integer data (stored in an INTEGER array), etc. -* -* Note that, unlike -c astResample<X>, the astRebin<X> -f AST_RESAMPLE<X>, the AST_REBIN<X> -* set of functions does not yet support unsigned integer data types -* or integers of different sizes. - -* Pixel Spreading Schemes: -* The pixel spreading scheme specifies the Point Spread Function (PSF) -* applied to each input pixel value as it is copied into the output -* array. It can be thought of as the inverse of the sub-pixel -* interpolation schemes used by the -c astResample<X> -f AST_RESAMPLE<X> -* group of functions. That is, in a sub-pixel interpolation scheme the -* kernel specifies the weight to assign to each input pixel when -* forming the weighted mean of the input pixels, whereas the kernel in a -* pixel spreading scheme specifies the fraction of the input data value -* which is to be assigned to each output pixel. As for interpolation, the -* choice of suitable pixel spreading scheme involves stricking a balance -* between schemes which tend to degrade sharp features in the data by -* smoothing them, and those which attempt to preserve sharp features but -* which often tend to introduce unwanted artifacts. See the -c astResample<X> -f AST_RESAMPLE<X> -* documentation for further discussion. -* -* The binning algorithm used has the ability to introduce artifacts -* not seen when using a resampling algorithm. Particularly, when -* viewing the output image at high contrast, systems of curves lines -* covering the entire image may be visible. These are caused by a -* beating effect between the input pixel positions and the output pixels -* position, and their nature and strength depend critically upon the -* nature of the Mapping and the spreading function being used. In -* general, the nearest neighbour spreading function demonstrates this -* effect more clearly than the other functions, and for this reason -* should be used with caution. -* -* The following values (defined in the -c "ast.h" header file) -f AST_PAR include file) -* may be assigned to the -c "spread" -f SPREAD -* parameter. See the -c astResample<X> -f AST_RESAMPLE<X> -* documentation for details of these schemes including the use of the -c "fspread" and "params" parameters: -f FSPREAD and PARAMS arguments: -* -* - AST__NEAREST -* - AST__LINEAR -* - AST__SINC -* - AST__SINCSINC -* - AST__SINCCOS -* - AST__SINCGAUSS -* - AST__SOMBCOS -* -* In addition, the following schemes can be used with -f AST_REBIN<X> but not with AST_RESAMPLE<X>: -c astRebin<X> but not with astResample<X>: -* -* - AST__GAUSS: This scheme uses a kernel of the form exp(-k*x*x), with k -* a positive constant determined by the full-width at half-maximum (FWHM). -* The FWHM should be supplied in units of output pixels by means of the -c "params[1]" -f PARAMS(2) -* value and should be at least 0.1. The -c "params[0]" -f PARAMS(1) -* value should be used to specify at what point the Gaussian is truncated -* to zero. This should be given as a number of output pixels on either -* side of the central output point in each dimension (the nearest integer -* value is used). - -* Control Flags: -c The following flags are defined in the "ast.h" header file and -f The following flags are defined in the AST_PAR include file and -* may be used to provide additional control over the rebinning -* process. Having selected a set of flags, you should supply the -c bitwise OR of their values via the "flags" parameter: -f sum of their values via the FLAGS argument: -* -* - AST__USEBAD: Indicates that there may be bad pixels in the -* input array(s) which must be recognised by comparing with the -c value given for "badval" and propagated to the output array(s). -f value given for BADVAL and propagated to the output array(s). -* If this flag is not set, all input values are treated literally -c and the "badval" value is only used for flagging output array -f and the BADVAL value is only used for flagging output array -* values. -f - AST__USEVAR: Indicates that variance information should be -f processed in order to provide estimates of the statistical error -f associated with the rebined values. If this flag is not set, -f no variance processing will occur and the IN_VAR and OUT_VAR -f arrays will not be used. (Note that this flag is only available -f in the Fortran interface to AST.) - -* Propagation of Missing Data: -* Instances of missing data (bad pixels) in the output grid are -c identified by occurrences of the "badval" value in the "out" -f identified by occurrences of the BADVAL value in the OUT -* array. These are produced if the sum of the weights of the -* contributing input pixels is less than -c "wlim". -f WLIM. -* -* An input pixel is considered bad (and is consequently ignored) if -* its -c data value is equal to "badval" and the AST__USEBAD flag is -c set via the "flags" parameter. -f data value is equal to BADVAL and the AST__USEBAD flag is -f set via the FLAGS argument. -* -* In addition, associated output variance estimates (if -c calculated) may be declared bad and flagged with the "badval" -c value in the "out_var" array for similar reasons. -f calculated) may be declared bad and flagged with the BADVAL -f value in the OUT_VAR array for similar reasons. -*-- -*/ -/* Define a macro to implement the function for a specific data - type. */ -#define MAKE_REBIN(X,Xtype,IntType) \ -static void Rebin##X( AstMapping *this, double wlim, int ndim_in, \ - const int lbnd_in[], const int ubnd_in[], \ - const Xtype in[], const Xtype in_var[], \ - int spread, const double params[], int flags, \ - double tol, int maxpix, Xtype badval, \ - int ndim_out, const int lbnd_out[], \ - const int ubnd_out[], const int lbnd[], \ - const int ubnd[], Xtype out[], Xtype out_var[], int *status ) { \ -\ -/* Local Variables: */ \ - astDECLARE_GLOBALS /* Thread-specific data */ \ - const char *badflag; /* Name of illegal flag */ \ - AstMapping *simple; /* Pointer to simplified Mapping */ \ - Xtype *d; /* Pointer to next output data value */ \ - Xtype *v; /* Pointer to next output variance value */ \ - double *w; /* Pointer to next weight value */ \ - double *work; /* Pointer to weight array */ \ - int idim; /* Loop counter for coordinate dimensions */ \ - int ipix_out; /* Index into output array */ \ - int nin; /* Number of Mapping input coordinates */ \ - int nout; /* Number of Mapping output coordinates */ \ - int npix; /* Number of pixels in input region */ \ - int npix_out; /* Number of pixels in output array */ \ - int64_t mpix; /* Number of pixels for testing */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Get a pointer to a structure holding thread-specific global data values */ \ - astGET_GLOBALS(this); \ -\ -/* Obtain values for the Nin and Nout attributes of the Mapping. */ \ - nin = astGetNin( this ); \ - nout = astGetNout( this ); \ -\ -/* If OK, check that the number of input grid dimensions matches the \ - number required by the Mapping and is at least 1. Report an error \ - if necessary. */ \ - if ( astOK && ( ( ndim_in != nin ) || ( ndim_in < 1 ) ) ) { \ - astError( AST__NGDIN, "astRebin"#X"(%s): Bad number of input grid " \ - "dimensions (%d).", status, astGetClass( this ), ndim_in ); \ - if ( ndim_in != nin ) { \ - astError( AST__NGDIN, "The %s given requires %d coordinate value%s " \ - "to specify an input position.", status, \ - astGetClass( this ), nin, ( nin == 1 ) ? "" : "s" ); \ - } \ - } \ -\ -/* If OK, also check that the number of output grid dimensions matches \ - the number required by the Mapping and is at least 1. Report an \ - error if necessary. */ \ - if ( astOK && ( ( ndim_out != nout ) || ( ndim_out < 1 ) ) ) { \ - astError( AST__NGDIN, "astRebin"#X"(%s): Bad number of output grid " \ - "dimensions (%d).", status, astGetClass( this ), ndim_out ); \ - if ( ndim_out != nout ) { \ - astError( AST__NGDIN, "The %s given generates %s%d coordinate " \ - "value%s for each output position.", status, astGetClass( this ), \ - ( nout < ndim_out ) ? "only " : "", nout, \ - ( nout == 1 ) ? "" : "s" ); \ - } \ - } \ -\ -/* Check that the lower and upper bounds of the input grid are \ - consistent. Report an error if any pair is not. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - if ( lbnd_in[ idim ] > ubnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astRebin"#X"(%s): Lower bound of " \ - "input grid (%d) exceeds corresponding upper bound " \ - "(%d).", status, astGetClass( this ), \ - lbnd_in[ idim ], ubnd_in[ idim ] ); \ - astError( AST__GBDIN, "Error in input dimension %d.", status, \ - idim + 1 ); \ - break; \ - } else { \ - mpix *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the input. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astRebin"#X"(%s): Supplied input array " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Check that the positional accuracy tolerance supplied is valid and \ - report an error if necessary. */ \ - if ( astOK && ( tol < 0.0 ) ) { \ - astError( AST__PATIN, "astRebin"#X"(%s): Invalid positional " \ - "accuracy tolerance (%.*g pixel).", status, \ - astGetClass( this ), AST__DBL_DIG, tol ); \ - astError( AST__PATIN, "This value should not be less than zero." , status); \ - } \ -\ -/* Check that the initial scale size in pixels supplied is valid and \ - report an error if necessary. */ \ - if ( astOK && ( maxpix < 0 ) ) { \ - astError( AST__SSPIN, "astRebin"#X"(%s): Invalid initial scale " \ - "size in pixels (%d).", status, astGetClass( this ), maxpix ); \ - astError( AST__SSPIN, "This value should not be less than zero." , status); \ - } \ -\ -/* Check that the lower and upper bounds of the output grid are \ - consistent. Report an error if any pair is not. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - if ( lbnd_out[ idim ] > ubnd_out[ idim ] ) { \ - astError( AST__GBDIN, "astRebin"#X"(%s): Lower bound of " \ - "output grid (%d) exceeds corresponding upper bound " \ - "(%d).", status, astGetClass( this ), \ - lbnd_out[ idim ], ubnd_out[ idim ] ); \ - astError( AST__GBDIN, "Error in output dimension %d.", status, \ - idim + 1 ); \ - break; \ - } else { \ - mpix *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the output. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astRebin"#X"(%s): Supplied output array " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Similarly check the bounds of the input region. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - if ( lbnd[ idim ] > ubnd[ idim ] ) { \ - astError( AST__GBDIN, "astRebin"#X"(%s): Lower bound of " \ - "input region (%d) exceeds corresponding upper " \ - "bound (%d).", status, astGetClass( this ), \ - lbnd[ idim ], ubnd[ idim ] ); \ -\ -/* Also check that the input region lies wholly within the input \ - grid. */ \ - } else if ( lbnd[ idim ] < lbnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astRebin"#X"(%s): Lower bound of " \ - "input region (%d) is less than corresponding " \ - "bound of input grid (%d).", status, astGetClass( this ), \ - lbnd[ idim ], lbnd_in[ idim ] ); \ - } else if ( ubnd[ idim ] > ubnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astRebin"#X"(%s): Upper bound of " \ - "input region (%d) exceeds corresponding " \ - "bound of input grid (%d).", status, astGetClass( this ), \ - ubnd[ idim ], ubnd_in[ idim ] ); \ - } else { \ - mpix *= ubnd[ idim ] - lbnd[ idim ] + 1; \ - } \ -\ -/* Say which dimension produced the error. */ \ - if ( !astOK ) { \ - astError( AST__GBDIN, "Error in output dimension %d.", status, \ - idim + 1 ); \ - break; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the input region. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astRebin"#X"(%s): Supplied input region " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* If OK, loop to determine how many input pixels are to be binned. */ \ - simple = NULL; \ - npix = 1; \ - npix_out = 1; \ - unsimplified_mapping = this; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - npix *= ubnd[ idim ] - lbnd[ idim ] + 1; \ - } \ -\ -/* Loop to determine how many pixels the output array contains. */ \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - npix_out *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ - } \ -\ -/* If there are sufficient pixels to make it worthwhile, simplify the \ - Mapping supplied to improve performance. Otherwise, just clone the \ - Mapping pointer. Note we have already saved a pointer to the original \ - Mapping so that lower-level functions can use it if they need to report \ - an error. */ \ - if ( npix > 1024 ) { \ - simple = astSimplify( this ); \ - } else { \ - simple = astClone( this ); \ - } \ - } \ -\ -/* Report an error if the forward transformation of this simplified \ - Mapping is not defined. */ \ - if ( !astGetTranForward( simple ) && astOK ) { \ - astError( AST__TRNND, "astRebin"#X"(%s): An forward coordinate " \ - "transformation is not defined by the %s supplied.", status, \ - astGetClass( unsimplified_mapping ), \ - astGetClass( unsimplified_mapping ) ); \ - } \ -\ -/* Report an error if any illegal flags were supplied. */ \ - if( flags & AST__REBININIT ) { \ - badflag = "AST__REBININIT"; \ - } else if( flags & AST__REBINEND ) { \ - badflag = "AST__REBINEND"; \ - } else if( flags & AST__GENVAR ) { \ - badflag = "AST__GENVAR"; \ - } else if( flags & AST__DISVAR ) { \ - badflag = "AST__DISVAR"; \ - } else if( flags & AST__VARWGT ) { \ - badflag = "AST__VARWGT"; \ - } else if( flags & AST__PARWGT ) { \ - badflag = "AST__PARWGT"; \ - } else if( flags & AST__NONORM ) { \ - badflag = "AST__NONORM"; \ - } else if( flags & AST__CONSERVEFLUX ) { \ - badflag = "AST__CONSERVEFLUX"; \ - } else if( flags & ~( AST__USEBAD + AST__USEVAR ) ) { \ - badflag = "unknown"; \ - } else { \ - badflag = NULL; \ - } \ - if ( badflag && astOK ) { \ - astError( AST__BADFLG, "astRebin"#X"(%s): An illegal flag (%s) " \ - "was included in the 'flags' argument.", status, \ - astGetClass( unsimplified_mapping ), badflag ); \ - } \ -\ -/* If required, allocate work array to hold the sum of the weights \ - contributing to each output pixel, and initialise it to zero. */ \ - if( wlim > 0.0 ) { \ - work = astMalloc( sizeof( double )*(size_t) npix_out ); \ - if( work ) { \ - w = work; \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++ ) *(w++) = 0.0; \ - } \ - } else { \ - work = NULL; \ - } \ -\ -/* Initialise the output arrays to hold zeros. */ \ - d = out; \ - if( out_var ) { \ - v = out_var; \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, d++, v++ ) { \ - *d = 0; \ - *v = 0; \ - } \ - } else { \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, d++ ) { \ - *d = 0; \ - } \ - } \ -\ -/* Perform the rebinning. Note that we pass all gridded data, the \ - spread function and the bad pixel value by means of pointer \ - types that obscure the underlying data type. This is to avoid \ - having to replicate functions unnecessarily for each data \ - type. However, we also pass an argument that identifies the data \ - type we have obscured. */ \ - if( RebinAdaptively( simple, ndim_in, lbnd_in, ubnd_in, \ - (const void *) in, (const void *) in_var, \ - TYPE_##X, spread, \ - params, flags, tol, maxpix, \ - (const void *) &badval, \ - ndim_out, lbnd_out, ubnd_out, \ - lbnd, ubnd, npix_out, \ - (void *) out, (void *) out_var, work, \ - NULL, status ) && astOK ) { \ - astError( AST__CNFLX, "astRebin"#X"(%s): Flux conservation was " \ - "requested but could not be performed because the " \ - "forward transformation of the supplied Mapping " \ - "is too non-linear.", status, astGetClass( this ) ); \ - } \ -\ -/* If required set output pixels bad if they have a total weight less \ - than "wlim". */ \ - if( work ) { \ - w = work; \ - d = out; \ - if( out_var ) { \ - v = out_var; \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, d++, w++, v++ ) { \ - if( fabs( *w ) < wlim ) { \ - *d = badval; \ - *v = badval; \ - } \ - } \ - } else { \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, d++, w++ ) { \ - if( fabs( *w ) < wlim ) *d = badval; \ - } \ - } \ -\ -/* Free the work array. */ \ - work = astFree( work ); \ - } \ -\ -/* Annul the pointer to the simplified/cloned Mapping. */ \ - simple = astAnnul( simple ); \ -\ -} - -/* Expand the above macro to generate a function for each required - data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_REBIN(LD,long double,0) -#endif -MAKE_REBIN(D,double,0) -MAKE_REBIN(F,float,0) -MAKE_REBIN(I,int,1) -MAKE_REBIN(B,signed char,1) -MAKE_REBIN(UB,unsigned char,1) - -/* Undefine the macro. */ -#undef MAKE_REBIN - -static int RebinAdaptively( AstMapping *this, int ndim_in, - const int *lbnd_in, const int *ubnd_in, - const void *in, const void *in_var, - DataType type, int spread, - const double *params, int flags, double tol, - int maxpix, const void *badval_ptr, - int ndim_out, const int *lbnd_out, - const int *ubnd_out, const int *lbnd, - const int *ubnd, int npix_out, - void *out, void *out_var, double *work, - int64_t *nused, int *status ){ -/* -* Name: -* RebinAdaptively - -* Purpose: -* Rebin a section of a data grid adaptively. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int RebinAdaptively( AstMapping *this, int ndim_in, -* const int *lbnd_in, const int *ubnd_in, -* const void *in, const void *in_var, -* DataType type, int spread, -* const double *params, int flags, double tol, -* int maxpix, const void *badval_ptr, -* int ndim_out, const int *lbnd_out, -* const int *ubnd_out, const int *lbnd, -* const int *ubnd, int npix_out, void *out, -* void *out_var, double *work, int64_t *nused, -* int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function rebins a specified section of a rectangular grid of -* data (with any number of dimensions) into another rectangular grid -* (with a possibly different number of dimensions). The coordinate -* transformation used to convert input pixel coordinates into positions -* in the output grid is given by the forward transformation of the -* Mapping which is supplied. Any pixel spreading scheme may be specified -* for distributing the flux of an input pixel amongst the output -* pixels. -* -* This function is very similar to RebinWithBlocking and RebinSection -* which lie below it in the calling hierarchy. However, this function -* also attempts to adapt to the Mapping supplied and to sub-divide the -* section being rebinned into smaller sections within which a linear -* approximation to the Mapping may be used. This reduces the number of -* Mapping evaluations, thereby improving efficiency particularly when -* complicated Mappings are involved. - -* Parameters: -* this -* Pointer to a Mapping, whose forward transformation may be -* used to transform the coordinates of pixels in the input -* grid into associated positions in the output grid. -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* in -* Pointer to the input array of data to be rebinned (with one -* element for each pixel in the input grid). The numerical type -* of these data should match the "type" value (below). The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and data type as the "in" array), -* which represent estimates of the statistical variance -* associated with each element of the "in" array. If this -* second array is given (along with the corresponding "out_var" -* array), then estimates of the variance of the rebinned data -* will also be returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* type -* A value taken from the "DataType" enum, which specifies the -* data type of the input and output arrays containing the -* gridded data (and variance) values. -* spread -* A value selected from a set of pre-defined macros to identify -* which pixel spread function should be used. -* params -* Pointer to an optional array of parameters that may be passed -* to the pixel spread algorithm, if required. If no parameters -* are required, a NULL pointer should be supplied. -* flags -* The bitwise OR of a set of flag values which provide additional -* control over the resampling operation. -* tol -* The maximum permitted positional error in transforming input -* pixel positions into the output grid in order to rebin -* it. This should be expressed as a displacement in pixels in -* the output grid's coordinate system. If the Mapping's forward -* transformation can be approximated by piecewise linear functions -* to this accuracy, then such functions may be used instead of the -* Mapping in order to improve performance. Otherwise, every input -* pixel position will be transformed individually using the Mapping. -* -* If linear approximation is not required, a "tol" value of -* zero may be given. This will ensure that the Mapping is used -* without any approximation. -* maxpix -* A value which specifies the largest scale size on which to -* search for non-linearities in the Mapping supplied. This -* value should be expressed as a number of pixels in the input -* grid. The function will break the input section specified -* into smaller sub-sections (if necessary), each no larger than -* "maxpix" pixels in any dimension, before it attempts to -* approximate the Mapping by a linear function over each -* sub-section. -* -* If the value given is larger than the largest dimension of -* the input section (the normal recommendation), the function -* will initially search for non-linearity on a scale determined -* by the size of the input section. This is almost always -* satisfactory. Very occasionally, however, a Mapping may -* appear linear on this scale but nevertheless have smaller -* irregularities (e.g. "holes") in it. In such cases, "maxpix" -* may be set to a suitably smaller value so as to ensure this -* non-linearity is not overlooked. Typically, a value of 50 to -* 100 pixels might be suitable and should have little effect on -* performance. -* -* If too small a value is given, however, it will have the -* effect of preventing linear approximation occurring at all -* (equivalent to setting "tol" to zero). Although this may -* degrade performance, accurate results will still be obtained. -* badval_ptr -* If the AST__USEBAD flag is set (above), this parameter is a -* pointer to a value which is used to identify bad data and/or -* variance values in the input array(s). The referenced value's -* data type must match that of the "in" (and "in_var") -* arrays. The same value will also be used to flag any output -* array elements for which rebinned values could not be -* obtained. The output arrays(s) may be flagged with this -* value whether or not the AST__USEBAD flag is set (the -* function return value indicates whether any such values have -* been produced). -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output data grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output data grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output data grid in the same way as "lbnd_in" -* and "ubnd_in" define the shape and size of the input grid -* (see above). -* lbnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the first pixel in the -* section of the input data grid which is to be rebinned. -* ubnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the last pixel in the -* section of the input data grid which is to be rebinned. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the input grid which is to be rebinned. This section -* should lie wholly within the extent of the input grid (as defined -* by the "lbnd_out" and "ubnd_out" arrays). Regions of the input -* grid lying outside this section will be ignored. -* npix_out -* The number of pixels in the output array. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the rebinned data will be returned. The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the rebinned values may be returned. This array will only be -* used if the "in_var" array has been given. -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* work -* An optional pointer to a double array with the same size as -* the "out" array. The contents of this array (if supplied) are -* incremented by the accumulated weights assigned to each output pixel. -* If no accumulated weights are required, a NULL pointer should be -* given. -* nused -* An optional pointer to a int64_t which will be incremented by the -* number of input values pasted into the output array. Ignored if NULL. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if "flags" included AST__CONSERVEFLUX (i.e. -* flux conservation was requested), but the forward transformation of the -* supplied Mapping had zero determinant everywhere within the region -* being binned (no error is reported if this happens). Zero is returned -* otherwise. - -*/ - -/* Local Variables: */ - double *flbnd; /* Array holding floating point lower bounds */ - double *fubnd; /* Array holding floating point upper bounds */ - double *linear_fit; /* Pointer to array of fit coefficients */ - int *hi; /* Pointer to array of section upper bounds */ - int *lo; /* Pointer to array of section lower bounds */ - int coord_in; /* Loop counter for input coordinates */ - int dim; /* Output section dimension size */ - int dimx; /* Dimension with maximum section extent */ - int divide; /* Sub-divide the output section? */ - int i; /* Loop count */ - int isLinear; /* Is the transformation linear? */ - int mxdim; /* Largest output section dimension size */ - int need_fit; /* Do we need to perform a linear fit? */ - int npix; /* Number of pixels in output section */ - int npoint; /* Number of points for obtaining a fit */ - int nvertex; /* Number of vertices of output section */ - int result; /* Returned value */ - int res1; /* Flux conservation error in 1st section? */ - int res2; /* Flux conservation error in 2nd section? */ - int toobig; /* Section too big (must sub-divide)? */ - int toosmall; /* Section too small to sub-divide? */ - -/* Initialise */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialisation. */ - npix = 1; - mxdim = 0; - dimx = 1; - nvertex = 1; - -/* Loop through the input grid dimensions. */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - -/* Obtain the extent in each dimension of the input section which is - to be rebinned, and calculate the total number of pixels it contains. */ - dim = ubnd[ coord_in ] - lbnd[ coord_in ] + 1; - npix *= dim; - -/* Find the maximum dimension size of this input section and note which - dimension has this size. */ - if ( dim > mxdim ) { - mxdim = dim; - dimx = coord_in; - } - -/* Calculate how many vertices the output section has. */ - nvertex *= 2; - } - -/* Calculate how many sample points will be needed (by the astLinearApprox - function) to obtain a linear fit to the Mapping's forward transformation. */ - npoint = 1 + 4 * ndim_in + 2 * nvertex; - -/* If the number of pixels in the input section is not at least 4 - times this number, we will probably not save significant time by - attempting to obtain a linear fit, so note that the input section - is too small. */ - toosmall = ( npix < ( 4 * npoint ) ); - -/* Note if the maximum dimension of the input section exceeds the - user-supplied scale factor. */ - toobig = ( maxpix < mxdim ); - -/* Indicate we do not yet have a linear fit. */ - linear_fit = NULL; - -/* Initialise a flag indicating if we need to perform a linear fit. This - is always the case if flux conservation was requested. */ - need_fit = ( flags & AST__CONSERVEFLUX ); - -/* If the output section is too small to be worth obtaining a linear - fit, or if the accuracy tolerance is zero, we will not - sub-divide. This means that the Mapping will be used to transform - each pixel's coordinates and no linear approximation will be - used. */ - if ( toosmall || ( tol == 0.0 ) ) { - divide = 0; - -/* Otherwise, if the largest input section dimension exceeds the - scale length given, we will sub-divide. This offers the possibility - of obtaining a linear approximation to the Mapping over a reduced - range of input coordinates (which will be handled by a recursive - invocation of this function). */ - } else if ( toobig ) { - divide = 1; - -/* If neither of the above apply, we need to do a fit regardless of - whether flux conservation was requested or not. Whether we divide or - not will depend on whether the Mapping is linear or not. Assume for - the moment that the Mapping is not linear and so we will divide. */ - } else { - need_fit = 1; - divide = 1; - } - -/* If required, attempt to fit a linear approximation to the Mapping's - forward transformation over the range of coordinates covered by the - input section. We need to temporarily copy the integer bounds into - floating point arrays to use astLinearApprox. */ - if( need_fit ) { - -/* Allocate memory for floating point bounds and for the coefficient array */ - flbnd = astMalloc( sizeof( double )*(size_t) ndim_in ); - fubnd = astMalloc( sizeof( double )*(size_t) ndim_in ); - linear_fit = astMalloc( sizeof( double )* - (size_t) ( ndim_out*( ndim_in + 1 ) ) ); - if( astOK ) { - -/* Copy the bounds into these arrays, and change them so that they refer - to the lower and upper edges of the cell rather than the centre. This - is essential if one of the axes is spanned by a single cell, since - otherwise the upper and lower bounds would be identical. */ - for( i = 0; i < ndim_in; i++ ) { - flbnd[ i ] = (double) lbnd[ i ] - 0.5; - fubnd[ i ] = (double) ubnd[ i ] + 0.5; - } - -/* Get the linear approximation to the forward transformation. */ - isLinear = astLinearApprox( this, flbnd, fubnd, tol, linear_fit ); - -/* Free the coeff array if the inverse transformation is not linear. */ - if( !isLinear ) linear_fit = astFree( linear_fit ); - - } else { - linear_fit = astFree( linear_fit ); - } - -/* Free resources */ - flbnd = astFree( flbnd ); - fubnd = astFree( fubnd ); - -/* If a linear fit was obtained, we will use it and therefore do not - wish to sub-divide further. Otherwise, we sub-divide (unless the - section is too small or too big as determined earlier) in the hope - that this may result in a linear fit next time. */ - if( linear_fit ) divide = 0; - } - -/* If no sub-division is required, perform rebinning (in a - memory-efficient manner, since the section we are rebinning might - still be very large). This will use the linear fit, if obtained - above. */ - if ( astOK ) { - if ( !divide ) { - result = RebinWithBlocking( this, linear_fit, ndim_in, lbnd_in, - ubnd_in, in, in_var, type, spread, - params, flags, badval_ptr, ndim_out, - lbnd_out, ubnd_out, lbnd, ubnd, npix_out, - out, out_var, work, nused, status ); - -/* Otherwise, allocate workspace to perform the sub-division. */ - } else { - lo = astMalloc( sizeof( int ) * (size_t) ndim_in ); - hi = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Initialise the bounds of a new input section to match the original - input section. */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - lo[ coord_in ] = lbnd[ coord_in ]; - hi[ coord_in ] = ubnd[ coord_in ]; - } - -/* Replace the upper bound of the section's largest dimension with the - mid-point of the section along this dimension, rounded downwards. */ - hi[ dimx ] = - (int) floor( 0.5 * (double) ( lbnd[ dimx ] + ubnd[ dimx ] ) ); - -/* Rebin the resulting smaller section using a recursive invocation - of this function. */ - res1 = RebinAdaptively( this, ndim_in, lbnd_in, ubnd_in, in, - in_var, type, spread, params, - flags, tol, maxpix, badval_ptr, ndim_out, - lbnd_out, ubnd_out, lo, hi, npix_out, out, - out_var, work, nused, status ); - -/* Now set up a second section which covers the remaining half of the - original input section. */ - lo[ dimx ] = hi[ dimx ] + 1; - hi[ dimx ] = ubnd[ dimx ]; - -/* If this section contains pixels, resample it in the same way, - summing the returned values. */ - if ( lo[ dimx ] <= hi[ dimx ] ) { - res2 = RebinAdaptively( this, ndim_in, lbnd_in, ubnd_in, in, - in_var, type, spread, params, - flags, tol, maxpix, badval_ptr, - ndim_out, lbnd_out, ubnd_out, - lo, hi, npix_out, out, out_var, work, - nused, status ); - } else { - res2 = 0; - } - -/* If neither section could be rebinned because of an indeterminant - mapping, return a result indicating this. */ - result = ( res1 && res2 ); - } - -/* Free the workspace. */ - lo = astFree( lo ); - hi = astFree( hi ); - } - } - -/* If coefficients for a linear fit were obtained, then free the space - they occupy. */ - if ( linear_fit ) linear_fit = astFree( linear_fit ); - -/* Retyurn a flag indicating if no part of the array could be binned - because of an indeterminate Mapping. */ - return result; -} - -static void RebinSection( AstMapping *this, const double *linear_fit, - int ndim_in, const int *lbnd_in, const int *ubnd_in, - const void *in, const void *in_var, double infac, - DataType type, int spread, const double *iparams, - int flags, const void *badval_ptr, int ndim_out, - const int *lbnd_out, const int *ubnd_out, - const int *lbnd, const int *ubnd, int npix_out, - void *out, void *out_var, double *work, - int64_t *nused, int *status ) { -/* -* Name: -* RebinSection - -* Purpose: -* Rebin a section of a data grid. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void RebinSection( AstMapping *this, const double *linear_fit, -* int ndim_in, const int *lbnd_in, const int *ubnd_in, -* const void *in, const void *in_var, double infac, -* DataType type, int spread, const double *iparams, -* int flags, const void *badval_ptr, int ndim_out, -* const int *lbnd_out, const int *ubnd_out, -* const int *lbnd, const int *ubnd, int npix_out, -* void *out, void *out_var, double *work, -* int64_t *nused, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function rebins a specified section of a rectangular grid of -* data (with any number of dimensions) into another rectangular grid -* (with a possibly different number of dimensions). The coordinate -* transformation used to convert input pixel coordinates into positions -* in the output grid is given by the forward transformation of the -* Mapping which is supplied or, alternatively, by a linear approximation -* fitted to a Mapping's forward transformation. Any pixel spreading scheme -* may be specified for distributing the flux of an input pixel amongst -* the output pixels. - -* Parameters: -* this -* Pointer to a Mapping, whose forward transformation may be -* used to transform the coordinates of pixels in the input -* grid into associated positions in the output grid. -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* linear_fit -* Pointer to an optional array of double which contains the -* coefficients of a linear fit which approximates the above -* Mapping's forward coordinate transformation. If this is -* supplied, it will be used in preference to the above Mapping -* when transforming coordinates. This may be used to enhance -* performance in cases where evaluation of the Mapping's -* forward transformation is expensive. If no linear fit is -* available, a NULL pointer should be supplied. -* -* The way in which the fit coefficients are stored in this -* array and the number of array elements are as defined by the -* astLinearApprox function. -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* in -* Pointer to the input array of data to be rebinned (with one -* element for each pixel in the input grid). The numerical type -* of these data should match the "type" value (below). The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and data type as the "in" array), -* which represent estimates of the statistical variance -* associated with each element of the "in" array. If this -* second array is given (along with the corresponding "out_var" -* array), then estimates of the variance of the rebinned data -* will also be returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* infac -* A factor by which to multiply the input data values before use. -* type -* A value taken from the "DataType" enum, which specifies the -* data type of the input and output arrays containing the -* gridded data (and variance) values. -* spread -* A value selected from a set of pre-defined macros to identify -* which pixel spread function should be used. -* iparams -* Pointer to an optional array of parameters that may be passed -* to the pixel spread algorithm, if required. If no parameters -* are required, a NULL pointer should be supplied. -* flags -* The bitwise OR of a set of flag values which provide additional -* control over the resampling operation. -* badval_ptr -* If the AST__USEBAD flag is set (above), this parameter is a -* pointer to a value which is used to identify bad data and/or -* variance values in the input array(s). The referenced value's -* data type must match that of the "in" (and "in_var") -* arrays. The same value will also be used to flag any output -* array elements for which rebinned values could not be -* obtained. The output arrays(s) may be flagged with this -* value whether or not the AST__USEBAD flag is set (the -* function return value indicates whether any such values have -* been produced). -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output data grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output data grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output data grid in the same way as "lbnd_in" -* and "ubnd_in" define the shape and size of the input grid -* (see above). -* lbnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the first pixel in the -* section of the input data grid which is to be rebinned. -* ubnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the last pixel in the -* section of the input data grid which is to be rebinned. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the input grid which is to be rebinned. This section -* should lie wholly within the extent of the input grid (as defined -* by the "lbnd_out" and "ubnd_out" arrays). Regions of the input -* grid lying outside this section will be ignored. -* npix_out -* The number of pixels in the output array. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the rebinned data will be returned. The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the rebinned values may be returned. This array will only be -* used if the "in_var" array has been given. -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* work -* An optional pointer to a double array with the same size as -* the "out" array. The contents of this array (if supplied) are -* incremented by the accumulated weights assigned to each output pixel. -* If no accumulated weights are required, a NULL pointer should be -* given. -* nused -* An optional pointer to a int64_t which will be incremented by the -* number of input values pasted into the output array. Ignored if NULL. - -* Notes: -* - This function does not take steps to limit memory usage if the -* grids supplied are large. To resample large grids in a more -* memory-efficient way, the ResampleWithBlocking function should -* be used. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific data */ - AstPointSet *pset_in; /* Input PointSet for transformation */ - AstPointSet *pset_out; /* Output PointSet for transformation */ - const double *params; /* Pointer to spreading scheme parameters */ - const double *grad; /* Pointer to gradient matrix of linear fit */ - const double *zero; /* Pointer to zero point array of fit */ - double **ptr_in; /* Pointer to input PointSet coordinates */ - double **ptr_out; /* Pointer to output PointSet coordinates */ - double *accum; /* Pointer to array of accumulated sums */ - double conwgt; /* Constant weight for all pixels */ - double x1; /* Interim x coordinate value */ - double xx1; /* Initial x coordinate value */ - double y1; /* Interim y coordinate value */ - double yy1; /* Initial y coordinate value */ - int *dim; /* Pointer to array of output pixel indices */ - int *offset; /* Pointer to array of output pixel offsets */ - int *stride; /* Pointer to array of output grid strides */ - int coord_in; /* Loop counter for input dimensions */ - int coord_out; /* Loop counter for output dimensions */ - int done; /* All pixel indices done? */ - int i1; /* Interim offset into "accum" array */ - int i2; /* Final offset into "accum" array */ - int idim; /* Loop counter for dimensions */ - int ix; /* Loop counter for output x coordinate */ - int iy; /* Loop counter for output y coordinate */ - int neighb; /* Number of neighbouring pixels */ - int npoint; /* Number of output points (pixels) */ - int off1; /* Interim pixel offset into output array */ - int off2; /* Interim pixel offset into output array */ - int off; /* Final pixel offset into output array */ - int point; /* Counter for output points (pixels ) */ - int s; /* Temporary variable for strides */ - const double *par; /* Pointer to parameter array */ - double fwhm; /* Full width half max. of gaussian */ - double lpar[ 1 ]; /* Local parameter array */ - void (* kernel)( double, const double [], int, double *, int * ); /* Kernel fn. */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to a structure holding thread-specific global data values */ - astGET_GLOBALS(this); - -/* Further initialisation. */ - pset_in = NULL; - ptr_in = NULL; - ptr_out = NULL; - pset_out = NULL; - neighb = 0; - kernel = NULL; - -/* If a constant weight is to be factored in to all pixels, it will have - been supplied as the first value in the "params" array, with the remaining - values being the actual parameters of the requested spreading scheme. - Copy the constant weight into another value and modify the pointer to the - start of the params array to exclude it. */ - if( flags & AST__PARWGT ) { - params = iparams + 1; - conwgt = iparams[ 0 ]; - } else { - params = iparams; - conwgt = 1.0; - } - -/* Calculate the number of input points, as given by the product of - the input grid dimensions. */ - for ( npoint = 1, coord_in = 0; coord_in < ndim_in; coord_in++ ) { - npoint *= ubnd[ coord_in ] - lbnd[ coord_in ] + 1; - } - -/* Allocate workspace. */ - offset = astMalloc( sizeof( int ) * (size_t) npoint ); - stride = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Calculate the stride for each input grid dimension. */ - off = 0; - s = 1; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - stride[ coord_in ] = s; - s *= ubnd_in[ coord_in ] - lbnd_in[ coord_in ] + 1; - } - -/* A linear fit to the Mapping is available. */ -/* ========================================= */ - if ( linear_fit ) { - -/* If a linear fit to the Mapping has been provided, then obtain - pointers to the array of gradients and zero-points comprising the - fit. */ - grad = linear_fit + ndim_out; - zero = linear_fit; - -/* Create a PointSet to hold the output grid coordinates and obtain an - array of pointers to its coordinate data. */ - pset_out = astPointSet( npoint, ndim_out, "", status ); - ptr_out = astGetPoints( pset_out ); - if ( astOK ) { - -/* Initialise the count of input points. */ - point = 0; - -/* Handle the 1-dimensional case optimally. */ -/* ---------------------------------------- */ - if ( ( ndim_in == 1 ) && ( ndim_out == 1 ) ) { - -/* Loop through the pixels of the input grid and transform their x - coordinates into the output grid's coordinate system using the - linear fit supplied. Store the results in the PointSet created - above. */ - off = lbnd[ 0 ] - lbnd_in[ 0 ]; - xx1 = zero[ 0 ] + grad[ 0 ] * (double) lbnd[ 0 ]; - - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_out[ 0 ][ point ] = xx1; - xx1 += grad[ 0 ]; - offset[ point++ ] = off++; - } - -/* Handle the 2-dimensional case optimally. */ -/* ---------------------------------------- */ - } else if ( ( ndim_in == 2 ) && ( ndim_out == 2 ) ) { - -/* Loop through the range of y coordinates in the input grid and - calculate interim values of the output coordinates using the linear - fit supplied. */ - x1 = zero[ 0 ] + grad[ 1 ] * (double) ( lbnd[ 1 ] - 1 ); - y1 = zero[ 1 ] + grad[ 3 ] * (double) ( lbnd[ 1 ] - 1 ); - off1 = stride[ 1 ] * ( lbnd[ 1 ] - lbnd_in[ 1 ] - 1 ) - lbnd_in[ 0 ]; - for ( iy = lbnd[ 1 ]; iy <= ubnd[ 1 ]; iy++ ) { - x1 += grad[ 1 ]; - y1 += grad[ 3 ]; - -/* Also calculate an interim pixel offset into the input array. */ - off1 += stride[ 1 ]; - -/* Now loop through the range of input x coordinates and calculate - the final values of the input coordinates, storing the results in - the PointSet created above. */ - xx1 = x1 + grad[ 0 ] * (double) lbnd[ 0 ]; - yy1 = y1 + grad[ 2 ] * (double) lbnd[ 0 ]; - off = off1 + lbnd[ 0 ]; - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_out[ 0 ][ point ] = xx1; - xx1 += grad[ 0 ]; - ptr_out[ 1 ][ point ] = yy1; - yy1 += grad[ 2 ]; - -/* Also calculate final pixel offsets into the input array. */ - offset[ point++ ] = off++; - } - } - -/* Handle other numbers of dimensions. */ -/* ----------------------------------- */ - } else { - -/* Allocate workspace. */ - accum = astMalloc( sizeof( double ) * - (size_t) ( ndim_in * ndim_out ) ); - dim = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Initialise an array of pixel indices for the input grid which refer to the - first pixel which we will rebin. Also calculate the offset of this pixel - within the input array. */ - off = 0; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - dim[ coord_in ] = lbnd[ coord_in ]; - off += stride[ coord_in ] * - ( dim[ coord_in ] - lbnd_in[ coord_in ] ); - } - -/* To calculate each output grid coordinate we must perform a matrix - multiply on the input grid coordinates (using the gradient matrix) - and then add the zero points. However, since we will usually only - be altering one input coordinate at a time (the least - significant), we can avoid the full matrix multiply by accumulating - partial sums for the most significant input coordinates and only - altering those sums which need to change each time. The zero points - never change, so we first fill the "most significant" end of the - "accum" array with these. */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - accum[ ( coord_out + 1 ) * ndim_in - 1 ] = - zero[ coord_out ]; - } - coord_in = ndim_in - 1; - -/* Now loop to process each input pixel. */ - for ( done = 0; !done; point++ ) { - -/* To generate the output coordinate that corresponds to the current - input pixel, we work down from the most significant dimension - whose index has changed since the previous pixel we considered - (given by "coord_in"). For each affected dimension, we accumulate - in "accum" the matrix sum (including the zero point) for that - dimension and all higher input dimensions. We must accumulate a - separate set of sums for each output coordinate we wish to - produce. (Note that for the first pixel we process, all dimensions - are considered "changed", so we start by initialising the whole - "accum" array.) */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { -/* - ptr_out[ coord_out ][ point ] = zero[ coord_out ]; - for ( idim = 0; idim < ndim_in; idim++ ) { - ptr_out[ coord_out ][ point ] += - grad[ idim + coord_out*ndim_in ] * - dim[ idim ]; - } -*/ - - i1 = coord_out * ndim_in; - for ( idim = coord_in; idim >= 1; idim-- ) { - i2 = i1 + idim; - accum[ i2 - 1 ] = accum[ i2 ] + - dim[ idim ] * grad[ i2 ]; - } - -/* The output coordinate for each dimension is given by the accumulated - sum for input dimension zero (giving the sum over all input - dimensions). We do not store this in the "accum" array, but assign - the result directly to the coordinate array of the PointSet created - earlier. */ - ptr_out[ coord_out ][ point ] = accum[ i1 ] + - dim[ 0 ] * grad[ i1 ]; - } - -/* Store the offset of the current pixel in the input array. */ - offset[ point ] = off; - -/* Now update the array of pixel indices to refer to the next input pixel. */ - coord_in = 0; - do { - -/* The least significant index which currently has less than its maximum - value is incremented by one. The offset into the input array is updated - accordingly. */ - if ( dim[ coord_in ] < ubnd[ coord_in ] ) { - dim[ coord_in ]++; - off += stride[ coord_in ]; - break; - -/* Any less significant indices which have reached their maximum value - are returned to their minimum value and the input pixel offset is - decremented appropriately. */ - } else { - dim[ coord_in ] = lbnd[ coord_in ]; - off -= stride[ coord_in ] * - ( ubnd[ coord_in ] - lbnd[ coord_in ] ); - -/* All the output pixels have been processed once the most significant - pixel index has been returned to its minimum value. */ - done = ( ++coord_in == ndim_in ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - accum = astFree( accum ); - dim = astFree( dim ); - } - } - -/* No linear fit to the Mapping is available. */ -/* ========================================== */ - } else { - -/* Create a PointSet to hold the coordinates of the input pixels and - obtain a pointer to its coordinate data. */ - pset_in = astPointSet( npoint, ndim_in, "", status ); - ptr_in = astGetPoints( pset_in ); - if ( astOK ) { - -/* Initialise the count of input points. */ - point = 0; - -/* Handle the 1-dimensional case optimally. */ -/* ---------------------------------------- */ - if ( ndim_in == 1 && ndim_out == 1 ) { - -/* Loop through the required range of input x coordinates, assigning - the coordinate values to the PointSet created above. Also store a - pixel offset into the input array. */ - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_in[ 0 ][ point ] = (double) ix; - offset[ point++ ] = ix - lbnd_in[ 0 ]; - } - -/* Handle the 2-dimensional case optimally. */ -/* ---------------------------------------- */ - } else if ( ndim_in == 2 && ndim_out == 2) { - -/* Loop through the required range of input y coordinates, - calculating an interim pixel offset into the input array. */ - off1 = stride[ 1 ] * ( lbnd[ 1 ] - lbnd_in[ 1 ] - 1 ) - - lbnd_in[ 0 ]; - for ( iy = lbnd[ 1 ]; iy <= ubnd[ 1 ]; iy++ ) { - off1 += stride[ 1 ]; - -/* Loop through the required range of input x coordinates, assigning - the coordinate values to the PointSet created above. Also store a - final pixel offset into the input array. */ - off2 = off1 + lbnd[ 0 ]; - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_in[ 0 ][ point ] = (double) ix; - ptr_in[ 1 ][ point ] = (double) iy; - offset[ point++ ] = off2++; - } - } - -/* Handle other numbers of dimensions. */ -/* ----------------------------------- */ - } else { - -/* Allocate workspace. */ - dim = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Initialise an array of pixel indices for the input grid which - refer to the first pixel to be rebinned. Also calculate the offset - of this pixel within the input array. */ - off = 0; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - dim[ coord_in ] = lbnd[ coord_in ]; - off += stride[ coord_in ] * - ( dim[ coord_in ] - lbnd_in[ coord_in ] ); - } - -/* Loop to generate the coordinates of each input pixel. */ - for ( done = 0; !done; point++ ) { - -/* Copy each pixel's coordinates into the PointSet created above. */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - ptr_in[ coord_in ][ point ] = - (double) dim[ coord_in ]; - } - -/* Store the offset of the pixel in the input array. */ - offset[ point ] = off; - -/* Now update the array of pixel indices to refer to the next input - pixel. */ - coord_in = 0; - do { - -/* The least significant index which currently has less than its - maximum value is incremented by one. The offset into the input - array is updated accordingly. */ - if ( dim[ coord_in ] < ubnd[ coord_in ] ) { - dim[ coord_in ]++; - off += stride[ coord_in ]; - break; - -/* Any less significant indices which have reached their maximum value - are returned to their minimum value and the input pixel offset is - decremented appropriately. */ - } else { - dim[ coord_in ] = lbnd[ coord_in ]; - off -= stride[ coord_in ] * - ( ubnd[ coord_in ] - lbnd[ coord_in ] ); - -/* All the input pixels have been processed once the most significant - pixel index has been returned to its minimum value. */ - done = ( ++coord_in == ndim_in ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - dim = astFree( dim ); - } - -/* When all the input pixel coordinates have been generated, use the - Mapping's forward transformation to generate the output coordinates - from them. Obtain an array of pointers to the resulting coordinate - data. */ - pset_out = astTransform( this, pset_in, 1, NULL ); - ptr_out = astGetPoints( pset_out ); - } - -/* Annul the PointSet containing the input coordinates. */ - pset_in = astAnnul( pset_in ); - } - } - - -/* Rebin the input grid. */ -/* ------------------------ */ - if( astOK ) { - -/* Identify the pixel spreading scheme to be used. */ -/* Nearest pixel. */ -/* -------------- */ - switch ( spread ) { - case AST__NEAREST: - -/* Define a macro to use a "case" statement to invoke the - nearest-pixel spreading function appropriate to a given data - type. */ -#define CASE_NEAREST(X,Xtype) \ - case ( TYPE_##X ): \ - SpreadNearest##X( ndim_out, lbnd_out, ubnd_out, \ - (Xtype *) in, (Xtype *) in_var, \ - infac, npoint, offset, \ - (const double *const *) ptr_out, \ - conwgt, flags, *( (Xtype *) badval_ptr ), \ - npix_out, (Xtype *) out, \ - (Xtype *) out_var, work, nused, status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_NEAREST(LD,long double) -#endif - CASE_NEAREST(D,double) - CASE_NEAREST(F,float) - CASE_NEAREST(I,int) - CASE_NEAREST(B,signed char) - CASE_NEAREST(UB,unsigned char) - - case ( TYPE_L ): break; - case ( TYPE_K ): break; - case ( TYPE_S ): break; - case ( TYPE_UL ): break; - case ( TYPE_UI ): break; - case ( TYPE_UK ): break; - case ( TYPE_US ): break; - } - break; - -/* Undefine the macro. */ -#undef CASE_NEAREST - -/* Linear spreading. */ -/* ----------------- */ -/* Note this is also the default if zero is given. */ - case AST__LINEAR: - case 0: - -/* Define a macro to use a "case" statement to invoke the linear - spreading function appropriate to a given data type. */ -#define CASE_LINEAR(X,Xtype) \ - case ( TYPE_##X ): \ - SpreadLinear##X( ndim_out, lbnd_out, ubnd_out,\ - (Xtype *) in, (Xtype *) in_var, \ - infac, npoint, offset, \ - (const double *const *) ptr_out, \ - conwgt, flags, *( (Xtype *) badval_ptr ), \ - npix_out, (Xtype *) out, \ - (Xtype *) out_var, work, nused, status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_LINEAR(LD,long double) -#endif - CASE_LINEAR(D,double) - CASE_LINEAR(F,float) - CASE_LINEAR(I,int) - CASE_LINEAR(B,signed char) - CASE_LINEAR(UB,unsigned char) - - case ( TYPE_L ): break; - case ( TYPE_K ): break; - case ( TYPE_S ): break; - case ( TYPE_UL ): break; - case ( TYPE_UI ): break; - case ( TYPE_UK ): break; - case ( TYPE_US ): break; - } - break; - -/* Undefine the macro. */ -#undef CASE_LINEAR - -/* Spreading using a 1-d kernel. */ -/* ----------------------------- */ - case AST__SINC: - case AST__SINCCOS: - case AST__SINCGAUSS: - case AST__GAUSS: - case AST__SINCSINC: - case AST__SOMB: - case AST__SOMBCOS: - -/* Obtain a pointer to the appropriate 1-d kernel function (either - internal or user-defined) and set up any parameters it may - require. */ - par = NULL; - switch ( spread ) { - -/* sinc(pi*x) */ -/* ---------- */ -/* Assign the kernel function. */ - case AST__SINC: - kernel = Sinc; - -/* Calculate the number of neighbouring pixels to use. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) { - neighb = 2; - } else { - neighb = MaxI( 1, neighb, status ); - } - break; - -/* somb(pi*x) */ -/* ---------- */ -/* Assign the kernel function. */ - case AST__SOMB: - kernel = Somb; - -/* Calculate the number of neighbouring pixels to use. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) { - neighb = 2; - } else { - neighb = MaxI( 1, neighb, status ); - } - break; - -/* sinc(pi*x)*cos(k*pi*x) */ -/* ---------------------- */ -/* Assign the kernel function. */ - case AST__SINCCOS: - kernel = SincCos; - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 0.5 / MaxD( 1.0, params[ 1 ], status ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, the number will be calculated automatically below. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = INT_MAX; - -/* Calculate the maximum number of neighbouring pixels required by the - width of the kernel, and use this value if preferable. */ - neighb = MinI( neighb, - (int) ceil( MaxD( 1.0, params[ 1 ], status ) ), status ); - break; - -/* sinc(pi*x)*exp(-k*x*x) */ -/* ---------------------- */ -/* Assign the kernel function. */ - case AST__SINCGAUSS: - kernel = SincGauss; - -/* Constrain the full width half maximum of the gaussian factor. */ - fwhm = MaxD( 0.1, params[ 1 ], status ); - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 4.0 * log( 2.0 ) / ( fwhm * fwhm ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, use the number of neighbouring pixels required by the width - of the kernel (out to where the gaussian term falls to 1% of its - peak value). */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = (int) ceil( sqrt( -log( 0.01 ) / - lpar[ 0 ] ) ); - break; - -/* exp(-k*x*x) */ -/* ----------- */ -/* Assign the kernel function. */ - case AST__GAUSS: - kernel = Gauss; - -/* Constrain the full width half maximum of the gaussian. */ - fwhm = MaxD( 0.1, params[ 1 ], status ); - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 4.0 * log( 2.0 ) / ( fwhm * fwhm ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, use the number of neighbouring pixels required by the width - of the kernel (out to where the gaussian term falls to 1% of its - peak value). */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = (int) ceil( sqrt( -log( 0.01 ) / - lpar[ 0 ] ) ); - break; - -/* somb(pi*x)*cos(k*pi*x) */ -/* ---------------------- */ -/* Assign the kernel function. */ - case AST__SOMBCOS: - kernel = SombCos; - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 0.5 / MaxD( 1.0, params[ 1 ], status ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, the number will be calculated automatically below. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = INT_MAX; - -/* Calculate the maximum number of neighbouring pixels required by the - width of the kernel, and use this value if preferable. */ - neighb = MinI( neighb, - (int) ceil( MaxD( 1.0, params[ 1 ], status ) ), status ); - break; - -/* sinc(pi*x)*sinc(k*pi*x) */ -/* ----------------------- */ -/* Assign the kernel function. */ - case AST__SINCSINC: - kernel = SincSinc; - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 0.5 / MaxD( 1.0, params[ 1 ], status ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, the number will be calculated automatically below. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = INT_MAX; - -/* Calculate the maximum number of neighbouring pixels required by the - width of the kernel, and use this value if preferable. */ - neighb = MinI( neighb, - (int) ceil( MaxD( 1.0, params[ 1 ], status ) ), status ); - break; - } - -/* Define a macro to use a "case" statement to invoke the 1-d kernel - interpolation function appropriate to a given data type, passing it - the pointer to the kernel function obtained above. */ -#define CASE_KERNEL1(X,Xtype) \ - case ( TYPE_##X ): \ - SpreadKernel1##X( this, ndim_out, lbnd_out, ubnd_out, \ - (Xtype *) in, (Xtype *) in_var, \ - infac, npoint, offset, \ - (const double *const *) ptr_out, \ - kernel, neighb, par, conwgt, flags, \ - *( (Xtype *) badval_ptr ), \ - npix_out, (Xtype *) out, \ - (Xtype *) out_var, work, nused, \ - status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_KERNEL1(LD,long double) -#endif - CASE_KERNEL1(D,double) - CASE_KERNEL1(F,float) - CASE_KERNEL1(I,int) - CASE_KERNEL1(B,signed char) - CASE_KERNEL1(UB,unsigned char) - - case ( TYPE_L ): break; - case ( TYPE_K ): break; - case ( TYPE_S ): break; - case ( TYPE_UL ): break; - case ( TYPE_UI ): break; - case ( TYPE_UK ): break; - case ( TYPE_US ): break; - } - break; - -/* Undefine the macro. */ -#undef CASE_KERNEL1 - -/* Error: invalid pixel spreading scheme specified. */ -/* ------------------------------------------------ */ - default: - -/* Define a macro to report an error message appropriate to a given - data type. */ -#define CASE_ERROR(X) \ - case TYPE_##X: \ - astError( AST__SISIN, "astRebin"#X"(%s): Invalid " \ - "pixel spreading scheme (%d) specified.", status, \ - astGetClass( unsimplified_mapping ), spread ); \ - break; - -/* Use the above macro to report an appropriate error message. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_ERROR(LD) -#endif - CASE_ERROR(D) - CASE_ERROR(F) - CASE_ERROR(I) - CASE_ERROR(B) - CASE_ERROR(UB) - - case ( TYPE_L ): break; - case ( TYPE_K ): break; - case ( TYPE_S ): break; - case ( TYPE_UL ): break; - case ( TYPE_UI ): break; - case ( TYPE_UK ): break; - case ( TYPE_US ): break; - } - break; - -/* Undefine the macro. */ -#undef CASE_ERROR - } - } - -/* Annul the PointSet used to hold output coordinates. */ - pset_out = astAnnul( pset_out ); - -/* Free the workspace. */ - offset = astFree( offset ); - stride = astFree( stride ); -} - -/* -*++ -* Name: -c astRebinSeq<X> -f AST_REBINSEQ<X> - -* Purpose: -* Rebin a region of a sequence of data grids. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astRebinSeq<X>( AstMapping *this, double wlim, int ndim_in, -c const int lbnd_in[], const int ubnd_in[], -c const <Xtype> in[], const <Xtype> in_var[], -c int spread, const double params[], int flags, -c double tol, int maxpix, <Xtype> badval, -c int ndim_out, const int lbnd_out[], -c const int ubnd_out[], const int lbnd[], -c const int ubnd[], <Xtype> out[], <Xtype> out_var[], -c double weights[], int64_t *nused ); -f CALL AST_REBINSEQ<X>( THIS, WLIM, NDIM_IN, LBND_IN, UBND_IN, IN, IN_VAR, -f SPREAD, PARAMS, FLAGS, TOL, MAXPIX, BADVAL, -f NDIM_OUT, LBND_OUT, UBND_OUT, LBND, UBND, OUT, -f OUT_VAR, WEIGHTS, NUSED, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -* This set of -c functions is identical to astRebin<X> -f routines is identical to AST_REBIN<X> -* except that the rebinned input data is added into the supplied -* output arrays, rather than simply over-writing the contents of the -* output arrays. Thus, by calling this -c function -f routine -* repeatedly, a sequence of input arrays can be rebinned and accumulated -* into a single output array, effectively forming a mosaic of the -* input data arrays. -* -* In addition, the weights associated with each output pixel are -* returned. The weight of an output pixel indicates the number of input -* pixels which have been accumulated in that output pixel. If the entire -* value of an input pixel is assigned to a single output pixel, then the -* weight of that output pixel is incremented by one. If some fraction of -* the value of an input pixel is assigned to an output pixel, then the -* weight of that output pixel is incremented by the fraction used. -* -* The start of a new sequence is indicated by specifying the -* AST__REBININIT flag via the -c "flags" parameter. -f FLAGS argument. -* This causes the supplied arrays to be filled with zeros before the -* rebinned input data is added into them. Subsequenct invocations -* within the same sequence should omit the AST__REBININIT flag. -* -* The last call in a sequence is indicated by specifying the -* AST__REBINEND flag. Depending on which flags are supplied, this may -* cause the output data and variance arrays to be normalised before -* being returned. This normalisation consists of dividing the data -* array by the weights array, and can eliminate artifacts which may be -* introduced into the rebinned data as a consequence of aliasing -* between the input and output grids. This results in each output -* pixel value being the weighted mean of the input pixel values that -* fall in the neighbourhood of the output pixel (rather like -c astResample<X>). -f AST_RESAMPLE<X>). -* Optionally, these normalised -* values can then be multiplied by a scaling factor to ensure that the -* total data sum in any small area is unchanged. This scaling factor -* is equivalent to the number of input pixel values that fall into each -* output pixel. In addition to -* normalisation of the output data values, any output variances are -* also appropriately normalised, and any output data values with -* weight less than -c "wlim" are set to "badval". -f WLIM are set to BADVAL. -* -* Output variances can be generated in two ways; by rebinning the supplied -* input variances with appropriate weights, or by finding the spread of -* input data values contributing to each output pixel (see the AST__GENVAR -* and AST__USEVAR flags). - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to a Mapping, whose forward transformation will be -* used to transform the coordinates of pixels in the input -* grid into the coordinate system of the output grid. -* -* The number of input coordinates used by this Mapping (as -* given by its Nin attribute) should match the number of input -c grid dimensions given by the value of "ndim_in" -f grid dimensions given by the value of NDIM_IN -* below. Similarly, the number of output coordinates (Nout -* attribute) should match the number of output grid dimensions -c given by "ndim_out". -f given by NDIM_OUT. -c If "in" is NULL, the Mapping will not be used, but a valid -c Mapping must still be supplied. -c wlim -f WLIM = DOUBLE PRECISION (Given) -* This value is only used if the AST__REBINEND flag is specified -* via the -c "flags" parameter. -f FLAGS argument. -* It gives the required number of input pixel values which must -* contribute to an output pixel (i.e. the output pixel weight) in -* order for the output pixel value to be considered valid. If the sum -* of the input pixel weights contributing to an output pixel is less -* than the supplied -c "wlim" -f WLIM -* value, then the output pixel value is returned set to the -* supplied bad value. If the supplied value is less than 1.0E-10 -* then 1.0E-10 is used instead. -c ndim_in -f NDIM_IN = INTEGER (Given) -* The number of dimensions in the input grid. This should be at -* least one. -c Not used if "in" is NULL. -c lbnd_in -f LBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the input grid along each dimension. -c Not used if "in" is NULL. -c ubnd_in -f UBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the input grid along each dimension. -* -c Note that "lbnd_in" and "ubnd_in" together define the shape -f Note that LBND_IN and UBND_IN together define the shape -* and size of the input grid, its extent along a particular -c (j'th) dimension being ubnd_in[j]-lbnd_in[j]+1 (assuming the -c index "j" to be zero-based). They also define -f (J'th) dimension being UBND_IN(J)-LBND_IN(J)+1. They also define -* the input grid's coordinate system, each pixel having unit -* extent along each dimension with integral coordinate values -* at its centre. -c Not used if "in" is NULL. -c in -f IN( * ) = <Xtype> (Given) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* input grid, containing the input data to be rebined. The -* numerical type of this array should match the 1- or -* 2-character type code appended to the function name (e.g. if -c you are using astRebinSeqF, the type of each array element -c should be "float"). -f you are using AST_REBINSEQR, the type of each array element -f should be REAL). -* -* The storage order of data within this array should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c If a NULL pointer is supplied for "in", then no data is added to -c the output arrays, but any initialisation or normalisation -c requested by "flags" is still performed. -c in_var -f IN_VAR( * ) = <Xtype> (Given) -* An optional -c pointer to a -* second array with the same size and type as the -c "in" -f IN -* array. If given, this should contain a set of non-negative values -* which represent estimates of the statistical variance associated -* with each element of the -c "in" -f IN -* array. -* If neither the AST__USEVAR nor the AST__VARWGT flag is set, no -* input variance estimates are required and this -f array -c pointer -* will not be used. -f A dummy (e.g. one-element) array -c A NULL pointer -* may then be supplied. -c spread -f SPREAD = INTEGER (Given) -c This parameter specifies the scheme to be used for dividing -f This argument specifies the scheme to be used for dividing -* each input data value up amongst the corresponding output pixels. -* It may be used to select -* from a set of pre-defined schemes by supplying one of the -* values described in the "Pixel Spreading Schemes" -* section in the description of the -c astRebin<X> functions. -f AST_REBIN<X> routines. -* If a value of zero is supplied, then the default linear spreading -* scheme is used (equivalent to supplying the value AST__LINEAR). -c Not used if "in" is NULL. -c params -f PARAMS( * ) = DOUBLE PRECISION (Given) -c An optional pointer to an array of double which should contain -f An optional array which should contain -* any additional parameter values required by the pixel -* spreading scheme. If such parameters are required, this -* will be noted in the "Pixel Spreading Schemes" section in the -* description of the -c astRebin<X> functions. -f AST_REBIN<X> routines. -* -c If no additional parameters are required, this array is not -c used and a NULL pointer may be given. See also flag AST__PARWGT. -f If no additional parameters are required, this array is not -f used. A dummy (e.g. one-element) array may then be supplied. -c Not used if "in" is NULL. -c flags -f FLAGS = INTEGER (Given) -c The bitwise OR of a set of flag values which may be used to -f The sum of a set of flag values which may be used to -* provide additional control over the rebinning operation. See -* the "Control Flags" section below for a description of the -* options available. If no flag values are to be set, a value -* of zero should be given. -c tol -f TOL = DOUBLE PRECISION (Given) -* The maximum tolerable geometrical distortion which may be -* introduced as a result of approximating non-linear Mappings -* by a set of piece-wise linear transformations. This should be -* expressed as a displacement in pixels in the output grid's -* coordinate system. -* -* If piece-wise linear approximation is not required, a value -* of zero may be given. This will ensure that the Mapping is -* used without any approximation, but may increase execution -* time. -* -* If the value is too high, discontinuities between the linear -* approximations used in adjacent panel will be higher, and may -* cause the edges of the panel to be visible when viewing the output -* image at high contrast. If this is a problem, reduce the -* tolerance value used. -c Not used if "in" is NULL. -c maxpix -f MAXPIX = INTEGER (Given) -* A value which specifies an initial scale size (in pixels) for -* the adaptive algorithm which approximates non-linear Mappings -* with piece-wise linear transformations. Normally, this should -* be a large value (larger than any dimension of the region of -* the input grid being used). In this case, a first attempt to -* approximate the Mapping by a linear transformation will be -* made over the entire input region. -* -* If a smaller value is used, the input region will first be -c divided into sub-regions whose size does not exceed "maxpix" -f divided into sub-regions whose size does not exceed MAXPIX -* pixels in any dimension. Only at this point will attempts at -* approximation commence. -* -* This value may occasionally be useful in preventing false -* convergence of the adaptive algorithm in cases where the -* Mapping appears approximately linear on large scales, but has -* irregularities (e.g. holes) on smaller scales. A value of, -* say, 50 to 100 pixels can also be employed as a safeguard in -* general-purpose software, since the effect on performance is -* minimal. -* -* If too small a value is given, it will have the effect of -* inhibiting linear approximation altogether (equivalent to -c setting "tol" to zero). Although this may degrade -f setting TOL to zero). Although this may degrade -* performance, accurate results will still be obtained. -c Not used if "in" is NULL. -c badval -f BADVAL = <Xtype> (Given) -* This argument should have the same type as the elements of -c the "in" array. It specifies the value used to flag missing -f the IN array. It specifies the value used to flag missing -* data (bad pixels) in the input and output arrays. -* -c If the AST__USEBAD flag is set via the "flags" parameter, -f If the AST__USEBAD flag is set via the FLAGS argument, -c then this value is used to test for bad pixels in the "in" -c (and "in_var") array(s). -f then this value is used to test for bad pixels in the IN -f (and IN_VAR) array(s). -* -* In all cases, this value is also used to flag any output -c elements in the "out" (and "out_var") array(s) for which -f elements in the OUT (and OUT_VAR) array(s) for which -* rebined values could not be obtained (see the "Propagation -* of Missing Data" section below for details of the -* circumstances under which this may occur). -c ndim_out -f NDIM_OUT = INTEGER (Given) -* The number of dimensions in the output grid. This should be -* at least one. It need not necessarily be equal to the number -* of dimensions in the input grid. -c lbnd_out -f LBND_OUT( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the output grid along each dimension. -c ubnd_out -f UBND_OUT( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the output grid along each dimension. -* -c Note that "lbnd_out" and "ubnd_out" together define the -f Note that LBND_OUT and UBND_OUT together define the -* shape, size and coordinate system of the output grid in the -c same way as "lbnd_in" and "ubnd_in" define the shape, size -f same way as LBND_IN and UBND_IN define the shape, size -* and coordinate system of the input grid. -c lbnd -f LBND( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the first pixel in the region -* of the input grid which is to be included in the rebined output -* array. -c Not used if "in" is NULL. -c ubnd -f UBND( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the last pixel in the region of -* the input grid which is to be included in the rebined output -* array. -* -c Note that "lbnd" and "ubnd" together define the shape and -f Note that LBND and UBND together define the shape and -* position of a (hyper-)rectangular region of the input grid -* which is to be included in the rebined output array. This region -* should lie wholly within the extent of the input grid (as -c defined by the "lbnd_in" and "ubnd_in" arrays). Regions of -f defined by the LBND_IN and UBND_IN arrays). Regions of -* the input grid lying outside this region will not be used. -c Not used if "in" is NULL. -c out -f OUT( * ) = <Xtype> (Given and Returned) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* output grid. The rebined data values will be added into the -* original contents of this array. The numerical type of this array -* should match that of the -c "in" array, and the data storage order should be such -f IN array, and the data storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c out_var -f OUT_VAR( * ) = <Xtype> (Given and Returned) -* A -c pointer to an -* array with the same type and size as the -c "out" -f OUT -* array. This -c pointer -f array -* will only be used if the AST__USEVAR or AST__GENVAR flag is set -f via the FLAGS argument, -f via the "flags" parameter, -* in which case variance estimates for the rebined data values will -* be added into the array. If neither the AST__USEVAR flag nor the -* AST__GENVAR flag is set, no output variance estimates will be -* calculated and this -c pointer -f array -* will not be used. A -c NULL pointer -f dummy (e.g. one-element) array -* may then be supplied. -c weights -f WEIGHTS( * ) = DOUBLE PRECISION (Given and Returned) -c Pointer to an array of double, -f An array -* with one or two elements for each pixel in the output grid, -* depending on whether or not the AST__GENVAR flag has been supplied -* via the -c "flags" parameter. -f FLAGS parameter. -* If AST__GENVAR has not been specified then the array should have -* one element for each output pixel, and it will be used to -* accumulate the weight associated with each output pixel. -* If AST__GENVAR has been specified then the array should have -* two elements for each output pixel. The first half of the array -* is again used to accumulate the weight associated with each output -* pixel, and the second half is used to accumulate the square of -* the weights. In each half, the data storage order should be such that -* the index of the first grid dimension varies most rapidly and that of -* the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c nused -f NUSED = INTEGER*8 (Given and Returned) -c A pointer to an int64_t containing the -f The -* number of input data values that have been added into the output -* array so far. The supplied value is incremented on exit by the -* number of input values used. The value is initially set to zero -* if the AST__REBININIT flag is set in -c "flags". -f FLAGS. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Data Type Codes: -* To select the appropriate rebinning function, you should -c replace <X> in the generic function name astRebinSeq<X> with a -f replace <X> in the generic function name AST_REBINSEQ<X> with a -* 1- or 2-character data type code, so as to match the numerical -* type <Xtype> of the data you are processing, as follows: -c - D: double -c - F: float -c - I: int -c - B: byte (signed char) -c - UB: unsigned byte (unsigned char) -f - D: DOUBLE PRECISION -f - R: REAL -f - I: INTEGER -f - B: BYTE (treated as signed) -f - UB: BYTE (treated as unsigned) -* -c For example, astRebinSeqD would be used to process "double" -c data, while astRebinSeqI would be used to process "int" -c data, etc. -f For example, AST_REBIND would be used to process DOUBLE -f PRECISION data, while AST_REBINI would be used to process -f integer data (stored in an INTEGER array), etc. -* -* Note that, unlike -c astResample<X>, the astRebinSeq<X> -f AST_RESAMPLE<X>, the AST_REBINSEQ<X> -* set of functions does not yet support unsigned integer data types -* or integers of different sizes. - -* Control Flags: -c The following flags are defined in the "ast.h" header file and -f The following flags are defined in the AST_PAR include file and -* may be used to provide additional control over the rebinning -* process. Having selected a set of flags, you should supply the -c bitwise OR of their values via the "flags" parameter: -f sum of their values via the FLAGS argument: -* -* - AST__REBININIT: Used to mark the first call in a sequence. It indicates -* that the supplied -c "out", "out_var" and "weights" -f OUT, OUT_VAR and WEIGHTS -* arrays should be filled with zeros (thus over-writing any supplied -* values) before adding the rebinned input data into them. This flag -* should be used when rebinning the first input array in a sequence. -* - AST__REBINEND: Used to mark the last call in a sequence. It causes -* each value in the -c "out" and "out_var" -f OUT and OUT_VAR -* arrays to be divided by a normalisation factor before being -* returned. The normalisation factor for each output data value is just -* the corresponding value from the weights array. The normalisation -* factor for each output variance value is the square of the data value -* normalisation factor (see also AST__CONSERVEFLUX). It also causes -* output data values to be set bad if the corresponding weight is less -* than the value supplied for -c parameter "wlim". -f argument WLIM. -* It also causes any temporary values stored in the output variance array -* (see flag AST__GENVAR below) to be converted into usable variance values. -* Note, this flag is ignored if the AST__NONORM flag is set. -* - AST__USEBAD: Indicates that there may be bad pixels in the -* input array(s) which must be recognised by comparing with the -c value given for "badval" and propagated to the output array(s). -f value given for BADVAL and propagated to the output array(s). -* If this flag is not set, all input values are treated literally -c and the "badval" value is only used for flagging output array -f and the BADVAL value is only used for flagging output array -* values. -* - AST__USEVAR: Indicates that output variance estimates should be -* created by rebinning the supplied input variance estimates. An -* error will be reported if both this flag and the AST__GENVAR flag -* are supplied. -* - AST__GENVAR: Indicates that output variance estimates should be -* created based on the spread of input data values contributing to each -* output pixel. An error will be reported if both this flag and the -* AST__USEVAR flag are supplied. If the AST__GENVAR flag is specified, -* the supplied output variance array is first used as a work array to -* accumulate the temporary values needed to generate the output -* variances. When the sequence ends (as indicated by the -* AST__REBINEND flag), the contents of the output variance array are -* converted into the required variance estimates. If the generation of -* such output variances is required, this flag should be used on every -* invocation of this -c function -f routine -* within a sequence, and any supplied input variances will have no effect -* on the output variances (although input variances will still be used -* to weight the input data if the AST__VARWGT flag is also supplied). -* The statistical meaning of these output varianes is determined by -* the presence or absence of the AST__DISVAR flag (see below). -* - AST__DISVAR: This flag is ignored unless the AST__GENVAR flag -* has also been specified. It determines the statistical meaning of -* the generated output variances. If AST__DISVAR is not specified, -* generated variances represent variances on the output mean values. If -* AST__DISVAR is specified, the generated variances represent the variance -* of the distribution from which the input values were taken. Each output -* variance created with AST__DISVAR will be larger than that created -* without AST__DISVAR by a factor equal to the number of input samples -* that contribute to the output sample. -* - AST__VARWGT: Indicates that the input data should be weighted by -* the reciprocal of the input variances. Otherwise, all input data are -* given equal weight. If this flag is specified, the calculation of the -* output variances (if any) is modified to take account of the -* varying weights assigned to the input data values. See also AST__PARWGT. -* - AST__PARWGT: Indicates that a constant weight should be used when -* pasting each pixel of the supplied input array into the returned -* arrays. This extra weight value should be inserted at the start of the -c "params" -f 'PARAMS -* array (which should consequently be one element longer than specified in -* the "Pixel Spreading Schemes" section in the description of the -c astRebin<X> functions). -f AST_REBIN<X> routines). -* If the AST__VARWGT flag is also specified, the total weight for -* each pixel is the product of the reciprocal of the pixel variance -* and the value supplied in the last element of the -c "params" array. -f 'PARAMS array. -* - AST__NONORM: If the simple unnormalised sum of all input data falling -* in each output pixel is required, then this flag should be set on -* each call in the sequence and the AST__REBINEND should not be used -* on the last call. In this case -c NULL pointers can be supplied for "weights" and "nused". -f WEIGHTS and NUSED are ignored. -* This flag cannot be used with the AST__CONSERVEFLUX, AST__GENVAR, -* AST__PARWGT or AST__VARWGT flag. -* - AST__CONSERVEFLUX: Indicates that the normalized output pixel values -* generated by the AST__REBINEND flag should be scaled in such a way as -* to preserve the total data value in a feature on the sky. Without this -* flag, each normalised output pixel value represents a weighted mean -* of the input data values around the corresponding input position. -f (i.e. AST_REBINSEQ<F> behaves similarly to AST_RESAMPLE<X>). This -f (i.e. AST_REBINSEQ<F> behaves similarly to AST_RESAMPLE<X>). This -* is appropriate if the input data represents the spatial density of -* some quantity (e.g. surface brightness in Janskys per square -* arc-second) because the output pixel values will have the same -* normalisation and units as the input pixel values. However, if the -* input data values represent flux (or some other physical quantity) -* per pixel, then the AST__CONSERVEFLUX flag could be of use. It causes -* each output pixel value to be scaled by the ratio of the output pixel -* size to the input pixel size. -* -* This flag can only be used if the Mapping is successfully approximated -* by one or more linear transformations. Thus an error will be reported -* if it used when the -c "tol" parameter -f TOL argument -* is set to zero (which stops the use of linear approximations), or -* if the Mapping is too non-linear to be approximated by a piece-wise -* linear transformation. The ratio of output to input pixel size is -* evaluated once for each panel of the piece-wise linear approximation to -* the Mapping, and is assumed to be constant for all output pixels in the -* panel. The scaling factors for adjacent panels will in general -* differ slightly, and so the joints between panels may be visible when -* viewing the output image at high contrast. If this is a problem, -* reduce the value of the -c "tol" parameter -f TOL argument -* until the difference between adjacent panels is sufficiently small -* to be insignificant. -* -* This flag should normally be supplied on each invocation of -c astRebinSeq<X> -f AST_REBINSEQ<X> -* within a given sequence. -* -* Note, this flag cannot be used in conjunction with the AST__NOSCALE -* flag (an error will be reported if both flags are specified). - -* Propagation of Missing Data: -* Instances of missing data (bad pixels) in the output grid are -c identified by occurrences of the "badval" value in the "out" -f identified by occurrences of the BADVAL value in the OUT -* array. These are only produced if the AST__REBINEND flag is -* specified and a pixel has zero weight. -* -* An input pixel is considered bad (and is consequently ignored) if -* its -c data value is equal to "badval" and the AST__USEBAD flag is -c set via the "flags" parameter. -f data value is equal to BADVAL and the AST__USEBAD flag is -f set via the FLAGS argument. -* -* In addition, associated output variance estimates (if -c calculated) may be declared bad and flagged with the "badval" -c value in the "out_var" array for similar reasons. -f calculated) may be declared bad and flagged with the BADVAL -f value in the OUT_VAR array for similar reasons. - -*-- -*/ -/* Define a macro to implement the function for a specific data - type. */ -#define MAKE_REBINSEQ(X,Xtype,IntType) \ -static void RebinSeq##X( AstMapping *this, double wlim, int ndim_in, \ - const int lbnd_in[], const int ubnd_in[], \ - const Xtype in[], const Xtype in_var[], \ - int spread, const double params[], int flags, \ - double tol, int maxpix, Xtype badval, \ - int ndim_out, const int lbnd_out[], \ - const int ubnd_out[], const int lbnd[], \ - const int ubnd[], Xtype out[], Xtype out_var[], \ - double weights[], int64_t *nused, int *status ) { \ -\ -/* Local Variables: */ \ - AstMapping *simple; /* Pointer to simplified Mapping */ \ - Xtype *d; /* Pointer to next output data value */ \ - Xtype *v; /* Pointer to next output variance value */ \ - astDECLARE_GLOBALS /* Thread-specific data */ \ - double *w; /* Pointer to next weight value */ \ - double mwpip; /* Mean weight per input pixel */ \ - double neff; /* Effective number of contributing input pixels */ \ - double sw; /* Sum of weights at output pixel */ \ - double wgt; /* Output pixel weight */ \ - int i; /* Loop counter for output pixels */ \ - int idim; /* Loop counter for coordinate dimensions */ \ - int ipix_out; /* Index into output array */ \ - int nin; /* Number of Mapping input coordinates */ \ - int nout; /* Number of Mapping output coordinates */ \ - int npix; /* Number of pixels in input region */ \ - int npix_out; /* Number of pixels in output array */ \ - int64_t mpix; /* Number of pixels for testing */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Get a pointer to a structure holding thread-specific global data values */ \ - astGET_GLOBALS(this); \ -\ -/* Loop to determine how many pixels the output array contains. */ \ - npix_out = 1; \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - npix_out *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ - } \ -\ -/* Obtain values for the Nin and Nout attributes of the Mapping. */ \ - nin = astGetNin( this ); \ - nout = astGetNout( this ); \ -\ -/* If OK, also check that the number of output grid dimensions matches \ - the number required by the Mapping and is at least 1. Report an \ - error if necessary. */ \ - if ( astOK && ( ( ndim_out != nout ) || ( ndim_out < 1 ) ) ) { \ - astError( AST__NGDIN, "astRebinSeq"#X"(%s): Bad number of output grid " \ - "dimensions (%d).", status, astGetClass( this ), ndim_out ); \ - if ( ndim_out != nout ) { \ - astError( AST__NGDIN, "The %s given generates %s%d coordinate " \ - "value%s for each output position.", status, astGetClass( this ), \ - ( nout < ndim_out ) ? "only " : "", nout, \ - ( nout == 1 ) ? "" : "s" ); \ - } \ - } \ -\ -/* If no input data was supplied, jump to the normalisation section. */ \ - simple = NULL; \ - if( in ) { \ -\ -/* If OK, check that the number of input grid dimensions matches the \ - number required by the Mapping and is at least 1. Report an error \ - if necessary. */ \ - if ( astOK && ( ( ndim_in != nin ) || ( ndim_in < 1 ) ) ) { \ - astError( AST__NGDIN, "astRebinSeq"#X"(%s): Bad number of input grid " \ - "dimensions (%d).", status, astGetClass( this ), ndim_in ); \ - if ( ndim_in != nin ) { \ - astError( AST__NGDIN, "The %s given requires %d coordinate value%s " \ - "to specify an input position.", status, \ - astGetClass( this ), nin, ( nin == 1 ) ? "" : "s" ); \ - } \ - } \ -\ -/* Check that the lower and upper bounds of the input grid are \ - consistent. Report an error if any pair is not. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - if ( lbnd_in[ idim ] > ubnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astRebinSeq"#X"(%s): Lower bound of " \ - "input grid (%d) exceeds corresponding upper bound " \ - "(%d).", status, astGetClass( this ), \ - lbnd_in[ idim ], ubnd_in[ idim ] ); \ - astError( AST__GBDIN, "Error in input dimension %d.", status, \ - idim + 1 ); \ - break; \ - } else { \ - mpix *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the input. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astRebinSeq"#X"(%s): Supplied input array " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Ensure any supplied "in_var" pointer is ignored if no input variances are \ - needed. */ \ - if( !( flags & AST__USEVAR ) && !( flags & AST__VARWGT ) ) { \ - in_var = NULL; \ - } \ -\ -/* Ensure any supplied "out_var" pointer is ignored if no output variances \ - being created. */ \ - if( !( flags & AST__USEVAR ) && !( flags & AST__GENVAR ) ) { \ - out_var = NULL; \ - } \ -\ -/* Check that the positional accuracy tolerance supplied is valid and \ - report an error if necessary. */ \ - if ( astOK && ( tol < 0.0 ) ) { \ - astError( AST__PATIN, "astRebinSeq"#X"(%s): Invalid positional " \ - "accuracy tolerance (%.*g pixel).", status, \ - astGetClass( this ), AST__DBL_DIG, tol ); \ - astError( AST__PATIN, "This value should not be less than zero." , status); \ - } \ -\ -/* Check that the initial scale size in pixels supplied is valid and \ - report an error if necessary. */ \ - if ( astOK && ( maxpix < 0 ) ) { \ - astError( AST__SSPIN, "astRebinSeq"#X"(%s): Invalid initial scale " \ - "size in pixels (%d).", status, astGetClass( this ), maxpix ); \ - astError( AST__SSPIN, "This value should not be less than zero." , status); \ - } \ -\ -/* Check that the lower and upper bounds of the output grid are \ - consistent. Report an error if any pair is not. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - if ( lbnd_out[ idim ] > ubnd_out[ idim ] ) { \ - astError( AST__GBDIN, "astRebinSeq"#X"(%s): Lower bound of " \ - "output grid (%d) exceeds corresponding upper bound " \ - "(%d).", status, astGetClass( this ), \ - lbnd_out[ idim ], ubnd_out[ idim ] ); \ - astError( AST__GBDIN, "Error in output dimension %d.", status, \ - idim + 1 ); \ - break; \ - } else { \ - mpix *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the output. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astRebinSeq"#X"(%s): Supplied output array " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Similarly check the bounds of the input region. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - if ( lbnd[ idim ] > ubnd[ idim ] ) { \ - astError( AST__GBDIN, "astRebinSeq"#X"(%s): Lower bound of " \ - "input region (%d) exceeds corresponding upper " \ - "bound (%d).", status, astGetClass( this ), \ - lbnd[ idim ], ubnd[ idim ] ); \ -\ -/* Also check that the input region lies wholly within the input \ - grid. */ \ - } else if ( lbnd[ idim ] < lbnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astRebinSeq"#X"(%s): Lower bound of " \ - "input region (%d) is less than corresponding " \ - "bound of input grid (%d).", status, astGetClass( this ), \ - lbnd[ idim ], lbnd_in[ idim ] ); \ - } else if ( ubnd[ idim ] > ubnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astRebinSeq"#X"(%s): Upper bound of " \ - "input region (%d) exceeds corresponding " \ - "bound of input grid (%d).", status, astGetClass( this ), \ - ubnd[ idim ], ubnd_in[ idim ] ); \ - } else { \ - mpix *= ubnd[ idim ] - lbnd[ idim ] + 1; \ - } \ -\ -/* Say which dimension produced the error. */ \ - if ( !astOK ) { \ - astError( AST__GBDIN, "Error in output dimension %d.", status, \ - idim + 1 ); \ - break; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the input region. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astRebinSeq"#X"(%s): Supplied input region " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Check that only one of AST__USEVAR and ASR__GENVAR has been supplied. */ \ - if( ( flags & AST__USEVAR ) && ( flags & AST__GENVAR ) ) { \ - if( astOK ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): Incompatible flags " \ - "AST__GENVAR and AST__USEVAR have been specified " \ - "together (programming error).", status, astGetClass( this ) ); \ - } \ - } \ -\ -/* If AST__USEVAR or AST_VARWGT has been specified, check we have an \ - input variance array. */ \ - if( !in_var && astOK ) { \ - if( ( flags & AST__USEVAR ) ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): The AST__USEVAR flag " \ - "was specified but no input variance array was supplied " \ - "(programming error).", status, astGetClass( this ) ); \ - } else if( ( flags & AST__VARWGT ) ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): The AST__VARWGT flag " \ - "was specified but no input variance array was supplied " \ - "(programming error).", status, astGetClass( this ) ); \ - } \ - } \ -\ -/* If AST__USEVAR or AST_GENVAR has been specified, check we have an \ - output variance array. */ \ - if( !out_var && astOK ) { \ - if( ( flags & AST__USEVAR ) ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): The AST__USEVAR flag " \ - "was specified but no output variance array was supplied " \ - "(programming error).", status, astGetClass( this ) ); \ - } else if( ( flags & AST__GENVAR ) ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): The AST__GENVAR flag " \ - "was specified but no output variance array was supplied " \ - "(programming error).", status, astGetClass( this ) ); \ - } \ - } \ -\ -/* If the AST__NONORM flag has been supplied, check no incompatible flags have \ - been specified. */ \ - if( flags & AST__NONORM ) { \ - if( ( flags & AST__GENVAR ) && astOK ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): Incompatible flags " \ - "AST__GENVAR and AST__NONORM have been specified " \ - "together (programming error).", status, astGetClass( this ) ); \ - } else if( ( flags & AST__VARWGT ) && astOK ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): Incompatible flags " \ - "AST__VARWGT and AST__NONORM have been specified " \ - "together (programming error).", status, astGetClass( this ) ); \ - } else if( ( flags & AST__PARWGT ) && astOK ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): Incompatible flags " \ - "AST__PARWGT and AST__NONORM have been specified " \ - "together (programming error).", status, astGetClass( this ) ); \ - } else if( ( flags & AST__CONSERVEFLUX ) && astOK ) { \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): Incompatible flags " \ - "AST__CONSERVEFLUX and AST__NONORM have been specified " \ - "together (programming error).", status, astGetClass( this ) ); \ - } \ -\ -/* If the AST__NONORM flag has not been supplied, check that a weights array \ - and nused pointer have been supplied. */ \ - } else if( !weights ){ \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): No weights array " \ - "supplied (programming error).", status, \ - astGetClass( this ) ); \ - } else if( !nused ){ \ - astError( AST__BDPAR, "astRebinSeq"#X"(%s): No 'nused' pointer " \ - "supplied (programming error).", status, \ - astGetClass( this ) ); \ - } \ -\ -/* If OK, loop to determine how many input pixels are to be binned. */ \ - npix = 1; \ - unsimplified_mapping = this; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - npix *= ubnd[ idim ] - lbnd[ idim ] + 1; \ - } \ -\ -/* If there are sufficient pixels to make it worthwhile, simplify the \ - Mapping supplied to improve performance. Otherwise, just clone the \ - Mapping pointer. Note we have already saved a pointer to the original \ - Mapping so that lower-level functions can use it if they need to report \ - an error. */ \ - if ( npix > 1024 ) { \ - simple = astSimplify( this ); \ - } else { \ - simple = astClone( this ); \ - } \ - } \ -\ -/* Report an error if the forward transformation of this simplified \ - Mapping is not defined. */ \ - if ( !astGetTranForward( simple ) && astOK ) { \ - astError( AST__TRNND, "astRebinSeq"#X"(%s): An forward coordinate " \ - "transformation is not defined by the %s supplied.", status, \ - astGetClass( unsimplified_mapping ), \ - astGetClass( unsimplified_mapping ) ); \ - } \ -\ -/* If required, initialise the output arrays to hold zeros. */ \ - if( flags & AST__REBININIT ) { \ - d = out; \ - if( out_var ) { \ - v = out_var; \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, d++, v++ ) { \ - *d = 0; \ - *v = 0; \ - } \ - } else { \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, d++ ) { \ - *d = 0; \ - } \ - } \ - if( weights ) { \ - w = weights; \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, w++ ) { \ - *w = 0; \ - } \ - if( flags & AST__GENVAR ) { \ - for( ipix_out = 0; ipix_out < npix_out; ipix_out++, w++ ) *w = 0; \ - } \ - } \ - if( nused ) *nused = 0; \ - } \ -\ -/* Paste the input values into the supplied output arrays. */ \ - if( RebinAdaptively( simple, ndim_in, lbnd_in, ubnd_in, \ - (const void *) in, (const void *) in_var, \ - TYPE_##X, spread, params, flags, \ - tol, maxpix, (const void *) &badval, \ - ndim_out, lbnd_out, ubnd_out, lbnd, \ - ubnd, npix_out, (void *) out, \ - (void *) out_var, weights, nused, status ) ) { \ - astError( AST__CNFLX, "astRebinSeq"#X"(%s): Flux conservation was " \ - "requested but could not be performed because the " \ - "forward transformation of the supplied Mapping " \ - "is too non-linear.", status, astGetClass( this ) ); \ - } \ -\ -/* Annul the pointer to the simplified/cloned Mapping. */ \ - simple = astAnnul( simple ); \ -\ - } \ -\ -/* If required, finalise the sequence. */ \ - if( ( flags & AST__REBINEND ) && !( flags & AST__NONORM ) && \ - weights && nused ) { \ -\ -/* Ensure "wlim" is not zero. */ \ - if( wlim < 1.0E-10 ) wlim = 1.0E-10; \ -\ -/* If it will be needed, find the average weight per input pixel. */ \ - if( !( flags & AST__GENVAR ) && *nused > 0 ) { \ - sw = 0.0; \ - for( i = 0; i < npix_out; i++ ) { \ - sw += weights[ i ]; \ - } \ - mwpip = sw/( *nused ); \ - } else { \ - mwpip = AST__BAD; \ - } \ -\ -/* Normalise each output pixel. */ \ - for( i = 0; i < npix_out; i++ ) { \ -\ -/* Find the effective number of input samples that contribute to the \ - output sample. To do this properly requires the sum of the squared \ - weights in each output pixel, but this is only available if AST__GENVAR \ - flag is in use. In order to avoid changing the API for astRebinSeq, we \ - honour this long-standing restriction, and use an approximation if \ - AST__GENVAR is not in use. */ \ - wgt = weights[ i ]; \ - if( flags & AST__GENVAR ) { \ - if( wgt > 0.0 && weights[ i + npix_out ] > 0 ) { \ - neff = (wgt*wgt)/weights[ i + npix_out ]; \ - } else { \ - neff = 0.0; \ - } \ -\ -/* If the sum of the squared weights is not available, compare the weight \ - for this output pixel with the mean weight per input pixel. */ \ - } else if( mwpip != AST__BAD ){ \ - neff = wgt/mwpip; \ -\ - } else if( astOK ) { \ - astError( AST__BADIN, "astRebinSeq"#X"(%s): The overlap " \ - "between the %d-d input array and the %d-d output " \ - "array contains no pixels with good data %svalues.", \ - status, astGetClass( this ), nin, nout, \ - in_var ? "and variance " : "" ); \ - } \ -\ -/* Assign bad values to unused output pixels. */ \ - if( neff < wlim || neff == 0.0 ) { \ - out[ i ] = badval; \ - if( out_var ) out_var[ i ] = badval; \ -\ -/* Otherwise, normalise the returned data value. No need to check "wgt" \ - since it must be larger than zero since neff is larger than wlim. */ \ - } else { \ - out[ i ] /= wgt; \ -\ -/* Normalise the returned variance: propagated from input variances... */ \ - if( out_var ) { \ - if( flags & AST__USEVAR ) { \ - out_var[ i ] /= wgt*wgt; \ -\ -/* Normalise the returned variance: from spread of input values... */ \ - } else if( flags & AST__GENVAR && neff > 1.0 ) { \ - out_var[ i ] /= wgt; \ - out_var[ i ] -= out[ i ]*out[ i ]; \ - if( out_var[ i ] < 0.0 ) out_var[ i ] = 0.0; \ -\ -/* If output variances are estimates of the variance of the distribution \ - from which the input values were sampled... */ \ - if( flags & AST__DISVAR ) { \ - out_var[ i ] *= neff/( neff - 1.0 ); \ -\ -/* If output variances are estimates of the error on the mean data value... */ \ - } else { \ - out_var[ i ] *= 1.0/( neff - 1.0 ); \ - } \ -\ - } else { \ - out_var[ i ] = badval; \ - } \ - } \ - } \ - } \ - } \ -\ -} - -/* Expand the above macro to generate a function for each required - data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_REBINSEQ(LD,long double,0) -#endif -MAKE_REBINSEQ(D,double,0) -MAKE_REBINSEQ(F,float,0) -MAKE_REBINSEQ(I,int,1) -MAKE_REBINSEQ(B,signed char,1) -MAKE_REBINSEQ(UB,unsigned char,1) - -/* Undefine the macro. */ -#undef MAKE_REBINSEQ - -static int RebinWithBlocking( AstMapping *this, const double *linear_fit, - int ndim_in, const int *lbnd_in, - const int *ubnd_in, const void *in, - const void *in_var, DataType type, - int spread, const double *params, int flags, - const void *badval_ptr, int ndim_out, - const int *lbnd_out, const int *ubnd_out, - const int *lbnd, const int *ubnd, int npix_out, - void *out, void *out_var, double *work, - int64_t *nused, int *status ) { -/* -* Name: -* RebinWithBlocking - -* Purpose: -* Rebin a section of a data grid in a memory-efficient way. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int RebinWithBlocking( AstMapping *this, const double *linear_fit, -* int ndim_in, const int *lbnd_in, -* const int *ubnd_in, const void *in, -* const void *in_var, DataType type, -* int spread, const double *params, int flags, -* const void *badval_ptr, int ndim_out, -* const int *lbnd_out, const int *ubnd_out, -* const int *lbnd, const int *ubnd, int npix_out, -* void *out, void *out_var, double *work, -* int64_t *nused, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function rebins a specified section of a rectangular grid of -* data (with any number of dimensions) into another rectangular grid -* (with a possibly different number of dimensions). The coordinate -* transformation used to convert input pixel coordinates into positions -* in the output grid is given by the forward transformation of the -* Mapping which is supplied. Any pixel spreading scheme may be specified -* for distributing the flux of an input pixel amongst the output -* pixels. -* -* This function is very similar to RebinSection, except that in -* order to limit memory usage and to ensure locality of reference, -* it divides the input grid up into "blocks" which have a limited -* extent along each input dimension. Each block, which will not -* contain more than a pre-determined maximum number of pixels, is -* then passed to RebinSection for resampling. - -* Parameters: -* this -* Pointer to a Mapping, whose forward transformation may be -* used to transform the coordinates of pixels in the input -* grid into associated positions in the output grid. -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* linear_fit -* Pointer to an optional array of double which contains the -* coefficients of a linear fit which approximates the above -* Mapping's forward coordinate transformation. If this is -* supplied, it will be used in preference to the above Mapping -* when transforming coordinates. This may be used to enhance -* performance in cases where evaluation of the Mapping's -* forward transformation is expensive. If no linear fit is -* available, a NULL pointer should be supplied. -* -* The way in which the fit coefficients are stored in this -* array and the number of array elements are as defined by the -* astLinearApprox function. -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* in -* Pointer to the input array of data to be rebinned (with one -* element for each pixel in the input grid). The numerical type -* of these data should match the "type" value (below). The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and data type as the "in" array), -* which represent estimates of the statistical variance -* associated with each element of the "in" array. If this -* second array is given (along with the corresponding "out_var" -* array), then estimates of the variance of the rebinned data -* will also be returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* type -* A value taken from the "DataType" enum, which specifies the -* data type of the input and output arrays containing the -* gridded data (and variance) values. -* spread -* A value selected from a set of pre-defined macros to identify -* which pixel spread function should be used. -* params -* Pointer to an optional array of parameters that may be passed -* to the pixel spread algorithm, if required. If no parameters -* are required, a NULL pointer should be supplied. -* flags -* The bitwise OR of a set of flag values which provide additional -* control over the resampling operation. -* badval_ptr -* If the AST__USEBAD flag is set (above), this parameter is a -* pointer to a value which is used to identify bad data and/or -* variance values in the input array(s). The referenced value's -* data type must match that of the "in" (and "in_var") -* arrays. The same value will also be used to flag any output -* array elements for which rebinned values could not be -* obtained. The output arrays(s) may be flagged with this -* value whether or not the AST__USEBAD flag is set (the -* function return value indicates whether any such values have -* been produced). -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output data grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output data grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output data grid in the same way as "lbnd_in" -* and "ubnd_in" define the shape and size of the input grid -* (see above). -* lbnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the first pixel in the -* section of the input data grid which is to be rebinned. -* ubnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the last pixel in the -* section of the input data grid which is to be rebinned. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the input grid which is to be rebinned. This section -* should lie wholly within the extent of the input grid (as defined -* by the "lbnd_out" and "ubnd_out" arrays). Regions of the input -* grid lying outside this section will be ignored. -* npix_out -* The number of pixels in the output array. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the rebinned data will be returned. The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the rebinned values may be returned. This array will only be -* used if the "in_var" array has been given. -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* work -* An optional pointer to a double array with the same size as -* the "out" array. The contents of this array (if supplied) are -* incremented by the accumulated weights assigned to each output pixel. -* If no accumulated weights are required, a NULL pointer should be -* given. -* nused -* An optional pointer to a int64_t which will be incremented by the -* number of input values pasted into the output array. Ignored if NULL. - -* Returned Value: -* A non-zero value is returned if "flags" included AST__CONSERVEFLUX (i.e. -* flux conservation was requested), but the supplied linear fit to the -* forward transformation of the Mapping had zero determinant (no error -* is reported if this happens). Zero is returned otherwise. - -*/ - -/* Local Constants: */ - const int mxpix = 2 * 1024; /* Maximum number of pixels in a block (this - relatively small number seems to give best - performance) */ - -/* Local Variables: */ - double factor; /* Flux conservation factor */ - int *dim_block; /* Pointer to array of block dimensions */ - int *lbnd_block; /* Pointer to block lower bound array */ - int *ubnd_block; /* Pointer to block upper bound array */ - int dim; /* Dimension size */ - int done; /* All blocks rebinned? */ - int hilim; /* Upper limit on maximum block dimension */ - int idim; /* Loop counter for dimensions */ - int lolim; /* Lower limit on maximum block dimension */ - int mxdim_block; /* Maximum block dimension */ - int npix; /* Number of pixels in block */ - int result; /* Returned value */ - -/* Initialise */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Allocate workspace. */ - lbnd_block = astMalloc( sizeof( int ) * (size_t) ndim_in ); - ubnd_block = astMalloc( sizeof( int ) * (size_t) ndim_in ); - dim_block = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Find the optimum block size. */ -/* ---------------------------- */ -/* We first need to find the maximum extent which a block of input - pixels may have in each dimension. We determine this by taking the - input grid extent in each dimension and then limiting the maximum - dimension size until the resulting number of pixels is sufficiently - small. This approach allows the block shape to approximate (or - match) the input grid shape when appropriate. */ - -/* First loop to calculate the total number of input pixels and the - maximum input dimension size. */ - npix = 1; - mxdim_block = 0; - for ( idim = 0; idim < ndim_in; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - npix *= dim; - if ( mxdim_block < dim ) mxdim_block = dim; - } - -/* If the number of input pixels is too large for a single block, we - perform iterations to determine the optimum upper limit on a - block's dimension size. Initialise the limits on this result. */ - if ( npix > mxpix ) { - lolim = 1; - hilim = mxdim_block; - -/* Loop to perform a binary chop, searching for the best result until - the lower and upper limits on the result converge to adjacent - values. */ - while ( ( hilim - lolim ) > 1 ) { - -/* Form a new estimate from the mid-point of the previous limits. */ - mxdim_block = ( hilim + lolim ) / 2; - -/* See how many pixels a block contains if its maximum dimension is - limited to this new value. */ - for ( npix = 1, idim = 0; idim < ndim_in; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - npix *= ( dim < mxdim_block ) ? dim : mxdim_block; - } - -/* Update the appropriate limit, according to whether the number of - pixels is too large or too small. */ - *( ( npix <= mxpix ) ? &lolim : &hilim ) = mxdim_block; - } - -/* When iterations have converged, obtain the maximum limit on the - dimension size of a block which results in no more than the maximum - allowed number of pixels per block. However, ensure that all block - dimensions are at least 2. */ - mxdim_block = lolim; - } - if ( mxdim_block < 2 ) mxdim_block = 2; - -/* Calculate the block dimensions by applying this limit to the output - grid dimensions. */ - for ( idim = 0; idim < ndim_in; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - dim_block[ idim ] = ( dim < mxdim_block ) ? dim : mxdim_block; - -/* Also initialise the lower and upper bounds of the first block of - output grid pixels to be rebinned, ensuring that this does not - extend outside the grid itself. */ - lbnd_block[ idim ] = lbnd[ idim ]; - ubnd_block[ idim ] = MinI( lbnd[ idim ] + dim_block[ idim ] - 1, - ubnd[ idim ], status ); - } - -/* Determine the flux conservation constant if needed. */ -/* --------------------------------------------------- */ - factor = 1.0; - if( flags & AST__CONSERVEFLUX ) { - if( linear_fit ) { - factor = MatrixDet( ndim_out, ndim_in, linear_fit + ndim_out, - status ); - if( factor != 0.0 ) { - factor = 1.0/factor; - } else { - result = 1; - } - } else { - result = 1; - } - } - -/* Rebin each block of input pixels. */ -/* --------------------------------- */ -/* Loop to generate the extent of each block of input pixels and to - rebin them. */ - done = result; - while ( !done && astOK ) { - -/* Rebin the current block, accumulating the sum of bad pixels produced. */ - RebinSection( this, linear_fit, ndim_in, lbnd_in, ubnd_in, in, - in_var, factor, type, spread, params, flags, badval_ptr, - ndim_out, lbnd_out, ubnd_out, lbnd_block, ubnd_block, - npix_out, out, out_var, work, nused, status ); - -/* Update the block extent to identify the next block of input pixels. */ - idim = 0; - do { - -/* We find the least significant dimension where the upper bound of - the block has not yet reached the upper bound of the region of the - input grid which we are rebinning. The block's position is then - incremented by one block extent along this dimension, checking that - the resulting extent does not go outside the region being rebinned. */ - if ( ubnd_block[ idim ] < ubnd[ idim ] ) { - lbnd_block[ idim ] = MinI( lbnd_block[ idim ] + - dim_block[ idim ], ubnd[ idim ], status ); - ubnd_block[ idim ] = MinI( lbnd_block[ idim ] + - dim_block[ idim ] - 1, - ubnd[ idim ], status ); - break; - -/* If any less significant dimensions are found where the upper bound - of the block has reached its maximum value, we reset the block to - its lowest position. */ - } else { - lbnd_block[ idim ] = lbnd[ idim ]; - ubnd_block[ idim ] = MinI( lbnd[ idim ] + dim_block[ idim ] - 1, - ubnd[ idim ], status ); - -/* All the blocks have been processed once the position along the most - significant dimension has been reset. */ - done = ( ++idim == ndim_in ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - lbnd_block = astFree( lbnd_block ); - ubnd_block = astFree( ubnd_block ); - dim_block = astFree( dim_block ); - -/* Return a flag indicating if there was an error conserving flux. */ - return result; -} - -static AstMapping *RemoveRegions( AstMapping *this, int *status ) { -/* -*++ -* Name: -c astRemoveRegions -f AST_REMOVEREGIONS - -* Purpose: -* Remove any Regions from a Mapping. - -* Type: -* Public function. - -* Synopsis: -c #include "mapping.h" -c AstMapping *astRemoveRegions( AstMapping *this ) -f RESULT = AST_REMOVEREGIONS( THIS, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -* This function searches the suppliedMapping (which may be a -* compound Mapping such as a CmpMap) for any component Mappings -* that are instances of the AST Region class. It then creates -* a new Mapping from which all Regions have been removed. If -* a Region cannot simply be removed (for instance, if it is a -* component of a parallel CmpMap), then it is replaced with an -* equivalent UnitMap in the returned Mapping. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the original Mapping. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astRemoveRegions() -f AST_REMOVEREGIONS = INTEGER -* A new pointer to the (possibly modified) Mapping. - -* Applicability: -* CmpFrame -* If the supplied Mapping is a CmpFrame, any component Frames -* that are instances of the Region class are replaced by the -* equivalent Frame. -* FrameSet -* If the supplied Mapping is a FrameSet, the returned Mapping -* will be a copy of the supplied FrameSet in which Regions -* have been removed from all the inter-Frame Mappings, and any -* Frames which are instances of the Region class are replaced by -* the equivalent Frame. -* Mapping -* This function applies to all Mappings. -* Region -* If the supplied Mapping is a Region, the returned Mapping will -* be the equivalent Frame. - -* Notes: -* - This function can safely be applied even to Mappings -* which contain no Regions. If no Regions are found, it -c behaves exactly like astClone and returns a pointer to the -f behaves exactly like AST_CLONE and returns a pointer to the -* original Mapping. -* - The Mapping returned by this function may not be independent -* of the original (even if some Regions were removed), and -* modifying it may therefore result in indirect modification of -* the original. If a completely independent result is required, a -c copy should be made using astCopy. -f copy should be made using AST_COPY. -* - A null Object pointer (AST__NULL) will be returned if this -c function is invoked with the AST error status set, or if it -f function is invoked with STATUS set to an error value, or if it -* should fail for any reason. -*-- -*/ - -/* This base iplementation just returns a clone of the supplied Mapping - pointer. Sub-classes should override it as necessary. */ - return astClone( this ); -} - -static void ReportPoints( AstMapping *this, int forward, - AstPointSet *in_points, AstPointSet *out_points, int *status ) { -/* -*+ -* Name: -* astReportPoints - -* Purpose: -* Report the effect of transforming a set of points using a Mapping. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* void astReportPoints( AstMapping *this, int forward, -* AstPointSet *in_points, AstPointSet *out_points ) - -* Class Membership: -* Mapping method. - -* Description: -* This function reports the coordinates of a set of points before -* and after being transformed by a Mapping, by writing them to -* standard output. - -* Parameters: -* this -* Pointer to the Mapping. -* forward -* A non-zero value indicates that the Mapping's forward -* coordinate transformation has been applied, while a zero -* value indicates the inverse transformation. -* in_points -* Pointer to a PointSet which is associated with the -* coordinates of a set of points before the Mapping was -* applied. -* out_points -* Pointer to a PointSet which is associated with the -* coordinates of the same set of points after the Mapping has -* been applied. - -* Notes: -* - This method is provided as a development and debugging aid to -* be invoked when coordinates are transformed by public Mapping -* methods and under control of the "Report" Mapping attribute. -* - Derived clases may over-ride this method in order to change -* the way in which coordinates are formatted, etc. -*- -*/ - -/* Local Variables: */ - double **ptr_in; /* Pointer to array of input data pointers */ - double **ptr_out; /* Pointer to array of output data pointers */ - int coord; /* Loop counter for coordinates */ - int ncoord_in; /* Number of input coordinates per point */ - int ncoord_out; /* Number of output coordinates per point */ - int npoint; /* Number of points to report */ - int npoint_in; /* Number of input points */ - int npoint_out; /* Number of output points */ - int point; /* Loop counter for points */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain the numbers of points and coordinates associated with each - PointSet. */ - npoint_in = astGetNpoint( in_points ); - npoint_out = astGetNpoint( out_points ); - ncoord_in = astGetNcoord( in_points ); - ncoord_out = astGetNcoord( out_points ); - -/* Obtain the pointers that give access to the coordinate data - associated with each PointSet. */ - ptr_in = astGetPoints( in_points ); - ptr_out = astGetPoints( out_points ); - -/* In the event that both PointSets don't contain equal numbers of - points (this shouldn't actually happen), simply use the minimum - number. */ - npoint = ( npoint_in < npoint_out ) ? npoint_in : npoint_out; - -/* Loop to report the effect of the Mapping on each point in turn. */ - for ( point = 0; point < npoint; point++ ) { - -/* Report the input coordinates (in parentheses and separated by - commas). Replace coordinate values of AST__BAD with the string - "<bad>" to indicate missing values. */ - printf( "(" ); - for ( coord = 0; coord < ncoord_in; coord++ ) { - if ( ptr_in[ coord ][ point ] == AST__BAD ) { - printf( "%s<bad>", coord ? ", " : "" ); - } else { - printf( "%s%.*g", coord ? ", " : "", - AST__DBL_DIG, ptr_in[ coord ][ point ] ); - } - } - -/* Similarly report the output coordinates. */ - printf( ") --> (" ); - for ( coord = 0; coord < ncoord_out; coord++ ) { - if ( ptr_out[ coord ][ point ] == AST__BAD ) { - printf( "%s<bad>", coord ? ", " : "" ); - } else { - printf( "%s%.*g", coord ? ", " : "", - AST__DBL_DIG, ptr_out[ coord ][ point ] ); - } - } - printf( ")\n" ); - } -} - -/* -*++ -* Name: -c astResample<X> -f AST_RESAMPLE<X> - -* Purpose: -* Resample a region of a data grid. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c int astResample<X>( AstMapping *this, int ndim_in, -c const int lbnd_in[], const int ubnd_in[], -c const <Xtype> in[], const <Xtype> in_var[], -c int interp, void (* finterp)( void ), -c const double params[], int flags, -c double tol, int maxpix, -c <Xtype> badval, int ndim_out, -c const int lbnd_out[], const int ubnd_out[], -c const int lbnd[], const int ubnd[], -c <Xtype> out[], <Xtype> out_var[] ); -f RESULT = AST_RESAMPLE<X>( THIS, NDIM_IN, LBND_IN, UBND_IN, IN, IN_VAR, -f INTERP, FINTERP, PARAMS, FLAGS, -f TOL, MAXPIX, BADVAL, -f NDIM_OUT, LBND_OUT, UBND_OUT, -f LBND, UBND, OUT, OUT_VAR, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -* This is a set of functions for resampling gridded data (e.g. an -* image) under the control of a geometrical transformation, which -* is specified by a Mapping. The functions operate on a pair of -* data grids (input and output), each of which may have any number -* of dimensions. Resampling may be restricted to a specified -* region of the output grid. An associated grid of error estimates -* associated with the input data may also be supplied (in the form -* of variance values), so as to produce error estimates for the -* resampled output data. Propagation of missing data (bad pixels) -* is supported. -* -* You should use a resampling function which matches the numerical -* type of the data you are processing by replacing <X> in -c the generic function name astResample<X> by an appropriate 1- or -f the generic function name AST_RESAMPLE<X> by an appropriate 1- or -* 2-character type code. For example, if you are resampling data -c with type "float", you should use the function astResampleF (see -f with type REAL, you should use the function AST_RESAMPLER (see -* the "Data Type Codes" section below for the codes appropriate to -* other numerical types). -* -* Resampling of the grid of input data is performed by -* transforming the coordinates of the centre of each output grid -* element (or pixel) into the coordinate system of the input grid. -* Since the resulting coordinates will not, in general, coincide -* with the centre of an input pixel, sub-pixel interpolation is -* performed between the neighbouring input pixels. This produces a -* resampled value which is then assigned to the output pixel. A -* choice of sub-pixel interpolation schemes is provided, but you -* may also implement your own. -* -* This algorithm samples the input data value, it does not integrate -* it. Thus total data value in the input image will not, in general, -* be conserved. However, an option is provided (see the "Control Flags" -* section below) which can produce approximate flux conservation by -* scaling the output values using the ratio of the output pixel size -* to the input pixel size. However, if accurate flux conservation is -* important to you, consder using the -c astRebin<X> or astRebinSeq<X> family of functions -f AST_REBIN<X> or AST_REBINSEQ<X> family of routines -* instead. -* -* Output pixel coordinates are transformed into the coordinate -* system of the input grid using the inverse transformation of the -* Mapping which is supplied. This means that geometrical features -* in the input data are subjected to the Mapping's forward -* transformation as they are transferred from the input to the -* output grid (although the Mapping's forward transformation is -* not explicitly used). -* -* In practice, transforming the coordinates of every pixel of a -* large data grid can be time-consuming, especially if the Mapping -* involves complicated functions, such as sky projections. To -* improve performance, it is therefore possible to approximate -* non-linear Mappings by a set of linear transformations which are -* applied piece-wise to separate sub-regions of the data. This -* approximation process is applied automatically by an adaptive -* algorithm, under control of an accuracy criterion which -* expresses the maximum tolerable geometrical distortion which may -* be introduced, as a fraction of a pixel. -* -* This algorithm first attempts to approximate the Mapping with a -* linear transformation applied over the whole region of the -* output grid which is being used. If this proves to be -* insufficiently accurate, the output region is sub-divided into -* two along its largest dimension and the process is repeated -* within each of the resulting sub-regions. This process of -* sub-division continues until a sufficiently good linear -* approximation is found, or the region to which it is being -* applied becomes too small (in which case the original Mapping is -* used directly). - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to a Mapping, whose inverse transformation will be -* used to transform the coordinates of pixels in the output -* grid into the coordinate system of the input grid. This -* yields the positions which are used to obtain resampled -* values by sub-pixel interpolation within the input grid. -* -* The number of input coordinates used by this Mapping (as -* given by its Nin attribute) should match the number of input -c grid dimensions given by the value of "ndim_in" -f grid dimensions given by the value of NDIM_IN -* below. Similarly, the number of output coordinates (Nout -* attribute) should match the number of output grid dimensions -c given by "ndim_out". -f given by NDIM_OUT. -c ndim_in -f NDIM_IN = INTEGER (Given) -* The number of dimensions in the input grid. This should be at -* least one. -c lbnd_in -f LBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the input grid along each dimension. -c ubnd_in -f UBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the input grid along each dimension. -* -c Note that "lbnd_in" and "ubnd_in" together define the shape -f Note that LBND_IN and UBND_IN together define the shape -* and size of the input grid, its extent along a particular -c (j'th) dimension being ubnd_in[j]-lbnd_in[j]+1 (assuming the -c index "j" to be zero-based). They also define -f (J'th) dimension being UBND_IN(J)-LBND_IN(J)+1. They also define -* the input grid's coordinate system, each pixel having unit -* extent along each dimension with integral coordinate values -* at its centre. -c in -f IN( * ) = <Xtype> (Given) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* input grid, containing the input data to be resampled. The -* numerical type of this array should match the 1- or -* 2-character type code appended to the function name (e.g. if -c you are using astResampleF, the type of each array element -c should be "float"). -f you are using AST_RESAMPLER, the type of each array element -f should be REAL). -* -* The storage order of data within this array should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c in_var -f IN_VAR( * ) = <Xtype> (Given) -c An optional pointer to a second array with the same size and -c type as the "in" array. If given, this should contain a set -c of non-negative values which represent estimates of the -c statistical variance associated with each element of the "in" -c array. If this array is supplied (together with the -c corresponding "out_var" array), then estimates of the -c variance of the resampled output data will be calculated. -c -c If no input variance estimates are being provided, a NULL -c pointer should be given. -f An optional second array with the same size and type as the -f IN array. If the AST__USEVAR flag is set via the FLAGS -f argument (below), this array should contain a set of -f non-negative values which represent estimates of the -f statistical variance associated with each element of the IN -f array. Estimates of the variance of the resampled output data -f will then be calculated. -f -f If the AST__USEVAR flag is not set, no input variance -f estimates are required and this array will not be used. A -f dummy (e.g. one-element) array may then be supplied. -c interp -f INTERP = INTEGER (Given) -c This parameter specifies the scheme to be used for sub-pixel -f This argument specifies the scheme to be used for sub-pixel -* interpolation within the input grid. It may be used to select -* from a set of pre-defined schemes by supplying one of the -* values described in the "Sub-Pixel Interpolation Schemes" -* section below. If a value of zero is supplied, then the -* default linear interpolation scheme is used (equivalent to -* supplying the value AST__LINEAR). -* -* Alternatively, you may supply a value which indicates that -c you will provide your own function to perform sub-pixel -c interpolation by means of the "finterp " parameter. Again, see -f you will provide your own routine to perform sub-pixel -f interpolation by means of the FINTERP argument. Again, see -* the "Sub-Pixel Interpolation Schemes" section below for -* details. -c finterp -f FINTERP = SUBROUTINE (Given) -c If the value given for the "interp" parameter indicates that -c you will provide your own function for sub-pixel -c interpolation, then a pointer to that function should be -c given here. For details of the interface which the function -c should have (several are possible, depending on the value of -c "interp"), see the "Sub-Pixel Interpolation Schemes" section -c below. -f If the value given for the INTERP argument indicates that you -f will provide your own routine for sub-pixel interpolation, -f then the name of that routine should be given here (the name -f should also appear in a Fortran EXTERNAL statement in the -f routine which invokes AST_RESAMPLE<X>). For details of the -f interface which the routine should have (several are -f possible, depending on the value of INTERP), see the -f "Sub-Pixel Interpolation Schemes" section below. -* -c If the "interp" parameter has any other value, corresponding -c to one of the pre-defined interpolation schemes, then this -c function will not be used and you may supply a NULL pointer. -f If the INTERP argument has any other value, corresponding to -f one of the pre-defined interpolation schemes, then this -f routine will not be used and you may supply the null routine -f AST_NULL here (note only one underscore). No EXTERNAL -f statement is required for this routine, so long as the AST_PAR -f include file has been used. -c params -f PARAMS( * ) = DOUBLE PRECISION (Given) -c An optional pointer to an array of double which should contain -f An optional array which should contain -* any additional parameter values required by the sub-pixel -* interpolation scheme. If such parameters are required, this -* will be noted in the "Sub-Pixel Interpolation Schemes" -c section below (you may also use this array to pass values -c to your own interpolation function). -f section below (you may also use this array to pass values -f to your own interpolation routine). -* -c If no additional parameters are required, this array is not -c used and a NULL pointer may be given. -f If no additional parameters are required, this array is not -f used. A dummy (e.g. one-element) array may then be supplied. -c flags -f FLAGS = INTEGER (Given) -c The bitwise OR of a set of flag values which may be used to -f The sum of a set of flag values which may be used to -* provide additional control over the resampling operation. See -* the "Control Flags" section below for a description of the -* options available. If no flag values are to be set, a value -* of zero should be given. -c tol -f TOL = DOUBLE PRECISION (Given) -* The maximum tolerable geometrical distortion which may be -* introduced as a result of approximating non-linear Mappings -* by a set of piece-wise linear transformations. This should be -* expressed as a displacement in pixels in the input grid's -* coordinate system. -* -* If piece-wise linear approximation is not required, a value -* of zero may be given. This will ensure that the Mapping is -* used without any approximation, but may increase execution -* time. -c maxpix -f MAXPIX = INTEGER (Given) -* A value which specifies an initial scale size (in pixels) for -* the adaptive algorithm which approximates non-linear Mappings -* with piece-wise linear transformations. Normally, this should -* be a large value (larger than any dimension of the region of -* the output grid being used). In this case, a first attempt to -* approximate the Mapping by a linear transformation will be -* made over the entire output region. -* -* If a smaller value is used, the output region will first be -c divided into sub-regions whose size does not exceed "maxpix" -f divided into sub-regions whose size does not exceed MAXPIX -* pixels in any dimension. Only at this point will attempts at -* approximation commence. -* -* This value may occasionally be useful in preventing false -* convergence of the adaptive algorithm in cases where the -* Mapping appears approximately linear on large scales, but has -* irregularities (e.g. holes) on smaller scales. A value of, -* say, 50 to 100 pixels can also be employed as a safeguard in -* general-purpose software, since the effect on performance is -* minimal. -* -* If too small a value is given, it will have the effect of -* inhibiting linear approximation altogether (equivalent to -c setting "tol" to zero). Although this may degrade -f setting TOL to zero). Although this may degrade -* performance, accurate results will still be obtained. -c badval -f BADVAL = <Xtype> (Given) -* This argument should have the same type as the elements of -c the "in" array. It specifies the value used to flag missing -f the IN array. It specifies the value used to flag missing -* data (bad pixels) in the input and output arrays. -* -c If the AST__USEBAD flag is set via the "flags" parameter, -f If the AST__USEBAD flag is set via the FLAGS argument, -c then this value is used to test for bad pixels in the "in" -c (and "in_var") array(s). -f then this value is used to test for bad pixels in the IN -f (and IN_VAR) array(s). -* -c Unless the AST__NOBAD flag is set via the "flags" parameter, -f Unless the AST__NOBAD flag is set via the FLAGS argument, -* this value is also used to flag any output -c elements in the "out" (and "out_var") array(s) for which -f elements in the OUT (and OUT_VAR) array(s) for which -* resampled values could not be obtained (see the "Propagation -* of Missing Data" section below for details of the -c circumstances under which this may occur). The astResample<X> -f circumstances under which this may occur). The AST_RESAMPLE<X> -* function return value indicates whether any such values have -* been produced. If the AST__NOBAD flag is set. then output array -* elements for which no resampled value could be obtained are -* left set to the value they had on entry to this function. -c ndim_out -f NDIM_OUT = INTEGER (Given) -* The number of dimensions in the output grid. This should be -* at least one. It need not necessarily be equal to the number -* of dimensions in the input grid. -c lbnd_out -f LBND_OUT( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the output grid along each dimension. -c ubnd_out -f UBND_OUT( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the output grid along each dimension. -* -c Note that "lbnd_out" and "ubnd_out" together define the -f Note that LBND_OUT and UBND_OUT together define the -* shape, size and coordinate system of the output grid in the -c same way as "lbnd_in" and "ubnd_in" define the shape, size -f same way as LBND_IN and UBND_IN define the shape, size -* and coordinate system of the input grid. -c lbnd -f LBND( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the first pixel in the region -* of the output grid for which a resampled value is to be -* calculated. -c ubnd -f UBND( NDIM_OUT ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_out" elements, -f An array -* containing the coordinates of the last pixel in the region of -* the output grid for which a resampled value is to be -* calculated. -* -c Note that "lbnd" and "ubnd" together define the shape and -f Note that LBND and UBND together define the shape and -* position of a (hyper-)rectangular region of the output grid -* for which resampled values should be produced. This region -* should lie wholly within the extent of the output grid (as -c defined by the "lbnd_out" and "ubnd_out" arrays). Regions of -f defined by the LBND_OUT and UBND_OUT arrays). Regions of -* the output grid lying outside this region will not be -* modified. -c out -f OUT( * ) = <Xtype> (Returned) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* output grid, into which the resampled data values will be -* returned. The numerical type of this array should match that -c of the "in" array, and the data storage order should be such -f of the IN array, and the data storage order should be such -* that the index of the first grid dimension varies most -* rapidly and that of the final dimension least rapidly -c (i.e. Fortran array indexing is used). -f (i.e. normal Fortran array storage order). -c out_var -f OUT_VAR( * ) = <Xtype> (Returned) -c An optional pointer to an array with the same type and size -c as the "out" array. If given, this array will be used to -c return variance estimates for the resampled data values. This -c array will only be used if the "in_var" array has also been -c supplied. -f An optional array with the same type and size as the OUT -f array. If the AST__USEVAR flag is set via the FLAGS argument, -f this array will be used to return variance estimates for the -f resampled data values. -* -* The output variance values will be calculated on the -* assumption that errors on the input data values are -* statistically independent and that their variance estimates -* may simply be summed (with appropriate weighting factors) -* when several input pixels contribute to an output data -* value. If this assumption is not valid, then the output error -* estimates may be biased. In addition, note that the -* statistical errors on neighbouring output data values (as -* well as the estimates of those errors) may often be -* correlated, even if the above assumption about the input data -* is correct, because of the sub-pixel interpolation schemes -* employed. -* -c If no output variance estimates are required, a NULL pointer -c should be given. -f If the AST__USEVAR flag is not set, no output variance -f estimates will be calculated and this array will not be -f used. A dummy (e.g. one-element) array may then be supplied. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astResample<X>() -f AST_RESAMPLE<X> = INTEGER -* The number of output pixels for which no valid resampled value -* could be obtained. Thus, in the absence of any error, a returned -* value of zero indicates that all the required output pixels -* received valid resampled data values (and variances). See the -c "badval" and "flags" parameters. -f BADVAL and FLAGS arguments. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. - -* Data Type Codes: -* To select the appropriate resampling function, you should -c replace <X> in the generic function name astResample<X> with a -f replace <X> in the generic function name AST_RESAMPLE<X> with a -* 1- or 2-character data type code, so as to match the numerical -* type <Xtype> of the data you are processing, as follows: -c - D: double -c - F: float -c - L: long int (may be 32 or 64 bit) -c - K: 64 bit int -c - UL: unsigned long int (may be 32 or 64 bit) -c - UK: unsigned 64 bit int -c - I: int -c - UI: unsigned int -c - S: short int -c - US: unsigned short int -c - B: byte (signed char) -c - UB: unsigned byte (unsigned char) -f - D: DOUBLE PRECISION -f - R: REAL -f - I: INTEGER -f - UI: INTEGER (treated as unsigned) -f - S: INTEGER*2 (short integer) -f - US: INTEGER*2 (short integer, treated as unsigned) -f - B: BYTE (treated as signed) -f - UB: BYTE (treated as unsigned) -* -c For example, astResampleD would be used to process "double" -c data, while astResampleS would be used to process "short int" -c data, etc. -f For example, AST_RESAMPLED would be used to process DOUBLE -f PRECISION data, while AST_RESAMPLES would be used to process -f short integer data (stored in an INTEGER*2 array), etc. -f -f For compatibility with other Starlink facilities, the codes W -f and UW are provided as synonyms for S and US respectively (but -f only in the Fortran interface to AST). - -* Sub-Pixel Interpolation Schemes: -* There is no such thing as a perfect sub-pixel interpolation -* scheme and, in practice, all resampling will result in some -* degradation of gridded data. A range of schemes is therefore -* provided, from which you can choose the one which best suits -* your needs. -* -* In general, a balance must be struck between schemes which tend -* to degrade sharp features in the data by smoothing them, and -* those which attempt to preserve sharp features. The latter will -* often tend to introduce unwanted oscillations, typically visible -* as "ringing" around sharp features and edges, especially if the -* data are under-sampled (i.e. if the sharpest features are less -* than about two pixels across). In practice, a good interpolation -* scheme is likely to be a compromise and may exhibit some aspects -* of both these features. -* -* For under-sampled data, some interpolation schemes may appear to -* preserve data resolution because they transform single input -* pixels into single output pixels, rather than spreading their -* data between several output pixels. While this may look -* better cosmetically, it can result in a geometrical shift of -* sharp features in the data. You should beware of this if you -* plan to use such features (e.g.) for image alignment. -* -* The following are two easy-to-use sub-pixel interpolation -* schemes which are generally applicable. They are selected by -c supplying the appropriate value (defined in the "ast.h" header -c file) via the "interp" parameter. In these cases, the "finterp" -c and "params" parameters are not used: -f supplying the appropriate value (defined in the AST_PAR include -f file) via the INTERP argument. In these cases, the FINTERP -f and PARAMS arguments are not used: -* -* - AST__NEAREST: This is the simplest possible scheme, in which -* the value of the input pixel with the nearest centre to the -* interpolation point is used. This is very quick to execute and -* will preserve single-pixel features in the data, but may -* displace them by up to half their width along each dimension. It -* often gives a good cosmetic result, so is useful for quick-look -* processing, but is unsuitable if accurate geometrical -* transformation is required. -* - AST__LINEAR: This is the default scheme, which uses linear -* interpolation between the nearest neighbouring pixels in the -* input grid (there are two neighbours in one dimension, four -* neighbours in two dimensions, eight in three dimensions, -* etc.). It is superior to the nearest-pixel scheme (above) in not -* displacing features in the data, yet it still executes fairly -* rapidly. It is generally a safe choice if you do not have any -* particular reason to favour another scheme, since it cannot -* introduce oscillations. However, it does introduce some spatial -* smoothing which varies according to the distance of the -* interpolation point from the neighbouring pixels. This can -* degrade the shape of sharp features in the data in a -* position-dependent way. It may also show in the output variance -* grid (if used) as a pattern of stripes or fringes. -* -* An alternative set of interpolation schemes is based on forming -* the interpolated value from the weighted sum of a set of -* surrounding pixel values (not necessarily just the nearest -* neighbours). This approach has its origins in the theory of -* digital filtering, in which interpolated values are obtained by -* conceptually passing the sampled data (represented by a grid of -* delta functions) through a linear filter which implements a -* convolution. Because the convolution kernel is continuous, the -* convolution yields a continuous function which may then be -* evaluated at fractional pixel positions. The (possibly -* multi-dimensional) kernel is usually regarded as "separable" and -* formed from the product of a set of identical 1-dimensional -* kernel functions, evaluated along each dimension. Different -* interpolation schemes are then distinguished by the choice of -* this 1-dimensional interpolation kernel. The number of -* surrounding pixels which contribute to the result may also be -* varied. -* -* From a practical standpoint, it is useful to divide the weighted -* sum of pixel values by the sum of the weights when determining -* the interpolated value. Strictly, this means that a true -* convolution is no longer being performed. However, the -* distinction is rarely important in practice because (for -* slightly subtle reasons) the sum of weights is always -* approximately constant for good interpolation kernels. The -* advantage of this technique, which is used here, is that it can -* easily accommodate missing data and tends to minimise unwanted -* oscillations at the edges of the data grid. -* -* In the following schemes, which are based on a 1-dimensional -c interpolation kernel, the first element of the "params" array -f interpolation kernel, the first element of the PARAMS array -* should be used to specify how many pixels are to contribute to the -* interpolated result on either side of the interpolation point in -* each dimension (the nearest integer value is used). Execution time -* increases rapidly with this number. Typically, a value of 2 is -* appropriate and the minimum value used will be 1 (i.e. two pixels -* altogether, one on either side of the interpolation point). -c A value of zero or less may be given for "params[0]" -f A value of zero or less may be given for PARAMS(1) -* to indicate that a suitable number of pixels should be calculated -* automatically. -* -c In each of these cases, the "finterp" parameter is not used: -f In each of these cases, the FINTERP argument is not used: -* -* - AST__GAUSS: This scheme uses a kernel of the form exp(-k*x*x), with -* k a positive constant. The full-width at half-maximum (FWHM) is -* given by -c "params[1]" -f PARAMS(2) -f value, which should be at least 0.1 (in addition, setting PARAMS(1) -* to zero will select the number of contributing pixels so as to utilise -* the width of the kernel out to where the envelope declines to 1% of its -* maximum value). This kernel suppresses noise at the expense of -* smoothing the output array. -* - AST__SINC: This scheme uses a sinc(pi*x) kernel, where x is the -* pixel offset from the interpolation point and sinc(z)=sin(z)/z. This -* sometimes features as an "optimal" interpolation kernel in books on -* image processing. Its supposed optimality depends on the assumption -* that the data are band-limited (i.e. have no spatial frequencies above -* a certain value) and are adequately sampled. In practice, astronomical -* data rarely meet these requirements. In addition, high spatial -* frequencies are often present due (e.g.) to image defects and cosmic -* ray events. Consequently, substantial ringing can be experienced with -* this kernel. The kernel also decays slowly with distance, so that -* many surrounding pixels are required, leading to poor performance. -* Abruptly truncating it, by using only a few neighbouring pixels, -c improves performance and may reduce ringing (if "params[0]" is set to -f improves performance and may reduce ringing (if PARAMS(1) is set to -* zero, then only two pixels will be used on either side). However, a -* more gradual truncation, as implemented by other kernels, is generally -* to be preferred. This kernel is provided mainly so that you can -* convince yourself not to use it! -* - AST__SINCSINC: This scheme uses an improved kernel, of the form -* sinc(pi*x).sinc(k*pi*x), with k a constant, out to the point where -* sinc(k*pi*x) goes to zero, and zero beyond. The second sinc() factor -* provides an "envelope" which gradually rolls off the normal sinc(pi*x) -* kernel at large offsets. The width of this envelope is specified by -* giving the number of pixels offset at which it goes to zero by means -c of the "params[1]" value, which should be at least 1.0 (in addition, -c setting "params[0]" to zero will select the number of contributing -f of the PARAMS(2) value, which should be at least 1.0 (in addition, -f setting PARAMS(1) to zero will select the number of contributing -* pixels so as to utilise the full width of the kernel, out to where it -c reaches zero). The case given by "params[0]=2, params[1]=2" is typically -f reaches zero). The case given by PARAMS(1)=2, PARAMS(2)=2 is typically -* a good choice and is sometimes known as the Lanczos kernel. This is a -* valuable general-purpose interpolation scheme, intermediate in its -* visual effect on images between the AST__NEAREST and AST__LINEAR -* schemes. Although the kernel is slightly oscillatory, ringing is -* adequately suppressed if the data are well sampled. -* - AST__SINCCOS: This scheme uses a kernel of the form -* sinc(pi*x).cos(k*pi*x), with k a constant, out to the point where -* cos(k*pi*x) goes to zero, and zero beyond. As above, the cos() factor -* provides an envelope which gradually rolls off the sinc() kernel -* at large offsets. The width of this envelope is specified by giving -* the number of pixels offset at which it goes to zero by means -c of the "params[1]" value, which should be at least 1.0 (in addition, -c setting "params[0]" to zero will select the number of contributing -f of the PARAMS(2) value, which should be at least 1.0 (in addition, -f setting PARAMS(1) to zero will select the number of contributing -* pixels so as to utilise the full width of the kernel, out to where it -* reaches zero). This scheme gives similar results to the -* AST__SINCSINC scheme, which it resembles. -* - AST__SINCGAUSS: This scheme uses a kernel of the form -* sinc(pi*x).exp(-k*x*x), with k a positive constant. Here, the sinc() -* kernel is rolled off using a Gaussian envelope which is specified by -c giving its full-width at half-maximum (FWHM) by means of the "params[1]" -c value, which should be at least 0.1 (in addition, setting "params[0]" -f giving its full-width at half-maximum (FWHM) by means of the PARAMS(2) -f value, which should be at least 0.1 (in addition, setting PARAMS(1) -* to zero will select the number of contributing pixels so as to utilise -* the width of the kernel out to where the envelope declines to 1% of its -* maximum value). On astronomical images and spectra, good results are -* often obtained by approximately matching the FWHM of the -c envelope function, given by "params[1]", to the point spread function -f envelope function, given by PARAMS(2), to the point spread function -* of the input data. However, there does not seem to be any theoretical -* reason for this. -* - AST__SOMB: This scheme uses a somb(pi*x) kernel (a "sombrero" -* function), where x is the pixel offset from the interpolation point -* and somb(z)=2*J1(z)/z (J1 is a Bessel function of the first kind of -* order 1). It is similar to the AST__SINC kernel, and has the same -* parameter usage. -* - AST__SOMBCOS: This scheme uses a kernel of the form -* somb(pi*x).cos(k*pi*x), with k a constant, out to the point where -* cos(k*pi*x) goes to zero, and zero beyond. It is similar to the -* AST__SINCCOS kernel, and has the same parameter usage. -* -* In addition, the following schemes are provided which are not based -* on a 1-dimensional kernel: -* -* - AST__BLOCKAVE: This scheme simply takes an average of all the -* pixels on the input grid in a cube centred on the interpolation -* point. The number of pixels in the cube is determined by the -c value of the first element of the "params" array, which gives -f value of the first element of the PARAMS array, which gives -* the number of pixels in each dimension on either side of the -c central point. Hence a block of (2 * params[0])^ndim_in -f central point. Hence a block of (2 * PARAMS(1))**NDIM_IN -* pixels in the input grid will be examined to determine the -* value of the output pixel. If the variance is not being used -c (var_in or var_out = NULL) then all valid pixels in this cube -f (USEVAR = .FALSE.) then all valid pixels in this cube -* will be averaged in to the result with equal weight. -* If variances are being used, then each input pixel will be -* weighted proportionally to the reciprocal of its variance; any -* pixel without a valid variance will be discarded. This scheme -* is suitable where the output grid is much coarser than the -* input grid; if the ratio of pixel sizes is R then a suitable -c value of params[0] may be R/2. -f value of PARAMS(1) may be R/2. -* -c Finally, supplying the following values for "interp" allows you -c to implement your own sub-pixel interpolation scheme by means of -c your own function. You should supply a pointer to this function -c via the "finterp" parameter: -f Finally, supplying the following values for INTERP allows you to -f implement your own sub-pixel interpolation scheme by means of -f your own routine. You should supply the name of this routine via -f the FINTERP argument: -* -c - AST__UKERN1: In this scheme, you supply a function to evaluate -c your own 1-dimensional interpolation kernel, which is then used -c to perform sub-pixel interpolation (as described above). The -c function you supply should have the same interface as the -c fictitious astUkern1 function (q.v.). In addition, a value -c should be given via "params[0]" to specify the number of -c neighbouring pixels which are to contribute to each interpolated -c value (in the same way as for the pre-defined interpolation -c schemes described above). Other elements of the "params" array -c are available to pass values to your interpolation function. -f - AST__UKERN1: In this scheme, you supply a routine to evaluate -f your own 1-dimensional interpolation kernel, which is then used -f to perform sub-pixel interpolation (as described above). The -f routine you supply should have the same interface as the -f fictitious AST_UKERN1 routine (q.v.). In addition, a value -f should be given via PARAMS(1) to specify the number of -f neighbouring pixels which are to contribute to each interpolated -f value (in the same way as for the pre-defined interpolation -f schemes described above). Other elements of the PARAMS array -f are available to pass values to your interpolation routine. -* -c - AST__UINTERP: This is a completely general scheme, in which -c your interpolation function has access to all of the input -c data. This allows you to implement any interpolation algorithm -c you choose, which could (for example) be non-linear, or -c adaptive. In this case, the astResample<X> functions play no -c role in the sub-pixel interpolation process and simply handle -c the geometrical transformation of coordinates and other -c housekeeping. The function you supply should have the same -c interface as the fictitious astUinterp function (q.v.). In this -c case, the "params" parameter is not used by astResample<X>, but -c is available to pass values to your interpolation function. -f - AST__UINTERP: This is a completely general scheme, in which -f your interpolation routine has access to all of the input -f data. This allows you to implement any interpolation algorithm -f you choose, which could (for example) be non-linear, or -f adaptive. In this case, the AST_RESAMPLE<X> functions play no -f role in the sub-pixel interpolation process and simply handle -f the geometrical transformation of coordinates and other -f housekeeping. The routine you supply should have the same -f interface as the fictitious AST_UINTERP routine (q.v.). In this -f case, the PARAMS argument is not used by AST_RESAMPLE<X>, but -f is available to pass values to your interpolation routine. - -* Control Flags: -c The following flags are defined in the "ast.h" header file and -f The following flags are defined in the AST_PAR include file and -* may be used to provide additional control over the resampling -* process. Having selected a set of flags, you should supply the -c bitwise OR of their values via the "flags" parameter: -f sum of their values via the FLAGS argument: -* -* - AST__NOBAD: Indicates that any output array elements for which no -* resampled value could be obtained should be left set to the value -* they had on entry to this function. If this flag is not supplied, -* such output array elements are set to the value supplied for -c parameter "badval". Note, this flag cannot be used in conjunction -f argument BADVAL. Note, this flag cannot be used in conjunction -* with the AST__CONSERVEFLUX flag (an error will be reported if both -* flags are specified). -* - AST__URESAMP1, 2, 3 & 4: A set of four flags which are -* reserved for your own use. They may be used to pass private -c information to any sub-pixel interpolation function which you -f information to any sub-pixel interpolation routine which you -* implement yourself. They are ignored by all the pre-defined -* interpolation schemes. -* - AST__USEBAD: Indicates that there may be bad pixels in the -* input array(s) which must be recognised by comparing with the -c value given for "badval" and propagated to the output array(s). -f value given for BADVAL and propagated to the output array(s). -* If this flag is not set, all input values are treated literally -c and the "badval" value is only used for flagging output array -f and the BADVAL value is only used for flagging output array -* values. -f - AST__USEVAR: Indicates that variance information should be -f processed in order to provide estimates of the statistical error -f associated with the resampled values. If this flag is not set, -f no variance processing will occur and the IN_VAR and OUT_VAR -f arrays will not be used. (Note that this flag is only available -f in the Fortran interface to AST.) -* - AST__CONSERVEFLUX: Indicates that the output pixel values should -* be scaled in such a way as to preserve (approximately) the total data -* value in a feature on the sky. Without this flag, each output pixel -* value represents an instantaneous sample of the input data values at -* the corresponding input position. This is appropriate if the input -* data represents the spatial density of some quantity (e.g. surface -* brightness in Janskys per square arc-second) because the output -* pixel values will have the same normalisation and units as the -* input pixel values. However, if the input data values represent -* flux (or some other physical quantity) per pixel, then the -* AST__CONSERVEFLUX flag could be used. This causes each output -* pixel value to be scaled by the ratio of the output pixel size to -* the input pixel size. -* -* This flag can only be used if the Mapping is successfully approximated -* by one or more linear transformations. Thus an error will be reported -* if it used when the -c "tol" parameter -f TOL argument -* is set to zero (which stops the use of linear approximations), or -* if the Mapping is too non-linear to be approximated by a piece-wise -* linear transformation. The ratio of output to input pixel size is -* evaluated once for each panel of the piece-wise linear approximation to -* the Mapping, and is assumed to be constant for all output pixels in the -* panel. The scaling factors for adjacent panels will in general -* differ slightly, and so the joints between panels may be visible when -* viewing the output image at high contrast. If this is a problem, -* reduce the value of the -c "tol" parameter -f TOL argument -* until the difference between adjacent panels is sufficiently small -* to be insignificant. -* -* Note, this flag cannot be used in conjunction with the AST__NOBAD -* flag (an error will be reported if both flags are specified). - -* Propagation of Missing Data: -* Unless the AST__NOBAD flag is specified, instances of missing data -* (bad pixels) in the output grid are -c identified by occurrences of the "badval" value in the "out" -f identified by occurrences of the BADVAL value in the OUT -* array. These may be produced if any of the following happen: -* -* - The input position (the transformed position of the output -* pixel's centre) lies outside the boundary of the grid of input -* pixels. -* - The input position lies inside the boundary of a bad input -* pixel. In this context, an input pixel is considered bad if its -c data value is equal to "badval" and the AST__USEBAD flag is -c set via the "flags" parameter. -f data value is equal to BADVAL and the AST__USEBAD flag is -f set via the FLAGS argument. -* (Positions which have half-integral coordinate values, and -* therefore lie on a pixel boundary, are regarded as lying within -* the pixel with the larger, i.e. more positive, index.) -* - The set of neighbouring input pixels (excluding those which -* are bad) is unsuitable for calculating an interpolated -* value. Whether this is true may depend on the sub-pixel -* interpolation scheme in use. -* - The interpolated value lies outside the range which can be -c represented using the data type of the "out" array. -f represented using the data type of the OUT array. -* -* In addition, associated output variance estimates (if -c calculated) may be declared bad and flagged with the "badval" -c value in the "out_var" array under any of the following -f calculated) may be declared bad and flagged with the BADVAL -f value in the OUT_VAR array under any of the following -* circumstances: -* -c - The associated resampled data value (in the "out" array) is bad. -f - The associated resampled data value (in the OUT array) is bad. -* - The set of neighbouring input pixels which contributed to the -* output data value do not all have valid variance estimates -* associated with them. In this context, an input variance -* estimate may be regarded as bad either because it has the value -c "badval" (and the AST__USEBAD flag is set), or because it is -f BADVAL (and the AST__USEBAD flag is set), or because it is -* negative. -* - The set of neighbouring input pixels for which valid variance -* values are available is unsuitable for calculating an overall -* variance value. Whether this is true may depend on the sub-pixel -* interpolation scheme in use. -* - The variance value lies outside the range which can be -c represented using the data type of the "out_var" array. -f represented using the data type of the OUT_VAR array. -* -* If the AST__NOBAD flag is specified via -c parameter "flags", -f argument FLAGS, -* then output array elements that would otherwise be set to -c "badval" -f BADVAL -* are instead left holding the value they had on entry to this -* function. The number of such array elements is returned as -* the function value. -*-- -*/ -/* Define a macro to implement the function for a specific data - type. */ -#define MAKE_RESAMPLE(X,Xtype) \ -static int Resample##X( AstMapping *this, int ndim_in, \ - const int lbnd_in[], const int ubnd_in[], \ - const Xtype in[], const Xtype in_var[], \ - int interp, void (* finterp)( void ), \ - const double params[], int flags, double tol, \ - int maxpix, Xtype badval, \ - int ndim_out, const int lbnd_out[], \ - const int ubnd_out[], const int lbnd[], \ - const int ubnd[], Xtype out[], Xtype out_var[], int *status ) { \ -\ -/* Local Variables: */ \ - astDECLARE_GLOBALS /* Thread-specific data */ \ - AstMapping *simple; /* Pointer to simplified Mapping */ \ - int idim; /* Loop counter for coordinate dimensions */ \ - int nin; /* Number of Mapping input coordinates */ \ - int nout; /* Number of Mapping output coordinates */ \ - int npix; /* Number of pixels in output region */ \ - int result; /* Result value to return */ \ - int64_t mpix; /* Number of pixels for testing */ \ -\ -/* Initialise. */ \ - result = 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Get a pointer to a structure holding thread-specific global data values */ \ - astGET_GLOBALS(this); \ -\ -/* Obtain values for the Nin and Nout attributes of the Mapping. */ \ - nin = astGetNin( this ); \ - nout = astGetNout( this ); \ -\ -/* If OK, check that the number of input grid dimensions matches the \ - number required by the Mapping and is at least 1. Report an error \ - if necessary. */ \ - if ( astOK && ( ( ndim_in != nin ) || ( ndim_in < 1 ) ) ) { \ - astError( AST__NGDIN, "astResample"#X"(%s): Bad number of input grid " \ - "dimensions (%d).", status, astGetClass( this ), ndim_in ); \ - if ( ndim_in != nin ) { \ - astError( AST__NGDIN, "The %s given requires %d coordinate value%s " \ - "to specify an input position.", status, \ - astGetClass( this ), nin, ( nin == 1 ) ? "" : "s" ); \ - } \ - } \ -\ -/* If OK, also check that the number of output grid dimensions matches \ - the number required by the Mapping and is at least 1. Report an \ - error if necessary. */ \ - if ( astOK && ( ( ndim_out != nout ) || ( ndim_out < 1 ) ) ) { \ - astError( AST__NGDIN, "astResample"#X"(%s): Bad number of output grid " \ - "dimensions (%d).", status, astGetClass( this ), ndim_out ); \ - if ( ndim_out != nout ) { \ - astError( AST__NGDIN, "The %s given generates %s%d coordinate " \ - "value%s for each output position.", status, astGetClass( this ), \ - ( nout < ndim_out ) ? "only " : "", nout, \ - ( nout == 1 ) ? "" : "s" ); \ - } \ - } \ -\ -/* Check that the lower and upper bounds of the input grid are \ - consistent. Report an error if any pair is not. Also get the number \ - of pixels in the input grid. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_in; idim++ ) { \ - if ( lbnd_in[ idim ] > ubnd_in[ idim ] ) { \ - astError( AST__GBDIN, "astResample"#X"(%s): Lower bound of " \ - "input grid (%d) exceeds corresponding upper bound " \ - "(%d).", status, astGetClass( this ), \ - lbnd_in[ idim ], ubnd_in[ idim ] ); \ - astError( AST__GBDIN, "Error in input dimension %d.", status, \ - idim + 1 ); \ - break; \ - } else { \ - mpix *= ubnd_in[ idim ] - lbnd_in[ idim ] + 1; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the input. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astResample"#X"(%s): Supplied input array " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Check that the positional accuracy tolerance supplied is valid and \ - report an error if necessary. */ \ - if ( astOK && ( tol < 0.0 ) ) { \ - astError( AST__PATIN, "astResample"#X"(%s): Invalid positional " \ - "accuracy tolerance (%.*g pixel).", status, \ - astGetClass( this ), AST__DBL_DIG, tol ); \ - astError( AST__PATIN, "This value should not be less than zero." , status); \ - } \ -\ -/* Check that the initial scale size in pixels supplied is valid and \ - report an error if necessary. */ \ - if ( astOK && ( maxpix < 0 ) ) { \ - astError( AST__SSPIN, "astResample"#X"(%s): Invalid initial scale " \ - "size in pixels (%d).", status, astGetClass( this ), maxpix ); \ - astError( AST__SSPIN, "This value should not be less than zero." , status); \ - } \ -\ -/* Check that the lower and upper bounds of the output grid are \ - consistent. Report an error if any pair is not. Also get the \ - number of pixels in the output array. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - if ( lbnd_out[ idim ] > ubnd_out[ idim ] ) { \ - astError( AST__GBDIN, "astResample"#X"(%s): Lower bound of " \ - "output grid (%d) exceeds corresponding upper bound " \ - "(%d).", status, astGetClass( this ), \ - lbnd_out[ idim ], ubnd_out[ idim ] ); \ - astError( AST__GBDIN, "Error in output dimension %d.", status, \ - idim + 1 ); \ - break; \ - } else { \ - mpix *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the output. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astResample"#X"(%s): Supplied output array " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* Similarly check the bounds of the output region. */ \ - mpix = 1; \ - if ( astOK ) { \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - if ( lbnd[ idim ] > ubnd[ idim ] ) { \ - astError( AST__GBDIN, "astResample"#X"(%s): Lower bound of " \ - "output region (%d) exceeds corresponding upper " \ - "bound (%d).", status, astGetClass( this ), \ - lbnd[ idim ], ubnd[ idim ] ); \ -\ -/* Also check that the output region lies wholly within the output \ - grid. */ \ - } else if ( lbnd[ idim ] < lbnd_out[ idim ] ) { \ - astError( AST__GBDIN, "astResample"#X"(%s): Lower bound of " \ - "output region (%d) is less than corresponding " \ - "bound of output grid (%d).", status, astGetClass( this ), \ - lbnd[ idim ], lbnd_out[ idim ] ); \ - } else if ( ubnd[ idim ] > ubnd_out[ idim ] ) { \ - astError( AST__GBDIN, "astResample"#X"(%s): Upper bound of " \ - "output region (%d) exceeds corresponding " \ - "bound of output grid (%d).", status, astGetClass( this ), \ - ubnd[ idim ], ubnd_out[ idim ] ); \ - } else { \ - mpix *= ubnd[ idim ] - lbnd[ idim ] + 1; \ - } \ -\ -/* Say which dimension produced the error. */ \ - if ( !astOK ) { \ - astError( AST__GBDIN, "Error in output dimension %d.", status, \ - idim + 1 ); \ - break; \ - } \ - } \ - } \ -\ -/* Report an error if there are too many pixels in the output region. */ \ - if ( astOK && (int) mpix != mpix ) { \ - astError( AST__EXSPIX, "astResample"#X"(%s): Supplied output region " \ - "contains too many pixels (%g): must be fewer than %d.", \ - status, astGetClass( this ), (double) mpix, INT_MAX ); \ - } \ -\ -/* If we are conserving flux, check "tol" is not zero. */ \ - if( ( flags & AST__CONSERVEFLUX ) && astOK ) { \ - if( tol == 0.0 ) { \ - astError( AST__CNFLX, "astResample"#X"(%s): Flux conservation was " \ - "requested but cannot be performed because zero tolerance " \ - "was also specified.", status, astGetClass( this ) ); \ -\ -/* Also check "nin" and "nout" are equal. */ \ - } else if( nin != nout ) { \ - astError( AST__CNFLX, "astResample"#X"(%s): Flux conservation was " \ - "requested but cannot be performed because the Mapping " \ - "has different numbers of inputs and outputs.", status, \ - astGetClass( this ) ); \ - } \ - } \ -\ -/* If OK, loop to determine how many pixels require resampled values. */ \ - simple = NULL; \ - if ( astOK ) { \ - npix = 1; \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - npix *= ubnd[ idim ] - lbnd[ idim ] + 1; \ - } \ -\ -/* If there are sufficient pixels to make it worthwhile, simplify the \ - Mapping supplied to improve performance. Otherwise, just clone the \ - Mapping pointer. Note we save a pointer to the original Mapping so \ - that lower-level functions can use it if they need to report an \ - error. */ \ - unsimplified_mapping = this; \ - if ( npix > 1024 ) { \ - simple = astSimplify( this ); \ - } else { \ - simple = astClone( this ); \ - } \ - } \ -\ -/* Report an error if the inverse transformation of this simplified \ - Mapping is not defined. */ \ - if ( !astGetTranInverse( simple ) && astOK ) { \ - astError( AST__TRNND, "astResample"#X"(%s): An inverse coordinate " \ - "transformation is not defined by the %s supplied.", status, \ - astGetClass( unsimplified_mapping ), \ - astGetClass( unsimplified_mapping ) ); \ - } \ -\ -/* Perform the resampling. Note that we pass all gridded data, the \ - interpolation function and the bad pixel value by means of pointer \ - types that obscure the underlying data type. This is to avoid \ - having to replicate functions unnecessarily for each data \ - type. However, we also pass an argument that identifies the data \ - type we have obscured. */ \ - result = ResampleAdaptively( simple, ndim_in, lbnd_in, ubnd_in, \ - (const void *) in, (const void *) in_var, \ - TYPE_##X, interp, finterp, \ - params, flags, tol, maxpix, \ - (const void *) &badval, \ - ndim_out, lbnd_out, ubnd_out, \ - lbnd, ubnd, \ - (void *) out, (void *) out_var, status ); \ -\ -/* Annul the pointer to the simplified/cloned Mapping. */ \ - simple = astAnnul( simple ); \ -\ -/* If an error occurred, clear the returned result. */ \ - if ( !astOK ) result = 0; \ -\ -/* Return the result. */ \ - return result; \ -} - -/* Expand the above macro to generate a function for each required - data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_RESAMPLE(LD,long double) -#endif -MAKE_RESAMPLE(D,double) -MAKE_RESAMPLE(F,float) -MAKE_RESAMPLE(L,long int) -MAKE_RESAMPLE(UL,unsigned long int) -MAKE_RESAMPLE(K,INT_BIG) -MAKE_RESAMPLE(UK,UINT_BIG) -MAKE_RESAMPLE(I,int) -MAKE_RESAMPLE(UI,unsigned int) -MAKE_RESAMPLE(S,short int) -MAKE_RESAMPLE(US,unsigned short int) -MAKE_RESAMPLE(B,signed char) -MAKE_RESAMPLE(UB,unsigned char) - -/* Undefine the macro. */ -#undef MAKE_RESAMPLE - -static int ResampleAdaptively( AstMapping *this, int ndim_in, - const int *lbnd_in, const int *ubnd_in, - const void *in, const void *in_var, - DataType type, int interp, void (* finterp)( void ), - const double *params, int flags, double tol, - int maxpix, const void *badval_ptr, - int ndim_out, const int *lbnd_out, - const int *ubnd_out, const int *lbnd, - const int *ubnd, void *out, void *out_var, int *status ) { -/* -* Name: -* ResampleAdaptively - -* Purpose: -* Resample a section of a data grid adaptively. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int ResampleAdaptively( AstMapping *this, int ndim_in, -* const int *lbnd_in, const int *ubnd_in, -* const void *in, const void *in_var, -* DataType type, int interp, void (* finterp)( void ), -* const double *params, int flags, double tol, -* int maxpix, const void *badval_ptr, -* int ndim_out, const int *lbnd_out, -* const int *ubnd_out, const int *lbnd, -* const int *ubnd, void *out, void *out_var ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function resamples a rectangular grid of data (with any -* number of dimensions) into a specified section of another -* rectangular grid (with a possibly different number of -* dimensions). The coordinate transformation used to convert -* output pixel coordinates into positions in the input grid is -* given by the inverse transformation of the Mapping which is -* supplied. Any pixel interpolation scheme may be specified for -* interpolating between the pixels of the input grid. -* -* This function is very similar to ResampleWithBlocking and -* ResampleSection which lie below it in the calling -* hierarchy. However, this function also attempts to adapt to the -* Mapping supplied and to sub-divide the section being resampled -* into smaller sections within which a linear approximation to the -* Mapping may be used. This reduces the number of Mapping -* evaluations, thereby improving efficiency particularly when -* complicated Mappings are involved. - -* Parameters: -* this -* Pointer to a Mapping, whose inverse transformation may be -* used to transform the coordinates of pixels in the output -* grid into associated positions in the input grid, from which -* the output pixel values should be derived (by interpolation -* if necessary). -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* in -* Pointer to the input array of data to be resampled (with one -* element for each pixel in the input grid). The numerical type -* of these data should match the "type" value (below). The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and data type as the "in" array), -* which represent estimates of the statistical variance -* associated with each element of the "in" array. If this -* second array is given (along with the corresponding "out_var" -* array), then estimates of the variance of the resampled data -* will also be returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* type -* A value taken from the "DataType" enum, which specifies the -* data type of the input and output arrays containing the -* gridded data (and variance) values. -* interp -* A value selected from a set of pre-defined macros to identify -* which sub-pixel interpolation algorithm should be used. -* finterp -* If "interp" is set to a value which requires a user-supplied -* function, then a pointer to that function shoild be given -* here. Otherwise, this value is not used and may be a NULL -* pointer. -* params -* Pointer to an optional array of parameters that may be passed -* to the interpolation algorithm, if required. If no parameters -* are required, a NULL pointer should be supplied. -* flags -* The bitwise OR of a set of flag values which provide -* additional control over the resampling operation. -* tol -* The maximum permitted positional error in transforming output -* pixel positions into the input grid in order to resample -* it. This should be expressed as a displacement in pixels in -* the input grid's coordinate system. If the Mapping's inverse -* transformation can be approximated by piecewise linear -* functions to this accuracy, then such functions may be used -* instead of the Mapping in order to improve -* performance. Otherwise, every output pixel position will be -* transformed individually using the Mapping. -* -* If linear approximation is not required, a "tol" value of -* zero may be given. This will ensure that the Mapping is used -* without any approximation. -* maxpix -* A value which specifies the largest scale size on which to -* search for non-linearities in the Mapping supplied. This -* value should be expressed as a number of pixels in the output -* grid. The function will break the output section specified -* into smaller sub-sections (if necessary), each no larger than -* "maxpix" pixels in any dimension, before it attempts to -* approximate the Mapping by a linear function over each -* sub-section. -* -* If the value given is larger than the largest dimension of -* the output section (the normal recommendation), the function -* will initially search for non-linearity on a scale determined -* by the size of the output section. This is almost always -* satisfactory. Very occasionally, however, a Mapping may -* appear linear on this scale but nevertheless have smaller -* irregularities (e.g. "holes") in it. In such cases, "maxpix" -* may be set to a suitably smaller value so as to ensure this -* non-linearity is not overlooked. Typically, a value of 50 to -* 100 pixels might be suitable and should have little effect on -* performance. -* -* If too small a value is given, however, it will have the -* effect of preventing linear approximation occurring at all -* (equivalent to setting "tol" to zero). Although this may -* degrade performance, accurate results will still be obtained. -* badval_ptr -* If the AST__USEBAD flag is set (above), this parameter is a -* pointer to a value which is used to identify bad data and/or -* variance values in the input array(s). The referenced value's -* data type must match that of the "in" (and "in_var") -* arrays. Unless the AST__NOBAD flag is set, the same value will -* also be used to flag any output array elements for which -* resampled values could not be obtained. The output arrays(s) -* may be flagged with this value whether or not the AST__USEBAD -* flag is set (the function return value indicates whether any -* such values have been produced). -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output data grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output data grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output data grid in the same way as "lbnd_in" -* and "ubnd_in" define the shape and size of the input grid -* (see above). -* lbnd -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the first pixel in the -* section of the output data grid for which a value is -* required. -* ubnd -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the last pixel in the -* section of the output data grid for which a value is -* required. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the output grid for which resampled values are -* required. This section should lie wholly within the extent of -* the output grid (as defined by the "lbnd_out" and "ubnd_out" -* arrays). Regions of the output grid lying outside this section -* will not be modified. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. -* -* If no output variance estimates are required, a NULL pointer -* should be given. - -* Returned Value: -* The number of output grid points for which no valid output value -* could be obtained. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - double *flbnd; /* Array holding floating point lower bounds */ - double *fubnd; /* Array holding floating point upper bounds */ - double *linear_fit; /* Pointer to array of fit coefficients */ - int *hi; /* Pointer to array of section upper bounds */ - int *lo; /* Pointer to array of section lower bounds */ - int coord_out; /* Loop counter for output coordinates */ - int dim; /* Output section dimension size */ - int dimx; /* Dimension with maximum section extent */ - int divide; /* Sub-divide the output section? */ - int i; /* Loop count */ - int isLinear; /* Is the transformation linear? */ - int mxdim; /* Largest output section dimension size */ - int npix; /* Number of pixels in output section */ - int npoint; /* Number of points for obtaining a fit */ - int nvertex; /* Number of vertices of output section */ - int result; /* Result value to return */ - int toobig; /* Section too big (must sub-divide)? */ - int toosmall; /* Section too small to sub-divide? */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialisation. */ - npix = 1; - mxdim = 0; - dimx = 1; - nvertex = 1; - -/* Loop through the output grid dimensions. */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - -/* Obtain the extent in each dimension of the output section which is - to receive resampled values, and calculate the total number of - pixels it contains. */ - dim = ubnd[ coord_out ] - lbnd[ coord_out ] + 1; - npix *= dim; - -/* Find the maximum dimension size of this output section and note - which dimension has this size. */ - if ( dim > mxdim ) { - mxdim = dim; - dimx = coord_out; - } - -/* Calculate how many vertices the output section has. */ - nvertex *= 2; - } - -/* Calculate how many sample points will be needed (by the - astLinearApprox function) to obtain a linear fit to the Mapping's - inverse transformation. */ - npoint = 1 + 4 * ndim_out + 2 * nvertex; - -/* If the number of pixels in the output section is not at least 4 - times this number, we will probably not save significant time by - attempting to obtain a linear fit, so note that the output section - is too small. */ - toosmall = ( npix < ( 4 * npoint ) ); - -/* Note if the maximum dimension of the output section exceeds the - user-supplied scale factor. */ - toobig = ( maxpix < mxdim ); - -/* Assume the Mapping is significantly non-linear before deciding - whether to sub-divide the output section. */ - linear_fit = NULL; - -/* If the output section is too small to be worth obtaining a linear - fit, or if the accuracy tolerance is zero, we will not - sub-divide. This means that the Mapping will be used to transform - each pixel's coordinates and no linear approximation will be - used. */ - if ( toosmall || ( tol == 0.0 ) ) { - divide = 0; - -/* Otherwise, if the largest output section dimension exceeds the - scale length given, we will sub-divide. This offers the possibility - of obtaining a linear approximation to the Mapping over a reduced - range of output coordinates (which will be handled by a recursive - invocation of this function). */ - } else if ( toobig ) { - divide = 1; - -/* If neither of the above apply, then attempt to fit a linear - approximation to the Mapping's inverse transformation over the - range of coordinates covered by the output section. We need to - temporarily copy the integer bounds into floating point arrays to - use astLinearApprox. */ - } else { - -/* Allocate memory for floating point bounds and for the coefficient array */ - flbnd = astMalloc( sizeof( double )*(size_t) ndim_out ); - fubnd = astMalloc( sizeof( double )*(size_t) ndim_out ); - linear_fit = astMalloc( sizeof( double )* - (size_t) ( ndim_in*( ndim_out + 1 ) ) ); - if( astOK ) { - -/* Copy the bounds into these arrays, and change them so that they refer - to the lower and upper edges of the cell rather than the centre. This - is essential if one of the axes is spanned by a single cell, since - otherwise the upper and lower bounds would be identical. */ - for( i = 0; i < ndim_out; i++ ) { - flbnd[ i ] = (double) lbnd[ i ] - 0.5; - fubnd[ i ] = (double) ubnd[ i ] + 0.5; - } - -/* Get the linear approximation to the inverse transformation. The - astLinearApprox function fits the forward transformation so temporarily - invert the Mapping in order to get a fit to the inverse transformation. */ - astInvert( this ); - isLinear = astLinearApprox( this, flbnd, fubnd, tol, linear_fit ); - astInvert( this ); - -/* Free the coeff array if the inverse transformation is not linear. */ - if( !isLinear ) linear_fit = astFree( linear_fit ); - - } else { - linear_fit = astFree( linear_fit ); - } - -/* Free resources */ - flbnd = astFree( flbnd ); - fubnd = astFree( fubnd ); - -/* If a linear fit was obtained, we will use it and therefore do not - wish to sub-divide further. Otherwise, we sub-divide in the hope - that this may result in a linear fit next time. */ - divide = !linear_fit; - } - -/* If no sub-division is required, perform resampling (in a - memory-efficient manner, since the section we are resampling might - still be very large). This will use the linear fit, if obtained - above. */ - if ( astOK ) { - if ( !divide ) { - result = ResampleWithBlocking( this, linear_fit, - ndim_in, lbnd_in, ubnd_in, - in, in_var, type, interp, finterp, - params, flags, badval_ptr, - ndim_out, lbnd_out, ubnd_out, - lbnd, ubnd, out, out_var, status ); - -/* Otherwise, allocate workspace to perform the sub-division. */ - } else { - lo = astMalloc( sizeof( int ) * (size_t) ndim_out ); - hi = astMalloc( sizeof( int ) * (size_t) ndim_out ); - if ( astOK ) { - -/* Initialise the bounds of a new output section to match the original - output section. */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - lo[ coord_out ] = lbnd[ coord_out ]; - hi[ coord_out ] = ubnd[ coord_out ]; - } - -/* Replace the upper bound of the section's largest dimension with the - mid-point of the section along this dimension, rounded - downwards. */ - hi[ dimx ] = - (int) floor( 0.5 * (double) ( lbnd[ dimx ] + ubnd[ dimx ] ) ); - -/* Resample the resulting smaller section using a recursive invocation - of this function. */ - result = ResampleAdaptively( this, ndim_in, lbnd_in, ubnd_in, - in, in_var, type, interp, finterp, - params, flags, tol, maxpix, - badval_ptr, ndim_out, - lbnd_out, ubnd_out, - lo, hi, out, out_var, status ); - -/* Now set up a second section which covers the remaining half of the - original output section. */ - lo[ dimx ] = hi[ dimx ] + 1; - hi[ dimx ] = ubnd[ dimx ]; - -/* If this section contains pixels, resample it in the same way, - summing the returned values. */ - if ( lo[ dimx ] <= hi[ dimx ] ) { - result += ResampleAdaptively( this, ndim_in, lbnd_in, ubnd_in, - in, in_var, type, interp, finterp, - params, flags, tol, maxpix, - badval_ptr, ndim_out, - lbnd_out, ubnd_out, - lo, hi, out, out_var, status ); - } - } - -/* Free the workspace. */ - lo = astFree( lo ); - hi = astFree( hi ); - } - } - -/* If coefficients for a linear fit were obtained, then free the space - they occupy. */ - if ( linear_fit ) linear_fit = astFree( linear_fit ); - -/* If an error occurred, clear the returned result. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static int ResampleSection( AstMapping *this, const double *linear_fit, - int ndim_in, - const int *lbnd_in, const int *ubnd_in, - const void *in, const void *in_var, - DataType type, int interp, void (* finterp)( void ), - const double *params, double factor, int flags, - const void *badval_ptr, int ndim_out, - const int *lbnd_out, const int *ubnd_out, - const int *lbnd, const int *ubnd, - void *out, void *out_var, int *status ) { -/* -* Name: -* ResampleSection - -* Purpose: -* Resample a section of a data grid. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int ResampleSection( AstMapping *this, const double *linear_fit, -* int ndim_in, const int *lbnd_in, const int *ubnd_in, -* const void *in, const void *in_var, -* DataType type, int interp, void (* finterp)( void ), -* const double *params, double factor, int flags, -* const void *badval_ptr, int ndim_out, -* const int *lbnd_out, const int *ubnd_out, -* const int *lbnd, const int *ubnd, -* void *out, void *out_var ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function resamples a rectangular grid of data (with any -* number of dimensions) into a specified section of another -* rectangular grid (with a possibly different number of -* dimensions). The coordinate transformation used is given by the -* inverse transformation of the Mapping which is supplied or, -* alternatively, by a linear approximation fitted to a Mapping's -* inverse transformation. Any pixel interpolation scheme may be -* specified for interpolating between the pixels of the input -* grid. - -* Parameters: -* this -* Pointer to a Mapping, whose inverse transformation may be -* used to transform the coordinates of pixels in the output -* grid into associated positions in the input grid, from which -* the output pixel values should be derived (by interpolation -* if necessary). -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* linear_fit -* Pointer to an optional array of double which contains the -* coefficients of a linear fit which approximates the above -* Mapping's inverse coordinate transformation. If this is -* supplied, it will be used in preference to the above Mapping -* when transforming coordinates. This may be used to enhance -* performance in cases where evaluation of the Mapping's -* inverse transformation is expensive. If no linear fit is -* available, a NULL pointer should be supplied. -* -* The way in which the fit coefficients are stored in this -* array and the number of array elements are as defined by the -* astLinearApprox function. -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* in -* Pointer to the input array of data to be resampled (with one -* element for each pixel in the input grid). The numerical type -* of these data should match the "type" value (below). The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and data type as the "in" array), -* which represent estimates of the statistical variance -* associated with each element of the "in" array. If this -* second array is given (along with the corresponding "out_var" -* array), then estimates of the variance of the resampled data -* will also be returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* type -* A value taken from the "DataType" enum, which specifies the -* data type of the input and output arrays containing the -* gridded data (and variance) values. -* interp -* A value selected from a set of pre-defined macros to identify -* which sub-pixel interpolation algorithm should be used. -* finterp -* If "interp" is set to a value which requires a user-supplied -* function, then a pointer to that function shoild be given -* here. Otherwise, this value is not used and may be a NULL -* pointer. -* params -* Pointer to an optional array of parameters that may be passed -* to the interpolation algorithm, if required. If no parameters -* are required, a NULL pointer should be supplied. -* factor -* A factor by which to scale the resampled output data values before -* returning them. If flux is being conserved this should be set to -* the ratio of the output pixel size to the input pixel size in the -* section. Otherwise it should be set to 1.0. -* flags -* The bitwise OR of a set of flag values which provide -* additional control over the resampling operation. -* badval_ptr -* If the AST__USEBAD flag is set (above), this parameter is a -* pointer to a value which is used to identify bad data and/or -* variance values in the input array(s). The referenced value's -* data type must match that of the "in" (and "in_var") -* arrays. Unless the AST__NOBAD flag is set, the same value will -* also be used to flag any output array elements for which -* resampled values could not be obtained. The output arrays(s) -* may be flagged with this value whether or not the AST__USEBAD -* flag is set (the function return value indicates whether any -* such values have been produced). -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output data grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output data grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output data grid in the same way as "lbnd_in" -* and "ubnd_in" define the shape and size of the input grid -* (see above). -* lbnd -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the first pixel in the -* section of the output data grid for which a value is -* required. -* ubnd -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the last pixel in the -* section of the output data grid for which a value is -* required. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the output grid for which resampled values are -* required. This section should lie wholly within the extent of -* the output grid (as defined by the "lbnd_out" and "ubnd_out" -* arrays). Regions of the output grid lying outside this section -* will not be modified. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. -* -* If no output variance estimates are required, a NULL pointer -* should be given. - -* Returned Value: -* The number of output grid points for which no valid output value -* could be obtained. - -* Notes: -* - This function does not take steps to limit memory usage if the -* grids supplied are large. To resample large grids in a more -* memory-efficient way, the ResampleWithBlocking function should -* be used. -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific data */ - AstPointSet *pset_in; /* Input PointSet for transformation */ - AstPointSet *pset_out; /* Output PointSet for transformation */ - const double *grad; /* Pointer to gradient matrix of linear fit */ - const double *par; /* Pointer to parameter array */ - const double *zero; /* Pointer to zero point array of fit */ - double **ptr_in; /* Pointer to input PointSet coordinates */ - double **ptr_out; /* Pointer to output PointSet coordinates */ - double *accum; /* Pointer to array of accumulated sums */ - double fwhm; /* Full width half max. of gaussian */ - double lpar[ 1 ]; /* Local parameter array */ - double x1; /* Interim x coordinate value */ - double y1; /* Interim y coordinate value */ - int *dim; /* Pointer to array of output pixel indices */ - int *offset; /* Pointer to array of output pixel offsets */ - int *stride; /* Pointer to array of output grid strides */ - int conserve; /* Conserve flux? */ - int coord_in; /* Loop counter for input dimensions */ - int coord_out; /* Loop counter for output dimensions */ - int done; /* All pixel indices done? */ - int i1; /* Interim offset into "accum" array */ - int i2; /* Final offset into "accum" array */ - int idim; /* Loop counter for dimensions */ - int ix; /* Loop counter for output x coordinate */ - int iy; /* Loop counter for output y coordinate */ - int nbad; /* Number of pixels assigned a bad value */ - int neighb; /* Number of neighbouring pixels */ - int npoint; /* Number of output points (pixels) */ - int off1; /* Interim pixel offset into output array */ - int off; /* Final pixel offset into output array */ - int point; /* Counter for output points (pixels ) */ - int result; /* Result value to be returned */ - int s; /* Temporary variable for strides */ - int usevar; /* Process variance array? */ - void (* gifunc)( void ); /* General interpolation function */ - void (* kernel)( double, const double [], int, double *, int * ); /* Kernel fn. */ - void (* fkernel)( double, const double [], int, double * ); /* User kernel fn. */ - -/* Initialise. */ - result = 0; - -/* Get a pointer to a structure holding thread-specific global data values */ - astGET_GLOBALS(this); - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialisation. */ - pset_in = NULL; - ptr_in = NULL; - neighb = 0; - gifunc = NULL; - kernel = NULL; - fkernel = NULL; - -/* See if we are conserving flux */ - conserve = flags & AST__CONSERVEFLUX; - -/* If we are conserving flux, then we need some way to tell which output - array elements have been assigned a value and which have not. If the - AST__NOBAD flag has been specified then this is not possible to report - an error. */ - if( ( flags & AST__NOBAD ) && conserve ) { - astError( AST__BADFLG, "astResample: Cannot use the AST__NOBAD and " - "AST__CONSERVEFLUX flags together (programming error)." , status); - } - -/* Calculate the number of output points, as given by the product of - the output grid dimensions. */ - for ( npoint = 1, coord_out = 0; coord_out < ndim_out; coord_out++ ) { - npoint *= ubnd[ coord_out ] - lbnd[ coord_out ] + 1; - } - -/* Allocate workspace. */ - offset = astMalloc( sizeof( int ) * (size_t) npoint ); - stride = astMalloc( sizeof( int ) * (size_t) ndim_out ); - if ( astOK ) { - -/* Calculate the stride for each output grid dimension. */ - off = 0; - s = 1; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - stride[ coord_out ] = s; - s *= ubnd_out[ coord_out ] - lbnd_out[ coord_out ] + 1; - } - -/* A linear fit to the Mapping is available. */ -/* ========================================= */ - if ( linear_fit ) { - -/* If a linear fit to the Mapping has been provided, then obtain - pointers to the array of gradients and zero-points comprising the - fit. */ - grad = linear_fit + ndim_in; - zero = linear_fit; - -/* Create a PointSet to hold the input grid coordinates and obtain an - array of pointers to its coordinate data. */ - pset_in = astPointSet( npoint, ndim_in, "", status ); - ptr_in = astGetPoints( pset_in ); - if ( astOK ) { - -/* Initialise the count of output points. */ - point = 0; - -/* Handle the 1-dimensional case optimally. */ -/* ---------------------------------------- */ - if ( ( ndim_in == 1 ) && ( ndim_out == 1 ) ) { - -/* Loop through the pixels of the output grid and transform their x - coordinates into the input grid's coordinate system using the - linear fit supplied. Store the results in the PointSet created - above. */ - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_in[ 0 ][ point ] = zero[ 0 ] + grad[ 0 ] * (double) ix; - -/* Calculate the offset of each pixel within the output array. */ - offset[ point ] = ix - lbnd_out[ 0 ]; - point++; - } - -/* Handle the 2-dimensional case optimally. */ -/* ---------------------------------------- */ - } else if ( ( ndim_in == 2 ) && ( ndim_out == 2 ) ) { - -/* Loop through the range of y coordinates in the output grid and - calculate interim values of the input coordinates using the linear - fit supplied. */ - for ( iy = lbnd[ 1 ]; iy <= ubnd[ 1 ]; iy++ ) { - x1 = zero[ 0 ] + grad[ 1 ] * (double) iy; - y1 = zero[ 1 ] + grad[ 3 ] * (double) iy; - -/* Also calculate an interim pixel offset into the output array. */ - off1 = stride[ 1 ] * ( iy - lbnd_out[ 1 ] ) - lbnd_out[ 0 ]; - -/* Now loop through the range of output x coordinates and calculate - the final values of the input coordinates, storing the results in - the PointSet created above. */ - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_in[ 0 ][ point ] = x1 + grad[ 0 ] * (double) ix; - ptr_in[ 1 ][ point ] = y1 + grad[ 2 ] * (double) ix; - -/* Also calculate final pixel offsets into the output array. */ - offset[ point ] = off1 + ix; - point++; - } - } - -/* Handle other numbers of dimensions. */ -/* ----------------------------------- */ - } else { - -/* Allocate workspace. */ - accum = astMalloc( sizeof( double ) * - (size_t) ( ndim_in * ndim_out ) ); - dim = astMalloc( sizeof( int ) * (size_t) ndim_out ); - if ( astOK ) { - -/* Initialise an array of pixel indices for the output grid which - refer to the first pixel for which we require a value. Also - calculate the offset of this pixel within the output array. */ - off = 0; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - dim[ coord_out ] = lbnd[ coord_out ]; - off += stride[ coord_out ] * - ( dim[ coord_out ] - lbnd_out[ coord_out ] ); - } - -/* To calculate each input grid coordinate we must perform a matrix - multiply on the output grid coordinates (using the gradient matrix) - and then add the zero points. However, since we will usually only - be altering one output coordinate at a time (the least - significant), we can avoid the full matrix multiply by accumulating - partial sums for the most significant output coordinates and only - altering those sums which need to change each time. The zero points - never change, so we first fill the "most significant" end of the - "accum" array with these. */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - accum[ ( coord_in + 1 ) * ndim_out - 1 ] = - zero[ coord_in ]; - } - coord_out = ndim_out - 1; - -/* Now loop to process each output pixel. */ - for ( done = 0; !done; point++ ) { - -/* To generate the input coordinate that corresponds to the current - output pixel, we work down from the most significant dimension - whose index has changed since the previous pixel we considered - (given by "coord_out"). For each affected dimension, we accumulate - in "accum" the matrix sum (including the zero point) for that - dimension and all higher output dimensions. We must accumulate a - separate set of sums for each input coordinate we wish to - produce. (Note that for the first pixel we process, all dimensions - are considered "changed", so we start by initialising the whole - "accum" array.) */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - i1 = coord_in * ndim_out; - for ( idim = coord_out; idim >= 1; idim-- ) { - i2 = i1 + idim; - accum[ i2 - 1 ] = accum[ i2 ] + - dim[ idim ] * grad[ i2 ]; - } - -/* The input coordinate for each dimension is given by the accumulated - sum for output dimension zero (giving the sum over all output - dimensions). We do not store this in the "accum" array, but assign - the result directly to the coordinate array of the PointSet created - earlier. */ - ptr_in[ coord_in ][ point ] = accum[ i1 ] + - dim[ 0 ] * grad[ i1 ]; - } - -/* Store the offset of the current pixel in the output array. */ - offset[ point ] = off; - -/* Now update the array of pixel indices to refer to the next output - pixel. */ - coord_out = 0; - do { - -/* The least significant index which currently has less than its - maximum value is incremented by one. The offset into the output - array is updated accordingly. */ - if ( dim[ coord_out ] < ubnd[ coord_out ] ) { - dim[ coord_out ]++; - off += stride[ coord_out ]; - break; - -/* Any less significant indices which have reached their maximum value - are returned to their minimum value and the output pixel offset is - decremented appropriately. */ - } else { - dim[ coord_out ] = lbnd[ coord_out ]; - off -= stride[ coord_out ] * - ( ubnd[ coord_out ] - lbnd[ coord_out ] ); - -/* All the output pixels have been processed once the most significant - pixel index has been returned to its minimum value. */ - done = ( ++coord_out == ndim_out ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - accum = astFree( accum ); - dim = astFree( dim ); - } - } - -/* No linear fit to the Mapping is available. */ -/* ========================================== */ - } else { - -/* If flux conseravtion was requested, report an error, since we can only - conserve flux if a linear approximation is available. */ - if( conserve && astOK ) { - astError( AST__CNFLX, "astResampleSection(%s): Flux conservation " - "was requested but cannot be performed because either the Mapping " - "is too non-linear, or the requested tolerance is too small.", status, - astGetClass( this ) ); - } - -/* Create a PointSet to hold the coordinates of the output pixels and - obtain a pointer to its coordinate data. */ - pset_out = astPointSet( npoint, ndim_out, "", status ); - ptr_out = astGetPoints( pset_out ); - if ( astOK ) { - -/* Initialise the count of output points. */ - point = 0; - -/* Handle the 1-dimensional case optimally. */ -/* ---------------------------------------- */ - if ( ndim_out == 1 && ndim_in == 1 ) { - -/* Loop through the required range of output x coordinates, assigning - the coordinate values to the PointSet created above. Also store a - pixel offset into the output array. */ - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_out[ 0 ][ point ] = (double) ix; - offset[ point ] = ix - lbnd_out[ 0 ]; - -/* Increment the count of output pixels. */ - point++; - } - -/* Handle the 2-dimensional case optimally. */ -/* ---------------------------------------- */ - } else if ( ndim_out == 2 && ndim_in == 2 ) { - -/* Loop through the required range of output y coordinates, - calculating an interim pixel offset into the output array. */ - for ( iy = lbnd[ 1 ]; iy <= ubnd[ 1 ]; iy++ ) { - off1 = stride[ 1 ] * ( iy - lbnd_out[ 1 ] ) - lbnd_out[ 0 ]; - -/* Loop through the required range of output x coordinates, assigning - the coordinate values to the PointSet created above. Also store a - final pixel offset into the output array. */ - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_out[ 0 ][ point ] = (double) ix; - ptr_out[ 1 ][ point ] = (double) iy; - offset[ point ] = off1 + ix; - -/* Increment the count of output pixels. */ - point++; - } - } - -/* Handle other numbers of dimensions. */ -/* ----------------------------------- */ - } else { - -/* Allocate workspace. */ - dim = astMalloc( sizeof( int ) * (size_t) ndim_out ); - if ( astOK ) { - -/* Initialise an array of pixel indices for the output grid which - refer to the first pixel for which we require a value. Also - calculate the offset of this pixel within the output array. */ - off = 0; - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - dim[ coord_out ] = lbnd[ coord_out ]; - off += stride[ coord_out ] * - ( dim[ coord_out ] - lbnd_out[ coord_out ] ); - } - -/* Loop to generate the coordinates of each output pixel. */ - for ( done = 0; !done; point++ ) { - -/* Copy each pixel's coordinates into the PointSet created above. */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - ptr_out[ coord_out ][ point ] = - (double) dim[ coord_out ]; - } - -/* Store the offset of the pixel in the output array. */ - offset[ point ] = off; - -/* Now update the array of pixel indices to refer to the next output - pixel. */ - coord_out = 0; - do { - -/* The least significant index which currently has less than its - maximum value is incremented by one. The offset into the output - array is updated accordingly. */ - if ( dim[ coord_out ] < ubnd[ coord_out ] ) { - dim[ coord_out ]++; - off += stride[ coord_out ]; - break; - -/* Any less significant indices which have reached their maximum value - are returned to their minimum value and the output pixel offset is - decremented appropriately. */ - } else { - dim[ coord_out ] = lbnd[ coord_out ]; - off -= stride[ coord_out ] * - ( ubnd[ coord_out ] - lbnd[ coord_out ] ); - -/* All the output pixels have been processed once the most significant - pixel index has been returned to its minimum value. */ - done = ( ++coord_out == ndim_out ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - dim = astFree( dim ); - } - -/* When all the output pixel coordinates have been generated, use the - Mapping's inverse transformation to generate the input coordinates - from them. Obtain an array of pointers to the resulting coordinate - data. */ - pset_in = astTransform( this, pset_out, 0, NULL ); - ptr_in = astGetPoints( pset_in ); - } - -/* Annul the PointSet containing the output coordinates. */ - pset_out = astAnnul( pset_out ); - } - } - -/* Resample the input grid. */ -/* ------------------------ */ -/* Determine if a variance array is to be processed. */ - usevar = ( in_var && out_var ); - -/* If the input coordinates have been produced successfully, identify - the input grid resampling method to be used. */ - if ( astOK ) { - -/* Nearest pixel. */ -/* -------------- */ - switch ( interp ) { - case AST__NEAREST: - -/* Define a macro to use a "case" statement to invoke the - nearest-pixel interpolation function appropriate to a given data - type. */ -#define CASE_NEAREST(X,Xtype) \ - case ( TYPE_##X ): \ - result = \ - InterpolateNearest##X( ndim_in, lbnd_in, ubnd_in, \ - (Xtype *) in, (Xtype *) in_var, \ - npoint, offset, \ - (const double *const *) ptr_in, \ - flags, *( (Xtype *) badval_ptr ), \ - (Xtype *) out, (Xtype *) out_var, status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_NEAREST(LD,long double) -#endif - CASE_NEAREST(D,double) - CASE_NEAREST(F,float) - CASE_NEAREST(L,long int) - CASE_NEAREST(UL,unsigned long int) - CASE_NEAREST(K,INT_BIG) - CASE_NEAREST(UK,UINT_BIG) - CASE_NEAREST(I,int) - CASE_NEAREST(UI,unsigned int) - CASE_NEAREST(S,short int) - CASE_NEAREST(US,unsigned short int) - CASE_NEAREST(B,signed char) - CASE_NEAREST(UB,unsigned char) - } - break; - -/* Undefine the macro. */ -#undef CASE_NEAREST - -/* Linear interpolation. */ -/* --------------------- */ -/* Note this is also the default if zero is given. */ - case AST__LINEAR: - case 0: - -/* Define a macro to use a "case" statement to invoke the linear - interpolation function appropriate to a given data type. */ -#define CASE_LINEAR(X,Xtype) \ - case ( TYPE_##X ): \ - result = \ - InterpolateLinear##X( ndim_in, lbnd_in, ubnd_in,\ - (Xtype *) in, (Xtype *) in_var, \ - npoint, offset, \ - (const double *const *) ptr_in, \ - flags, *( (Xtype *) badval_ptr ), \ - (Xtype *) out, (Xtype *) out_var, status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_LINEAR(LD,long double) -#endif - CASE_LINEAR(D,double) - CASE_LINEAR(F,float) - CASE_LINEAR(L,long int) - CASE_LINEAR(UL,unsigned long int) - CASE_LINEAR(K,INT_BIG) - CASE_LINEAR(UK,UINT_BIG) - CASE_LINEAR(I,int) - CASE_LINEAR(UI,unsigned int) - CASE_LINEAR(S,short int) - CASE_LINEAR(US,unsigned short int) - CASE_LINEAR(B,signed char) - CASE_LINEAR(UB,unsigned char) - } - break; - -/* Undefine the macro. */ -#undef CASE_LINEAR - -/* Interpolation using a 1-d kernel. */ -/* --------------------------------- */ - case AST__GAUSS: - case AST__SINC: - case AST__SINCCOS: - case AST__SINCGAUSS: - case AST__SINCSINC: - case AST__SOMB: - case AST__SOMBCOS: - case AST__UKERN1: /* User-supplied 1-d kernel function */ - -/* Obtain a pointer to the appropriate 1-d kernel function (either - internal or user-defined) and set up any parameters it may - require. */ - par = NULL; - switch ( interp ) { - -/* sinc(pi*x) interpolation. */ -/* ------------------------- */ -/* Assign the kernel function. */ - case AST__SINC: - kernel = Sinc; - -/* Calculate the number of neighbouring pixels to use. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) { - neighb = 2; - } else { - neighb = MaxI( 1, neighb, status ); - } - break; - -/* sinc(pi*x)*cos(k*pi*x) interpolation. */ -/* ------------------------------------- */ -/* Assign the kernel function. */ - case AST__SINCCOS: - kernel = SincCos; - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 0.5 / MaxD( 1.0, params[ 1 ], status ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, the number will be calculated automatically below. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = INT_MAX; - -/* Calculate the maximum number of neighbouring pixels required by the - width of the kernel, and use this value if preferable. */ - neighb = MinI( neighb, - (int) ceil( MaxD( 1.0, params[ 1 ], status ) ), status ); - break; - -/* somb(pi*x) interpolation. */ -/* ------------------------- */ -/* Assign the kernel function. */ - case AST__SOMB: - kernel = Somb; - -/* Calculate the number of neighbouring pixels to use. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) { - neighb = 2; - } else { - neighb = MaxI( 1, neighb, status ); - } - break; - -/* somb(pi*x)*cos(k*pi*x) interpolation. */ -/* ------------------------------------- */ -/* Assign the kernel function. */ - case AST__SOMBCOS: - kernel = SombCos; - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 0.5 / MaxD( 1.0, params[ 1 ], status ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, the number will be calculated automatically below. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = INT_MAX; - -/* Calculate the maximum number of neighbouring pixels required by the - width of the kernel, and use this value if preferable. */ - neighb = MinI( neighb, - (int) ceil( MaxD( 1.0, params[ 1 ], status ) ), status ); - break; - -/* sinc(pi*x)*exp(-k*x*x) interpolation. */ -/* ------------------------------------- */ -/* Assign the kernel function. */ - case AST__SINCGAUSS: - kernel = SincGauss; - -/* Constrain the full width half maximum of the gaussian factor. */ - fwhm = MaxD( 0.1, params[ 1 ], status ); - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 4.0 * log( 2.0 ) / ( fwhm * fwhm ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, use the number of neighbouring pixels required by the width - of the kernel (out to where the gaussian term falls to 1% of its - peak value). */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = (int) ceil( sqrt( -log( 0.01 ) / - lpar[ 0 ] ) ); - break; - -/* exp(-k*x*x) interpolation. */ -/* -------------------------- */ -/* Assign the kernel function. */ - case AST__GAUSS: - kernel = Gauss; - -/* Constrain the full width half maximum of the gaussian. */ - fwhm = MaxD( 0.1, params[ 1 ], status ); - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 4.0 * log( 2.0 ) / ( fwhm * fwhm ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, use the number of neighbouring pixels required by the width - of the kernel (out to where the gaussian term falls to 1% of its - peak value). */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = (int) ceil( sqrt( -log( 0.01 ) / - lpar[ 0 ] ) ); - break; - -/* sinc(pi*x)*sinc(k*pi*x) interpolation. */ -/* -------------------------------------- */ -/* Assign the kernel function. */ - case AST__SINCSINC: - kernel = SincSinc; - -/* Store the required value of "k" in a local parameter array and pass - this array to the kernel function. */ - lpar[ 0 ] = 0.5 / MaxD( 1.0, params[ 1 ], status ); - par = lpar; - -/* Obtain the number of neighbouring pixels to use. If this is zero or - less, the number will be calculated automatically below. */ - neighb = (int) floor( params[ 0 ] + 0.5 ); - if ( neighb <= 0 ) neighb = INT_MAX; - -/* Calculate the maximum number of neighbouring pixels required by the - width of the kernel, and use this value if preferable. */ - neighb = MinI( neighb, - (int) ceil( MaxD( 1.0, params[ 1 ], status ) ), status ); - break; - -/* User-supplied kernel. */ -/* --------------------- */ -/* Assign the kernel function. */ - case AST__UKERN1: - fkernel = (void (*)( double, const double [], - int, double * )) finterp; - -/* Calculate the number of neighbouring pixels to use. */ - neighb = MaxI( 1, (int) floor( params[ 0 ] + 0.5 ), status ); - -/* Pass a pointer to the "params" array. */ - par = params; - break; - } - -/* Define a macro to use a "case" statement to invoke the 1-d kernel - interpolation function appropriate to a given data type, passing it - the pointer to the kernel function obtained above. */ -#define CASE_KERNEL1(X,Xtype) \ - case ( TYPE_##X ): \ - result = \ - InterpolateKernel1##X( this, ndim_in, lbnd_in, ubnd_in, \ - (Xtype *) in, (Xtype *) in_var, \ - npoint, offset, \ - (const double *const *) ptr_in, \ - kernel, fkernel, neighb, par, flags, \ - *( (Xtype *) badval_ptr ), \ - (Xtype *) out, (Xtype *) out_var, status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_KERNEL1(LD,long double) -#endif - CASE_KERNEL1(D,double) - CASE_KERNEL1(F,float) - CASE_KERNEL1(L,long int) - CASE_KERNEL1(UL,unsigned long int) - CASE_KERNEL1(K,INT_BIG) - CASE_KERNEL1(UK,UINT_BIG) - CASE_KERNEL1(I,int) - CASE_KERNEL1(UI,unsigned int) - CASE_KERNEL1(S,short int) - CASE_KERNEL1(US,unsigned short int) - CASE_KERNEL1(B,signed char) - CASE_KERNEL1(UB,unsigned char) - } - break; - -/* Undefine the macro. */ -#undef CASE_KERNEL1 - -/* General sub-pixel interpolation function. */ -/* ----------------------------------------- */ - case AST__BLOCKAVE: - case AST__UINTERP: - -/* Define a macro to use a "case" statement to invoke the general - sub-pixel interpolation function appropriate to a given type and - the selected value of the interp variable. */ -#define CASE_GINTERP(X,Xtype) \ - case ( TYPE_##X ): \ -\ -/* Obtain a pointer to the appropriate general interpolation function \ - (either internal or user-defined) and set up any parameters it may \ - require. */ \ - switch ( interp ) { \ -\ -/* Block averaging interpolation. */ \ -/* ------------------------------ */ \ - case AST__BLOCKAVE: \ - gifunc = (void (*)( void )) InterpolateBlockAverage##X; \ - break; \ -\ -/* User-supplied sub-pixel interpolation function. */ \ -/* ----------------------------------------------- */ \ - case AST__UINTERP: \ - gifunc = (void (*)( void )) finterp; \ - break; \ - } \ -\ -/* Invoke the general interpolation function. It has to be cast to the \ - right type (i.e. a function with the correctly typed arguments) \ - to prevent default promotion (to int or double) of its arguments. \ - The cast here corresponds to the declaration of - ast_resample_uinterp##Xtype. */ \ - ( *( (void (*)( int, const int[], const int[], \ - const Xtype[], \ - const Xtype[], \ - int, const int[], \ - const double *const[], \ - const double[], int, \ - Xtype, \ - Xtype *, \ - Xtype *, \ - int * )) \ - gifunc ) )( ndim_in, lbnd_in, ubnd_in, \ - (Xtype *) in, \ - (Xtype *) ( usevar ? in_var : NULL ), \ - npoint, offset, \ - (const double *const *) ptr_in, \ - params, flags, \ - *( (Xtype *) badval_ptr ), \ - (Xtype *) out, \ - (Xtype *) ( usevar ? out_var : NULL ), \ - &nbad ); \ - if ( astOK ) { \ - result += nbad; \ - } else { \ - astError( astStatus, "astResample"#X"(%s): Error " \ - "signalled by user-supplied sub-pixel " \ - "interpolation function.", status, \ - astGetClass( unsimplified_mapping ) ); \ - } \ - break; - -/* Use the above macro to invoke the function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_GINTERP(LD,long double) -#endif - CASE_GINTERP(D,double) - CASE_GINTERP(F,float) - CASE_GINTERP(L,long int) - CASE_GINTERP(UL,unsigned long int) - CASE_GINTERP(K,INT_BIG) - CASE_GINTERP(UK,UINT_BIG) - CASE_GINTERP(I,int) - CASE_GINTERP(UI,unsigned int) - CASE_GINTERP(S,short int) - CASE_GINTERP(US,unsigned short int) - CASE_GINTERP(B,signed char) - CASE_GINTERP(UB,unsigned char) - } - break; - -/* Undefine the macro. */ -#undef CASE_GINTERP - -/* Error: invalid interpolation scheme specified. */ -/* ---------------------------------------------- */ - default: - -/* Define a macro to report an error message appropriate to a given - data type. */ -#define CASE_ERROR(X) \ - case TYPE_##X: \ - astError( AST__SISIN, "astResample"#X"(%s): Invalid " \ - "sub-pixel interpolation scheme (%d) specified.", status, \ - astGetClass( unsimplified_mapping ), interp ); \ - break; - -/* Use the above macro to report an appropriate error message. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_ERROR(LD) -#endif - CASE_ERROR(D) - CASE_ERROR(F) - CASE_ERROR(L) - CASE_ERROR(UL) - CASE_ERROR(K) - CASE_ERROR(UK) - CASE_ERROR(I) - CASE_ERROR(UI) - CASE_ERROR(S) - CASE_ERROR(US) - CASE_ERROR(B) - CASE_ERROR(UB) - } - break; - -/* Undefine the macro. */ -#undef CASE_ERROR - } - } - -/* Now scale the output values to conserve flux if required. */ - if( conserve ) { - -/* Define a macro to use a "case" statement to invoke the function - appropriate to a given data type. These simply multiple the output data - value by the factor, and the output variance by the square of the - factor. */ -#define CASE_CONSERVE(X,Xtype) \ - case ( TYPE_##X ): \ - ConserveFlux##X( factor, npoint, offset, *( (Xtype *) badval_ptr ), \ - (Xtype *) out, \ - (Xtype *) ( usevar ? out_var : NULL ), status ); \ - break; - -/* Use the above macro to invoke the appropriate function. */ - switch ( type ) { -#if HAVE_LONG_DOUBLE /* Not normally implemented */ - CASE_CONSERVE(LD,long double) -#endif - CASE_CONSERVE(D,double) - CASE_CONSERVE(F,float) - CASE_CONSERVE(L,long int) - CASE_CONSERVE(UL,unsigned long int) - CASE_CONSERVE(K,INT_BIG) - CASE_CONSERVE(UK,UINT_BIG) - CASE_CONSERVE(I,int) - CASE_CONSERVE(UI,unsigned int) - CASE_CONSERVE(S,short int) - CASE_CONSERVE(US,unsigned short int) - CASE_CONSERVE(B,signed char) - CASE_CONSERVE(UB,unsigned char) - } - -/* Undefine the macro. */ -#undef CASE_CONSERVE - } - -/* Annul the PointSet used to hold input coordinates. */ - pset_in = astAnnul( pset_in ); - -/* Free the workspace. */ - offset = astFree( offset ); - stride = astFree( stride ); - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static int ResampleWithBlocking( AstMapping *this, const double *linear_fit, - int ndim_in, - const int *lbnd_in, const int *ubnd_in, - const void *in, const void *in_var, - DataType type, int interp, void (* finterp)( void ), - const double *params, int flags, - const void *badval_ptr, int ndim_out, - const int *lbnd_out, const int *ubnd_out, - const int *lbnd, const int *ubnd, - void *out, void *out_var, int *status ) { -/* -* Name: -* ResampleWithBlocking - -* Purpose: -* Resample a section of a data grid in a memory-efficient way. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int ResampleWithBlocking( AstMapping *this, const double *linear_fit, -* int ndim_in, -* const int *lbnd_in, const int *ubnd_in, -* const void *in, const void *in_var, -* DataType type, int interp, void (* finterp)( void ), -* const double *params, int flags, -* const void *badval_ptr, int ndim_out, -* const int *lbnd_out, const int *ubnd_out, -* const int *lbnd, const int *ubnd, -* void *out, void *out_var, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function resamples a rectangular grid of data (with any -* number of dimensions) into a specified section of another -* rectangular grid (with a possibly different number of -* dimensions). The coordinate transformation used is given by the -* inverse transformation of the Mapping which is supplied or, -* alternatively, by a linear approximation fitted to a Mapping's -* inverse transformation. Any pixel interpolation scheme may be -* specified for interpolating between the pixels of the input -* grid. -* -* This function is very similar to ResampleSection, except that in -* order to limit memory usage and to ensure locality of reference, -* it divides the output grid up into "blocks" which have a limited -* extent along each output dimension. Each block, which will not -* contain more than a pre-determined maximum number of pixels, is -* then passed to ResampleSection for resampling. - -* Parameters: -* this -* Pointer to a Mapping, whose inverse transformation may be -* used to transform the coordinates of pixels in the output -* grid into associated positions in the input grid, from which -* the output pixel values should be derived (by interpolation -* if necessary). -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* linear_fit -* Pointer to an optional array of double which contains the -* coefficients of a linear fit which approximates the above -* Mapping's inverse coordinate transformation. If this is -* supplied, it will be used in preference to the above Mapping -* when transforming coordinates. This may be used to enhance -* performance in cases where evaluation of the Mapping's -* inverse transformation is expensive. If no linear fit is -* available, a NULL pointer should be supplied. -* -* The way in which the fit coefficients are stored in this -* array and the number of array elements are as defined by the -* astLinearApprox function. -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* in -* Pointer to the input array of data to be resampled (with one -* element for each pixel in the input grid). The numerical type -* of these data should match the "type" value (below). The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and data type as the "in" array), -* which represent estimates of the statistical variance -* associated with each element of the "in" array. If this -* second array is given (along with the corresponding "out_var" -* array), then estimates of the variance of the resampled data -* will also be returned. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* type -* A value taken from the "DataType" enum, which specifies the -* data type of the input and output arrays containing the -* gridded data (and variance) values. -* interp -* A value selected from a set of pre-defined macros to identify -* which sub-pixel interpolation algorithm should be used. -* finterp -* If "interp" is set to a value which requires a user-supplied -* function, then a pointer to that function shoild be given -* here. Otherwise, this value is not used and may be a NULL -* pointer. -* params -* Pointer to an optional array of parameters that may be passed -* to the interpolation algorithm, if required. If no parameters -* are required, a NULL pointer should be supplied. -* flags -* The bitwise OR of a set of flag values which provide -* additional control over the resampling operation. -* badval_ptr -* If the AST__USEBAD flag is set (above), this parameter is a -* pointer to a value which is used to identify bad data and/or -* variance values in the input array(s). The referenced value's -* data type must match that of the "in" (and "in_var") -* arrays. Unless the AST__NOBAD flag is set, the same value will -* also be used to flag any output array elements for which -* resampled values could not be obtained. The output arrays(s) -* may be flagged with this value whether or not the AST__USEBAD -* flag is set (the function return value indicates whether any -* such values have been produced). -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output data grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output data grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output data grid in the same way as "lbnd_in" -* and "ubnd_in" define the shape and size of the input grid -* (see above). -* lbnd -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the first pixel in the -* section of the output data grid for which a value is -* required. -* ubnd -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the last pixel in the -* section of the output data grid for which a value is -* required. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the output grid for which resampled values are -* required. This section should lie wholly within the extent of -* the output grid (as defined by the "lbnd_out" and "ubnd_out" -* arrays). Regions of the output grid lying outside this section -* will not be modified. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the resampled data will be returned. The -* storage order should be such that the coordinate of the first -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order is used). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the resampled values may be returned. This array will only be -* used if the "in_var" array has been given. -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of output grid points for which no valid output value -* could be obtained. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Constants: */ - const int mxpix = 2 * 1024; /* Maximum number of pixels in a block (this - relatively small number seems to give best - performance) */ - -/* Local Variables: */ - double factor; /* Flux conservation factor */ - int *dim_block; /* Pointer to array of block dimensions */ - int *lbnd_block; /* Pointer to block lower bound array */ - int *ubnd_block; /* Pointer to block upper bound array */ - int dim; /* Dimension size */ - int done; /* All blocks resampled? */ - int hilim; /* Upper limit on maximum block dimension */ - int idim; /* Loop counter for dimensions */ - int lolim; /* Lower limit on maximum block dimension */ - int mxdim_block; /* Maximum block dimension */ - int npix; /* Number of pixels in block */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Allocate workspace. */ - lbnd_block = astMalloc( sizeof( int ) * (size_t) ndim_out ); - ubnd_block = astMalloc( sizeof( int ) * (size_t) ndim_out ); - dim_block = astMalloc( sizeof( int ) * (size_t) ndim_out ); - if ( astOK ) { - -/* Find the optimum block size. */ -/* ---------------------------- */ -/* We first need to find the maximum extent which a block of output - pixels may have in each dimension. We determine this by taking the - output grid extent in each dimension and then limiting the maximum - dimension size until the resulting number of pixels is sufficiently - small. This approach allows the block shape to approximate (or - match) the output grid shape when appropriate. */ - -/* First loop to calculate the total number of output pixels and the - maximum output dimension size. */ - npix = 1; - mxdim_block = 0; - for ( idim = 0; idim < ndim_out; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - npix *= dim; - if ( mxdim_block < dim ) mxdim_block = dim; - } - -/* If the number of output pixels is too large for a single block, we - perform iterations to determine the optimum upper limit on a - block's dimension size. Initialise the limits on this result. */ - if ( npix > mxpix ) { - lolim = 1; - hilim = mxdim_block; - -/* Loop to perform a binary chop, searching for the best result until - the lower and upper limits on the result converge to adjacent - values. */ - while ( ( hilim - lolim ) > 1 ) { - -/* Form a new estimate from the mid-point of the previous limits. */ - mxdim_block = ( hilim + lolim ) / 2; - -/* See how many pixels a block contains if its maximum dimension is - limited to this new value. */ - for ( npix = 1, idim = 0; idim < ndim_out ; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - npix *= ( dim < mxdim_block ) ? dim : mxdim_block; - } - -/* Update the appropriate limit, according to whether the number of - pixels is too large or too small. */ - *( ( npix <= mxpix ) ? &lolim : &hilim ) = mxdim_block; - } - -/* When iterations have converged, obtain the maximum limit on the - dimension size of a block which results in no more than the maximum - allowed number of pixels per block. However, ensure that all block - dimensions are at least 2. */ - mxdim_block = lolim; - } - if ( mxdim_block < 2 ) mxdim_block = 2; - -/* Calculate the block dimensions by applying this limit to the output - grid dimensions. */ - for ( idim = 0; idim < ndim_out ; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - dim_block[ idim ] = ( dim < mxdim_block ) ? dim : mxdim_block; - -/* Also initialise the lower and upper bounds of the first block of - output grid pixels to be resampled, ensuring that this does not - extend outside the grid itself. */ - lbnd_block[ idim ] = lbnd[ idim ]; - ubnd_block[ idim ] = MinI( lbnd[ idim ] + dim_block[ idim ] - 1, - ubnd[ idim ], status ); - } - -/* Determine the flux conservation constant if needed. */ -/* --------------------------------------------------- */ - if( ( flags & AST__CONSERVEFLUX ) && linear_fit ) { - factor = MatrixDet( ndim_in, ndim_out, linear_fit + ndim_in, status ); - } else { - factor = 1.0; - } - -/* Resample each block of output pixels. */ -/* ------------------------------------- */ -/* Loop to generate the extent of each block of output pixels and to - resample them. */ - done = 0; - while ( !done && astOK ) { - -/* Resample the current block, accumulating the sum of bad pixels - produced. */ - result += ResampleSection( this, linear_fit, - ndim_in, lbnd_in, ubnd_in, - in, in_var, type, interp, finterp, params, - factor, flags, badval_ptr, - ndim_out, lbnd_out, ubnd_out, - lbnd_block, ubnd_block, out, out_var, status ); - -/* Update the block extent to identify the next block of output - pixels. */ - idim = 0; - do { - -/* We find the least significant dimension where the upper bound of - the block has not yet reached the upper bound of the region of the - output grid which we are resampling. The block's position is then - incremented by one block extent along this dimension, checking that - the resulting extent does not go outside the region being - resampled. */ - if ( ubnd_block[ idim ] < ubnd[ idim ] ) { - lbnd_block[ idim ] = MinI( lbnd_block[ idim ] + - dim_block[ idim ], ubnd[ idim ], status ); - ubnd_block[ idim ] = MinI( lbnd_block[ idim ] + - dim_block[ idim ] - 1, - ubnd[ idim ], status ); - break; - -/* If any less significant dimensions are found where the upper bound - of the block has reached its maximum value, we reset the block to - its lowest position. */ - } else { - lbnd_block[ idim ] = lbnd[ idim ]; - ubnd_block[ idim ] = MinI( lbnd[ idim ] + dim_block[ idim ] - 1, - ubnd[ idim ], status ); - -/* All the blocks have been processed once the position along the most - significant dimension has been reset. */ - done = ( ++idim == ndim_out ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - lbnd_block = astFree( lbnd_block ); - ubnd_block = astFree( ubnd_block ); - dim_block = astFree( dim_block ); - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { -/* -* Name: -* SetAttrib - -* Purpose: -* Set an attribute value for a Mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SetAttrib( AstObject *this, const char *setting ) - -* Class Membership: -* Mapping member function (over-rides the astSetAttrib protected -* method inherited from the Object class). - -* Description: -* This function assigns an attribute value for a Mapping, the -* attribute and its value being specified by means of a string of -* the form: -* -* "attribute= value " -* -* Here, "attribute" specifies the attribute name and should be in -* lower case with no white space present. The value to the right -* of the "=" should be a suitable textual representation of the -* value to be assigned and this will be interpreted according to -* the attribute's data type. White space surrounding the value is -* only significant for string attributes. - -* Parameters: -* this -* Pointer to the Mapping. -* setting -* Pointer to a null terminated string specifying the new attribute -* value. -*/ - -/* Local Variables: */ - AstMapping *this; /* Pointer to the Mapping structure */ - int invert; /* Invert attribute value */ - int len; /* Length of setting string */ - int nc; /* Number of characters read by astSscanf */ - int report; /* Report attribute value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the Mapping structure. */ - this = (AstMapping *) this_object; - -/* Obtain the length of the setting string. */ - len = (int) strlen( setting ); - -/* Test for each recognised attribute in turn, using "astSscanf" to parse - the setting string and extract the attribute value (or an offset to - it in the case of string values). In each case, use the value set - in "nc" to check that the entire string was matched. Once a value - has been obtained, use the appropriate method to set it. */ - -/* Invert. */ -/* ------- */ - if ( nc = 0, - ( 1 == astSscanf( setting, "invert= %d %n", &invert, &nc ) ) - && ( nc >= len ) ) { - astSetInvert( this, invert ); - -/* Report. */ -/* ------- */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "report= %d %n", &report, &nc ) ) - && ( nc >= len ) ) { - astSetReport( this, report ); - -/* Define a macro to see if the setting string matches any of the - read-only attributes of this class. */ -#define MATCH(attrib) \ - ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \ - ( nc >= len ) ) - -/* If the attribute was not recognised, use this macro to report an error - if a read-only attribute has been specified. */ - } else if ( MATCH( "nin" ) || - MATCH( "nout" ) || - MATCH( "islinear" ) || - MATCH( "issimple" ) || - MATCH( "tranforward" ) || - MATCH( "traninverse" ) ) { - astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status, - setting, astGetClass( this ) ); - astError( AST__NOWRT, "This is a read-only attribute." , status); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - (*parent_setattrib)( this_object, setting, status ); - } - -/* Undefine macros local to this function. */ -#undef MATCH -} - -static void Sinc( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* Sinc - -* Purpose: -* 1-dimensional sinc(pi*x) interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void Sinc( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. The function used is sinc(pi*x), where -* sinc(z)=sin(z)/z. - -* Parameters: -* offset -* The offset of a pixel from the interpolation point, measured -* in pixels. -* params -* Not used. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - static double pi; /* Value of pi */ - static int init = 0; /* Initialisation flag */ - -/* On the first invocation, initialise a local value for pi. Do this - only once. */ - if ( !init ) { - pi = acos( -1.0 ); - init = 1; - } - -/* Scale the offset. */ - offset *= pi; - -/* Evaluate the function. */ - *value = ( offset != 0.0 ) ? ( sin( offset ) / offset ) : 1.0; -} - -static void SincCos( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* SincCos - -* Purpose: -* 1-dimensional sinc(pi*x)*cos(k*pi*x) interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SincCos( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. The function used is sinc(pi*x)*cos(k*pi*x) -* out to the point where cos(k*pi*x) = 0, and zero beyond. Here, -* sinc(z)=sin(z)/z. - -* Parameters: -* offset -* The offset of a pixel from the interpolation point, measured -* in pixels. -* params -* The first element of this array should give a value for "k" -* in the cos(k*pi*x) term. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - double offset_k; /* Scaled offset */ - static double halfpi; /* Value of pi/2 */ - static double pi; /* Value of pi */ - static int init = 0; /* Initialisation flag */ - -/* On the first invocation, initialise local values for pi and - pi/2. Do this only once. */ - if ( !init ) { - pi = acos( -1.0 ); - halfpi = 0.5 * pi; - init = 1; - } - -/* Multiply the offset by pi and remove its sign. */ - offset = pi * fabs( offset ); - -/* Find the offset scaled by the "k" factor. */ - offset_k = offset * params[ 0 ]; - -/* If the cos(k*pi*x) term has not reached zero, calculate the - result. */ - if ( offset_k < halfpi ) { - *value = ( ( offset != 0.0 ) ? ( sin( offset ) / offset ) : 1.0 ) * - cos( offset_k ); - -/* Otherwise, the result is zero. */ - } else { - *value = 0.0; - } -} - -static void SincGauss( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* SincGauss - -* Purpose: -* 1-dimensional sinc(pi*x)*exp(-k*x*x) interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SincGauss( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. The function used is sinc(pi*x)*exp(-k*x*x), -* where sinc(z)=sin(z)/z. - -* Parameters: -* offset -* The offset of a pixel from the interpolation point, measured -* in pixels. -* params -* The first element of this array should give a value for "k" -* in the exp(-k*x*x) term. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - double offset_pi; /* Offset multiplied by pi */ - static double pi; /* Value of pi */ - static int init = 0; /* Initialisation flag */ - -/* On the first invocation, initialise a local value for pi. Do this - only once. */ - if ( !init ) { - pi = acos( -1.0 ); - init = 1; - } - -/* Find the offset scaled by pi. */ - offset_pi = pi * offset; - -/* Calculate the result. */ - *value = ( ( offset_pi != 0.0 ) ? ( sin( offset_pi ) / offset_pi ) : 1.0 ) * - exp( -params[ 0 ] * offset * offset ); -} - -static void SincSinc( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* SincSinc - -* Purpose: -* 1-dimensional sinc(pi*x)*sinc(k*pi*x) interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SincSinc( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. The function used is sinc(pi*x)*sinc(k*pi*x), -* out to the point where sinc(k*pi*x)=0, and zero beyond. Here, -* sinc(z)=sin(z)/z. - -* Parameters: -* offset -* The offset of a pixel from the interpolation point, measured -* in pixels. -* params -* The first element of this array should give a value for "k" -* in the sinc(k*pi*x) term. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - double offset_k; /* Scaled offset */ - static double halfpi; /* Value of pi/2 */ - static double pi; /* Value of pi */ - static int init = 0; /* Initialisation flag */ - -/* On the first invocation, initialise local values for pi and - pi/2. Do this only once. */ - if ( !init ) { - pi = acos( -1.0 ); - halfpi = 0.5 * pi; - init = 1; - } - -/* Multiply the offset by pi and remove its sign. */ - offset = pi * fabs( offset ); - -/* Find the offset scaled by the "k" factor. */ - offset_k = offset * params[ 0 ]; - -/* If the sinc(k*pi*x) term has not reached zero, calculate the - result. */ - if ( offset_k < halfpi ) { - *value = ( ( offset != 0.0 ) ? ( sin( offset ) / offset ) : 1.0 ) * - ( ( offset_k != 0.0 ) ? ( sin( offset_k ) / offset_k ) : 1.0 ); - -/* Otherwise, the result is zero. */ - } else { - *value = 0.0; - } -} - -static AstMapping *Simplify( AstMapping *this, int *status ) { -/* -*++ -* Name: -c astSimplify -f AST_SIMPLIFY - -* Purpose: -* Simplify a Mapping. - -* Type: -* Public function. - -* Synopsis: -c #include "mapping.h" -c AstMapping *astSimplify( AstMapping *this ) -f RESULT = AST_SIMPLIFY( THIS, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -* This function simplifies a Mapping (which may be a compound -* Mapping such as a CmpMap) to eliminate redundant computational -* steps, or to merge separate steps which can be performed more -* efficiently in a single operation. -* -* As a simple example, a Mapping which multiplied coordinates by -* 5, and then multiplied the result by 10, could be simplified to -* a single step which multiplied by 50. Similarly, a Mapping which -* multiplied by 5, and then divided by 5, could be reduced to a -* simple copying operation. -* -* This function should typically be applied to Mappings which have -* undergone substantial processing or have been formed by merging -* other Mappings. It is of potential benefit, for example, in -* reducing execution time if applied before using a Mapping to -* transform a large number of coordinates. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the original Mapping. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astSimplify() -f AST_SIMPLIFY = INTEGER -* A new pointer to the (possibly simplified) Mapping. - -* Applicability: -* Mapping -* This function applies to all Mappings. -* FrameSet -* If the supplied Mapping is a FrameSet, the returned Mapping -* will be a copy of the supplied FrameSet in which all the -* inter-Frame Mappings have been simplified. - -* Notes: -* - Mappings that have a set value for their Ident attribute are -* left unchanged after simplification. This is so that their -* individual identity is preserved. This restriction does not -* apply to the simplification of Frames. -* - This function can safely be applied even to Mappings which -* cannot be simplified. If no simplification is possible, it -c behaves exactly like astClone and returns a pointer to the -f behaves exactly like AST_CLONE and returns a pointer to the -* original Mapping. -* - The Mapping returned by this function may not be independent -* of the original (even if simplification was possible), and -* modifying it may therefore result in indirect modification of -* the original. If a completely independent result is required, a -c copy should be made using astCopy. -f copy should be made using AST_COPY. -* - A null Object pointer (AST__NULL) will be returned if this -c function is invoked with the AST error status set, or if it -f function is invoked with STATUS set to an error value, or if it -* should fail for any reason. -*-- -*/ - -/* Local Variables: */ - AstMapping **map_list; /* Pointer to array of Mapping pointers */ - AstMapping *map; /* Cloned pointer to nominated Mapping */ - AstMapping *result; /* Pointer to result Mapping */ - int *invert_list; /* Pointer to array of invert flags */ - int imap; /* Loop counter for Mappings */ - int modified; /* Index of first modified element */ - int nmap; /* Number of Mappings */ - int simpler; /* Simplification achieved? */ - -/* Initialise. */ - result = NULL; - -/* Check the inherited status. */ - if ( !astOK ) return result; - -/* Initialise dynamic arrays of Mapping pointers and associated invert - flags. */ - nmap = 0; - map_list = NULL; - invert_list = NULL; - -/* Build a Mapping list to contain this Mapping (the list should only - have 1 element). */ - astMapList( this, 1, astGetInvert( this ), &nmap, &map_list, &invert_list ); - -/* Pass the list repeatedly to the "astMapMerge" method for - simplification. */ - simpler = 0; - while ( astOK ) { - map = astClone( map_list[ 0 ] ); - modified = astMapMerge( map, 0, 1, &nmap, &map_list, &invert_list ); - map = astAnnul( map ); - -/* Quit looping if the number of Mappings increases above 1, or if no - further change occurs. Note if any simplification was achieved. */ - if ( ( nmap > 1 ) || ( modified < 0 ) ) break; - simpler = 1; - } - -/* Check whether simplification has occurred. If not, simply clone the - original Mapping pointer. This is what will normally happen for - Mapping classes which inherit the default (null) "astMapMerge" - method from this class and do not define one of their own. */ - if ( astOK ) { - if ( !simpler || ( nmap > 1 ) ) { - result = astClone( this ); - -/* If simplification occurred, test if the resulting Mapping has the - Invert attribute value we want. If so, we can simply clone a - pointer to it. */ - } else { - if ( invert_list[ 0 ] == astGetInvert( map_list[ 0 ] ) ) { - result = astClone( map_list[ 0 ] ); - -/* If not, we must make a copy. */ - } else { - result = astCopy( map_list[ 0 ] ); - -/* Either clear the copy's Invert attribute, or set it to 1, as - required. */ - if ( invert_list[ 0 ] ) { - astSetInvert( result, 1 ); - } else { - astClearInvert( result ); - } - } - } - } - -/* Loop to annul all the pointers in the Mapping list. */ - for ( imap = 0; imap < nmap; imap++ ) { - map_list[ imap ] = astAnnul( map_list[ imap ] ); - } - -/* Free the dynamic arrays. */ - map_list = astFree( map_list ); - invert_list = astFree( invert_list ); - -/* If an error occurred, annul the returned Mapping. */ - if ( !astOK ) result = astAnnul( result ); - -/* Return the result. */ - return result; -} - -static void Somb( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* Somb - -* Purpose: -* 1-dimensional somb(pi*x) interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void Somb( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. The function used is somb(pi*x), where -* somb(z)=2*J1(z)/z (J1 is a Bessel function of the first kind of -* order 1). - -* Parameters: -* offset -* The offset of a pixel from the interpolation point, measured -* in pixels. -* params -* Not used. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - static double pi; /* Value of pi */ - static int init = 0; /* Initialisation flag */ - -/* On the first invocation, initialise a local value for pi. Do this - only once. */ - if ( !init ) { - pi = acos( -1.0 ); - init = 1; - } - -/* Scale the offset. */ - offset *= pi; - -/* Evaluate the function. */ - *value = ( offset != 0.0 ) ? ( 2.0*J1Bessel( offset, status ) / offset ) : 1.0; -} - -static void SombCos( double offset, const double params[], int flags, - double *value, int *status ) { -/* -* Name: -* SombCos - -* Purpose: -* 1-dimensional somb(pi*x)*cos(k*pi*x) interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SombCos( double offset, const double params[], int flags, -* double *value, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. The function used is somb(pi*x)*cos(k*pi*x) -* out to the point where cos(k*pi*x) = 0, and zero beyond. Here, -* somb(z)=2*J1(z)/z (J1 is a Bessel function of the first kind of -* order 1). - -* Parameters: -* offset -* The offset of a pixel from the interpolation point, measured -* in pixels. -* params -* The first element of this array should give a value for "k" -* in the cos(k*pi*x) term. -* flags -* Not used. -* value -* Pointer to a double to receive the calculated kernel value. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -*/ - -/* Local Variables: */ - double offset_k; /* Scaled offset */ - static double halfpi; /* Value of pi/2 */ - static double pi; /* Value of pi */ - static int init = 0; /* Initialisation flag */ - -/* On the first invocation, initialise local values for pi and - pi/2. Do this only once. */ - if ( !init ) { - pi = acos( -1.0 ); - halfpi = 0.5 * pi; - init = 1; - } - -/* Multiply the offset by pi and remove its sign. */ - offset = pi * fabs( offset ); - -/* Find the offset scaled by the "k" factor. */ - offset_k = offset * params[ 0 ]; - -/* If the cos(k*pi*x) term has not reached zero, calculate the - result. */ - if ( offset_k < halfpi ) { - *value = ( ( offset != 0.0 ) ? ( J1Bessel( offset, status ) / offset ) : 1.0 ) * - cos( offset_k ); - -/* Otherwise, the result is zero. */ - } else { - *value = 0.0; - } -} - -static int SpecialBounds( const MapData *mapdata, double *lbnd, double *ubnd, - double xl[], double xu[], int *status ) { -/* -* Name: -* SpecialBounds - -* Purpose: -* Estimate coordinate bounds using special points. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int SpecialBounds( const MapData *mapdata, double *lbnd, double *ubnd, -* double xl[], double xu[], int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function makes a rough estimate of the lower and upper -* bounds of a Mapping function over a constrained region of its -* input coordinate space by transforming a set of special test -* points. The points used lie at the corners of the constrained -* region, at the centre of each of its faces, at its centroid, and -* (if within the coordinate constraints) the origin. -* -* In many practical cases, the true extrema may actually lie at -* one or other of these points, in which case the true bounds will -* be found. In other cases, this function only provides an -* approximate limit on each bound (there is no way of telling if -* this is the case, however). In either case, having these initial -* estimates can speed subsequent searches to find the global -* extrema as well as making that search more secure - -* Parameters: -* mapdata -* Pointer to a MapData structure describing the Mapping -* function, its coordinate constraints, etc. -* lbnd -* Pointer to a double. On entry, this should contain a -* previously-obtained upper limit on the lower bound, or -* AST__BAD if no such limit is available. On exit, it will be -* updated with a new estimate of the lower bound, if a better -* one has been found. -* ubnd -* Pointer to a double. On entry, this should contain a -* previously-obtained lower limit on the upper bound, or -* AST__BAD if no such limit is available. On exit, it will be -* updated with a new estimate of the upper bound, if a better -* one has been found. -* xl -* Pointer to an array of double, with one element for each -* input coordinate, in which to return the position of a (not -* necessarily unique) input point at which the lower output -* bound is reached. This array is not altered if an improved -* estimate of the lower bound cannot be found. -* xu -* Pointer to an array of double, with one element for each -* input coordinate, in which to return the position of a (not -* necessarily unique) input point at which the upper output -* bound is reached. This array is not altered if an improved -* estimate of the upper bound cannot be found. -* status -* Pointer to the inherited status variable. - -* Returned: -* A flag indicating if the returned values can be refined. - -*/ - -/* Local Variables: */ - AstPointSet *pset_in; /* PointSet for input coordinates */ - AstPointSet *pset_out; /* PointSet for output coordinates */ - double **ptr_in; /* Pointer to input coordinates */ - double **ptr_out; /* Pointer to output coordinates */ - double *sxl; /* Secondary xl values */ - double *sxu; /* Secondary xu values */ - double f; /* Output coordinate value */ - double slbnd; /* Secondary lbnd value */ - double subnd; /* Secondary lbnd value */ - int *limit; /* Workspace for lower/upper limit flags */ - int bad; /* Output coordinate bad? */ - int coord; /* Loop counter for coordinates */ - int done; /* All corners done? */ - int face; /* Loop counter for faces */ - int ic; /* Index of corner */ - int icen; /* Index of centroid point */ - int ncorner; /* Number of corners */ - int ncoord; /* Number of input coordinates */ - int npoint; /* Number of points */ - int origin; /* Origin lies within bounds? */ - int point; /* Loop counter for points */ - int result; /* Returned flag */ - -/* Initialise */ - result = 1; - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - pset_out = NULL; - -/* Obtain the number of coordinate axes and calculate the number of - points required in order to place one at every corner of the - constrained region of the coordinate space. */ - ncoord = mapdata->nin; - for ( npoint = 1, coord = 0; coord < ncoord; coord++ ) npoint *= 2; - -/* Also include a second point at each corner,offset slightly from the - corner towards the centroid */ - ncorner = npoint; - npoint *= 2; - -/* Also include placing one at the centre of every face and one at the - centroid of the constrained coordinate space. */ - npoint += 2 * ncoord + 1; - -/* Determine if the origin lies within the bounds. If so, include it - as a further point. */ - origin = 1; - for ( coord = 0; coord < ncoord; coord++ ) { - if ( ( mapdata->lbnd[ coord ] > 0.0 ) || - ( mapdata->ubnd[ coord ] < 0.0 ) ) { - origin = 0; - break; - } - } - if ( origin ) npoint++; - -/* Initialise secondary bounds to be the supplied primary bounds */ - slbnd = *lbnd; - subnd = *ubnd; - -/* Create workspace for ssecondary xl xu values */ - sxl = astMalloc( sizeof(double)*(size_t) ncoord ); - sxu = astMalloc( sizeof(double)*(size_t) ncoord ); - -/* Create a PointSet to hold the coordinates and obtain a pointer to - its coordinate values. Also allocate workspace for calculating the - corner coordinates. */ - pset_in = astPointSet( npoint, ncoord, "", status ); - ptr_in = astGetPoints( pset_in ); - limit = astMalloc( sizeof( int ) * (size_t) ncoord ); - if ( astOK ) { - -/* Initialise the workspace. */ - for ( coord = 0; coord < ncoord; coord++ ) limit[ coord ] = 0; - -/* Loop to visit every corner. */ - point = 0; - done = 0; - do { - -/* At each corner, translate the contents of the "limit" array - (containing zeros and ones) into the lower or upper bound on the - corresponding axis. This gives the coordinates of the corner, which - we store in the input PointSet. */ - for ( coord = 0; coord < ncoord; coord++ ) { - ptr_in[ coord ][ point ] = limit[ coord ] ? - mapdata->ubnd[ coord ] : - mapdata->lbnd[ coord ]; - } - -/* Increment the count of points (i.e. corners). */ - point++; - -/* Now update the limit array to identify the next corner. */ - coord = 0; - do { - -/* Flip the first zero found to become a one. This gives a new - corner. */ - if ( !limit[ coord ] ) { - limit[ coord ] = 1; - break; - -/* However, first flip any previous ones to become zeros and then - examine the next element. We have processed all corners once the - array is entirely filled with ones. */ - } else { - limit[ coord ] = 0; - done = ( ++coord == ncoord ); - } - } while ( !done ); - } while ( !done ); - -/* Once the corners have been processed, loop to consider the centre - of each face. */ - for ( face = 0; face < ( 2 * ncoord ); face++ ) { - -/* First calculate the centroid value for each coordinate. Then set - one of these coordinates to the bound where the face lies. */ - for ( coord = 0; coord < ncoord; coord++ ) { - ptr_in[ coord ][ point ] = 0.5 * ( mapdata->lbnd[ coord ] + - mapdata->ubnd[ coord ] ); - } - ptr_in[ face / 2 ][ point ] = ( face % 2 ) ? - mapdata->lbnd[ face / 2 ] : - mapdata->ubnd[ face / 2 ]; - -/* Increment the count of points. */ - point++; - } - -/* Place a point at the centroid of the constrained coordinate - space. */ - for ( coord = 0; coord < ncoord; coord++ ) { - ptr_in[ coord ][ point ] = 0.5 * ( mapdata->lbnd[ coord ] + - mapdata->ubnd[ coord ] ); - } - icen = point++; - -/* Add a set of positions which are offset slightly from each corner - towards the centroid. */ - for ( ic = 0; ic < ncorner; ic++ ) { - for ( coord = 0; coord < ncoord; coord++ ) { - ptr_in[ coord ][ point ] = 0.999*ptr_in[ coord ][ ic ] + - 0.001*ptr_in[ coord ][ icen ]; - } - point++; - } - -/* Finally, add the origin, if it lies within the constraints. */ - if ( origin ) { - for ( coord = 0; coord < ncoord; coord++ ) { - ptr_in[ coord ][ point ] = 0.0; - } - } - -/* Once all the input coordinates have been calculated, transform them - and obtain a pointer to the resulting coordinate values. */ - pset_out = astTransform( mapdata->mapping, pset_in, mapdata->forward, - NULL ); - ptr_out = astGetPoints( pset_out ); - if ( astOK ) { - -/* Loop through each point and test if any of its transformed - coordinates is bad. */ - for ( point = 0; point < npoint; point++ ) { - bad = 0; - for ( coord = 0; coord < mapdata->nout; coord++ ) { - if ( ptr_out[ coord ][ point ] == AST__BAD ) { - bad = 1; - break; - } - } - -/* If so, we ignore the point. Otherwise, extract the required - coordinate. */ - f = ptr_out[ mapdata->coord ][ point ]; - if ( !bad ) { - -/* Use this to update the lower and upper bounds we are seeking. If - either bound is updated, also store the coordinates of the - corresponding input point. */ - if ( ( *lbnd == AST__BAD ) || ( f < *lbnd ) ) { - *lbnd = f; - for ( coord = 0; coord < ncoord; coord++ ) { - xl[ coord ] = ptr_in[ coord ][ point ]; - } - } - if ( ( *ubnd == AST__BAD ) || ( f > *ubnd ) ) { - *ubnd = f; - for ( coord = 0; coord < ncoord; coord++ ) { - xu[ coord ] = ptr_in[ coord ][ point ]; - } - } - -/* If this point has a bad coord value, it may still be useful if the - required coord value is not bad. In this case, extract the required - coordinate. */ - } else if ( f != AST__BAD ) { - -/* Use this to update secondary lower and upper bounds we are seeking. - These will be returned if no primary values are found via the previous - code block. */ - if ( ( slbnd == AST__BAD ) || ( f < slbnd ) ) { - slbnd = f; - for ( coord = 0; coord < ncoord; coord++ ) { - sxl[ coord ] = ptr_in[ coord ][ point ]; - } - } - if ( ( subnd == AST__BAD ) || ( f > subnd ) ) { - subnd = f; - for ( coord = 0; coord < ncoord; coord++ ) { - sxu[ coord ] = ptr_in[ coord ][ point ]; - } - } - } - } - -/* If no primary values could be found, use secondary values. */ - if( *lbnd == AST__BAD && *ubnd == AST__BAD ) { - *lbnd = slbnd; - *ubnd = subnd; - for ( coord = 0; coord < ncoord; coord++ ) { - xu[ coord ] = sxu[ coord ]; - xl[ coord ] = sxl[ coord ]; - } - result = ( slbnd == AST__BAD || subnd == AST__BAD ); - } - } - } - -/* Free workspace */ - sxl = astFree( sxl ); - sxu = astFree( sxu ); - -/* Annul the temporary PointSets and free the workspace. */ - pset_in = astAnnul( pset_in ); - pset_out = astAnnul( pset_out ); - limit = astFree( limit ); - - return result; -} - -/* -* Name: -* SpreadKernel1<X> - -* Purpose: -* Rebin a data grid, using a 1-d interpolation kernel. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SpreadKernel1<X>( AstMapping *this, int ndim_out, -* const int *lbnd_out, const int *ubnd_out, -* const <Xtype> *in, const <Xtype> *in_var, -* double infac, int npoint, const int *offset, -* const double *const *coords, -* void (* kernel)( double, const double [], int, -* double *, int * ), -* int neighb, const double *params, double conwgt, -* int flags, <Xtype> badval, int npix_out, <Xtype> *out, -* <Xtype> *out_var, double *work, int64_t *nused, -* int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which rebins a rectangular region of an -* input grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. Each input -* grid point may be mapped on to a position in the output grid in -* an arbitrary way. The input and output grids may have any number -* of dimensions, not necessarily equal. -* -* Where the input positions given do not correspond with a pixel centre -* in the output grid, the each input pixel value is spread out between the -* surrounding output pixels using weights determined by a separable kernel -* which is the product of a 1-dimensional kernel function evaluated along -* each output dimension. A pointer should be supplied to the 1-dimensional -* kernel function to be used. - -* Parameters: -* this -* Pointer to the Mapping being used in the rebinning operation -* (this is only used for constructing error messages). -* ndim_out -* The number of dimensions in the output grid. This should be at -* least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output grid, its extent along a particular -* (i'th) dimension being ubnd_out[i]-lbnd_out[i]+1 (assuming "i" -* is zero-based). They also define the output grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be rebinned. The numerical type -* of these data should match the function used, as given by the -* suffix on the function name. Note that details of how the input -* grid maps on to this array (e.g. the storage order, number of -* dimensions, etc.) is arbitrary and is specified entirely by means -* of the "offset" array. The "in" array should therefore contain -* sufficient elements to accommodate the "offset" values supplied. -* There is no requirement that all elements of the "in" array -* should be rebinned, and any which are not addressed by the -* contents of the "offset" array will be ignored. -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. It is addressed in exactly the same way (via the -* "offset" array) as the "in" array. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* infac -* A factor by which to multiply the input data values before use. -* npoint -* The number of input points which are to be rebinned. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each input point, this array should contain the zero-based -* offset in the input array(s) (i.e. the "in" and, optionally, -* the "in_var" arrays) from which the value to be rebinned should -* be obtained. -* coords -* An array of pointers to double, with "ndim_out" elements. -* Element "coords[coord]" should point at the first element of -* an array of double (with "npoint" elements) which contains the -* values of coordinate number "coord" for each point being -* rebinned. The value of coordinate number "coord" for -* rebinning point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices are -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding input data (and -* variance) value will be ignored. -* kernel -* Pointer to the 1-dimensional kernel function to be used. -* neighb -* The number of neighbouring pixels in each dimension (on each -* side of the interpolation position) which are to receive -* contributions from the input pixel value. This value should be at -* least 1. -* params -* Pointer to an optional array of parameter values to be passed -* to the kernel function. If no parameters are required by this -* function, then a NULL pointer may be supplied. -* conwgt -* The initial weight to use for all pixels (typically 1.0). Other -* weights (e.g. interpolation weights, variance weights, etc) are -* applied as factors to this initial value. -* flags -* The bitwise OR of a set of flag values which control the -* operation of the function. These are chosend from: -* -* - AST__USEBAD: indicates whether there are "bad" (i.e. missing) data -* in the input array(s) which must be recognised. If this flag is not -* set, all input values are treated literally. -* - AST__GENVAR: Indicates that output variances should be generated -* from the spread of values contributing to each output pixel. -* - AST__USEVAR: Indicates that output variances should be generated -* by rebinning the input variances. -* - AST__VARWGT: Indicates that input variances should be used to -* create weights for the input data values. -* -* Only one of AST__GENVAR and AST__USEVAR should be supplied. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. The same value will also be used to flag any output -* array elements for which resampled values could not be -* obtained. The output arrays(s) may be flagged with this -* value whether or not the AST__USEBAD flag is set (the -* function return value indicates whether any such values have -* been produced). -* npix_out -* Number of pixels in output array. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the rebinned data will be returned. The -* storage order should be such that the index of the first grid -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the rebinned values may be returned. This array will only be -* used if the "in_var" array has been given. The values returned -* are estimates of the statistical variance of the corresponding -* values in the "out" array, on the assumption that all errors in -* input grid values (in the "in" array) are statistically independent -* and that their variance estimates (in the "in_var" array) may -* simply be summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* work -* A pointer to an array with the same data type and size as the "out" -* array which is used as work space. The values in the supplied -* array are incremented on exit by the sum of the weights used -* with each output pixel. -* nused -* An optional pointer to a int64_t which will be incremented by the -* number of input values pasted into the output array. Ignored if NULL. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -*/ -/* Define macros to implement the function for a specific data - type. */ -#define MAKE_SPREAD_KERNEL1(X,Xtype,IntType) \ -static void SpreadKernel1##X( AstMapping *this, int ndim_out, \ - const int *lbnd_out, const int *ubnd_out, \ - const Xtype *in, const Xtype *in_var, \ - double infac, int npoint, const int *offset, \ - const double *const *coords, \ - void (* kernel)( double, const double [], \ - int, double *, int * ), \ - int neighb, const double *params, \ - double conwgt, int flags, Xtype badval, int npix_out, \ - Xtype *out, Xtype *out_var, double *work, \ - int64_t *nused, int *status ) { \ -\ -/* Local Variables: */ \ - astDECLARE_GLOBALS /* Thread-specific data */ \ - Xtype c; \ - Xtype in_val; /* Input pixel value */ \ - double **wtptr; /* Pointer to array of weight pointers */ \ - double **wtptr_last; /* Array of highest weight pointer values */ \ - double *filter; /* Pointer to Nd array of filter values */ \ - double *kp; /* Pointer to next weight values */ \ - double *kstart; /* Pointer to next kernel value */ \ - double *kval; /* Pointer to 1d array of kernel values */ \ - double *wtprod; /* Accumulated weight value array pointer */ \ - double *xfilter; /* Pointer to 1d array of x axis filter values */ \ - double *xnl; /* Pointer to previous ofset array (n-d) */ \ - double pfac; /* Input weight with extra supplied factor */ \ - double pixwt; /* Weight to apply to individual pixel */ \ - double sum; /* Sum of all filter values */ \ - double wgt; /* Weight for input value */ \ - double x; /* x coordinate value */ \ - double xn; /* Coordinate value (n-d) */ \ - double xx; /* X offset */ \ - double xxl; /* Previous X offset */ \ - double xxn; \ - double y; /* y coordinate value */ \ - double yy; /* Y offset */ \ - double yyl; /* Previous Y offset */ \ - int *hi; /* Pointer to array of upper indices */ \ - int *jhi; /* Pointer to array of filter upper indices */ \ - int *jlo; /* Pointer to array of filter lower indices */ \ - int *lo; /* Pointer to array of lower indices */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int done; /* All pixel indices done? */ \ - int genvar; /* Generate output variances? */ \ - int hi_ix; /* Upper output pixel index (x dimension) */ \ - int hi_iy; /* Upper output pixel index (y dimension) */ \ - int hi_jx; /* Upper filter pixel index (x dimension) */ \ - int hi_jy; /* Upper filter pixel index (y dimension) */ \ - int idim; /* Loop counter for dimensions */ \ - int ii; /* Loop counter for dimensions */ \ - int ix; /* Pixel index in output grid x dimension */ \ - int iy; /* Pixel index in output grid y dimension */ \ - int jjx; /* Reflected pixel index in filter grid x dimension */ \ - int jjy; /* Reflected pixel index in filter grid y dimension */ \ - int jx; /* Pixel index in filter grid x dimension */ \ - int jxn; \ - int jy; /* Pixel index in filter grid y dimension */ \ - int kerror; /* Error signalled by kernel function? */ \ - int lo_ix; /* Lower output pixel index (x dimension) */ \ - int lo_iy; /* Lower output pixel index (y dimension) */ \ - int lo_jx; /* Lower filter pixel index (x dimension) */ \ - int lo_jy; /* Lower filter pixel index (y dimension) */ \ - int nb2; /* The total number of neighbouring pixels */ \ - int nf; /* Number of pixels in filter array */ \ - int nwx; /* Used X width of kernel function (*2) */ \ - int nwy; /* Used Y width of kernel function (*2) */ \ - int off1; /* Input pixel offset due to y index */ \ - int off_in; /* Offset to input pixel */ \ - int off_out; /* Offset to output pixel */ \ - int off_xedge; /* Does filter box overlap array edge on the X axis? */ \ - int off_yedge; /* Does filter box overlap array edge on the Y axis? */ \ - int point; /* Loop counter for output points */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int varwgt; /* Use input variances as weights? */ \ - int ystride; /* Stride along input grid y dimension */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Get a pointer to a structure holding thread-specific global data values */ \ - astGET_GLOBALS(this); \ -\ -/* Further initialisation. */ \ - kerror = 0; \ - sum = 0.0; \ - bad = 0; \ -\ -/* Find the total number of pixels in the filter used to spread a single \ - input pixel into the output image. */ \ - nb2 = 2*neighb; \ - nf = 1; \ - for ( idim = 0; idim < ndim_out; idim++ ) nf *= nb2; \ -\ -/* Allocate workspace to hold the filter values. */ \ - filter = astMalloc( sizeof( double ) * (size_t) nf ); \ - if ( astOK ) { \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - usebad = flags & AST__USEBAD; \ - usevar = 0; \ - genvar = 0; \ - if( flags & AST__GENVAR ) { \ - genvar = out_var && work; \ - } else if( flags & AST__USEVAR ) { \ - usevar = in_var && out_var; \ - } \ - varwgt = ( flags & AST__VARWGT ) && in_var && work; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_out == 1 ) { \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - KERNEL_1D(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - KERNEL_1D(X,Xtype,1,0,1,IntType,1) \ - } else { \ - KERNEL_1D(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - KERNEL_1D(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - KERNEL_1D(X,Xtype,0,0,1,IntType,1) \ - } else { \ - KERNEL_1D(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - KERNEL_1D(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - KERNEL_1D(X,Xtype,1,0,1,IntType,0) \ - } else { \ - KERNEL_1D(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - KERNEL_1D(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - KERNEL_1D(X,Xtype,0,0,1,IntType,0) \ - } else { \ - KERNEL_1D(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Exit point on error in kernel function */ \ - Kernel_SError_1d: ; \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_out == 2 ) { \ -\ -/* Allocate workspace to hold the X axis filter values. */ \ - xfilter = astMalloc( sizeof( double ) * (size_t) nb2 ); \ -\ -/* Calculate the stride along the y dimension of the output grid. */ \ - ystride = ubnd_out[ 0 ] - lbnd_out[ 0 ] + 1; \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - KERNEL_2D(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - KERNEL_2D(X,Xtype,1,0,1,IntType,1) \ - } else { \ - KERNEL_2D(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - KERNEL_2D(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - KERNEL_2D(X,Xtype,0,0,1,IntType,1) \ - } else { \ - KERNEL_2D(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - KERNEL_2D(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - KERNEL_2D(X,Xtype,1,0,1,IntType,0) \ - } else { \ - KERNEL_2D(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - KERNEL_2D(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - KERNEL_2D(X,Xtype,0,0,1,IntType,0) \ - } else { \ - KERNEL_2D(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Free work space */ \ - xfilter = astFree( xfilter ); \ -\ -/* Exit point on error in kernel function */ \ - Kernel_SError_2d: ; \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - hi = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - lo = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - jhi = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - jlo = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - xnl = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - kval = astMalloc( sizeof( double ) * (size_t) \ - ( nb2 * ndim_out ) ); \ - wtprod = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - wtptr = astMalloc( sizeof( double * ) * (size_t) ndim_out ); \ - wtptr_last = astMalloc( sizeof( double * ) * (size_t) ndim_out ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the output grid. */ \ - for ( s = 1, idim = 0; idim < ndim_out; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ - xnl[ idim ] = AST__BAD; \ - } \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - KERNEL_ND(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - KERNEL_ND(X,Xtype,1,0,1,IntType,1) \ - } else { \ - KERNEL_ND(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - KERNEL_ND(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - KERNEL_ND(X,Xtype,0,0,1,IntType,1) \ - } else { \ - KERNEL_ND(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - KERNEL_ND(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - KERNEL_ND(X,Xtype,1,0,1,IntType,0) \ - } else { \ - KERNEL_ND(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - KERNEL_ND(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - KERNEL_ND(X,Xtype,0,0,1,IntType,0) \ - } else { \ - KERNEL_ND(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Exit point on error in kernel function */ \ - Kernel_SError_Nd: ;\ - } \ -\ -/* Free the workspace. */ \ - hi = astFree( hi ); \ - lo = astFree( lo ); \ - jhi = astFree( jhi ); \ - jlo = astFree( jlo ); \ - stride = astFree( stride ); \ - xnl = astFree( xnl ); \ - kval = astFree( kval ); \ - wtprod = astFree( wtprod ); \ - wtptr = astFree( wtptr ); \ - wtptr_last = astFree( wtptr_last ); \ - } \ - filter = astFree( filter ); \ - }\ -\ -/* If an error occurred in the kernel function, then report a \ - contextual error message. */ \ - if ( kerror ) { \ - astError( astStatus, "astRebin"#X"(%s): Error signalled by " \ - "user-supplied 1-d interpolation kernel.", status, \ - astGetClass( unsimplified_mapping ) ); \ - } \ -\ -} - - - - -#define KERNEL_1D(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* We do not yet have a previous filter position. */ \ - xxl = AST__BAD; \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Obtain the x coordinate of the current point and test if it is bad. \ - Also test that the central point falls within the output array. */ \ - x = coords[ 0 ][ point ]; \ - ix = (int) floor( x + 0.5 ); \ - if( ix < lbnd_out[ 0 ] || ix > ubnd_out[ 0 ] ) bad = 1; \ - bad = bad || ( x == AST__BAD ); \ -\ -/* If OK, calculate the lowest and highest indices (in the x \ - dimension) of the region of neighbouring output pixels that will \ - receive contributions from the current input pixel. Constrain these \ - values to lie within the output grid. */ \ - if ( !bad ) { \ - ix = (int) floor( x ) - neighb + 1; \ - lo_ix = MaxI( ix, lbnd_out[ 0 ], status ); \ - hi_ix = MinI( ix + nb2 - 1, ubnd_out[ 0 ], status ); \ -\ -/* Skip to the next input point if the current input point makes no \ - contribution to any output pixel. */ \ - if( lo_ix <= hi_ix ) { \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* Convert these output indices to the corresponding indices \ - within a box [ 0, 2*neighb ] holding the kernel values. */ \ - lo_jx = lo_ix - ix; \ - hi_jx = hi_ix - ix; \ -\ -/* See if the kernel extends off the edge of the output array. */ \ - nwx = hi_jx - lo_jx + 1; \ - off_xedge = ( nwx < nb2 ); \ -\ -/* Use the kernel function to fill the work array with weights for all output \ - pixels whether or not they fall within the output array. At the same \ - time find the sum of all the factors. */ \ - xx = (double) ix - x; \ - if( xx != xxl || off_xedge ) { \ - sum = 0.0; \ -\ -/* First handle cases where the kernel box overlaps an edge of the output \ - array. In these cases, in order to conserve flux, the bit of the \ - kernel function that is off the edge is reflected back onto the array. \ - Care must be taken since the reflected part of the kernel may itself \ - overlap the opposite edge of the array, in which case the overlapping \ - part must again be reflected back onto the array. This iterative \ - reflection is implemented using a fractional division (%) operator. */ \ - if( off_xedge ) { \ - nwx *= 2; \ - xxl = AST__BAD; \ - for( jx = 0; jx < nb2; jx++ ) filter[ jx ] = 0.0; \ -\ - for ( jx = 0; jx < nb2; jx++ ) { \ - ( *kernel )( xx, params, flags, &pixwt, status ); \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_1d; \ - } \ -\ - jjx = ( jx - lo_jx ) % nwx + lo_jx; \ - if( jjx < lo_jx ) jjx += nwx; \ - if( jjx > hi_jx ) jjx = 2*hi_jx - jjx + 1; \ -\ - filter[ jjx ] += pixwt; \ - sum += pixwt; \ - xx += 1.0; \ - } \ -\ -/* Now handle cases where the kernel box is completely within the output \ - array. */ \ - } else { \ - xxl = xx; \ -\ - for ( jx = 0; jx < nb2; jx++ ) { \ - ( *kernel )( xx, params, flags, &pixwt, status ); \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_1d; \ - } \ -\ -/* Store the kernel factor and increment the sum of all factors. */ \ - filter[ jx ] = pixwt; \ - sum += pixwt; \ - xx += 1.0; \ - } \ -\ - } \ -\ -/* Ensure we do not divide by zero. */ \ - if( sum == 0.0 ) sum = 1.0; \ - } \ -\ -/* If we are using the input data variances as weights, calculate the \ - total weight, incorporating the normalisation factor for the kernel. */ \ - if( Varwgt ) { \ - wgt = conwgt/(sum*in_var[ off_in ]); \ -\ -/* If we are not using input variances as weights, the weight is just the \ - kernel normalisation factor. */ \ - } else { \ - wgt = conwgt/sum; \ - } \ -\ -/* Loop round all the output pixels which receive contributions from this \ - input pixel, calculating the offset of each pixel from the start of the \ - input array. */ \ - off_out = lo_ix - lbnd_out[ 0 ]; \ - for ( jx = lo_jx; jx <= hi_jx; jx++, off_out++ ) { \ -\ -/* Retrieve the weight for the current output pixel and normalise it. */ \ - pixwt = wgt*filter[ jx ]; \ - pfac = pixwt*infac; \ -\ -/* Update the output pixel with the required fraction of the input pixel \ - value. */ \ - c = CONV(IntType,pfac*in_val); \ -\ - if( work ) { \ - out[ off_out ] += c; \ - work[ off_out ] += pixwt; \ - } else {\ - out[ off_out ] += c; \ - } \ -\ - if ( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ -\ - } \ - } \ - } \ - } - - - - -#define KERNEL_2D(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* We do not yet have a previous filter position. */ \ - xxl = AST__BAD; \ - yyl = AST__BAD; \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Obtain the x coordinate of the current point and test if it is bad. \ - Also test that the central point falls within the output array. */ \ - x = coords[ 0 ][ point ]; \ - ix = (int) floor( x + 0.5 ); \ - if( ix < lbnd_out[ 0 ] || ix > ubnd_out[ 0 ] ) bad = 1; \ - bad = bad || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Similarly obtain and test the y coordinate. */ \ - y = coords[ 1 ][ point ]; \ - iy = (int) floor( y + 0.5 ); \ - if( iy < lbnd_out[ 1 ] || iy > ubnd_out[ 1 ] ) bad = 1; \ - bad = bad || ( y == AST__BAD ); \ - if ( !bad ) { \ -\ -/* If OK, calculate the lowest and highest indices (in each dimension) \ - of the region of neighbouring output pixels which will receive \ - contributions from the current input pixel. Constrain these values \ - to lie within the input grid. */ \ - ix = (int) floor( x ) - neighb + 1; \ - lo_ix = MaxI( ix, lbnd_out[ 0 ], status ); \ - hi_ix = MinI( ix + nb2 - 1, ubnd_out[ 0 ], status ); \ - iy = (int) floor( y ) - neighb + 1; \ - lo_iy = MaxI( iy, lbnd_out[ 1 ], status ); \ - hi_iy = MinI( iy + nb2 - 1, ubnd_out[ 1 ], status ); \ -\ -/* Skip to the next input point if the current input point makes no \ - contribution to any output pixel. */ \ - if( lo_ix <= hi_ix && lo_iy <= hi_iy ) { \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* Convert these output indices to the corresponding indices \ - within a box [ 0:2*neighb, 0:2*neighb ] holding the kernel values. */ \ - lo_jx = lo_ix - ix; \ - hi_jx = hi_ix - ix; \ - lo_jy = lo_iy - iy; \ - hi_jy = hi_iy - iy; \ -\ -/* See if the kernel extends off the edge of the output array on either \ - axis. */ \ - nwx = hi_jx - lo_jx + 1; \ - nwy = hi_jy - lo_jy + 1; \ - off_xedge = ( nwx < nb2 ); \ - off_yedge = ( nwy < nb2 ); \ -\ -/* Loop to evaluate the kernel function along the y dimension, storing \ - the resulting weight values in all elements of each associated row \ - in the kvar array. The function's argument is the offset of the \ - output pixel (along this dimension) from the central output \ - position. */ \ - yy = (double) iy - y; \ - xx = (double) ix - x; \ - if( xx != xxl || yy != yyl || off_xedge || off_yedge ) { \ -\ -/* First handle cases where the kernel box extends beyond the top or \ - bottom edge of the output array. In these cases, in order to conserve \ - flux, the bit of the kernel function that is off the edge is reflected \ - back onto the array. Care must be taken since the reflected part of the \ - kernel may itself overlap the opposite edge of the array, in which \ - case the overlapping part must again be reflected back onto the \ - array. This iterative reflection is implemented using a fractional \ - division (%) operator. */ \ - if( off_yedge ) { \ - nwy *= 2; \ - xxl = AST__BAD; \ - yyl = AST__BAD; \ - for( jy = 0; jy < nb2*nb2; jy++ ) filter[ jy ] = 0.0; \ -\ - for ( jy = 0; jy < nb2; jy++ ) { \ - ( *kernel )( yy, params, flags, &pixwt, status ); \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_2d; \ - } \ -\ - jjy = ( jy - lo_jy ) % nwy + lo_jy; \ - if( jjy < lo_jy ) jjy += nwy; \ - if( jjy > hi_jy ) jjy = 2*hi_jy - jjy + 1; \ -\ - kp = filter + jjy*nb2; \ - for( jx = 0; jx < nb2; jx++ ) *(kp++) += pixwt; \ - yy += 1.0; \ - } \ -\ -/* Now handles cases where the kernel does not overlap the top or bottom edge \ - of the output array. */ \ - } else { \ - xxl = xx; \ - yyl = yy; \ - kp = filter; \ - for ( jy = 0; jy < nb2; jy++ ) { \ - ( *kernel )( yy, params, flags, &pixwt, status ); \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_2d; \ - } \ -\ -/* Store the kernel factor in all elements of the current row. */ \ - for( jx = 0; jx < nb2; jx++ ) *(kp++) = pixwt; \ -\ -/* Move on to the next row. */ \ - yy += 1.0; \ - } \ - } \ -\ -/* Loop to evaluate the kernel function along the x dimension, multiplying \ - the resulting weight values by the values already stored in the the \ - associated column in the kvar array. The function's argument is the \ - offset of the output pixel (along this dimension) from the central output \ - position. Also form the total data sum in the filter array. First \ - handle cases where the kernel overlaps the left or right edge of the \ - output array. */ \ - sum = 0.0; \ -\ -/* First deal with cases where the kernel extends beyond the left or \ - right edge of the output array. */ \ - if( off_xedge ) { \ - nwx *= 2; \ - xxl = AST__BAD; \ - for( jx = 0; jx < nb2; jx++ ) xfilter[ jx ] = 0.0; \ -\ - for ( jx = 0; jx < nb2; jx++ ) { \ - ( *kernel )( xx, params, flags, &pixwt, status ); \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_2d; \ - } \ -\ - jjx = ( jx - lo_jx ) % nwx + lo_jx; \ - if( jjx < lo_jx ) jjx += nwx; \ - if( jjx > hi_jx ) jjx = 2*hi_jx - jjx + 1; \ -\ - xfilter[ jjx ] += pixwt; \ - xx += 1.0; \ - } \ -\ - for ( jx = 0; jx < nb2; jx++ ) { \ - kp = filter + jx; \ - for( jy = 0; jy < nb2; jy++, kp += nb2 ) { \ - *kp *= xfilter[ jx ]; \ - sum += *kp; \ - } \ - } \ -\ -/* Now deal with cases where the kernel does not extends beyond the left or \ - right edge of the output array. */ \ - } else { \ -\ - for ( jx = 0; jx < nb2; jx++ ) { \ - ( *kernel )( xx, params, flags, &pixwt, status ); \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_2d; \ - } \ -\ -/* Multiply the kernel factor by all elements of the current column. */ \ - kp = filter + jx; \ - for( jy = 0; jy < nb2; jy++, kp += nb2 ) { \ - *kp *= pixwt; \ - sum += *kp; \ - } \ -\ -/* Move on to the next column. */ \ - xx += 1.0; \ - } \ - } \ -\ -/* Ensure we do not divide by zero. */ \ - if( sum == 0.0 ) sum = 1.0; \ - } \ -\ -/* If we are using the input data variances as weights, calculate the \ - total weight, incorporating the normalisation factor for the kernel. */ \ - if( Varwgt ) { \ - wgt = conwgt/(sum*in_var[ off_in ]); \ -\ -/* If we are not using input variances as weights, the weight is just the \ - kernel normalisation factor. */ \ - } else { \ - wgt = conwgt/sum; \ - } \ -\ -/* Find the offset into the output array at the first modified output pixel \ - in the first modified row. */ \ - off1 = lo_ix - lbnd_out[ 0 ] + ystride * ( lo_iy - lbnd_out[ 1 ] ); \ -\ -/* Loop over the affected output rows again. */ \ - for ( jy = lo_jy; jy <= hi_jy; jy++, off1 += ystride ) { \ -\ -/* Save the offset of the first output pixel to be modified in the \ - current row. */ \ - off_out = off1; \ -\ -/* Get a pointer to the first weight value which will be used. */ \ - kp = filter + lo_jx + jy*nb2; \ -\ -/* Loop over the affected output columns again. */ \ - for ( jx = lo_jx; jx <= hi_jx; jx++, off_out++, kp++ ) { \ -\ -/* Calculate the weight for this output pixel and normalise it. */ \ - pixwt = wgt*( *kp ); \ -\ -/* Update the output pixel with the required fraction of the input pixel \ - value. */ \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ -\ - out[ off_out ] += c; \ - if( work ) work[ off_out ] += pixwt; \ -\ - if ( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ - } \ - } \ - } \ - } \ - } \ - } - - - - -#define KERNEL_ND(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* We do not yet have a normalising factor */ \ - sum = AST__BAD; \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Initialise offsets into the output array. Then loop to obtain each \ - coordinate associated with the current output point. Set a flag \ - indicating if any output pixel will be modified. */ \ - if( !bad ) { \ - off_out = 0; \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate is bad. If true, the corresponding output pixel \ - value will be bad, so give up on this point. */ \ - ix = (int) floor( xn + 0.5 ); \ - if( ix < lbnd_out[ idim ] || ix > ubnd_out[ idim ] ) bad = 1; \ - bad = bad || ( xn == AST__BAD ); \ - if ( bad ) break; \ -\ -/* Calculate the lowest and highest indices (in the current dimension) \ - of the region of neighbouring output pixels that will be modified. \ - Constrain these values to lie within the output grid. */ \ - ix = (int) floor( xn ) - neighb + 1; \ - lo[ idim ] = MaxI( ix, lbnd_out[ idim ], status ); \ - hi[ idim ] = MinI( ix + nb2 - 1, ubnd_out[ idim ], status ); \ - jlo[ idim ] = lo[ idim ] - ix; \ - jhi[ idim ] = hi[ idim ] - ix; \ -\ -/* Check there is some overlap with the output array on this axis. */ \ - if( lo[ idim ] > hi[ idim ] ) { \ - bad = 1; \ - break; \ - } \ -\ -/* Accumulate the offset (from the start of the output array) of the \ - modified output pixel which has the lowest index in each dimension. */ \ - off_out += stride[ idim ] * ( lo[ idim ] - lbnd_out[ idim ] ); \ -\ -/* Set up an array of pointers to locate the first filter pixel (stored in the \ - "kval" array) for each dimension. */ \ - wtptr[ idim ] = kval + nb2*idim; \ - wtptr_last[ idim ] = wtptr[ idim ] + nb2 - 1; \ -\ -/* See if the kernel extends off the edge of the output array on the current \ - axis. */ \ - lo_jx = jlo[ idim ]; \ - hi_jx = jhi[ idim ]; \ - nwx = hi_jx - lo_jx + 1; \ - off_xedge = ( nwx < nb2 ); \ -\ -/* Loop to evaluate the kernel function along each dimension, storing \ - the resulting values. The function's argument is the offset of the \ - output pixel (along the relevant dimension) from the central output \ - point. */ \ - xxn = (double) ix - xn; \ - if( xxn != xnl[ idim ] || off_xedge ) { \ - sum = AST__BAD; \ -\ -/* First handle cases where the kernel box overlaps an edge of the output \ - array. In these cases, in order to conserve flux, the bit of the \ - kernel function that is off the edge is reflected back onto the array. \ - Care must be taken since the reflected part of the kernel may itself \ - overlap the opposite edge of the array, in which case the overlapping \ - part must again be reflected back onto the array. This iterative \ - reflection is implemented using a fractional division (%) operator. */ \ - if( off_xedge ) { \ - nwx *= 2; \ - xnl[ idim ] = AST__BAD; \ - kp = wtptr[ idim ]; \ - for( jx = 0; jx < nb2; jx++ ) *(kp++) = 0.0; \ -\ - kp = wtptr[ idim ]; \ - for ( jx = 0; jx < nb2; jx++ ) { \ - ( *kernel )( xxn, params, flags, &pixwt, status ); \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_1d; \ - } \ -\ - jjx = ( jx - lo_jx ) % nwx + lo_jx; \ - if( jjx < lo_jx ) jjx += nwx; \ - if( jjx > hi_jx ) jjx = 2*hi_jx - jjx + 1; \ -\ - kp[ jjx ] += pixwt; \ - xxn += 1.0; \ - } \ -\ -/* Now handle cases where the kernel box is completely within the output \ - array. */ \ - } else { \ - xnl[ idim ] = xxn; \ - for ( jxn = 0; jxn < nb2; jxn++ ) { \ - ( *kernel )( xxn, params, flags, wtptr[ idim ] + jxn, status ); \ -\ -/* Check for errors arising in the kernel function. */ \ - if ( !astOK ) { \ - kerror = 1; \ - goto Kernel_SError_Nd; \ - } \ -\ -/* Increment the kernel position. */ \ - xxn += 1.0; \ - } \ - } \ - } \ - } \ -\ -/* If OK... */ \ - if ( !bad ) { \ -\ -/* We only need to modify the normalising factor if the weight values \ - have changed. */ \ - if( sum == AST__BAD ) { \ -\ -/* The kernel value to use for each output pixel is the product of the \ - kernel values for each individual axis at that point. To conserve \ - flux we need to make sure that the sum of these kernel products is unity. \ - So loop over the values now to find the total sum of all kernel values. */ \ - idim = ndim_out - 1; \ - wtprod[ idim ] = 1.0; \ - done = 0; \ - sum = 0; \ - do { \ -\ -/* Each modified output pixel has a weight equal to the product of the kernel \ - weight factors evaluated along each input dimension. However, since \ - we typically only change the index of one dimension at a time, we \ - can avoid forming this product repeatedly by retaining an array of \ - accumulated products for all higher dimensions. We need then only \ - update the lower elements in this array, corresponding to those \ - dimensions whose index has changed. We do this here, "idim" being \ - the index of the most significant dimension to have changed. Note \ - that on the first pass, all dimensions are considered changed, \ - causing this array to be initialised. */ \ - for ( ii = idim; ii >= 1; ii-- ) { \ - wtprod[ ii - 1 ] = wtprod[ ii ] * *( wtptr[ ii ] ); \ - } \ -\ -/* Obtain the weight of each pixel from the accumulated product of \ - weights. Also multiply by the weight for dimension zero, which is not \ - included in the "wtprod" array). Increment the sum of all weights. */ \ - sum += wtprod[ 0 ] * *( wtptr[ 0 ] ); \ -\ -/* Now update the weight value pointers and pixel offset to refer to \ - the next output pixel to be considered. */ \ - idim = 0; \ - do { \ -\ -/* The first input dimension whose weight value pointer has not yet \ - reached its final value has this pointer incremented. */ \ - if ( wtptr[ idim ] != wtptr_last[ idim ] ) { \ - wtptr[ idim ]++; \ - break; \ -\ -/* Any earlier dimensions (which have reached the final pointer value) \ - have this pointer returned to its lowest value. */ \ - } else { \ - wtptr[ idim ] -= nb2 - 1; \ - done = ( ++idim == ndim_out ); \ - } \ - } while ( !done ); \ - } while ( !done ); \ -\ -/* Ensure we do not divide by zero. */ \ - if( sum == 0.0 ) sum = 1.0; \ - } \ -\ -/* Re-initialise the weights pointers to refer to the first and last \ - filter pixels which overlaps the output array. */ \ - kstart = kval; \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - wtptr[ idim ] = kstart + jlo[ idim ]; \ - wtptr_last[ idim ] = kstart + jhi[ idim ]; \ - kstart += nb2; \ - } \ -\ -/* If we are using the input data variances as weights, calculate the \ - total weight, incorporating the normalisation factor for the kernel. */ \ - if( Varwgt ) { \ - wgt = conwgt/(sum*in_var[ off_in ]); \ -\ -/* If we are not using input variances as weights, the weight is just the \ - kernel normalisation factor. */ \ - } else { \ - wgt = conwgt/sum; \ - } \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* Initialise, and loop over the neighbouring output pixels to divide up \ - the input pixel value between them. */ \ - idim = ndim_out - 1; \ - wtprod[ idim ] = 1.0; \ - done = 0; \ - do { \ -\ -/* Each modified output pixel has a weight equal to the product of the kernel \ - weight factors evaluated along each input dimension. However, since \ - we typically only change the index of one dimension at a time, we \ - can avoid forming this product repeatedly by retaining an array of \ - accumulated products for all higher dimensions. We need then only \ - update the lower elements in this array, corresponding to those \ - dimensions whose index has changed. We do this here, "idim" being \ - the index of the most significant dimension to have changed. Note \ - that on the first pass, all dimensions are considered changed, \ - causing this array to be initialised. */ \ - for ( ii = idim; ii >= 1; ii-- ) { \ - wtprod[ ii - 1 ] = wtprod[ ii ] * *( wtptr[ ii ] ); \ - } \ -\ -/* Obtain the weight of each pixel from the accumulated \ - product of weights. Also multiply by the weight for dimension zero, \ - which is not included in the "wtprod" array). */ \ - pixwt = ( wtprod[ 0 ] * *( wtptr[ 0 ] ) )*wgt; \ -\ -/* Update the output pixel with the required fraction of the input pixel \ - value. */ \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ -\ - if( work ) { \ - out[ off_out ] += c; \ - work[ off_out ] += pixwt; \ - } else {\ - out[ off_out ] += c; \ - } \ -\ - if ( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ -\ -/* Now update the weight value pointers and pixel offset to refer to \ - the next output pixel to be considered. */ \ - idim = 0; \ - do { \ -\ -/* The first input dimension whose weight value pointer has not yet \ - reached its final value has this pointer incremented, and the pixel \ - offset into the input array is updated accordingly. */ \ - if ( wtptr[ idim ] != wtptr_last[ idim ] ) { \ - wtptr[ idim ]++; \ - off_out += stride[ idim ]; \ - break; \ -\ -/* Any earlier dimensions (which have reached the final pointer value) \ - have this pointer returned to its lowest value. Again, the pixel \ - offset into the input image is updated accordingly. */ \ - } else { \ - wtptr[ idim ] -= ( hi[ idim ] - lo[ idim ] ); \ - off_out -= stride[ idim ] * \ - ( hi[ idim ] - lo[ idim ] ); \ - done = ( ++idim == ndim_out ); \ - } \ - } while ( !done ); \ - } while ( !done ); \ - } \ - } \ - } - - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_SPREAD_KERNEL1(LD,long double,0) -#endif -MAKE_SPREAD_KERNEL1(D,double,0) -MAKE_SPREAD_KERNEL1(F,float,0) -MAKE_SPREAD_KERNEL1(I,int,1) -MAKE_SPREAD_KERNEL1(B,signed char,1) -MAKE_SPREAD_KERNEL1(UB,unsigned char,1) - -/* Undefine the macros used above. */ -#undef KERNEL_ND -#undef KERNEL_2D -#undef KERNEL_1D -#undef MAKE_SPREAD_KERNEL1 - -/* -* Name: -* SpreadLinear<X> - -* Purpose: -* Rebin a data grid, using the linear spreading scheme. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SpreadLinear<X>( int ndim_out, -* const int *lbnd_out, const int *ubnd_out, -* const <Xtype> *in, const <Xtype> *in_var, -* double infac, int npoint, const int *offset, -* const double *const *coords, double conwgt, int flags, -* <Xtype> badval, int npix_out, <Xtype> *out, -* <Xtype> *out_var, double *work, int64_t *nused ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which rebins a rectangular region of an -* input grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. Each input -* grid point may be mapped on to a position in the output grid in -* an arbitrary way. Where the positions given do not correspond -* with a pixel centre in the input grid, the spreading scheme -* used divides the input pixel value up linearly between the -* nearest neighbouring output pixels in each dimension (there are 2 -* nearest neighbours in 1 dimension, 4 in 2 dimensions, 8 in 3 -* dimensions, etc.). - -* Parameters: -* ndim_out -* The number of dimensions in the output grid. This should be at -* least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output grid, its extent along a particular -* (i'th) dimension being ubnd_out[i]-lbnd_out[i]+1 (assuming "i" -* is zero-based). They also define the output grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be rebinned. The numerical type -* of these data should match the function used, as given by the -* suffix on the function name. Note that details of how the input -* grid maps on to this array (e.g. the storage order, number of -* dimensions, etc.) is arbitrary and is specified entirely by means -* of the "offset" array. The "in" array should therefore contain -* sufficient elements to accommodate the "offset" values supplied. -* There is no requirement that all elements of the "in" array -* should be rebinned, and any which are not addressed by the -* contents of the "offset" array will be ignored. -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. It is addressed in exactly the same way (via the -* "offset" array) as the "in" array. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* infac -* A factor by which to multiply the input data values before use. -* npoint -* The number of input points which are to be rebinned. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each input point, this array should contain the zero-based -* offset in the input array(s) (i.e. the "in" and, optionally, -* the "in_var" arrays) from which the value to be rebinned should -* be obtained. -* coords -* An array of pointers to double, with "ndim_out" elements. -* Element "coords[coord]" should point at the first element of -* an array of double (with "npoint" elements) which contains the -* values of coordinate number "coord" for each point being -* rebinned. The value of coordinate number "coord" for -* rebinning point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices are -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding input data (and -* variance) value will be ignored. -* The bitwise OR of a set of flag values which control the -* operation of the function. These are chosend from: -* -* - AST__USEBAD: indicates whether there are "bad" (i.e. missing) data -* in the input array(s) which must be recognised. If this flag is not -* set, all input values are treated literally. -* - AST__GENVAR: Indicates that any input variances are to be -* ignored, and that the output variances should be generated from -* the spread of values contributing to each output pixel. -* conwgt -* The initial weight to use for all pixels (typically 1.0). Other -* weights (e.g. interpolation weights, variance weights, etc) are -* applied as factors to this initial value. -* flags -* The bitwise OR of a set of flag values which control the -* operation of the function. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. The same value will also be used to flag any output -* array elements for which resampled values could not be -* obtained. The output arrays(s) may be flagged with this -* value whether or not the AST__USEBAD flag is set (the -* function return value indicates whether any such values have -* been produced). -* npix_out -* Number of pixels in output array. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the rebinned data will be returned. The -* storage order should be such that the index of the first grid -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the rebinned values may be returned. This array will only be -* used if the "in_var" array has been given. The values returned -* are estimates of the statistical variance of the corresponding -* values in the "out" array, on the assumption that all errors in -* input grid values (in the "in" array) are statistically independent -* and that their variance estimates (in the "in_var" array) may -* simply be summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* work -* An optional pointer to a double array with the same size as -* the "out" array. The contents of this array (if supplied) are -* incremented by the accumulated weights assigned to each output pixel. -* If no accumulated weights are required, a NULL pointer should be -* given. -* nused -* An optional pointer to a int64_t which will be incremented by the -* number of input values pasted into the output array. Ignored if NULL. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -*/ -/* Define macros to implement the function for a specific data - type. */ -#define MAKE_SPREAD_LINEAR(X,Xtype,IntType) \ -static void SpreadLinear##X( int ndim_out, \ - const int *lbnd_out, const int *ubnd_out, \ - const Xtype *in, const Xtype *in_var, \ - double infac, int npoint, const int *offset, \ - const double *const *coords, double conwgt, int flags, \ - Xtype badval, int npix_out, Xtype *out, \ - Xtype *out_var, double *work, int64_t *nused, \ - int *status ) { \ -\ -/* Local Variables: */ \ - Xtype c; /* Contribution to output value */ \ - Xtype in_val; /* Input value */ \ - double *frac_hi; /* Pointer to array of weights */ \ - double *frac_lo; /* Pointer to array of weights */ \ - double *wt; /* Pointer to array of weights */ \ - double *wtprod; /* Array of accumulated weights pointer */ \ - double *xn_max; /* Pointer to upper limits array (n-d) */ \ - double *xn_min; /* Pointer to lower limits array (n-d) */ \ - double frac_hi_x; /* Pixel weight (x dimension) */ \ - double frac_hi_y; /* Pixel weight (y dimension) */ \ - double frac_lo_x; /* Pixel weight (x dimension) */ \ - double frac_lo_y; /* Pixel weight (y dimension) */ \ - double pfac; /* Scaled pixel weight */ \ - double pixwt; /* Total pixel weight */ \ - double wgt; /* Weight for input value */ \ - double x; /* x coordinate value */ \ - double xmax; /* x upper limit */ \ - double xmin; /* x lower limit */ \ - double xn; /* Coordinate value (n-d) */ \ - double y; /* y coordinate value */ \ - double ymax; /* y upper limit */ \ - double ymin; /* y lower limit */ \ - int *dim; /* Pointer to array of pixel indices */ \ - int *hi; /* Pointer to array of upper indices */ \ - int *lo; /* Pointer to array of lower indices */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int done; /* All pixel indices done? */ \ - int genvar; /* Generate output variances? */ \ - int hi_x; /* Upper pixel index (x dimension) */ \ - int hi_y; /* Upper pixel index (y dimension) */ \ - int idim; /* Loop counter for dimensions */ \ - int ii; /* Loop counter for weights */ \ - int ixn; /* Pixel index (n-d) */ \ - int lo_x; /* Lower pixel index (x dimension) */ \ - int lo_y; /* Lower pixel index (y dimension) */ \ - int off; /* Total offset to input pixel */ \ - int off_in; /* Offset to input pixel */ \ - int off_lo; /* Offset to "first" input pixel */ \ - int off_out; /* Offset to output pixel */ \ - int point; /* Loop counter for output points */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int varwgt; /* Use input variances as weights? */ \ - int ystride; /* Stride along input grid y dimension */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Initialise variables to avoid "used of uninitialised variable" \ - messages from dumb compilers. */ \ - bad = 0; \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - usebad = flags & AST__USEBAD; \ - usevar = 0; \ - genvar = 0; \ - if( flags & AST__GENVAR ) { \ - genvar = out_var && work; \ - } else if( flags & AST__USEVAR ) { \ - usevar = in_var && out_var; \ - } \ - varwgt = ( flags & AST__VARWGT ) && in_var && work; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_out == 1 ) { \ -\ -/* Calculate the coordinate limits of the input grid. */ \ - xmin = (double) lbnd_out[ 0 ] - 0.5; \ - xmax = (double) ubnd_out[ 0 ] + 0.5; \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - LINEAR_1D(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - LINEAR_1D(X,Xtype,1,0,1,IntType,1) \ - } else { \ - LINEAR_1D(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - LINEAR_1D(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - LINEAR_1D(X,Xtype,0,0,1,IntType,1) \ - } else { \ - LINEAR_1D(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - LINEAR_1D(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - LINEAR_1D(X,Xtype,1,0,1,IntType,0) \ - } else { \ - LINEAR_1D(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - LINEAR_1D(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - LINEAR_1D(X,Xtype,0,0,1,IntType,0) \ - } else { \ - LINEAR_1D(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_out == 2 ) { \ -\ -/* Calculate the stride along the y dimension of the output grid. */ \ - ystride = ubnd_out[ 0 ] - lbnd_out[ 0 ] + 1; \ -\ -/* Calculate the coordinate limits of the output grid in each \ - dimension. */ \ - xmin = (double) lbnd_out[ 0 ] - 0.5; \ - xmax = (double) ubnd_out[ 0 ] + 0.5; \ - ymin = (double) lbnd_out[ 1 ] - 0.5; \ - ymax = (double) ubnd_out[ 1 ] + 0.5; \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - LINEAR_2D(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - LINEAR_2D(X,Xtype,1,0,1,IntType,1) \ - } else { \ - LINEAR_2D(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - LINEAR_2D(X,Xtype,0,1,0,IntType,1) \ - }else if ( genvar ) { \ - LINEAR_2D(X,Xtype,0,0,1,IntType,1) \ - } else { \ - LINEAR_2D(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - LINEAR_2D(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - LINEAR_2D(X,Xtype,1,0,1,IntType,0) \ - } else { \ - LINEAR_2D(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - LINEAR_2D(X,Xtype,0,1,0,IntType,0) \ - }else if ( genvar ) { \ - LINEAR_2D(X,Xtype,0,0,1,IntType,0) \ - } else { \ - LINEAR_2D(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - dim = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - frac_hi = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - frac_lo = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - hi = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - lo = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - wt = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - wtprod = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - xn_max = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - xn_min = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the output grid. */ \ - for ( s = 1, idim = 0; idim < ndim_out; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ -\ -/* Calculate the coordinate limits of the output grid in each \ - dimension. */ \ - xn_min[ idim ] = (double) lbnd_out[ idim ] - 0.5; \ - xn_max[ idim ] = (double) ubnd_out[ idim ] + 0.5; \ - } \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - LINEAR_ND(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - LINEAR_ND(X,Xtype,1,0,1,IntType,1) \ - } else { \ - LINEAR_ND(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - LINEAR_ND(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - LINEAR_ND(X,Xtype,0,0,1,IntType,1) \ - } else { \ - LINEAR_ND(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - LINEAR_ND(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - LINEAR_ND(X,Xtype,1,0,1,IntType,0) \ - } else { \ - LINEAR_ND(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - LINEAR_ND(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - LINEAR_ND(X,Xtype,0,0,1,IntType,0) \ - } else { \ - LINEAR_ND(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ - } \ -\ -/* Free the workspace. */ \ - dim = astFree( dim ); \ - frac_hi = astFree( frac_hi ); \ - frac_lo = astFree( frac_lo ); \ - hi = astFree( hi ); \ - lo = astFree( lo ); \ - stride = astFree( stride ); \ - wt = astFree( wt ); \ - wtprod = astFree( wtprod ); \ - xn_max = astFree( xn_max ); \ - xn_min = astFree( xn_min ); \ - } \ -\ -} - - - - - - -#define LINEAR_1D(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the output grid. Also test if it is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = bad || ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ -\ -/* If OK, obtain the indices along the output grid x dimension of the \ - two adjacent output pixels which will receive contributions from the \ - input pixel. Also obtain the fractional weight to be applied to each of \ - these pixels. */ \ - if ( !bad ) { \ - lo_x = (int) floor( x ); \ - hi_x = lo_x + 1; \ - frac_lo_x = (double) hi_x - x; \ - frac_hi_x = 1.0 - frac_lo_x; \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* Obtain the offset within the output array of the first pixel to be \ - updated (the one with the smaller index). */ \ - off_lo = lo_x - lbnd_out[ 0 ]; \ -\ -/* If we are using the input data variances as weights, calculate the \ - weight, and scale the fractions of each input pixel by the weight. */ \ - wgt = conwgt; \ - if( Varwgt ) wgt *= 1.0/in_var[ off_in ]; \ - frac_lo_x *= wgt; \ - frac_hi_x *= wgt; \ -\ -/* For each of the two pixels which may be updated, test if the pixel index \ - lies within the output grid. Where it does, update the output pixel \ - with the required fraction of the input pixel value. */ \ - if ( lo_x >= lbnd_out[ 0 ] ) { \ - pfac = frac_lo_x*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off_lo ] += CONV(IntType, c ); \ - if( work ) work[ off_lo ] += frac_lo_x; \ - if ( Usevar ) { \ - out_var[ off_lo ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && frac_lo_x != 0.0 ) { \ - out_var[ off_lo ] += c*c/frac_lo_x; \ - work[ off_lo + npix_out ] += frac_lo_x*frac_lo_x; \ - } \ - } \ - if ( hi_x <= ubnd_out[ 0 ] ) { \ - pfac = frac_hi_x*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off_lo + 1 ] += CONV(IntType, c ); \ - if( work ) work[ off_lo + 1 ] += frac_hi_x; \ - if ( Usevar ) { \ - out_var[ off_lo + 1 ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && frac_hi_x != 0.0 ) { \ - out_var[ off_lo + 1 ] += c*c/frac_hi_x; \ - work[ off_lo + 1 + npix_out ] += frac_hi_x*frac_hi_x; \ - } \ - } \ - } \ - } - - - - -#define LINEAR_2D(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Obtain the x coordinate of the current point and test if it lies \ - outside the output grid. Also test if it is bad. */ \ - y = coords[ 1 ][ point ]; \ - bad = bad || ( y < ymin ) || ( y >= ymax ) || ( y == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Similarly obtain and test the y coordinate. */ \ - x = coords[ 0 ][ point ]; \ - bad = bad || ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* If OK, obtain the indices along the output grid x dimension of the \ - two adjacent pixels which recieve contributions from the input pixel. \ - Also obtain the fractional weight to be applied to each of \ - these pixels. */ \ - lo_x = (int) floor( x ); \ - hi_x = lo_x + 1; \ - frac_lo_x = (double) hi_x - x; \ - frac_hi_x = 1.0 - frac_lo_x; \ -\ -/* Repeat this process for the y dimension. */ \ - lo_y = (int) floor( y ); \ - hi_y = lo_y + 1; \ - frac_lo_y = (double) hi_y - y; \ - frac_hi_y = 1.0 - frac_lo_y; \ -\ -/* If we are using the input data variances as weights, calculate the \ - weight, and scale the fractions of each input pixel by the weight. \ - Since the product of two fractions is always used to scale the input \ - data values, we use the square root of the reciprocal of the variance \ - as the weight (so that when the product of two fractions is taken, \ - the square roots multiply together to give the required 1/variance \ - weight). */ \ - wgt = conwgt; \ - if( Varwgt ) wgt *= 1.0/sqrt( in_var[ off_in ] ); \ - frac_lo_x *= wgt; \ - frac_hi_x *= wgt; \ - frac_lo_y *= wgt; \ - frac_hi_y *= wgt; \ -\ -/* Obtain the offset within the output array of the first pixel to be \ - updated (the one with the smaller index along both dimensions). */ \ - off_lo = lo_x - lbnd_out[ 0 ] + ystride * ( lo_y - lbnd_out[ 1 ] ); \ -\ -/* For each of the four pixels which may be updated, test if the pixel indices \ - lie within the output grid. Where they do, update the output pixel \ - with the required fraction of the input pixel value. */ \ - if ( lo_y >= lbnd_out[ 1 ] ) { \ - if ( lo_x >= lbnd_out[ 0 ] ) { \ - pixwt = frac_lo_x * frac_lo_y; \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off_lo ] += CONV(IntType, c ); \ - if( work ) work[ off_lo ] += pixwt; \ - if ( Usevar ) { \ - out_var[ off_lo ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off_lo ] += c*c/pixwt; \ - work[ off_lo + npix_out ] += pixwt*pixwt; \ - } \ - } \ - if ( hi_x <= ubnd_out[ 0 ] ) { \ - off = off_lo + 1; \ - pixwt = frac_hi_x * frac_lo_y; \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off ] += CONV(IntType, c ); \ - if( work ) work[ off ] += pixwt; \ - if ( Usevar ) { \ - out_var[ off ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off ] += c*c/pixwt; \ - work[ off + npix_out ] += pixwt*pixwt; \ - } \ - } \ - } \ - if ( hi_y <= ubnd_out[ 1 ] ) { \ - if ( lo_x >= lbnd_out[ 0 ] ) { \ - off = off_lo + ystride; \ - pixwt = frac_lo_x * frac_hi_y; \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off ] += CONV(IntType, c ); \ - if( work ) work[ off ] += pixwt; \ - if ( Usevar ) { \ - out_var[ off ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off ] += c*c/pixwt; \ - work[ off + npix_out ] += pixwt*pixwt; \ - } \ - } \ - if ( hi_x <= ubnd_out[ 0 ] ) { \ - off = off_lo + ystride + 1; \ - pixwt = frac_hi_x * frac_hi_y; \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off ] += CONV(IntType, c ); \ - if( work ) work[ off ] += pixwt; \ - if ( Usevar ) { \ - out_var[ off ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off ] += c*c/pixwt; \ - work[ off + npix_out ] += pixwt*pixwt; \ - } \ - } \ - } \ - } \ - } \ - } - - -#define LINEAR_ND(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Initialise offsets into the output array. Then loop to obtain each \ - coordinate associated with the current output point. */ \ - if( !bad ) { \ - off_out = 0; \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate lies outside the output grid. Also test if \ - it is bad. If either is true, the corresponding output pixel value \ - will be bad, so give up on this point. */ \ - bad = ( xn < xn_min[ idim ] ) || ( xn >= xn_max[ idim ] ) || \ - ( xn == AST__BAD ); \ - if ( bad ) break; \ -\ -/* Obtain the indices along the current dimension of the output grid of \ - the two (usually adjacent) pixels which will be updated. If necessary, \ - however, restrict each index to ensure it does not lie outside the \ - input grid. Also calculate the fractional weight to be given to each \ - pixel in order to divide the input value linearly between them. */ \ - ixn = (int) floor( xn ); \ - lo[ idim ] = MaxI( ixn, lbnd_out[ idim ], status ); \ - hi[ idim ] = MinI( ixn + 1, ubnd_out[ idim ], status ); \ - frac_lo[ idim ] = 1.0 - fabs( xn - (double) lo[ idim ] ); \ - frac_hi[ idim ] = 1.0 - fabs( xn - (double) hi[ idim ] ); \ -\ -/* Store the lower index involved in spreading along each \ - dimension and accumulate the offset from the start of the output \ - array of the pixel which has these indices. */ \ - dim[ idim ] = lo[ idim ]; \ - off_out += stride[ idim ] * ( lo[ idim ] - lbnd_out[ idim ] ); \ -\ -/* Also store the fractional weight associated with the lower pixel \ - along each dimension. */ \ - wt[ idim ] = frac_lo[ idim ]; \ - } \ -\ -/* If we are using the input data variances as weights, calculate the \ - weight, and scale the fractions of each input pixel by the weight. */ \ - wgt = conwgt; \ - if( Varwgt ) wgt *= pow( in_var[ off_in ], -1.0/(double)ndim_out ); \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - frac_lo[ idim ] *= wgt; \ - frac_hi[ idim ] *= wgt; \ - wt[ idim ] = frac_lo[ idim ]; \ - } \ -\ -/* If OK, increment the number of input pixels pasted into the output array. */ \ - if ( !bad ) { \ - if( nused ) (*nused)++; \ -\ -/* Loop over adjacent output pixels to divide up the input value. */ \ - idim = ndim_out - 1; \ - wtprod[ idim ] = 1.0; \ - done = 0; \ - do { \ -\ -/* Each pixel pixel to be updated has a total weight equal to the product \ - of the weights which account for the displacement of its centre from \ - the required position along each dimension. However, since we typically \ - only change the index of one dimension at a time, we can avoid forming \ - this product repeatedly by retaining an array of accumulated weight \ - products for all higher dimensions. We need then only update the \ - lower elements in this array, corresponding to those dimensions \ - whose index has changed. We do this here, "idim" being the index of \ - the most significant dimension to have changed. Note that on the \ - first pass, all dimensions are considered changed, causing this \ - array to be initialised. */ \ - for ( ii = idim; ii >= 1; ii-- ) { \ - wtprod[ ii - 1 ] = wtprod[ ii ] * wt[ ii ]; \ - } \ -\ -/* Update the relevent output pixel. The pixel weight is formed by including \ - the weight factor for dimension zero, since this is not included in \ - the "wtprod" array. */ \ - pixwt = wtprod[ 0 ] * wt[ 0 ]; \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ - out[ off_out ] += CONV(IntType, c ); \ - if( work ) work[ off_out ] += pixwt; \ - if ( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ - } else if ( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ -\ -/* Now update the indices, offset and weight factors to refer to the \ - next output pixel to be updated. */ \ - idim = 0; \ - do { \ -\ -/* The first input dimension which still refers to the pixel with the \ - lower of the two possible indices is switched to refer to the other \ - pixel (with the higher index). The offset into the output array and \ - the fractional weight factor for this dimension are also updated \ - accordingly. */ \ - if ( dim[ idim ] != hi[ idim ] ) { \ - dim[ idim ] = hi[ idim ]; \ - off_out += stride[ idim ]; \ - wt[ idim ] = frac_hi[ idim ]; \ - break; \ -\ -/* Any earlier dimensions (referring to the higher index) are switched \ - back to the lower index, if not already there, before going on to \ - consider the next dimension. (This process is the same as \ - incrementing a binary number and propagating overflows up through \ - successive digits, except that dimensions where the "lo" and "hi" \ - values are the same can only take one value.) The process stops at \ - the first attempt to return the final dimension to the lower \ - index. */ \ - } else { \ - if ( dim[ idim ] != lo[ idim ] ) { \ - dim[ idim ] = lo[ idim ]; \ - off_out -= stride[ idim ]; \ - wt[ idim ] = frac_lo[ idim ]; \ - } \ - done = ( ++idim == ndim_out ); \ - } \ - } while ( !done ); \ - } while ( !done ); \ - } \ - } \ - } - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_SPREAD_LINEAR(LD,long double,0) -#endif -MAKE_SPREAD_LINEAR(D,double,0) -MAKE_SPREAD_LINEAR(F,float,0) -MAKE_SPREAD_LINEAR(I,int,1) -MAKE_SPREAD_LINEAR(B,signed char,1) -MAKE_SPREAD_LINEAR(UB,unsigned char,1) - -/* Undefine the macros used above. */ -#undef LINEAR_1D -#undef LINEAR_2D -#undef LINEAR_ND -#undef MAKE_SPREAD_LINEAR - -/* -* Name: -* SpreadNearest<X> - -* Purpose: -* Rebin a data grid, using the nearest-pixel spreading scheme. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void SpreadNearest<X>( int ndim_out, const int *lbnd_out, -* const int *ubnd_out, const <Xtype> *in, -* const <Xtype> *in_var, double infac, int npoint, -* const int *offset, const double *const *coords, -* double conwgt, int flags, <Xtype> badval, int npix_out, <Xtype> *out, -* <Xtype> *out_var, double *work, int64_t *nused, -* int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This is a set of functions which rebins a rectangular region of an -* input grid of data (and, optionally, associated statistical variance -* values) so as to place them into a new output grid. Each input -* grid point may be mapped on to a position in the output grid in -* an arbitrary way. Where the positions given do not correspond -* with a pixel centre in the output grid, the spreading scheme -* used is simply to select the nearest pixel (i.e. the one whose -* bounds contain the supplied position). - -* Parameters: -* ndim_out -* The number of dimensions in the output grid. This should be at -* least one. -* lbnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the first -* pixel in the output grid along each dimension. -* ubnd_out -* Pointer to an array of integers, with "ndim_out" elements. -* This should give the coordinates of the centre of the last -* pixel in the output grid along each dimension. -* -* Note that "lbnd_out" and "ubnd_out" together define the shape -* and size of the output grid, its extent along a particular -* (i'th) dimension being ubnd_out[i]-lbnd_out[i]+1 (assuming "i" -* is zero-based). They also define the output grid's coordinate -* system, with each pixel being of unit extent along each -* dimension with integral coordinate values at its centre. -* in -* Pointer to the array of data to be rebinned. The numerical type -* of these data should match the function used, as given by the -* suffix on the function name. Note that details of how the input -* grid maps on to this array (e.g. the storage order, number of -* dimensions, etc.) is arbitrary and is specified entirely by means -* of the "offset" array. The "in" array should therefore contain -* sufficient elements to accommodate the "offset" values supplied. -* There is no requirement that all elements of the "in" array -* should be rebinned, and any which are not addressed by the -* contents of the "offset" array will be ignored. -* in_var -* An optional pointer to a second array of positive numerical -* values (with the same size and type as the "in" array), which -* represent estimates of the statistical variance associated -* with each element of the "in" array. If this second array is -* given (along with the corresponding "out_var" array), then -* estimates of the variance of the resampled data will also be -* returned. It is addressed in exactly the same way (via the -* "offset" array) as the "in" array. -* -* If no variance estimates are required, a NULL pointer should -* be given. -* infac -* A factor by which to multiply the input data values before use. -* npoint -* The number of input points which are to be rebinned. -* offset -* Pointer to an array of integers with "npoint" elements. For -* each input point, this array should contain the zero-based -* offset in the input array(s) (i.e. the "in" and, optionally, -* the "in_var" arrays) from which the value to be rebinned should -* be obtained. -* coords -* An array of pointers to double, with "ndim_out" elements. -* Element "coords[coord]" should point at the first element of -* an array of double (with "npoint" elements) which contains the -* values of coordinate number "coord" for each point being -* rebinned. The value of coordinate number "coord" for -* rebinning point number "point" is therefore given by -* "coords[coord][point]" (assuming both indices are -* zero-based). If any point has a coordinate value of AST__BAD -* associated with it, then the corresponding input data (and -* variance) value will be ignored. -* conwgt -* The initial weight to use for all pixels (typically 1.0). Other -* weights (e.g. interpolation weights, variance weights, etc) are -* applied as factors to this initial value. -* flags -* The bitwise OR of a set of flag values which control the -* operation of the function. These are chosen from: -* -* - AST__USEBAD: indicates whether there are "bad" (i.e. missing) data -* in the input array(s) which must be recognised. If this flag is not -* set, all input values are treated literally. -* - AST__GENVAR: Indicates that output variances should be generated -* from the spread of values contributing to each output pixel. -* - AST__USEVAR: Indicates that output variances should be generated -* by rebinning the input variances. -* - AST__VARWGT: Indicates that input variances should be used to -* create weights for the input data values. -* -* Only one of AST__GENVAR and AST__USEVAR should be supplied. -* badval -* If the AST__USEBAD flag is set in the "flags" value (above), -* this parameter specifies the value which is used to identify -* bad data and/or variance values in the input array(s). Its -* numerical type must match that of the "in" (and "in_var") -* arrays. The same value will also be used to flag any output -* array elements for which resampled values could not be -* obtained. The output arrays(s) may be flagged with this -* value whether or not the AST__USEBAD flag is set (the -* function return value indicates whether any such values have -* been produced). -* npix_out -* Number of pixels in output array. -* out -* Pointer to an array with the same data type as the "in" -* array, into which the rebinned data will be returned. The -* storage order should be such that the index of the first grid -* dimension varies most rapidly and that of the final dimension -* least rapidly (i.e. Fortran array storage order). -* out_var -* An optional pointer to an array with the same data type and -* size as the "out" array, into which variance estimates for -* the rebinned values may be returned. This array will only be -* used if the "in_var" array has been given. The values returned -* are estimates of the statistical variance of the corresponding -* values in the "out" array, on the assumption that all errors in -* input grid values (in the "in" array) are statistically independent -* and that their variance estimates (in the "in_var" array) may -* simply be summed (with appropriate weighting factors). -* -* If no output variance estimates are required, a NULL pointer -* should be given. -* work -* A pointer to an array with the same data type and size as the "out" -* array which is used as work space. The values in the supplied -* array are incremented on exit by the sum of the weights used -* with each output pixel. -* nused -* An optional pointer to a size_t which will be incremented by the -* number of input values pasted into the output array. Ignored if NULL. - -* Notes: -* - There is a separate function for each numerical type of -* gridded data, distinguished by replacing the <X> in the function -* name by the appropriate 1- or 2-character suffix. -*/ -/* Define a macro to implement the function for a specific data type. */ -#define MAKE_SPREAD_NEAREST(X,Xtype,IntType) \ -static void SpreadNearest##X( int ndim_out, \ - const int *lbnd_out, const int *ubnd_out, \ - const Xtype *in, const Xtype *in_var, \ - double infac, int npoint, const int *offset, \ - const double *const *coords, double conwgt, int flags, \ - Xtype badval, int npix_out, Xtype *out, \ - Xtype *out_var, double *work, int64_t *nused, \ - int *status ) { \ -\ -/* Local Variables: */ \ - Xtype c; /* Contribution to output value */ \ - Xtype in_val; /* Input data value */ \ - double *xn_max; /* Pointer to upper limits array (n-d) */ \ - double *xn_min; /* Pointer to lower limits array (n-d) */ \ - double pfac; /* Input weight with extra supplied factor */ \ - double pixwt; /* Weight for input value */ \ - double x; /* x coordinate value */ \ - double xmax; /* x upper limit */ \ - double xmin; /* x lower limit */ \ - double xn; /* Coordinate value (n-d) */ \ - double y; /* y coordinate value */ \ - double ymax; /* y upper limit */ \ - double ymin; /* y lower limit */ \ - int *stride; /* Pointer to array of dimension strides */ \ - int bad; /* Output pixel bad? */ \ - int genvar; /* Generate output variances? */ \ - int idim; /* Loop counter for dimensions */ \ - int ix; /* Number of pixels offset in x direction */ \ - int ixn; /* Number of pixels offset (n-d) */ \ - int iy; /* Number of pixels offset in y direction */ \ - int off_in; /* Pixel offset into input array */ \ - int off_out; /* Pixel offset into output array */ \ - int point; /* Loop counter for output points */ \ - int s; /* Temporary variable for strides */ \ - int usebad; /* Use "bad" input pixel values? */ \ - int usevar; /* Process variance array? */ \ - int varwgt; /* Use input variances as weights? */ \ - int ystride; /* Stride along input grid y direction */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Determine if we are processing bad pixels or variances. */ \ - usebad = flags & AST__USEBAD; \ - usevar = 0; \ - genvar = 0; \ - if( flags & AST__GENVAR ) { \ - genvar = out_var && work; \ - } else if( flags & AST__USEVAR ) { \ - usevar = in_var && out_var; \ - } \ - varwgt = ( flags & AST__VARWGT ) && in_var && work; \ -\ -/* Handle the 1-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - if ( ndim_out == 1 ) { \ -\ -/* Calculate the coordinate limits of the output array. */ \ - xmin = (double) lbnd_out[ 0 ] - 0.5; \ - xmax = (double) ubnd_out[ 0 ] + 0.5; \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - NEAR_1D(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - NEAR_1D(X,Xtype,1,0,1,IntType,1) \ - } else { \ - NEAR_1D(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - NEAR_1D(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - NEAR_1D(X,Xtype,0,0,1,IntType,1) \ - } else { \ - NEAR_1D(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - NEAR_1D(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - NEAR_1D(X,Xtype,1,0,1,IntType,0) \ - } else { \ - NEAR_1D(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - NEAR_1D(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - NEAR_1D(X,Xtype,0,0,1,IntType,0) \ - } else { \ - NEAR_1D(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Handle the 2-dimensional case optimally. */ \ -/* ---------------------------------------- */ \ - } else if ( ndim_out == 2 ) { \ -\ -/* Calculate the stride along the y dimension of the output grid. */ \ - ystride = ubnd_out[ 0 ] - lbnd_out[ 0 ] + 1; \ -\ -/* Calculate the coordinate limits of the output array in each \ - dimension. */ \ - xmin = (double) lbnd_out[ 0 ] - 0.5; \ - xmax = (double) ubnd_out[ 0 ] + 0.5; \ - ymin = (double) lbnd_out[ 1 ] - 0.5; \ - ymax = (double) ubnd_out[ 1 ] + 0.5; \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - NEAR_2D(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - NEAR_2D(X,Xtype,1,0,1,IntType,1) \ - } else { \ - NEAR_2D(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - NEAR_2D(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - NEAR_2D(X,Xtype,0,0,1,IntType,1) \ - } else { \ - NEAR_2D(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - NEAR_2D(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - NEAR_2D(X,Xtype,1,0,1,IntType,0) \ - } else { \ - NEAR_2D(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - NEAR_2D(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - NEAR_2D(X,Xtype,0,0,1,IntType,0) \ - } else { \ - NEAR_2D(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ -\ -/* Handle other numbers of dimensions. */ \ -/* ----------------------------------- */ \ - } else { \ -\ -/* Allocate workspace. */ \ - stride = astMalloc( sizeof( int ) * (size_t) ndim_out ); \ - xn_max = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - xn_min = astMalloc( sizeof( double ) * (size_t) ndim_out ); \ - if ( astOK ) { \ -\ -/* Calculate the stride along each dimension of the output grid. */ \ - for ( s = 1, idim = 0; idim < ndim_out; idim++ ) { \ - stride[ idim ] = s; \ - s *= ubnd_out[ idim ] - lbnd_out[ idim ] + 1; \ -\ -/* Calculate the coordinate limits of the output grid in each \ - dimension. */ \ - xn_min[ idim ] = (double) lbnd_out[ idim ] - 0.5; \ - xn_max[ idim ] = (double) ubnd_out[ idim ] + 0.5; \ - } \ -\ -/* Identify eight cases, according to whether bad pixels and/or variances \ - are being processed and/or used. In each case we assign constant values \ - (0 or 1) to the "Usebad", "Usevar" and "Varwgt" flags so that code for \ - handling bad pixels and variances can be eliminated by the compiler's \ - optimisation system when not required. */ \ - if( varwgt ) { \ - if ( usebad ) { \ - if ( usevar ) { \ - NEAR_ND(X,Xtype,1,1,0,IntType,1) \ - } else if ( genvar ) { \ - NEAR_ND(X,Xtype,1,0,1,IntType,1) \ - } else { \ - NEAR_ND(X,Xtype,1,0,0,IntType,1) \ - } \ - } else { \ - if ( usevar ) { \ - NEAR_ND(X,Xtype,0,1,0,IntType,1) \ - } else if ( genvar ) { \ - NEAR_ND(X,Xtype,0,0,1,IntType,1) \ - } else { \ - NEAR_ND(X,Xtype,0,0,0,IntType,1) \ - } \ - } \ - } else { \ - if ( usebad ) { \ - if ( usevar ) { \ - NEAR_ND(X,Xtype,1,1,0,IntType,0) \ - } else if ( genvar ) { \ - NEAR_ND(X,Xtype,1,0,1,IntType,0) \ - } else { \ - NEAR_ND(X,Xtype,1,0,0,IntType,0) \ - } \ - } else { \ - if ( usevar ) { \ - NEAR_ND(X,Xtype,0,1,0,IntType,0) \ - } else if ( genvar ) { \ - NEAR_ND(X,Xtype,0,0,1,IntType,0) \ - } else { \ - NEAR_ND(X,Xtype,0,0,0,IntType,0) \ - } \ - } \ - } \ - } \ -\ -/* Free the workspace. */ \ - stride = astFree( stride ); \ - xn_max = astFree( xn_max ); \ - xn_min = astFree( xn_min ); \ - } \ -\ -} - - - - - -#define NEAR_1D(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Obtain the output x coordinate corresponding to the centre of the \ - current input pixel and test if it lies outside the output grid, or \ - is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = bad || ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* If not, then obtain the offset within the output grid of the pixel \ - which contains the current input point. */ \ - off_out = (int) floor( x + 0.5 ) - lbnd_out[ 0 ]; \ -\ -/* If we are using the input data variances as weights, calculate the \ - weight. */ \ - pixwt = conwgt; \ - if( Varwgt ) pixwt *= 1.0/in_var[ off_in ]; \ -\ -/* Get the weighted input data value, including any extra scaling. */ \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ -\ -/* Increment the value of this output pixel by the weighted input pixel \ - value, and increment the sum of the weights. */ \ - out[ off_out ] += CONV(IntType, c ); \ - if( work ) work[ off_out ] += pixwt; \ -\ -/* If output variances are being calculated on the basis of the input \ - variances, then we also store the required sum in "out_var". */ \ - if( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ -\ -/* If output variances are being calculated on the basis of the spread of \ - input values, we need the sum of the squared weighted data values, the \ - sum of the weights (already in the first half of the "work" array), and \ - the sum of the squared weights. */ \ - } else if( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ - } \ - } - - - - - - -#define NEAR_2D(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ -/* Obtain the output y coordinate corresponding to the centre of the \ - current input pixel and test if it lies outside the output grid, or \ - is bad. */ \ - y = coords[ 1 ][ point ]; \ - bad = bad || ( y < ymin ) || ( y >= ymax ) || ( y == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Obtain the output x coordinate corresponding to the centre of the \ - current input pixel and test if it lies outside the output grid, or \ - is bad. */ \ - x = coords[ 0 ][ point ]; \ - bad = bad || ( x < xmin ) || ( x >= xmax ) || ( x == AST__BAD ); \ - if ( !bad ) { \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* Obtain the offsets along each output grid dimension of the output \ - pixel which is to receive the input pixel value. */ \ - ix = (int) floor( x + 0.5 ) - lbnd_out[ 0 ]; \ - iy = (int) floor( y + 0.5 ) - lbnd_out[ 1 ]; \ -\ -/* Calculate this pixel's offset from the start of the output array. */ \ - off_out = ix + ystride * iy; \ -\ -/* If we are using the input data variances as weights, calculate the \ - weight. */ \ - pixwt = conwgt; \ - if( Varwgt ) pixwt *= 1.0/in_var[ off_in ]; \ -\ -/* Get the weighted input data value, including any extra scaling. */ \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ -\ -/* Increment the value of this output pixel by the weighted input pixel \ - value, and increment the sum of the weights. */ \ - out[ off_out ] += CONV(IntType, c ); \ - if( work ) work[ off_out ] += pixwt; \ -\ -/* If output variances are being calculated on the basis of the input \ - variances, then we also store the required sum in "out_var". */ \ - if( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ -\ -/* If output variances are being calculated on the basis of the spread of \ - input values, we need the sum of the squared weighted data values, the \ - sum of the weights (already in the first half of the "work" array), and \ - the sum of the squared weights. */ \ - } else if( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ - } \ - } \ - } - - - -#define NEAR_ND(X,Xtype,Usebad,Usevar,Genvar,IntType,Varwgt) \ -\ -/* Loop round all input points which are to be rebinned. */ \ - for( point = 0; point < npoint; point++ ) { \ -\ -/* Obtain the input data value which is to be added into the output array. */ \ - off_in = offset[ point ]; \ - in_val = in[ off_in ]; \ -\ -/* If necessary, test if the input data value or variance is bad. If we \ - are using the reciprocal of the input variances as weights, then \ - variance values of zero are also effectively bad (but we can use input \ - variances of zero otherwise). */ \ - if ( Usebad ) { \ - bad = ( in_val == badval ); \ - if ( Varwgt ) { \ - bad = bad || ( in_var[ off_in ] == badval ) \ - || ( in_var[ off_in ] <= 0.0 ); \ - } else if ( Usevar ) { \ - bad = bad || ( in_var[ off_in ] == badval ); \ - } \ - } else { \ - if ( Varwgt ) { \ - bad = ( in_var[ off_in ] <= 0.0 ); \ - } else { \ - bad = 0; \ - } \ - } \ -\ - if( !bad ) { \ -\ -/* Initialise the offset into the output array. Then loop to obtain \ - each coordinate associated with the current output point. */ \ - off_out = 0; \ - for ( idim = 0; idim < ndim_out; idim++ ) { \ - xn = coords[ idim ][ point ]; \ -\ -/* Test if the coordinate lies outside the output grid, or is bad. If \ - either is true, the corresponding input pixel value will be ignored, \ - so give up on this point. */ \ - bad = ( xn < xn_min[ idim ] ) || ( xn >= xn_max[ idim ] ) || \ - ( xn == AST__BAD ); \ - if ( bad ) { \ - break; \ - } \ -\ -/* Obtain the offset along the current output grid dimension of the \ - output pixel which is to receive the input pixel value. */ \ - ixn = (int) floor( xn + 0.5 ) - lbnd_out[ idim ]; \ -\ -/* Accumulate this pixel's offset from the start of the output array. */ \ - off_out += ixn * stride[ idim ]; \ - } \ -\ - if( !bad ) { \ -\ -/* Increment the number of input pixels pasted into the output array. */ \ - if( nused ) (*nused)++; \ -\ -/* If we are using the input data variances as weights, calculate the \ - weight. */ \ - pixwt = conwgt; \ - if( Varwgt ) pixwt *= 1.0/in_var[ off_in ]; \ -\ -/* Get the weighted input data value, including any extra scaling. */ \ - pfac = pixwt*infac; \ - c = CONV(IntType,pfac*in_val); \ -\ -/* Increment the value of this output pixel by the weighted input pixel \ - value, and increment the sum of the weights. */ \ - out[ off_out ] += CONV(IntType, c ); \ - if( work ) work[ off_out ] += pixwt; \ -\ -/* If output variances are being calculated on the basis of the input \ - variances, then we also store the required sum in "out_var". */ \ - if( Usevar ) { \ - out_var[ off_out ] += CONV(IntType,in_var[ off_in ]*pfac*pfac); \ -\ -/* If output variances are being calculated on the basis of the spread of \ - input values, we need the sum of the squared weighted data values, the \ - sum of the weights (already in the first half of the "work" array), and \ - the sum of the squared weights. */ \ - } else if( Genvar && pixwt != 0.0 ) { \ - out_var[ off_out ] += c*c/pixwt; \ - work[ off_out + npix_out ] += pixwt*pixwt; \ - } \ - } \ - } \ - } - - - - - - -/* Expand the main macro above to generate a function for each - required signed data type. */ -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_SPREAD_NEAREST(LD,long double,0) -#endif - -MAKE_SPREAD_NEAREST(D,double,0) -MAKE_SPREAD_NEAREST(F,float,0) -MAKE_SPREAD_NEAREST(I,int,1) -MAKE_SPREAD_NEAREST(B,signed char,1) -MAKE_SPREAD_NEAREST(UB,unsigned char,1) - -/* Undefine the macros used above. */ -#undef NEAR_ND -#undef NEAR_2D -#undef NEAR_1D -#undef MAKE_SPREAD_NEAREST - - - - - - -static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* TestAttrib - -* Purpose: -* Test if a specified attribute value is set for a Mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* int TestAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* Mapping member function (over-rides the astTestAttrib protected -* method inherited from the Object class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* a value has been set for one of a Mapping's attributes. - -* Parameters: -* this -* Pointer to the Mapping. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if a value has been set, otherwise zero. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstMapping *this; /* Pointer to the Mapping structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the Mapping structure. */ - this = (AstMapping *) this_object; - -/* Check the attribute name and test the appropriate attribute. */ - -/* Invert. */ -/* ------- */ - if ( !strcmp( attrib, "invert" ) ) { - result = astTestInvert( this ); - -/* Report. */ -/* ------- */ - } else if ( !strcmp( attrib, "report" ) ) { - result = astTestReport( this ); - -/* If the name is not recognised, test if it matches any of the - read-only attributes of this class. If it does, then return - zero. */ - } else if ( !strcmp( attrib, "nin" ) || - !strcmp( attrib, "islinear" ) || - !strcmp( attrib, "issimple" ) || - !strcmp( attrib, "nout" ) || - !strcmp( attrib, "tranforward" ) || - !strcmp( attrib, "traninverse" ) ) { - result = 0; - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_testattrib)( this_object, attrib, status ); - } - -/* Return the result, */ - return result; -} - -static void Tran1( AstMapping *this, int npoint, const double xin[], - int forward, double xout[], int *status ) { -/* -*++ -* Name: -c astTran1 -f AST_TRAN1 - -* Purpose: -* Transform 1-dimensional coordinates. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astTran1( AstMapping *this, int npoint, const double xin[], -c int forward, double xout[] ) -f CALL AST_TRAN1( THIS, NPOINT, XIN, FORWARD, XOUT, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function applies a Mapping to transform the coordinates of -f This routine applies a Mapping to transform the coordinates of -* a set of points in one dimension. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping to be applied. -c npoint -f NPOINT = INTEGER (Given) -* The number of points to be transformed. -c xin -f XIN( NPOINT ) = DOUBLE PRECISION (Given) -c An array of "npoint" coordinate values for the input -f An array of coordinate values for the input -* (untransformed) points. -c forward -f FORWARD = LOGICAL (Given) -c A non-zero value indicates that the Mapping's forward -c coordinate transformation is to be applied, while a zero -c value indicates that the inverse transformation should be -c used. -f A .TRUE. value indicates that the Mapping's forward -f coordinate transformation is to be applied, while a .FALSE. -f value indicates that the inverse transformation should be -f used. -c xout -f XOUT( NPOINT ) = DOUBLE PRECISION (Returned) -c An array (with "npoint" elements) into which the -f An array into which the -* coordinates of the output (transformed) points will be written. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -* - The Mapping supplied must have the value 1 for both its Nin -* and Nout attributes. -*-- -*/ - -/* Local Variables: */ - AstPointSet *in_points; /* Pointer to input PointSet */ - AstPointSet *out_points; /* Pointer to output PointSet */ - const double *in_ptr[ 1 ]; /* Array of input data pointers */ - double *out_ptr[ 1 ]; /* Array of output data pointers */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Validate the Mapping and numbers of points/coordinates. */ - ValidateMapping( this, forward, npoint, 1, 1, "astTran1", status ); - -/* Set up pointers to the input and output coordinate arrays. */ - if ( astOK ) { - in_ptr[ 0 ] = xin; - out_ptr[ 0 ] = xout; - -/* Create PointSets to describe the input and output points. */ - in_points = astPointSet( npoint, 1, "", status ); - out_points = astPointSet( npoint, 1, "", status ); - -/* Associate the data pointers with the PointSets (note we must - explicitly remove the "const" qualifier from the input data here, - although they will not be modified). */ - astSetPoints( in_points, (double **) in_ptr ); - astSetPoints( out_points, out_ptr ); - -/* Apply the required transformation to the coordinates. */ - (void) astTransform( this, in_points, forward, out_points ); - -/* If the Mapping's Report attribute is set, report the effect the - Mapping has had on the coordinates. */ - if ( astGetReport( this ) ) astReportPoints( this, forward, - in_points, out_points ); - -/* Delete the two PointSets. */ - in_points = astDelete( in_points ); - out_points = astDelete( out_points ); - } -} - -static void Tran2( AstMapping *this, - int npoint, const double xin[], const double yin[], - int forward, double xout[], double yout[], int *status ) { -/* -*++ -* Name: -c astTran2 -f AST_TRAN2 - -* Purpose: -* Transform 2-dimensional coordinates. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astTran2( AstMapping *this, -c int npoint, const double xin[], const double yin[], -c int forward, double xout[], double yout[] ) -f CALL AST_TRAN2( THIS, NPOINT, XIN, YIN, FORWARD, XOUT, YOUT, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function applies a Mapping to transform the coordinates of -f This routine applies a Mapping to transform the coordinates of -* a set of points in two dimensions. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping to be applied. -c npoint -f NPOINT = INTEGER (Given) -* The number of points to be transformed. -c xin -f XIN( NPOINT ) = DOUBLE PRECISION (Given) -c An array of "npoint" X-coordinate values for the input -f An array of X-coordinate values for the input -* (untransformed) points. -c yin -f YIN( NPOINT ) = DOUBLE PRECISION (Given) -c An array of "npoint" Y-coordinate values for the input -f An array of Y-coordinate values for the input -* (untransformed) points. -c forward -f FORWARD = LOGICAL (Given) -c A non-zero value indicates that the Mapping's forward -c coordinate transformation is to be applied, while a zero -c value indicates that the inverse transformation should be -c used. -f A .TRUE. value indicates that the Mapping's forward -f coordinate transformation is to be applied, while a .FALSE. -f value indicates that the inverse transformation should be -f used. -c xout -f XOUT( NPOINT ) = DOUBLE PRECISION (Returned) -c An array (with "npoint" elements) into which the -f An array into which the -* X-coordinates of the output (transformed) points will be written. -c yout -f YOUT( NPOINT ) = DOUBLE PRECISION (Returned) -c An array (with "npoint" elements) into which the -f An array into which the -* Y-coordinates of the output (transformed) points will be written. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -* - The Mapping supplied must have the value 2 for both its Nin -* and Nout attributes. -*-- -*/ - -/* Local Variables: */ - AstPointSet *in_points; /* Pointer to input PointSet */ - AstPointSet *out_points; /* Pointer to output PointSet */ - const double *in_ptr[ 2 ]; /* Array of input data pointers */ - double *out_ptr[ 2 ]; /* Array of output data pointers */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Validate the Mapping and the numbers of points/coordinates. */ - ValidateMapping( this, forward, npoint, 2, 2, "astTran2", status ); - -/* Set up pointers to the input and output coordinate arrays. */ - if ( astOK ) { - in_ptr[ 0 ] = xin; - in_ptr[ 1 ] = yin; - out_ptr[ 0 ] = xout; - out_ptr[ 1 ] = yout; - -/* Create PointSets to describe the input and output points. */ - in_points = astPointSet( npoint, 2, "", status ); - out_points = astPointSet( npoint, 2, "", status ); - -/* Associate the data pointers with the PointSets (note we must - explicitly remove the "const" qualifier from the input data here, - although they will not be modified). */ - astSetPoints( in_points, (double **) in_ptr ); - astSetPoints( out_points, out_ptr ); - -/* Apply the required transformation to the coordinates. */ - (void) astTransform( this, in_points, forward, out_points ); - -/* If the Mapping's Report attribute is set, report the effect the - Mapping has had on the coordinates. */ - if ( astGetReport( this ) ) astReportPoints( this, forward, - in_points, out_points ); - -/* Delete the two PointSets. */ - in_points = astDelete( in_points ); - out_points = astDelete( out_points ); - } -} - -static void TranGrid( AstMapping *this, int ncoord_in, const int lbnd[], - const int ubnd[], double tol, int maxpix, int forward, - int ncoord_out, int outdim, double *out, int *status ) { -/* -*++ -* Name: -c astTranGrid -f AST_TRANGRID - -* Purpose: -* Transform a grid of positions - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astTranGrid( AstMapping *this, int ncoord_in, -c const int lbnd[], const int ubnd[], -c double tol, int maxpix, int forward, -c int ncoord_out, int outdim, double *out ); -f CALL AST_TRANGRID( THIS, NCOORD_IN, LBND, UBND, TOL, MAXPIX, -f FORWARD, NCOORD_OUT, OUTDIM, OUT, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -* This function uses the supplied Mapping to transforms a regular square -* grid of points covering a specified box. It attempts to do this -* quickly by first approximating the Mapping with a linear transformation -* applied over the whole region of the input grid which is being used. -* If this proves to be insufficiently accurate, the input region is -* sub-divided into two along its largest dimension and the process is -* repeated within each of the resulting sub-regions. This process of -* sub-division continues until a sufficiently good linear approximation -* is found, or the region to which it is being applied becomes too small -* (in which case the original Mapping is used directly). - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping to be applied. -c ncoord_in -f NCOORD_IN = INTEGER (Given) -* The number of coordinates being supplied for each box corner -* (i.e. the number of dimensions of the space in which the -* input points reside). -c lbnd -f LBND( NCOORD_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ncoord_in" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the input grid along each dimension. -c ubnd -f UBND( NCOORD_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ncoord_in" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the input grid along each dimension. -* -c Note that "lbnd" and "ubnd" together define the shape -f Note that LBND and UBND together define the shape -* and size of the input grid, its extent along a particular -c (j'th) dimension being ubnd[j]-lbnd[j]+1 (assuming the -c index "j" to be zero-based). They also define -f (J'th) dimension being UBND(J)-LBND(J)+1. They also define -* the input grid's coordinate system, each pixel having unit -* extent along each dimension with integral coordinate values -* at its centre. -c tol -f TOL = DOUBLE PRECISION (Given) -* The maximum tolerable geometrical distortion which may be -* introduced as a result of approximating non-linear Mappings -* by a set of piece-wise linear transformations. This should be -* expressed as a displacement within the output coordinate system -* of the Mapping. -* -* If piece-wise linear approximation is not required, a value -* of zero may be given. This will ensure that the Mapping is -* used without any approximation, but may increase execution -* time. -* -* If the value is too high, discontinuities between the linear -* approximations used in adjacent panel will be higher. If this -* is a problem, reduce the tolerance value used. -c maxpix -f MAXPIX = INTEGER (Given) -* A value which specifies an initial scale size (in input grid points) -* for the adaptive algorithm which approximates non-linear Mappings -* with piece-wise linear transformations. Normally, this should -* be a large value (larger than any dimension of the region of -* the input grid being used). In this case, a first attempt to -* approximate the Mapping by a linear transformation will be -* made over the entire input region. -* -* If a smaller value is used, the input region will first be -c divided into sub-regions whose size does not exceed "maxpix" -f divided into sub-regions whose size does not exceed MAXPIX -* grid points in any dimension. Only at this point will attempts -* at approximation commence. -* -* This value may occasionally be useful in preventing false -* convergence of the adaptive algorithm in cases where the -* Mapping appears approximately linear on large scales, but has -* irregularities (e.g. holes) on smaller scales. A value of, -* say, 50 to 100 grid points can also be employed as a safeguard -* in general-purpose software, since the effect on performance is -* minimal. -* -* If too small a value is given, it will have the effect of -* inhibiting linear approximation altogether (equivalent to -c setting "tol" to zero). Although this may degrade -f setting TOL to zero). Although this may degrade -* performance, accurate results will still be obtained. -c forward -f FORWARD = LOGICAL (Given) -c A non-zero value indicates that the Mapping's forward -c coordinate transformation is to be applied, while a zero -c value indicates that the inverse transformation should be -c used. -f A .TRUE. value indicates that the Mapping's forward -f coordinate transformation is to be applied, while a .FALSE. -f value indicates that the inverse transformation should be -f used. -c ncoord_out -f NCOORD_OUT = INTEGER (Given) -* The number of coordinates being generated by the Mapping for -* each output point (i.e. the number of dimensions of the -* space in which the output points reside). This need not be -c the same as "ncoord_in". -f the same as NCOORD_IN. -c outdim -f OUTDIM = INTEGER (Given) -c The number of elements along the second dimension of the "out" -f The number of elements along the first dimension of the OUT -* array (which will contain the output coordinates). The value -* given should not be less than the number of points in the grid. -c out -f OUT( OUTDIM, NCOORD_OUT ) = DOUBLE PRECISION (Returned) -c The address of the first element in a 2-dimensional array of -c shape "[ncoord_out][outdim]", into -c which the coordinates of the output (transformed) points will -c be written. These will be stored such that the value of -c coordinate number "coord" for output point number "point" -c will be found in element "out[coord][point]". -f An array into which the coordinates of the output -f (transformed) points will be written. These will be stored -f such that the value of coordinate number COORD for output -f point number POINT will be found in element OUT(POINT,COORD). -* The points are ordered such that the first axis of the input -* grid changes most rapidly. For example, if the input grid is -* 2-dimensional and extends from (2,-1) to (3,1), the output -* points will be stored in the order (2,-1), (3, -1), (2,0), (3,0), -* (2,1), (3,1). -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -c - If the forward coordinate transformation is being applied, the -c Mapping supplied must have the value of "ncoord_in" for its Nin -c attribute and the value of "ncoord_out" for its Nout attribute. If -c the inverse transformation is being applied, these values should -c be reversed. -f - If the forward coordinate transformation is being applied, the -f Mapping supplied must have the value of NCOORD_IN for its Nin -f attribute and the value of NCOORD_OUT for its Nout attribute. If -f the inverse transformation is being applied, these values should -f be reversed. -*-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific data */ - AstMapping *simple; /* Pointer to simplified Mapping */ - double **out_ptr; /* Pointer to array of output data pointers */ - int coord; /* Loop counter for coordinates */ - int idim; /* Loop counter for coordinate dimensions */ - int npoint; /* Number of points in the grid */ - int64_t mpix; /* Number of points for testing */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to a structure holding thread-specific global data values */ - astGET_GLOBALS(this); - -/* Calculate the number of points in the grid, and check that the lower and - upper bounds of the input grid are consistent. Report an error if any - pair is not. */ - mpix = 1; - for ( idim = 0; idim < ncoord_in; idim++ ) { - if ( lbnd[ idim ] > ubnd[ idim ] ) { - astError( AST__GBDIN, "astTranGrid(%s): Lower bound of " - "input grid (%d) exceeds corresponding upper bound " - "(%d).", status, astGetClass( this ), - lbnd[ idim ], ubnd[ idim ] ); - astError( AST__GBDIN, "Error in input dimension %d.", status, - idim + 1 ); - break; - } else { - mpix *= ubnd[ idim ] - lbnd[ idim ] + 1; - } - } - -/* Report an error if there are too many pixels in the input. */ - npoint = mpix; - if ( astOK && npoint != mpix ) { - astError( AST__EXSPIX, "astTranGrid(%s): Supplied grid " - "contains too many points (%g): must be fewer than %d.", - status, astGetClass( this ), (double) mpix, INT_MAX/ncoord_out ); - } - - mpix = outdim*ncoord_out; - if ( astOK && (int) mpix != mpix ) { - astError( AST__EXSPIX, "astTranGrid(%s): Supplied output array " - "contains too many pixels (%g): must be fewer than %d.", - status, astGetClass( this ), (double) mpix, INT_MAX ); - } - - -/* Validate the mapping and numbers of points/coordinates. */ - ValidateMapping( this, forward, npoint, ncoord_in, ncoord_out, - "astTranGrid", status ); - -/* Check that the positional accuracy tolerance supplied is valid and - report an error if necessary. */ - if ( astOK && ( tol < 0.0 ) ) { - astError( AST__PATIN, "astTranGrid(%s): Invalid positional " - "accuracy tolerance (%.*g pixel).", status, - astGetClass( this ), AST__DBL_DIG, tol ); - astError( AST__PATIN, "This value should not be less than zero." , status); - } - -/* Check that the initial scale size in grid points supplied is valid and - report an error if necessary. */ - if ( astOK && ( maxpix < 0 ) ) { - astError( AST__SSPIN, "astTranGrid(%s): Invalid initial scale " - "size in grid points (%d).", status, astGetClass( this ), maxpix ); - astError( AST__SSPIN, "This value should not be less than zero." , status); - } - -/* Validate the output array dimension argument. */ - if ( astOK && ( outdim < npoint ) ) { - astError( AST__DIMIN, "astTranGrid(%s): The output array dimension value " - "(%d) is invalid.", status, astGetClass( this ), outdim ); - astError( AST__DIMIN, "This should not be less than the number of " - "grid points being transformed (%d).", status, npoint ); - } - -/* If there are sufficient pixels to make it worthwhile, simplify the - Mapping supplied to improve performance. Otherwise, just clone the - Mapping pointer. Note we save a pointer to the original Mapping so - that lower-level functions can use it if they need to report an error. */ - simple = NULL; - unsimplified_mapping = this; - if ( astOK ) { - if ( npoint > 1024 ) { - simple = astSimplify( this ); - -/* Report an error if the required transformation of this simplified - Mapping is not defined. */ - if( astOK ) { - if ( forward && !astGetTranForward( simple ) ) { - astError( AST__TRNND, "astTranGrid(%s): A forward coordinate " - "transformation is not defined by the %s supplied.", status, - astGetClass( unsimplified_mapping ), - astGetClass( unsimplified_mapping ) ); - } else if ( !forward && !astGetTranInverse( simple ) ) { - astError( AST__TRNND, "astTranGrid(%s): An inverse coordinate " - "transformation is not defined by the %s supplied.", status, - astGetClass( unsimplified_mapping ), - astGetClass( unsimplified_mapping ) ); - } - } - - } else { - simple = astClone( this ); - } - -/* Allocate memory to hold the array of output data pointers. */ - out_ptr = astMalloc( sizeof( double * ) * (size_t) ncoord_out ); - -/* Initialise the output data pointers to point into the "out" array. */ - if ( astOK ) { - for ( coord = 0; coord < ncoord_out; coord++ ) { - out_ptr[ coord ] = out + coord * outdim; - } - -/* If required, temporarily invert the Mapping. */ - if( !forward ) astInvert( simple ); - -/* Perform the transformation. */ - TranGridAdaptively( simple, ncoord_in, lbnd, ubnd, lbnd, ubnd, tol, - maxpix, ncoord_out, out_ptr, status ); - -/* If required, uninvert the Mapping. */ - if( !forward ) astInvert( simple ); - - } - -/* Free the memory used for the data pointers. */ - out_ptr = astFree( out_ptr ); - -/* Annul the pointer to the simplified/cloned Mapping. */ - simple = astAnnul( simple ); - } -} - -static void TranGridAdaptively( AstMapping *this, int ncoord_in, - const int *lbnd_in, const int *ubnd_in, - const int lbnd[], const int ubnd[], - double tol, int maxpix, int ncoord_out, - double *out[], int *status ){ -/* -* Name: -* TranGridAdaptively - -* Purpose: -* Transform grid positions adaptively. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void TranGridAdaptively( AstMapping *this, int ncoord_in, -* const int *lbnd_in, const int *ubnd_in, -* const int lbnd[], const int ubnd[], -* double tol, int maxpix, int ncoord_out, -* double *out[] ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function transforms grid points within a specified section of a -* rectangular grid (with any number of dimensions) using the forward -* transformation of the specified Mapping. -* -* This function is very similar to TranGridWithBlocking and TranGridSection -* which lie below it in the calling hierarchy. However, this function -* also attempts to adapt to the Mapping supplied and to sub-divide the -* section being transformed into smaller sections within which a linear -* approximation to the Mapping may be used. This reduces the number of -* Mapping evaluations, thereby improving efficiency particularly when -* complicated Mappings are involved. - -* Parameters: -* this -* Pointer to the Mapping to be applied. The forward transformation -* is used. -* ncoord_in -* The number of coordinates being supplied for each box corner -* (i.e. the number of dimensions of the space in which the -* input points reside). -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the whole input grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* lbnd -* Pointer to an array of integers, with "ncoord_in" elements, -* containing the coordinates of the centre of the first pixel -* in the input grid along each dimension. -* ubnd -* Pointer to an array of integers, with "ncoord_in" elements, -* containing the coordinates of the centre of the last pixel in -* the input grid along each dimension. -* -* Note that "lbnd" and "ubnd" together define the shape -* and size of the input grid, its extent along a particular -* (j'th) dimension being ubnd[j]-lbnd[j]+1 (assuming the -* index "j" to be zero-based). They also define -* the input grid's coordinate system, each pixel having unit -* extent along each dimension with integral coordinate values -* at its centre. -* tol -* The maximum tolerable geometrical distortion which may be -* introduced as a result of approximating non-linear Mappings -* by a set of piece-wise linear transformations. This should be -* expressed as a displacement in pixels in the output grid's -* coordinate system. -* -* If piece-wise linear approximation is not required, a value -* of zero may be given. This will ensure that the Mapping is -* used without any approximation, but may increase execution -* time. -* -* If the value is too high, discontinuities between the linear -* approximations used in adjacent panel will be higher. If this -* is a problem, reduce the tolerance value used. -* maxpix -* A value which specifies an initial scale size (in grid points) -* for the adaptive algorithm which approximates non-linear Mappings -* with piece-wise linear transformations. Normally, this should -* be a large value (larger than any dimension of the region of -* the input grid being used). In this case, a first attempt to -* approximate the Mapping by a linear transformation will be -* made over the entire input region. -* -* If a smaller value is used, the input region will first be -* divided into sub-regions whose size does not exceed "maxpix" -* grid points in any dimension. Only at this point will attempts -* at approximation commence. -* -* This value may occasionally be useful in preventing false -* convergence of the adaptive algorithm in cases where the -* Mapping appears approximately linear on large scales, but has -* irregularities (e.g. holes) on smaller scales. A value of, -* say, 50 to 100 grid points can also be employed as a safeguard -* in general-purpose software, since the effect on performance is -* minimal. -* -* If too small a value is given, it will have the effect of -* inhibiting linear approximation altogether (equivalent to -* setting "tol" to zero). Although this may degrade -* performance, accurate results will still be obtained. -* ncoord_out -* The number of dimensions of the space in which the output points -* reside. -* out -* Pointer to an array with "ndim_out" elements. Element [i] of -* this array is a pointer to an array in which to store the -* transformed values for output axis "i". The points are ordered -* such that the first axis of the input grid changes most rapidly. -* For example, if the input grid is 2-dimensional and extends from -* (2,-1) to (3,1), the output points will be stored in the order -* (2,-1), (3, -1), (2,0), (3,0), (2,1), (3,1). - -*/ - -/* Local Variables: */ - double *flbnd; /* Array holding floating point lower bounds */ - double *fubnd; /* Array holding floating point upper bounds */ - double *linear_fit; /* Pointer to array of fit coefficients */ - int *hi; /* Pointer to array of section upper bounds */ - int *lo; /* Pointer to array of section lower bounds */ - int coord_in; /* Loop counter for input coordinates */ - int dim; /* Output section dimension size */ - int dimx; /* Dimension with maximum section extent */ - int divide; /* Sub-divide the output section? */ - int i; /* Loop count */ - int isLinear; /* Is the transformation linear? */ - int mxdim; /* Largest output section dimension size */ - int npix; /* Number of pixels in output section */ - int npoint; /* Number of points for obtaining a fit */ - int nvertex; /* Number of vertices of output section */ - int toobig; /* Section too big (must sub-divide)? */ - int toosmall; /* Section too small to sub-divide? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Further initialisation. */ - npix = 1; - mxdim = 0; - dimx = 1; - nvertex = 1; - -/* Loop through the input grid dimensions. */ - for ( coord_in = 0; coord_in < ncoord_in; coord_in++ ) { - -/* Obtain the extent in each dimension of the input section which is - to be rebinned, and calculate the total number of pixels it contains. */ - dim = ubnd[ coord_in ] - lbnd[ coord_in ] + 1; - npix *= dim; - -/* Find the maximum dimension size of this input section and note which - dimension has this size. */ - if ( dim > mxdim ) { - mxdim = dim; - dimx = coord_in; - } - -/* Calculate how many vertices the output section has. */ - nvertex *= 2; - } - -/* Calculate how many sample points will be needed (by the astLinearApprox - function) to obtain a linear fit to the Mapping's forward transformation. */ - npoint = 1 + 4 * ncoord_in + 2 * nvertex; - -/* If the number of pixels in the input section is not at least 4 - times this number, we will probably not save significant time by - attempting to obtain a linear fit, so note that the input section - is too small. */ - toosmall = ( npix < ( 4 * npoint ) ); - -/* Note if the maximum dimension of the input section exceeds the - user-supplied scale factor. */ - toobig = ( maxpix < mxdim ); - -/* Assume the Mapping is significantly non-linear before deciding - whether to sub-divide the output section. */ - linear_fit = NULL; - -/* If the output section is too small to be worth obtaining a linear - fit, or if the accuracy tolerance is zero, we will not - sub-divide. This means that the Mapping will be used to transform - each pixel's coordinates and no linear approximation will be - used. */ - if ( toosmall || ( tol == 0.0 ) ) { - divide = 0; - -/* Otherwise, if the largest input section dimension exceeds the - scale length given, we will sub-divide. This offers the possibility - of obtaining a linear approximation to the Mapping over a reduced - range of input coordinates (which will be handled by a recursive - invocation of this function). */ - } else if ( toobig ) { - divide = 1; - -/* If neither of the above apply, then attempt to fit a linear - approximation to the forward transformation of the Mapping over - the range of coordinates covered by the input section. We need to - temporarily copy the integer bounds into floating point arrays to - use astLinearApprox. */ - } else { - -/* Allocate memory for floating point bounds and for the coefficient array */ - flbnd = astMalloc( sizeof( double )*(size_t) ncoord_in ); - fubnd = astMalloc( sizeof( double )*(size_t) ncoord_in ); - linear_fit = astMalloc( sizeof( double )* - (size_t) ( ncoord_out*( ncoord_in + 1 ) ) ); - if( astOK ) { - -/* Copy the bounds into these arrays, and change them so that they refer - to the lower and upper edges of the cell rather than the centre. This - is essential if one of the axes is spanned by a single cell, since - otherwise the upper and lower bounds would be identical. */ - for( i = 0; i < ncoord_in; i++ ) { - flbnd[ i ] = (double) lbnd[ i ] - 0.5; - fubnd[ i ] = (double) ubnd[ i ] + 0.5; - } - -/* Get the linear approximation to the forward transformation. */ - isLinear = astLinearApprox( this, flbnd, fubnd, tol, linear_fit ); - -/* Free the coeff array if the inverse transformation is not linear. */ - if( !isLinear ) linear_fit = astFree( linear_fit ); - - } else { - linear_fit = astFree( linear_fit ); - } - -/* Free resources */ - flbnd = astFree( flbnd ); - fubnd = astFree( fubnd ); - -/* If a linear fit was obtained, we will use it and therefore do not - wish to sub-divide further. Otherwise, we sub-divide in the hope - that this may result in a linear fit next time. */ - divide = !linear_fit; - } - -/* If no sub-division is required, perform the transformation (in a - memory-efficient manner, since the section we are rebinning might - still be very large). This will use the linear fit, if obtained - above. */ - if ( astOK ) { - if ( !divide ) { - TranGridWithBlocking( this, linear_fit, ncoord_in, lbnd_in, - ubnd_in, lbnd, ubnd, ncoord_out, out, status ); - -/* Otherwise, allocate workspace to perform the sub-division. */ - } else { - lo = astMalloc( sizeof( int ) * (size_t) ncoord_in ); - hi = astMalloc( sizeof( int ) * (size_t) ncoord_in ); - if ( astOK ) { - -/* Initialise the bounds of a new input section to match the original - input section. */ - for ( coord_in = 0; coord_in < ncoord_in; coord_in++ ) { - lo[ coord_in ] = lbnd[ coord_in ]; - hi[ coord_in ] = ubnd[ coord_in ]; - } - -/* Replace the upper bound of the section's largest dimension with the - mid-point of the section along this dimension, rounded downwards. */ - hi[ dimx ] = - (int) floor( 0.5 * (double) ( lbnd[ dimx ] + ubnd[ dimx ] ) ); - -/* Rebin the resulting smaller section using a recursive invocation - of this function. */ - TranGridAdaptively( this, ncoord_in, lbnd_in, ubnd_in, lo, hi, - tol, maxpix, ncoord_out, out, status ); - -/* Now set up a second section which covers the remaining half of the - original input section. */ - lo[ dimx ] = hi[ dimx ] + 1; - hi[ dimx ] = ubnd[ dimx ]; - -/* If this section contains pixels, transform it in the same way. */ - if ( lo[ dimx ] <= hi[ dimx ] ) { - TranGridAdaptively( this, ncoord_in, lbnd_in, ubnd_in, lo, hi, - tol, maxpix, ncoord_out, out, status ); - } - } - -/* Free the workspace. */ - lo = astFree( lo ); - hi = astFree( hi ); - } - } - -/* If coefficients for a linear fit were obtained, then free the space - they occupy. */ - if ( linear_fit ) linear_fit = astFree( linear_fit ); -} - -static void TranGridSection( AstMapping *this, const double *linear_fit, - int ndim_in, const int *lbnd_in, - const int *ubnd_in, const int *lbnd, - const int *ubnd, int ndim_out, double *out[], int *status ){ -/* -* Name: -* TranGridSection - -* Purpose: -* Transform grid points within a section of a rectangular grid. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void TranGridSection( AstMapping *this, const double *linear_fit, -* int ndim_in, const int *lbnd_in, -* const int *ubnd_in, const int *lbnd, -* const int *ubnd, int ndim_out, double *out[] ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function transforms grid points within a specified section of a -* rectangular grid (with any number of dimensions) using a specified -* Mapping or, alternatively, a linear approximation fitted to the -* Mapping's forward transformation. - -* Parameters: -* this -* Pointer to a Mapping, whose forward transformation may be -* used to transform the coordinates of points in the input -* grid. -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* linear_fit -* Pointer to an optional array of double which contains the -* coefficients of a linear fit which approximates the above -* Mapping's forward coordinate transformation. If this is -* supplied, it will be used in preference to the above Mapping -* when transforming coordinates. This may be used to enhance -* performance in cases where evaluation of the Mapping's -* forward transformation is expensive. If no linear fit is -* available, a NULL pointer should be supplied. -* -* The way in which the fit coefficients are stored in this -* array and the number of array elements are as defined by the -* astLinearApprox function. -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input data grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input data grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the input data grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* lbnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the first pixel in the -* section of the input data grid which is to be rebinned. -* ubnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the last pixel in the -* section of the input data grid which is to be rebinned. -* -* Note that "lbnd" and "ubnd" define the shape and position of -* the section of the input grid which is to be rebinned. This section -* should lie wholly within the extent of the input grid (as defined -* by the "lbnd_out" and "ubnd_out" arrays). Regions of the input -* grid lying outside this section will be ignored. -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* out -* Pointer to an array with "ndim_out" elements. Element [i] of -* this array is a pointer to an array in which to store the -* transformed values for output axis "i". The points are ordered -* such that the first axis of the input grid changes most rapidly. -* For example, if the input grid is 2-dimensional and extends from -* (2,-1) to (3,1), the output points will be stored in the order -* (2,-1), (3, -1), (2,0), (3,0), (2,1), (3,1). - -* Notes: -* - This function does not take steps to limit memory usage if the -* grids supplied are large. To resample large grids in a more -* memory-efficient way, the ResampleWithBlocking function should -* be used. -*/ - -/* Local Variables: */ - AstPointSet *pset_in; /* Input PointSet for transformation */ - AstPointSet *pset_out; /* Output PointSet for transformation */ - const double *grad; /* Pointer to gradient matrix of linear fit */ - const double *zero; /* Pointer to zero point array of fit */ - double **ptr_in; /* Pointer to input PointSet coordinates */ - double **ptr_out; /* Pointer to output PointSet coordinates */ - double *accum; /* Pointer to array of accumulated sums */ - double x1; /* Interim x coordinate value */ - double xx1; /* Initial x coordinate value */ - double y1; /* Interim y coordinate value */ - double yy1; /* Initial y coordinate value */ - int *dim; /* Pointer to array of output pixel indices */ - int *offset; /* Pointer to array of output pixel offsets */ - int *stride; /* Pointer to array of output grid strides */ - int coord_in; /* Loop counter for input dimensions */ - int coord_out; /* Loop counter for output dimensions */ - int done; /* All pixel indices done? */ - int i1; /* Interim offset into "accum" array */ - int i2; /* Final offset into "accum" array */ - int idim; /* Loop counter for dimensions */ - int ix; /* Loop counter for output x coordinate */ - int iy; /* Loop counter for output y coordinate */ - int npoint; /* Number of output points (pixels) */ - int off1; /* Interim pixel offset into output array */ - int off2; /* Interim pixel offset into output array */ - int off; /* Final pixel offset into output array */ - int point; /* Counter for output points (pixels ) */ - int s; /* Temporary variable for strides */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Further initialisation. */ - pset_in = NULL; - ptr_in = NULL; - ptr_out = NULL; - pset_out = NULL; - -/* Calculate the number of input points, as given by the product of - the input grid dimensions. */ - for ( npoint = 1, coord_in = 0; coord_in < ndim_in; coord_in++ ) { - npoint *= ubnd[ coord_in ] - lbnd[ coord_in ] + 1; - } - -/* Allocate workspace. */ - offset = astMalloc( sizeof( int ) * (size_t) npoint ); - stride = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Calculate the stride for each input grid dimension. */ - off = 0; - s = 1; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - stride[ coord_in ] = s; - s *= ubnd_in[ coord_in ] - lbnd_in[ coord_in ] + 1; - } - -/* A linear fit to the Mapping is available. */ -/* ========================================= */ - if ( linear_fit ) { - -/* If a linear fit to the Mapping has been provided, then obtain - pointers to the array of gradients and zero-points comprising the - fit. */ - grad = linear_fit + ndim_out; - zero = linear_fit; - -/* Create a PointSet to hold the output grid coordinates and obtain an - array of pointers to its coordinate data. */ - pset_out = astPointSet( npoint, ndim_out, "", status ); - ptr_out = astGetPoints( pset_out ); - if ( astOK ) { - -/* Initialise the count of input points. */ - point = 0; - -/* Handle the 1-dimensional case optimally. */ -/* ---------------------------------------- */ - if ( ( ndim_in == 1 ) && ( ndim_out == 1 ) ) { - -/* Loop through the pixels of the input grid and transform their x - coordinates into the output grid's coordinate system using the - linear fit supplied. Store the results in the PointSet created - above. */ - off = lbnd[ 0 ] - lbnd_in[ 0 ]; - xx1 = zero[ 0 ] + grad[ 0 ] * (double) lbnd[ 0 ]; - - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_out[ 0 ][ point ] = xx1; - xx1 += grad[ 0 ]; - offset[ point++ ] = off++; - } - -/* Handle the 2-dimensional case optimally. */ -/* ---------------------------------------- */ - } else if ( ( ndim_in == 2 ) && ( ndim_out == 2 ) ) { - -/* Loop through the range of y coordinates in the input grid and - calculate interim values of the output coordinates using the linear - fit supplied. */ - x1 = zero[ 0 ] + grad[ 1 ] * (double) ( lbnd[ 1 ] - 1 ); - y1 = zero[ 1 ] + grad[ 3 ] * (double) ( lbnd[ 1 ] - 1 ); - off1 = stride[ 1 ] * ( lbnd[ 1 ] - lbnd_in[ 1 ] - 1 ) - lbnd_in[ 0 ]; - for ( iy = lbnd[ 1 ]; iy <= ubnd[ 1 ]; iy++ ) { - x1 += grad[ 1 ]; - y1 += grad[ 3 ]; - -/* Also calculate an interim pixel offset into the input array. */ - off1 += stride[ 1 ]; - -/* Now loop through the range of input x coordinates and calculate - the final values of the input coordinates, storing the results in - the PointSet created above. */ - xx1 = x1 + grad[ 0 ] * (double) lbnd[ 0 ]; - yy1 = y1 + grad[ 2 ] * (double) lbnd[ 0 ]; - off = off1 + lbnd[ 0 ]; - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_out[ 0 ][ point ] = xx1; - xx1 += grad[ 0 ]; - ptr_out[ 1 ][ point ] = yy1; - yy1 += grad[ 2 ]; - -/* Also calculate final pixel offsets into the input array. */ - offset[ point++ ] = off++; - } - } - -/* Handle other numbers of dimensions. */ -/* ----------------------------------- */ - } else { - -/* Allocate workspace. */ - accum = astMalloc( sizeof( double ) * - (size_t) ( ndim_in * ndim_out ) ); - dim = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Initialise an array of pixel indices for the input grid which refer to the - first pixel which we will rebin. Also calculate the offset of this pixel - within the input array. */ - off = 0; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - dim[ coord_in ] = lbnd[ coord_in ]; - off += stride[ coord_in ] * - ( dim[ coord_in ] - lbnd_in[ coord_in ] ); - } - -/* To calculate each output grid coordinate we must perform a matrix - multiply on the input grid coordinates (using the gradient matrix) - and then add the zero points. However, since we will usually only - be altering one input coordinate at a time (the least - significant), we can avoid the full matrix multiply by accumulating - partial sums for the most significant input coordinates and only - altering those sums which need to change each time. The zero points - never change, so we first fill the "most significant" end of the - "accum" array with these. */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - accum[ ( coord_out + 1 ) * ndim_in - 1 ] = - zero[ coord_out ]; - } - coord_in = ndim_in - 1; - -/* Now loop to process each input pixel. */ - for ( done = 0; !done; point++ ) { - -/* To generate the output coordinate that corresponds to the current - input pixel, we work down from the most significant dimension - whose index has changed since the previous pixel we considered - (given by "coord_in"). For each affected dimension, we accumulate - in "accum" the matrix sum (including the zero point) for that - dimension and all higher input dimensions. We must accumulate a - separate set of sums for each output coordinate we wish to - produce. (Note that for the first pixel we process, all dimensions - are considered "changed", so we start by initialising the whole - "accum" array.) */ - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - i1 = coord_out * ndim_in; - for ( idim = coord_in; idim >= 1; idim-- ) { - i2 = i1 + idim; - accum[ i2 - 1 ] = accum[ i2 ] + - dim[ idim ] * grad[ i2 ]; - } - -/* The output coordinate for each dimension is given by the accumulated - sum for input dimension zero (giving the sum over all input - dimensions). We do not store this in the "accum" array, but assign - the result directly to the coordinate array of the PointSet created - earlier. */ - ptr_out[ coord_out ][ point ] = accum[ i1 ] + - dim[ 0 ] * grad[ i1 ]; - } - -/* Store the offset of the current pixel in the input array. */ - offset[ point ] = off; - -/* Now update the array of pixel indices to refer to the next input pixel. */ - coord_in = 0; - do { - -/* The least significant index which currently has less than its maximum - value is incremented by one. The offset into the input array is updated - accordingly. */ - if ( dim[ coord_in ] < ubnd[ coord_in ] ) { - dim[ coord_in ]++; - off += stride[ coord_in ]; - break; - -/* Any less significant indices which have reached their maximum value - are returned to their minimum value and the input pixel offset is - decremented appropriately. */ - } else { - dim[ coord_in ] = lbnd[ coord_in ]; - off -= stride[ coord_in ] * - ( ubnd[ coord_in ] - lbnd[ coord_in ] ); - -/* All the output pixels have been processed once the most significant - pixel index has been returned to its minimum value. */ - done = ( ++coord_in == ndim_in ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - accum = astFree( accum ); - dim = astFree( dim ); - } - } - -/* No linear fit to the Mapping is available. */ -/* ========================================== */ - } else { - -/* Create a PointSet to hold the coordinates of the input pixels and - obtain a pointer to its coordinate data. */ - pset_in = astPointSet( npoint, ndim_in, "", status ); - ptr_in = astGetPoints( pset_in ); - if ( astOK ) { - -/* Initialise the count of input points. */ - point = 0; - -/* Handle the 1-dimensional case optimally. */ -/* ---------------------------------------- */ - if ( ndim_in == 1 && ndim_out == 1 ) { - -/* Loop through the required range of input x coordinates, assigning - the coordinate values to the PointSet created above. Also store a - pixel offset into the input array. */ - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_in[ 0 ][ point ] = (double) ix; - offset[ point++ ] = ix - lbnd_in[ 0 ]; - } - -/* Handle the 2-dimensional case optimally. */ -/* ---------------------------------------- */ - } else if ( ndim_in == 2 && ndim_out == 2 ) { - -/* Loop through the required range of input y coordinates, - calculating an interim pixel offset into the input array. */ - off1 = stride[ 1 ] * ( lbnd[ 1 ] - lbnd_in[ 1 ] - 1 ) - - lbnd_in[ 0 ]; - for ( iy = lbnd[ 1 ]; iy <= ubnd[ 1 ]; iy++ ) { - off1 += stride[ 1 ]; - -/* Loop through the required range of input x coordinates, assigning - the coordinate values to the PointSet created above. Also store a - final pixel offset into the input array. */ - off2 = off1 + lbnd[ 0 ]; - for ( ix = lbnd[ 0 ]; ix <= ubnd[ 0 ]; ix++ ) { - ptr_in[ 0 ][ point ] = (double) ix; - ptr_in[ 1 ][ point ] = (double) iy; - offset[ point++ ] = off2++; - } - } - -/* Handle other numbers of dimensions. */ -/* ----------------------------------- */ - } else { - -/* Allocate workspace. */ - dim = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Initialise an array of pixel indices for the input grid which - refer to the first pixel to be rebinned. Also calculate the offset - of this pixel within the input array. */ - off = 0; - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - dim[ coord_in ] = lbnd[ coord_in ]; - off += stride[ coord_in ] * - ( dim[ coord_in ] - lbnd_in[ coord_in ] ); - } - -/* Loop to generate the coordinates of each input pixel. */ - for ( done = 0; !done; point++ ) { - -/* Copy each pixel's coordinates into the PointSet created above. */ - for ( coord_in = 0; coord_in < ndim_in; coord_in++ ) { - ptr_in[ coord_in ][ point ] = - (double) dim[ coord_in ]; - } - -/* Store the offset of the pixel in the input array. */ - offset[ point ] = off; - -/* Now update the array of pixel indices to refer to the next input - pixel. */ - coord_in = 0; - do { - -/* The least significant index which currently has less than its - maximum value is incremented by one. The offset into the input - array is updated accordingly. */ - if ( dim[ coord_in ] < ubnd[ coord_in ] ) { - dim[ coord_in ]++; - off += stride[ coord_in ]; - break; - -/* Any less significant indices which have reached their maximum value - are returned to their minimum value and the input pixel offset is - decremented appropriately. */ - } else { - dim[ coord_in ] = lbnd[ coord_in ]; - off -= stride[ coord_in ] * - ( ubnd[ coord_in ] - lbnd[ coord_in ] ); - -/* All the input pixels have been processed once the most significant - pixel index has been returned to its minimum value. */ - done = ( ++coord_in == ndim_in ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - dim = astFree( dim ); - } - -/* When all the input pixel coordinates have been generated, use the - Mapping's forward transformation to generate the output coordinates - from them. Obtain an array of pointers to the resulting coordinate - data. */ - pset_out = astTransform( this, pset_in, 1, NULL ); - ptr_out = astGetPoints( pset_out ); - } - -/* Annul the PointSet containing the input coordinates. */ - pset_in = astAnnul( pset_in ); - } - } - -/* Copy the output coordinates into the correct positions within the - supplied "out" array. */ -/* ================================================================= */ - if( astOK ) { - for ( coord_out = 0; coord_out < ndim_out; coord_out++ ) { - for ( point = 0; point < npoint; point++ ) { - out[ coord_out ][ offset[ point ] ] = ptr_out[ coord_out ][ point ]; - } - } - } - -/* Annul the PointSet used to hold output coordinates. */ - pset_out = astAnnul( pset_out ); - -/* Free the workspace. */ - offset = astFree( offset ); - stride = astFree( stride ); -} - -static void TranGridWithBlocking( AstMapping *this, const double *linear_fit, - int ndim_in, const int *lbnd_in, - const int *ubnd_in, const int *lbnd, - const int *ubnd, int ndim_out, - double *out[], int *status ){ -/* -* Name: -* TranGridWithBlocking - -* Purpose: -* Transforms positions in a section of a grid in a memory-efficient way. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void TranGridWithBlocking( AstMapping *this, const double *linear_fit, -* int ndim_in, const int *lbnd_in, -* const int *ubnd_in, const int *lbnd, -* const int *ubnd, int ndim_out, -* double *out[], int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function transforms positions within a specified section of a -* rectangular grid (with any number of dimensions) using the forward -* transformation of the supplied Mapping. -* -* This function is very similar to TranGridSection, except that in -* order to limit memory usage and to ensure locality of reference, -* it divides the input grid up into "blocks" which have a limited -* extent along each input dimension. Each block, which will not -* contain more than a pre-determined maximum number of pixels, is -* then passed to TranGridSection for transformation. - -* Parameters: -* this -* Pointer to a Mapping, whose forward transformation may be -* used to transform the coordinates of pixels in the input -* grid into associated positions in the output grid. -* -* The number of input coordintes for the Mapping (Nin -* attribute) should match the value of "ndim_in" (below), and -* the number of output coordinates (Nout attribute) should -* match the value of "ndim_out". -* linear_fit -* Pointer to an optional array of double which contains the -* coefficients of a linear fit which approximates the above -* Mapping's forward coordinate transformation. If this is -* supplied, it will be used in preference to the above Mapping -* when transforming coordinates. This may be used to enhance -* performance in cases where evaluation of the Mapping's -* forward transformation is expensive. If no linear fit is -* available, a NULL pointer should be supplied. -* -* The way in which the fit coefficients are stored in this -* array and the number of array elements are as defined by the -* astLinearApprox function. -* ndim_in -* The number of dimensions in the input grid. This should be at -* least one. -* lbnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the first -* pixel in the input grid along each dimension. -* ubnd_in -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the centre of the last -* pixel in the input grid along each dimension. -* -* Note that "lbnd_in" and "ubnd_in" together define the shape -* and size of the whole input grid, its extent along a -* particular (i'th) dimension being (ubnd_in[i] - lbnd_in[i] + -* 1). They also define the input grid's coordinate system, with -* each pixel being of unit extent along each dimension with -* integral coordinate values at its centre. -* lbnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the first pixel in the -* section of the input data grid which is to be transformed. -* ubnd -* Pointer to an array of integers, with "ndim_in" elements. -* This should give the coordinates of the last pixel in the -* section of the input data grid which is to be transformed. -* -* Note that "lbnd" and "ubnd" define the shape and position of the -* section of the input grid which is to be transformed. -* ndim_out -* The number of dimensions in the output grid. This should be -* at least one. -* out -* Pointer to an array with "ndim_out" elements. Element [i] of -* this array is a pointer to an array in which to store the -* transformed values for output axis "i". The points are ordered -* such that the first axis of the input grid changes most rapidly. -* For example, if the input grid is 2-dimensional and extends from -* (2,-1) to (3,1), the output points will be stored in the order -* (2,-1), (3, -1), (2,0), (3,0), (2,1), (3,1). -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Constants: */ - const int mxpix = 2 * 1024; /* Maximum number of pixels in a block (this - relatively small number seems to give best - performance) */ - -/* Local Variables: */ - int *dim_block; /* Pointer to array of block dimensions */ - int *lbnd_block; /* Pointer to block lower bound array */ - int *ubnd_block; /* Pointer to block upper bound array */ - int dim; /* Dimension size */ - int done; /* All blocks rebinned? */ - int hilim; /* Upper limit on maximum block dimension */ - int idim; /* Loop counter for dimensions */ - int lolim; /* Lower limit on maximum block dimension */ - int mxdim_block; /* Maximum block dimension */ - int npix; /* Number of pixels in block */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Allocate workspace. */ - lbnd_block = astMalloc( sizeof( int ) * (size_t) ndim_in ); - ubnd_block = astMalloc( sizeof( int ) * (size_t) ndim_in ); - dim_block = astMalloc( sizeof( int ) * (size_t) ndim_in ); - if ( astOK ) { - -/* Find the optimum block size. */ -/* ---------------------------- */ -/* We first need to find the maximum extent which a block of input - pixels may have in each dimension. We determine this by taking the - input grid extent in each dimension and then limiting the maximum - dimension size until the resulting number of pixels is sufficiently - small. This approach allows the block shape to approximate (or - match) the input grid shape when appropriate. */ - -/* First loop to calculate the total number of input pixels and the - maximum input dimension size. */ - npix = 1; - mxdim_block = 0; - for ( idim = 0; idim < ndim_in; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - npix *= dim; - if ( mxdim_block < dim ) mxdim_block = dim; - } - -/* If the number of input pixels is too large for a single block, we - perform iterations to determine the optimum upper limit on a - block's dimension size. Initialise the limits on this result. */ - if ( npix > mxpix ) { - lolim = 1; - hilim = mxdim_block; - -/* Loop to perform a binary chop, searching for the best result until - the lower and upper limits on the result converge to adjacent - values. */ - while ( ( hilim - lolim ) > 1 ) { - -/* Form a new estimate from the mid-point of the previous limits. */ - mxdim_block = ( hilim + lolim ) / 2; - -/* See how many pixels a block contains if its maximum dimension is - limited to this new value. */ - for ( npix = 1, idim = 0; idim < ndim_in; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - npix *= ( dim < mxdim_block ) ? dim : mxdim_block; - } - -/* Update the appropriate limit, according to whether the number of - pixels is too large or too small. */ - *( ( npix <= mxpix ) ? &lolim : &hilim ) = mxdim_block; - } - -/* When iterations have converged, obtain the maximum limit on the - dimension size of a block which results in no more than the maximum - allowed number of pixels per block. However, ensure that all block - dimensions are at least 2. */ - mxdim_block = lolim; - } - if ( mxdim_block < 2 ) mxdim_block = 2; - -/* Calculate the block dimensions by applying this limit to the output - grid dimensions. */ - for ( idim = 0; idim < ndim_in; idim++ ) { - dim = ubnd[ idim ] - lbnd[ idim ] + 1; - dim_block[ idim ] = ( dim < mxdim_block ) ? dim : mxdim_block; - -/* Also initialise the lower and upper bounds of the first block of - output grid pixels to be rebinned, ensuring that this does not - extend outside the grid itself. */ - lbnd_block[ idim ] = lbnd[ idim ]; - ubnd_block[ idim ] = MinI( lbnd[ idim ] + dim_block[ idim ] - 1, - ubnd[ idim ], status ); - } - -/* Transform each block of input grid positions. */ -/* --------------------------------------------- */ -/* Loop to generate the extent of each block of input grid positions and to - transform them. */ - done = 0; - while ( !done && astOK ) { - -/* Rebin the current block, accumulating the sum of bad pixels produced. */ - TranGridSection( this, linear_fit, ndim_in, lbnd_in, ubnd_in, - lbnd_block, ubnd_block, ndim_out, out, status ); - -/* Update the block extent to identify the next block of input pixels. */ - idim = 0; - do { - -/* We find the least significant dimension where the upper bound of - the block has not yet reached the upper bound of the region of the - input grid which we are rebinning. The block's position is then - incremented by one block extent along this dimension, checking that - the resulting extent does not go outside the region being rebinned. */ - if ( ubnd_block[ idim ] < ubnd[ idim ] ) { - lbnd_block[ idim ] = MinI( lbnd_block[ idim ] + - dim_block[ idim ], ubnd[ idim ], status ); - ubnd_block[ idim ] = MinI( lbnd_block[ idim ] + - dim_block[ idim ] - 1, - ubnd[ idim ], status ); - break; - -/* If any less significant dimensions are found where the upper bound - of the block has reached its maximum value, we reset the block to - its lowest position. */ - } else { - lbnd_block[ idim ] = lbnd[ idim ]; - ubnd_block[ idim ] = MinI( lbnd[ idim ] + dim_block[ idim ] - 1, - ubnd[ idim ], status ); - -/* All the blocks have been processed once the position along the most - significant dimension has been reset. */ - done = ( ++idim == ndim_in ); - } - } while ( !done ); - } - } - -/* Free the workspace. */ - lbnd_block = astFree( lbnd_block ); - ubnd_block = astFree( ubnd_block ); - dim_block = astFree( dim_block ); -} - -static void TranN( AstMapping *this, int npoint, - int ncoord_in, int indim, const double *in, - int forward, - int ncoord_out, int outdim, double *out, int *status ) { -/* -*++ -* Name: -c astTranN -f AST_TRANN - -* Purpose: -* Transform N-dimensional coordinates. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astTranN( AstMapping *this, int npoint, -c int ncoord_in, int indim, const double *in, -c int forward, -c int ncoord_out, int outdim, double *out ) -f CALL AST_TRANN( THIS, NPOINT, -f NCOORD_IN, INDIM, IN, -f FORWARD, NCOORD_OUT, OUTDIM, OUT, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function applies a Mapping to transform the coordinates of -f This routine applies a Mapping to transform the coordinates of -* a set of points in an arbitrary number of dimensions. It is the -* appropriate routine to use if the coordinates are not purely 1- -* or 2-dimensional and are stored in a single array (which they -* need not fill completely). -c -c If the coordinates are not stored in a single array, then the -c astTranP function might be more suitable. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping to be applied. -c npoint -f NPOINT = INTEGER (Given) -* The number of points to be transformed. -c ncoord_in -f NCOORD_IN = INTEGER (Given) -* The number of coordinates being supplied for each input point -* (i.e. the number of dimensions of the space in which the -* input points reside). -c indim -f INDIM = INTEGER (Given) -c The number of elements along the second dimension of the "in" -f The number of elements along the first dimension of the IN -* array (which contains the input coordinates). This value is -* required so that the coordinate values can be correctly -* located if they do not entirely fill this array. The value -c given should not be less than "npoint". -f given should not be less than NPOINT. -c in -f IN( INDIM, NCOORD_IN ) = DOUBLE PRECISION (Given) -c The address of the first element in a 2-dimensional array of -c shape "[ncoord_in][indim]", -c containing the coordinates of the input (untransformed) -c points. These should be stored such that the value of -c coordinate number "coord" for input point number "point" is -c found in element "in[coord][point]". -f An array containing the coordinates of the input -f (untransformed) points. These should be stored such that the -f value of coordinate number COORD for input point number POINT -f is found in element IN(POINT,COORD). -c forward -f FORWARD = LOGICAL (Given) -c A non-zero value indicates that the Mapping's forward -c coordinate transformation is to be applied, while a zero -c value indicates that the inverse transformation should be -c used. -f A .TRUE. value indicates that the Mapping's forward -f coordinate transformation is to be applied, while a .FALSE. -f value indicates that the inverse transformation should be -f used. -c ncoord_out -f NCOORD_OUT = INTEGER (Given) -* The number of coordinates being generated by the Mapping for -* each output point (i.e. the number of dimensions of the -* space in which the output points reside). This need not be -c the same as "ncoord_in". -f the same as NCOORD_IN. -c outdim -f OUTDIM = INTEGER (Given) -c The number of elements along the second dimension of the "out" -f The number of elements along the first dimension of the OUT -* array (which will contain the output coordinates). This value -* is required so that the coordinate values can be correctly -* located if they will not entirely fill this array. The value -c given should not be less than "npoint". -f given should not be less than NPOINT. -c out -f OUT( OUTDIM, NCOORD_OUT ) = DOUBLE PRECISION (Returned) -c The address of the first element in a 2-dimensional array of -c shape "[ncoord_out][outdim]", into -c which the coordinates of the output (transformed) points will -c be written. These will be stored such that the value of -c coordinate number "coord" for output point number "point" -c will be found in element "out[coord][point]". -f An array into which the coordinates of the output -f (transformed) points will be written. These will be stored -f such that the value of coordinate number COORD for output -f point number POINT will be found in element OUT(POINT,COORD). -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -c - If the forward coordinate transformation is being applied, the -c Mapping supplied must have the value of "ncoord_in" for its Nin -c attribute and the value of "ncoord_out" for its Nout attribute. If -c the inverse transformation is being applied, these values should -c be reversed. -f - If the forward coordinate transformation is being applied, the -f Mapping supplied must have the value of NCOORD_IN for its Nin -f attribute and the value of NCOORD_OUT for its Nout attribute. If -f the inverse transformation is being applied, these values should -f be reversed. -*-- -*/ - -/* Local Variables: */ - AstPointSet *in_points; /* Pointer to input PointSet */ - AstPointSet *out_points; /* Pointer to output PointSet */ - const double **in_ptr; /* Pointer to array of input data pointers */ - double **out_ptr; /* Pointer to array of output data pointers */ - int coord; /* Loop counter for coordinates */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Validate the mapping and numbers of points/coordinates. */ - ValidateMapping( this, forward, npoint, ncoord_in, ncoord_out, "astTranN", status ); - -/* Also validate the input array dimension argument. */ - if ( astOK && ( indim < npoint ) ) { - astError( AST__DIMIN, "astTranN(%s): The input array dimension value " - "(%d) is invalid.", status, astGetClass( this ), indim ); - astError( AST__DIMIN, "This should not be less than the number of " - "points being transformed (%d).", status, npoint ); - } - -/* Similarly, validate the output array dimension argument. */ - if ( astOK && ( outdim < npoint ) ) { - astError( AST__DIMIN, "astTranN(%s): The output array dimension value " - "(%d) is invalid.", status, astGetClass( this ), outdim ); - astError( AST__DIMIN, "This should not be less than the number of " - "points being transformed (%d).", status, npoint ); - } - -/* Allocate memory to hold the arrays of input and output data - pointers. */ - if ( astOK ) { - in_ptr = (const double **) astMalloc( sizeof( const double * ) * - (size_t) ncoord_in ); - out_ptr = astMalloc( sizeof( double * ) * (size_t) ncoord_out ); - - -#ifdef DEBUG - { int i, ns; - ns = ncoord_out*outdim; - for( i = 0; i < ns; i++ ) out[ i ] = 0.0; - } -#endif - - -/* Initialise the input data pointers to locate the coordinate data in - the "in" array. */ - if ( astOK ) { - for ( coord = 0; coord < ncoord_in; coord++ ) { - in_ptr[ coord ] = in + coord * indim; - } - -/* Similarly initialise the output data pointers to point into the - "out" array. */ - for ( coord = 0; coord < ncoord_out; coord++ ) { - out_ptr[ coord ] = out + coord * outdim; - } - -/* Create PointSets to describe the input and output points. */ - in_points = astPointSet( npoint, ncoord_in, "", status ); - out_points = astPointSet( npoint, ncoord_out, "", status ); - -/* Associate the data pointers with the PointSets (note we must - explicitly remove the "const" qualifier from the input data here, - although they will not be modified). */ - astSetPoints( in_points, (double **) in_ptr ); - astSetPoints( out_points, out_ptr ); - -/* Apply the required transformation to the coordinates. */ - (void) astTransform( this, in_points, forward, out_points ); - -/* If the Mapping's Report attribute is set, report the effect the - Mapping has had on the coordinates. */ - if ( astGetReport( this ) ) astReportPoints( this, forward, - in_points, out_points ); - -/* Delete the two PointSets. */ - in_points = astDelete( in_points ); - out_points = astDelete( out_points ); - } - -/* Free the memory used for the data pointers. */ - in_ptr = (const double **) astFree( (void *) in_ptr ); - out_ptr = astFree( out_ptr ); - } -} - -static void TranP( AstMapping *this, int npoint, - int ncoord_in, const double *ptr_in[], - int forward, int ncoord_out, double *ptr_out[], int *status ) { -/* -c++ -* Name: -* astTranP - -* Purpose: -* Transform N-dimensional coordinates held in separate arrays. - -* Type: -* Public virtual function. - -* Synopsis: -* #include "mapping.h" -* void astTranP( AstMapping *this, int npoint, -* int ncoord_in, const double *ptr_in[], -* int forward, int ncoord_out, double *ptr_out[] ) - -* Class Membership: -* Mapping method. - -* Description: -* This function applies a Mapping to transform the coordinates of -* a set of points in an arbitrary number of dimensions. It is the -* appropriate routine to use if the coordinates are not purely 1- -* or 2-dimensional and are stored in separate arrays, since each -* coordinate array is located by supplying a separate pointer to -* it. -* -* If the coordinates are stored in a single (2-dimensional) array, -* then the astTranN function might be more suitable. - -* Parameters: -* this -* Pointer to the Mapping to be applied. -* npoint -* The number of points to be transformed. -* ncoord_in -* The number of coordinates being supplied for each input point -* (i.e. the number of dimensions of the space in which the -* input points reside). -* ptr_in -* An array of pointers to double, with "ncoord_in" -* elements. Element "ptr_in[coord]" should point at the first -* element of an array of double (with "npoint" elements) which -* contain the values of coordinate number "coord" for each -* input (untransformed) point. The value of coordinate number -* "coord" for input point number "point" is therefore given by -* "ptr_in[coord][point]" (assuming both indices are -* zero-based). -* forward -* A non-zero value indicates that the Mapping's forward -* coordinate transformation is to be applied, while a zero -* value indicates that the inverse transformation should be -* used. -* ncoord_out -* The number of coordinates being generated by the Mapping for -* each output point (i.e. the number of dimensions of the space -* in which the output points reside). This need not be the same -* as "ncoord_in". -* ptr_out -* An array of pointers to double, with "ncoord_out" -* elements. Element "ptr_out[coord]" should point at the first -* element of an array of double (with "npoint" elements) into -* which the values of coordinate number "coord" for each output -* (transformed) point will be written. The value of coordinate -* number "coord" for output point number "point" will therefore -* be found in "ptr_out[coord][point]". - -* Notes: -* - If the forward coordinate transformation is being applied, the -* Mapping supplied must have the value of "ncoord_in" for its Nin -* attribute and the value of "ncoord_out" for its Nout -* attribute. If the inverse transformation is being applied, these -* values should be reversed. -* - This routine is not available in the Fortran 77 interface to -* the AST library. -c-- -*/ - -/* Local Variables: */ - AstPointSet *in_points; /* Pointer to input PointSet */ - AstPointSet *out_points; /* Pointer to output PointSet */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Validate the Mapping and number of points/coordinates. */ - ValidateMapping( this, forward, npoint, ncoord_in, ncoord_out, "astTranP", status ); - -/* Create PointSets to describe the input and output points. */ - if ( astOK ) { - in_points = astPointSet( npoint, ncoord_in, "", status ); - out_points = astPointSet( npoint, ncoord_out, "", status ); - -/* Associate the data pointers with the PointSets (note we must - explicitly remove the "const" qualifier from the input data here, - although they will not be modified). */ - astSetPoints( in_points, (double **) ptr_in ); - astSetPoints( out_points, ptr_out ); - -/* Apply the required transformation to the coordinates. */ - (void) astTransform( this, in_points, forward, out_points ); - -/* If the Mapping's Report attribute is set, report the effect the - Mapping has had on the coordinates. */ - if ( astGetReport( this ) ) astReportPoints( this, forward, - in_points, out_points ); - -/* Delete the two PointSets. */ - in_points = astDelete( in_points ); - out_points = astDelete( out_points ); - } -} - -static AstPointSet *Transform( AstMapping *this, AstPointSet *in, - int forward, AstPointSet *out, int *status ) { -/* -*+ -* Name: -* astTransform - -* Purpose: -* Transform a set of points. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "mapping.h" -* AstPointSet *astTransform( AstMapping *this, AstPointSet *in, -* int forward, AstPointSet *out ) - -* Class Membership: -* Mapping method. - -* Description: -* This function takes a Mapping and a set of points encapsulated -* in a PointSet, and applies either the forward or inverse -* coordinate transformation (if defined by the Mapping) to the -* points. - -* Parameters: -* this -* Pointer to the Mapping. The nature of the coordinate -* transformation will depend on the class of Mapping -* supplied. Note that there is no constructor for the Mapping -* class itself, so this object should be from a derived class. -* in -* Pointer to the PointSet holding the input coordinate data. -* forward -* A non-zero value indicates that the forward coordinate -* transformation should be applied, while a zero value requests -* the inverse transformation. -* out -* Pointer to a PointSet which will hold the transformed -* (output) coordinate values. A NULL value may also be given, -* in which case a new PointSet will be created by this -* function. - -* Returned Value: -* Pointer to the output (possibly new) PointSet. - -* Notes: -* - An error will result if the Mapping supplied does not define -* the requested coordinate transformation (either forward or -* inverse). -* - The number of coordinate values per point in the input -* PointSet must match the number of input coordinates for the -* Mapping being applied (or number of output coordinates if the -* inverse transformation is requested). -* - If an output PointSet is supplied, it must have space for -* sufficient number of points and coordinate values per point to -* accommodate the result (e.g. the number of Mapping output -* coordinates, or number of input coordinates if the inverse -* transformation is requested). Any excess space will be ignored. -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstPointSet *result; /* Pointer to output PointSet */ - int def; /* Coordinate transformation defined? */ - int ncoord_in; /* Number of input PointSet coordinates */ - int ncoord_out; /* Number of coordinates in output PointSet */ - int nin; /* Number of input Mapping coordinates */ - int nout; /* Number of output Mapping coordinates */ - int npoint; /* Number of points to transform */ - int npoint_out; /* Number of points in output PointSet */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise. */ - result = NULL; - -/* Determine if a coordinate transformation is defined for the requested - direction. */ - def = forward ? astGetTranForward( this ) : astGetTranInverse( this ); - -/* Report an error if the transformation is not defined. */ - if ( astOK && !def ) { - astError( AST__TRNND, "astTransform(%s): %s coordinate transformation " - "is not defined by the %s supplied.", status, astGetClass( this ), - forward ? "A forward" : "An inverse", astGetClass( this ) ); - } - -/* Obtain the effective number of input and output coordinate values for the - transformation to be performed, taking account of the transformation - direction required. Note we use Mapping methods to obtain these values, as - this will take account of whether the Mapping has been inverted. */ - nin = forward ? astGetNin( this ) : astGetNout( this ); - nout = forward ? astGetNout( this ) : astGetNin( this ); - -/* Obtain the number of input points to transform and the number of coordinate - values per input point. */ - npoint = astGetNpoint( in ); - ncoord_in = astGetNcoord( in ); - -/* If OK, check that the number of input coordinates matches the number - required by the mapping. Report an error if these numbers do not match. */ - if ( astOK && ( ncoord_in != nin ) ) { - astError( AST__NCPIN, "astTransform(%s): Bad number of coordinate " - "values (%d) in input %s.", status, astGetClass( this ), ncoord_in, - astGetClass( in ) ); - astError( AST__NCPIN, "The %s given requires %d coordinate value(s) for " - "each input point.", status, astGetClass( this ), nin ); - } - -/* If still OK, and a non-NULL pointer has been given for the output PointSet, - then obtain the number of points and number of coordinates per point for - this PointSet. */ - if ( astOK && out ) { - npoint_out = astGetNpoint( out ); - ncoord_out = astGetNcoord( out ); - -/* Check that the dimensions of this PointSet are adequate to accommodate the - output coordinate values and report an error if they are not. */ - if ( astOK ) { - if ( npoint_out < npoint ) { - astError( AST__NOPTS, "astTransform(%s): Too few points (%d) in " - "output %s.", status, astGetClass( this ), npoint_out, - astGetClass( out ) ); - astError( AST__NOPTS, "The %s needs space to hold %d transformed " - "point(s).", status, astGetClass( this ), npoint ); - } else if ( ncoord_out < nout ) { - astError( AST__NOCTS, "astTransform(%s): Too few coordinate " - "values per point (%d) in output %s.", status, - astGetClass( this ), ncoord_out, astGetClass( out ) ); - astError( AST__NOCTS, "The %s supplied needs space to store %d " - "coordinate value(s) per transformed point.", status, - astGetClass( this ), nout ); - } - } - } - -/* If all the validation stages are passed successfully, and a NULL output - pointer was given, then create a new PointSet to encapsulate the output - coordinate data. */ - if ( astOK ) { - if ( !out ) { - result = astPointSet( npoint, nout, "", status ); - -/* Otherwise, use the PointSet supplied. */ - } else { - result = out; - } - } - -/* Return a pointer to the output PointSet. Note that we do not actually - transform (or even copy) the coordinates. This is left for derived classes - to implement. */ - return result; -} - -/* -*++ -* Name: -c astUinterp -f AST_UINTERP - -* Purpose: -* Perform sub-pixel interpolation on a grid of data. - -* Type: -* Fictitious function. - -* Synopsis: -c #include "mapping.h" -c void astUinterp( int ndim_in, const int lbnd_in[], const int ubnd_in[], -c const <Xtype> in[], const <Xtype> in_var[], -c int npoint, const int offset[], -c const double *const coords[], const double params[], -c int flags, <Xtype> badval, -c <Xtype> out[], <Xtype> out_var[], int *nbad ) -f CALL AST_UINTERP( NDIM_IN, LBND_IN, UBND_IN, IN, IN_VAR, -f NPOINT, OFFSET, COORDS, PARAMS, FLAGS, BADVAL, -f OUT, OUT_VAR, NBAD, STATUS ) - -* Class Membership: -* Mapping member function. - -* Description: -c This is a fictitious function which does not actually -c exist. Instead, this description constitutes a template so that -c you may implement a function with this interface for yourself -c (and give it any name you wish). A pointer to such a function -c may be passed via the "finterp" parameter of the astResample<X> -c functions (q.v.) in order to perform sub-pixel interpolation -c during resampling of gridded data (you must also set the -c "interp" parameter of astResample<X> to the value -c AST__UINTERP). This allows you to use your own interpolation -c algorithm in addition to those which are pre-defined. -f This is a fictitious routine which does not actually -f exist. Instead, this description constitutes a template so that -f you may implement a routine with this interface for yourself -f (and give it any name you wish). Such a routine -f may be passed via the FINTERP argument of the AST_RESAMPLE<X> -f functions (q.v.) in order to perform sub-pixel interpolation -f during resampling of gridded data (you must also set the -f INTERP argument of AST_RESAMPLE<X> to the value -f AST__UINTERP). This allows you to use your own interpolation -f algorithm in addition to those which are pre-defined. -* -c The function interpolates an input grid of data (and, -f The routine interpolates an input grid of data (and, -* optionally, processes associated statistical variance estimates) -* at a specified set of points. - -* Parameters: -c ndim_in -f NDIM_IN = INTEGER (Given) -* The number of dimensions in the input grid. This will be at -* least one. -c lbnd_in -f LBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the first pixel -* in the input grid along each dimension. -c ubnd_in -f UBND_IN( NDIM_IN ) = INTEGER (Given) -c Pointer to an array of integers, with "ndim_in" elements, -f An array -* containing the coordinates of the centre of the last pixel in -* the input grid along each dimension. -* -c Note that "lbnd_in" and "ubnd_in" together define the shape, -f Note that LBND_IN and UBND_IN together define the shape, -* size and coordinate system of the input grid in the same -c way as they do in astResample<X>. -f way as they do in AST_RESAMPLE<X>. -c in -f IN( * ) = <Xtype> (Given) -c Pointer to an array, with one element for each pixel in the -f An array, with one element for each pixel in the -* input grid, containing the input data. This will be the same -c array as was passed to astResample<X> via the "in" parameter. -f array as was passed to AST_RESAMPLE<X> via the IN argument. -* The numerical type of this array should match that of the -* data being processed. -c in_var -f IN_VAR( * ) = <Xtype> (Given) -c Pointer to an optional second array with the same size and -c type as the "in" array. If given, this will contain the set -c of variance values associated with the input data and will be -c the same array as was passed to astResample<X> via the -c "in_var" parameter. -f An optional second array with the same size and type as the -f IN array. This will only be given if the AST__USEVAR flag is -f set via the FLAGS argument (below). If given, it will contain -f the set of variance values associated with the input data and -f will be the same array as was passed to AST_RESAMPLE<X> via -f the IN_VAR argument. -* -c If no variance values are being processed, this will be a -c NULL pointer. -f If the AST__USEVAR flag is not set, then no variance values -f are being processed. In this case, this array of variance -f values may be a dummy (e.g. one-element) array and should not -f be used. -c npoint -f NPOINT = INTEGER (Given) -* The number of points at which the input grid is to be -* interpolated. This will be at least one. -c offset -f OFFSET( NPOINT ) = INTEGER (Given) -c Pointer to an array of integers with "npoint" elements. For -c each interpolation point, this will contain the zero-based -c index in the "out" (and "out_var") array(s) at which the -c interpolated value (and its variance, if required) should be -c stored. For example, the interpolated value for point number -c "point" should be stored in "out[offset[point]]" (assuming -c the index "point" is zero-based). -f For each interpolation point, this array will contain the -f offset from the start of the OUT (and OUT_VAR) array(s) at -f which the interpolated value (and its variance, if required) -f should be stored. For example, the interpolated value for -f point number POINT should be stored in OUT(1+OFFSET(POINT)). -c coords -f COORDS( NPOINT, NDIM_IN ) = DOUBLE PRECISION (Given) -c An array of pointers to double, with "ndim_in" -c elements. Element "coords[coord]" will point at the first -c element of an array of double (with "npoint" elements) which -c contains the values of coordinate number "coord" for each -c interpolation point. The value of coordinate number "coord" -c for interpolation point number "point" is therefore given by -c "coords[coord][point]" (assuming both indices are -c zero-based). -f A 2-dimensional array containing the coordinates of the -f points at which interpolation should be performed. These will -f be stored so that coordinate number COORD for interpolation -f point number POINT is found in element COORDS(POINT,COORD). -* -* If any interpolation point has any of its coordinates equal -c to the value AST__BAD (as defined in the "ast.h" header -f to the value AST__BAD (as defined in the AST_PAR include -* file), then the corresponding output data (and variance) -c should either be set to the value given by "badval", -f should either be set to the value given by BADVAL, -* or left unchanged, depending on whether the AST__NOBAD flag is -c specified by "flags". -f specified by FLAGS. -c params -f PARAMS( * ) = DOUBLE PRECISION (Given) -c This will be a pointer to the same array as was given via the -c "params" parameter of astResample<X>. You may use this to -f This will be the same array as was given via the -f PARAMS argument of AST_RESAMPLE<X>. You may use this to -* pass any additional parameter values required by your -* interpolation algorithm. -c flags -f FLAGS = INTEGER (Given) -c This will be the same value as was given via the "flags" -c parameter of astResample<X>. You may test this value to -f This will be the same value as was given via the FLAGS -f argument of AST_RESAMPLE<X>. You may test this value to -* provide additional control over the operation of your -* resampling algorithm. Note that the special flag values -* AST__URESAMP1, 2, 3 & 4 are reserved for you to use for your -* own purposes and will not clash with other pre-defined flag -c values (see astResample<X>). -f values (see AST_RESAMPLE<X>). -c badval -f BADVAL = <Xtype> (Given) -c This will be the same value as was given via the "badval" -c parameter of astResample<X>, and will have the same numerical -c type as the data being processed (i.e. as elements of the -c "in" array). It should be used to test for bad pixels in the -c input grid (but only if the AST__USEBAD flag is set via the -c "flags" parameter) and (unless the AST__NOBAD flag is set in -c "flags") for identifying bad output values in -c the "out" (and "out_var") array(s). -f This will be the same value as was given for the BADVAL -f argument of AST_RESAMPLE<X>, and will have the same numerical -f type as the data being processed (i.e. as elements of the IN -f array). It should be used to test for bad pixels in the -f input grid (but only if the AST__USEBAD flag is set via the -f FLAGS argument) and (unless the AST__NOBAD flag is set in -f FLAGS) for identifying bad output values in the OUT (and -f OUT_VAR) array(s). -c out -f OUT( * ) = <Xtype> (Returned) -c Pointer to an array with the same numerical type as the "in" -f An array with the same numerical type as the IN -* array, into which the interpolated data values should be -* returned. Note that details of the storage order and number -* of dimensions of this array are not required, since the -c "offset" array contains all necessary information about where -f OFFSET array contains all necessary information about where -* each returned value should be stored. -* -c In general, not all elements of this array (or the "out_var" -f In general, not all elements of this array (or the OUT_VAR -* array below) may be used in any particular invocation of the -c function. Those which are not used should be returned -f routine. Those which are not used should be returned -* unchanged. -c out_var -f OUT_VAR( * ) = <Xtype> (Returned) -c Pointer to an optional array with the same type and size as -c the "out" array, into which variance estimates for the -c resampled values should be returned. This array will only be -c given if the "in_var" array has also been given. -f An optional array with the same type and size as the OUT -f array, into which variance estimates for the resampled values -f should be returned. This array will only be given if the -f AST__USEVAR flag is set via the FLAGS argument. -* -c If given, it is addressed in exactly the same way (via the -c "offset" array) as the "out" array. The values returned -c should be estimates of the statistical variance of the -c corresponding values in the "out" array, on the assumption -c that all errors in input data values are statistically -c independent and that their variance estimates may simply be -c summed (with appropriate weighting factors). -f If given, it is addressed in exactly the same way (via the -f OFFSET array) as the OUT array. The values returned should be -f estimates of the statistical variance of the corresponding -f values in the OUT array, on the assumption that all errors in -f input data values are statistically independent and that -f their variance estimates may simply be summed (with -f appropriate weighting factors). -* -c If no output variance estimates are required, a NULL pointer -c will be given. -f If the AST__USEVAR flag is not set, then variance values are -f not being processed. In this case, this array may be a dummy -f (e.g. one-element) array and should not be used. -c nbad -f NBAD = INTEGER (Returned) -c Pointer to an int in which to return the number of interpolation -c points at -f This should return the number of interpolation points at -* which no valid interpolated value could be obtained. The maximum -c value that should be returned is "npoint", and the minimum is -f value that should be returned is NPOINT, and the minimum is -* zero (indicating that all output values were successfully -* obtained). -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -* - The data type <Xtype> indicates the numerical type of the data -c being processed, as for astResample<X>. -f being processed, as for AST_RESAMPLE<X>. -c - This function will typically be invoked more than once for each -c invocation of astResample<X>. -f - This routine will typically be invoked more than once for each -f invocation of AST_RESAMPLE<X>. -c - If an error occurs within this function, it should use -c astSetStatus to set the AST error status to an error value. -c This will cause an immediate return from astResample<X>. The error -c value AST__UINER is available for this purpose, but other values may -c also be used (e.g. if you wish to distinguish different types of -c error). -f - If an error occurs within this routine, it should set the -f STATUS argument to an error value before returning. This will -f cause an immediate return from AST_RESAMPLE<X>. The error value -f AST__UINER is available for this purpose, but other values may also -f be used (e.g. if you wish to distinguish different types of error). -f The AST__UINER error value is defined in the AST_ERR include file. -*-- -*/ -/* Note the above is just a description to act as a template. The - function does not actually exist. */ - -/* -*++ -* Name: -c astUkern1 -f AST_UKERN1 - -* Purpose: -* 1-dimensional sub-pixel interpolation kernel. - -* Type: -* Fictitious function. - -* Synopsis: -c #include "mapping.h" -c void astUkern1( double offset, const double params[], int flags, -c double *value ) -f CALL AST_UKERN1( OFFSET, PARAMS, FLAGS, VALUE, STATUS ) - -* Class Membership: -* Mapping member function. - -* Description: -c This is a fictitious function which does not actually -c exist. Instead, this description constitutes a template so that -c you may implement a function with this interface for yourself -c (and give it any name you wish). A pointer to such a function -c may be passed via the "finterp" parameter of the astResample<X> -c functions (q.v.) in order to supply a 1-dimensional -c interpolation kernel to the algorithm which performs sub-pixel -c interpolation during resampling of gridded data (you must also -c set the "interp" parameter of astResample<X> to the value -c AST__UKERN1). This allows you to use your own interpolation -c kernel in addition to those which are pre-defined. -f This is a fictitious routine which does not actually -f exist. Instead, this description constitutes a template so that -f you may implement a routine with this interface for yourself -f (and give it any name you wish). Such a routine -f may be passed via the FINTERP argument of the AST_RESAMPLE<X> -f functions (q.v.) in order to supply a 1-dimensional -f interpolation kernel to the algorithm which performs sub-pixel -f interpolation during resampling of gridded data (you must also -f set the INTERP argument of AST_RESAMPLE<X> to the value -f AST__UKERN1). This allows you to use your own interpolation -f kernel in addition to those which are pre-defined. -* -c The function calculates the value of a 1-dimensional sub-pixel -f The routine calculates the value of a 1-dimensional sub-pixel -* interpolation kernel. This determines how the weight given to -* neighbouring pixels in calculating an interpolated value depends -* on the pixel's offset from the interpolation point. In more than -* one dimension, the weight assigned to a pixel is formed by -* evaluating this 1-dimensional kernel using the offset along each -* dimension in turn. The product of the returned values is then -* used as the pixel weight. - -* Parameters: -c offset -f OFFSET = DOUBLE PRECISION (Given) -* This will be the offset of the pixel from the interpolation -* point, measured in pixels. This value may be positive or -* negative, but for most practical interpolation schemes its -* sign should be ignored. -c params -f PARAMS( * ) = DOUBLE PRECISION (Given) -c This will be a pointer to the same array as was given via the -c "params" parameter of astResample<X>. You may use this to -f This will be the same array as was given via the -f PARAMS argument of AST_RESAMPLE<X>. You may use this to -* pass any additional parameter values required by your kernel, -c but note that "params[0]" will already have been used to specify -f but note that PARAMS(1) will already have been used to specify -* the number of neighbouring pixels which contribute to the -* interpolated value. -c flags -f FLAGS = INTEGER (Given) -c This will be the same value as was given via the "flags" -c parameter of astResample<X>. You may test this value to -f This will be the same value as was given via the FLAGS -f argument of AST_RESAMPLE<X>. You may test this value to -* provide additional control over the operation of your -c function. Note that the special flag values AST__URESAMP1, 2, -f routine. Note that the special flag values AST__URESAMP1, 2, -* 3 & 4 are reserved for you to use for your own purposes and -* will not clash with other pre-defined flag -c values (see astResample<X>). -f values (see AST_RESAMPLE<X>). -c value -f VALUE = DOUBLE PRECISION (Returned) -c Pointer to a double to receive the calculated kernel value, -f The calculated kernel value, -* which may be positive or negative. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -* - Not all functions make good interpolation kernels. In general, -* acceptable kernels tend to be symmetrical about zero, to have a -* positive peak (usually unity) at zero, and to evaluate to zero -* whenever the pixel offset has any other integral value (this -* ensures that the interpolated values pass through the original -* data). An interpolation kernel may or may not have regions with -* negative values. You should consult a good book on image -* processing for more details. -c - If an error occurs within this function, it should use -c astSetStatus to set the AST error status to an error value. -c This will cause an immediate return from astResample<X>. The error -c value AST__UK1ER is available for this purpose, but other values may -c also be used (e.g. if you wish to distinguish different types of -c error). -f - If an error occurs within this routine, it should set the -f STATUS argument to an error value before returning. This will -f cause an immediate return from AST_RESAMPLE<X>. The error value -f AST__UK1ER is available for this purpose, but other values may also -f be used (e.g. if you wish to distinguish different types of error). -f The AST__UK1ER error value is defined in the AST_ERR include file. -*-- -*/ -/* Note the above is just a description to act as a template. The - function does not actually exist. */ - -static double UphillSimplex( const MapData *mapdata, double acc, int maxcall, - const double dx[], double xmax[], double *err, - int *ncall, int *status ) { -/* -* Name: -* UphillSimplex - -* Purpose: -* Find a function maximum using a modification of the simplex method. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* double UphillSimplex( const MapData *mapdata, double acc, int maxcall, -* const double dx[], double xmax[], double *err, -* int *ncall, int *status ); - -* Class Membership: -* Mapping member function. - -* Description: -* This function applies a modification of the simplex method to -* find a local maximum in the value returned by a Mapping -* function. The modification used allows the method to cope with -* coordinate constraints and (equivalently) regions where the -* function returns "bad" values. The method is robust and not -* susceptible to overflow, so is suitable for applying to Mapping -* functions of unknown form. - -* Parameters: -* mapdata -* Pointer to a MapData structure which describes the Mapping -* function, its coordinate constraints, etc. -* acc -* The accuracy required in the value of the maximum. -* maxcall -* The maximum number of Mapping function evaluations to use. -* dx -* Pointer to an array of double containing an offset along each -* input coordinate for the Mapping function supplied. These -* offsets will be used to construct the initial simplex -* (i.e. they are the initial "step lengths" for each -* coordinate) and may be positive or negative. -* xmax -* Pointer to an array of double which contains the coordinates -* of an initial estimate of the location of the maximum. On -* exit, this will be updated to contain the best estimate of -* the location of the maximum as generated by this function. -* err -* Pointer to a double in which to return an estimate of the -* error in the value of the maximum found. For normal -* convergence, this should be no larger than "acc". However, if -* the maximum number of Mapping function evaluations is -* reached, the returned value may be larger than this, although -* it should still be valid. In such cases, re-starting the -* algorithm at the new location returned in "xmax" may be -* advisable. -* ncall -* Pointer to an int in which the number of Mapping function -* evaluations will be returned. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* An estimate of the Mapping function value at the local maximum. - -* Notes: -* - The function may return before the requested accuracy has been -* met and before all Mapping function evaluations have been -* made. This signifies that an excessive number of function values -* have been needed outside the coordinate constraints. This is -* only likely if the function is unable to make progress near such -* a constraint, in which case the algorithm should probably be -* re-started. -* - A value of AST__BAD will be returned if no maximum could be -* found. This means that all the Mapping function evaluations -* performed returned a value of AST__BAD. -* - A value of AST__BAD will also be returned and no useful -* information about a solution will be produced if this routine is -* invoked with the global error status set, or if it should fail -* for any reason. -*/ - -/* Local Constants: */ - const double factor = 3.0; /* Simplex contraction/expansion factor */ - -/* Local Variables: */ - double *f; /* Pointer to array of function values */ - double *x; /* Pointer to array of vertex coordinates */ - double *xnew; /* Pointer to workspace array */ - double fnew; /* New function value */ - double fsave; /* Saved function value */ - double offset; /* Coordinate difference between vertices */ - double range; /* Range of simplex values */ - double result; /* Value to return */ - double tmp; /* Temporary store for coordinate */ - int coord; /* Loop counter for coordinates */ - int hi; /* Index of best vertex */ - int lo; /* Index of worst vertex */ - int ncalla; /* Number of function calls attempted */ - int ncoord; /* Number of function dimensions */ - int nextlo; /* Index of second worst vertex */ - int nvertex; /* Number of simplex vertices */ - int vertex; /* Loop counter for vertices */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialisation. */ - *err = DBL_MAX; - *ncall = 0; - -/* Obtain the number of input coordinates for the Mapping function and - calculate the number of simplex vertices. */ - ncoord = mapdata->nin; - nvertex = ncoord + 1; - -/* Allocate workspace. */ - f = astMalloc( sizeof( double ) * (size_t) nvertex ); - x = astMalloc( sizeof( double ) * (size_t) ( ncoord * nvertex ) ); - xnew = astMalloc( sizeof( double ) * (size_t) ncoord ); - if ( astOK ) { - -/* Loop to set up an initial simplex. */ - for ( vertex = 0; vertex < nvertex; vertex++ ) { - for ( coord = 0; coord < ncoord; coord++ ) { - tmp = xmax[ coord ]; - -/* Displace each point (except the first) the required amount along - one of the axes to generate the coordinates of the simplex - vertices. */ - if ( coord == ( vertex - 1 ) ) tmp += dx[ coord ]; - x[ vertex * ncoord + coord ] = tmp; - } - -/* Evaluate the Mapping function at each vertex. */ - f[ vertex ] = MapFunction( mapdata, &x[ vertex * ncoord ], ncall, status ); - if ( f[ vertex ] == AST__BAD ) f[ vertex ] = -DBL_MAX; - } - -/* Initialise the number of times we attempt to call the Mapping - function (not necessarily the same as the number of times it was - actually called, which is stored in *ncall). */ - ncalla = nvertex; - -/* Loop until convergence is reached or an error occurs. */ - while( astOK ) { - -/* Initialise the index of the lowest vertex of the simplex, the next - lowest vertex and the highest vertex. */ - lo = ( f[ 0 ] < f[ 1 ] ) ? 0 : 1; - nextlo = 1 - lo; - hi = 0; - -/* Loop to inspect each vertex and update these values. Ensure that in - the case of equal vertices, the first one is taken to be the - highest. This makes the maximisation stable (so that if no better - maximum can be found, the original position is returned rather than - a nearby position that yields the same function value). */ - for ( vertex = 0; vertex < nvertex; vertex++ ) { - if ( f[ vertex ] <= f[ lo ] ) { - nextlo = lo; - lo = vertex; - } else if ( ( f[ vertex ] <= f[ nextlo ] ) && ( vertex != lo ) ) { - nextlo = vertex; - } - if ( f[ vertex ] > f[ hi ] ) hi = vertex; - } - -/* Estimate the error on the result as the difference between the - highest and lowest simplex vertices. */ - if ( ( f[ hi ] == -DBL_MAX ) || ( f[ lo ] == -DBL_MAX ) ) { - range = DBL_MAX; - } else { - range = f[ hi ] - f[ lo ]; - } - -/* Test for convergence. Ideally, the accuracy criterion should have - been met. However, also quit if the maximum number of Mapping - function evaluations has been reached, or the number of points at - which function values have been requested reaches three times this - limit (this latter number will typically be larger because points - lying outside the coordinate constraints do not result in the - Mapping function being evaluated). */ - if ( range <= fabs( acc ) || - ( *ncall >= maxcall ) || ( ncalla >= ( 3 * maxcall ) ) ) { - -/* If quitting, return the coordinates and function value at the best - simplex vertex, and the error estimate. */ - for ( coord = 0; coord < ncoord; coord++ ) { - xmax[ coord ] = x[ hi * ncoord + coord ]; - } - result = ( f[ hi ] == -DBL_MAX ) ? AST__BAD : f[ hi ]; - *err = range; - break; - } - -/* If performing another iteration, first try reflecting the worst - vertex through the opposite face of the simplex. Check for - errors. */ - fnew = NewVertex( mapdata, lo, -1.0, x, f, ncall, xnew, status ); - ncalla++; - if ( astOK ) { - -/* If this results in a point lying in a forbiddden region (either - outside the coordinate constraints or where the Mapping function - yields bad coordinate values), then we must make a departure from - the standard simplex algorithm. This is because the inability to - make forward progress in this case can cause the simplex to - repeatedly contract about each face (except one) in turn. This - mechanism normally results in lateral contraction as the simplex - attempts to squeeze through a narrow gap which is impeding - progress. However, in this case there is no gap to get through, so - the lateral contraction can eventually make the simplex become - degenerate (due to rounding). This prevents it from expanding - laterally again and exploring the region adjacent to the constraint - boundary once it has become small enough. */ - if ( fnew == AST__BAD ) { - -/* To overcome this, we instead contract the worst simplex vertex - towards the best vertex (this has the cumulative effect of - contracting the simplex without changing its shape). First find the - offset in each coordinate between these two vertices. */ - for ( coord = 0; coord < ncoord; coord++ ) { - offset = x[ lo * ncoord + coord ] - x[ hi * ncoord + coord ]; - -/* Scale the offset to obtain the new coordinate. */ - x[ lo * ncoord + coord ] = x[ hi * ncoord + coord ] + - offset / factor; - -/* If the distance between the two vertices has not decreased, we are - in a region where rounding errors prevent them approaching each - other any more closely, so simply set them equal. */ - if ( fabs( x[ lo * ncoord + coord ] - - x[ hi * ncoord + coord ] ) >= fabs( offset ) ) { - x[ lo * ncoord + coord ] = x[ hi * ncoord + coord ]; - } - } - -/* Evaluate the Mapping function at the new vertex. */ - f[ lo ] = MapFunction( mapdata, &x[ lo * ncoord ], ncall, status ); - if ( f[ lo ] == AST__BAD ) f[ lo ] = -DBL_MAX; - ncalla++; - -/* We now return to the standard simplex algorithm. If the new vertex - is a new maximum, then see if more of the same is even better by - trying to expand the best vertex away from the opposite face. */ - } else if ( fnew >= f[ hi ] ) { - fnew = NewVertex( mapdata, lo, factor, x, f, ncall, xnew, status ); - ncalla++; - -/* Otherwise, if the new vertex was no improvement on the second - worst, then try contracting the worst vertex towards the opposite - face. */ - } else if ( fnew <= f[ nextlo ] ) { - fsave = f[ lo ]; - fnew = NewVertex( mapdata, lo, 1.0 / factor, x, f, ncall, xnew, status ); - ncalla++; - -/* If this didn't result in any improvement, then contract the entire - simplex towards the best vertex. Use the same approach as earlier - to protect against rounding so that all the simplex vertices will - eventually coalesce if this process is repeated enough times. */ - if ( astOK && ( fnew <= fsave ) ) { - for ( vertex = 0; vertex < nvertex; vertex++ ) { - if ( vertex != hi ) { - for ( coord = 0; coord < ncoord; coord++ ) { - offset = x[ vertex * ncoord + coord ] - - x[ hi * ncoord + coord ]; - x[ vertex * ncoord + coord ] = - x[ hi * ncoord + coord ] + offset / factor; - if ( fabs( x[ vertex * ncoord + coord ] - - x[ hi * ncoord + coord ] ) >= - fabs( offset ) ) { - x[ vertex * ncoord + coord ] = - x[ hi * ncoord + coord ]; - } - } - -/* Evaluate the Mapping function at each new vertex. */ - f[ vertex ] = MapFunction( mapdata, - &x[ vertex * ncoord ], - ncall, status ); - if ( f[ vertex ] == AST__BAD ) f[ vertex ] = -DBL_MAX; - ncalla++; - } - } - } - } - } - } - } - -/* Free workspace. */ - f = astFree( f ); - x = astFree( x ); - xnew = astFree( xnew ); - -/* If an error occurred, clear the returned result. */ - if ( !astOK ) result = AST__BAD; - -/* Return the result. */ - return result; -} - -static void ValidateMapping( AstMapping *this, int forward, - int npoint, int ncoord_in, int ncoord_out, - const char *method, int *status ) { -/* -* Name: -* ValidateMapping - -* Purpose: -* Validate a Mapping for use to transform coordinates. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void ValidateMapping( AstMapping *this, int forward, -* int npoint, int ncoord_in, int ncoord_out, -* const char *method, int *status ) - -* Class Membership: -* Mapping member function. - -* Description: -* This function checks that a Mapping is suitable for transforming -* a set of points. It also checks that the number of points and -* the number of coordinate values per point is valid. If an error -* is detected, the global error status is set and an error report -* made. Otherwise, the function returns without further action. - -* Parameters: -* this -* Pointer to the Mapping. -* forward -* A non-zero value indicates that the forward coordinate -* transformation is to be checked, while a zero value requests -* the inverse transformation. -* npoint -* The number of points being transformed. -* ncoord_in -* The number of coordinates associated with each input point. -* ncoord_out -* The number of coordinates associated with each output point. -* method -* Pointer to a null terminated character string containing the -* name of the method which invoked this function to validate a -* Mapping. This is used solely for constructing error messages. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - int nin; /* Mapping Nin attribute value */ - int nout; /* Mapping Nout attribute value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Report an error if the requested transformation is not defined. */ - if ( !( forward ? astGetTranForward( this ) : astGetTranInverse( this ) ) - && astOK ) { - astError( AST__TRNND, "%s(%s): %s coordinate transformation " - "is not defined by the %s supplied.", status, method, - astGetClass( this ), - ( forward ? "A forward" : "An inverse" ), - astGetClass( this ) ); - } - -/* Obtain the effective values of the Nin and Nout attributes for the - Mapping. */ - nin = forward ? astGetNin( this ) : astGetNout( this ); - nout = forward ? astGetNout( this ) : astGetNin( this ); - -/* If OK, check that the number of input coordinates matches the - number required by the Mapping. Report an error if these numbers do - not match. */ - if ( astOK && ( ncoord_in != nin ) ) { - astError( AST__NCPIN, "%s(%s): Bad number of input coordinate values " - "(%d).", status, method, astGetClass( this ), ncoord_in ); - astError( AST__NCPIN, "The %s given requires %d coordinate value%s for " - "each input point.", status, astGetClass( this ), nin, - ( nin == 1 ) ? "" : "s" ); - } - -/* If OK, also check that the number of output coordinates matches the - number required by the Mapping. Report an error if these numbers do - not match. */ - if ( astOK && ( ncoord_out != nout ) ) { - astError( AST__NCPIN, "%s(%s): Bad number of output coordinate values " - "(%d).", status, method, astGetClass( this ), ncoord_out ); - astError( AST__NCPIN, "The %s given generates %s%d coordinate value%s " - "for each output point.", status, astGetClass( this ), - ( nout < ncoord_out ) ? "only " : "", nout, - ( nout == 1 ) ? "" : "s" ); - } - -/* Check that the number of points being transformed is not negative - and report an error if necessary. */ - if ( astOK && ( npoint < 0 ) ) { - astError( AST__NPTIN, "%s(%s): Number of points to be transformed (%d) " - "is invalid.", status, method, astGetClass( this ), npoint ); - } -} - -/* Functions which access class attributes. */ -/* ---------------------------------------- */ -/* Implement member functions to access the attributes associated with - this class using the macros defined for this purpose in the - "object.h" file. */ -/* -*att++ -* Name: -* Invert - -* Purpose: -* Mapping inversion flag. - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute controls which one of a Mapping's two possible -* coordinate transformations is considered the "forward" -* transformation (the other being the "inverse" -* transformation). If the attribute value is zero (the default), -* the Mapping's behaviour will be the same as when it was first -* created. However, if it is non-zero, its two transformations -* will be inter-changed, so that the Mapping displays the inverse -* of its original behaviour. -* -* Inverting the boolean sense of the Invert attribute will cause -* the values of a Mapping's Nin and Nout attributes to be -* interchanged. The values of its TranForward and TranInverse -* attributes will also be interchanged. This operation may be -c performed with the astInvert function. -f performed with the AST_INVERT routine. - -* Applicability: -* Mapping -* All Mappings have this attribute. -* UnitMap -* The value of the Invert attribute has no effect on the -* behaviour of a UnitMap. -* FrameSet -* Inverting the boolean sense of the Invert attribute for a -* FrameSet will cause its base and current Frames (and its Base -* and Current attributes) to be interchanged. This, in turn, -* may affect other properties and attributes of the FrameSet -* (such as Nin, Nout, Naxes, TranForward, TranInverse, -* etc.). The Invert attribute of a FrameSet is not itself -* affected by selecting a new base or current Frame. -*att-- -*/ -/* This ia a boolean value (0 or 1) with a value of CHAR_MAX when - undefined but yielding a default of zero. */ -astMAKE_CLEAR(Mapping,Invert,invert,CHAR_MAX) -astMAKE_GET(Mapping,Invert,int,0,( ( this->invert == CHAR_MAX ) ? - 0 : this->invert )) -astMAKE_SET(Mapping,Invert,int,invert,( (this->flags&=~AST__ISSIMPLE_FLAG),(value!=0) )) -astMAKE_TEST(Mapping,Invert,( this->invert != CHAR_MAX )) - -/* -*att++ -* Name: -* IsLinear - -* Purpose: -* Is the Mapping linear? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean), read-only. - -* Description: -* This attribute indicates whether a Mapping is an instance of a -* class that always represents a linear transformation. Note, some -* Mapping classes can represent linear or non-linear transformations -* (the MathMap class for instance). Such classes have a zero value for -* the IsLinear attribute. Specific instances of such classes can be -* tested for linearity using the -* astLinearApprox function. -* AST_LINEARAPPROX routine. - -* Applicability: -* Mapping -* All Mappings have this attribute. -* CmpMap -* The IsLinear value for a CmpMap is determined by the classes -* of the encapsulated Mappings. For instance, a CmpMap that combines -* a ZoomMap and a ShiftMap will have a non-zero value for its IsLinear -* attribute, but a CmpMap that contains a MathMap will have a -* value of zero for its IsLinear attribute. -* Frame -* The IsLinear value for a Frame is 1 (since a Frame is equivalent -* to a UnitMap). -* FrameSet -* The IsLinear value for a FrameSet is obtained from the Mapping -* from the base Frame to the current Frame. - -*att-- -*/ - -/* -*att++ -* Name: -* IsSimple - -* Purpose: -* Has the Mapping been simplified? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean), read-only. - -* Description: -* This attribute indicates whether a Mapping has been simplified -* by the -c astSimplify -f AST_SIMPLIFY -* method. If the IsSimple value is non-zero, then the Mapping has -* been simplified and so there is nothing to be gained by simplifying -* it again. Indeed, the -c astSimplify -f AST_SIMPLIFY -* method will immediately return the Mapping unchanged if the IsSimple -* attribute indicates that the Mapping has already been simplified. - -* Applicability: -* Mapping -* All Mappings have this attribute. -* Frame -* All classes of Frame return zero for the IsSimple attribute. -* This is because changes can be made to a Frame which affect the -* Mapping represented by the Frame, and so there can be no -* guarantee that the Mapping may not need re-simplifying. Most -* non-Frame Mappings, on the other hand, are immutable and so when -* they are simplified it is certain that they weill remain in a -* simple state. - -*att-- -*/ -astMAKE_GET(Mapping,IsSimple,int,0,((this->flags)&AST__ISSIMPLE_FLAG)) - -/* -*att++ -* Name: -* Nin - -* Purpose: -* Number of input coordinates for a Mapping. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute gives the number of coordinate values required to -* specify an input point for a Mapping (i.e. the number of -* dimensions of the space in which the Mapping's input points -* reside). - -* Applicability: -* Mapping -* All Mappings have this attribute. -* CmpMap -* If a CmpMap's component Mappings are joined in series, then -* its Nin attribute is equal to the Nin attribute of the first -* component (or to the Nout attribute of the second component -* if the the CmpMap's Invert attribute is non-zero). -* -* If a CmpMap's component Mappings are joined in parallel, then -* its Nin attribute is given by the sum of the Nin attributes -* of each component (or to the sum of their Nout attributes if -* the CmpMap's Invert attribute is non-zero). -* Frame -* The Nin attribute for a Frame is always equal to the number -* of Frame axes (Naxes attribute). -* FrameSet -* The Nin attribute of a FrameSet is equal to the number of -* axes (Naxes attribute) of its base Frame (as specified by the -* FrameSet's Base attribute). The Nin attribute value may -* therefore change if a new base Frame is selected. -*att-- -*/ - -/* -*att++ -* Name: -* Nout - -* Purpose: -* Number of output coordinates for a Mapping. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute gives the number of coordinate values generated -* by a Mapping to specify each output point (i.e. the number of -* dimensions of the space in which the Mapping's output points -* reside). - -* Applicability: -* Mapping -* All Mappings have this attribute. -* CmpMap -* If a CmpMap's component Mappings are joined in series, then -* its Nout attribute is equal to the Nout attribute of the -* second component (or to the Nin attribute of the first -* component if the the CmpMap's Invert attribute is non-zero). -* -* If a CmpMap's component Mappings are joined in parallel, then -* its Nout attribute is given by the sum of the Nout attributes -* of each component (or to the sum of their Nin attributes if -* the CmpMap's Invert attribute is non-zero). -* Frame -* The Nout attribute for a Frame is always equal to the number -* of Frame axes (Naxes attribute). -* FrameSet -* The Nout attribute of a FrameSet is equal to the number of -* FrameSet axes (Naxes attribute) which, in turn, is equal to -* the Naxes attribute of the FrameSet's current Frame (as -* specified by the Current attribute). The Nout attribute value -* may therefore change if a new current Frame is selected. -*att-- -*/ - -/* -*att++ -* Name: -* Report - -* Purpose: -* Report transformed coordinates? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute controls whether coordinate values are reported -* whenever a Mapping is used to transform a set of points. If its -* value is zero (the default), no report is made. However, if it -* is non-zero, the coordinates of each point are reported (both -* before and after transformation) by writing them to standard -* output. -* -* This attribute is provided as an aid to debugging, and to avoid -* having to report values explicitly in simple programs. - -* Applicability: -* Mapping -* All Mappings have this attribute. -* CmpMap -* When applied to a compound Mapping (CmpMap), only the Report -* attribute of the CmpMap, and not those of its component -* Mappings, is used. Coordinate information is never reported -* for the component Mappings individually, only for the -* complete CmpMap. -* Frame -* When applied to any Frame, the formatting capabilities of the -c Frame (as provided by the astFormat function) will be used to -f Frame (as provided by the AST_FORMAT function) will be used to -* format the reported coordinates. -* FrameSet -* When applied to any FrameSet, the formatting capabilities of -* the base and current Frames will be used (as above) to -* individually format the input and output coordinates, as -* appropriate. The Report attribute of a FrameSet is not itself -* affected by selecting a new base or current Frame, but the -* resulting formatting capabilities may be. - -* Notes: -* - Unlike most other attributes, the value of the Report -* attribute is not transferred when a Mapping is copied. Instead, -* its value is undefined (and therefore defaults to zero) in any -* copy. Similarly, it becomes undefined in any external -c representation of a Mapping produced by the astWrite function. -f representation of a Mapping produced by the AST_WRITE routine. -*att-- -*/ -/* This ia a boolean value (0 or 1) with a value of CHAR_MAX when - undefined but yielding a default of zero. */ -astMAKE_CLEAR(Mapping,Report,report,CHAR_MAX) -astMAKE_GET(Mapping,Report,int,0,( ( this->report == CHAR_MAX ) ? - 0 : this->report )) -astMAKE_SET(Mapping,Report,int,report,( value != 0 )) -astMAKE_TEST(Mapping,Report,( this->report != CHAR_MAX )) - -/* -*att++ -* Name: -* TranForward - -* Purpose: -* Forward transformation defined? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean), read-only. - -* Description: -* This attribute indicates whether a Mapping is able to transform -* coordinates in the "forward" direction (i.e. converting input -* coordinates into output coordinates). If this attribute is -* non-zero, the forward transformation is available. Otherwise, it -* is not. - -* Applicability: -* Mapping -* All Mappings have this attribute. -* CmpMap -* The TranForward attribute value for a CmpMap is given by the -* boolean AND of the value for each component Mapping. -* FrameSet -* The TranForward attribute of a FrameSet applies to the -* transformation which converts between the FrameSet's base -* Frame and its current Frame (as specified by the Base and -* Current attributes). This value is given by the boolean AND -* of the TranForward values which apply to each of the -* individual sub-Mappings required to perform this conversion. -* The TranForward attribute value for a FrameSet may therefore -* change if a new Base or Current Frame is selected. - -* Notes: -* - An error will result if a Mapping with a TranForward value of -* zero is used to transform coordinates in the forward direction. -*att-- -*/ - -/* -*att++ -* Name: -* TranInverse - -* Purpose: -* Inverse transformation defined? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean), readonly. - -* Description: -* This attribute indicates whether a Mapping is able to transform -* coordinates in the "inverse" direction (i.e. converting output -* coordinates back into input coordinates). If this attribute is -* non-zero, the inverse transformation is available. Otherwise, it -* is not. - -* Applicability: -* Mapping -* All Mappings have this attribute. -* CmpMap -* The TranInverse attribute value for a CmpMap is given by the -* boolean AND of the value for each component Mapping. -* FrameSet -* The TranInverse attribute of a FrameSet applies to the -* transformation which converts between the FrameSet's current -* Frame and its base Frame (as specified by the Current and -* Base attributes). This value is given by the boolean AND of -* the TranInverse values which apply to each of the individual -* sub-Mappings required to perform this conversion. -* The TranInverse attribute value for a FrameSet may therefore -* change if a new Base or Current Frame is selected. - -* Notes: -* - An error will result if a Mapping with a TranInverse value of -* zero is used to transform coordinates in the inverse direction. -*att-- -*/ - -/* Copy constructor. */ -/* ----------------- */ -static void Copy( const AstObject *objin, AstObject *objout, int *status ) { -/* -* Name: -* Copy - -* Purpose: -* Copy constructor for Mapping objects. - -* Type: -* Private function. - -* Synopsis: -* void Copy( const AstObject *objin, AstObject *objout, int *status ) - -* Description: -* This function implements the copy constructor for Mapping objects. - -* Parameters: -* objin -* Pointer to the Mapping to be copied. -* objout -* Pointer to the Mapping being constructed. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This constructor exists simply to ensure that the "Report" -* attribute is cleared in any copy made of a Mapping. -*/ - -/* Local Variables: */ - AstMapping *out; /* Pointer to output Mapping */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the output Mapping. */ - out = (AstMapping *) objout; - -/* Clear the output Report attribute. */ - out->report = CHAR_MAX; -} - -/* Destructor. */ -/* ----------- */ -static void Delete( AstObject *obj, int *status ) { -/* -* Name: -* Delete - -* Purpose: -* Destructor for Mapping objects. - -* Type: -* Private function. - -* Synopsis: -* void Delete( AstObject *obj, int *status ) - -* Description: -* This function implements the destructor for Mapping objects. - -* Parameters: -* obj -* Pointer to the Mapping to be deleted. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This destructor does nothing and exists only to maintain a -* one-to-one correspondence between destructors and copy -* constructors. -*/ - -/* Return without action. */ -} - -/* Dump function. */ -/* -------------- */ -static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { -/* -* Name: -* Dump - -* Purpose: -* Dump function for Mapping objects. - -* Type: -* Private function. - -* Synopsis: -* void Dump( AstObject *this, AstChannel *channel, int *status ) - -* Description: -* This function implements the Dump function which writes out data -* for the Mapping class to an output Channel. - -* Parameters: -* this -* Pointer to the Mapping whose data are being written. -* channel -* Pointer to the Channel to which the data are being written. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstMapping *this; /* Pointer to the Mapping structure */ - int invert; /* Mapping inverted? */ - int ival; /* Integer value */ - int set; /* Attribute value set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the Mapping structure. */ - this = (AstMapping *) this_object; - -/* Write out values representing the instance variables for the - Mapping class. Accompany these with appropriate comment strings, - possibly depending on the values being written.*/ - -/* In the case of attributes, we first use the appropriate (private) - Test... member function to see if they are set. If so, we then use - the (private) Get... function to obtain the value to be written - out. - - For attributes which are not set, we use the astGet... method to - obtain the value instead. This will supply a default value - (possibly provided by a derived class which over-rides this method) - which is more useful to a human reader as it corresponds to the - actual default attribute value. Since "set" will be zero, these - values are for information only and will not be read back. */ - -/* Determine if the Mapping is inverted. The output values - (e.g. number of input and output coordinates) will refer to the - Mapping ***before*** this inversion flag is applied, but we need it - when using (e.g.) the astGetNin/astGetNout methods to determine - which one will return the required value. */ - invert = astGetInvert( this ); - -/* (NB. there is a subtle point here that dictates the extent to which - this inversion flag can be used... All use of methods (such as - astGetInvert, which might be over-ridden by derived classes) must - be restricted to determining the values of "unset" output - quantities only (below). This is because when re-loading the - Mapping, the derived classes will not have been loaded at the point - when these values are re-read - hence any value whose - interpretation depends on these methods cannot be reliably - recovered.) */ - -/* Nin. */ -/* ---- */ -/* Use the instance variable directly to avoid the effect of the - Invert attribute on the private member function. Treat zero as the - default. */ - set = ( this->nin != 0 ); - ival = set ? this->nin : ( !invert ? astGetNin( this ) : - astGetNout( this ) ); - astWriteInt( channel, "Nin", set, 0, ival, - "Number of input coordinates" ); - -/* Nout. */ -/* ----- */ -/* Use the instance variable directly. Treat zero as the default. */ - set = ( this->nout != this->nin ); - ival = set ? this->nout : ( !invert ? astGetNout( this ) : - astGetNin( this ) ); - astWriteInt( channel, "Nout", set, 0, ival, - "Number of output coordinates" ); - -/* IsSimple. */ -/* --------- */ - ival = astGetIsSimple( this ); - astWriteInt( channel, "IsSimp", ival, 0, ival, - ival ? "Mapping has been simplified" : - "Mapping has not been simplified" ); - -/* Invert. */ -/* ------- */ - set = TestInvert( this, status ); - ival = set ? GetInvert( this, status ) : astGetInvert( this ); - astWriteInt( channel, "Invert", set, 0, ival, - ival ? "Mapping inverted" : - "Mapping not inverted" ); - -/* TranForward. */ -/* ------------ */ -/* Use the instance variable directly. Treat 1 as the default. */ - set = ( this->tran_forward == 0 ); - ival = set ? this->tran_forward : ( !invert ? astGetTranForward( this ) : - astGetTranInverse( this ) ); - astWriteInt( channel, "Fwd", set, 0, ival, - ival ? "Forward transformation defined" : - "Forward transformation not defined" ); - -/* TranInverse. */ -/* ------------ */ -/* Use the instance variable directly. Treat 1 as the default. */ - set = ( this->tran_inverse == 0 ); - ival = set ? this->tran_inverse : ( !invert ? astGetTranInverse( this ) : - astGetTranForward( this ) ); - astWriteInt( channel, "Inv", set, 0, ival, - ival ? "Inverse transformation defined" : - "Inverse transformation not defined" ); - -/* Report. */ -/* ------- */ - set = TestReport( this, status ); - ival = set ? GetReport( this, status ) : astGetReport( this ); - astWriteInt( channel, "Report", set, 0, ival, - ival ? "Report coordinate transformations" : - "Don't report coordinate transformations" ); -} - -/* Standard class functions. */ -/* ========================= */ -/* Implement the astIsAMapping and astCheckMapping functions using the macros - defined for this purpose in the "object.h" header file. */ -astMAKE_ISA(Mapping,Object) -astMAKE_CHECK(Mapping) - -AstMapping *astInitMapping_( void *mem, size_t size, int init, - AstMappingVtab *vtab, const char *name, - int nin, int nout, - int tran_forward, int tran_inverse, int *status ) { -/* -*+ -* Name: -* astInitMapping - -* Purpose: -* Initialise a Mapping. - -* Type: -* Protected function. - -* Synopsis: -* #include "mapping.h" -* AstMapping *astInitMapping( void *mem, size_t size, int init, -* AstMappingVtab *vtab, const char *name, -* int nin, int nout, -* int tran_forward, int tran_inverse ) - -* Class Membership: -* Mapping initialiser. - -* Description: -* This function is provided for use by class implementations to initialise -* a new Mapping object. It allocates memory (if necessary) to accommodate -* the Mapping plus any additional data associated with the derived class. -* It then initialises a Mapping structure at the start of this memory. If -* the "init" flag is set, it also initialises the contents of a virtual -* function table for a Mapping at the start of the memory passed via the -* "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the Mapping is to be initialised. -* This must be of sufficient size to accommodate the Mapping data -* (sizeof(Mapping)) plus any data used by the derived class. If a value -* of NULL is given, this function will allocate the memory itself using -* the "size" parameter to determine its size. -* size -* The amount of memory used by the Mapping (plus derived class data). -* This will be used to allocate memory if a value of NULL is given for -* the "mem" parameter. This value is also stored in the Mapping -* structure, so a valid value must be supplied even if not required for -* allocating memory. -* init -* A logical flag indicating if the Mapping's virtual function table is -* to be initialised. If this value is non-zero, the virtual function -* table will be initialised by this function. -* vtab -* Pointer to the start of the virtual function table to be associated -* with the new Mapping. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the new object belongs (it is this -* pointer value that will subsequently be returned by the astGetClass -* method). -* nin -* The number of coordinate values per input point. -* nout -* The number of coordinate vales per output point. -* tran_forward -* A non-zero value indicates that the Mapping will be able to -* transform coordinates in the forward direction. A zero value -* indicates that it will not. -* tran_inverse -* A non-zero value indicates that the Mapping will be able to -* transform coordinates in the inverse direction. A zero value -* indicates that it will not. - -* Returned Value: -* A pointer to the new Mapping. - -* Notes: -* - The Mappings produced by this function implement all the basic methods -* defined by the Mapping class. However, their astTransform method does not -* actually perform any coordinate transformation (although it performs all -* necessary argument validation and creates an output PointSet if -* necessary, leaving its coordinate values undefined). -* - This means that Mappings produced by this function are of limited use -* on their own, but may easily be extended by a derived class simply by -* over-riding the astTransform method to add the necessary coordinate -* arithmetic. -* - A null pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*- -*/ - -/* Local Variables: */ - AstMapping *new; /* Pointer to new Mapping */ - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* If necessary, initialise the virtual function table. */ - if ( init ) astInitMappingVtab( vtab, name ); - -/* Initialise. */ - new = NULL; - -/* Check the initialisation values for validity, reporting an error if - necessary. */ - if ( nin < 0 ) { - astError( AST__BADNI, "astInitMapping(%s): Bad number of input " - "coordinates (%d).", status, name, nin ); - astError( AST__BADNI, "This number should be zero or more." , status); - } else if ( nout < 0 ) { - astError( AST__BADNO, "astInitMapping(%s): Bad number of output " - "coordinates (%d).", status, name, nout ); - astError( AST__BADNI, "This number should be zero or more." , status); - } - -/* Initialise an Object structure (the parent class) as the first component - within the Mapping structure, allocating memory if necessary. */ - new = (AstMapping *) astInitObject( mem, size, 0, - (AstObjectVtab *) vtab, name ); - - if ( astOK ) { - -/* Initialise the Mapping data. */ -/* ---------------------------- */ -/* Store the numbers of input and output coordinates. */ - new->nin = nin; - new->nout = nout; - -/* Store the flags indicating which coordinate transformations are - defined (constrain these values to 0 or 1). */ - new->tran_forward = ( tran_forward != 0 ); - new->tran_inverse = ( tran_inverse != 0 ); - -/* Initialise other attributes to their undefined values. */ - new->invert = CHAR_MAX; - new->report = CHAR_MAX; - new->flags = 0; - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new object. */ - return new; -} - -AstMapping *astLoadMapping_( void *mem, size_t size, - AstMappingVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadMapping - -* Purpose: -* Load a Mapping. - -* Type: -* Protected function. - -* Synopsis: -* #include "mapping.h" -* AstMapping *astLoadMapping( void *mem, size_t size, -* AstMappingVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* Mapping loader. - -* Description: -* This function is provided to load a new Mapping using data read -* from a Channel. It first loads the data used by the parent class -* (which allocates memory if necessary) and then initialises a -* Mapping structure in this memory, using data read from the input -* Channel. -* -* If the "init" flag is set, it also initialises the contents of a -* virtual function table for a Mapping at the start of the memory -* passed via the "vtab" parameter. - - -* Parameters: -* mem -* A pointer to the memory into which the Mapping is to be -* loaded. This must be of sufficient size to accommodate the -* Mapping data (sizeof(Mapping)) plus any data used by derived -* classes. If a value of NULL is given, this function will -* allocate the memory itself using the "size" parameter to -* determine its size. -* size -* The amount of memory used by the Mapping (plus derived class -* data). This will be used to allocate memory if a value of -* NULL is given for the "mem" parameter. This value is also -* stored in the Mapping structure, so a valid value must be -* supplied even if not required for allocating memory. -* -* If the "vtab" parameter is NULL, the "size" value is ignored -* and sizeof(AstMapping) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new Mapping. If this is NULL, a pointer -* to the (static) virtual function table for the Mapping class -* is used instead. -* name -* Pointer to a constant null-terminated character string which -* contains the name of the class to which the new object -* belongs (it is this pointer value that will subsequently be -* returned by the astGetClass method). -* -* If the "vtab" parameter is NULL, the "name" value is ignored -* and a pointer to the string "Mapping" is used instead. - -* Returned Value: -* A pointer to the new Mapping. - -* Notes: -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstMapping *new; /* Pointer to the new Mapping */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(channel); - -/* If a NULL virtual function table has been supplied, then this is - the first loader to be invoked for this Mapping. In this case the - Mapping belongs to this class, so supply appropriate values to be - passed to the parent class loader (and its parent, etc.). */ - if ( !vtab ) { - size = sizeof( AstMapping ); - vtab = &class_vtab; - name = "Mapping"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitMappingVtab( vtab, name ); - class_init = 1; - } - } - -/* Invoke the parent class loader to load data for all the ancestral - classes of the current one, returning a pointer to the resulting - partly-built Mapping. */ - new = astLoadObject( mem, size, (AstObjectVtab *) vtab, name, - channel ); - - if ( astOK ) { - -/* Read input data. */ -/* ================ */ -/* Request the input Channel to read all the input data appropriate to - this class into the internal "values list". */ - astReadClassData( channel, "Mapping" ); - -/* Now read each individual data item from this list and use it to - initialise the appropriate instance variable(s) for this class. */ - -/* In the case of attributes, we first read the "raw" input value, - supplying the "unset" value as the default. If a "set" value is - obtained, we then use the appropriate (private) Set... member - function to validate and set the value properly. */ - -/* Initialise bitwise flags to zero. */ - new->flags = 0; - -/* Nin. */ -/* ---- */ - new->nin = astReadInt( channel, "nin", 0 ); - if ( new->nin < 0 ) new->nin = 0; - -/* Nout. */ -/* ----- */ - new->nout = astReadInt( channel, "nout", new->nin ); - if ( new->nout < 0 ) new->nout = 0; - -/* Invert. */ -/* ------- */ - new->invert = astReadInt( channel, "invert", CHAR_MAX ); - if ( TestInvert( new, status ) ) SetInvert( new, new->invert, status ); - -/* IsSimple. */ -/* --------- */ - if( astReadInt( channel, "issimp", 0 ) ) new->flags |= AST__ISSIMPLE_FLAG; - -/* TranForward. */ -/* ------------ */ - new->tran_forward = ( astReadInt( channel, "fwd", 1 ) != 0 ); - -/* TranInverse. */ -/* ------------ */ - new->tran_inverse = ( astReadInt( channel, "inv", 1 ) != 0 ); - -/* Report. */ -/* ------- */ - new->report = astReadInt( channel, "report", CHAR_MAX ); - if ( TestReport( new, status ) ) SetReport( new, new->report, status ); - -/* If an error occurred, clean up by deleting the new Mapping. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return the new Mapping pointer. */ - return new; -} - -/* Virtual function interfaces. */ -/* ============================ */ -/* These provide the external interface to the virtual functions - defined by this class. Each simply checks the global error status - and then locates and executes the appropriate member function, - using the function pointer stored in the object's virtual function - table (this pointer is located using the astMEMBER macro defined in - "object.h"). - - Note that the member function may not be the one defined here, as - it may have been over-ridden by a derived class. However, it should - still have the same interface. */ - -void astDecompose_( AstMapping *this, AstMapping **map1, AstMapping **map2, - int *series, int *invert1, int *invert2, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,Decompose))( this, map1, map2, series, invert1, invert2, status ); -} -int astGetNin_( AstMapping *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,GetNin))( this, status ); -} -int astGetNout_( AstMapping *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,GetNout))( this, status ); -} -int astGetIsLinear_( AstMapping *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,GetIsLinear))( this, status ); -} -int astGetTranForward_( AstMapping *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,GetTranForward))( this, status ); -} -int astGetTranInverse_( AstMapping *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,GetTranInverse))( this, status ); -} -void astInvert_( AstMapping *this, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,Invert))( this, status ); -} -void astMapBox_( AstMapping *this, - const double lbnd_in[], const double ubnd_in[], int forward, - int coord_out, double *lbnd_out, double *ubnd_out, - double xl[], double xu[], int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,MapBox))( this, lbnd_in, ubnd_in, forward, - coord_out, lbnd_out, ubnd_out, xl, xu, status ); -} -int astMapList_( AstMapping *this, int series, int invert, int *nmap, - AstMapping ***map_list, int **invert_list, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,MapList))( this, series, invert, - nmap, map_list, invert_list, status ); -} -int *astMapSplit_( AstMapping *this, int nin, const int *in, AstMapping **map, - int *status ){ - int *result = NULL; - AstMapping *tmap; - - if( map ) *map = NULL; - if ( !astOK ) return NULL; - - result = (**astMEMBER(this,Mapping,MapSplit))( this, nin, in, &tmap, status ); - if( tmap ) { - *map = astCopy( tmap ); - tmap = astAnnul( tmap ); - } - - return result; -} -int astMapMerge_( AstMapping *this, int where, int series, int *nmap, - AstMapping ***map_list, int **invert_list, int *status ) { - - if ( !astOK || astDoNotSimplify( this ) ) return -1; - return (**astMEMBER(this,Mapping,MapMerge))( this, where, series, nmap, - map_list, invert_list, status ); -} -int astDoNotSimplify_( AstMapping *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,DoNotSimplify))( this, status ); -} -void astReportPoints_( AstMapping *this, int forward, - AstPointSet *in_points, AstPointSet *out_points, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,ReportPoints))( this, forward, - in_points, out_points, status ); -} -#define MAKE_RESAMPLE_(X,Xtype) \ -int astResample##X##_( AstMapping *this, int ndim_in, const int *lbnd_in, \ - const int *ubnd_in, const Xtype *in, \ - const Xtype *in_var, int interp, \ - void (* finterp)( void ), const double *params, \ - int flags, double tol, int maxpix, Xtype badval, \ - int ndim_out, \ - const int *lbnd_out, const int *ubnd_out, \ - const int *lbnd, const int *ubnd, Xtype *out, \ - Xtype *out_var, int *status ) { \ - if ( !astOK ) return 0; \ - return (**astMEMBER(this,Mapping,Resample##X))( this, ndim_in, lbnd_in, \ - ubnd_in, in, in_var, \ - interp, finterp, params, \ - flags, tol, maxpix, \ - badval, ndim_out, \ - lbnd_out, ubnd_out, \ - lbnd, ubnd, \ - out, out_var, status ); \ -} -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_RESAMPLE_(LD,long double) -#endif -MAKE_RESAMPLE_(D,double) -MAKE_RESAMPLE_(F,float) -MAKE_RESAMPLE_(L,long int) -MAKE_RESAMPLE_(UL,unsigned long int) -MAKE_RESAMPLE_(I,int) -MAKE_RESAMPLE_(UI,unsigned int) -MAKE_RESAMPLE_(K,INT_BIG) -MAKE_RESAMPLE_(UK,UINT_BIG) -MAKE_RESAMPLE_(S,short int) -MAKE_RESAMPLE_(US,unsigned short int) -MAKE_RESAMPLE_(B,signed char) -MAKE_RESAMPLE_(UB,unsigned char) -#undef MAKE_RESAMPLE_ - -#define MAKE_REBIN_(X,Xtype) \ -void astRebin##X##_( AstMapping *this, double wlim, int ndim_in, const int *lbnd_in, \ - const int *ubnd_in, const Xtype *in, \ - const Xtype *in_var, int interp, \ - const double *params, \ - int flags, double tol, int maxpix, Xtype badval, \ - int ndim_out, \ - const int *lbnd_out, const int *ubnd_out, \ - const int *lbnd, const int *ubnd, Xtype *out, \ - Xtype *out_var, int *status ) { \ - if ( !astOK ) return; \ - (**astMEMBER(this,Mapping,Rebin##X))( this, wlim, ndim_in, lbnd_in, \ - ubnd_in, in, in_var, \ - interp, params, \ - flags, tol, maxpix, \ - badval, ndim_out, \ - lbnd_out, ubnd_out, \ - lbnd, ubnd, \ - out, out_var, status ); \ -} -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_REBIN_(LD,long double) -#endif -MAKE_REBIN_(D,double) -MAKE_REBIN_(F,float) -MAKE_REBIN_(I,int) -MAKE_REBIN_(B,signed char) -MAKE_REBIN_(UB,unsigned char) -#undef MAKE_REBIN_ - - -#define MAKE_REBINSEQ_(X,Xtype) \ -void astRebinSeq##X##_( AstMapping *this, double wlim, int ndim_in, const int *lbnd_in, \ - const int *ubnd_in, const Xtype *in, \ - const Xtype *in_var, int interp, \ - const double *params, \ - int flags, double tol, int maxpix, Xtype badval, \ - int ndim_out, \ - const int *lbnd_out, const int *ubnd_out, \ - const int *lbnd, const int *ubnd, Xtype *out, \ - Xtype *out_var, double *weights, int64_t *nused, \ - int *status ) { \ - if ( !astOK ) return; \ - (**astMEMBER(this,Mapping,RebinSeq##X))( this, wlim, ndim_in, lbnd_in, \ - ubnd_in, in, in_var, \ - interp, params, \ - flags, tol, maxpix, \ - badval, ndim_out, \ - lbnd_out, ubnd_out, \ - lbnd, ubnd, out, out_var, \ - weights, nused, status ); \ -} - -#if HAVE_LONG_DOUBLE /* Not normally implemented */ -MAKE_REBINSEQ_(LD,long double) -#endif -MAKE_REBINSEQ_(D,double) -MAKE_REBINSEQ_(F,float) -MAKE_REBINSEQ_(I,int) -MAKE_REBINSEQ_(B,signed char) -MAKE_REBINSEQ_(UB,unsigned char) - -#undef MAKE_REBINSEQ_ - -double astRate_( AstMapping *this, double *at, int ax1, int ax2, int *status ){ - astDECLARE_GLOBALS - - if ( !astOK ) return AST__BAD; - - astGET_GLOBALS(this); - - if( ax1 < 0 || ax1 >= astGetNout( this ) ) { - astError( AST__AXIIN, "astRate(%s): Invalid output index (%d) " - "specified - should be in the range 1 to %d.", status, - astGetClass( this ), ax1 + 1, astGetNout( this ) ); - - } else if( ax2 < 0 || ax2 >= astGetNin( this ) ) { - astError( AST__AXIIN, "astRate(%s): Invalid input index (%d) " - "specified - should be in the range 1 to %d.", status, - astGetClass( this ), ax2 + 1, astGetNin( this ) ); - } - - if( rate_disabled ) { - return ( at[ ax2 ] != AST__BAD ) ? 1.0 : AST__BAD; - } else { - return (**astMEMBER(this,Mapping,Rate))( this, at, ax1, ax2, status ); - } -} -AstMapping *astRemoveRegions_( AstMapping *this, int *status ) { - if ( !astOK ) return NULL; - return (**astMEMBER(this,Mapping,RemoveRegions))( this, status ); -} - -AstMapping *astSimplify_( AstMapping *this, int *status ) { - AstMapping *result; - AstErrorContext error_context; - - if ( !astOK ) return NULL; - -/* If this Mapping has already been simplified, or if it cannot be - simplified (e.g. because it is a Frame) we just returned a clone - of the upplied pointer. */ - if( !astGetIsSimple( this ) && !astDoNotSimplify( this ) ) { - -/* Start a new error reporting context. This is done so that errors - caused by the siplification process attempting to do inappropriate things - with the supplied mapping can be caught. */ - astErrorBegin( &error_context ); - -/* Do the simplification. */ - result = (**astMEMBER(this,Mapping,Simplify))( this, status ); - -/* If a result was returned, indicate it has been simplified and so does - not need to be simplified again. */ - if( result ) { - result->flags |= AST__ISSIMPLE_FLAG; - -/* If the simplification process failed due to the supplied Mappings - being inappropriate (e.g. because it attempted to ue an undefined - transformation), clear the error status and return a clone of the - supplied Mapping. */ - } else if( astStatus == AST__NODEF || astStatus == AST__TRNND ){ - astClearStatus; - result = astClone( this ); - } - -/* End the error reporting context. */ - astErrorEnd( &error_context ); - -/* If the Mapping has already been simplified just return a clone. */ - } else { - result = astClone( this ); - } - - return result; -} - -AstPointSet *astTransform_( AstMapping *this, AstPointSet *in, - int forward, AstPointSet *out, int *status ) { - AstPointSet *result; - if ( !astOK ) return NULL; - result = (**astMEMBER(this,Mapping,Transform))( this, in, forward, out, status ); - (void) astReplaceNaN( result ); - return result; -} -void astTran1_( AstMapping *this, int npoint, const double xin[], - int forward, double xout[], int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,Tran1))( this, npoint, xin, forward, xout, status ); -} -void astTran2_( AstMapping *this, - int npoint, const double xin[], const double yin[], - int forward, double xout[], double yout[], int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,Tran2))( this, npoint, xin, yin, - forward, xout, yout, status ); -} -void astTranGrid_( AstMapping *this, int ncoord_in, const int lbnd[], - const int ubnd[], double tol, int maxpix, int forward, - int ncoord_out, int outdim, double *out, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,TranGrid))( this, ncoord_in, lbnd, ubnd, tol, - maxpix, forward, ncoord_out, outdim, - out, status ); -} -void astTranN_( AstMapping *this, int npoint, - int ncoord_in, int indim, const double *in, - int forward, int ncoord_out, int outdim, double *out, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,TranN))( this, npoint, - ncoord_in, indim, in, - forward, ncoord_out, outdim, out, status ); -} -void astTranP_( AstMapping *this, int npoint, - int ncoord_in, const double *ptr_in[], - int forward, int ncoord_out, double *ptr_out[], int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Mapping,TranP))( this, npoint, - ncoord_in, ptr_in, - forward, ncoord_out, ptr_out, status ); -} -int astLinearApprox_( AstMapping *this, const double *lbnd, - const double *ubnd, double tol, double *fit, int *status ){ - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,LinearApprox))( this, lbnd, ubnd, tol, fit, status ); -} - - -int astQuadApprox_( AstMapping *this, const double lbnd[2], - const double ubnd[2], int nx, int ny, double *fit, - double *rms, int *status ){ - if ( !astOK ) return 0; - return (**astMEMBER(this,Mapping,QuadApprox))( this, lbnd, ubnd, nx, - ny, fit, rms, status ); -} - - - -/* Public Interface Function Prototypes. */ -/* ------------------------------------- */ -/* The following functions have public prototypes only (i.e. no - protected prototypes), so we must provide local prototypes for use - within this module. */ -void DecomposeId_( AstMapping *, AstMapping **, AstMapping **, int *, int *, int *, int * ); -void MapBoxId_( AstMapping *, const double [], const double [], int, int, double *, double *, double [], double [], int * ); -double astRateId_( AstMapping *, double *, int, int, int * ); -void astMapSplitId_( AstMapping *, int, const int *, int *, AstMapping **, - int * ); - -/* Special interface function implementations. */ -/* ------------------------------------------- */ -void astDecomposeId_( AstMapping *this, AstMapping **map1, - AstMapping **map2, int *series, int *invert1, - int *invert2, int *status ) { -/* -*++ -* Name: -c astDecompose -f AST_DECOMPOSE - -* Purpose: -* Decompose a Mapping into two component Mappings. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astDecompose( AstMapping *this, AstMapping **map1, -c AstMapping **map2, int *series, int *invert1, -c int *invert2 ) -f CALL AST_DECOMPOSE( THIS, MAP1, MAP2, SERIES, INVERT1, INVERT2, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function returns pointers to two Mappings which, when applied -f This routine returns pointers to two Mappings which, when applied -* either in series or parallel, are equivalent to the supplied Mapping. -* -* Since the Frame class inherits from the Mapping class, Frames can -* be considered as special types of Mappings and so this method can -* be used to decompose either CmpMaps or CmpFrames. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping. -c map1 -f MAP1 = INTEGER (Returned) -c Address of a location to receive a pointer to first component -f A pointer to first component -* Mapping. -c map2 -f MAP2 = INTEGER (Returned) -c Address of a location to receive a pointer to second component -f A pointer to second component -* Mapping. -c series -f SERIES = LOGICAL (Returned) -c Address of a location to receive a value indicating if the -c component Mappings are applied in series or parallel. A non-zero -c value means that the supplied Mapping is equivalent to applying map1 -c followed by map2 in series. A zero value means that the supplied -c Mapping is equivalent to applying map1 to the lower numbered axes -c and map2 to the higher numbered axes, in parallel. -f Indicates if the -f component Mappings are applied in series or parallel. A .TRUE. -f value means that the supplied Mapping is equivalent to applying MAP1 -f followed by MAP2 in series. A zero value means that the supplied -f Mapping is equivalent to applying MAP1 to the lower numbered axes -f and MAP2 to the higher numbered axes, in parallel. -c invert1 -f INVERT1 = INTEGER (Returned) -c The value of the Invert attribute to be used with map1. -f The value of the Invert attribute to be used with MAP1. -c invert2 -f INVERT2 = INTEGER (Returned) -c The value of the Invert attribute to be used with map2. -f The value of the Invert attribute to be used with MAP2. - -* Applicability: -* CmpMap -c If the supplied Mapping is a CmpMap, then map1 and map2 will be -f If the supplied Mapping is a CmpMap, then MAP1 and MAP2 will be -* returned holding pointers to the component Mappings used to -* create the CmpMap, either in series or parallel. Note, changing -* the Invert attribute of either of the component Mappings using -* the returned pointers will have no effect on the supplied CmpMap. -* This is because the CmpMap remembers and uses the original settings -* of the Invert attributes (that is, the values of the Invert -* attributes when the CmpMap was first created). These are the -c Invert values which are returned in invert1 and invert2. -f Invert values which are returned in INVERT1 and INVERT2. -* TranMap -c If the supplied Mapping is a TranMap, then map1 and map2 will be -f If the supplied Mapping is a TranMap, then MAP1 and MAP2 will be -* returned holding pointers to the forward and inverse Mappings -* represented by the TranMap (zero will be returned for -c series). -f SERIES). -* Note, changing the Invert attribute of -* either of the component Mappings using the returned pointers will -* have no effect on the supplied TranMap. This is because the TranMap -* remembers and uses the original settings of the Invert attributes -* (that is, the values of the Invert attributes when the TranMap was -* first created). These are the -c Invert values which are returned in invert1 and invert2. -f Invert values which are returned in INVERT1 and INVERT2. -* Mapping -c For any class of Mapping other than a CmpMap, map1 will be -c returned holding a clone of the supplied Mapping pointer, and map2 -c will be returned holding a NULL pointer. Invert1 will be returned -c holding the current value of the Invert attribute for the supplied -c Mapping, and invert2 will be returned holding zero. -f For any class of Mapping other than a CmpMap, MAP1 will be -f returned holding a clone of the supplied Mapping pointer, and MAP2 -f will be returned holding AST__NULL. INVERT1 will be returned -f holding the current value of the Invert attribute for the supplied -f Mapping, and INVERT2 will be returned holding zero. -* CmpFrame -c If the supplied Mapping is a CmpFrame, then map1 and map2 will be -f If the supplied Mapping is a CmpFrame, then MAP1 and MAP2 will be -* returned holding pointers to the component Frames used to -* create the CmpFrame. The component Frames are considered to be in -* applied in parallel. -* Frame -c For any class of Frame other than a CmpFrame, map1 will be -c returned holding a clone of the supplied Frame pointer, and map2 -c will be returned holding a NULL pointer. -f For any class of Frame other than a CmpFrame, MAP1 will be -f returned holding a clone of the supplied Frame pointer, and MAP2 -f will be returned holding AST__NULL. - -* Notes: -* - The returned Invert values should be used in preference to the -* current values of the Invert attribute in map1 and map2. This is -* because the attributes may have changed value since the Mappings -* were combined. -* - Any changes made to the component Mappings using the returned -* pointers will be reflected in the supplied Mapping. - -*-- - -* Implementation Notes: -* This function implements the public interface for the -* astDecompose method. It is identical to astDecompose_ except for -* the following: -* -* - ID values are returned via the "map1" and "map2" parameters -* instead of true C pointers. This is required because this -* conversion cannot be performed by the macro that invokes the -* function. -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Invoke the normal astDecompose_ function to decompose the Mapping. */ - astDecompose( this, map1, map2, series, invert1, invert2 ); - -/* If required, return ID values for the component Mappings. */ - if ( map1 ) *map1 = astMakeId( *map1 ); - if ( map2 ) *map2 = astMakeId( *map2 ); - -} - -void astMapBoxId_( AstMapping *this, - const double lbnd_in[], const double ubnd_in[], - int forward, int coord_out, - double *lbnd_out, double *ubnd_out, - double xl[], double xu[], int *status ) { -/* -*++ -* Name: -c astMapBox -f AST_MAPBOX - -* Purpose: -* Find a bounding box for a Mapping. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astMapBox( AstMapping *this, -c const double lbnd_in[], const double ubnd_in[], -c int forward, int coord_out, -c double *lbnd_out, double *ubnd_out, -c double xl[], double xu[] ); -f CALL AST_MAPBOX( THIS, LBND_IN, UBND_IN, FORWARD, COORD_OUT, -f LBND_OUT, UBND_OUT, XL, XU, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function allows you to find the "bounding box" which just -c encloses another box after it has been transformed by a Mapping -c (using either its forward or inverse transformation). A typical -c use might be to calculate the size of an image after being -c transformed by a Mapping. -f This routine allows you to find the "bounding box" which just -f encloses another box after it has been transformed by a Mapping -f (using either its forward or inverse transformation). A typical -f use might be to calculate the size of an image after being -f transformed by a Mapping. -* -c The function works on one dimension at a time. When supplied -c with the lower and upper bounds of a rectangular region (box) of -c input coordinate space, it finds the lowest and highest values -c taken by a nominated output coordinate within that -c region. Optionally, it also returns the input coordinates where -c these bounding values are attained. It should be used repeatedly -c to obtain the extent of the bounding box in more than one -c dimension. -f The routine works on one dimension at a time. When supplied with -f the lower and upper bounds of a rectangular region (box) of -f input coordinate space, it finds the lowest and highest values -f taken by a nominated output coordinate within that region. It -f also returns the input coordinates where these bounding values -f are attained. It should be used repeatedly to obtain the extent -f of the bounding box in more than one dimension. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping. -c lbnd_in -f LBND_IN( * ) = DOUBLE PRECISION (Given) -c Pointer to an array of double, with one element for each -c Mapping input coordinate. This should contain the lower bound -c of the input box in each input dimension. -f An array with one element for each Mapping input -f coordinate. This should contain the lower bound of the input -f box in each input dimension. -c ubnd_in -f UBND_IN( * ) = DOUBLE PRECISION (Given) -c Pointer to an array of double, with one element for each -c Mapping input coordinate. This should contain the upper bound -c of the input box in each input dimension. -f An array with one element for each Mapping input -f coordinate. This should contain the upper bound of the input -f box in each input dimension. -* -* Note that it is permissible for the upper bound to be less -* than the corresponding lower bound, as the values will simply -* be swapped before use. -c forward -f FORWARD = LOGICAL (Given) -c If this value is non-zero, then the Mapping's forward -c transformation will be used to transform the input -c box. Otherwise, its inverse transformation will be used. -f If this value is .TRUE., then the Mapping's forward -f transformation will be used to transform the input -f box. Otherwise, its inverse transformation will be used. -* -c (If the inverse transformation is selected, then references -c to "input" and "output" coordinates in this description -c should be transposed. For example, the size of the "lbnd_in" -c and "ubnd_in" arrays should match the number of output -c coordinates, as given by the Mapping's Nout -c attribute. Similarly, the "coord_out" parameter, below, -c should nominate one of the Mapping's input coordinates.) -f (If the inverse transformation is selected, then references -f to "input" and "output" coordinates in this description -f should be transposed. For example, the size of the LBND_IN -f and UBND_IN arrays should match the number of output -f coordinates, as given by the Mapping's Nout attribute. -f Similarly, the COORD_OUT argument, below, should nominate one -f of the Mapping's input coordinates.) -c coord_out -f COORD_OUT = INTEGER (Given) -* The index of the output coordinate for which the lower and -* upper bounds are required. This value should be at least one, -* and no larger than the number of Mapping output coordinates. -c lbnd_out -f LBND_OUT = DOUBLE PRECISION (Returned) -c Pointer to a double in which to return the lowest value taken -c by the nominated output coordinate within the specified -c region of input coordinate space. -f The lowest value taken by the nominated output coordinate -f within the specified region of input coordinate space. -c ubnd_out -f UBND_OUT = DOUBLE PRECISION (Returned) -c Pointer to a double in which to return the highest value -c taken by the nominated output coordinate within the specified -c region of input coordinate space. -f The highest value taken by the nominated output coordinate -f within the specified region of input coordinate space. -c xl -f XL( * ) = DOUBLE PRECISION (Returned) -c An optional pointer to an array of double, with one element -c for each Mapping input coordinate. If given, this array will -c be filled with the coordinates of an input point (although -c not necessarily a unique one) for which the nominated output -c coordinate attains the lower bound value returned in -c "*lbnd_out". -c -c If these coordinates are not required, a NULL pointer may be -c supplied. -f An array with one element for each Mapping input -f coordinate. This will return the coordinates of an input -f point (although not necessarily a unique one) for which the -f nominated output coordinate attains the lower bound value -f returned in LBND_OUT. -c xu -f XU( * ) = DOUBLE PRECISION (Returned) -c An optional pointer to an array of double, with one element -c for each Mapping input coordinate. If given, this array will -c be filled with the coordinates of an input point (although -c not necessarily a unique one) for which the nominated output -c coordinate attains the upper bound value returned in -c "*ubnd_out". -c -c If these coordinates are not required, a NULL pointer may be -c supplied. -f An array with one element for each Mapping input -f coordinate. This will return the coordinates of an input -f point (although not necessarily a unique one) for which the -f nominated output coordinate attains the upper bound value -f returned in UBND_OUT. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Notes: -* - Any input points which are transformed by the Mapping to give -* output coordinates containing the value AST__BAD are regarded as -* invalid and are ignored. They will make no contribution to -* determining the output bounds, even although the nominated -* output coordinate might still have a valid value at such points. -c - An error will occur if the required output bounds cannot be -c found. Typically, this might happen if all the input points -c which the function considers turn out to be invalid (see -c above). The number of points considered before generating such -c an error is quite large, so this is unlikely to occur by -c accident unless valid points are restricted to a very small -c subset of the input coordinate space. -f - An error will occur if the required output bounds cannot be -f found. Typically, this might happen if all the input points -f which the routine considers turn out to be invalid (see -f above). The number of points considered before generating such -f an error is quite large, so this is unlikely to occur by -f accident unless valid points are restricted to a very small -f subset of the input coordinate space. -c - The values returned via "lbnd_out", "ubnd_out", "xl" and "xu" -c will be set to the value AST__BAD if this function should fail -c for any reason. Their initial values on entry will not be -c altered if the function is invoked with the AST error status -c set. -f - The values returned via LBND_OUT, UBND_OUT, XL and XU will be -f set to the value AST__BAD if this routine should fail for any -f reason. Their initial values on entry will not be altered if the -f routine is invoked with STATUS set to an error value. -*-- - -* Implementation Notes: -* This function implements the public interface for the astMapBox -* method. It is identical to astMapBox_ except that the nominated -* output coordinate given in "coord_out" is decremented by one -* before use. This is to allow the public interface to use -* one-based coordinate numbering (internally, zero-based -* coordinate numbering is used). -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Invoke the protected version of this function with the "coord_out" - value decremented. */ - astMapBox( this, lbnd_in, ubnd_in, forward, coord_out - 1, - lbnd_out, ubnd_out, xl, xu ); -} - -double astRateId_( AstMapping *this, double *at, int ax1, int ax2, int *status ){ -/* -*++ -* Name: -c astRate -f AST_RATE - -* Purpose: -* Calculate the rate of change of a Mapping output. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c double astRate( AstMapping *this, double *at, int ax1, int ax2 ) -f RESULT = AST_RATE( THIS, AT, AX1, AX2, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function -f This routine -* evaluates the rate of change of a specified output of the supplied -* Mapping with respect to a specified input, at a specified input -* position. -* -* The result is estimated by interpolating the function using a -* fourth order polynomial in the neighbourhood of the specified -* position. The size of the neighbourhood used is chosen to minimise -* the RMS residual per unit length between the interpolating -* polynomial and the supplied Mapping function. This method produces -* good accuracy but can involve evaluating the Mapping 100 or more -* times. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping to be applied. -c at -f AT( * ) = DOUBLE PRECISION (Given) -c The address of an -f An -* array holding the axis values at the position at which the rate -* of change is to be evaluated. The number of elements in this -* array should equal the number of inputs to the Mapping. -c ax1 -f AX1 = INTEGER (Given) -* The index of the Mapping output for which the rate of change is to -* be found (output numbering starts at 1 for the first output). -c ax2 -f AX2 = INTEGER (Given) -* The index of the Mapping input which is to be varied in order to -* find the rate of change (input numbering starts at 1 for the first -* input). -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astRate() -f AST_RATE = DOUBLE PRECISION -c The rate of change of Mapping output "ax1" with respect to input -c "ax2", evaluated at "at", or AST__BAD if the value cannot be -c calculated. -f The rate of change of Mapping output AX1 with respect to input -f AX2, evaluated at AT, or AST__BAD if the value cannot be -f calculated. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*-- - -* Implementation Notes: -* This function implements the public interface for the astRate -* method. It is identical to astRate_ except that the nominated -* coordinates given in "ax1" and "ax2" are decremented by one -* before use. This is to allow the public interface to use -* one-based coordinate numbering (internally, zero-based -* coordinate numbering is used). -*/ - -/* Check the global error status. */ - if ( !astOK ) return AST__BAD; - -/* Invoke the protected version of this function with the axis indices - decremented. */ - return astRate( this, at, ax1 - 1, ax2 - 1 ); -} - -void astMapSplitId_( AstMapping *this, int nin, const int *in, int *out, - AstMapping **map, int *status ){ -/* -*++ -* Name: -c astMapSplit -f AST_MAPSPLIT - -* Purpose: -* Split a Mapping up into parallel component Mappings. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "mapping.h" -c void astMapSplit( AstMapping *this, int nin, const int *in, int *out, -c AstMapping **map ) -f CALL AST_MAPSPLIT( THIS, NIN, IN, OUT, MAP, STATUS ) - -* Class Membership: -* Mapping method. - -* Description: -c This function -f This routine -* creates a new Mapping which connects specified inputs within a -* supplied Mapping to the corresponding outputs of the supplied Mapping. -* This is only possible if the specified inputs correspond to some -* subset of the Mapping outputs. That is, there must exist a subset of -* the Mapping outputs for which each output depends only on the selected -* Mapping inputs, and not on any of the inputs which have not been -* selected. Also, any output which is not in this subset must not depend -* on any of the selected inputs. If these conditions are not met by the -* supplied Mapping, then -c a NULL -f an AST__NULL -* Mapping pointer is returned. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Mapping to be split. -c nin -f NIN = INTEGER (Given) -c The number of inputs to pick from "this". -f The number of inputs to pick from THIS. -c in -f IN( NIN ) = INTEGER (Given) -c Pointer to an -f An -* array holding the indices within the supplied Mapping of the inputs -* which are to be picked from the Mapping. -c This array should have "nin" elements. -* If "Nin" is the number of inputs of the supplied Mapping, then each -* element should have a value in the range 1 to Nin. -c out -f OUT( * ) = INTEGER (Returned) -c Pointer to an -f An -* array in which to return the indices of the outputs of the supplied -* Mapping which are fed by the picked inputs. A value of one is -* used to refer to the first Mapping output. The supplied array should -* have a length at least equal to the number of outputs in the -* supplied Mapping. The number of values stored in the array on -* exit will equal the number of outputs in the returned Mapping. -* The i'th element in the returned array holds the index within -* the supplied Mapping which corresponds to the i'th output of -* the returned Mapping. -c map -f MAP = INTEGER (Returned) -c Address of a location at which to return a pointer to the -f The -* returned Mapping. This Mapping will have -c "nin" inputs (the number of outputs may be different to "nin"). NULL -f NIN inputs (the number of outputs may be different to NIN). AST__NULL -* is returned if the supplied Mapping has no subset of outputs which -* depend only on the selected inputs. The returned Mapping is a -* deep copy of the required parts of the supplied Mapping. - -* Notes: -* - If this -c function -f routine -* is invoked with the global error status set, or if it should fail for -* any reason, then -c a NULL value -f AST__NULL -* will be returned for -c the "map" pointer. -f MAP. -*-- - -* Implementation Notes: -* - This function implements the astMapSplit method available via the -* public interface to the Mapping class and uses 1-based axis indices. -* The protected interface method is provided by the astMapSplit function -* and uses zero-based axis indices. Also, an ID value is returned for -* "map" rather than a pointer. -*/ - -/* Local Variables: */ - int *in_zero; /* Pointer to array of zero-based input indices */ - int *result; /* Pointer to array of zero-based output indices*/ - int i; /* Axis index */ - int nout; /* No of outputs */ - -/* Initialise */ - *map = NULL; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Decrement the axis indices by 1. */ - in_zero = astMalloc( sizeof( int )*(size_t) nin ); - if( in_zero ) { - for( i = 0; i < nin; i++ ) in_zero[ i ] = in[ i ] - 1; - -/* Invoked the protected astMapSplit functon. */ - result = astMapSplit( this, nin, in_zero, map ); - -/* If succesful, copy the output axes to the supplied array. */ - if( result ) { - nout = astGetNout( *map ); - for( i = 0; i < nout; i++ ) out[ i ] = result[ i ] + 1; - -/* Free resurces. */ - result = astFree( result ); - } - in_zero = astFree( in_zero ); - } - -/* Free the returned Mapping if an error has occurred. */ - if( !astOK ) *map = astAnnul( *map ); - -/* Return an ID value for the Mapping. */ - *map = astMakeId( *map ); -} - - - - - - - - |