# # Create Core.xs # - needed since we allow bad pixel handling to be switched off # use strict; use Config; use File::Basename qw(&basename &dirname); # check for bad value support use vars qw( $bvalflag $usenan $bvalPerPdl ); require "badsupport.p"; # are we big or little endian? require PDL::Core::Dev; my $isbigendian = PDL::Core::Dev::isbigendian(); # This forces PL files to create target in same directory as PL file. # This is so that make depend always knows where to find PL derivatives. chdir(dirname($0)); my $file; ($file = basename($0)) =~ s/\.PL$//; $file =~ s/\.pl$// if ($Config{'osname'} eq 'VMS' or $Config{'osname'} eq 'OS2'); # "case-forgiving" if ( $bvalflag ) { print "Extracting $file (WITH bad value support)\n"; } else { print "Extracting $file (NO bad value support)\n"; } open OUT,">$file" or die "Can't create $file: $!"; chmod 0644, $file; print OUT <<"!WITH!SUBS!"; /* Core.xs - automatically generated by Core.xs.PL - bad value support = $bvalflag */ !WITH!SUBS! print OUT <<'!NO!SUBS!'; #ifndef WIN32 #include #include #include #define USE_MMAP #endif #include "EXTERN.h" /* std perl include */ #include "perl.h" /* std perl include */ #include "XSUB.h" /* XSUB include */ #if defined(CONTEXT) #undef CONTEXT #endif #define PDL_CORE /* For certain ifdefs */ #include "pdl.h" /* Data structure declarations */ #include "pdlcore.h" /* Core declarations */ !NO!SUBS! if ( $bvalflag ) { print OUT "#include \n" unless $usenan; print OUT "#include \n"; } # if: $bvalflag print OUT <<'!NO!SUBS!'; /* Return a integer or numeric scalar as approroate */ #define setflag(reg,flagval,val) (val?(reg |= flagval):(reg &= ~flagval)) #define SET_RETVAL_NV(x) x->datatype ok */ av_store( array, i, newSViv( (IV)dims[i] ) ); return (SV*) array; } /* * Free the data if possible; used by mmapper * Moved from pdlhash.c July 10 2006 DJB */ static void pdl_freedata (pdl *a) { if(a->datasv) { SvREFCNT_dec(a->datasv); a->datasv=0; a->data=0; } else if(a->data) { die("Trying to free data of untouchable (mmapped?) pdl"); } } !NO!SUBS! if ( $bvalflag ) { print OUT <<'!NO!SUBS!'; #ifdef FOOFOO_PROPOGATE_BADFLAG /* * this seems to cause an infinite loop in between tests 42 & 43 of * t/bad.t - ie * * $a = sequence( byte, 2, 3 ); * $b = $a->slice("(1),:"); * my $mask = sequence( byte, 2, 3 ); * $mask = $mask->setbadif( ($mask % 3) == 2 ); * print "a,b == ", $a->badflag, ",", $b->badflag, "\n"; * $a->inplace->copybad( $mask ); <-- think this is the call * print "a,b == ", $a->badflag, ",", $b->badflag, "\n"; * print "$a $b\n"; * ok( $b->badflag, 1 ); * */ /* used by propogate_badflag() */ void propogate_badflag_children( pdl *it, int newval ) { PDL_DECL_CHILDLOOP(it) PDL_START_CHILDLOOP(it) { pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it); int i; for( i = trans->vtable->nparents; i < trans->vtable->npdls; i++ ) { pdl *child = trans->pdls[i]; if ( newval ) child->state |= PDL_BADVAL; else child->state &= ~PDL_BADVAL; /* make sure we propogate to grandchildren, etc */ propogate_badflag_children( child, newval ); } /* for: i */ } PDL_END_CHILDLOOP(it) } /* propogate_badflag_children */ /* used by propogate_badflag() */ void propogate_badflag_parents( pdl *it ) { PDL_DECL_CHILDLOOP(it) PDL_START_CHILDLOOP(it) { pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it); int i; for( i = 0; i < trans->vtable->nparents; i++ ) { pdl *parent = trans->pdls[i]; /* only sets allowed here */ parent->state |= PDL_BADVAL; /* make sure we propogate to grandparents, etc */ propogate_badflag_parents( parent ); } /* for: i */ } PDL_END_CHILDLOOP(it) } /* propogate_badflag_parents */ /* * we want to change the bad flag of the children * (newval = 1 means set flag, 0 means clear it). * If newval == 1, then we also loop through the * parents, setting their bad flag * * thanks to Christian Soeller for this */ void propogate_badflag( pdl *it, int newval ) { /* only do anything if the flag has changed - do we need this check ? */ if ( newval ) { if ( (it->state & PDL_BADVAL) == 0 ) { propogate_badflag_parents( it ); propogate_badflag_children( it, newval ); } } else { if ( (it->state & PDL_BADVAL) > 0 ) { propogate_badflag_children( it, newval ); } } } /* propogate_badflag */ #else /* FOOFOO_PROPOGATE_BADFLAG */ /* newval = 1 means set flag, 0 means clear it */ /* thanks to Christian Soeller for this */ void propogate_badflag( pdl *it, int newval ) { PDL_DECL_CHILDLOOP(it) PDL_START_CHILDLOOP(it) { pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it); int i; for( i = trans->vtable->nparents; i < trans->vtable->npdls; i++ ) { pdl *child = trans->pdls[i]; if ( newval ) child->state |= PDL_BADVAL; else child->state &= ~PDL_BADVAL; /* make sure we propogate to grandchildren, etc */ propogate_badflag( child, newval ); } /* for: i */ } PDL_END_CHILDLOOP(it) } /* propogate_badflag */ #endif /* FOOFOO_PROPOGATE_BADFLAG */ void propogate_badvalue( pdl *it ) { PDL_DECL_CHILDLOOP(it) PDL_START_CHILDLOOP(it) { pdl_trans *trans = PDL_CHILDLOOP_THISCHILD(it); int i; for( i = trans->vtable->nparents; i < trans->vtable->npdls; i++ ) { pdl *child = trans->pdls[i]; child->has_badvalue = 1; child->badvalue = it->badvalue; /* make sure we propogate to grandchildren, etc */ propogate_badvalue( child ); } /* for: i */ } PDL_END_CHILDLOOP(it) } /* propogate_badvalue */ /* this is horrible - the routines from bad should perhaps be here instead ? */ double pdl_get_badvalue( int datatype ) { double retval; switch ( datatype ) { !NO!SUBS! use PDL::Types; my $ntypes = $#PDL::Types::names; my $str; foreach my $i ( 0 .. $ntypes ) { my $type = PDL::Type->new( $i ); my $typesym = $type->symbol; my $cname = $type->ctype; $cname =~ s/^PDL_//; my $storage = "PDL.bvals.$cname"; print OUT "\tcase $typesym: retval = $storage; break;\n"; } print OUT <<'!NO!SUBS!'; default: croak("Unknown type sent to pdl_get_badvalue\n"); } return retval; } /* pdl_get_badvalue() */ double pdl_get_pdl_badvalue( pdl *it ) { double retval; int datatype; !NO!SUBS! if ($bvalPerPdl) { print OUT ' if (it->has_badvalue) { retval = it->badvalue; } else { datatype = it->datatype; retval = pdl_get_badvalue( datatype ); } '; } else { print OUT ' datatype = it->datatype; retval = pdl_get_badvalue( datatype ); '; } print OUT <<'!NO!SUBS!'; return retval; } /* pdl_get_pdl_badvalue() */ !NO!SUBS! } # if: $bvalflag print OUT <<'!NO!SUBS!'; MODULE = PDL::Core PACKAGE = PDL # Destroy a PDL - note if a hash do nothing, the $$x{PDL} component # will be destroyed anyway on a separate call void DESTROY(sv) SV * sv; CODE: pdl *self; if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV) 1; /* Do nothing */ else { self = SvPDLV(sv); PDLDEBUG_f(printf("DESTROYING %d\n",self);) if (self != NULL) pdl_destroy(self); } # Return the transformation object or an undef otherwise. SV * get_trans(self) pdl *self; CODE: ST(0) = sv_newmortal(); if(self->trans) { sv_setref_pv(ST(0), "PDL::Trans", (void*)(self->trans)); } else { ST(0) = &PL_sv_undef; } # This will change in the future, as can be seen from the name ;) # the argument passing is a real quick hack: you can pass 3 integers # and nothing else. MODULE = PDL::Core PACKAGE = PDL::Trans void call_trans_foomethod(trans,i1,i2,i3) pdl_trans *trans int i1 int i2 int i3 CODE: PDL_TR_CHKMAGIC(trans); pdl_trans_changesoon(trans,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED); if(trans->vtable->foomethod == NULL) { croak("This transformation doesn't have a foomethod!"); } (trans->vtable->foomethod)(trans,i1,i2,i3); pdl_trans_changed(trans,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED); MODULE = PDL::Core PACKAGE = PDL int iscontig(x) pdl* x CODE: RETVAL = 1; pdl_make_physvaffine( x ); if PDL_VAFFOK(x) { int i, inc=1; printf("vaff check...\n"); for (i=0;indims;i++) { if (PDL_REPRINC(x,i) != inc) { RETVAL = 0; break; } inc *= x->dims[i]; } } OUTPUT: RETVAL !NO!SUBS! # access (read, if set is true then write as well; if postset true then # read first and write new value after that) # to piddle's state # my %flags = ( hdrcpy => { set => 1 }, fflows => { FLAG => "DATAFLOW_F" }, bflows => { FLAG => "DATAFLOW_B" }, is_inplace => { FLAG => "INPLACE", postset => 1 }, donttouch => { FLAG => "DONTTOUCHDATA" }, allocated => { }, vaffine => { FLAG => "OPT_VAFFTRANSOK" }, anychgd => { FLAG => "ANYCHANGED" }, dimschgd => { FLAG => "PARENTDIMSCHANGED" }, tracedebug => { FLAG => "TRACEDEBUG", set => 1}, ); #if ( $bvalflag ) { $flags{baddata} = { set => 1, FLAG => "BADVAL" }; } foreach my $name ( keys %flags ) { my $flag = "PDL_" . ($flags{$name}{FLAG} || uc($name)); if ( $flags{$name}{set} ) { print OUT <<"!WITH!SUBS!"; int $name(x,mode=0) pdl *x int mode CODE: if (items>1) { setflag(x->state,$flag,mode); } RETVAL = ((x->state & $flag) > 0); OUTPUT: RETVAL !WITH!SUBS! } elsif ($flags{$name}{postset}) { print OUT <<"!WITH!SUBS!"; int $name(x,mode=0) pdl *x int mode CODE: RETVAL = ((x->state & $flag) > 0); if (items>1) { setflag(x->state,$flag,mode); } OUTPUT: RETVAL !WITH!SUBS! } else { print OUT <<"!WITH!SUBS!"; int $name(self) pdl *self CODE: RETVAL = ((self->state & $flag) > 0); OUTPUT: RETVAL !WITH!SUBS! } } # foreach: keys %flags =begin windows_mmap I found this at http://mollyrocket.com/forums/viewtopic.php?p=2529&sid=973b8e0a1e639e3008d7ef05f686c6fa and thougt we might consider using it to make windows mmapping possible. -David Mertens /* This code was placed in the public domain by the author, Sean Barrett, in November 2007. Do with it as you will. (Seee the page for stb_vorbis or the mollyrocket source page for a longer description of the public domain non-license). */ #define WIN32_LEAN_AND_MEAN #include typedef struct { HANDLE f; HANDLE m; void *p; } SIMPLE_UNMMAP; // map 'filename' and return a pointer to it. fill out *length and *un if not-NULL void *simple_mmap(const char *filename, int *length, SIMPLE_UNMMAP *un) { HANDLE f = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE m; void *p; if (!f) return NULL; m = CreateFileMapping(f, NULL, PAGE_READONLY, 0,0, NULL); if (!m) { CloseHandle(f); return NULL; } p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0); if (!p) { CloseHandle(m); CloseHandle(f); return NULL; } if (n) *n = GetFileSize(f, NULL); if (un) { un->f = f; un->m = m; un->p = p; } return p; } void simple_unmmap(SIMPLE_UNMMAP *un) { UnmapViewOfFile(un->p); CloseHandle(un->m); CloseHandle(un->f); } =end windows_mmap =cut print OUT <<'!NO!SUBS!'; void set_inplace(self,val) pdl *self; int val; CODE: setflag(self->state,PDL_INPLACE,val); int address(self) pdl *self; CODE: RETVAL = (int) self; OUTPUT: RETVAL pdl * pdl_hard_copy(src) pdl *src; pdl * sever(src) pdl *src; CODE: if(src->trans) { pdl_make_physvaffine(src); pdl_destroytransform(src->trans,1); } RETVAL=src; OUTPUT: RETVAL int set_data_by_mmap(it,fname,len,writable,shared,creat,mode,trunc) pdl *it char *fname int len int writable int shared int creat int mode int trunc CODE: #ifdef USE_MMAP int fd; pdl_freedata(it); fd = open(fname,(writable && shared ? O_RDWR : O_RDONLY)| (creat ? O_CREAT : 0),mode); if(fd < 0) { croak("Error opening file"); } if(trunc) { ftruncate(fd,0); /* Clear all previous data */ ftruncate(fd,len); /* And make it long enough */ } if(len) { it->data = mmap(0,len,PROT_READ | (writable ? PROT_WRITE : 0), (shared ? MAP_SHARED : MAP_PRIVATE), fd,0); if(!it->data) croak("Error mmapping!"); } else { /* Special case: zero-length file */ it->data = NULL; } PDLDEBUG_f(printf("PDL::MMap: mapped to %d\n",it->data);) it->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED; pdl_add_deletedata_magic(it, pdl_delete_mmapped_data, len); close(fd); #else croak("mmap not supported on this architecture"); #endif RETVAL = 1; OUTPUT: RETVAL int set_data_by_offset(it,orig,offset) pdl *it pdl *orig int offset CODE: pdl_freedata(it); it->data = ((char *) orig->data) + offset; it->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED; RETVAL = 1; OUTPUT: RETVAL int nelem(x) pdl *x CODE: pdl_make_physdims(x); RETVAL = x->nvals; OUTPUT: RETVAL # Convert PDL to new datatype (called by float(), int() etc.) # SV * # convert(a,datatype) # pdl* a # int datatype # CODE: # pdl* b; # pdl_make_physical(a); # RETVAL = pdl_copy(a,""); /* Init value to return */ # b = SvPDLV(RETVAL); /* Map */ # pdl_converttype( &b, datatype, PDL_PERM ); # PDLDEBUG_f(printf("converted %d, %d, %d, %d\n",a, b, a->datatype, b->datatype)); # OUTPUT: # RETVAL # Call my howbig function int howbig_c(datatype) int datatype CODE: RETVAL = pdl_howbig(datatype); OUTPUT: RETVAL MODULE = PDL::Core PACKAGE = PDL::Core unsigned int is_scalar_SvPOK(arg) SV* arg; CODE: RETVAL = SvPOK(arg); OUTPUT: RETVAL int set_debugging(i) int i; CODE: RETVAL = pdl_debugging; pdl_debugging = i; OUTPUT: RETVAL SV * sclr_c(it) pdl* it CODE: PDL_Long nullp = 0; PDL_Long dummyd = 1; PDL_Long dummyi = 1; double result; /* get the first element of a piddle and return as * Perl double scalar (NV) */ pdl_make_physvaffine( it ); if (it->nvals < 1) croak("piddle must have at least one element"); /* offs = PDL_REPROFFS(it); */ /* result = pdl_get_offs(PDL_REPRP(it),offs); */ result=pdl_at(PDL_REPRP(it), it->datatype, &nullp, &dummyd, &dummyi, PDL_REPROFFS(it),1); SET_RETVAL_NV(it) ; OUTPUT: RETVAL SV * at_c(x,position) pdl* x PDL_Long * pos = NO_INIT CODE: int npos, ipos; double result; pdl_make_physvaffine( x ); pos = pdl_packdims( ST(1), &npos); if (pos == NULL || npos < x->ndims) croak("Invalid position"); /* allow additional trailing indices * which must be all zero, i.e. a * [3,1,5] piddle is treated as an [3,1,5,1,1,1,....] * infinite dim piddle */ for (ipos=x->ndims; iposdatatype, pos, x->dims, (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs), PDL_REPROFFS(x), x->ndims); SET_RETVAL_NV(x) ; OUTPUT: RETVAL SV * at_bad_c(x,position) pdl* x PDL_Long * pos = NO_INIT CODE: int npos, ipos, badflag; double result; pdl_make_physvaffine( x ); pos = pdl_packdims( ST(1), &npos); if (pos == NULL || npos < x->ndims) croak("Invalid position"); /* allow additional trailing indices * which must be all zero, i.e. a * [3,1,5] piddle is treated as an [3,1,5,1,1,1,....] * infinite dim piddle */ for (ipos=x->ndims; iposdatatype, pos, x->dims, (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs), PDL_REPROFFS(x), x->ndims); !NO!SUBS! if ( $bvalflag ) { print OUT ' badflag = (x->state & PDL_BADVAL) > 0; '; # do we have to bother about NaN's? if ( $usenan ) { print OUT ' if ( badflag && ( ( x->datatype < 4 && ( result == pdl_get_badvalue( x->datatype ) ) ) || ( x->datatype >= 4 && ( finite(result) == 0 ) ) ) ) { RETVAL = newSVpvn( "BAD", 3 ); } else '; } else { print OUT ' if ( badflag && ( pdl_get_badvalue( x->datatype ) == result ) ) { RETVAL = newSVpvn( "BAD", 3 ); } else '; } # if: $usenan } # if: $bvalflag print OUT <<'!NO!SUBS!'; SET_RETVAL_NV(x) ; OUTPUT: RETVAL void list_c(x) pdl *x PPCODE: PDL_Long *inds,*incs,offs; void *data; int ind; int stop = 0; pdl_make_physvaffine( x ); inds = pdl_malloc(sizeof(PDL_Long) * x->ndims); /* GCC -> on stack :( */ data = PDL_REPRP(x); incs = (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs); offs = PDL_REPROFFS(x); EXTEND(sp,x->nvals); for(ind=0; ind < x->ndims; ind++) inds[ind] = 0; while(!stop) { PUSHs(sv_2mortal(newSVnv(pdl_at( data, x->datatype, inds, x->dims, incs, offs, x->ndims)))); stop = 1; for(ind = 0; ind < x->ndims; ind++) if(++(inds[ind]) >= x->dims[ind]) inds[ind] = 0; else {stop = 0; break;} } # returns the string 'BAD' if an element is bad # SV * listref_c(x) pdl *x CODE: PDL_Long *inds,*incs,offs; void *data; int ind, lind; int stop = 0; AV *av; !NO!SUBS! if ( $bvalflag ) { # note: # the badvalue is stored in a double, but that's what pdl_at() # returns print OUT ' SV *sv; double pdl_val, pdl_badval; int badflag = (x->state & PDL_BADVAL) > 0; '; # do we have to bother about NaN's? if ( $usenan ) { print OUT ' if ( badflag && x->datatype < 4 ) { pdl_badval = pdl_get_pdl_badvalue( x ); } '; } else { print OUT ' if ( badflag ) { pdl_badval = pdl_get_pdl_badvalue( x ); } '; } # if: $usenan } # if: $bvalflag print OUT <<'!NO!SUBS!'; pdl_make_physvaffine( x ); inds = pdl_malloc(sizeof(PDL_Long) * x->ndims); /* GCC -> on stack :( */ data = PDL_REPRP(x); incs = (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs); offs = PDL_REPROFFS(x); av = newAV(); av_extend(av,x->nvals); lind=0; for(ind=0; ind < x->ndims; ind++) inds[ind] = 0; while(!stop) { !NO!SUBS! if ( $bvalflag ) { my $condition; if ( $usenan ) { $condition = '( (x->datatype < 4 && pdl_val == pdl_badval) || (x->datatype >= 4 && finite(pdl_val) == 0) )'; } else { $condition = 'pdl_val == pdl_badval'; } print OUT <<"!WITH!SUBS!"; pdl_val = pdl_at( data, x->datatype, inds, x->dims, incs, offs, x->ndims ); if ( badflag && $condition ) { sv = newSVpvn( "BAD", 3 ); } else { sv = newSVnv( pdl_val ); } av_store( av, lind, sv ); !WITH!SUBS! } else { print OUT <<'!NO!SUBS!'; av_store(av,lind, newSVnv( pdl_at( data, x->datatype, inds, x->dims, incs, offs, x->ndims ) ) ); !NO!SUBS! } # bvalflag print OUT <<'!NO!SUBS!'; lind++; stop = 1; for(ind = 0; ind < x->ndims; ind++) { if(++(inds[ind]) >= x->dims[ind]) { inds[ind] = 0; } else { stop = 0; break; } } } RETVAL = newRV_noinc((SV *)av); OUTPUT: RETVAL void set_c(x,position,value) pdl* x PDL_Long * pos = NO_INIT double value CODE: int npos,ipos; pdl_make_physvaffine( x ); pos = pdl_packdims( ST(1), &npos); if (pos == NULL || npos < x->ndims) croak("Invalid position"); /* allow additional trailing indices * which must be all zero, i.e. a * [3,1,5] piddle is treated as an [3,1,5,1,1,1,....] * infinite dim piddle */ for (ipos=x->ndims; iposdatatype, pos, x->dims, (PDL_VAFFOK(x) ? x->vafftrans->incs : x->dimincs), PDL_REPROFFS(x), x->ndims,value); if (PDL_VAFFOK(x)) pdl_vaffinechanged(x, PDL_PARENTDATACHANGED); else pdl_changed( x , PDL_PARENTDATACHANGED , 0 ); BOOT: /* Initialize structure of pointers to core C routines */ PDL.Version = PDL_CORE_VERSION; PDL.SvPDLV = SvPDLV; PDL.SetSV_PDL = SetSV_PDL; PDL.create = pdl_create; PDL.pdlnew = pdl_external_new; PDL.tmp = pdl_external_tmp; PDL.destroy = pdl_destroy; PDL.null = pdl_null; PDL.copy = pdl_copy; PDL.hard_copy = pdl_hard_copy; PDL.converttype = pdl_converttype; PDL.twod = pdl_twod; PDL.smalloc = pdl_malloc; PDL.howbig = pdl_howbig; PDL.packdims = pdl_packdims; PDL.unpackdims = pdl_unpackdims; PDL.setdims = pdl_setdims; PDL.grow = pdl_grow; PDL.flushcache = NULL; PDL.reallocdims = pdl_reallocdims; PDL.reallocthreadids = pdl_reallocthreadids; PDL.resize_defaultincs = pdl_resize_defaultincs; PDL.get_threadoffsp = pdl_get_threadoffsp; PDL.thread_copy = pdl_thread_copy; PDL.clearthreadstruct = pdl_clearthreadstruct; PDL.initthreadstruct = pdl_initthreadstruct; PDL.startthreadloop = pdl_startthreadloop; PDL.iterthreadloop = pdl_iterthreadloop; PDL.freethreadloop = pdl_freethreadloop; PDL.thread_create_parameter = pdl_thread_create_parameter; PDL.add_deletedata_magic = pdl_add_deletedata_magic; PDL.setdims_careful = pdl_setdims_careful; PDL.put_offs = pdl_put_offs; PDL.get_offs = pdl_get_offs; PDL.get = pdl_get; PDL.set_trans_childtrans = pdl_set_trans_childtrans; PDL.set_trans_parenttrans = pdl_set_trans_parenttrans; PDL.make_now = pdl_make_now; PDL.get_convertedpdl = pdl_get_convertedpdl; PDL.make_trans_mutual = pdl_make_trans_mutual; PDL.trans_mallocfreeproc = pdl_trans_mallocfreeproc; PDL.make_physical = pdl_make_physical; PDL.make_physdims = pdl_make_physdims; PDL.make_physvaffine = pdl_make_physvaffine; PDL.pdl_barf = pdl_barf; PDL.allocdata = pdl_allocdata; PDL.safe_indterm = pdl_safe_indterm; PDL.children_changesoon = pdl_children_changesoon; PDL.changed = pdl_changed; PDL.vaffinechanged = pdl_vaffinechanged; PDL.NaN_float = union_nan_float.f; PDL.NaN_double = union_nan_double.d; !NO!SUBS! if ( $bvalflag ) { print OUT <<'!NO!SUBS!'; PDL.propogate_badflag = propogate_badflag; PDL.propogate_badvalue = propogate_badvalue; PDL.get_pdl_badvalue = pdl_get_pdl_badvalue; !NO!SUBS! for my $type (PDL::Types::types) { my $typename = $type->ctype; $typename =~ s/^PDL_//; my $bval = $type->defbval; my $ctype = $type->ctype; if ($usenan && $type->usenan) { # note: no defaults if usenan print OUT "\tPDL.bvals.$typename = PDL.NaN_$type;\n"; #Core NaN value } else { print OUT "\tPDL.bvals.$typename = PDL.bvals.default_$typename = $bval;\n"; } } # PDL.bvals.Byte = PDL.bvals.default_Byte = UCHAR_MAX; # PDL.bvals.Short = PDL.bvals.default_Short = SHRT_MIN; # PDL.bvals.Ushort = PDL.bvals.default_Ushort = USHRT_MAX; # PDL.bvals.Long = PDL.bvals.default_Long = INT_MIN; } # if: $bvalflag print OUT <<'!NO!SUBS!'; /* "Publish" pointer to this structure in perl variable for use by other modules */ sv_setiv(get_sv("PDL::SHARE",TRUE|GV_ADDMULTI), PTR2IV(&PDL)); # version of eval() which propogates errors encountered in # any internal eval(). Must be passed a code reference - could # be use perl_eval_sv() but that is still buggy. This subroutine is # primarily for the perlDL shell to use. # # Thanks to Sarathy (gsar@engin.umich.edu) for suggesting this, though # it needs to be wrapped up in the stack stuff to avoid certain SEGVs! void myeval(code) SV * code; PROTOTYPE: $ CODE: PUSHMARK(sp) ; perl_call_sv(code, G_EVAL|G_KEEPERR|GIMME_V); # make piddle belonging to 'class' and of type 'type' # from avref 'array_ref' which is checked for being # rectangular first SV* pdl_avref(array_ref, class, type) SV* array_ref char* class int type CODE: /* make a piddle from a Perl array ref */ AV *dims, *av; int i, depth; int datalevel = -1; SV* psv; pdl* p; if (!SvROK(array_ref)) croak("pdl_avref: not a reference"); if (SvTYPE(SvRV(array_ref)) != SVt_PVAV) croak("pdl_avref: not an array reference"); av = (AV *) SvRV(array_ref); dims = (AV *) sv_2mortal( (SV *) newAV()); av_store(dims,0,newSViv((IV) av_len(av)+1)); /* even if we contain nothing depth is one */ depth = 1 + av_ndcheck(av,dims,0,&datalevel); /* printf("will make type %s\n",class); */ /* at this stage start making a piddle and populate it with values from the array (which has already been checked in av_check) */ if (strcmp(class,"PDL") == 0) { p = pdl_from_array(av,dims,type,NULL); /* populate with data */ ST(0) = sv_newmortal(); SetSV_PDL(ST(0),p); } else { /* call class->initialize method */ PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(class, 0))); PUTBACK; perl_call_method("initialize", G_SCALAR); SPAGAIN; psv = POPs; PUTBACK; p = SvPDLV(psv); /* and get piddle from returned object */ ST(0) = psv; pdl_from_array(av,dims,type,p); /* populate ;) */ } MODULE = PDL::Core PACKAGE = PDL # pdl_null is created/imported with no PREFIX as pdl_null. # 'null' is supplied in Core.pm that calls 'initialize' which calls # the pdl_null here pdl * pdl_null(...) MODULE = PDL::Core PACKAGE = PDL::Core PREFIX = pdl_ int pdl_pthreads_enabled() MODULE = PDL::Core PACKAGE = PDL PREFIX = pdl_ int isnull(self) pdl *self; CODE: RETVAL= !!(self->state & PDL_NOMYDIMS); OUTPUT: RETVAL pdl * make_physical(self) pdl *self; CODE: pdl_make_physical(self); RETVAL = self; OUTPUT: RETVAL pdl * make_physvaffine(self) pdl *self; CODE: pdl_make_physvaffine(self); RETVAL = self; OUTPUT: RETVAL pdl * make_physdims(self) pdl *self; CODE: pdl_make_physdims(self); RETVAL = self; OUTPUT: RETVAL void pdl_dump(x) pdl *x; void pdl_add_threading_magic(it,nthdim,nthreads) pdl *it int nthdim int nthreads void pdl_remove_threading_magic(it) pdl *it CODE: pdl_add_threading_magic(it,-1,-1); MODULE = PDL::Core PACKAGE = PDL SV * initialize(class) SV *class PPCODE: HV *bless_stash; if (SvROK(class)) { /* a reference to a class */ bless_stash = SvSTASH(SvRV(class)); } else { /* a class name */ bless_stash = gv_stashsv(class, 0); } ST(0) = sv_newmortal(); SetSV_PDL(ST(0),pdl_null()); /* set a null PDL to this SV * */ ST(0) = sv_bless(ST(0), bless_stash); /* bless appropriately */ XSRETURN(1); SV * get_dataref(self) pdl *self CODE: if(self->state & PDL_DONTTOUCHDATA) { croak("Trying to get dataref to magical (mmaped?) pdl"); } pdl_make_physical(self); /* XXX IS THIS MEMLEAK WITHOUT MORTAL? */ RETVAL = (newRV(self->datasv)); OUTPUT: RETVAL int get_datatype(self) pdl *self CODE: RETVAL = self->datatype; OUTPUT: RETVAL int upd_data(self) pdl *self CODE: STRLEN n_a; if(self->state & PDL_DONTTOUCHDATA) { croak("Trying to touch dataref of magical (mmaped?) pdl"); } self->data = SvPV((SV*)self->datasv,n_a); XSRETURN(0); void set_dataflow_f(self,value) pdl *self; int value; CODE: if(value) self->state |= PDL_DATAFLOW_F; else self->state &= ~PDL_DATAFLOW_F; void set_dataflow_b(self,value) pdl *self; int value; CODE: if(value) self->state |= PDL_DATAFLOW_B; else self->state &= ~PDL_DATAFLOW_B; int getndims(x) pdl *x ALIAS: PDL::ndims = 1 CODE: pdl_make_physdims(x); RETVAL = x->ndims; OUTPUT: RETVAL int getdim(x,y) pdl *x int y ALIAS: PDL::dim = 1 CODE: pdl_make_physdims(x); if (y < 0) y = x->ndims + y; if (y < 0) croak("negative dim index too large"); if (y < x->ndims) RETVAL = x->dims[y]; else RETVAL = 1; /* return size 1 for all other dims */ OUTPUT: RETVAL int getnthreadids(x) pdl *x CODE: pdl_make_physdims(x); RETVAL = x->nthreadids; OUTPUT: RETVAL int getthreadid(x,y) pdl *x int y CODE: RETVAL = x->threadids[y]; OUTPUT: RETVAL void setdims(x,dims) pdl *x PDL_Long *dims = NO_INIT CODE: { int ndims; int i; pdl_children_changesoon(x,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED); dims = pdl_packdims(ST(1),&ndims); pdl_reallocdims(x,ndims); for(i=0; idims[i] = dims[i]; pdl_resize_defaultincs(x); x->threadids[0] = ndims; /* make null != dims = [0] */ #ifndef ELIFJELFIJSEJIF x->state &= ~PDL_NOMYDIMS; #else if(ndims == 1 && dims[0] == 0) { x->state |= PDL_NOMYDIMS; } else { x->state &= ~PDL_NOMYDIMS; } #endif pdl_changed(x,PDL_PARENTDIMSCHANGED|PDL_PARENTDATACHANGED,0); } void dowhenidle() CODE: pdl_run_delayed_magic(); XSRETURN(0); void bind(p,c) pdl *p SV *c PROTOTYPE: $& CODE: pdl_add_svmagic(p,c); XSRETURN(0); void sethdr(p,h) pdl *p SV *h CODE: HV* hash; if(p->hdrsv == NULL) { p->hdrsv = &PL_sv_undef; /*(void*) newSViv(0);*/ } /* Throw an error if we're not either undef or hash */ if ( (h != &PL_sv_undef && h != NULL) && ( !SvROK(h) || SvTYPE(SvRV(h)) != SVt_PVHV ) ) croak("Not a HASH reference"); /* Clear the old header */ SvREFCNT_dec(p->hdrsv); /* Put the new header (or undef) in place */ if(h == &PL_sv_undef || h == NULL) p->hdrsv = NULL; else p->hdrsv = (void*) newRV( (SV*) SvRV(h) ); SV * hdr(p) pdl *p CODE: pdl_make_physdims(p); /* Make sure that in the undef case we return not */ /* undef but an empty hash ref. */ if((p->hdrsv==NULL) || (p->hdrsv == &PL_sv_undef)) { p->hdrsv = (void*) newRV_noinc( (SV*)newHV() ); } RETVAL = newRV( (SV*) SvRV((SV*)p->hdrsv) ); OUTPUT: RETVAL # fhdr(p) is implemented in perl; see Core.pm.PL if you're looking for it # --CED 9-Feb-2003 # SV * gethdr(p) pdl *p CODE: pdl_make_physdims(p); if((p->hdrsv==NULL) || (p->hdrsv == &PL_sv_undef)) { RETVAL = &PL_sv_undef; } else { RETVAL = newRV( (SV*) SvRV((SV*)p->hdrsv) ); } OUTPUT: RETVAL void set_datatype(a,datatype) pdl *a int datatype CODE: pdl_make_physical(a); if(a->trans) pdl_destroytransform(a->trans,1); /* if(! (a->state && PDL_NOMYDIMS)) { */ pdl_converttype( &a, datatype, PDL_PERM ); /* } */ void threadover_n(...) CODE: { int npdls = items - 1; if(npdls <= 0) croak("Usage: threadover_n(pdl[,pdl...],sub)"); { int i,sd; pdl **pdls = malloc(sizeof(pdl *) * npdls); int *realdims = malloc(sizeof(int) * npdls); pdl_thread pdl_thr; SV *code = ST(items-1); for(i=0; i 0) nothers = SvIV(ST(0)); if(targs <= 0 || nothers < 0 || nothers >= targs) croak("Usage: threadover(nothers,pdl[,pdl...][,otherpars..],realdims,creating,sub)"); npdls = targs-nothers; { int i,j,nd1,nd2,dtype=0,nc=npdls; SV* rdimslist = ST(items-3); SV* cdimslist = ST(items-2); SV *code = ST(items-1); pdl_thread pdl_thr; pdl **pdls = malloc(sizeof(pdl *) * npdls); pdl **child = malloc(sizeof(pdl *) * npdls); SV **csv = malloc(sizeof(SV *) * npdls); SV **dims = malloc(sizeof(SV *) * npdls); SV **incs = malloc(sizeof(SV *) * npdls); SV **others = malloc(sizeof(SV *) * nothers); int *creating = pdl_packint(cdimslist,&nd2); int *realdims = pdl_packint(rdimslist,&nd1); CHECKP(pdls); CHECKP(child); CHECKP(dims); CHECKP(incs); CHECKP(csv); if (nd1 != npdls || nd2 < npdls) croak("threadover: need one realdim and creating flag " "per pdl!"); for(i=0; idatatype); } } for (i=npdls+1; i<=targs; i++) others[i-npdls-1] = ST(i); if (nd2 < nc) croak("Not enough dimension info to create pdls"); #ifdef DEBUG_PTHREAD for (i=0;idims[j]); printf("] Incs: ["); for (j=0;jdatatype = dtype; pdl_thread_create_parameter(&pdl_thr,i,cp,0); nc += realdims[i]; pdl_make_physical(pdls[i]); PDLDEBUG_f(pdl_dump(pdls[i])); /* And make it nonnull, now that we've created it */ pdls[i]->state &= (~PDL_NOMYDIMS); } pdl_startthreadloop(&pdl_thr,NULL,NULL); for(i=0; idims,realdims[i])); incs[i] = newRV(pdl_unpackint(PDL_VAFFOK(pdls[i]) ? pdls[i]->vafftrans->incs: pdls[i]->dimincs,realdims[i])); /* need to make sure we get the vaffine (grand)parent */ if (PDL_VAFFOK(pdls[i])) pdls[i] = pdls[i]->vafftrans->from; child[i]=pdl_null(); /* instead of pdls[i] its vaffine parent !!!XXX */ PDL.affine_new(pdls[i],child[i],pdl_thr.offs[i],dims[i], incs[i]); pdl_make_physical(child[i]); /* make sure we can get at the vafftrans */ csv[i] = sv_newmortal(); SetSV_PDL(csv[i], child[i]); /* pdl* into SV* */ } do { /* the actual threadloop */ pdl_trans_affine *traff; dSP; PUSHMARK(sp); EXTEND(sp,npdls); for(i=0; itrans; traff->offs = pdl_thr.offs[i]; child[i]->vafftrans->offs = pdl_thr.offs[i]; child[i]->state |= PDL_PARENTDATACHANGED; PUSHs(csv[i]); } for (i=0; i