/* *+ * Name: * fintramap.c * Purpose: * Define a FORTRAN 77 interface to the AST IntraMap class. * Type of Module: * C source file. * Description: * This file defines FORTRAN 77-callable C functions which provide * a public FORTRAN 77 interface to the IntraMap class. * Routines Defined: * AST_INTRAMAP * AST_INTRAREG * AST_ISAINTRAMAP * 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 * . * Authors: * RFWS: R.F. Warren-Smith (Starlink) * History: * 18-MAR-1998 (RFWS): * Original version. * 15-SEP-1999 (RFWS): * Added a THIS pointer to the external transformation function * used by an IntraMap. */ /* Define the astFORTRAN77 macro which prevents error messages from AST C functions from reporting the file and line number where the error occurred (since these would refer to this file, they would not be useful). */ #define astFORTRAN77 /* Header files. */ /* ============= */ #include "f77.h" /* FORTRAN <-> C interface macros (SUN/209) */ #include "c2f77.h" /* F77 <-> C support functions/macros */ #include "error.h" /* Error reporting facilities */ #include "memory.h" /* Memory handling facilities */ #include "intramap.h" /* C interface to the IntraMap class */ #include #include /* Prototypes for private functions. */ /* ================================= */ static void TranWrap( void (*)( AstMapping *, int, int, const double *[], int, int, double *[] ), AstMapping *, int, int, const double *[], int, int, double *[], int * ); /* Transformation function interface. */ /* ================================== */ /* This is concerned with allowing FORTRAN implementations of transformation functions to be passed to the IntraMap class and invoked when necessary by C code in the main class implementation. All FORTRAN-specific aspects of this interface are encapsulated here. */ static void TranWrap( void (* tran)( AstMapping *, int, int, const double *[], int, int, double *[] ), AstMapping *this, int npoint, int ncoord_in, const double *ptr_in[], int forward, int ncoord_out, double *ptr_out[], int *status ) { /* * Name: * TranWrap * Purpose: * Wrapper function to invoke a FORTRAN transformation function. * Type: * Private function. * Synopsis: * void TranWrap( void (* tran)( AstMapping *, int, int, const double *[], * int, int, double *[] ), * AstMapping *this, int npoint, int ncoord_in, * const double *ptr_in[], int forward, int ncoord_out, * double *ptr_out[], int *status ) * Description: * This function invokes a FORTRAN implementation of a * transformation function (which resembles AST_TRANN from the * Mapping class FORTRAN interface) in order to make it callable by * C code which would prefer to call a C function that resembles * astTranP (from the Mapping class C interface). * Parameters: * tran * Pointer to the FORTRAN transformation function to be invoked. * This should result from a cast applied to a pointer to a * function that resembles AST_TRANN (but with the first * argument omitted). * this * An external Mapping ID associated with the internal (true C) pointer * for the IntraMap whose transformation is being evaluated. * 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]". * forward * A non-zero value indicates that the 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 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]". * status * Pointer to the inherited status value. */ /* Local Variables; */ DECLARE_INTEGER(INDIM); /* First dimension size of input array */ DECLARE_INTEGER(NCOORD_IN); /* Number of input coordinates */ DECLARE_INTEGER(NCOORD_OUT); /* Number of output coordinates */ DECLARE_INTEGER(NPOINT); /* Number of points */ DECLARE_INTEGER(OUTDIM); /* First dimension size of output array */ DECLARE_INTEGER(STATUS); /* FORTRAN error status variable */ DECLARE_INTEGER(THIS); /* External ID for the IntraMap */ DECLARE_LOGICAL(FORWARD); /* Use forward transformation? */ F77_DOUBLE_TYPE *IN; /* Input coordinate array for FORTRAN */ F77_DOUBLE_TYPE *OUT; /* Output coordinate array for FORTRAN */ int coord; /* Loop counter for coordinates */ int i; /* Index into FORTRAN arrays */ /* Check the global error status. */ if ( !astOK ) return; /* Assign input values to the arguments for the FORTRAN transformation function. */ THIS = astP2I( this ); NPOINT = npoint; NCOORD_IN = ncoord_in; INDIM = npoint; FORWARD = forward ? F77_TRUE : F77_FALSE; NCOORD_OUT = ncoord_out; OUTDIM = npoint; /* Since the input/output coordinate values may be stored in separate arrays, we must move them temporarily into new 2-dimensional arrays, as required by the FORTRAN transformation function interface. Allocate memory for these arrays. */ IN = astMalloc( (size_t) ( npoint * ncoord_in ) * sizeof( F77_DOUBLE_TYPE ) ); OUT = astMalloc( (size_t) ( npoint * ncoord_out ) * sizeof( F77_DOUBLE_TYPE ) ); /* If OK, fill the input array with coordinate values. Use "memcpy" to avoid numerical errors if the data contain junk - this allows the transformation function to produce the appropriate error instead of it happening here. */ if ( astOK ) { i = 0; for ( coord = 0; coord < ncoord_in; coord++ ) { (void) memcpy( IN + i, ptr_in[ coord ], (size_t) npoint * sizeof( F77_DOUBLE_TYPE ) ); i += npoint; } } /* Cast the transformation function pointer to a pointer to the FORTRAN subroutine and then invoke it. Transfer the AST error status to and from the subroutine's error status argument. */ if ( astOK ) { STATUS = astStatus; ( *(void (*)()) tran )( INTEGER_ARG(&THIS), INTEGER_ARG(&NPOINT), INTEGER_ARG(&NCOORD_IN), INTEGER_ARG(&INDIM), DOUBLE_ARRAY_ARG(IN), LOGICAL_ARG(&FORWARD), INTEGER_ARG(&NCOORD_OUT), INTEGER_ARG(&OUTDIM), DOUBLE_ARRAY_ARG(OUT), INTEGER_ARG(&STATUS) ); astSetStatus( STATUS ); } /* If OK, transfer the transformed coordinate values to the output arrays. */ if ( astOK ) { i = 0; for ( coord = 0; coord < ncoord_out; coord++ ) { (void) memcpy( ptr_out[ coord ], OUT + i, (size_t) npoint * sizeof( F77_DOUBLE_TYPE ) ); i += npoint; } } /* Free the temporary arrays. */ astFree( IN ); astFree( OUT ); } /* FORTRAN interface functions. */ /* ============================ */ /* These functions implement the remainder of the FORTRAN interface. */ F77_SUBROUTINE(ast_intrareg)( CHARACTER(NAME), INTEGER(NIN), INTEGER(NOUT), void (* TRAN)(), INTEGER(FLAGS), CHARACTER(PURPOSE), CHARACTER(AUTHOR), CHARACTER(CONTACT), INTEGER(STATUS) TRAIL(NAME) TRAIL(PURPOSE) TRAIL(AUTHOR) TRAIL(CONTACT) ) { GENPTR_CHARACTER(NAME) GENPTR_INTEGER(NIN) GENPTR_INTEGER(NOUT) GENPTR_INTEGER(FLAGS) GENPTR_CHARACTER(PURPOSE) GENPTR_CHARACTER(AUTHOR) GENPTR_CHARACTER(CONTACT) char *name; void (* tran)( AstMapping *, int, int, const double *[], int, int, double *[] ); char *purpose; char *author; char *contact; astAt( "AST_INTRAREG", NULL, 0 ); astWatchSTATUS( name = astString( NAME, NAME_length ); tran = (void (*)( AstMapping *, int, int, const double *[], int, int, double *[] )) TRAN; purpose = astString( PURPOSE, PURPOSE_length ); author = astString( AUTHOR, AUTHOR_length ); contact = astString( CONTACT, CONTACT_length ); astIntraRegFor( name, *NIN, *NOUT, tran, TranWrap, *FLAGS, purpose, author, contact ); astFree( name ); astFree( purpose ); astFree( author ); astFree( contact ); ) } F77_INTEGER_FUNCTION(ast_intramap)( CHARACTER(NAME), INTEGER(NIN), INTEGER(NOUT), CHARACTER(OPTIONS), INTEGER(STATUS) TRAIL(NAME) TRAIL(OPTIONS) ) { GENPTR_CHARACTER(NAME) GENPTR_INTEGER(NIN) GENPTR_INTEGER(NOUT) GENPTR_CHARACTER(OPTIONS) F77_INTEGER_TYPE(RESULT); char *name; char *options; int i; astAt( "AST_INTRAMAP", NULL, 0 ); astWatchSTATUS( name = astString( NAME, NAME_length ); options = astString( OPTIONS, OPTIONS_length ); /* Truncate the options string to exlucde any trailing spaces. */ astChrTrunc( options ); /* Change ',' to '\n' (see AST_SET in fobject.c for why). */ if ( astOK ) { for ( i = 0; options[ i ]; i++ ) { if ( options[ i ] == ',' ) options[ i ] = '\n'; } } RESULT = astP2I( astIntraMap( name, *NIN, *NOUT, "%s", options ) ); astFree( name ); astFree( options ); ) return RESULT; } F77_LOGICAL_FUNCTION(ast_isaintramap)( INTEGER(THIS), INTEGER(STATUS) ) { GENPTR_INTEGER(THIS) F77_LOGICAL_TYPE(RESULT); astAt( "AST_ISAINTRAMAP", NULL, 0 ); astWatchSTATUS( RESULT = astIsAIntraMap( astI2P( *THIS ) ) ? F77_TRUE : F77_FALSE; ) return RESULT; }