1 /*
2  Author: Michael Droettboom
3          mdroe@stsci.edu
4 */
5 
6 #ifndef __PYUTIL_H__
7 #define __PYUTIL_H__
8 
9 #include "util.h"
10 
11 #define PY_ARRAY_UNIQUE_SYMBOL astropy_wcs_numpy_api
12 
13 #include <Python.h>
14 
15 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
16 #include <numpy/arrayobject.h>
17 #include <numpy/npy_math.h>
18 
19 PyObject*
20 PyArrayProxy_New(
21     PyObject* self,
22     int nd,
23     const npy_intp* dims,
24     int typenum,
25     const void* data);
26 
27 PyObject*
28 PyArrayReadOnlyProxy_New(
29     PyObject* self,
30     int nd,
31     const npy_intp* dims,
32     int typenum,
33     const void* data);
34 
35 /*@null@*/ PyObject *
36 PyStrListProxy_New(
37     PyObject* owner,
38     Py_ssize_t size,
39     Py_ssize_t maxsize,
40     char (*array)[72]
41     );
42 
43 int
44 _setup_str_list_proxy_type(
45     PyObject* m);
46 
47 static INLINE void
offset_c_array(double * value,npy_intp size,double offset)48 offset_c_array(
49     double* value,
50     npy_intp size,
51     double offset) {
52   double* end = value + size;
53 
54   for ( ; value != end; ++value) {
55     *value += offset;
56   }
57 }
58 
59 static INLINE
nan2undefined(double * value,unsigned int nvalues)60 void nan2undefined(
61     double* value,
62     unsigned int nvalues) {
63 
64   double* end = value + nvalues;
65 
66   for ( ; value != end; ++value) {
67     if (isnan64(*value)) {
68       *value = UNDEFINED;
69     }
70   }
71 }
72 
73 static INLINE
undefined2nan(double * value,unsigned int nvalues)74 void undefined2nan(
75     double* value,
76     unsigned int nvalues) {
77 
78   double* end = value + nvalues;
79 
80   for ( ; value != end; ++value) {
81     if (*value == UNDEFINED) {
82       *value = (double)NPY_NAN;
83     }
84   }
85 }
86 
87 void
88 preoffset_array(
89     PyArrayObject* array,
90     int value);
91 
92 void
93 unoffset_array(
94     PyArrayObject* array,
95     int value);
96 
97 void
98 copy_array_to_c_double(
99     PyArrayObject* array,
100     double* dest);
101 
102 void
103 copy_array_to_c_int(
104     PyArrayObject* array,
105     int* dest);
106 
107 /**
108  Returns TRUE if pointer is NULL, and sets Python exception
109 */
110 int
111 is_null(/*@null@*/ void *);
112 
113 typedef void (*value_fixer_t)(double*, unsigned int);
114 
115 void
116 wcsprm_c2python(
117     /*@null@*/ struct wcsprm* x);
118 
119 void
120 wcsprm_python2c(
121     /*@null@*/ struct wcsprm* x);
122 
123 /***************************************************************************
124  * Exceptions                                                              *
125  ***************************************************************************/
126 
127 extern PyObject* WcsExc_SingularMatrix;
128 extern PyObject* WcsExc_InconsistentAxisTypes;
129 extern PyObject* WcsExc_InvalidTransform;
130 extern PyObject* WcsExc_InvalidCoordinate;
131 extern PyObject* WcsExc_NoSolution;
132 extern PyObject* WcsExc_InvalidSubimageSpecification;
133 extern PyObject* WcsExc_NonseparableSubimageCoordinateSystem;
134 extern PyObject* WcsExc_NoWcsKeywordsFound;
135 extern PyObject* WcsExc_InvalidTabularParameters;
136 
137 /* This is an array mapping the wcs status codes to Python exception
138  * types.  The exception string is stored as part of wcslib itself in
139  * wcs_errmsg.
140  */
141 extern PyObject** wcs_errexc[14];
142 #define WCS_ERRMSG_MAX 14
143 #define WCSFIX_ERRMSG_MAX 11
144 
145 int
146 _define_exceptions(PyObject* m);
147 
148 const char*
149 wcslib_get_error_message(int stat);
150 
151 void
152 wcserr_to_python_exc(const struct wcserr *err);
153 
154 void
155 wcs_to_python_exc(const struct wcsprm *wcs);
156 
157 void
158 wcshdr_err_to_python_exc(int status, const struct wcsprm *wcs);
159 
160 void
161 wcserr_fix_to_python_exc(const struct wcserr *err);
162 
163 /***************************************************************************
164   Property helpers
165  ***************************************************************************/
166 static INLINE int
check_delete(const char * propname,PyObject * value)167 check_delete(
168     const char* propname,
169     PyObject* value) {
170 
171   if (value == NULL) {
172     PyErr_Format(PyExc_TypeError, "'%s' can not be deleted", propname);
173     return -1;
174   }
175 
176   return 0;
177 }
178 
179 static INLINE PyObject*
get_string(const char * propname,const char * value)180 get_string(
181     /*@unused@*/ const char* propname,
182     const char* value) {
183   return PyUnicode_FromString(value);
184 }
185 
186 int
187 set_string(
188     const char* propname,
189     PyObject* value,
190     char* dest,
191     Py_ssize_t maxlen);
192 
193 static INLINE PyObject*
get_bool(const char * propname,long value)194 get_bool(
195     /*@unused@*/ const char* propname,
196     long value) {
197 
198   return PyBool_FromLong(value);
199 }
200 
201 int
202 set_bool(
203     const char* propname,
204     PyObject* value,
205     int* dest);
206 
207 static INLINE PyObject*
get_int(const char * propname,long value)208 get_int(
209     /*@unused@*/ const char* propname,
210     long value) {
211 
212   return PyLong_FromLong(value);
213 }
214 
215 int
216 set_int(
217     const char* propname,
218     PyObject* value,
219     int* dest);
220 
221 static INLINE PyObject*
get_double(const char * propname,double value)222 get_double(
223     const char* propname,
224     double value) {
225 
226   return PyFloat_FromDouble(value);
227 }
228 
229 int
230 set_double(
231     const char* propname,
232     PyObject* value,
233     double* dest);
234 
235 /*@null@*/ static INLINE PyObject*
get_double_array(const char * propname,double * value,int ndims,const npy_intp * dims,PyObject * owner)236 get_double_array(
237     /*@unused@*/ const char* propname,
238     double* value,
239     int ndims,
240     const npy_intp* dims,
241     /*@shared@*/ PyObject* owner) {
242 
243   return PyArrayProxy_New(owner, ndims, dims, NPY_DOUBLE, value);
244 }
245 
246 /*@null@*/ static INLINE PyObject*
get_double_array_readonly(const char * propname,double * value,int ndims,const npy_intp * dims,PyObject * owner)247 get_double_array_readonly(
248     /*@unused@*/ const char* propname,
249     double* value,
250     int ndims,
251     const npy_intp* dims,
252     /*@shared@*/ PyObject* owner) {
253 
254   return PyArrayReadOnlyProxy_New(owner, ndims, dims, NPY_DOUBLE, value);
255 }
256 
257 int
258 set_double_array(
259     const char* propname,
260     PyObject* value,
261     int ndims,
262     const npy_intp* dims,
263     double* dest);
264 
265 /*@null@*/ static INLINE PyObject*
get_int_array(const char * propname,int * value,int ndims,const npy_intp * dims,PyObject * owner)266 get_int_array(
267     /*@unused@*/ const char* propname,
268     int* value,
269     int ndims,
270     const npy_intp* dims,
271     /*@shared@*/ PyObject* owner) {
272 
273   return PyArrayProxy_New(owner, ndims, dims, NPY_INT, value);
274 }
275 
276 int
277 set_int_array(
278     const char* propname,
279     PyObject* value,
280     int ndims,
281     const npy_intp* dims,
282     int* dest);
283 
284 static INLINE PyObject*
get_str_list(const char * propname,char (* array)[72],Py_ssize_t len,Py_ssize_t maxlen,PyObject * owner)285 get_str_list(
286     /*@unused@*/ const char* propname,
287     char (*array)[72],
288     Py_ssize_t len,
289     Py_ssize_t maxlen,
290     PyObject* owner) {
291 
292   return PyStrListProxy_New(owner, len, maxlen, array);
293 }
294 
295 int
296 set_str_list(
297     const char* propname,
298     PyObject* value,
299     Py_ssize_t len,
300     Py_ssize_t maxlen,
301     char (*dest)[72]);
302 
303 PyObject*
304 get_pscards(
305     const char* propname,
306     struct pscard* ps,
307     int nps);
308 
309 int
310 set_pscards(
311     const char* propname,
312     PyObject* value,
313     struct pscard** ps,
314     int *nps,
315     int *npsmax);
316 
317 PyObject*
318 get_pvcards(
319     const char* propname,
320     struct pvcard* pv,
321     int npv);
322 
323 int
324 set_pvcards(
325     const char* propname,
326     PyObject* value,
327     struct pvcard** pv,
328     int *npv,
329     int *npvmax);
330 
331 PyObject*
332 get_deepcopy(
333     PyObject* obj,
334     PyObject* memo);
335 
336 /***************************************************************************
337   Miscellaneous helper functions
338  ***************************************************************************/
339 
340 int
341 parse_unsafe_unit_conversion_spec(
342     const char* arg, int* ctrl);
343 
344 #endif /* __PYUTIL_H__ */
345