~ubuntu-branches/ubuntu/lucid/pdl/lucid

« back to all changes in this revision

Viewing changes to Basic/Core/Core.xs.PL

  • Committer: Bazaar Package Importer
  • Author(s): Ben Gertzfield
  • Date: 2002-04-08 18:47:16 UTC
  • Revision ID: james.westby@ubuntu.com-20020408184716-0hf64dc96kin3htp
Tags: upstream-2.3.2
ImportĀ upstreamĀ versionĀ 2.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Create Core.xs
 
3
# - needed since we allow bad pixel handling to be switched off
 
4
#
 
5
 
 
6
use strict;
 
7
 
 
8
use Config;
 
9
use File::Basename qw(&basename &dirname);
 
10
 
 
11
# check for bad value support
 
12
use vars qw( $bvalflag $usenan );
 
13
require "badsupport.p";
 
14
 
 
15
# are we big or little endian?
 
16
require PDL::Core::Dev;
 
17
my $isbigendian = PDL::Core::Dev::isbigendian();
 
18
 
 
19
# This forces PL files to create target in same directory as PL file.
 
20
# This is so that make depend always knows where to find PL derivatives.
 
21
chdir(dirname($0));
 
22
my $file;
 
23
($file = basename($0)) =~ s/\.PL$//;
 
24
$file =~ s/\.pl$//
 
25
        if ($Config{'osname'} eq 'VMS' or
 
26
            $Config{'osname'} eq 'OS2');  # "case-forgiving"
 
27
 
 
28
if ( $bvalflag ) {
 
29
    print "Extracting $file (WITH bad value support)\n";
 
30
} else {                     
 
31
    print "Extracting $file (NO bad value support)\n";
 
32
}
 
33
open OUT,">$file" or die "Can't create $file: $!";
 
34
chmod 0644, $file;
 
35
 
 
36
print OUT <<"!WITH!SUBS!";
 
37
 
 
38
/*
 
39
   Core.xs
 
40
   - automatically generated by Core.xs.PL
 
41
   - bad value support = $bvalflag
 
42
*/
 
43
!WITH!SUBS!
 
44
 
 
45
print OUT <<'!NO!SUBS!';
 
46
 
 
47
#ifndef WIN32
 
48
#include <unistd.h>
 
49
#include <sys/mman.h>
 
50
#include <fcntl.h>
 
51
#define USE_MMAP
 
52
#endif
 
53
 
 
54
#include "EXTERN.h"   /* std perl include */
 
55
#include "perl.h"     /* std perl include */
 
56
#include "XSUB.h"     /* XSUB include */
 
57
 
 
58
#if defined(CONTEXT)
 
59
#undef CONTEXT
 
60
#endif
 
61
 
 
62
#define PDL_CORE      /* For certain ifdefs */
 
63
#include "pdl.h"      /* Data structure declarations */
 
64
#include "pdlcore.h"  /* Core declarations */
 
65
 
 
66
!NO!SUBS!
 
67
 
 
68
    if ( $bvalflag ) {
 
69
        print OUT "#include <float.h>\n" unless $usenan;
 
70
        print OUT "#include <limits.h>\n";
 
71
 
 
72
        # set up the NaN value, if necessary
 
73
        # based on the GNU version of /usr/include/bits/nan.h
 
74
        # - need to work out whether we're big/little endian here
 
75
        #
 
76
        if ( $usenan ) {
 
77
            print OUT 
 
78
                "static union { unsigned char __c[4]; float __d; } __pdl_nan = { ";
 
79
            if ( $isbigendian ) {
 
80
                print OUT "{ 0x7f, 0xc0, 0, 0 } };\n\n";
 
81
            } else {
 
82
                print OUT "{ 0, 0, 0xc0, 0x7f } };\n\n";
 
83
            }
 
84
        } # if: $usenan
 
85
    } # if: $bvalflag
 
86
 
 
87
print OUT <<'!NO!SUBS!';
 
88
 
 
89
/* Return a integer or numeric scalar as approroate */
 
90
 
 
91
#define setflag(reg,flagval,val) (val?(reg |= flagval):(reg &= ~flagval))
 
92
 
 
93
#define SET_RETVAL_NV(x) x->datatype<PDL_F ? (RETVAL=newSViv( (IV)result )) : (RETVAL=newSVnv( result ))
 
94
 
 
95
Core PDL; /* Struct holding pointers to shared C routines */
 
96
 
 
97
#ifdef FOO
 
98
Core *pdl__Core_get_Core() /* INTERNAL TO CORE! DON'T CALL FROM OUTSIDE */
 
99
{
 
100
        return PDL;
 
101
}
 
102
#endif
 
103
 
 
104
int pdl_debugging=0;
 
105
 
 
106
#define CHECKP(p)    if ((p) == NULL) croak("Out of memory")
 
107
 
 
108
static int* pdl_packint( SV* sv, int *ndims ) {
 
109
 
 
110
   SV*  bar;
 
111
   AV*  array;
 
112
   int i;
 
113
   int *dims;
 
114
 
 
115
   if (!(SvROK(sv) && SvTYPE(SvRV(sv))==SVt_PVAV))  /* Test */
 
116
       return NULL;
 
117
   array = (AV *) SvRV(sv);   /* dereference */
 
118
     *ndims = (int) av_len(array) + 1;  /* Number of dimensions */
 
119
   /* Array space */
 
120
   dims = (int *) pdl_malloc( (*ndims) * sizeof(*dims) );
 
121
   CHECKP(dims);
 
122
 
 
123
   for(i=0; i<(*ndims); i++) {
 
124
      bar = *(av_fetch( array, i, 0 )); /* Fetch */
 
125
      dims[i] = (int) SvIV(bar);
 
126
   }
 
127
   return dims;
 
128
}
 
129
 
 
130
static SV* pdl_unpackint ( PDL_Long *dims, int ndims ) {
 
131
 
 
132
   AV*  array;
 
133
   int i;
 
134
 
 
135
   array = newAV();
 
136
 
 
137
   for(i=0; i<ndims; i++) /* if ndims == 0, nothing stored -> ok */
 
138
         av_store( array, i, newSViv( (IV)dims[i] ) );
 
139
 
 
140
   return (SV*) array;
 
141
}
 
142
 
 
143
!NO!SUBS!
 
144
 
 
145
    if ( $bvalflag ) {
 
146
        print OUT <<'!NO!SUBS!';
 
147
 
 
148
#ifdef FOOFOO_PROPOGATE_BADFLAG
 
149
 
 
150
/*
 
151
 * this seems to cause an infinite loop in between tests 42 & 43 of
 
152
 * t/bad.t - ie
 
153
 *
 
154
 * $a = sequence( byte, 2, 3 );
 
155
 * $b = $a->slice("(1),:");
 
156
 * my $mask = sequence( byte, 2, 3 );
 
157
 * $mask = $mask->setbadif( ($mask % 3) == 2 );
 
158
 * print "a,b == ", $a->badflag, ",", $b->badflag, "\n";
 
159
 * $a->inplace->copybad( $mask );                          <-- think this is the call
 
160
 * print "a,b == ", $a->badflag, ",", $b->badflag, "\n";
 
161
 * print "$a $b\n";
 
162
 * ok( $b->badflag, 1 );
 
163
 * 
 
164
 */
 
165
 
 
166
/* used by propogate_badflag() */
 
167
 
 
168
void propogate_badflag_children( pdl *it, int newval ) {
 
169
    PDL_DECL_CHILDLOOP(it)
 
170
    PDL_START_CHILDLOOP(it)
 
171
    {
 
172
        pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it);
 
173
        int i;
 
174
 
 
175
        for( i = trans->vtable->nparents;
 
176
             i < trans->vtable->npdls; 
 
177
             i++ ) {
 
178
            
 
179
            pdl *child = trans->pdls[i];
 
180
 
 
181
            if ( newval ) child->state |=  PDL_BADVAL;
 
182
            else          child->state &= ~PDL_BADVAL;
 
183
 
 
184
            /* make sure we propogate to grandchildren, etc */
 
185
            propogate_badflag_children( child, newval );
 
186
 
 
187
        } /* for: i */
 
188
    }
 
189
    PDL_END_CHILDLOOP(it)
 
190
} /* propogate_badflag_children */
 
191
 
 
192
/* used by propogate_badflag() */
 
193
 
 
194
void propogate_badflag_parents( pdl *it ) {
 
195
    PDL_DECL_CHILDLOOP(it)
 
196
    PDL_START_CHILDLOOP(it)
 
197
    {
 
198
        pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it);
 
199
        int i;
 
200
 
 
201
        for( i = 0;
 
202
             i < trans->vtable->nparents; 
 
203
             i++ ) {
 
204
            
 
205
            pdl *parent = trans->pdls[i];
 
206
 
 
207
            /* only sets allowed here */
 
208
            parent->state |= PDL_BADVAL;
 
209
 
 
210
            /* make sure we propogate to grandparents, etc */
 
211
            propogate_badflag_parents( parent );
 
212
 
 
213
        } /* for: i */
 
214
    }
 
215
    PDL_END_CHILDLOOP(it)
 
216
} /* propogate_badflag_parents */
 
217
 
 
218
/*
 
219
 * we want to change the bad flag of the children
 
220
 * (newval = 1 means set flag, 0 means clear it).
 
221
 * If newval == 1, then we also loop through the
 
222
 * parents, setting their bad flag
 
223
 *
 
224
 * thanks to Christian Soeller for this 
 
225
 */
 
226
 
 
227
void propogate_badflag( pdl *it, int newval ) {
 
228
   /* only do anything if the flag has changed - do we need this check ? */
 
229
   if ( newval ) {
 
230
      if ( (it->state & PDL_BADVAL) == 0 ) {
 
231
         propogate_badflag_parents( it );
 
232
         propogate_badflag_children( it, newval );
 
233
      }
 
234
   } else {
 
235
      if ( (it->state & PDL_BADVAL) > 0 ) {
 
236
         propogate_badflag_children( it, newval );
 
237
      }
 
238
 
 
239
   }
 
240
 
 
241
} /* propogate_badflag */
 
242
 
 
243
#else        /* FOOFOO_PROPOGATE_BADFLAG */
 
244
 
 
245
/* newval = 1 means set flag, 0 means clear it */
 
246
/* thanks to Christian Soeller for this */
 
247
 
 
248
void propogate_badflag( pdl *it, int newval ) {
 
249
    PDL_DECL_CHILDLOOP(it)
 
250
    PDL_START_CHILDLOOP(it)
 
251
    {
 
252
        pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it);
 
253
        int i;
 
254
 
 
255
        for( i = trans->vtable->nparents;
 
256
             i < trans->vtable->npdls; i++ ) {
 
257
            
 
258
            pdl *child = trans->pdls[i];
 
259
 
 
260
            if ( newval ) child->state |=  PDL_BADVAL;
 
261
            else          child->state &= ~PDL_BADVAL;
 
262
 
 
263
            /* make sure we propogate to grandchildren, etc */
 
264
            propogate_badflag( child, newval );
 
265
 
 
266
        } /* for: i */
 
267
    }
 
268
    PDL_END_CHILDLOOP(it)
 
269
} /* propogate_badflag */
 
270
 
 
271
#endif    /* FOOFOO_PROPOGATE_BADFLAG */
 
272
 
 
273
 
 
274
/* this is horrible - the routines from bad should perhaps be here instead ? */
 
275
double pdl_get_badvalue( int datatype ) {
 
276
    double retval;
 
277
    switch ( datatype ) {
 
278
        case 0: retval = PDL.bvals.Byte;   break;
 
279
        case 1: retval = PDL.bvals.Short;  break;
 
280
        case 2: retval = PDL.bvals.Ushort; break;
 
281
        case 3: retval = PDL.bvals.Long;   break;
 
282
        case 4: retval = PDL.bvals.Float;  break;
 
283
        case 5: retval = PDL.bvals.Double; break;
 
284
 
 
285
      default:
 
286
        croak("Unknown type sent to pdl_get_badvalue\n");
 
287
    }
 
288
    return retval;
 
289
} /* pdl_get_badvalue() */
 
290
 
 
291
!NO!SUBS!
 
292
    
 
293
} # if: $bvalflag
 
294
 
 
295
print OUT <<'!NO!SUBS!';
 
296
 
 
297
MODULE = PDL::Core     PACKAGE = PDL
 
298
 
 
299
 
 
300
# Destroy a PDL - note if a hash do nothing, the $$x{PDL} component
 
301
# will be destroyed anyway on a separate call
 
302
 
 
303
void
 
304
DESTROY(sv)
 
305
  SV *  sv;
 
306
  CODE:
 
307
    pdl *self;
 
308
    if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV)
 
309
       1; /* Do nothing */
 
310
    else {
 
311
       self = SvPDLV(sv);
 
312
       PDLDEBUG_f(printf("DESTROYING %d\n",self);)
 
313
       if (self != NULL)
 
314
          pdl_destroy(self);
 
315
    }
 
316
 
 
317
# Return the transformation object or an undef otherwise.
 
318
 
 
319
SV *
 
320
get_trans(self)
 
321
        pdl *self;
 
322
        CODE:
 
323
        ST(0) = sv_newmortal();
 
324
        if(self->trans)  {
 
325
                sv_setref_pv(ST(0), "PDL::Trans", (void*)(self->trans));
 
326
        } else {
 
327
               ST(0) = &PL_sv_undef;
 
328
        }
 
329
 
 
330
# This will change in the future, as can be seen from the name ;)
 
331
# the argument passing is a real quick hack: you can pass 3 integers
 
332
# and nothing else.
 
333
 
 
334
MODULE = PDL::Core      PACKAGE = PDL::Trans
 
335
void
 
336
call_trans_foomethod(trans,i1,i2,i3)
 
337
        pdl_trans *trans
 
338
        int i1
 
339
        int i2
 
340
        int i3
 
341
        CODE:
 
342
        PDL_TR_CHKMAGIC(trans);
 
343
        pdl_trans_changesoon(trans,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED);
 
344
        if(trans->vtable->foomethod == NULL) {
 
345
                croak("This transformation doesn't have a foomethod!");
 
346
        }
 
347
        (trans->vtable->foomethod)(trans,i1,i2,i3);
 
348
        pdl_trans_changed(trans,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED);
 
349
 
 
350
MODULE = PDL::Core      PACKAGE = PDL
 
351
 
 
352
int
 
353
iscontig(x)
 
354
   pdl* x
 
355
   CODE:
 
356
      RETVAL = 1;
 
357
      pdl_make_physvaffine( x );
 
358
        if PDL_VAFFOK(x) {
 
359
           int i, inc=1;
 
360
           printf("vaff check...\n");
 
361
           for (i=0;i<x->ndims;i++) {
 
362
              if (PDL_REPRINC(x,i) != inc) {
 
363
                     RETVAL = 0;
 
364
                     break;
 
365
              }
 
366
              inc *= x->dims[i];
 
367
           }
 
368
        }
 
369
  OUTPUT:
 
370
    RETVAL
 
371
 
 
372
!NO!SUBS!
 
373
 
 
374
# access (read, if set is true then write as well)
 
375
# to piddle's state
 
376
#
 
377
 
 
378
my %flags = 
 
379
    ( 
 
380
      hdrcpy => { set => 1 },
 
381
      fflows => { FLAG => "DATAFLOW_F" },
 
382
      bflows => { FLAG => "DATAFLOW_B" },
 
383
      is_inplace => { FLAG => "INPLACE" },
 
384
      donttouch => { FLAG => "DONTTOUCHDATA" },
 
385
      allocated => { },
 
386
      vaffine => { FLAG => "OPT_VAFFTRANSOK" },
 
387
      anychgd => { FLAG => "ANYCHANGED" },
 
388
      dimschgd => { FLAG => "PARENTDIMSCHANGED" },
 
389
 
 
390
     );
 
391
 
 
392
#if ( $bvalflag ) { $flags{baddata} = { set => 1, FLAG => "BADVAL" }; }
 
393
 
 
394
foreach my $name ( keys %flags ) {
 
395
    my $flag = "PDL_" . ($flags{$name}{FLAG} || uc($name));
 
396
    if ( $flags{$name}{set} ) {
 
397
        print OUT <<"!WITH!SUBS!";
 
398
int
 
399
$name(x,mode=0)
 
400
        pdl *x
 
401
        int mode
 
402
        CODE:
 
403
        if (items>1) 
 
404
           { setflag(x->state,$flag,mode); }
 
405
        RETVAL = ((x->state & $flag) > 0);
 
406
        OUTPUT:
 
407
        RETVAL
 
408
 
 
409
!WITH!SUBS!
 
410
 
 
411
} else {
 
412
        print OUT <<"!WITH!SUBS!";
 
413
int
 
414
$name(self)
 
415
        pdl *self
 
416
        CODE:
 
417
        RETVAL = ((self->state & $flag) > 0);
 
418
        OUTPUT:
 
419
        RETVAL
 
420
 
 
421
!WITH!SUBS!
 
422
 
 
423
 
424
 
 
425
} # foreach: keys %flags 
 
426
 
 
427
print OUT <<'!NO!SUBS!';
 
428
 
 
429
void
 
430
set_inplace(self,val)
 
431
  pdl *self;
 
432
  int val;
 
433
  CODE:
 
434
    setflag(self->state,PDL_INPLACE,val);
 
435
 
 
436
int
 
437
address(self)
 
438
  pdl *self;
 
439
  CODE:
 
440
    RETVAL = (int) self;
 
441
  OUTPUT:
 
442
    RETVAL
 
443
 
 
444
pdl *
 
445
pdl_hard_copy(src)
 
446
        pdl *src;
 
447
 
 
448
pdl *
 
449
sever(src)
 
450
        pdl *src;
 
451
        CODE:
 
452
                if(src->trans) {
 
453
                        pdl_make_physvaffine(src);
 
454
                        pdl_destroytransform(src->trans,1);
 
455
                }
 
456
                RETVAL=src;
 
457
        OUTPUT:
 
458
                RETVAL
 
459
 
 
460
int
 
461
set_data_by_mmap(it,fname,len,writable,shared,creat,mode,trunc)
 
462
        pdl *it
 
463
        char *fname
 
464
        int len
 
465
        int writable
 
466
        int shared
 
467
        int creat
 
468
        int mode
 
469
        int trunc
 
470
        CODE:
 
471
#ifdef USE_MMAP
 
472
       int fd;
 
473
       pdl_freedata(it);
 
474
       fd = open(fname,(writable && shared ? O_RDWR : O_RDONLY)|
 
475
               (creat ? O_CREAT : 0),mode);
 
476
       if(fd < 0) {
 
477
               croak("Error opening file");
 
478
       }
 
479
       if(trunc) {
 
480
               ftruncate(fd,0);   /* Clear all previous data */
 
481
               ftruncate(fd,len); /* And make it long enough */
 
482
       }
 
483
       if(len) {
 
484
                it->data = mmap(0,len,PROT_READ | (writable ?
 
485
                                        PROT_WRITE : 0),
 
486
                                (shared ? MAP_SHARED : MAP_PRIVATE),
 
487
                                fd,0);
 
488
                if(!it->data)
 
489
                        croak("Error mmapping!");
 
490
       } else {
 
491
               /* Special case: zero-length file */
 
492
               it->data = NULL;
 
493
       }
 
494
       PDLDEBUG_f(printf("PDL::MMap: mapped to %d\n",it->data);)
 
495
       it->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
 
496
       pdl_add_deletedata_magic(it, pdl_delete_mmapped_data, len);
 
497
       close(fd);
 
498
#else
 
499
        croak("mmap not supported on this architecture");
 
500
#endif
 
501
       RETVAL = 1;
 
502
OUTPUT:
 
503
       RETVAL
 
504
 
 
505
 
 
506
int
 
507
set_data_by_offset(it,orig,offset)
 
508
      pdl *it
 
509
      pdl *orig
 
510
      int offset
 
511
      CODE:
 
512
              pdl_freedata(it);
 
513
              it->data = ((char *) orig->data) + offset;
 
514
              it->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
 
515
              RETVAL = 1;
 
516
      OUTPUT:
 
517
              RETVAL
 
518
 
 
519
int
 
520
nelem(x)
 
521
        pdl *x
 
522
        CODE:
 
523
                pdl_make_physdims(x);
 
524
                RETVAL = x->nvals;
 
525
        OUTPUT:
 
526
                RETVAL
 
527
 
 
528
# Convert PDL to new datatype (called by float(), int() etc.)
 
529
 
 
530
# SV *
 
531
# convert(a,datatype)
 
532
#    pdl*       a
 
533
#    int        datatype
 
534
#    CODE:
 
535
#     pdl* b;
 
536
#     pdl_make_physical(a);
 
537
#     RETVAL = pdl_copy(a,""); /* Init value to return */
 
538
#     b = SvPDLV(RETVAL);      /* Map */
 
539
#     pdl_converttype( &b, datatype, PDL_PERM );
 
540
#     PDLDEBUG_f(printf("converted %d, %d, %d, %d\n",a, b, a->datatype, b->datatype));
 
541
 
 
542
#     OUTPUT:
 
543
#      RETVAL
 
544
 
 
545
 
 
546
# Call my howbig function
 
547
 
 
548
int
 
549
howbig_c(datatype)
 
550
   int  datatype
 
551
   CODE:
 
552
     RETVAL = pdl_howbig(datatype);
 
553
   OUTPUT:
 
554
     RETVAL
 
555
 
 
556
MODULE = PDL::Core     PACKAGE = PDL::Core
 
557
 
 
558
int
 
559
set_debugging(i)
 
560
        int i;
 
561
        CODE:
 
562
        RETVAL = pdl_debugging;
 
563
        pdl_debugging = i;
 
564
        OUTPUT:
 
565
        RETVAL
 
566
 
 
567
 
 
568
SV *
 
569
sclr_c(it)
 
570
   pdl* it
 
571
   CODE:
 
572
        PDL_Long nullp = 0;
 
573
        PDL_Long dummyd = 1;
 
574
        PDL_Long dummyi = 1;
 
575
        double result;
 
576
 
 
577
        /* get the first element of a piddle and return as
 
578
         * Perl double scalar (NV)
 
579
         */
 
580
        pdl_make_physvaffine( it );
 
581
        if (it->nvals < 1)
 
582
           croak("piddle must have at least one element");
 
583
        /* offs = PDL_REPROFFS(it); */
 
584
        /* result = pdl_get_offs(PDL_REPRP(it),offs); */
 
585
        result=pdl_at(PDL_REPRP(it), it->datatype, &nullp, &dummyd,
 
586
        &dummyi, PDL_REPROFFS(it),1);
 
587
        SET_RETVAL_NV(it) ;
 
588
 
 
589
    OUTPUT:
 
590
        RETVAL
 
591
 
 
592
 
 
593
SV *
 
594
at_c(x,position)
 
595
   pdl* x
 
596
   PDL_Long *   pos = NO_INIT
 
597
   CODE:
 
598
    int npos, ipos;
 
599
    double result;
 
600
 
 
601
      pdl_make_physvaffine( x );
 
602
 
 
603
    pos = pdl_packdims( ST(1), &npos);
 
604
    
 
605
    if (pos == NULL || npos < x->ndims)
 
606
       croak("Invalid position");
 
607
 
 
608
    /*  allow additional trailing indices
 
609
     *  which must be all zero, i.e. a
 
610
     *  [3,1,5] piddle is treated as an [3,1,5,1,1,1,....]
 
611
     *  infinite dim piddle
 
612
     */
 
613
    for (ipos=x->ndims; ipos<npos; ipos++)
 
614
      if (pos[ipos] != 0)
 
615
         croak("Invalid position");
 
616
 
 
617
    result=pdl_at(PDL_REPRP(x), x->datatype, pos, x->dims,
 
618
        (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs), PDL_REPROFFS(x),
 
619
        x->ndims);
 
620
 
 
621
    SET_RETVAL_NV(x) ;
 
622
 
 
623
    OUTPUT:
 
624
     RETVAL
 
625
 
 
626
void
 
627
list_c(x)
 
628
        pdl *x
 
629
        PPCODE:
 
630
        PDL_Long *inds,*incs,offs;
 
631
        void *data;
 
632
        int ind;
 
633
        int stop = 0;
 
634
        pdl_make_physvaffine( x );
 
635
        inds = pdl_malloc(sizeof(PDL_Long) * x->ndims); /* GCC -> on stack :( */
 
636
 
 
637
        data = PDL_REPRP(x);
 
638
        incs = (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs);
 
639
        offs = PDL_REPROFFS(x);
 
640
        EXTEND(sp,x->nvals);
 
641
        for(ind=0; ind < x->ndims; ind++) inds[ind] = 0;
 
642
        while(!stop) {
 
643
                PUSHs(sv_2mortal(newSVnv(pdl_at( data, x->datatype,
 
644
                        inds, x->dims, incs, offs, x->ndims))));
 
645
                stop = 1;
 
646
                for(ind = 0; ind < x->ndims; ind++)
 
647
                        if(++(inds[ind]) >= x->dims[ind])
 
648
                                inds[ind] = 0;
 
649
                        else
 
650
                                {stop = 0; break;}
 
651
        }
 
652
 
 
653
# returns the string 'BAD' if an element is bad
 
654
#
 
655
 
 
656
SV *
 
657
listref_c(x)
 
658
   pdl *x
 
659
  CODE:
 
660
   PDL_Long *inds,*incs,offs;
 
661
   void *data;
 
662
   int ind, lind;
 
663
   int stop = 0;
 
664
   AV *av;
 
665
 
 
666
!NO!SUBS!
 
667
 
 
668
if ( $bvalflag ) {
 
669
    # note: 
 
670
    #  the badvalue is stored in a double, but that's what pdl_at()
 
671
    #  returns
 
672
 
 
673
    print OUT 
 
674
'
 
675
   SV *sv;
 
676
   double pdl_val, pdl_badval;
 
677
   int badflag = (x->state & PDL_BADVAL) > 0;
 
678
 
 
679
';
 
680
 
 
681
    # do we have to bother about NaN's?
 
682
    if ( $usenan ) { 
 
683
       print OUT
 
684
'
 
685
   if ( badflag && x->datatype < 4 ) {
 
686
      pdl_badval = pdl_get_badvalue( x->datatype ); 
 
687
   }
 
688
';
 
689
   } else {
 
690
       print OUT
 
691
'
 
692
   if ( badflag ) {
 
693
      pdl_badval = pdl_get_badvalue( x->datatype ); 
 
694
   }
 
695
';
 
696
 
 
697
   } # if: $usenan
 
698
} # if: $bvalflag
 
699
 
 
700
print OUT <<'!NO!SUBS!';
 
701
 
 
702
   pdl_make_physvaffine( x );
 
703
   inds = pdl_malloc(sizeof(PDL_Long) * x->ndims); /* GCC -> on stack :( */
 
704
   data = PDL_REPRP(x);
 
705
   incs = (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs);
 
706
   offs = PDL_REPROFFS(x);
 
707
   av = newAV();
 
708
   av_extend(av,x->nvals);
 
709
   lind=0;
 
710
   for(ind=0; ind < x->ndims; ind++) inds[ind] = 0;
 
711
   while(!stop) {
 
712
 
 
713
!NO!SUBS!
 
714
 
 
715
    if ( $bvalflag ) {
 
716
 
 
717
        my $condition;
 
718
        if ( $usenan ) {
 
719
            $condition = '( (x->datatype < 4 && pdl_val == pdl_badval) ||
 
720
                        (x->datatype >= 4 && finite(pdl_val) == 0) )';
 
721
        } else {
 
722
            $condition = 'pdl_val == pdl_badval';
 
723
        }
 
724
 
 
725
        print OUT <<"!WITH!SUBS!";
 
726
      pdl_val = pdl_at( data, x->datatype, inds, x->dims, incs, offs, x->ndims );
 
727
      if ( badflag && $condition ) {
 
728
         sv = newSVpvn( "BAD", 3 );
 
729
      } else {
 
730
         sv = newSVnv( pdl_val );
 
731
      }
 
732
      av_store( av, lind, sv );
 
733
!WITH!SUBS!
 
734
 
 
735
    } else {
 
736
 
 
737
        print OUT <<'!NO!SUBS!';
 
738
      av_store(av,lind,
 
739
               newSVnv( pdl_at( data, x->datatype,
 
740
               inds, x->dims, incs, offs, x->ndims ) )
 
741
               );
 
742
!NO!SUBS!
 
743
 
 
744
} # bvalflag
 
745
 
 
746
print OUT <<'!NO!SUBS!';
 
747
 
 
748
      lind++;
 
749
      stop = 1;
 
750
      for(ind = 0; ind < x->ndims; ind++) {
 
751
         if(++(inds[ind]) >= x->dims[ind]) {
 
752
            inds[ind] = 0;
 
753
         } else {
 
754
            stop = 0; break;
 
755
         }
 
756
      }
 
757
   }
 
758
   RETVAL = newRV_noinc((SV *)av);
 
759
  OUTPUT:
 
760
   RETVAL
 
761
 
 
762
void
 
763
set_c(x,position,value)
 
764
    pdl*        x
 
765
    PDL_Long *  pos = NO_INIT
 
766
    double      value
 
767
   CODE:
 
768
    int npos,ipos;
 
769
 
 
770
    pdl_make_physvaffine( x );
 
771
 
 
772
    pos = pdl_packdims( ST(1), &npos);
 
773
    if (pos == NULL || npos < x->ndims)
 
774
       croak("Invalid position");
 
775
 
 
776
    /*  allow additional trailing indices
 
777
     *  which must be all zero, i.e. a
 
778
     *  [3,1,5] piddle is treated as an [3,1,5,1,1,1,....]
 
779
     *  infinite dim piddle
 
780
     */
 
781
    for (ipos=x->ndims; ipos<npos; ipos++)
 
782
      if (pos[ipos] != 0)
 
783
         croak("Invalid position");
 
784
 
 
785
    pdl_children_changesoon( x , PDL_PARENTDATACHANGED );
 
786
    pdl_set(PDL_REPRP(x), x->datatype, pos, x->dims,
 
787
        (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs), PDL_REPROFFS(x),
 
788
        x->ndims,value);
 
789
    if (PDL_VAFFOK(x))
 
790
       pdl_vaffinechanged(x, PDL_PARENTDATACHANGED);
 
791
    else
 
792
       pdl_changed( x , PDL_PARENTDATACHANGED , 0 );
 
793
 
 
794
BOOT:
 
795
 
 
796
   /* Initialise structure of pointers to core C routines */
 
797
 
 
798
   PDL.Version     = PDL_CORE_VERSION;
 
799
   PDL.SvPDLV      = SvPDLV;
 
800
   PDL.SetSV_PDL   = SetSV_PDL;
 
801
   PDL.create      = pdl_create;
 
802
   PDL.pdlnew      = pdl_external_new;
 
803
   PDL.tmp         = pdl_external_tmp;
 
804
   PDL.destroy     = pdl_destroy;
 
805
   PDL.null        = pdl_null;
 
806
   PDL.copy        = pdl_copy;
 
807
   PDL.converttype = pdl_converttype;
 
808
   PDL.twod        = pdl_twod;
 
809
   PDL.smalloc     = pdl_malloc;
 
810
   PDL.howbig      = pdl_howbig;
 
811
   PDL.packdims    = pdl_packdims;
 
812
   PDL.unpackdims  = pdl_unpackdims;
 
813
   PDL.setdims     = pdl_setdims;
 
814
   PDL.grow        = pdl_grow;
 
815
   PDL.flushcache  = NULL;
 
816
   PDL.reallocdims = pdl_reallocdims;
 
817
   PDL.reallocthreadids = pdl_reallocthreadids;
 
818
   PDL.resize_defaultincs = pdl_resize_defaultincs;
 
819
   PDL.get_threadoffsp = pdl_get_threadoffsp;
 
820
   PDL.thread_copy = pdl_thread_copy;
 
821
   PDL.clearthreadstruct = pdl_clearthreadstruct;
 
822
   PDL.initthreadstruct = pdl_initthreadstruct;
 
823
   PDL.startthreadloop = pdl_startthreadloop;
 
824
   PDL.iterthreadloop = pdl_iterthreadloop;
 
825
   PDL.freethreadloop = pdl_freethreadloop;
 
826
   PDL.thread_create_parameter = pdl_thread_create_parameter;
 
827
   PDL.add_deletedata_magic = pdl_add_deletedata_magic;
 
828
 
 
829
   PDL.setdims_careful = pdl_setdims_careful;
 
830
   PDL.put_offs = pdl_put_offs;
 
831
   PDL.get_offs = pdl_get_offs;
 
832
   PDL.get = pdl_get;
 
833
   PDL.set_trans_childtrans = pdl_set_trans_childtrans;
 
834
   PDL.set_trans_parenttrans = pdl_set_trans_parenttrans;
 
835
   PDL.make_now = pdl_make_now;
 
836
 
 
837
   PDL.get_convertedpdl = pdl_get_convertedpdl;
 
838
 
 
839
   PDL.make_trans_mutual = pdl_make_trans_mutual;
 
840
   PDL.trans_mallocfreeproc = pdl_trans_mallocfreeproc;
 
841
   PDL.make_physical = pdl_make_physical;
 
842
   PDL.make_physdims = pdl_make_physdims;
 
843
   PDL.make_physvaffine = pdl_make_physvaffine;
 
844
   PDL.pdl_barf      = pdl_barf;
 
845
   PDL.allocdata     = pdl_allocdata;
 
846
   PDL.safe_indterm  = pdl_safe_indterm;
 
847
 
 
848
!NO!SUBS!
 
849
 
 
850
if ( $bvalflag ) {
 
851
    print OUT <<'!NO!SUBS!';
 
852
 
 
853
    PDL.propogate_badflag = propogate_badflag;
 
854
 
 
855
    PDL.bvals.Byte   = PDL.bvals.default_Byte   = UCHAR_MAX;
 
856
    PDL.bvals.Short  = PDL.bvals.default_Short  = SHRT_MIN;
 
857
    PDL.bvals.Ushort = PDL.bvals.default_Ushort = USHRT_MAX;
 
858
    PDL.bvals.Long   = PDL.bvals.default_Long   = INT_MIN;
 
859
!NO!SUBS!
 
860
 
 
861
    # note: no defaults if usenan
 
862
    if ( $usenan ) {
 
863
    print OUT 
 
864
'
 
865
    PDL.bvals.Float  = __pdl_nan.__d;
 
866
    PDL.bvals.Double = (double) __pdl_nan.__d;
 
867
';
 
868
} else {
 
869
    print OUT 
 
870
'
 
871
      PDL.bvals.Float  = PDL.bvals.default_Float  = -FLT_MAX;
 
872
      PDL.bvals.Double = PDL.bvals.default_Double = -DBL_MAX;
 
873
';
 
874
 
 
875
} # if: $usenan
 
876
} # if: $bvalflag
 
877
 
 
878
print OUT <<'!NO!SUBS!';
 
879
   /*
 
880
      "Publish" pointer to this structure in perl variable for use
 
881
       by other modules
 
882
   */
 
883
 
 
884
   sv_setiv(perl_get_sv("PDL::SHARE",TRUE), (IV) (void*) &PDL);
 
885
 
 
886
# version of eval() which propogates errors encountered in
 
887
# any internal eval(). Must be passed a code reference - could
 
888
# be use perl_eval_sv() but that is still buggy. This subroutine is
 
889
# primarily for the perlDL shell to use.
 
890
#
 
891
# Thanks to Sarathy (gsar@engin.umich.edu) for suggesting this, though
 
892
# it needs to be wrapped up in the stack stuff to avoid certain SEGVs!
 
893
 
 
894
void
 
895
myeval(code)
 
896
  SV *  code;
 
897
  PROTOTYPE: $
 
898
  CODE:
 
899
   PUSHMARK(sp) ;
 
900
   perl_call_sv(code, G_EVAL|G_KEEPERR|GIMME);
 
901
 
 
902
 
 
903
MODULE = PDL::Core      PACKAGE = PDL
 
904
 
 
905
# pdl_null is created/imported with no PREFIX  as pdl_null.
 
906
#  'null' is supplied in Core.pm that calls 'initialize' which calls
 
907
#   the pdl_null here
 
908
 
 
909
pdl *
 
910
pdl_null(...)
 
911
 
 
912
 
 
913
MODULE = PDL::Core     PACKAGE = PDL::Core     PREFIX = pdl_
 
914
 
 
915
int
 
916
pdl_pthreads_enabled()
 
917
 
 
918
MODULE = PDL::Core      PACKAGE = PDL   PREFIX = pdl_
 
919
 
 
920
int
 
921
isnull(self)
 
922
        pdl *self;
 
923
        CODE:
 
924
                RETVAL= !!(self->state & PDL_NOMYDIMS);
 
925
        OUTPUT:
 
926
                RETVAL
 
927
 
 
928
pdl *
 
929
make_physical(self)
 
930
        pdl *self;
 
931
        CODE:
 
932
                pdl_make_physical(self);
 
933
                RETVAL = self;
 
934
        OUTPUT:
 
935
                RETVAL
 
936
 
 
937
pdl *
 
938
make_physvaffine(self)
 
939
        pdl *self;
 
940
        CODE:
 
941
                pdl_make_physvaffine(self);
 
942
                RETVAL = self;
 
943
        OUTPUT:
 
944
                RETVAL
 
945
 
 
946
 
 
947
pdl *
 
948
make_physdims(self)
 
949
        pdl *self;
 
950
        CODE:
 
951
                pdl_make_physdims(self);
 
952
                RETVAL = self;
 
953
        OUTPUT:
 
954
                RETVAL
 
955
 
 
956
void
 
957
pdl_dump(x)
 
958
  pdl *x;
 
959
 
 
960
void
 
961
pdl_add_threading_magic(it,nthdim,nthreads)
 
962
        pdl *it
 
963
        int nthdim
 
964
        int nthreads
 
965
 
 
966
void
 
967
pdl_remove_threading_magic(it)
 
968
        pdl *it
 
969
        CODE:
 
970
                pdl_add_threading_magic(it,-1,-1);
 
971
 
 
972
MODULE = PDL::Core      PACKAGE = PDL   
 
973
 
 
974
SV *
 
975
initialize(class)
 
976
        SV *class
 
977
 
 
978
        PPCODE:
 
979
        HV *bless_stash;
 
980
 
 
981
        if (SvROK(class)) { /* a reference to a class */
 
982
          bless_stash = SvSTASH(SvRV(class));
 
983
        } else {            /* a class name */
 
984
          bless_stash = gv_stashsv(class, 0);
 
985
        }
 
986
        ST(0) = sv_newmortal();
 
987
        SetSV_PDL(ST(0),pdl_null());   /* set a null PDL to this SV * */
 
988
        ST(0) = sv_bless(ST(0), bless_stash); /* bless appropriately  */
 
989
        XSRETURN(1);
 
990
 
 
991
SV *
 
992
get_dataref(self)
 
993
        pdl *self
 
994
        CODE:
 
995
        if(self->state & PDL_DONTTOUCHDATA) {
 
996
                croak("Trying to get dataref to magical (mmaped?) pdl");
 
997
        }
 
998
        pdl_make_physical(self); /* XXX IS THIS MEMLEAK WITHOUT MORTAL? */
 
999
        RETVAL = (newRV(self->datasv));
 
1000
        OUTPUT:
 
1001
        RETVAL
 
1002
 
 
1003
int
 
1004
get_datatype(self)
 
1005
        pdl *self
 
1006
        CODE:
 
1007
        RETVAL = self->datatype;
 
1008
        OUTPUT:
 
1009
        RETVAL
 
1010
 
 
1011
int
 
1012
upd_data(self)
 
1013
        pdl *self
 
1014
        CODE:
 
1015
       STRLEN n_a;
 
1016
        if(self->state & PDL_DONTTOUCHDATA) {
 
1017
                croak("Trying to touch dataref of magical (mmaped?) pdl");
 
1018
        }
 
1019
       self->data = SvPV((SV*)self->datasv,n_a);
 
1020
        XSRETURN(0);
 
1021
 
 
1022
void
 
1023
set_dataflow_f(self,value)
 
1024
        pdl *self;
 
1025
        int value;
 
1026
        CODE:
 
1027
        if(value)
 
1028
                self->state |= PDL_DATAFLOW_F;
 
1029
        else
 
1030
                self->state &= ~PDL_DATAFLOW_F;
 
1031
 
 
1032
void
 
1033
set_dataflow_b(self,value)
 
1034
        pdl *self;
 
1035
        int value;
 
1036
        CODE:
 
1037
        if(value)
 
1038
                self->state |= PDL_DATAFLOW_B;
 
1039
        else
 
1040
                self->state &= ~PDL_DATAFLOW_B;
 
1041
 
 
1042
int
 
1043
getndims(x)
 
1044
        pdl *x
 
1045
        ALIAS:
 
1046
             PDL::ndims = 1
 
1047
        CODE:
 
1048
                pdl_make_physdims(x);
 
1049
                RETVAL = x->ndims;
 
1050
        OUTPUT:
 
1051
                RETVAL
 
1052
 
 
1053
int
 
1054
getdim(x,y)
 
1055
        pdl *x
 
1056
        int y
 
1057
        ALIAS:
 
1058
             PDL::dim = 1
 
1059
        CODE:
 
1060
                pdl_make_physdims(x);
 
1061
                if (y < 0) y = x->ndims + y;
 
1062
                if (y < 0) croak("negative dim index too large");
 
1063
                if (y < x->ndims)
 
1064
                   RETVAL = x->dims[y];
 
1065
                else
 
1066
                   RETVAL = 1; /* return size 1 for all other dims */
 
1067
        OUTPUT:
 
1068
                RETVAL
 
1069
 
 
1070
int
 
1071
getnthreadids(x)
 
1072
        pdl *x
 
1073
        CODE:
 
1074
                pdl_make_physdims(x);
 
1075
                RETVAL = x->nthreadids;
 
1076
        OUTPUT:
 
1077
                RETVAL
 
1078
 
 
1079
int
 
1080
getthreadid(x,y)
 
1081
        pdl *x
 
1082
        int y
 
1083
        CODE:
 
1084
                RETVAL = x->threadids[y];
 
1085
        OUTPUT:
 
1086
                RETVAL
 
1087
 
 
1088
void
 
1089
setdims(x,dims)
 
1090
        pdl *x
 
1091
        PDL_Long *dims = NO_INIT
 
1092
        CODE:
 
1093
        {
 
1094
                int ndims; int i;
 
1095
                pdl_children_changesoon(x,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED);
 
1096
                dims = pdl_packdims(ST(1),&ndims);
 
1097
                pdl_reallocdims(x,ndims);
 
1098
                for(i=0; i<ndims; i++) x->dims[i] = dims[i];
 
1099
                pdl_resize_defaultincs(x);
 
1100
                x->threadids[0] = ndims;
 
1101
 /* make null != dims = [0] */
 
1102
#ifndef ELIFJELFIJSEJIF
 
1103
                x->state &= ~PDL_NOMYDIMS;
 
1104
#else
 
1105
                   if(ndims == 1 && dims[0] == 0) {
 
1106
                        x->state |= PDL_NOMYDIMS;
 
1107
                   } else {
 
1108
                        x->state &= ~PDL_NOMYDIMS;
 
1109
                   }
 
1110
#endif
 
1111
                pdl_changed(x,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED,0);
 
1112
        }
 
1113
 
 
1114
void
 
1115
dowhenidle()
 
1116
        CODE:
 
1117
                pdl_run_delayed_magic();
 
1118
                XSRETURN(0);
 
1119
 
 
1120
void
 
1121
bind(p,c)
 
1122
        pdl *p
 
1123
        SV *c
 
1124
        PROTOTYPE: $&
 
1125
        CODE:
 
1126
                pdl_add_svmagic(p,c);
 
1127
                XSRETURN(0);
 
1128
 
 
1129
void
 
1130
sethdr(p,h)
 
1131
        pdl *p
 
1132
        SV *h
 
1133
        CODE:
 
1134
        HV* hash;
 
1135
                if(p->hdrsv == NULL) {
 
1136
                      p->hdrsv = (void*) newSViv(0);
 
1137
                }
 
1138
                if (!SvROK(h) || SvTYPE(SvRV(h)) != SVt_PVHV)
 
1139
                      croak("Not a HASH reference");            
 
1140
                p->hdrsv = (void*) newRV( (SV*) SvRV(h) );
 
1141
 
 
1142
SV *
 
1143
gethdr(p)
 
1144
        pdl *p
 
1145
        CODE:
 
1146
                pdl_make_physdims(p);
 
1147
                if(p->hdrsv) {
 
1148
                   RETVAL = newRV( (SV*) SvRV((SV*)p->hdrsv) );
 
1149
                } else {
 
1150
                   XSRETURN_UNDEF;
 
1151
                }
 
1152
        OUTPUT:
 
1153
         RETVAL
 
1154
 
 
1155
void
 
1156
set_datatype(a,datatype)
 
1157
   pdl *a
 
1158
   int datatype
 
1159
   CODE:
 
1160
    pdl_make_physical(a);
 
1161
    if(a->trans)
 
1162
            pdl_destroytransform(a->trans,1);
 
1163
/*     if(! (a->state && PDL_NOMYDIMS)) { */
 
1164
    pdl_converttype( &a, datatype, PDL_PERM );
 
1165
/*     } */
 
1166
 
 
1167
void
 
1168
threadover_n(...)
 
1169
   CODE:
 
1170
   {
 
1171
    int npdls = items - 1;
 
1172
    if(npdls <= 0)
 
1173
        croak("Usage: threadover_n(pdl[,pdl...],sub)");
 
1174
    {
 
1175
            int i,sd;
 
1176
            pdl **pdls = malloc(sizeof(pdl *) * npdls);
 
1177
            int *realdims = malloc(sizeof(int) * npdls);
 
1178
            pdl_thread pdl_thr;
 
1179
            SV *code = ST(items-1);
 
1180
            for(i=0; i<npdls; i++) {
 
1181
                pdls[i] = SvPDLV(ST(i));
 
1182
                /* XXXXXXXX Bad */
 
1183
                pdl_make_physical(pdls[i]);
 
1184
                realdims[i] = 0;
 
1185
            }
 
1186
            pdl_initthreadstruct(0,pdls,realdims,realdims,npdls,NULL,&pdl_thr,NULL);
 
1187
            pdl_startthreadloop(&pdl_thr,NULL,NULL);
 
1188
            sd = pdl_thr.ndims;
 
1189
            do {
 
1190
                dSP;
 
1191
                PUSHMARK(sp);
 
1192
                EXTEND(sp,items);
 
1193
                PUSHs(sv_2mortal(newSViv((sd-1))));
 
1194
                for(i=0; i<npdls; i++) {
 
1195
                        PUSHs(sv_2mortal(newSVnv(
 
1196
                                pdl_get_offs(pdls[i],pdl_thr.offs[i]))));
 
1197
                }
 
1198
                PUTBACK;
 
1199
                perl_call_sv(code,G_DISCARD);
 
1200
            } while(sd = pdl_iterthreadloop(&pdl_thr,0));
 
1201
            pdl_freethreadloop(&pdl_thr);
 
1202
            free(pdls);
 
1203
            free(realdims);
 
1204
    }
 
1205
   }
 
1206
 
 
1207
void
 
1208
threadover(...)
 
1209
   CODE:
 
1210
   {
 
1211
    int npdls, nothers = -1;
 
1212
    int targs = items - 4;
 
1213
    if (items > 0) nothers = SvIV(ST(0));
 
1214
    if(targs <= 0 || nothers < 0 || nothers >= targs)
 
1215
        croak("Usage: threadover(nothers,pdl[,pdl...][,otherpars..],realdims,creating,sub)");
 
1216
    npdls = targs-nothers;
 
1217
    {
 
1218
            int i,j,nd1,nd2,dtype=0,nc=npdls;
 
1219
            SV* rdimslist = ST(items-3);
 
1220
            SV* cdimslist = ST(items-2);
 
1221
            SV *code = ST(items-1);
 
1222
            pdl_thread pdl_thr;
 
1223
            pdl **pdls = malloc(sizeof(pdl *) * npdls);
 
1224
            pdl **child = malloc(sizeof(pdl *) * npdls);
 
1225
            SV **csv = malloc(sizeof(SV *) * npdls);
 
1226
            SV **dims = malloc(sizeof(SV *) * npdls);
 
1227
            SV **incs = malloc(sizeof(SV *) * npdls);
 
1228
            SV **others = malloc(sizeof(SV *) * nothers);
 
1229
            int *creating = pdl_packint(cdimslist,&nd2);
 
1230
            int *realdims = pdl_packint(rdimslist,&nd1);
 
1231
            CHECKP(pdls); CHECKP(child); CHECKP(dims);
 
1232
            CHECKP(incs); CHECKP(csv);
 
1233
 
 
1234
            if (nd1 != npdls || nd2 < npdls)
 
1235
                croak("threadover: need one realdim and creating flag "
 
1236
                      "per pdl!");
 
1237
            for(i=0; i<npdls; i++) {
 
1238
                pdls[i] = SvPDLV(ST(i+1));
 
1239
                if (creating[i])
 
1240
                  nc += realdims[i];
 
1241
                else {
 
1242
                  pdl_make_physical(pdls[i]); /* is this what we want?XXX */
 
1243
                  dtype = PDLMAX(dtype,pdls[i]->datatype);
 
1244
                }
 
1245
            }
 
1246
            for (i=npdls+1; i<=targs; i++)
 
1247
                others[i-npdls-1] = ST(i);
 
1248
            if (nd2 < nc)
 
1249
                croak("Not enough dimension info to create pdls");
 
1250
#ifdef DEBUG_PTHREAD
 
1251
                for (i=0;i<npdls;i++) { /* just for debugging purposes */
 
1252
                printf("pdl %d Dims: [",i);
 
1253
                for (j=0;j<realdims[i];j++)
 
1254
                        printf("%d ",pdls[i]->dims[j]);
 
1255
                printf("] Incs: [");
 
1256
                for (j=0;j<realdims[i];j++)
 
1257
                        printf("%d ",PDL_REPRINC(pdls[i],j));
 
1258
                printf("]\n");
 
1259
                }
 
1260
#endif
 
1261
            pdl_initthreadstruct(0,pdls,realdims,creating,npdls,
 
1262
                                NULL,&pdl_thr,NULL);
 
1263
            for(i=0, nc=npdls; i<npdls; i++)  /* create as necessary */
 
1264
              if (creating[i]) {
 
1265
                int *cp = creating+nc;
 
1266
                pdls[i]->datatype = dtype;
 
1267
                pdl_thread_create_parameter(&pdl_thr,i,cp,0);
 
1268
                nc += realdims[i];
 
1269
                pdl_make_physical(pdls[i]);
 
1270
                PDLDEBUG_f(pdl_dump(pdls[i]));
 
1271
                /* And make it nonnull, now that we've created it */
 
1272
                pdls[i]->state &= (~PDL_NOMYDIMS);
 
1273
              }
 
1274
            pdl_startthreadloop(&pdl_thr,NULL,NULL);
 
1275
            for(i=0; i<npdls; i++) { /* will the SV*'s be properly freed? */
 
1276
                dims[i] = newRV(pdl_unpackint(pdls[i]->dims,realdims[i]));
 
1277
                incs[i] = newRV(pdl_unpackint(PDL_VAFFOK(pdls[i]) ?
 
1278
                pdls[i]->vafftrans->incs: pdls[i]->dimincs,realdims[i]));
 
1279
                /* need to make sure we get the vaffine (grand)parent */
 
1280
                if (PDL_VAFFOK(pdls[i]))
 
1281
                   pdls[i] = pdls[i]->vafftrans->from;
 
1282
                child[i]=pdl_null();
 
1283
                /*  instead of pdls[i] its vaffine parent !!!XXX */
 
1284
                PDL.affine_new(pdls[i],child[i],pdl_thr.offs[i],dims[i],
 
1285
                                                incs[i]);
 
1286
                pdl_make_physical(child[i]); /* make sure we can get at
 
1287
                                                the vafftrans          */
 
1288
                csv[i] = sv_newmortal();
 
1289
                SetSV_PDL(csv[i], child[i]); /* pdl* into SV* */
 
1290
            }
 
1291
            do {  /* the actual threadloop */
 
1292
                pdl_trans_affine *traff;
 
1293
                dSP;
 
1294
                PUSHMARK(sp);
 
1295
                EXTEND(sp,npdls);
 
1296
                for(i=0; i<npdls; i++) {
 
1297
                   /* just twiddle the offset - quick and dirty */
 
1298
                   /* we must twiddle both !! */
 
1299
                   traff = (pdl_trans_affine *) child[i]->trans;
 
1300
                   traff->offs = pdl_thr.offs[i];
 
1301
                   child[i]->vafftrans->offs = pdl_thr.offs[i];
 
1302
                   child[i]->state |= PDL_PARENTDATACHANGED;
 
1303
                   PUSHs(csv[i]);
 
1304
                }
 
1305
                for (i=0; i<nothers; i++)
 
1306
                  PUSHs(others[i]);   /* pass the OtherArgs onto the stack */
 
1307
                PUTBACK;
 
1308
                perl_call_sv(code,G_DISCARD);
 
1309
            } while (pdl_iterthreadloop(&pdl_thr,0));
 
1310
            pdl_freethreadloop(&pdl_thr);
 
1311
            free(pdls);  /* should all these be done with pdl_malloc */
 
1312
            free(dims);  /* in case the sub barfs ? XXXX            */
 
1313
            free(child);
 
1314
            free(csv);
 
1315
            free(incs);
 
1316
            free(others);
 
1317
    }
 
1318
   }
 
1319
 
 
1320
!NO!SUBS!