summaryrefslogtreecommitdiffstats
path: root/ast/mapping.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2019-05-10 15:55:01 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2019-05-10 15:55:01 (GMT)
commit9646e8d50bc1481de77459d59738826f9c256ad6 (patch)
treee47684c08ae346d96e3c6ea8780f3886fe74e6f6 /ast/mapping.c
parent37e757832a7f2c690cea41df5bf9cfa9ee18f67f (diff)
downloadblt-9646e8d50bc1481de77459d59738826f9c256ad6.zip
blt-9646e8d50bc1481de77459d59738826f9c256ad6.tar.gz
blt-9646e8d50bc1481de77459d59738826f9c256ad6.tar.bz2
upgrade ast 8.7.1
Diffstat (limited to 'ast/mapping.c')
-rw-r--r--ast/mapping.c24732
1 files changed, 0 insertions, 24732 deletions
diff --git a/ast/mapping.c b/ast/mapping.c
deleted file mode 100644
index e2b131f..0000000
--- a/ast/mapping.c
+++ /dev/null
@@ -1,24732 +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.
-*--
-
-* 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 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 repalced 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 );
-}
-
-
-
-
-
-
-
-