File Coverage

lib/PDL/Core.xs
Criterion Covered Total %
statement 610 655 93.1
branch 613 1194 51.3
condition n/a
subroutine n/a
pod n/a
total 1223 1849 66.1


line stmt bran cond sub pod time code
1             #ifndef WIN32
2             #include
3             #include
4             #endif
5              
6             #include "EXTERN.h" /* std perl include */
7             #include "perl.h" /* std perl include */
8             #include "XSUB.h" /* XSUB include */
9              
10             #if defined(CONTEXT)
11             #undef CONTEXT
12             #endif
13              
14             #include "pdl.h" /* Data structure declarations */
15             #define PDL_IN_CORE /* access funcs directly not through PDL-> */
16             #include "pdlcore.h" /* Core declarations */
17             #include "pdlperl.h"
18              
19             #define TRANS_PDLS(from, to) \
20             pdl_transvtable *vtable = trans->vtable; \
21             if (!vtable) croak("This transformation doesn't have a vtable!"); \
22             PDL_Indx i; \
23             EXTEND(SP, to - from); \
24             for (i=from; i
25             SV *sv = sv_newmortal(); \
26             if (!trans->pdls[i]->sv) trans->pdls[i]->state |= PDL_DYNLANG_NODESTROY; \
27             pdl_SetSV_PDL(sv, trans->pdls[i]); \
28             PUSHs(sv); \
29             }
30              
31             #define PDL_FLAG_COMMA(f) f,
32             #define PDL_FLAG_STRCOMMA(f) #f,
33             #define PDL_FLAG_DUMP(macro, flagvar) \
34             int flagval[] = { \
35             macro(PDL_FLAG_COMMA) \
36             0 \
37             }; \
38             char *flagchar[] = { \
39             macro(PDL_FLAG_STRCOMMA) \
40             NULL \
41             }; \
42             int i, f = flagvar; \
43             for (i=0; flagval[i]!=0; i++) \
44             if (f & flagval[i]) \
45             XPUSHs(sv_2mortal(newSVpv(flagchar[i], 0)));
46              
47             #define setflag(reg,flagval,val) (val?(reg |= flagval):(reg &= ~flagval))
48              
49             Core PDL; /* Struct holding pointers to shared C routines */
50             static char *type_names[PDL_NTYPES+1] = {
51             #define X(symbol, ctype, ppsym, shortctype, defbval, realctype, convertfunc, ...) \
52             #convertfunc,
53             PDL_TYPELIST_ALL(X)
54             #undef X
55             NULL
56             };
57              
58             int pdl_debugging=0;
59             int pdl_autopthread_targ = 0; /* No auto-pthreading unless set using the set_autopthread_targ */
60             int pdl_autopthread_actual = 0;
61             PDL_Indx pdl_autopthread_dim = -1;
62             int pdl_autopthread_size = 1;
63              
64 1764           char *_dims_from_args(AV *av, SV **svs, IV n) {
65             IV i;
66 4697 100         for (i = 0; i < n; i++) {
67 2934           SV *sv = svs[i];
68 2934 100         if (!SvROK(sv)) {
69 2914 100         if (SvTRUE(sv) && SvIV(sv) < 0) return "Dimensions must be non-negative";
    100          
70 2913 100         if (SvTRUE(sv))
71 2547           SvREFCNT_inc(sv); /* stack entries are mortal */
72             else
73 366           sv = newSViv(0);
74 2913           av_push(av, sv);
75 2913           continue;
76             }
77 20 50         if (SvROK(sv) && !sv_derived_from(sv, "PDL")) return "Trying to use non-ndarray as dimensions?";
    50          
78 20           pdl *p = pdl_SvPDLV(sv);
79 20 50         if (!p) return "Failed to get PDL from arg";
80 20 50         if (p->ndims > 1) return "Trying to use multi-dim ndarray as dimensions?";
81 20           PDL_Indx nvals = p->nvals, v;
82 20 50         if (nvals > 10) warn("creating > 10 dim ndarray (ndarray arg)!");
83 40 100         for (v = 0; v < nvals; v++) {
84 20           PDL_Anyval anyval = { PDL_INVALID, {0} };
85 20 0         ANYVAL_FROM_CTYPE_OFFSET(anyval, p->datatype, PDL_REPRP(p), PDL_REPROFFS(p)+v);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
86 20 50         if (anyval.type < 0) return "Error getting value from ndarray";
87 20           SV *dv = newSV(0);
88 20 0         ANYVAL_TO_SV(dv, anyval);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
89 20 50         if (SvIV(dv) < 0) return "Dimensions must be non-negative";
90 20           av_push(av, dv);
91             }
92             }
93 1763           return NULL;
94             }
95              
96 510           static inline SV *pdl2avref(pdl *x, char flatten) {
97 510           int stop = 0, badflag = (x->state & PDL_BADVAL) > 0;
98 510           volatile PDL_Anyval pdl_val = { PDL_INVALID, {0} }; /* same reason as below */
99 510           volatile PDL_Anyval pdl_badval = { PDL_INVALID, {0} };
100 510 100         if (badflag) {
101 128 100         if (!(x->has_badvalue && x->badvalue.type != x->datatype)) {
    50          
102 128 100         if (x->has_badvalue)
103 19           pdl_badval = x->badvalue;
104             else {
105             #define X(datatype, ctype, ppsym, ...) \
106             pdl_badval.type = datatype; pdl_badval.value.ppsym = PDL.bvals.ppsym;
107 109           PDL_GENERICSWITCH(PDL_TYPELIST_ALL, x->datatype, X, )
108             #undef X
109             }
110             }
111 128 50         if (pdl_badval.type < 0) barf("Error getting badvalue, type=%d", pdl_badval.type);
112             }
113 510           pdl_barf_if_error(pdl_make_physvaffine( x ));
114 510 100         if (!x->nvals) return newRV_noinc((SV *)newAV());
115 509 100         void *data = PDL_REPRP(x);
116 509 100         PDL_Indx ind, inds[!x->ndims ? 1 : x->ndims];
117 509 100         AV *avs[(flatten || !x->ndims) ? 1 : x->ndims];
    100          
118 509 100         if (flatten || !x->ndims) {
    100          
119 461           inds[0] = 0;
120 461           avs[0] = newAV();
121 461 100         av_extend(avs[0], flatten ? x->nvals : 1);
122 588 100         if (flatten) for (ind=1; ind < x->ndims; ind++) inds[ind] = 0;
    100          
123             } else
124 112 100         for (ind=x->ndims-1; ind >= 0; ind--) {
125 64           inds[ind] = 0;
126 64           avs[ind] = newAV();
127 64           av_extend(avs[ind], x->dims[ind]);
128 64 100         if (ind < x->ndims-1) av_store(avs[ind+1], 0, newRV_noinc((SV *)avs[ind]));
129             }
130 509 100         PDL_Indx *incs = PDL_REPRINCS(x), offs = PDL_REPROFFS(x), lind = 0;
    100          
131 5114 50         while (!stop) {
132 5114           pdl_val.type = PDL_INVALID;
133 5114           PDL_Indx ioff = pdl_get_offset(inds, x->dims, incs, offs, x->ndims);
134 5114 50         if (ioff >= 0)
135 5114           ANYVAL_FROM_CTYPE_OFFSET(pdl_val, x->datatype, data, ioff);
136 5114 50         if (pdl_val.type < 0) croak("Position out of range");
137             SV *sv;
138 5114 100         if (badflag) {
139             /* volatile because gcc optimiser otherwise won't recalc for complex double when long-double code added */
140 479           volatile int isbad = ANYVAL_ISBAD(pdl_val, pdl_badval);
141 479 50         if (isbad == -1) croak("ANYVAL_ISBAD error on types %d, %d", pdl_val.type, pdl_badval.type);
142 479 100         if (isbad)
143 168           sv = newSVpvn( "BAD", 3 );
144             else {
145 311           sv = newSV(0);
146 311 50         ANYVAL_TO_SV(sv, pdl_val);
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
147             }
148             } else {
149 4635           sv = newSV(0);
150 4635 0         ANYVAL_TO_SV(sv, pdl_val);
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
151             }
152 5114 100         av_store( avs[0], flatten ? lind++ : inds[0], sv );
153 5114           stop = 1;
154 5114           char didwrap[x->ndims];
155 14223 100         for (ind = 0; ind < x->ndims; ind++) didwrap[ind] = 0;
156 6308 100         for (ind = 0; ind < x->ndims; ind++) {
157 5799 100         if (++(inds[ind]) < x->dims[ind]) {
158 4605           stop = 0; break;
159             }
160 1194           inds[ind] = 0;
161 1194           didwrap[ind] = 1;
162             }
163 5114 100         if (stop) break;
164 4605 100         if (flatten) continue;
165 706 100         for (ind=x->ndims-2; ind >= 0; ind--) { /* never redo outer so -2 */
166 395 100         if (!didwrap[ind]) continue;
167 91           avs[ind] = newAV();
168 91           av_extend(avs[ind], x->dims[ind]);
169 91           av_store(avs[ind+1], inds[ind+1], newRV_noinc((SV *)avs[ind]));
170             }
171             }
172 509 100         return newRV_noinc((SV *)avs[(flatten || !x->ndims) ? 0 : x->ndims-1]);
    100          
173             }
174              
175             MODULE = PDL::Core PACKAGE = PDL
176              
177             # Destroy a PDL - note if a hash do nothing, the $$x{PDL} component
178             # will be destroyed anyway on a separate call
179              
180             void
181             DESTROY(sv)
182             SV * sv;
183             PREINIT:
184             pdl *self;
185             CODE:
186 75092 50         if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV) return;
    100          
187 75037           self = pdl_SvPDLV(sv);
188 75037 50         PDLDEBUG_f(printf("DESTROYING %p\n",self));
189 75037 50         if (self == NULL) return;
190 75037 100         if (self->state & PDL_DYNLANG_NODESTROY) {
191 2 50         PDLDEBUG_f(printf(" (actually just setting sv to NULL)\n"));
192 2           self->state &= ~PDL_DYNLANG_NODESTROY;
193 2           self->sv = NULL;
194 2           return;
195             }
196 75035           pdl_barf_if_error(pdl_destroy(self));
197              
198             SV *
199             new_from_specification(invoc, ...)
200             SV *invoc;
201             ALIAS:
202             PDL::zeroes = 1
203             CODE:
204 1856 100         char ispdl = ix && SvROK(invoc) && sv_derived_from(invoc, "PDL");
    100          
    50          
205 1856           pdl *pdl_given = NULL;
206 1856 100         if (ispdl) {
207 99 50         if (!(pdl_given = pdl_SvPDLV(invoc))) barf("Failed to get PDL from arg");
208 99 100         if (pdl_given->state & PDL_INPLACE) {
209 2           amagic_call(invoc, sv_2mortal(newSViv(0)), concat_ass_amg, AMGf_assign);
210 2           ST(0) = invoc;
211 2           XSRETURN(1);
212             }
213             }
214 7453 100         IV i; for (i = 0; i < items; i++)
215 5599 50         if (!SvOK(ST(i)))
216 0           barf("Arg %"IVdf" is undefined", i);
217 1854           IV argstart = 1, type = PDL_D;
218 2665 100         if (items > 1 && sv_derived_from(ST(1), "PDL::Type")) {
    100          
219 811           argstart++;
220 811           AV *type_av = (AV *)SvRV(ST(1));
221 811 50         if (!type_av) barf("Arg 1 not a reference");
222 811 50         if (SvTYPE((SV *)type_av) != SVt_PVAV) barf("Arg 1 not an array-ref");
223 811           SV **firstval = av_fetch(type_av, 0, TRUE);
224 811 50         if (!firstval) barf("Failed to get type elt 0");
225 811           type = SvIV(*firstval);
226 1043 100         } else if (ispdl)
227 90           type = pdl_given->datatype;
228 1854           ENTER; SAVETMPS;
229 1854           SV *dims_ref = NULL;
230 1854 100         if (!(ispdl && items == 1)) {
    100          
231 1764           AV *dims_av = newAV();
232 1764 50         if (!dims_av) barf("Failed to make AV");
233 1764           dims_ref = sv_2mortal(newRV_noinc((SV *)dims_av));
234 1764 50         if (!dims_ref) barf("Failed to make ref to AV");
235 1764           char *retstr = _dims_from_args(dims_av, &ST(argstart), items-argstart);
236 1764 100         if (retstr) barf("%s", retstr);
237             }
238 1853 100         if (strcmp(SvPV_nolen(invoc), "PDL") == 0) {
239 1745           pdl *p = pdl_pdlnew();
240 1745 50         if (!p) barf("Failed to create ndarray");
241 1745           p->datatype = type;
242             PDL_Indx ndims, *dims;
243 1745 50         if (dims_ref) {
244 1745           dims = pdl_packdims(dims_ref, &ndims);
245 1745 50         if (!dims) barf("Failed to unpack dims");
246             } else {
247 0           dims = pdl_given->dims;
248 0           ndims = pdl_given->ndims;
249             }
250 1745           pdl_barf_if_error(pdl_setdims(p, dims, ndims));
251 1745 100         if (ix) pdl_barf_if_error(pdl_make_physical(p));
252 1745           pdl_SetSV_PDL(RETVAL = newSV(0), p);
253             } else {
254 108 50         PUSHMARK(SP);
255 108           PUSHs(ST(0));
256 108           PUTBACK;
257 108           int retvals = perl_call_method("initialize", G_SCALAR);
258 108           SPAGAIN;
259 108 50         if (retvals != 1) barf("initialize returned no values");
260 108           SvREFCNT_inc(RETVAL = POPs);
261 108 50         PUSHMARK(SP);
262 108 50         EXTEND(SP, 2); PUSHs(RETVAL); mPUSHi(type);
263 108           PUTBACK;
264 108           perl_call_method("set_datatype", G_VOID);
265 108           SPAGAIN;
266 108 100         if (!dims_ref) {
267 90           AV *dims_av = newAV();
268 90 50         if (!dims_av) barf("Failed to make AV");
269 90           dims_ref = sv_2mortal(newRV_noinc((SV *)dims_av));
270 90 50         if (!dims_ref) barf("Failed to make ref to AV");
271 90           PDL_Indx i, *dims = pdl_given->dims;
272 212 100         for (i = 0; i < pdl_given->ndims; i++)
273 122           av_push(dims_av, newSViv(dims[i]));
274             }
275 108 50         PUSHMARK(SP);
276 108 50         EXTEND(SP, 2); PUSHs(RETVAL); PUSHs(dims_ref);
277 108           PUTBACK;
278 108           perl_call_method("setdims", G_VOID);
279 108           SPAGAIN;
280             }
281 1853 50         FREETMPS; LEAVE;
282             OUTPUT:
283             RETVAL
284              
285             SV *
286             inplace(self, ...)
287             SV *self
288             CODE:
289 2413           pdl *p = pdl_SvPDLV(self);
290 2412 50         if (!p) barf("Failed to get PDL from arg");
291 2412           p->state |= PDL_INPLACE;
292 2412           SvREFCNT_inc(RETVAL = self);
293             OUTPUT:
294             RETVAL
295              
296             SV *
297             readonly(self)
298             SV *self
299             CODE:
300 2           pdl *p = pdl_SvPDLV(self);
301 2 50         if (!p) barf("Failed to get PDL from arg");
302 2 50         if (p->state & PDL_NOMYDIMS)
303 0           barf("Tried to set readonly on a null");
304 2           p->state |= PDL_READONLY;
305 2           SvREFCNT_inc(RETVAL = self);
306             OUTPUT:
307             RETVAL
308              
309             SV *
310             flowing(self)
311             SV *self
312             CODE:
313 21           pdl *p = pdl_SvPDLV(self);
314 21 50         if (!p) barf("Failed to get PDL from arg");
315 21           p->state |= PDL_DATAFLOW_F;
316 21           SvREFCNT_inc(RETVAL = self);
317             OUTPUT:
318             RETVAL
319              
320             SV *
321             topdl(klass, arg1, ...)
322             SV *klass;
323             SV *arg1;
324             CODE:
325 7426 100         if (items > 2 ||
326 7424 100         (!SvROK(arg1) && SvTYPE(arg1) < SVt_PVAV) ||
    50          
327 1643 50         (SvROK(arg1) && SvTYPE(SvRV(arg1)) == SVt_PVAV)
    100          
328 5801           ) {
329 5801 50         PUSHMARK(SP - items); /* this passes current set of args on */
330 5801           int retvals = perl_call_method("new", G_SCALAR);
331 5801           SPAGAIN;
332 5801 50         if (retvals != 1) barf("new returned no values");
333 5801           RETVAL = POPs;
334 1625 50         } else if (SvROK(arg1) && SvOBJECT(SvRV(arg1))) {
    100          
335 1624           RETVAL = arg1;
336             } else {
337 1           barf("Can not convert a %s to a %s", sv_reftype(arg1, 1), SvPV_nolen(klass));
338             }
339 7425           SvREFCNT_inc(RETVAL);
340             OUTPUT:
341             RETVAL
342              
343             int
344             has_vafftrans(self)
345             pdl *self;
346             CODE:
347 63 100         RETVAL = !!self->vafftrans;
348             OUTPUT:
349             RETVAL
350              
351             int
352             has_badvalue(self)
353             pdl *self;
354             CODE:
355 0 0         RETVAL = !!self->has_badvalue;
356             OUTPUT:
357             RETVAL
358              
359             # Return the transformation object or an undef otherwise.
360             pdl_trans *
361             trans_parent(self)
362             pdl *self;
363             CODE:
364 21           RETVAL = self->trans_parent;
365             OUTPUT:
366             RETVAL
367              
368             void
369             trans_children(self)
370             pdl *self
371             PPCODE:
372 19           U8 gimme = GIMME_V;
373 19 100         if (gimme == G_SCALAR)
374 6 50         mXPUSHu(self->ntrans_children);
375 13 50         else if (gimme == G_ARRAY) {
376 13 50         EXTEND(SP, self->ntrans_children);
    50          
377             PDL_Indx i;
378 91 100         for (i = 0; i < self->ntrans_children_allocated; i++) {
379 78           pdl_trans *t = self->trans_children[i];
380 78 100         if (!t) continue;
381 8           SV *sv = sv_newmortal();
382 8           sv_setref_pv(sv, "PDL::Trans", (void*)t);
383 8           PUSHs(sv);
384             }
385             }
386              
387             INCLUDE_COMMAND: $^X -e "require q{./Core/Dev.pm}; PDL::Core::Dev::generate_core_flags()"
388              
389             IV
390             address(self)
391             pdl *self;
392             CODE:
393 41 100         RETVAL = PTR2IV(self);
394             OUTPUT:
395             RETVAL
396              
397             IV
398             address_data(self)
399             pdl *self;
400             CODE:
401 7 100         RETVAL = PTR2IV(self->data);
402             OUTPUT:
403             RETVAL
404              
405             IV
406             address_datasv(p)
407             pdl *p
408             CODE:
409 2 100         RETVAL = PTR2IV(p->datasv);
410             OUTPUT:
411             RETVAL
412              
413             PDL_Indx
414             nelem_nophys(x)
415             pdl *x
416             CODE:
417 6 100         RETVAL = x->nvals;
418             OUTPUT:
419             RETVAL
420              
421             # only returns list, not context-aware
422             void
423             dimincs_nophys(x)
424             pdl *x
425             PPCODE:
426 0 0         EXTEND(SP, x->ndims);
    0          
427             PDL_Indx i;
428 0 0         for(i=0; indims; i++) mPUSHi(PDL_REPRINC(x,i));
    0          
429              
430             # only returns list, not context-aware
431             void
432             dims_nophys(x)
433             pdl *x
434             PPCODE:
435 2 50         EXTEND(SP, x->ndims);
    50          
436             PDL_Indx i;
437 4 100         for(i=0; indims; i++) mPUSHi(x->dims[i]);
438              
439             # only returns list, not context-aware
440             void
441             broadcastids_nophys(x)
442             pdl *x
443             PPCODE:
444 2 50         EXTEND(SP, x->nbroadcastids);
    50          
445             PDL_Indx i;
446 4 100         for(i=0; inbroadcastids; i++) mPUSHi(x->broadcastids[i]);
447              
448             void
449             firstvals_nophys(x)
450             pdl *x
451             PPCODE:
452 8 50         if (!(x->state & PDL_ALLOCATED)) barf("firstvals_nophys called on non-ALLOCATED %p", x);
453 8           PDL_Indx i, maxvals = PDLMIN(10, x->nvals);
454 8 50         EXTEND(SP, maxvals);
    50          
455 32 100         for(i=0; i
456 24           PDL_Anyval anyval = { PDL_INVALID, {0} };
457 24 50         ANYVAL_FROM_CTYPE_OFFSET(anyval, x->datatype, PDL_REPRP(x), PDL_REPROFFS(x)+i);
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
458 24 50         if (anyval.type < 0) barf("Error getting value, type=%d", anyval.type);
459 24           SV *sv = sv_newmortal();
460 24 0         ANYVAL_TO_SV(sv, anyval);
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
461 24           PUSHs(sv);
462 24           PUTBACK;
463             }
464              
465             IV
466             vaffine_from(self)
467             pdl *self;
468             CODE:
469 23 50         if (!self->vafftrans) barf("vaffine_from called on %p with NULL vafftrans", self);
470 23 50         RETVAL = PTR2IV(self->vafftrans->from);
471             OUTPUT:
472             RETVAL
473              
474             void
475             flags(x)
476             pdl *x
477             PPCODE:
478 150 100         PDL_FLAG_DUMP(PDL_LIST_FLAGS_PDLSTATE, x->state)
    50          
    100          
479              
480             int
481             set_donttouchdata(it,size=-1)
482             pdl *it
483             IV size
484             CODE:
485 24           it->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
486 24 100         if (size >= 0) it->nbytes = size;
487 24 100         RETVAL = 1;
488             OUTPUT:
489             RETVAL
490              
491             IV
492             nbytes(self)
493             pdl *self;
494             CODE:
495 15 100         RETVAL = self->nbytes;
496             OUTPUT:
497             RETVAL
498              
499             IV
500             datasv_refcount(p)
501             pdl *p
502             CODE:
503 17 50         if (!p->datasv) barf("NULL datasv");
504 17 50         RETVAL = SvREFCNT((SV*)p->datasv);
505             OUTPUT:
506             RETVAL
507              
508             PDL_Indx
509             nelem(x)
510             pdl *x
511             CODE:
512 14442           pdl_barf_if_error(pdl_make_physvaffine( x ));
513 14442 50         PDLDEBUG_f(printf("Core::nelem calling ")); pdl_barf_if_error(pdl_make_physdims(x));
514 14442 100         RETVAL = x->nvals;
515             OUTPUT:
516             RETVAL
517              
518              
519             # Call my howbig function
520              
521             int
522             howbig_c(datatype)
523             int datatype
524             CODE:
525 8181 100         RETVAL = pdl_howbig(datatype);
526             OUTPUT:
527             RETVAL
528              
529              
530             int
531             set_autopthread_targ(i)
532             int i;
533             CODE:
534 117           RETVAL = i;
535 117 100         pdl_autopthread_targ = i;
536             OUTPUT:
537             RETVAL
538              
539             int
540             get_autopthread_targ()
541             CODE:
542 0 0         RETVAL = pdl_autopthread_targ;
543             OUTPUT:
544             RETVAL
545              
546              
547             int
548             set_autopthread_size(i)
549             int i;
550             CODE:
551 2           RETVAL = i;
552 2 50         pdl_autopthread_size = i;
553             OUTPUT:
554             RETVAL
555              
556             int
557             get_autopthread_size()
558             CODE:
559 0 0         RETVAL = pdl_autopthread_size;
560             OUTPUT:
561             RETVAL
562              
563             int
564             get_autopthread_actual()
565             CODE:
566 15 100         RETVAL = pdl_autopthread_actual;
567             OUTPUT:
568             RETVAL
569              
570             int
571             get_autopthread_dim()
572             CODE:
573 14 100         RETVAL = pdl_autopthread_dim;
574             OUTPUT:
575             RETVAL
576              
577             void
578             _ci(...)
579             PPCODE:
580 132 50         PDL_XS_SCALAR(PDL_CD, C, 0 + I)
    50          
581              
582             void
583             _nan(...)
584             PPCODE:
585 90 50         PDL_XS_SCALAR(PDL_D, D, NAN)
    50          
586              
587             void
588             _inf(...)
589             PPCODE:
590 93 50         PDL_XS_SCALAR(PDL_D, D, INFINITY)
    50          
591              
592             MODULE = PDL::Core PACKAGE = PDL::Trans
593              
594             void
595             parents(trans)
596             pdl_trans *trans
597             PPCODE:
598 15 50         TRANS_PDLS(0, vtable->nparents)
    50          
    50          
    100          
    100          
599              
600             void
601             children(trans)
602             pdl_trans *trans
603             PPCODE:
604 14 50         TRANS_PDLS(vtable->nparents, vtable->npdls)
    50          
    50          
    50          
    100          
605              
606             IV
607             address(self)
608             pdl_trans *self;
609             CODE:
610 24 100         RETVAL = PTR2IV(self);
611             OUTPUT:
612             RETVAL
613              
614             IV
615             bvalflag(x)
616             pdl_trans *x
617             CODE:
618 2 100         RETVAL = x->bvalflag;
619             OUTPUT:
620             RETVAL
621              
622             void
623             flags(x)
624             pdl_trans *x
625             PPCODE:
626 30 100         PDL_FLAG_DUMP(PDL_LIST_FLAGS_PDLTRANS, x->flags)
    50          
    100          
627              
628             pdl_transvtable *
629             vtable(x)
630             pdl_trans *x
631             CODE:
632 13 50         if (!x->vtable) barf("%p has NULL vtable", x);
633 13           RETVAL = x->vtable;
634             OUTPUT:
635             RETVAL
636              
637             int
638             affine(x)
639             pdl_trans *x
640             CODE:
641 6 100         RETVAL= !!(x->flags & PDL_ITRANS_ISAFFINE);
642             OUTPUT:
643             RETVAL
644              
645             IV
646             offs(self)
647             pdl_trans *self;
648             CODE:
649 0 0         RETVAL = PTR2IV(self->offs);
650             OUTPUT:
651             RETVAL
652              
653             void
654             incs(x)
655             pdl_trans *x;
656             PPCODE:
657 0 0         if (!(x->flags & PDL_ITRANS_ISAFFINE)) barf("incs called on non-vaffine trans %p", x);
658 0 0         PDL_Indx i, max = x->incs ? x->pdls[1]->ndims : 0;
659 0 0         EXTEND(SP, max);
    0          
660 0 0         for(i=0; iincs[i]);
661              
662             # CORE21 hook up to own data
663             void
664             trans_children_indices(x)
665             pdl_trans *x;
666             PPCODE:
667 2           PDL_Indx i, max = x->vtable->ninds + x->vtable->nparents;
668 2 50         EXTEND(SP, max);
    50          
669 4 100         for(i=x->vtable->ninds; iind_sizes[i]);
670              
671             void
672             ind_sizes(x)
673             pdl_trans *x;
674             PPCODE:
675 2           PDL_Indx i, max = x->vtable->ninds;
676 2 50         EXTEND(SP, max);
    50          
677 2 50         for(i=0; iind_sizes[i]);
678              
679             void
680             inc_sizes(x)
681             pdl_trans *x;
682             PPCODE:
683 2           PDL_Indx i, max = x->vtable->nind_ids; /* CORE21 rename nind_ids */
684 2 50         EXTEND(SP, max);
    50          
685 2 50         for(i=0; iinc_sizes[i]);
686              
687             MODULE = PDL::Core PACKAGE = PDL::Trans::VTable
688              
689             char *
690             name(x)
691             pdl_transvtable *x;
692             CODE:
693 13           RETVAL = x->name;
694             OUTPUT:
695             RETVAL
696              
697             void
698             flags(x)
699             pdl_transvtable *x
700             PPCODE:
701 36 100         PDL_FLAG_DUMP(PDL_LIST_FLAGS_PDLVTABLE, x->flags)
    50          
    100          
702              
703             void
704             par_names(x)
705             pdl_transvtable *x
706             PPCODE:
707 5 50         EXTEND(SP, 2);
708             PDL_Indx i;
709 15 100         for (i=0; i < 2; i++) {
710 10           AV *av = (AV *)sv_2mortal((SV *)newAV());
711 10 50         if (!av) barf("Failed to create AV");
712 10           mPUSHs(newRV_inc((SV *)av));
713 10 100         PDL_Indx start = i==0 ? 0 : x->nparents, j, max = i==0 ? x->nparents : x->npdls;
    100          
714 10           av_extend(av, max-start);
715 21 100         for (j = start; j < max; j++) {
716 11           SV *sv = newSVpv(x->par_names[j], 0);
717 11 50         if (!sv) barf("Failed to create SV");
718 11 50         if (!av_store( av, j-start, sv )) {
719 0           SvREFCNT_dec(sv);
720 0           barf("Failed to store SV");
721             }
722             }
723             }
724              
725             void
726             dump(x)
727             pdl_transvtable *x;
728             CODE:
729 0           pdl_dump_transvtable(x, 0);
730              
731             MODULE = PDL::Core PACKAGE = PDL::Core
732              
733             IV
734             seed()
735             CODE:
736 0 0         RETVAL = pdl_pdl_seed();
737             OUTPUT:
738             RETVAL
739              
740             int
741             online_cpus()
742             CODE:
743 71           RETVAL = pdl_online_cpus();
744             OUTPUT:
745             RETVAL
746              
747             unsigned int
748             is_scalar_SvPOK(arg)
749             SV* arg;
750             CODE:
751 8274 100         RETVAL = SvPOK(arg);
752             OUTPUT:
753             RETVAL
754              
755              
756             int
757             set_debugging(i)
758             int i;
759             CODE:
760 0           RETVAL = pdl_debugging;
761 0 0         pdl_debugging = i;
762             OUTPUT:
763             RETVAL
764              
765              
766             SV *
767             at_bad_c(x,pos)
768             pdl* x
769             PDL_Indx pos_count=0;
770             PDL_Indx *pos
771             PREINIT:
772             PDL_Indx ipos;
773             int badflag;
774 19895           volatile PDL_Anyval result = { PDL_INVALID, {0} };
775             CODE:
776 19895 50         if (pos == NULL)
777 0           barf("Invalid NULL position given");
778 19895           pdl_barf_if_error(pdl_make_physvaffine( x ));
779 19879 50         if (pos_count < x->ndims)
780 0 0         barf("Invalid position: %"IND_FLAG" coordinate%s given for ndarray with %"IND_FLAG" dim%s", pos_count, pos_count == 1 ? "" : "s", x->ndims, x->ndims == 1 ? "" : "s");
    0          
781 39940 100         for (ipos=0; ipos < x->ndims; ipos++)
782 20077 100         if (pos[ipos] + ((pos[ipos] < 0) ? x->dims[ipos] : 0) >= x->dims[ipos])
    100          
783 16           barf("Position %"IND_FLAG" at dimension %"IND_FLAG" out of range", pos[ipos], ipos);
784             /* allow additional trailing indices
785             * which must be all zero, i.e. a
786             * [3,1,5] ndarray is treated as an [3,1,5,1,1,1,....]
787             * infinite dim ndarray
788             */
789 19871 100         for (ipos=x->ndims; ipos
790 8 50         if (pos[ipos] != 0)
791 0           barf("Invalid position %"IND_FLAG" at dimension %"IND_FLAG, pos[ipos], ipos);
792 19863 100         PDL_Indx ioff = pdl_get_offset(pos, x->dims, PDL_REPRINCS(x), PDL_REPROFFS(x), x->ndims);
    100          
793 19863 50         if (ioff >= 0)
794 19863 50         ANYVAL_FROM_CTYPE_OFFSET(result, x->datatype, PDL_REPRP(x), ioff);
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
795 19863 50         if (result.type < 0) barf("Position out of range");
796 19863           badflag = (x->state & PDL_BADVAL) > 0;
797 19863 100         if (badflag) {
798 2690           volatile PDL_Anyval badval = { PDL_INVALID, {0} };
799 2690 100         if (!(x->has_badvalue && x->badvalue.type != x->datatype)) {
    50          
800 2690 100         if (x->has_badvalue)
801 1           badval = x->badvalue;
802             else {
803             #define X(datatype, ctype, ppsym, ...) \
804             badval.type = datatype; badval.value.ppsym = PDL.bvals.ppsym;
805 2689           PDL_GENERICSWITCH(PDL_TYPELIST_ALL, x->datatype, X, )
806             #undef X
807             }
808             }
809 2690 50         if (badval.type < 0) barf("Error getting badvalue, type=%d", badval.type);
810 2690           int isbad = ANYVAL_ISBAD(result, badval);
811 2690 50         if (isbad == -1) barf("ANYVAL_ISBAD error on types %d, %d", result.type, badval.type);
812 2690 100         if (isbad)
813 2           RETVAL = newSVpvn( "BAD", 3 );
814             else {
815 2688           RETVAL = newSV(0);
816 2688 0         ANYVAL_TO_SV(RETVAL, result);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
817             }
818             } else {
819 17173           RETVAL = newSV(0);
820 17173 50         ANYVAL_TO_SV(RETVAL, result);
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
821             }
822             OUTPUT:
823             RETVAL
824              
825             SV *
826             listref_c(x)
827             pdl *x
828             CODE:
829 456           RETVAL = pdl2avref(x, 1);
830             OUTPUT:
831             RETVAL
832              
833             void
834             set_c(x,pos,value)
835             pdl* x
836             PDL_Indx pos_count=0;
837             PDL_Indx *pos
838             PDL_Anyval value
839             CODE:
840 92           pdl_barf_if_error(pdl_make_physvaffine( x ));
841 92 50         if (pos == NULL || pos_count < x->ndims)
    50          
842 0           croak("Invalid position");
843             /* allow additional trailing indices
844             * which must be all zero, i.e. a
845             * [3,1,5] ndarray is treated as an [3,1,5,1,1,1,....]
846             * infinite dim ndarray
847             */
848             PDL_Indx ipos;
849 92 50         for (ipos=x->ndims; ipos
850 0 0         if (pos[ipos] != 0)
851 0           croak("Invalid position");
852 183 100         pdl_barf_if_error(pdl_set(PDL_REPRP(x), x->datatype, pos, x->dims,
853 183 100         PDL_REPRINCS(x), PDL_REPROFFS(x),
    100          
854             x->ndims,value));
855 92           pdl_barf_if_error(pdl_changed(x, PDL_PARENTDATACHANGED, 0));
856              
857             BOOT:
858             /* Initialize structure of pointers to core C routines */
859 72           PDL.Version = PDL_CORE_VERSION;
860             #define X(sym, rettype, args) PDL.sym = pdl_ ## sym;
861 72           PDL_CORE_LIST(X)
862             #undef X
863             #define X(symbol, ctype, ppsym, shortctype, defbval, ...) \
864             PDL.bvals.ppsym = defbval;
865 72           PDL_TYPELIST_ALL(X)
866             #undef X
867 72           PDL.type_names = type_names;
868 72           PDL.ntypes = PDL_NTYPES;
869             /* "Publish" pointer to this structure in perl variable for use
870             by other modules */
871 72           sv_setiv(get_sv("PDL::SHARE",TRUE|GV_ADDMULTI), PTR2IV(&PDL));
872             /* modified from https://www.perlmonks.org/?node_id=849145 */
873 72           char *package = "PDL";
874 72           HV* stash = gv_stashpvn(package, strlen(package), TRUE);
875 72           char *meths[] = { "sever", "new_from_specification", NULL }, **methsptr = meths;
876 216 100         for (; *methsptr; methsptr++) {
877 144           SV **meth = hv_fetch(stash, *methsptr, strlen(*methsptr), 0);
878 144 50         if (!meth) croak("No found method '%s' in '%s'", *methsptr, package);
879 144           CV *cv = GvCV(*meth);
880 144 50         if (!cv) croak("No found CV for '%s' in '%s'", *methsptr, package);
881 144           CvLVALUE_on(cv);
882             }
883              
884             # make ndarray belonging to 'class' and of type 'type'
885             # from avref 'array_ref' which is checked for being
886             # rectangular first
887              
888             SV*
889             pdl_avref(array_ref, class, type)
890             SV* array_ref
891             char* class
892             int type
893             PREINIT:
894             AV *dims, *av;
895 7645           int datalevel = -1;
896             SV* psv;
897             pdl* p;
898             CODE:
899             /* make an ndarray from a Perl array ref */
900              
901 7645 50         if (!SvROK(array_ref))
902 0           croak("pdl_avref: not a reference");
903              
904              
905 7645 50         if (SvTYPE(SvRV(array_ref)) != SVt_PVAV)
906 0           croak("pdl_avref: not an array reference");
907              
908             // Expand the array ref to a list, and allocate a Perl list to hold the dimlist
909 7645           av = (AV *) SvRV(array_ref);
910 7645           dims = (AV *) sv_2mortal( (SV *) newAV());
911              
912 7645           av_store(dims,0,newSViv((IV) av_len(av)+1));
913              
914 7645           av_ndcheck(av,dims,0,&datalevel);
915              
916             /* printf("will make type %s\n",class); */
917             /*
918             at this stage start making an ndarray and populate it with
919             values from the array (which has already been checked in av_check)
920             */
921 7645           ENTER; SAVETMPS;
922 7645 100         if (strcmp(class,"PDL") == 0) {
923 7643           p = pdl_from_array(av,dims,type,NULL); /* populate with data */
924 7643           RETVAL = newSV(0);
925 7643           pdl_SetSV_PDL(RETVAL,p);
926             } else {
927             /* call class->initialize method */
928 2 50         PUSHMARK(SP);
929 2 50         XPUSHs(sv_2mortal(newSVpv(class, 0)));
930 2           PUTBACK;
931 2           perl_call_method("initialize", G_SCALAR);
932 2           SPAGAIN;
933 2           psv = POPs;
934 2           PUTBACK;
935 2           p = pdl_SvPDLV(psv); /* and get ndarray from returned object */
936 2           RETVAL = psv;
937 2           SvREFCNT_inc(psv);
938 2           pdl_from_array(av,dims,type,p); /* populate ;) */
939             }
940 7645 100         FREETMPS; LEAVE;
941             OUTPUT:
942             RETVAL
943              
944             MODULE = PDL::Core PACKAGE = PDL::Core PREFIX = pdl_
945              
946             int
947             pdl_pthreads_enabled()
948              
949             MODULE = PDL::Core PACKAGE = PDL PREFIX = pdl_
950              
951             int
952             isnull(self)
953             pdl *self;
954             CODE:
955 11475 100         RETVAL= !!(self->state & PDL_NOMYDIMS);
956             OUTPUT:
957             RETVAL
958              
959             pdl *
960             make_physical(self)
961             pdl *self;
962             CODE:
963 587           pdl_barf_if_error(pdl_make_physical(self));
964 581           RETVAL = self;
965             OUTPUT:
966             RETVAL
967              
968             pdl *
969             make_physvaffine(self)
970             pdl *self;
971             CODE:
972 16           pdl_barf_if_error(pdl_make_physvaffine(self));
973 16           RETVAL = self;
974             OUTPUT:
975             RETVAL
976              
977             pdl *
978             make_physdims(self)
979             pdl *self;
980             CODE:
981 8 50         PDLDEBUG_f(printf("Core::make_physdims calling ")); pdl_barf_if_error(pdl_make_physdims(self));
982 3           RETVAL = self;
983             OUTPUT:
984             RETVAL
985              
986             pdl *
987             _convert_int(self, new_dtype)
988             pdl *self;
989             int new_dtype;
990             CODE:
991 343           RETVAL = pdl_get_convertedpdl(self, new_dtype);
992 343 50         if (!RETVAL) barf("convert error");
993             OUTPUT:
994             RETVAL
995              
996             void
997             set_datatype(a,datatype)
998             pdl *a
999             int datatype
1000             CODE:
1001 8680           pdl_barf_if_error(pdl_set_datatype(a, datatype));
1002              
1003             int
1004             get_datatype(self)
1005             pdl *self
1006             CODE:
1007 23086 100         RETVAL = self->datatype;
1008             OUTPUT:
1009             RETVAL
1010              
1011             pdl *
1012             pdl_sever(src)
1013             pdl *src;
1014             CODE:
1015 5986           pdl_barf_if_error(pdl_sever(src));
1016 5986           RETVAL = src;
1017             OUTPUT:
1018             RETVAL
1019              
1020             void
1021             pdl_dump(x)
1022             pdl *x;
1023              
1024             void
1025             pdl_add_threading_magic(it,nthdim,nthreads)
1026             pdl *it
1027             PDL_Indx nthdim
1028             PDL_Indx nthreads
1029             CODE:
1030 26           pdl_barf_if_error(pdl_add_threading_magic(it,nthdim,nthreads));
1031              
1032             void
1033             pdl_remove_threading_magic(it)
1034             pdl *it
1035             CODE:
1036 4           pdl_barf_if_error(pdl_add_threading_magic(it,-1,-1));
1037              
1038             MODULE = PDL::Core PACKAGE = PDL
1039              
1040             PDL_Anyval
1041             sclr(it)
1042             pdl* it
1043             CODE:
1044             /* get the first element of an ndarray and return as
1045             * Perl scalar (autodetect suitable type IV or NV)
1046             */
1047 3636 50         PDLDEBUG_f(printf("Core::sclr calling ")); pdl_barf_if_error(pdl_make_physdims(it));
1048 3636 100         if (it->nvals > 1) barf("multielement ndarray in 'sclr' call");
1049 3634           pdl_barf_if_error(pdl_make_physvaffine( it ));
1050 3634           RETVAL.type = PDL_INVALID;
1051 3634 50         if (it->nvals == 1)
1052 3634 50         ANYVAL_FROM_CTYPE_OFFSET(RETVAL, it->datatype, PDL_REPRP(it), PDL_REPROFFS(it));
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
1053 3634 50         if (RETVAL.type < 0) croak("Position out of range");
1054             OUTPUT:
1055             RETVAL
1056              
1057             SV *
1058             initialize(class)
1059             SV *class
1060             CODE:
1061 37982           HV *bless_stash = SvROK(class)
1062 8149           ? SvSTASH(SvRV(class)) /* a reference to a class */
1063 18991 100         : gv_stashsv(class, 0); /* a class name */
1064 18991           RETVAL = newSV(0);
1065 18991           pdl *n = pdl_pdlnew();
1066 18991 50         if (!n) pdl_pdl_barf("Error making null pdl");
1067 18991           pdl_SetSV_PDL(RETVAL,n); /* set a null PDL to this SV * */
1068 18991           RETVAL = sv_bless(RETVAL, bless_stash); /* bless appropriately */
1069             OUTPUT:
1070             RETVAL
1071              
1072             # to facilitate for STORABLE_thaw
1073             void
1074             set_sv_to_null_pdl(sv)
1075             SV *sv
1076             CODE:
1077 18           pdl *it = pdl_pdlnew();
1078 18 50         if (!it) pdl_pdl_barf("Failed to create new pdl");
1079             /* connect pdl struct to this sv */
1080 18           sv_setiv(SvRV(sv),PTR2IV(it));
1081 18           it->sv = SvRV(sv);
1082 18           pdl_SetSV_PDL(sv,it);
1083              
1084             # undocumented for present. returns PDL still needing dims and datatype
1085             # offset is in bytes, not elements
1086             SV *
1087             new_around_datasv(class, datasv_pointer, offset=0)
1088             SV *class
1089             IV datasv_pointer
1090             IV offset
1091             CODE:
1092 16 100         if (offset < 0)
1093 1           pdl_pdl_barf("Tried to new_around_datasv with negative offset=%" IVdf, offset);
1094 15           STRLEN sv_len = SvCUR((SV*)datasv_pointer);
1095 15 100         if (offset >= sv_len)
1096 1           pdl_pdl_barf("Tried to new_around_datasv with offset=%" IVdf " >= %zd", offset, sv_len);
1097 28           HV *bless_stash = SvROK(class)
1098 0           ? SvSTASH(SvRV(class)) /* a reference to a class */
1099 14 50         : gv_stashsv(class, 0); /* a class name */
1100 14           pdl *n = pdl_pdlnew();
1101 14 50         if (!n) pdl_pdl_barf("Error making null pdl");
1102 14           RETVAL = newSV(0);
1103 14           pdl_SetSV_PDL(RETVAL,n); /* set a null PDL to this SV * */
1104 14           RETVAL = sv_bless(RETVAL, bless_stash); /* bless appropriately */
1105             /* set the datasv to what was supplied */
1106 14           n->datasv = (void*)datasv_pointer;
1107 14           SvREFCNT_inc((SV*)(datasv_pointer));
1108 14           n->data = SvPV_nolen((SV*)datasv_pointer) + offset;
1109 14           n->nbytes = sv_len - offset;
1110 14           n->state |= PDL_ALLOCATED;
1111             OUTPUT:
1112             RETVAL
1113              
1114             # undocumented for present. returns PDL still needing dims and datatype
1115             SV *
1116             new_around_pointer(class, ptr, nbytes)
1117             SV *class
1118             IV ptr
1119             IV nbytes
1120             CODE:
1121 2 50         if (nbytes < 0)
1122 0           pdl_pdl_barf("Tried to new_around_pointer with negative nbytes=%" IVdf, nbytes);
1123 2 100         if (!ptr)
1124 1           pdl_pdl_barf("Tried to new_around_pointer with NULL pointer");
1125 2           HV *bless_stash = SvROK(class)
1126 0           ? SvSTASH(SvRV(class)) /* a reference to a class */
1127 1 50         : gv_stashsv(class, 0); /* a class name */
1128 1           pdl *n = pdl_pdlnew();
1129 1 50         if (!n) pdl_pdl_barf("Error making null pdl");
1130 1           RETVAL = newSV(0);
1131 1           pdl_SetSV_PDL(RETVAL,n); /* set a null PDL to this SV * */
1132 1           RETVAL = sv_bless(RETVAL, bless_stash); /* bless appropriately */
1133             /* set the datasv to what was supplied */
1134 1           n->data = (void*)ptr;
1135 1           n->nbytes = nbytes;
1136 1           n->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
1137             OUTPUT:
1138             RETVAL
1139              
1140             SV *
1141             get_dataref(self)
1142             pdl *self
1143             CODE:
1144 11920 50         PDLDEBUG_f(printf("get_dataref %p\n", self));
1145 11920           pdl_barf_if_error(pdl_make_physical(self));
1146 11920 100         if (!self->datasv) {
1147 6030 50         PDLDEBUG_f(printf("get_dataref no datasv\n"));
1148 6030           self->datasv = newSVpvn("", 0);
1149 6030 50         (void)SvGROW((SV *)self->datasv, self->nbytes);
    100          
1150 6030           SvCUR_set((SV *)self->datasv, self->nbytes);
1151 6030           memmove(SvPV_nolen((SV*)self->datasv), self->data, self->nbytes);
1152             }
1153 11920           RETVAL = newRV(self->datasv);
1154 11920 50         PDLDEBUG_f(printf("get_dataref end: "); pdl_dump(self));
1155             OUTPUT:
1156             RETVAL
1157              
1158             void
1159             upd_data(self, keep_datasv=0)
1160             pdl *self
1161             IV keep_datasv
1162             CODE:
1163 7846 50         if(self->state & PDL_DONTTOUCHDATA)
1164 0           croak("Trying to touch dataref of magical (mmaped?) pdl");
1165 7846 50         PDLDEBUG_f(printf("upd_data: "); pdl_dump(self));
1166 7846 100         if (keep_datasv || !PDL_USESTRUCTVALUE(self)) {
    100          
1167 3903           self->data = SvPV_nolen((SV*)self->datasv);
1168 3943 100         } else if (self->datasv) {
1169 3942 50         PDLDEBUG_f(printf("upd_data zap datasv\n"));
1170 3942           Size_t svsize = SvCUR((SV*)self->datasv);
1171 3942 50         if (svsize != self->nbytes)
1172 0           croak("Trying to upd_data but datasv now length %zu instead of %td", svsize, self->nbytes);
1173 3942           memmove(self->data, SvPV_nolen((SV*)self->datasv), self->nbytes);
1174 3942           SvREFCNT_dec(self->datasv);
1175 3942           self->datasv = NULL;
1176             } else {
1177 1 50         PDLDEBUG_f(printf("upd_data datasv gone, maybe reshaped\n"));
1178             }
1179 7846           pdl_barf_if_error(pdl_changed(self, PDL_PARENTDATACHANGED, 0));
1180 7846 50         PDLDEBUG_f(printf("upd_data end: "); pdl_dump(self));
1181              
1182             void
1183             update_data_from(self, sv)
1184             pdl *self
1185             SV *sv
1186             CODE:
1187 7404 50         PDLDEBUG_f(printf("update_data_from: "); pdl_dump(self));
1188 7404           pdl_barf_if_error(pdl_make_physvaffine(self));
1189 7404           Size_t svsize = SvCUR(sv);
1190 7404 100         if (svsize != self->nbytes)
1191 1           croak("Trying to update_data_from but sv length %zu instead of %td", svsize, self->nbytes);
1192 7403           memmove(self->data, SvPV_nolen(sv), self->nbytes);
1193 7403           pdl_barf_if_error(pdl_changed(self, PDL_PARENTDATACHANGED, 0));
1194 7403 50         PDLDEBUG_f(printf("update_data_from end: "); pdl_dump(self));
1195              
1196             int
1197             badflag(x,newval=0)
1198             pdl *x
1199             int newval
1200             CODE:
1201 10475 100         if (items>1) {
1202 576 100         if (x->trans_parent)
1203 1           pdl_propagate_badflag_dir(x, newval, 0, 1);
1204 576           pdl_propagate_badflag_dir(x, newval, 1, 1);
1205             }
1206 10475 100         RETVAL = ((x->state & PDL_BADVAL) > 0);
1207             OUTPUT:
1208             RETVAL
1209              
1210             PDL_Indx
1211             getndims(x)
1212             pdl *x
1213             ALIAS:
1214             PDL::ndims = 1
1215             CODE:
1216             (void)ix;
1217 25083 50         PDLDEBUG_f(printf("Core::getndims calling ")); pdl_barf_if_error(pdl_make_physdims(x));
1218 25083 100         RETVAL = x->ndims;
1219             OUTPUT:
1220             RETVAL
1221              
1222             void
1223             dims(x)
1224             pdl *x
1225             PREINIT:
1226             PDL_Indx i;
1227 5405           U8 gimme = GIMME_V;
1228             PPCODE:
1229 5405 50         PDLDEBUG_f(printf("Core::dims calling ")); pdl_barf_if_error(pdl_make_physdims(x));
1230 5405 100         if (gimme == G_ARRAY) {
1231 4855 50         EXTEND(SP, x->ndims);
    50          
1232 11518 100         for(i=0; indims; i++) mPUSHi(x->dims[i]);
1233             }
1234 550 100         else if (gimme == G_SCALAR) {
1235 549 50         mXPUSHu(x->ndims);
1236             }
1237              
1238             # only returns list, not context-aware
1239             void
1240             dimincs(x)
1241             pdl *x
1242             PREINIT:
1243             PDL_Indx i;
1244             PPCODE:
1245 3           pdl_barf_if_error(pdl_make_physvaffine(x));
1246 3 50         EXTEND(SP, x->ndims);
    50          
1247 11 100         for (i=0; indims; i++) mPUSHi(PDL_REPRINC(x,i));
    100          
1248              
1249             PDL_Indx
1250             getdim(x,y)
1251             pdl *x
1252             PDL_Indx y
1253             ALIAS:
1254             PDL::dim = 1
1255             CODE:
1256             (void)ix;
1257 2440 50         PDLDEBUG_f(printf("Core::getdim calling ")); pdl_barf_if_error(pdl_make_physdims(x));
1258 2408 100         if (y < 0) y += x->ndims;
1259 2408 50         if (y < 0) croak("negative dim index too large");
1260 2408 100         RETVAL = y < x->ndims ? x->dims[y] : 1; /* all other dims=1 */
    100          
1261             OUTPUT:
1262             RETVAL
1263              
1264             PDL_Indx
1265             getnbroadcastids(x)
1266             pdl *x
1267             CODE:
1268 0 0         PDLDEBUG_f(printf("Core::getnbroadcastids calling ")); pdl_barf_if_error(pdl_make_physdims(x));
1269 0 0         RETVAL = x->nbroadcastids;
1270             OUTPUT:
1271             RETVAL
1272              
1273             void
1274             broadcastids(x)
1275             pdl *x
1276             PREINIT:
1277             PDL_Indx i;
1278 64           U8 gimme = GIMME_V;
1279             PPCODE:
1280 64 50         PDLDEBUG_f(printf("Core::broadcastids calling ")); pdl_barf_if_error(pdl_make_physdims(x));
1281 64 50         if (gimme == G_ARRAY) {
1282 64 50         EXTEND(SP, x->nbroadcastids);
    50          
1283 135 100         for(i=0; inbroadcastids; i++) mPUSHi(x->broadcastids[i]);
1284             }
1285 0 0         else if (gimme == G_SCALAR) {
1286 0 0         mXPUSHu(x->nbroadcastids);
1287             }
1288              
1289             PDL_Indx
1290             getbroadcastid(x,y)
1291             pdl *x
1292             PDL_Indx y
1293             CODE:
1294 2 100         if (y < 0 || y >= x->nbroadcastids) barf("requested invalid broadcastid %"IND_FLAG", nbroadcastids=%"IND_FLAG, y, x->nbroadcastids);
    50          
1295 0 0         RETVAL = x->broadcastids[y];
1296             OUTPUT:
1297             RETVAL
1298              
1299             void
1300             setdims(x,dims)
1301             pdl *x
1302             PDL_Indx dims_count=0;
1303             PDL_Indx *dims
1304             CODE:
1305 8221           pdl_barf_if_error(pdl_setdims(x,dims,dims_count));
1306              
1307             void
1308             dowhenidle()
1309             CODE:
1310 0           pdl_run_delayed_magic();
1311 0           XSRETURN(0);
1312              
1313             void
1314             bind(p,c)
1315             pdl *p
1316             SV *c
1317             PROTOTYPE: $&
1318             CODE:
1319 0 0         if (!pdl_add_svmagic(p,c)) croak("Failed to add magic");
1320 0           XSRETURN(0);
1321              
1322             void
1323             sethdr(p,h)
1324             pdl *p
1325             SV *h
1326             PREINIT:
1327             CODE:
1328 106 100         if(p->hdrsv == NULL) {
1329 98           p->hdrsv = &PL_sv_undef; /*(void*) newSViv(0);*/
1330             }
1331              
1332             /* Throw an error if we're not either undef or hash */
1333 106 100         if ( (h != &PL_sv_undef && h != NULL) &&
    50          
1334 103 50         ( !SvROK(h) || SvTYPE(SvRV(h)) != SVt_PVHV )
    50          
1335             )
1336 0           croak("Not a HASH reference");
1337              
1338             /* Clear the old header */
1339 106           SvREFCNT_dec(p->hdrsv);
1340              
1341             /* Put the new header (or undef) in place */
1342 106 100         if(h == &PL_sv_undef || h == NULL)
    50          
1343 3           p->hdrsv = NULL;
1344             else
1345 103           p->hdrsv = (void*) newRV( (SV*) SvRV(h) );
1346              
1347             SV *
1348             hdr(p)
1349             pdl *p
1350             CODE:
1351 332 50         PDLDEBUG_f(printf("Core::hdr calling ")); pdl_barf_if_error(pdl_make_physdims(p));
1352             /* Make sure that in the undef case we return not */
1353             /* undef but an empty hash ref. */
1354 332 100         if((p->hdrsv==NULL) || (p->hdrsv == &PL_sv_undef)) {
    50          
1355 17           p->hdrsv = (void*) newRV_noinc( (SV*)newHV() );
1356             }
1357 332           RETVAL = newRV( (SV*) SvRV((SV*)p->hdrsv) );
1358             OUTPUT:
1359             RETVAL
1360              
1361             SV *
1362             gethdr(p)
1363             pdl *p
1364             CODE:
1365 178 50         PDLDEBUG_f(printf("Core::gethdr calling ")); pdl_barf_if_error(pdl_make_physdims(p));
1366 178 100         if((p->hdrsv==NULL) || (p->hdrsv == &PL_sv_undef)) {
    50          
1367 117           RETVAL = &PL_sv_undef;
1368             } else {
1369 61           RETVAL = newRV( (SV*) SvRV((SV*)p->hdrsv) );
1370             }
1371             OUTPUT:
1372             RETVAL
1373              
1374             SV *
1375             unpdl(x)
1376             pdl *x
1377             CODE:
1378 54           pdl_barf_if_error(pdl_make_physvaffine( x ));
1379 54           RETVAL = pdl2avref(x, 0);
1380             OUTPUT:
1381             RETVAL
1382              
1383             void
1384             dog(x, opt=sv_2mortal(newRV_noinc((SV *)newHV())))
1385             pdl *x
1386             SV *opt
1387             PPCODE:
1388 47           HV *opt_hv = NULL;
1389 47 100         if (!(SvROK(opt) && SvTYPE(opt_hv = (HV*)SvRV(opt)) == SVt_PVHV))
    50          
1390 1           barf("Usage: $pdl->dog([\\%%opt])");
1391 46 50         PDLDEBUG_f(printf("Core::dog calling ")); pdl_barf_if_error(pdl_make_physdims(x));
1392 46 100         if (x->ndims <= 0) barf("dog: must have at least one dim");
1393 45           SV **svp = hv_fetchs(opt_hv, "Break", 0);
1394 45 100         char dobreak = (svp && *svp && SvOK(*svp));
    50          
    50          
1395 45 50         PDL_Indx *thesedims = x->dims, *theseincs = PDL_REPRINCS(x), ndimsm1 = x->ndims-1;
1396 45           PDL_Indx i, howmany = x->dims[ndimsm1], thisoffs = 0, topinc = x->dimincs[ndimsm1];
1397 45 50         EXTEND(SP, howmany);
    50          
1398 45           pdl_barf_if_error(pdl_prealloc_trans_children(x, x->ntrans_children_allocated + howmany));
1399 1159 100         for (i = 0; i < howmany; i++, thisoffs += topinc) {
1400 1114           pdl *childpdl = pdl_pdlnew();
1401 1114 50         if (!childpdl) pdl_pdl_barf("Error making null pdl");
1402 1114           pdl_barf_if_error(pdl_affine_new(x,childpdl,thisoffs,
1403             thesedims,ndimsm1,theseincs,ndimsm1));
1404 1114           SV *childsv = sv_newmortal();
1405 1114           pdl_SetSV_PDL(childsv, childpdl); /* do before sever so .sv true */
1406 1114 100         if (dobreak) pdl_barf_if_error(pdl_sever(childpdl));
1407 1114           PUSHs(childsv);
1408             }
1409 45           XSRETURN(howmany);
1410              
1411             void
1412             broadcastover_n(code, pdl1, ...)
1413             SV *code;
1414             pdl *pdl1;
1415             CODE:
1416 2           PDL_Indx npdls = items - 1;
1417             PDL_Indx i,sd;
1418 2           pdl *pdls[npdls];
1419 2           PDL_Indx realdims[npdls];
1420             pdl_broadcast pdl_brc;
1421 2           pdls[0] = pdl1;
1422 4 100         for(i=1; i
1423 2           pdls[i] = pdl_SvPDLV(ST(i+1));
1424 6 100         for(i=0; i
1425 4           pdl_barf_if_error(pdl_make_physical(pdls[i]));
1426 4           realdims[i] = 0;
1427             }
1428 2           PDL_CLRMAGIC(&pdl_brc);
1429 2           pdl_brc.gflags = 0; /* avoid uninitialised value use below */
1430 2           pdl_barf_if_error(pdl_initbroadcaststruct(0,pdls,realdims,realdims,npdls,NULL,&pdl_brc,NULL,NULL,NULL, 1));
1431 2           pdl_error error_ret = {0, NULL, 0};
1432 2 50         if (pdl_startbroadcastloop(&pdl_brc,NULL,NULL,&error_ret) < 0) croak("Error starting broadcastloop");
1433 2           pdl_barf_if_error(error_ret);
1434 2           sd = pdl_brc.ndims;
1435 2           ENTER; SAVETMPS;
1436             do {
1437 36           dSP;
1438 36 50         PUSHMARK(SP);
1439 36 50         EXTEND(SP,items);
    50          
1440 36           PUSHs(sv_2mortal(newSViv((sd-1))));
1441 108 100         for(i=0; i
1442 72           PDL_Anyval anyval = { PDL_INVALID, {0} };
1443 72 0         ANYVAL_FROM_CTYPE_OFFSET(anyval, pdls[i]->datatype, PDL_REPRP(pdls[i]), pdl_brc.offs[i]);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
1444 72 50         if (anyval.type < 0) die("Error getting value from ndarray");
1445 72           SV *sv = sv_newmortal();
1446 72 0         ANYVAL_TO_SV(sv, anyval);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1447 72           PUSHs(sv);
1448             }
1449 36           PUTBACK;
1450 36           perl_call_sv(code,G_DISCARD);
1451 36           sd = pdl_iterbroadcastloop(&pdl_brc,0);
1452 36 50         if ( sd < 0 ) die("Error in iterbroadcastloop");
1453 36 100         } while( sd );
1454 2 50         FREETMPS; LEAVE;
1455 2           pdl_freebroadcaststruct(&pdl_brc);
1456              
1457             void
1458             broadcastover(code, realdims, creating, nothers, pdl1, ...)
1459             PDL_Indx realdims_count=0;
1460             PDL_Indx creating_count=0;
1461             SV *code;
1462             PDL_Indx *realdims;
1463             PDL_Indx *creating;
1464             int nothers;
1465             pdl *pdl1;
1466             CODE:
1467 10           int targs = items - 4;
1468 10 50         if(nothers < 0 || nothers >= targs)
    50          
1469 0           croak("Usage: broadcastover(sub,realdims,creating,nothers,pdl1[,pdl...][,otherpars..])");
1470 10           PDL_Indx npdls = targs-nothers, i,nc=npdls;
1471 10           pdl *pdls[npdls], *child[npdls];
1472 10           SV *csv[npdls], *others[nothers];
1473 10 50         if (creating_count < npdls) croak("broadcastover: need at least one creating flag per pdl: %"IND_FLAG" pdls, %"IND_FLAG" flags", npdls, creating_count);
1474 10 50         if (realdims_count != npdls) croak("broadcastover: need one realdim flag per pdl: %"IND_FLAG" pdls, %"IND_FLAG" flags", npdls, realdims_count);
1475 10           int dtype=0;
1476 10           pdls[0] = pdl1;
1477 27 100         for(i=1; i
1478 17           pdls[i] = pdl_SvPDLV(ST(i+4));
1479 37 100         for(i=0; i
1480 27 100         if (creating[i])
1481 8           nc += realdims[i];
1482             else {
1483 19           pdl_barf_if_error(pdl_make_physvaffine(pdls[i]));
1484 19           dtype = PDLMAX(dtype,pdls[i]->datatype);
1485             }
1486             }
1487 10 50         if (creating_count < nc)
1488 0           croak("Not enough dimension info to create pdls");
1489 41 100         for (i=npdls; i<=targs; i++)
1490 31           others[i-npdls] = ST(i+4);
1491 10 50         PDLDEBUG_f(for (i=0;i
    0          
1492             pdl_broadcast pdl_brc;
1493 10           PDL_CLRMAGIC(&pdl_brc);
1494 10           pdl_brc.gflags = 0; /* avoid uninitialised value use below */
1495 10           pdl_barf_if_error(pdl_initbroadcaststruct(0,pdls,realdims,creating,npdls,
1496             NULL,&pdl_brc,NULL,NULL,NULL, 1));
1497 37 100         for(i=0, nc=npdls; i
1498 27 100         if (creating[i]) {
1499 8           PDL_Indx *cp = creating+nc;
1500 8           pdls[i]->datatype = dtype;
1501 8           pdl_barf_if_error(pdl_broadcast_create_parameter(&pdl_brc,i,cp,0));
1502 8           nc += realdims[i];
1503 8           pdl_barf_if_error(pdl_make_physical(pdls[i]));
1504 8 50         PDLDEBUG_f(pdl_dump(pdls[i]));
1505             /* And make it nonnull, now that we've created it */
1506 8           pdls[i]->state &= (~PDL_NOMYDIMS);
1507             }
1508 10           pdl_error error_ret = {0, NULL, 0};
1509 10 50         if (pdl_startbroadcastloop(&pdl_brc,NULL,NULL,&error_ret) < 0) croak("Error starting broadcastloop");
1510 10           pdl_barf_if_error(error_ret);
1511 37 100         for(i=0; i
1512 27 100         PDL_Indx *thesedims = pdls[i]->dims, *theseincs = PDL_REPRINCS(pdls[i]);
1513             /* need to make sure we get the vaffine (grand)parent */
1514 27 100         if (PDL_VAFFOK(pdls[i]))
1515 2           pdls[i] = pdls[i]->vafftrans->from;
1516 27           child[i]=pdl_pdlnew();
1517 27 50         if (!child[i]) pdl_pdl_barf("Error making null pdl");
1518 27           pdl_barf_if_error(pdl_affine_new(pdls[i],child[i],pdl_brc.offs[i],
1519 27           thesedims,realdims[i],
1520 27           theseincs,realdims[i]));
1521 27           pdl_barf_if_error(pdl_make_physvaffine(child[i])); /* make sure we can
1522             get at the vafftrans */
1523 27           csv[i] = sv_newmortal();
1524 27           pdl_SetSV_PDL(csv[i], child[i]); /* pdl* into SV* */
1525             }
1526             int brcloopval;
1527 10           ENTER; SAVETMPS;
1528             do { /* the actual broadcastloop */
1529             pdl_trans *traff;
1530 32           dSP;
1531 32 50         PUSHMARK(SP);
1532 32 50         EXTEND(SP,npdls+nothers);
    50          
1533 120 100         for(i=0; i
1534             /* just twiddle the offset - quick and dirty */
1535             /* we must twiddle both !! */
1536 88           traff = child[i]->trans_parent;
1537 88           traff->offs = pdl_brc.offs[i];
1538 88           child[i]->vafftrans->offs = pdl_brc.offs[i];
1539 88           child[i]->state |= PDL_PARENTDATACHANGED;
1540 88           PUSHs(csv[i]);
1541             }
1542 99 100         for (i=0; i
1543 67           PUSHs(others[i]); /* pass the OtherArgs onto the stack */
1544 32           PUTBACK;
1545 32           perl_call_sv(code,G_DISCARD);
1546 32           brcloopval = pdl_iterbroadcastloop(&pdl_brc,0);
1547 32 50         if ( brcloopval < 0 ) die("Error in iterbroadcastloop");
1548 32 100         } while( brcloopval );
1549 10 50         FREETMPS; LEAVE;
1550 10           pdl_freebroadcaststruct(&pdl_brc);