~ubuntu-branches/ubuntu/oneiric/python-scipy/oneiric-proposed

« back to all changes in this revision

Viewing changes to scipy/sandbox/xplt/pygist/gistfuncsmodule.c

  • Committer: Bazaar Package Importer
  • Author(s): Ondrej Certik
  • Date: 2008-06-16 22:58:01 UTC
  • mfrom: (2.1.24 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080616225801-irdhrpcwiocfbcmt
Tags: 0.6.0-12
* The description updated to match the current SciPy (Closes: #489149).
* Standards-Version bumped to 3.8.0 (no action needed)
* Build-Depends: netcdf-dev changed to libnetcdf-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1996, 1997, The Regents of the University of California.
 
2
 * All rights reserved.  See Legal.htm for full text and disclaimer. */
 
3
#include "Python.h"
 
4
#include "numpy/arrayobject.h"
 
5
/*#include "hlevel.h"*/
 
6
#include <stdio.h>
 
7
#include <stdlib.h>
 
8
 
 
9
#define MAX_INTERP_DIMS 6
 
10
 
 
11
static PyObject *ErrorObject;
 
12
 
 
13
/* Define 2 macros for error handling:
 
14
   Py_Try(BOOLEAN)
 
15
   If BOOLEAN is FALSE, assume the error object has
 
16
   been set and return NULL
 
17
 
 
18
   Py_Assert(BOOLEAN,ERROBJ,MESS)
 
19
   If BOOLEAN is FALSE set the error object to
 
20
   ERROBJ, and the message to MESS
 
21
 
 
22
*/
 
23
 
 
24
static char * errstr = NULL ;
 
25
 
 
26
#define Py_Try(BOOLEAN) {if (!(BOOLEAN)) return NULL;}
 
27
#define Py_Assert(BOOLEAN,ERROBJ,MESS) {if (!(BOOLEAN)) { \
 
28
                                           PyErr_SetString((ERROBJ), (MESS)); \
 
29
                                           return NULL;} \
 
30
                                       }
 
31
#define A_DATA(a) (((PyArrayObject *)a)->data)
 
32
#define A_SIZE(a) PyArray_Size((PyObject *) a)
 
33
#define A_TYPE(a) (int)(((PyArrayObject *)a)->descr->type_num)
 
34
#define isARRAY(a) ((a) && PyArray_Check((PyArrayObject *)a))
 
35
#define A_NDIM(a) (((PyArrayObject *)a)->nd)
 
36
#define A_DIM(a,i) (((PyArrayObject *)a)->dimensions[i])
 
37
#define GET_ARR(ap,op,type,dim) \
 
38
  Py_Try(ap=(PyArrayObject *)PyArray_ContiguousFromObject(op,type,dim,dim))
 
39
#define GET_ARR2(ap,op,type,min,max) \
 
40
   Py_Try(ap=(PyArrayObject *)PyArray_ContiguousFromObject(op,type,min,max))
 
41
#define ERRSS(s) ((PyObject *)(PyErr_SetString(ErrorObject,s),(void *)0))
 
42
#define SETERR(s) if(!PyErr_Occurred()) ERRSS(errstr ? errstr : s)
 
43
#define DECREF_AND_ZERO(p) do{Py_XDECREF(p);p=0;}while(0)
 
44
 
 
45
 
 
46
/* ----------------------------------------------------- */
 
47
 
 
48
static char arr_histogram__doc__[] =
 
49
""
 
50
;
 
51
 
 
52
static int mxx ( int * i , int len)
 
53
{
 
54
    /* find the index of the maximum element of an integer array */
 
55
    int mx = 0, max = i [0] ;
 
56
    int j ;
 
57
    for ( j = 1 ; j < len; j ++ )
 
58
        if ( i [j] > max )
 
59
            {max = i [j] ;
 
60
            mx = j ;}
 
61
    return mx;
 
62
}
 
63
 
 
64
static int mnx ( int * i , int len)
 
65
{
 
66
    /* find the index of the minimum element of an integer array */
 
67
    int mn = 0, min = i [0] ;
 
68
    int j ;
 
69
    for ( j = 1 ; j < len; j ++ )
 
70
        if ( i [j] < min )
 
71
            {min = i [j] ;
 
72
            mn = j ;}
 
73
    return mn;
 
74
}
 
75
 
 
76
static PyObject *
 
77
arr_histogram(PyObject *self, PyObject *args)
 
78
{
 
79
    /* histogram accepts one or two arguments. The first is an array
 
80
     * of non-negative integers and the second, if present, is an
 
81
     * array of weights, which must be promotable to double.
 
82
     * Call these arguments list and weight. Both must be one-
 
83
     * dimensional. len (weight) >= max (list) + 1.
 
84
     * If weight is not present:
 
85
     *   histogram (list) [i] is the number of occurrences of i in list.
 
86
     * If weight is present:
 
87
     *   histogram (list, weight) [i] is the sum of all weight [j]
 
88
     * where list [j] == i.                                              */
 
89
    /* self is not used */
 
90
    PyObject * list = NULL, * weight = NULL ;
 
91
    PyArrayObject *lst, *wts , *ans;
 
92
    int * numbers, *ians, len , mxi, mni, i, ans_size;
 
93
    double * weights , * dans ;
 
94
 
 
95
    Py_Try(PyArg_ParseTuple(args, "O|O", &list, &weight));
 
96
    GET_ARR(lst,list,PyArray_INT,1);
 
97
    len = A_SIZE (lst) ;
 
98
    numbers = (int *) A_DATA (lst) ;
 
99
    mxi = mxx (numbers, len) ;
 
100
    mni = mnx (numbers, len) ;
 
101
    if (numbers [mni] < 0)
 
102
        {SETERR ("First argument of histogram must be nonnegative.");
 
103
        Py_DECREF(lst);
 
104
        return NULL;}
 
105
    ans_size = numbers [mxi] + 1 ;
 
106
    if (weight == NULL)
 
107
        {
 
108
            Py_Try(ans =
 
109
                   (PyArrayObject *) PyArray_FromDims (1, &ans_size, PyArray_INT));
 
110
            ians = (int *) A_DATA (ans) ;
 
111
            for (i = 0 ; i < len ; i++)
 
112
                ians [numbers [i]] += 1 ;
 
113
            Py_DECREF(lst);
 
114
        }
 
115
    else
 
116
        {
 
117
            GET_ARR(wts,weight,PyArray_DOUBLE, 1);
 
118
            weights = (double *) A_DATA (wts) ;
 
119
            if (A_SIZE (wts) != len)
 
120
                {SETERR ("histogram: length of weights does not match that of list.");
 
121
                Py_DECREF(lst);
 
122
                Py_DECREF(wts);
 
123
                return NULL;}
 
124
            Py_Try(ans =
 
125
                   (PyArrayObject *) PyArray_FromDims (1, &ans_size, PyArray_DOUBLE));
 
126
            dans = (double *) A_DATA (ans);
 
127
            for (i = 0 ; i < len ; i++) {
 
128
                dans [numbers [i]] += weights [i];
 
129
            }
 
130
            Py_DECREF(lst);
 
131
            Py_DECREF(wts);
 
132
        }
 
133
 
 
134
    return PyArray_Return (ans);
 
135
}
 
136
 
 
137
static char arr_array_set__doc__[] =
 
138
""
 
139
;
 
140
 
 
141
static PyObject *
 
142
arr_array_set(PyObject *self, PyObject *args)
 
143
{
 
144
    /* array_set accepts three arguments. The first is an array of
 
145
     * numerics (Python characters, integers, or floats), and the
 
146
     * third is of the same type. The second is an array of integers
 
147
     * which are valid subscripts into the first. The third array
 
148
     * must be at least long enough to supply all the elements
 
149
     * called for by the subscript array. (It can also be a scalar,
 
150
     * in which case its value will be broadcast.) The result is that
 
151
     * elements of the third array are assigned in order to elements
 
152
     * of the first whose subscripts are elements of the second.
 
153
     *   arr_array_set (vals1, indices, vals2)
 
154
     * is equivalent to the Yorick assignment vals1 (indices) = vals2.
 
155
     * I have generalized this so that the source and target arrays
 
156
     * may be two dimensional; the second dimensions must match.
 
157
     * Then the array of subscripts is assumed to apply to the first
 
158
     * subscript only of the target. The target had better be contiguous. */
 
159
    /* self is not used */
 
160
    PyObject * tararg, * subsarg, *srcarg;
 
161
    PyArrayObject * tararr, * subsarr, * srcarr = NULL;
 
162
    double * dtar, * dsrc, ds=0.0;
 
163
    float * ftar, * fsrc, fs=0.0;
 
164
    char * ctar, * csrc, cs='\0';
 
165
    unsigned char * utar, * usrc, us=0;
 
166
    int * itar, * isrc, * isubs;
 
167
    long * ltar, * lsrc;
 
168
    long is=0;
 
169
    int i, j, len, mn, mx;
 
170
    int scalar_source = 0;
 
171
    char scalar_type = 'x';
 
172
    int nd, d1; /* number of dimensions and value of second dim. */
 
173
 
 
174
    Py_Try(PyArg_ParseTuple(args, "OOO", &tararg, &subsarg, &srcarg));
 
175
    d1 = 1;
 
176
    nd = A_NDIM (tararg) ;
 
177
    if (PyFloat_Check (srcarg)) {
 
178
        scalar_source = 1 ;
 
179
        scalar_type = 'f' ;
 
180
        ds = PyFloat_AS_DOUBLE ( (PyFloatObject *) srcarg) ;
 
181
    }
 
182
    else if (PyInt_Check (srcarg)) {
 
183
        scalar_source = 1 ;
 
184
        scalar_type = 'i' ;
 
185
        is = PyInt_AS_LONG ( (PyIntObject *) srcarg) ;
 
186
    }
 
187
    else if (PyString_Check (srcarg)) {
 
188
        scalar_source = 1 ;
 
189
        scalar_type = 'c' ;
 
190
        cs = PyString_AS_STRING ( (PyStringObject *) srcarg) [0] ;
 
191
    }
 
192
    else if (nd == 2) {
 
193
        d1 = A_DIM (tararg, 1) ;
 
194
        if (A_NDIM (srcarg) != 2 || A_DIM (srcarg,1) != d1) {
 
195
            SETERR ("array_set: dimension mismatch between source and target.");
 
196
            return NULL ;
 
197
        }
 
198
    }
 
199
    else if (nd != 1) {
 
200
        SETERR ("array_set: target must have one or two dimensions.");
 
201
        return NULL ;
 
202
    }
 
203
    GET_ARR(subsarr,subsarg,PyArray_INT,1);
 
204
    isubs = (int *)A_DATA(subsarr);
 
205
    len = A_SIZE(subsarr);
 
206
    mn = mnx (isubs, len);
 
207
    if (isubs [mn] < 0)
 
208
        {SETERR ("array_set: negative subscript specified.");
 
209
        Py_DECREF (subsarr);
 
210
        return NULL;}
 
211
    mx = mxx (isubs, len);
 
212
    switch (A_TYPE(tararg)) {
 
213
    case PyArray_UBYTE:
 
214
        GET_ARR(tararr,tararg,PyArray_UBYTE,nd);
 
215
        if (d1 * isubs [mx] > A_SIZE(tararr))
 
216
            {SETERR ("array_set: a subscript is out of range.");
 
217
            Py_DECREF (subsarr);
 
218
            Py_DECREF (tararr);
 
219
            return NULL;}
 
220
        if (! scalar_source) {
 
221
            GET_ARR(srcarr,srcarg,PyArray_UBYTE,1);
 
222
            if (A_SIZE(srcarr) < d1 * len)
 
223
                {SETERR
 
224
                     ("array_set: source is too short for number of subscripts.");
 
225
                Py_DECREF (subsarr);
 
226
                Py_DECREF (tararr);
 
227
                Py_DECREF (srcarr);
 
228
                return NULL;}
 
229
            utar = (unsigned char *)A_DATA(tararr);
 
230
            usrc = (unsigned char *)A_DATA(srcarr);
 
231
            for (i = 0; i < len; i++ )
 
232
                for (j = 0; j < d1; j++)
 
233
                    utar [d1 * isubs [i] + j] = usrc [i * d1 + j];
 
234
        }
 
235
        else {
 
236
            switch (scalar_type) {
 
237
            case 'c' :
 
238
                us = (unsigned char) cs ;
 
239
                break ;
 
240
            case 'i' :
 
241
                us = (unsigned char) is ;
 
242
                break ;
 
243
            case 'f' :
 
244
                us = (unsigned char) ds ;
 
245
                break ;
 
246
            }
 
247
            utar = (unsigned char *)A_DATA(tararr);
 
248
            for (i = 0; i < len; i++ )
 
249
                for (j = 0; j < d1; j++)
 
250
                    utar [d1 * isubs [i] + j] = us;
 
251
        }
 
252
        break;
 
253
    case PyArray_CHAR:
 
254
        GET_ARR(tararr,tararg,PyArray_CHAR,nd);
 
255
        if (d1 * isubs [mx] > A_SIZE(tararr))
 
256
            {SETERR ("array_set: a subscript is out of range.");
 
257
            Py_DECREF (subsarr);
 
258
            Py_DECREF (tararr);
 
259
            return NULL;}
 
260
        if (! scalar_source) {
 
261
            GET_ARR(srcarr,srcarg,PyArray_CHAR,nd);
 
262
            if (A_SIZE(srcarr) < d1 * len)
 
263
                {SETERR
 
264
                     ("array_set: source is too short for number of subscripts.");
 
265
                Py_DECREF (subsarr);
 
266
                Py_DECREF (tararr);
 
267
                Py_DECREF (srcarr);
 
268
                return NULL;}
 
269
            ctar = (char *)A_DATA(tararr);
 
270
            csrc = (char *)A_DATA(srcarr);
 
271
            for (i = 0; i < len; i++ )
 
272
                for (j = 0; j < d1; j++)
 
273
                    ctar [isubs [i] * d1 + j] = csrc [i * d1 + j];
 
274
        }
 
275
        else {
 
276
            switch (scalar_type) {
 
277
            case 'c' :
 
278
                break ;
 
279
            case 'i' :
 
280
                cs = (unsigned char) is ;
 
281
                break ;
 
282
            case 'f' :
 
283
                cs = (unsigned char) ds ;
 
284
                break ;
 
285
            }
 
286
            ctar = (char *)A_DATA(tararr);
 
287
            for (i = 0; i < len; i++ )
 
288
                for (j = 0; j < d1; j++)
 
289
                    ctar [d1 * isubs [i] + j] = cs;
 
290
        }
 
291
        break;
 
292
    case PyArray_INT:
 
293
        GET_ARR(tararr,tararg,PyArray_INT,nd);
 
294
        if (isubs [mx] * d1 > A_SIZE(tararr))
 
295
            {SETERR ("array_set: a subscript is out of range.");
 
296
            Py_DECREF (subsarr);
 
297
            Py_DECREF (tararr);
 
298
            return NULL;}
 
299
        if (! scalar_source) {
 
300
            GET_ARR(srcarr,srcarg,PyArray_INT,nd);
 
301
            if (A_SIZE(srcarr) < len * d1)
 
302
                {SETERR
 
303
                     ("array_set: source is too short for number of subscripts.");
 
304
                Py_DECREF (subsarr);
 
305
                Py_DECREF (tararr);
 
306
                Py_DECREF (srcarr);
 
307
                return NULL;}
 
308
            itar = (int *)A_DATA(tararr);
 
309
            isrc = (int *)A_DATA(srcarr);
 
310
            for (i = 0; i < len; i++ )
 
311
                for (j = 0; j < d1; j++)
 
312
                    itar [isubs [i] * d1 + j] = isrc [i * d1 + j];
 
313
        }
 
314
        else {
 
315
            switch (scalar_type) {
 
316
            case 'c' :
 
317
                is = (long) cs ;
 
318
                break ;
 
319
            case 'i' :
 
320
                break ;
 
321
            case 'f' :
 
322
                is = (long) ds ;
 
323
                break ;
 
324
            }
 
325
            itar = (int *)A_DATA(tararr);
 
326
            for (i = 0; i < len; i++ )
 
327
                for (j = 0; j < d1; j++)
 
328
                    itar [d1 * isubs [i] + j] = is;
 
329
        }
 
330
        break;
 
331
    case PyArray_LONG:
 
332
        GET_ARR(tararr,tararg,PyArray_LONG,nd);
 
333
        if (isubs [mx] * d1 > A_SIZE(tararr))
 
334
            {SETERR ("array_set: a subscript is out of range.");
 
335
            Py_DECREF (subsarr);
 
336
            Py_DECREF (tararr);
 
337
            return NULL;}
 
338
        if (! scalar_source) {
 
339
            GET_ARR(srcarr,srcarg,PyArray_LONG,nd);
 
340
            if (A_SIZE(srcarr) < len * d1)
 
341
                {SETERR
 
342
                     ("array_set: source is too short for number of subscripts.");
 
343
                Py_DECREF (subsarr);
 
344
                Py_DECREF (tararr);
 
345
                Py_DECREF (srcarr);
 
346
                return NULL;}
 
347
            ltar = (long *)A_DATA(tararr);
 
348
            lsrc = (long *)A_DATA(srcarr);
 
349
            for (i = 0; i < len; i++ )
 
350
                for (j = 0; j < d1; j++)
 
351
                    ltar [isubs [i] * d1 + j] = lsrc [i * d1 + j];
 
352
        }
 
353
        else {
 
354
            switch (scalar_type) {
 
355
            case 'c' :
 
356
                is = (long) cs ;
 
357
                break ;
 
358
            case 'i' :
 
359
                break ;
 
360
            case 'f' :
 
361
                is = (long) ds ;
 
362
                break ;
 
363
            }
 
364
            ltar = (long *)A_DATA(tararr);
 
365
            for (i = 0; i < len; i++ )
 
366
                for (j = 0; j < d1; j++)
 
367
                    ltar [d1 * isubs [i] + j] = is;
 
368
        }
 
369
        break;
 
370
    case PyArray_FLOAT:
 
371
        GET_ARR(tararr,tararg,PyArray_FLOAT,nd);
 
372
        if (isubs [mx] * d1 > A_SIZE(tararr))
 
373
            {SETERR ("array_set: a subscript is out of range.");
 
374
            Py_DECREF (subsarr);
 
375
            Py_DECREF (tararr);
 
376
            return NULL;}
 
377
        if (! scalar_source) {
 
378
            GET_ARR(srcarr,srcarg,PyArray_FLOAT,nd);
 
379
            if (A_SIZE(srcarr) < len * d1)
 
380
                {SETERR
 
381
                     ("array_set: source is too short for number of subscripts.");
 
382
                Py_DECREF (subsarr);
 
383
                Py_DECREF (tararr);
 
384
                Py_DECREF (srcarr);
 
385
                return NULL;}
 
386
            ftar = (float *)A_DATA(tararr);
 
387
            fsrc = (float *)A_DATA(srcarr);
 
388
            for (i = 0; i < len; i++ )
 
389
                for (j = 0; j < d1; j++)
 
390
                    ftar [isubs [i] * d1 + j] = fsrc [i * d1 + j];
 
391
        }
 
392
        else {
 
393
            switch (scalar_type) {
 
394
            case 'c' :
 
395
                fs = (float) cs ;
 
396
                break ;
 
397
            case 'i' :
 
398
                fs = (float) is ;
 
399
                break ;
 
400
            case 'f' :
 
401
                fs = (float) ds ;
 
402
                break ;
 
403
            }
 
404
            ftar = (float *)A_DATA(tararr);
 
405
            for (i = 0; i < len; i++ )
 
406
                for (j = 0; j < d1; j++)
 
407
                    ftar [d1 * isubs [i] + j] = fs;
 
408
        }
 
409
        break;
 
410
    case PyArray_DOUBLE:
 
411
        GET_ARR(tararr,tararg,PyArray_DOUBLE,nd);
 
412
        if (isubs [mx] * d1 > A_SIZE(tararr))
 
413
            {SETERR ("array_set: a subscript is out of range.");
 
414
            Py_DECREF (subsarr);
 
415
            Py_DECREF (tararr);
 
416
            return NULL;}
 
417
        if (! scalar_source) {
 
418
            GET_ARR(srcarr,srcarg,PyArray_DOUBLE,nd);
 
419
            if (A_SIZE(srcarr) < len * d1)
 
420
                {SETERR
 
421
                     ("array_set: source is too short for number of subscripts.");
 
422
                Py_DECREF (subsarr);
 
423
                Py_DECREF (tararr);
 
424
                Py_DECREF (srcarr);
 
425
                return NULL;}
 
426
            dtar = (double *)A_DATA(tararr);
 
427
            dsrc = (double *)A_DATA(srcarr);
 
428
            for (i = 0; i < len; i++ )
 
429
                for (j = 0; j < d1; j++)
 
430
                    dtar [isubs [i] * d1 + j] = dsrc [i * d1 + j];
 
431
        }
 
432
        else {
 
433
            switch (scalar_type) {
 
434
            case 'c' :
 
435
                ds = (double) cs ;
 
436
                break ;
 
437
            case 'i' :
 
438
                ds = (double) is ;
 
439
                break ;
 
440
            case 'f' :
 
441
                break ;
 
442
            }
 
443
            dtar = (double *)A_DATA(tararr);
 
444
            for (i = 0; i < len; i++ )
 
445
                for (j = 0; j < d1; j++)
 
446
                    dtar [d1 * isubs [i] + j] = ds;
 
447
        }
 
448
        break;
 
449
    default:
 
450
        SETERR("array_set: Not implemented for this type.");
 
451
        Py_DECREF(subsarr);
 
452
        return NULL;
 
453
    }
 
454
 
 
455
    Py_DECREF(subsarr);
 
456
    Py_DECREF(tararr);
 
457
    Py_XDECREF(srcarr);
 
458
    Py_INCREF(Py_None);
 
459
    return Py_None;
 
460
}
 
461
 
 
462
static void adjust (double * k, int * list, int i, int n)
 
463
{
 
464
    /* adjust the binary tree k with root list [i] to satisfy the heap
 
465
     * property. The left and right subtrees of list [i], with roots
 
466
     * list [2 * i + 1] and list [2 * i + 2], already satisfy the heap
 
467
     * property. No node has index greater than n.
 
468
     * Horowitz & Sahni, p. 358.                                     */
 
469
    double kt; /* will contain root value which may need to be moved */
 
470
    int kj ,   /* root value is at kj position in list               */
 
471
        j ,
 
472
        lowj ; /* parent of current j node                           */
 
473
 
 
474
    kj = list [i] ;
 
475
    kt = k [kj] ;
 
476
    j = 2 * i + 1 ;
 
477
    lowj = i ;
 
478
    while ( j < n )
 
479
        {
 
480
            if (j < n - 1 && k [list [j]] < k [list [j + 1]])
 
481
                /* make list [j] point to the larger child */
 
482
                j = j + 1 ;
 
483
            if ( kt >= k [list [j]] )
 
484
                {
 
485
                    list [lowj] = kj ;
 
486
                    return ;
 
487
                }
 
488
            list [lowj] = list [j] ;
 
489
            lowj = j ;
 
490
            j = 2 * j + 1 ;
 
491
        }
 
492
    list [lowj] = kj ;
 
493
}
 
494
 
 
495
static char arr_index_sort__doc__[] =
 
496
""
 
497
;
 
498
 
 
499
static PyObject *
 
500
arr_index_sort(PyObject *self, PyObject *args)
 
501
{
 
502
    /* index_sort accepts one array of some numerical type and returns
 
503
     * an integer array of the same length whose entries are the
 
504
     * subscripts of the elements of the original array arranged
 
505
     * in increasing order. I chose to use heap sort because its
 
506
     * worst behavior is n*log(n), unlike quicksort, whose worst
 
507
     * behavior is n**2.                                         */
 
508
    /* self is not used */
 
509
    PyObject * list;
 
510
    PyArrayObject * alist, * ilist;
 
511
    double * data;
 
512
    int len, i, * isubs, itmp;
 
513
 
 
514
    Py_Try(PyArg_ParseTuple(args, "O", &list));
 
515
    GET_ARR(alist,list,PyArray_DOUBLE,1);
 
516
    len = A_SIZE(alist);
 
517
    Py_Try(ilist = (PyArrayObject *) PyArray_FromDims (1, &len, PyArray_INT));
 
518
    isubs = (int *) A_DATA (ilist);
 
519
    for ( i = 0 ; i < len ; i ++ )
 
520
        isubs [i] = i ;
 
521
 
 
522
    data = (double *) A_DATA(alist) ;
 
523
    /* now do heap sort on subscripts */
 
524
    for (i = len / 2; i >= 0; i--) {
 
525
        adjust (data, isubs, i, len) ;
 
526
    }
 
527
    for (i = len - 1; i >= 0; i-- )
 
528
        {
 
529
            itmp = isubs [i] ;
 
530
            isubs [i] = isubs [0] ;
 
531
            isubs [0] = itmp ;
 
532
            adjust (data, isubs, 0, i) ;
 
533
        }
 
534
 
 
535
    Py_DECREF(alist);
 
536
    return (PyObject *) ilist ;
 
537
}
 
538
 
 
539
static int
 
540
binary_search(double dval, double dlist [], int len)
 
541
{
 
542
    /* binary_search accepts three arguments: a numeric value and
 
543
     * a numeric array and its length. It assumes that the array is sorted in
 
544
     * increasing order. It returns the index of the array's
 
545
     * largest element which is <= the value. It will return -1 if
 
546
     * the value is less than the least element of the array. */
 
547
    /* self is not used */
 
548
    int bottom , top , middle, result;
 
549
 
 
550
    if (dval < dlist [0])
 
551
        result = -1 ;
 
552
    else {
 
553
        bottom = 0;
 
554
        top = len - 1;
 
555
        while (bottom < top) {
 
556
            middle = (top + bottom) / 2 ;
 
557
            if (dlist [middle] < dval)
 
558
                bottom = middle + 1 ;
 
559
            else if (dlist [middle] > dval)
 
560
                top = middle - 1 ;
 
561
            else
 
562
                return middle ;
 
563
        }
 
564
        if (dlist [bottom] > dval)
 
565
            result = bottom - 1 ;
 
566
        else
 
567
            result = bottom ;
 
568
    }
 
569
 
 
570
    return result ;
 
571
}
 
572
 
 
573
static int
 
574
binary_searchf(float dval, float dlist [], int len)
 
575
{
 
576
    /* binary_search accepts three arguments: a numeric value and
 
577
     * a numeric array and its length. It assumes that the array is sorted in
 
578
     * increasing order. It returns the index of the array's
 
579
     * largest element which is <= the value. It will return -1 if
 
580
     * the value is less than the least element of the array. */
 
581
    /* self is not used */
 
582
    int bottom , top , middle, result;
 
583
 
 
584
    if (dval < dlist [0])
 
585
        result = -1 ;
 
586
    else {
 
587
        bottom = 0;
 
588
        top = len - 1;
 
589
        while (bottom < top) {
 
590
            middle = (top + bottom) / 2 ;
 
591
            if (dlist [middle] < dval)
 
592
                bottom = middle + 1 ;
 
593
            else if (dlist [middle] > dval)
 
594
                top = middle - 1 ;
 
595
            else
 
596
                return middle ;
 
597
        }
 
598
        if (dlist [bottom] > dval)
 
599
            result = bottom - 1 ;
 
600
        else
 
601
            result = bottom ;
 
602
    }
 
603
 
 
604
    return result ;
 
605
}
 
606
/* return float, rather than double */
 
607
 
 
608
static PyObject *
 
609
arr_interpf(PyObject *self, PyObject *args)
 
610
{
 
611
    /* interp (y, x, z) treats (x, y) as a piecewise linear function
 
612
     * whose value is y [0] for x < x [0] and y [len (y) -1] for x >
 
613
     * x [len (y) -1]. An array of floats the same length as z is
 
614
     * returned, whose values are ordinates for the corresponding z
 
615
     * abscissae interpolated into the piecewise linear function.         */
 
616
    /* self is not used */
 
617
    PyObject * oy, * ox, * oz ;
 
618
    PyArrayObject * ay, * ax, * az , * _interp;
 
619
    float * dy, * dx, * dz , * dres, * slopes;
 
620
    int leny, lenz, i, left ;
 
621
 
 
622
    PyObject *tpo = Py_None;  /* unused argument, we've already parsed it*/
 
623
 
 
624
    Py_Try(PyArg_ParseTuple(args, "OOO|O", &oy, &ox, &oz, &tpo));
 
625
    GET_ARR(ay,oy,PyArray_FLOAT,1);
 
626
    GET_ARR(ax,ox,PyArray_FLOAT,1);
 
627
    if ( (leny = A_SIZE (ay)) != A_SIZE (ax)) {
 
628
        SETERR ("interp: x and y are not the same length.");
 
629
        Py_DECREF(ay);
 
630
        Py_DECREF(ax);
 
631
        return NULL ;}
 
632
    GET_ARR2(az,oz,PyArray_FLOAT,1,MAX_INTERP_DIMS);
 
633
    lenz = A_SIZE (az);
 
634
    dy = (float *) A_DATA (ay);
 
635
    dx = (float *) A_DATA (ax);
 
636
    dz = (float *) A_DATA (az);
 
637
    /* create output array with same size as 'Z' input array */
 
638
    Py_Try (_interp = (PyArrayObject *) PyArray_FromDims
 
639
            (A_NDIM(az), az->dimensions, PyArray_FLOAT));
 
640
    dres = (float *) A_DATA (_interp) ;
 
641
    slopes = (float *) malloc ( (leny - 1) * sizeof (float)) ;
 
642
    for (i = 0 ; i < leny - 1; i++) {
 
643
        slopes [i] = (dy [i + 1] - dy [i]) / (dx [i + 1] - dx [i]) ;
 
644
    }
 
645
    for ( i = 0 ; i < lenz ; i ++ )
 
646
        {
 
647
            left = binary_searchf (dz [i], dx, leny) ;
 
648
            if (left < 0)
 
649
                dres [i] = dy [0] ;
 
650
            else if (left >= leny - 1)
 
651
                dres [i] = dy [leny - 1] ;
 
652
            else
 
653
                dres [i] = slopes [left] * (dz [i] - dx [left]) + dy [left];
 
654
        }
 
655
 
 
656
    free (slopes);
 
657
    Py_DECREF(ay);
 
658
    Py_DECREF(ax);
 
659
    Py_DECREF(az);
 
660
    return PyArray_Return (_interp);
 
661
}
 
662
 
 
663
static char arr_interp__doc__[] =
 
664
"interp(y, x, z [,resulttypecode]) = y(z) interpolated by treating y(x) as piecewise fcn."
 
665
;
 
666
 
 
667
static PyObject *
 
668
arr_interp(PyObject *self, PyObject *args)
 
669
{
 
670
    /* interp (y, x, z) treats (x, y) as a piecewise linear function
 
671
     * whose value is y [0] for x < x [0] and y [len (y) -1] for x >
 
672
     * x [len (y) -1]. An array of floats the same length as z is
 
673
     * returned, whose values are ordinates for the corresponding z
 
674
     * abscissae interpolated into the piecewise linear function.         */
 
675
    /* self is not used */
 
676
    PyObject * oy, * ox, * oz ;
 
677
    PyArrayObject * ay, * ax, * az , * _interp;
 
678
    double * dy, * dx, * dz , * dres, * slopes;
 
679
    int leny, lenz, i, left ;
 
680
    PyObject *tpo = Py_None;
 
681
    char type_char = 'd';
 
682
    char *type = &type_char;
 
683
 
 
684
    Py_Try(PyArg_ParseTuple(args, "OOO|O", &oy, &ox, &oz,&tpo));
 
685
    if (tpo != Py_None) {
 
686
        type = PyString_AsString(tpo);
 
687
        if (!type)
 
688
            return NULL;
 
689
        if(!*type)
 
690
            type = &type_char;
 
691
    }
 
692
    if (*type == 'f' ) {
 
693
        return arr_interpf(self, args);
 
694
    } else if (*type != 'd') {
 
695
        SETERR ("interp: unimplemented typecode.");
 
696
        return NULL;
 
697
    }
 
698
    GET_ARR(ay,oy,PyArray_DOUBLE,1);
 
699
    GET_ARR(ax,ox,PyArray_DOUBLE,1);
 
700
    if ( (leny = A_SIZE (ay)) != A_SIZE (ax)) {
 
701
        SETERR ("interp: x and y are not the same length.");
 
702
        Py_DECREF(ay);
 
703
        Py_DECREF(ax);
 
704
        return NULL ;}
 
705
    GET_ARR2(az,oz,PyArray_DOUBLE,1,MAX_INTERP_DIMS);
 
706
    lenz = A_SIZE (az);
 
707
    dy = (double *) A_DATA (ay);
 
708
    dx = (double *) A_DATA (ax);
 
709
    dz = (double *) A_DATA (az);
 
710
    /* create output array with same size as 'Z' input array */
 
711
    Py_Try (_interp = (PyArrayObject *) PyArray_FromDims
 
712
            (A_NDIM(az), az->dimensions, PyArray_DOUBLE));
 
713
    dres = (double *) A_DATA (_interp) ;
 
714
    slopes = (double *) malloc ( (leny - 1) * sizeof (double)) ;
 
715
    for (i = 0 ; i < leny - 1; i++) {
 
716
        slopes [i] = (dy [i + 1] - dy [i]) / (dx [i + 1] - dx [i]) ;
 
717
    }
 
718
    for ( i = 0 ; i < lenz ; i ++ )
 
719
        {
 
720
            left = binary_search (dz [i], dx, leny) ;
 
721
            if (left < 0)
 
722
                dres [i] = dy [0] ;
 
723
            else if (left >= leny - 1)
 
724
                dres [i] = dy [leny - 1] ;
 
725
            else
 
726
                dres [i] = slopes [left] * (dz [i] - dx [left]) + dy [left];
 
727
        }
 
728
 
 
729
    free (slopes);
 
730
    Py_DECREF(ay);
 
731
    Py_DECREF(ax);
 
732
    Py_DECREF(az);
 
733
    return PyArray_Return (_interp);
 
734
}
 
735
 
 
736
static int incr_slot_ (float x, double *bins, int lbins)
 
737
{
 
738
    int i ;
 
739
    for ( i = 0 ; i < lbins ; i ++ )
 
740
        if ( x < bins [i] )
 
741
            return i ;
 
742
    return lbins ;
 
743
}
 
744
 
 
745
static int decr_slot_ (double x, double * bins, int lbins)
 
746
{
 
747
    int i ;
 
748
    for ( i = lbins - 1 ; i >= 0; i -- )
 
749
        if (x < bins [i])
 
750
            return i + 1 ;
 
751
    return 0 ;
 
752
}
 
753
 
 
754
static int monotonic_ (double * a, int lena)
 
755
{
 
756
    int i;
 
757
    if (lena < 2)
 
758
        {SETERR
 
759
             ("digitize: If a vector, second argument must have at least 2 elements.");
 
760
        return 0;}
 
761
    if (a [0] <= a [1]) /* possibly monotonic increasing */
 
762
        {
 
763
            for (i = 1 ; i < lena - 1; i ++)
 
764
                if (a [i] > a [i + 1]) return 0 ;
 
765
            return 1 ;
 
766
        }
 
767
    else              /* possibly monotonic decreasing */
 
768
        {
 
769
            for (i = 1 ; i < lena - 1; i ++)
 
770
                if (a [i] < a [i + 1]) return 0 ;
 
771
            return - 1 ;
 
772
        }
 
773
}
 
774
 
 
775
static char arr_digitize__doc__[] =
 
776
""
 
777
;
 
778
 
 
779
static PyObject *
 
780
arr_zmin_zmax(PyObject *self, PyObject *args)
 
781
{
 
782
    /* zmin_zmax (z, ireg) returns a 2-tuple which consists
 
783
       of the minimum and maximum values of z on the portion of the
 
784
       mesh where ireg is not zero. z is a 2d array of Float and ireg
 
785
       is an array of the same shape of Integer. By convention the first
 
786
       row and column of ireg are zero, and the remaining entries are
 
787
       used to determine which region each cell belongs to. A zero
 
788
       entry says that this cell is excluded from the mesh. */
 
789
    PyObject * zobj, * iregobj;
 
790
    PyArrayObject * zarr, * iregarr;
 
791
    double * z, zmin=0.0, zmax=0.0;
 
792
    int * ireg;
 
793
    int have_min_max = 0;
 
794
    int i, j, k, n, m;
 
795
 
 
796
    Py_Try(PyArg_ParseTuple(args, "OO", &zobj, &iregobj));
 
797
    GET_ARR (zarr, zobj, PyArray_DOUBLE, 2);
 
798
    if (! (iregarr = (PyArrayObject *)PyArray_ContiguousFromObject(iregobj,
 
799
                                                                   PyArray_INT, 2, 2))) {
 
800
        Py_DECREF (zarr);
 
801
        return NULL;
 
802
    }
 
803
    n = A_DIM (iregarr, 0);
 
804
    m = A_DIM (iregarr, 1);
 
805
    if (n != A_DIM (zarr, 0) || m != A_DIM (zarr, 1)) {
 
806
        SETERR ("zmin_zmax: z and ireg do not have the same shape.");
 
807
        Py_DECREF (iregarr);
 
808
        Py_DECREF (zarr);
 
809
        return NULL;
 
810
    }
 
811
    ireg = (int *) A_DATA (iregarr);
 
812
    z = (double *) A_DATA (zarr);
 
813
    k = 0;         /* k is i * m + j */
 
814
    for ( i = 0; i < n; i++) {
 
815
        for (j = 0; j < m; j++) {
 
816
            if ( (ireg [k] != 0) ||
 
817
                 (i != n - 1 && j != m - 1 &&
 
818
                  (ireg [k + m] != 0 || ireg [k + 1] != 0 || ireg [k + m + 1] != 0))) {
 
819
                if (! have_min_max ) {
 
820
                    have_min_max = 1;
 
821
                    zmin = zmax = z [k];
 
822
                }
 
823
                else {
 
824
                    if (z [k] < zmin) zmin = z [k];
 
825
                    else if (z [k] > zmax) zmax = z [k];
 
826
                }
 
827
            }
 
828
            k++;
 
829
        }
 
830
    }
 
831
    Py_DECREF (iregarr);
 
832
    Py_DECREF (zarr);
 
833
    if (!have_min_max) {
 
834
        SETERR ("zmin_zmax: unable to calculate zmin and zmax!");
 
835
        return NULL;
 
836
    }
 
837
    return Py_BuildValue ("dd", zmin, zmax);
 
838
}
 
839
 
 
840
static char arr_zmin_zmax__doc__[] =
 
841
""
 
842
;
 
843
 
 
844
static PyObject *
 
845
arr_digitize(PyObject *self, PyObject *args)
 
846
{
 
847
    /* digitize (x, bins) returns an array of python integers the same
 
848
       length of x (if x is a one-dimensional array), or just an integer
 
849
       (if x is a scalar). The values i returned are such that
 
850
       bins [i - 1] <= x < bins [i] if bins is monotonically increasing,
 
851
       or bins [i - 1] > x >= bins [i] if bins is monotonically decreasing.
 
852
       Beyond the bounds of bins, returns either i = 0 or i = len (bins)
 
853
       as appropriate.                                                      */
 
854
    /* self is not used */
 
855
    PyObject * ox, * obins ;
 
856
    PyArrayObject *ax=NULL, *abins=NULL, *aret ;
 
857
    double x=0.0, bins=0.0;       /* if either or both is a scalar */
 
858
    double *dx=NULL, *dbins=NULL; /* if either or both is a vector */
 
859
    int lbins=0, lx ;             /* lengths, if vectors */
 
860
    long * iret ;
 
861
    int m, i ;
 
862
    int x_is_scalar, bins_is_scalar ;
 
863
 
 
864
    Py_Try(PyArg_ParseTuple(args, "OO", & ox, & obins));
 
865
    x_is_scalar = ! isARRAY (ox) ;
 
866
    bins_is_scalar = ! isARRAY (obins) ;
 
867
    if ( !x_is_scalar )
 
868
        {
 
869
            GET_ARR(ax,ox,PyArray_DOUBLE,1);
 
870
            if (A_NDIM (ax) > 1) {
 
871
                SETERR ("digitize: first argument has too many dimensions.") ;
 
872
                Py_DECREF (ax) ;
 
873
                return NULL ; }
 
874
            lx = A_SIZE (ax) ;
 
875
            dx = (double *) A_DATA (ax) ;
 
876
        }
 
877
    else
 
878
        {
 
879
            if (PyInt_Check (ox))
 
880
                x = (double) PyInt_AsLong (ox) ;
 
881
            else if (PyFloat_Check (ox))
 
882
                x = PyFloat_AS_DOUBLE ((PyFloatObject *)ox) ;
 
883
            else {
 
884
                SETERR ("digitize: bad type for first argument.") ;
 
885
                return NULL ; }
 
886
        }
 
887
    if ( !bins_is_scalar )
 
888
        {
 
889
            GET_ARR(abins,obins,PyArray_DOUBLE,1);
 
890
            if (A_NDIM (abins) > 1) {
 
891
                SETERR ("digitize: second argument has too many dimensions.") ;
 
892
                Py_DECREF (abins) ;
 
893
                Py_XDECREF(ax);
 
894
                return NULL ; }
 
895
            lbins = A_SIZE (abins) ;
 
896
            dbins = (double *) A_DATA (abins) ;
 
897
        }
 
898
    else
 
899
        {
 
900
            if (PyInt_Check (obins))
 
901
                bins = (double) PyInt_AsLong (obins) ;
 
902
            else if (PyFloat_Check (obins))
 
903
                bins = PyFloat_AS_DOUBLE ((PyFloatObject *)obins) ;
 
904
            else {
 
905
                SETERR ("digitize: bad type for second argument.") ;
 
906
                return NULL ; }
 
907
        }
 
908
 
 
909
    if (bins_is_scalar)
 
910
        if (x_is_scalar)
 
911
            if (x < bins)
 
912
                return PyInt_FromLong (0) ;
 
913
            else
 
914
                return PyInt_FromLong (1) ;
 
915
        else
 
916
            {
 
917
                aret = (PyArrayObject *) PyArray_FromDims (1, &lx, PyArray_LONG) ;
 
918
                iret = (long *) A_DATA (aret) ;
 
919
                for ( i = 0 ; i < lx ; i ++ )
 
920
                    if (dx [i] >= bins)
 
921
                        iret [i] = (long) 1 ;
 
922
            }
 
923
    else
 
924
        {
 
925
            m = monotonic_ (dbins, lbins) ;
 
926
            if ( m == -1 )
 
927
                {
 
928
                    if (x_is_scalar)
 
929
                        return PyInt_FromLong (decr_slot_ ((float)x, dbins, lbins)) ;
 
930
                    aret = (PyArrayObject *) PyArray_FromDims (1, &lx, PyArray_LONG) ;
 
931
                    iret = (long *) A_DATA (aret) ;
 
932
                    for ( i = 0 ; i < lx ; i ++ )
 
933
                        iret [i] = (long) decr_slot_ (dx [i], dbins, lbins) ;
 
934
                }
 
935
            else if ( m == 1 )
 
936
                {
 
937
                    if (x_is_scalar)
 
938
                        return PyInt_FromLong (incr_slot_ ((float)x, dbins, lbins)) ;
 
939
                    aret = (PyArrayObject *) PyArray_FromDims (1, &lx, PyArray_LONG) ;
 
940
                    iret = (long *) A_DATA (aret) ;
 
941
                    for ( i = 0 ; i < lx ; i ++ )
 
942
                        iret [i] = (long) incr_slot_ ((float)dx [i], dbins, lbins) ;
 
943
                }
 
944
            else
 
945
                {
 
946
                    SETERR ("digitize: Second argument must be monotonic.") ;
 
947
                    Py_XDECREF(ax);
 
948
                    Py_XDECREF(abins);
 
949
                    return NULL ;
 
950
                }
 
951
        }
 
952
 
 
953
    Py_XDECREF(ax);
 
954
    Py_XDECREF(abins);
 
955
    return PyArray_Return (aret) ;
 
956
}
 
957
 
 
958
static char arr_reverse__doc__[] =
 
959
""
 
960
;
 
961
 
 
962
static PyObject *
 
963
arr_reverse(PyObject *self, PyObject *args)
 
964
{
 
965
    /* reverse (x, n) returns a PyFloat Matrix the same size and shape as
 
966
       x, but with the elements along the nth dimension reversed.
 
967
       x must be two-dimensional.                                   */
 
968
    /* self is not used */
 
969
    PyObject * ox;
 
970
    int n;
 
971
    PyArrayObject * ax, * ares ;
 
972
    double * dx, * dres;
 
973
    int d0, d1, dims [2] ;
 
974
    int i, jl, jh;
 
975
 
 
976
    Py_Try(PyArg_ParseTuple(args, "Oi", &ox, &n));
 
977
    if (n != 0 && n != 1) {
 
978
        SETERR("reverse: Second argument must be 0 or 1.");
 
979
        return NULL; }
 
980
    GET_ARR(ax,ox,PyArray_DOUBLE,2);
 
981
    dx = (double *) A_DATA (ax);
 
982
    d0 = dims [0] = A_DIM (ax, 0);
 
983
    d1 = dims [1] = A_DIM (ax, 1);
 
984
    Py_Try(ares = (PyArrayObject *) PyArray_FromDims (2, dims, PyArray_DOUBLE));
 
985
    dres = (double *) A_DATA (ares);
 
986
    if (n == 0)  /* reverse the columns */
 
987
        for (i = 0; i < d1 ; i ++ )
 
988
            {for (jl = i, jh = (d0 - 1) * d1 + i; jl < jh; jl += d1, jh -= d1)
 
989
                {
 
990
                    dres [jl] = dx [jh] ;
 
991
                    dres [jh] = dx [jl] ;
 
992
                }
 
993
            if (jl == jh) dres [jl] = dx [jl] ;
 
994
            }
 
995
    else /* reverse the rows */
 
996
        for (i = 0; i < d0 ; i ++ )
 
997
            {for (jl = i * d1, jh = (i + 1) * d1 - 1; jl < jh; jl +=1, jh -= 1)
 
998
                {
 
999
                    dres [jl] = dx [jh] ;
 
1000
                    dres [jh] = dx [jl] ;
 
1001
                }
 
1002
            if (jl == jh) dres [jl] = dx [jl] ;
 
1003
            }
 
1004
 
 
1005
    Py_DECREF(ax);
 
1006
    return PyArray_Return (ares) ;
 
1007
}
 
1008
 
 
1009
static char arr_span__doc__[] =
 
1010
""
 
1011
;
 
1012
 
 
1013
static PyObject *
 
1014
arr_span(PyObject *self, PyObject *args)
 
1015
{
 
1016
    /* span (lo, hi, num, d2 = 0) returns an array of num equally
 
1017
       spaced PyFloats starting with lo and ending with hi. if d2 is
 
1018
       not zero, it will return a two-dimensional array, each of the
 
1019
       d2 rows of which is the array of equally spaced numbers. */
 
1020
    /* self is not used */
 
1021
 
 
1022
    int num, d2 = 0;
 
1023
    int dims [2];
 
1024
    double lo, hi, * drow, * dres;
 
1025
    int i, j, id2;
 
1026
    PyArrayObject * arow, * ares ;
 
1027
 
 
1028
    Py_Try(PyArg_ParseTuple(args, "ddi|i", &lo, &hi, &num, &d2));
 
1029
    dims [1] = num;
 
1030
    dims [0] = d2;
 
1031
    Py_Try(arow = (PyArrayObject *) PyArray_FromDims (1, &num, PyArray_DOUBLE));
 
1032
    drow = (double *) A_DATA (arow) ;
 
1033
    for (i = 0; i < num; i++)
 
1034
        drow [i] = lo + ( (double) i) * (hi - lo) / ( (double) (num - 1)) ;
 
1035
    if ( d2 == 0 )
 
1036
        return PyArray_Return (arow) ;
 
1037
    else
 
1038
        {
 
1039
            Py_Try
 
1040
                (ares = (PyArrayObject *) PyArray_FromDims (2, dims, PyArray_DOUBLE));
 
1041
            dres = (double *) A_DATA (ares) ;
 
1042
            for ( id2 = 0 ; id2 < num * d2 ; id2 += num )
 
1043
                for (j = 0; j < num; j ++ )
 
1044
                    dres [id2 + j] = drow [j] ;
 
1045
            Py_DECREF (arow) ;
 
1046
        }
 
1047
 
 
1048
    return PyArray_Return (ares) ;
 
1049
}
 
1050
 
 
1051
static char arr_nz__doc__ [] =
 
1052
""
 
1053
;
 
1054
 
 
1055
static PyObject *
 
1056
arr_nz (PyObject *self, PyObject *args)
 
1057
{
 
1058
    /* nz_ (x): x is an array of unsigned bytes. If x
 
1059
       ends with a bunch of zeros, this returns with the index of
 
1060
       the first zero element after the last nonzero element.
 
1061
       It returns the length of the array if its last element
 
1062
       is nonzero. This is essentially the "effective length"
 
1063
       of the array. */
 
1064
    /* self is not used */
 
1065
    int i , len ;
 
1066
    unsigned char * cdat;
 
1067
    PyObject * odat;
 
1068
    PyArrayObject * adat;
 
1069
 
 
1070
    Py_Try(PyArg_ParseTuple(args, "O", &odat)) ;
 
1071
    GET_ARR(adat,odat,PyArray_UBYTE,1) ;
 
1072
    cdat = (unsigned char *) A_DATA (adat) ;
 
1073
    len = A_SIZE (adat) ;
 
1074
    for (i = len; i > 0; i --)
 
1075
        if (cdat [i - 1] != (unsigned char) 0) break ;
 
1076
    Py_DECREF (adat) ;
 
1077
    return PyInt_FromLong ( (long) i) ;
 
1078
}
 
1079
 
 
1080
static char arr_find_mask__doc__ [] =
 
1081
""
 
1082
;
 
1083
 
 
1084
static PyObject * arr_find_mask (PyObject * self, PyObject * args)
 
1085
{
 
1086
    /* find_mask (fs, node_edges): This function is used to calculate
 
1087
       a mask whose corresponding entry is 1 precisely if an edge
 
1088
       of a cell is cut by an isosurface, i. e., if the function
 
1089
       fs is one on one of the two vertices of an edge and zero
 
1090
       on the other (fs = 1 represents where some function on
 
1091
       the mesh was found to be negative by the calling routine).
 
1092
       fs is ntotal by nv, where nv is the number of vertices
 
1093
       of a cell (4 for a tetrahedren, 5 for a pyramid, 6 for a prism).
 
1094
       node_edges is a nv by ne array, where ne is the number of
 
1095
       edges on a cell (6 for a tet, 8 for a pyramid, 9 for a prism).
 
1096
       The entries in each row are 1 precisely if the corresponding edge
 
1097
       is incident on the vertex. The exclusive or of the rows
 
1098
       which correspond to nonzero entries in fs contains 1 in
 
1099
       entries corresponding to edges where fs has opposite values
 
1100
       on the vertices.                                            */
 
1101
 
 
1102
    PyObject * fso, * node_edgeso ;
 
1103
    PyArrayObject * fsa, * node_edgesa, * maska ;
 
1104
    int * fs, * node_edges, * mask ;
 
1105
    int i, j, k, l, ll, ifs, imask, ntotal, ne, nv, ans_size ;
 
1106
 
 
1107
    Py_Try (PyArg_ParseTuple ( args, "OO", & fso, & node_edgeso ) ) ;
 
1108
    GET_ARR (fsa, fso, PyArray_INT, 2) ;
 
1109
    GET_ARR (node_edgesa, node_edgeso, PyArray_INT, 2) ;
 
1110
    fs = (int *) A_DATA (fsa) ;
 
1111
    node_edges = (int *) A_DATA (node_edgesa) ;
 
1112
    ntotal = A_DIM (fsa, 0) ;
 
1113
    nv = A_DIM (fsa, 1) ;
 
1114
    if ( nv != A_DIM (node_edgesa, 0) ) {
 
1115
        SETERR ("2nd dimension of 1st arg and 1st dimension of 2nd not equal.");
 
1116
        Py_DECREF (fsa) ;
 
1117
        Py_DECREF (node_edgesa) ;
 
1118
        return (NULL) ;
 
1119
    }
 
1120
    ne = A_DIM (node_edgesa, 1) ;
 
1121
    ans_size = ntotal * ne ;
 
1122
    Py_Try (maska = (PyArrayObject *) PyArray_FromDims
 
1123
            (1, & ans_size, PyArray_INT)) ;
 
1124
    mask = (int *) A_DATA (maska) ;
 
1125
 
 
1126
    for (i = 0, ifs = 0, imask = 0 ; i < ntotal ;
 
1127
         i ++, imask += ne, ifs += nv) {
 
1128
        for (j = ifs, k = 0; k < nv; j ++, k ++) {
 
1129
            if ( fs [j] ) {
 
1130
                for ( l = imask , ll = 0; ll < ne ; l ++ , ll ++) {
 
1131
                    mask [l] ^= node_edges [j % nv * ne + ll] ;
 
1132
                }
 
1133
            }
 
1134
        }
 
1135
    }
 
1136
 
 
1137
    return PyArray_Return (maska) ;
 
1138
 
 
1139
}
 
1140
 
 
1141
/* Data for construct3 and walk3 */
 
1142
int start_face4 [] = {0, 0, 1, 0, 2, 1} ;
 
1143
int start_face5 [] = {0, 0, 1, 2, 0, 1, 2, 3} ;
 
1144
int start_face6 [] = {1, 1, 0, 0, 2, 2, 0, 0, 1} ;
 
1145
int start_face8 [] = {0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3} ;
 
1146
static int * start_face [4] = {start_face4, start_face5, start_face6,
 
1147
                               start_face8} ;
 
1148
 
 
1149
int ef0 [] = {0, 1} ;
 
1150
int ef1 [] = {0, 2} ;
 
1151
int ef2 [] = {0, 3} ;
 
1152
int ef3 [] = {0, 4} ;
 
1153
int ef4 [] = {0, 5} ;
 
1154
int ef5 [] = {1, 2} ;
 
1155
int ef6 [] = {1, 3} ;
 
1156
int ef7 [] = {1, 4} ;
 
1157
int ef8 [] = {1, 5} ;
 
1158
int ef9 [] = {2, 3} ;
 
1159
int ef10 [] = {2, 4} ;
 
1160
int ef11 [] = {2, 5} ;
 
1161
int ef12 [] = {3, 4} ;
 
1162
int ef13 [] = {3, 5} ;
 
1163
int * edge_faces4 [] = {ef0, ef1, ef5, ef2, ef9, ef6} ;
 
1164
int * edge_faces5 [] = {ef2, ef0, ef5, ef9, ef3, ef7, ef10, ef12} ;
 
1165
int * edge_faces6 [] = {ef6, ef7, ef2, ef3, ef9, ef10, ef0, ef1, ef5} ;
 
1166
int * edge_faces8 [] = {ef1, ef5, ef2, ef6, ef3, ef7, ef4, ef8, ef10,
 
1167
                        ef12, ef11, ef13} ;
 
1168
static int ** edge_faces [] = {edge_faces4, edge_faces5, edge_faces6,
 
1169
                               edge_faces8} ;
 
1170
 
 
1171
int fe40 [] = {0, 1, 3} ;
 
1172
int fe41 [] = {0, 5, 2} ;
 
1173
int fe42 [] = {1, 2, 4} ;
 
1174
int fe43 [] = {3, 4, 5} ;
 
1175
int * face_edges4 [] = {fe40, fe41, fe42, fe43} ;
 
1176
int fe50 [] = {0, 1, 4} ;
 
1177
int fe51 [] = {1, 2, 5} ;
 
1178
int fe52 [] = {2, 3, 6} ;
 
1179
int fe53 [] = {0, 7, 3} ;
 
1180
int fe54 [] = {4, 5, 6, 7} ;
 
1181
int * face_edges5 [] = {fe50, fe51, fe52, fe53, fe54} ;
 
1182
int fe60 [] = {2, 7, 3, 6} ;
 
1183
int fe61 [] = {0, 6, 1, 8} ;
 
1184
int fe62 [] = {4, 8, 5, 7} ;
 
1185
int fe63 [] = {0, 4, 2} ;
 
1186
int fe64 [] = {1, 3, 5} ;
 
1187
int * face_edges6 [] = {fe60, fe61, fe62, fe63, fe64} ;
 
1188
int fe80 [] = {0, 6, 2, 4} ;
 
1189
int fe81 [] = {1, 5, 3, 7} ;
 
1190
int fe82 [] = {0, 8, 1, 10} ;
 
1191
int fe83 [] = {2, 11, 3, 9} ;
 
1192
int fe84 [] = {4, 9, 5, 8} ;
 
1193
int fe85 [] = {6, 10, 7, 11} ;
 
1194
int * face_edges8 [] = {fe80, fe81, fe82, fe83, fe84, fe85} ;
 
1195
static int ** face_edges [] = {face_edges4, face_edges5, face_edges6,
 
1196
                               face_edges8} ;
 
1197
 
 
1198
 
 
1199
int lens4 [] = {3, 3, 3, 3} ;
 
1200
int lens5 [] = {3, 3, 3, 3, 4} ;
 
1201
int lens6 [] = {4, 4, 4, 3, 3} ;
 
1202
int lens8 [] = {4, 4, 4, 4, 4, 4} ;
 
1203
static int * lens [] = {lens4, lens5, lens6, lens8} ;
 
1204
 
 
1205
static int no_edges [4] = {6, 8, 9, 12} ;
 
1206
/* static int no_verts [4] = {4, 5, 6, 8} ; */
 
1207
static int powers [4] = {14, 30, 62, 254} ;
 
1208
 
 
1209
/* FILE * dbg; */
 
1210
 
 
1211
static void walk3 ( int * permute, int * mask, int itype, int pt )
 
1212
{
 
1213
    int split ,
 
1214
        splits [12] ,
 
1215
        list [12] ,
 
1216
        nlist ,
 
1217
        edge = 0,
 
1218
        face ,
 
1219
        i ,
 
1220
        j ,
 
1221
        * ttry ,
 
1222
        lttry ,
 
1223
        now ;
 
1224
 
 
1225
    for (i = 0; i < 12; i++) splits [i] = 0 ;
 
1226
    /* list = mask.nonzero () */
 
1227
    for (i = 0, nlist = 0 ; i < no_edges [itype] ; i ++)
 
1228
        if (mask [i]) {
 
1229
            list [nlist++] = i ;
 
1230
            if (nlist == 1)
 
1231
                edge = i ;
 
1232
        }
 
1233
    split = 0 ;
 
1234
    face = start_face [itype] [edge] ;
 
1235
    for (i = 0 ; i < nlist - 1 ; i ++ )
 
1236
        {
 
1237
            /* record this edge */
 
1238
            permute [edge * pt] = i ;
 
1239
            splits [edge] = split ;
 
1240
            mask [edge] = 0 ;
 
1241
            /* advance to next edge */
 
1242
            ttry = face_edges [itype] [face] ;
 
1243
            lttry = lens [itype] [face] ;
 
1244
            now = 0 ;
 
1245
            for ( j = 1 ; j < lttry ; j ++ )
 
1246
                if (abs (ttry [now] - edge) > abs (ttry [j] - edge))
 
1247
                    now = j ;
 
1248
            now ++ ;
 
1249
            /* test opposite edge first (make X, never // or \\) */
 
1250
 edge = ttry [(now + 1) % lttry] ;
 
1251
 if ( ! mask [edge])
 
1252
     {
 
1253
         /* otherwise one or the other opposite edges must be set */
 
1254
         edge = ttry [now % lttry] ;
 
1255
         if ( ! mask [edge])
 
1256
             {
 
1257
                 edge = ttry [ (now + 2) % lttry] ;
 
1258
                 if ( ! mask [edge])
 
1259
                     {
 
1260
                         split ++ ;
 
1261
                         for (edge = 0 ; edge < no_edges [itype] ; edge++)
 
1262
                             {
 
1263
                                 if ( mask [edge] != 0 )
 
1264
                                     {
 
1265
                                         break ;
 
1266
                                     }
 
1267
                             }
 
1268
                     }
 
1269
             }
 
1270
     }
 
1271
 ttry = edge_faces [itype] [edge] ;
 
1272
 face = (face == ttry [0]) ? ttry [1] : ttry [0] ;
 
1273
        }
 
1274
            permute [edge * pt] = nlist - 1 ;
 
1275
            splits [edge] = split ;
 
1276
            mask [edge] = 0 ;
 
1277
            if (split != 0)
 
1278
                for ( i = 0 , j = 0 ; i < no_edges [itype] ; i ++ , j += pt)
 
1279
                    {
 
1280
                        permute [j] += no_edges [itype] * splits [i] ;
 
1281
                    }
 
1282
            return ;
 
1283
}
 
1284
 
 
1285
static char arr_construct3__doc__ [] =
 
1286
"" ;
 
1287
 
 
1288
static PyObject *
 
1289
arr_construct3 (PyObject * self, PyObject * args)
 
1290
{ /* construct3 (mask, itype) computes how the cut
 
1291
     edges of a particular type of cell must be ordered so
 
1292
     that the polygon of intersection can be drawn correctly.
 
1293
     itype = 0 for tetrahedra; 1 for pyramids; 2 for prisms;
 
1294
     3 for hexahedra. Suppose nv is the number of vertices
 
1295
     of the cell type, and ne is the number of edges. Mask
 
1296
     has been ravelled so that it was flat, originally it
 
1297
     had 2**nv-2 rows, each with ne entries. Each row is
 
1298
     ne long, and has an entry of 1 corresponding to each
 
1299
     edge that is cut when the set of vertices corresponding
 
1300
     to the row index has negative values. (The binary number
 
1301
     for the row index + 1 has a one in position i if vertex
 
1302
     i has a negative value.) The return array permute is
 
1303
     ne by 2**nv-2, and the rows of permute tell how
 
1304
     the edges should be ordered to draw the polygon properly. */
 
1305
 
 
1306
    PyObject * masko ;
 
1307
    PyArrayObject * permutea, * maska ;
 
1308
    int itype, ne, pt, nm ;
 
1309
    int * permute, * mask ;
 
1310
    int permute_dims [2] ;
 
1311
    int i ;
 
1312
 
 
1313
    /*    dbg = fopen ("dbg","w"); */
 
1314
    Py_Try (PyArg_ParseTuple ( args, "Oi", & masko, & itype ) ) ;
 
1315
    GET_ARR (maska, masko, PyArray_INT, 1) ;
 
1316
    mask = (int *) A_DATA (maska) ;
 
1317
    permute_dims [0] = ne = no_edges [itype] ;
 
1318
    permute_dims [1] = pt = powers [itype] ;
 
1319
    nm = A_DIM (maska, 0) ;
 
1320
    if ( ne * pt != nm ) {
 
1321
        SETERR ("permute and mask must have same number of elements.") ;
 
1322
        Py_DECREF (maska) ;
 
1323
        return NULL ;
 
1324
    }
 
1325
    Py_Try(permutea =
 
1326
           (PyArrayObject *) PyArray_FromDims (2, permute_dims, PyArray_INT));
 
1327
    permute = (int *) A_DATA (permutea) ;
 
1328
    for ( i = 0 ; i < pt ; i ++, permute ++, mask += ne )
 
1329
        {
 
1330
            walk3 (permute, mask, itype, pt) ;
 
1331
        }
 
1332
    Py_DECREF (maska) ;
 
1333
    /*    fclose (dbg) ; */
 
1334
    return PyArray_Return (permutea) ;
 
1335
}
 
1336
 
 
1337
static char arr_to_corners__doc__ [] =
 
1338
"" ;
 
1339
 
 
1340
static PyObject *
 
1341
arr_to_corners (PyObject * self, PyObject * args)
 
1342
{
 
1343
    /* This routine takes an array of floats describing cell-centered
 
1344
       values and expands it to node-centered values. */
 
1345
    PyObject * oarr, * onv;
 
1346
    int sum_nv;
 
1347
    PyArrayObject * aarr, *anv, *ares;
 
1348
    int * nv , i, j, snv, jtot;
 
1349
    double * arr, * res;
 
1350
 
 
1351
    Py_Try (PyArg_ParseTuple (args, "OOi", & oarr, & onv, & sum_nv));
 
1352
    GET_ARR (aarr, oarr, PyArray_DOUBLE, 1) ;
 
1353
    if isARRAY (onv) {
 
1354
        GET_ARR (anv, onv, PyArray_INT, 1) ;
 
1355
    }
 
1356
    else {
 
1357
        ERRSS ("The second argument must be an Int array") ;
 
1358
        Py_DECREF (aarr) ;
 
1359
        return (NULL) ;
 
1360
    }
 
1361
    snv = A_SIZE (anv) ;
 
1362
    if (snv != A_SIZE (aarr)) {
 
1363
        ERRSS ("The first and second arguments must be the same size.") ;
 
1364
        Py_DECREF (aarr) ;
 
1365
        Py_DECREF (anv) ;
 
1366
        return NULL ;
 
1367
    }
 
1368
    if ( ! (ares = (PyArrayObject *)
 
1369
            PyArray_FromDims (1, & sum_nv, PyArray_DOUBLE))) {
 
1370
        ERRSS ("Unable to create result array.") ;
 
1371
        Py_DECREF (aarr) ;
 
1372
        Py_DECREF (anv) ;
 
1373
        return NULL ;
 
1374
    }
 
1375
    res = (double *) A_DATA (ares) ;
 
1376
    arr = (double *) A_DATA (aarr) ;
 
1377
    nv = (int *) A_DATA (anv) ;
 
1378
    jtot = 0;
 
1379
    for ( i = 0; i < snv; i++) {
 
1380
        for (j = 0; j < nv [i]; j++) {
 
1381
            res [j + jtot] = arr [i];
 
1382
        }
 
1383
        jtot = jtot + nv [i];
 
1384
    }
 
1385
 
 
1386
    Py_DECREF (aarr) ;
 
1387
    Py_DECREF (anv) ;
 
1388
 
 
1389
    return PyArray_Return (ares) ;
 
1390
}
 
1391
 
 
1392
/* List of methods defined in the module */
 
1393
 
 
1394
static struct PyMethodDef arr_methods[] = {
 
1395
    {"histogram",       arr_histogram,  1,      arr_histogram__doc__},
 
1396
    {"array_set",       arr_array_set,  1,      arr_array_set__doc__},
 
1397
    {"index_sort",      arr_index_sort, 1,      arr_index_sort__doc__},
 
1398
    {"interp",  arr_interp,     1,      arr_interp__doc__},
 
1399
    {"digitize",        arr_digitize,   1,      arr_digitize__doc__},
 
1400
    {"zmin_zmax", arr_zmin_zmax, 1,      arr_zmin_zmax__doc__},
 
1401
    {"reverse", arr_reverse,    1,      arr_reverse__doc__},
 
1402
    {"span",    arr_span,       1,      arr_span__doc__},
 
1403
    {"nz",      arr_nz,         1,      arr_nz__doc__},
 
1404
    {"find_mask",arr_find_mask,  1,      arr_find_mask__doc__},
 
1405
    {"construct3",        arr_construct3, 1,     arr_construct3__doc__},
 
1406
    {"to_corners",   arr_to_corners,     1,      arr_to_corners__doc__},
 
1407
 
 
1408
    {NULL, NULL}                /* sentinel */
 
1409
};
 
1410
 
 
1411
 
 
1412
/* Initialization function for the module (*must* be called initarrayfns) */
 
1413
 
 
1414
static char arrayfns_module_documentation[] =
 
1415
""
 
1416
;
 
1417
 
 
1418
PyMODINIT_FUNC
 
1419
initgistfuncs(void)
 
1420
{
 
1421
    PyObject *m, *d;
 
1422
 
 
1423
    /* Create the module and add the functions */
 
1424
    m = Py_InitModule4("gistfuncs", arr_methods,
 
1425
                       arrayfns_module_documentation,
 
1426
                       (PyObject*)NULL,
 
1427
                       PYTHON_API_VERSION);
 
1428
 
 
1429
    /* Add some symbolic constants to the module */
 
1430
    d = PyModule_GetDict(m);
 
1431
    ErrorObject = PyErr_NewException("gistfuncs.error", NULL, NULL);
 
1432
    PyDict_SetItemString(d, "error", ErrorObject);
 
1433
 
 
1434
    /* XXXX Add constants here */
 
1435
    import_array();
 
1436
}