File Coverage

lib/PDL/Core/pdlapi.c
Criterion Covered Total %
statement 834 887 94.0
branch 881 1182 74.5
condition n/a
subroutine n/a
pod n/a
total 1715 2069 82.8


line stmt bran cond sub pod time code
1             /* pdlapi.c - functions for manipulating pdl structs */
2              
3             #include "pdl.h" /* Data structure declarations */
4             #define PDL_IN_CORE
5             #include "pdlcore.h" /* Core declarations */
6              
7             extern Core PDL; /* for PDL_TYPENAME */
8              
9             /* CORE21 incorporate error in here if no vtable function */
10             #define VTABLE_OR_DEFAULT(errcall, trans, is_fwd, func, default_func) \
11             do { \
12             pdl_transvtable *vtable = (trans)->vtable; \
13             PDLDEBUG_f(printf("VTOD call " #func "(trans=%p/%s)\n", trans, vtable->name)); \
14             PDL_Indx i, istart = is_fwd ? vtable->nparents : 0, iend = is_fwd ? vtable->npdls : vtable->nparents; \
15             if (is_fwd) \
16             for (i = istart; i < iend; i++) \
17             if (trans->pdls[i]->trans_parent == trans) \
18             PDL_ENSURE_ALLOCATED(trans->pdls[i]); \
19             PDL_Indx ncheck = iend - istart + 1; \
20             PDL_BITFIELD_ENT had_badflag[PDL_BITFIELD_SIZE(ncheck)]; \
21             PDL_BITFIELD_ZEROISE(had_badflag, ncheck); \
22             for (i = istart; i < iend; i++) \
23             if ((trans)->pdls[i] && (trans)->pdls[i]->state & PDL_BADVAL) \
24             PDL_BITFIELD_SET(had_badflag, i-istart); \
25             PDLDEBUG_f(printf("had_badflag bitfield: 0b"); for (i = iend-istart; i >= 0; i--) { printf("%d", PDL_BITFIELD_ISSET(had_badflag, i)); } printf("\n");); \
26             errcall(PDL_err, (vtable->func \
27             ? vtable->func \
28             : pdl_ ## default_func)(trans)); \
29             for (i = istart; i < iend; i++) { \
30             pdl *child = (trans)->pdls[i]; \
31             PDLDEBUG_f(printf("VTOD " #func " child=%p turning off datachanged, before=", child); pdl_dump_flags_fixspace(child->state, 0, PDL_FLAGS_PDL)); \
32             if (is_fwd) child->state &= ~PDL_PARENTDATACHANGED; \
33             if (child && \
34             !!(child->state & PDL_BADVAL) != !!PDL_BITFIELD_ISSET(had_badflag, i-istart) \
35             ) \
36             pdl_propagate_badflag_dir(child, !!(child->state & PDL_BADVAL), is_fwd, 1); \
37             } \
38             } while (0)
39             #define READDATA(trans) VTABLE_OR_DEFAULT(PDL_ACCUMERROR, trans, 1, readdata, readdata_affine)
40             #define WRITEDATA(trans) VTABLE_OR_DEFAULT(PDL_ACCUMERROR, trans, 0, writebackdata, writebackdata_affine)
41              
42             #define REDODIMS(errcall, trans) do { \
43             pdl_transvtable *vtable = (trans)->vtable; \
44             if (vtable->redodims) { \
45             PDL_Indx creating[vtable->npdls]; \
46             pdl **pdls = (trans)->pdls; \
47             PDL_Indx i; \
48             for (i=0; inpdls; i++) \
49             creating[i] = (vtable->par_flags[i] & PDL_PARAM_ISCREAT) && \
50             PDL_DIMS_FROM_TRANS(trans,pdls[i]); \
51             errcall(PDL_err, pdl_dim_checks( \
52             vtable, pdls, \
53             NULL, trans->broadcast.nimpl, creating, \
54             (trans)->ind_sizes, 1)); \
55             } \
56             if ((trans)->dims_redone) { \
57             FREETRANS(trans, 0); \
58             if (PDL_err.error) return PDL_err; \
59             (trans)->dims_redone = 0; \
60             } \
61             errcall(PDL_err, (vtable->redodims \
62             ? vtable->redodims \
63             : pdl_redodims_default)(trans)); \
64             PDL_Indx i; \
65             for (i = 0; i < vtable->ninds; i++) \
66             if (trans->ind_sizes[i] < 0) \
67             PDL_ACCUMERROR(PDL_err, pdl_make_error(PDL_EUSERERROR, \
68             "%s: RedoDims gave size < 0 for dim %s", \
69             trans->vtable->name, trans->vtable->ind_names[i])); \
70             if (PDL_err.error) errcall(PDL_err, PDL_err); \
71             for (i = vtable->nparents; i < vtable->npdls; i++) { \
72             pdl *child = (trans)->pdls[i]; \
73             PDLDEBUG_f(printf("REDODIMS child=%p turning off dimschanged, before=", child); pdl_dump_flags_fixspace(child->state, 0, PDL_FLAGS_PDL)); \
74             child->state &= ~PDL_PARENTDIMSCHANGED; \
75             } \
76             } while (0)
77             #define FREETRANS(trans, destroy) \
78             if (trans->vtable->freetrans) { \
79             PDLDEBUG_f(printf("call freetrans\n")); \
80             PDL_ACCUMERROR(PDL_err, trans->vtable->freetrans(trans, destroy)); \
81             /* ignore error for now as need to still free rest */ \
82             if (destroy) PDL_CLRMAGIC(trans); \
83             }
84             #define CHANGED(...) \
85             PDL_ACCUMERROR(PDL_err, pdl_changed(__VA_ARGS__))
86              
87             extern Core PDL;
88              
89             pdl_error pdl__make_physical_recprotect(pdl *it, int recurse_count);
90             pdl_error pdl__make_physvaffine_recprotect(pdl *it, int recurse_count);
91             /* Make sure transformation is done */
92 71822           pdl_error pdl__ensure_trans(pdl_trans *trans, int what, char inputs_only, int recurse_count)
93             {
94 71822           pdl_error PDL_err = {0, NULL, 0};
95 71822 50         PDLDEBUG_f(printf("pdl__ensure_trans %p what=", trans); pdl_dump_flags_fixspace(what, 0, PDL_FLAGS_PDL));
96 71822 50         PDL_TR_CHKMAGIC(trans);
    0          
97 71822           pdl_transvtable *vtable = trans->vtable;
98 71822 100         if (trans->flags & PDL_ITRANS_ISAFFINE) {
99 3549 50         if (!(vtable->nparents == 1 && vtable->npdls == 2))
    50          
100 0           return pdl_make_error_simple(PDL_EUSERERROR, "Affine trans other than 1 input 1 output");
101 3549           return pdl__make_physical_recprotect(trans->pdls[1], recurse_count+1);
102             }
103 68273 100         PDL_Indx j, flag=what, par_pvaf=0, j_end = inputs_only ? vtable->nparents : vtable->npdls;
104 181657 100         for (j=0; j
105 113384 100         if (vtable->par_flags[j] & PDL_PARAM_ISPHYS)
106 43237 50         PDL_RETERROR(PDL_err, pdl__make_physical_recprotect(trans->pdls[j], recurse_count+1));
107             else {
108 70147 50         PDL_RETERROR(PDL_err, pdl__make_physvaffine_recprotect(trans->pdls[j], recurse_count+1));
109 70147 100         if (PDL_VAFFOK(trans->pdls[j])) par_pvaf++;
110             }
111             }
112 137773 100         for (j=vtable->nparents; jnpdls; j++)
113 69500           flag |= trans->pdls[j]->state & PDL_ANYCHANGED;
114 68273 50         PDLDEBUG_f(printf("pdl__ensure_trans after accum, par_pvaf=%"IND_FLAG" flag=", par_pvaf); pdl_dump_flags_fixspace(flag, 0, PDL_FLAGS_PDL));
115 68273 100         if (par_pvaf || flag & PDL_PARENTDIMSCHANGED)
    100          
116 128998 100         REDODIMS(PDL_RETERROR, trans); /* CORE21 change to make_physdims_recetc */
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    0          
    0          
    50          
    100          
    100          
    100          
    50          
    100          
    100          
    50          
    50          
    100          
117 68240 100         if (flag & PDL_ANYCHANGED)
118 302966 50         READDATA(trans);
    100          
    100          
    50          
    100          
    100          
    50          
    100          
    100          
    50          
    0          
    50          
    100          
    50          
    50          
    100          
    100          
119 68240           return PDL_err;
120             }
121              
122 0           pdl *pdl_null(void) {
123 0 0         PDLDEBUG_f(printf("pdl_null\n"));
124 0           return pdl_pdlnew();
125             }
126              
127 8584           pdl *pdl_scalar(PDL_Anyval anyval) {
128 8584 50         PDLDEBUG_f(printf("pdl_scalar type=%d val=", anyval.type); pdl_dump_anyval(anyval); printf("\n"););
129 8584           pdl *it = pdl_pdlnew();
130 8584 50         if (!it) return it;
131 8584           it->datatype = anyval.type;
132 8584           it->broadcastids[0] = it->ndims = 0; /* 0 dims in a scalar */
133 8584           pdl_resize_defaultincs(it);
134 8584           pdl_error PDL_err = pdl_allocdata(it);
135 8584 50         if (PDL_err.error) { pdl_destroy(it); return NULL; }
136 8584           it->value = anyval.value;
137 8584           it->state &= ~(PDL_NOMYDIMS); /* has dims */
138 8584           return it;
139             }
140              
141             pdl_error pdl__converttypei_new_recprotect(pdl *PARENT, pdl *CHILD, pdl_datatypes totype, pdl_datatypes force_intype, int recurse_count);
142 13975           pdl_error pdl__get_convertedpdl_recprotect(pdl *old, pdl **retval, pdl_datatypes type, char switch_sense, int recurse_count) {
143 13975           pdl_error PDL_err = {0, NULL, 0};
144 13975 50         PDL_RECURSE_CHECK(recurse_count);
145 13975 50         PDLDEBUG_f(printf("pdl_get_convertedpdl switch_sense=%d\n", (int)switch_sense));
146 13975 50         if (old->datatype == type) { *retval = old; return PDL_err; }
147 13975           char was_flowing = (old->state & PDL_DATAFLOW_F);
148 13975           pdl *it = pdl_pdlnew();
149 13975 50         if (!it) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
150 13975 100         if (switch_sense) {
151 22           PDL_err = pdl__converttypei_new_recprotect(it, old, old->datatype, type, recurse_count + 1);
152 22 50         if (PDL_err.error) { pdl_destroy(it); return PDL_err; }
153 22           PDL_err = pdl_setdims(it, old->dims, old->ndims);
154 22 50         if (!PDL_err.error && switch_sense > 1 && old->data) { /* NULL data = unallocated "zeroes" */
    100          
    50          
155 12 50         PDLDEBUG_f(printf("pdl_get_convertedpdl back-pump because inplace\n"));
156 12           PDL_err = pdl__make_physical_recprotect(it, recurse_count + 1);
157 48 50         if (!PDL_err.error) WRITEDATA(old->trans_parent);
    50          
    100          
    50          
    50          
    100          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
158             }
159             } else
160 13953           PDL_err = pdl__converttypei_new_recprotect(old, it, type, old->datatype, recurse_count + 1);
161 13975 50         if (PDL_err.error) { pdl_destroy(it); return PDL_err; }
162 13975 100         if (was_flowing)
163 5           it->state |= PDL_DATAFLOW_F;
164 13975           *retval = it;
165 13975           return PDL_err;
166             }
167 343           pdl *pdl_get_convertedpdl(pdl *old, pdl_datatypes type) {
168             pdl *retval;
169 343           pdl_error PDL_err = pdl__get_convertedpdl_recprotect(old, &retval, type, 0, 0);
170 343 50         return PDL_err.error ? NULL : retval;
171             }
172              
173 93393           pdl_error pdl_allocdata(pdl *it) {
174 93393           pdl_error PDL_err = {0, NULL, 0};
175 93393 50         PDLDEBUG_f(printf("pdl_allocdata %p, %"IND_FLAG", %d\n",it, it->nvals,
176             it->datatype));
177 93393 50         if (it->nvals < 0)
178 0           return pdl_make_error(PDL_EUSERERROR, "Tried to allocdata with %"IND_FLAG" values", it->nvals);
179 93393           PDL_Indx nbytes = it->nvals * pdl_howbig(it->datatype);
180 93393           PDL_Indx ncurr = it->nbytes;
181 93393 100         if (ncurr == nbytes)
182 14982           return PDL_err; /* Nothing to be done */
183 78411 100         if (it->state & PDL_DONTTOUCHDATA)
184 1           return pdl_make_error_simple(PDL_EUSERERROR, "Trying to touch data of an untouchable (mmapped?) pdl");
185 78410           char was_useheap = (ncurr > sizeof(it->value)),
186 78410           will_useheap = (nbytes > sizeof(it->value));
187 78410 100         if (!was_useheap && !will_useheap) {
    100          
188 65458           it->data = &it->value;
189 12952 100         } else if (!will_useheap) {
190             /* was heap, now not */
191 4           void *data_old = it->data;
192 4           memmove(it->data = &it->value, data_old, PDLMIN(ncurr, nbytes));
193 4           SvREFCNT_dec((SV*)it->datasv);
194 4           it->datasv = NULL;
195             } else {
196             /* now change to be heap */
197 12948 100         if (it->datasv == NULL)
198 12947           it->datasv = newSVpvn("", 0);
199 12948 50         (void)SvGROW((SV*)it->datasv, nbytes);
    50          
200 12948           SvCUR_set((SV*)it->datasv, nbytes);
201 12948 100         if (it->data && !was_useheap)
    100          
202 29           memmove(SvPV_nolen((SV*)it->datasv), it->data, PDLMIN(ncurr, nbytes));
203 12948           it->data = SvPV_nolen((SV*)it->datasv);
204             }
205 78410 100         if (nbytes > ncurr) memset(it->data + ncurr, 0, nbytes - ncurr);
206 78410           it->nbytes = nbytes;
207 78410           it->state |= PDL_ALLOCATED;
208 78410 50         PDLDEBUG_f(pdl_dump(it));
209 78410           return PDL_err;
210             }
211              
212 96930           pdl* pdl_pdlnew(void) {
213 96930           pdl *it = (pdl*) malloc(sizeof(pdl));
214 96930 50         if (!it) return it;
215 96930           memset(it, 0, sizeof(pdl));
216 96930           it->magicno = PDL_MAGICNO;
217 96930           it->datatype = PDL_D;
218 96930           it->trans_parent = NULL;
219 96930           it->vafftrans = NULL;
220 96930           it->data = it->datasv = it->sv = NULL;
221 96930           it->has_badvalue = 0;
222 96930           it->state = PDL_NOMYDIMS;
223 96930           it->dims = it->def_dims;
224 96930           it->nbytes = it->nvals = it->dims[0] = 0;
225 96930           it->dimincs = it->def_dimincs;
226 96930           it->dimincs[0] = 1;
227 96930           it->nbroadcastids = 1;
228 96930           it->broadcastids = it->def_broadcastids;
229 96930           it->broadcastids[0] = it->ndims = 1;
230 96930           it->trans_children = it->def_trans_children;
231 96930           it->ntrans_children_allocated = PDL_NCHILDREN;
232 96930           it->ntrans_children = 0;
233 96930           it->magic = 0;
234 96930           it->hdrsv = 0;
235 96930 50         PDLDEBUG_f(printf("pdl_pdlnew %p (size=%zu)\n",it,sizeof(pdl)));
236 96930           return it;
237             }
238              
239 21098           void pdl_vafftrans_free(pdl *it)
240             {
241 21098 100         if (it->vafftrans && it->vafftrans->incs)
    50          
242 21085           free(it->vafftrans->incs);
243 21098 100         if (it->vafftrans)
244 21085           free(it->vafftrans);
245 21098           it->vafftrans=0;
246 21098           it->state &= ~PDL_OPT_VAFFTRANSOK;
247 21098           }
248              
249 21087           pdl_error pdl_vafftrans_alloc(pdl *it)
250             {
251 21087           pdl_error PDL_err = {0, NULL, 0};
252 21087 100         if (!it->vafftrans) {
253 21085           it->vafftrans = malloc(sizeof(*(it->vafftrans)));
254 21085 50         if (!it->vafftrans) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
255 21085           it->vafftrans->incs = 0;
256 21085           it->vafftrans->ndims = 0;
257             }
258 21087 100         if (!it->vafftrans->incs || it->vafftrans->ndims < it->ndims ) {
    50          
259 21087 100         if (it->vafftrans->incs) free(it->vafftrans->incs);
260 21087           it->vafftrans->incs = malloc(sizeof(*(it->vafftrans->incs))
261 21087           * (size_t)it->ndims);
262 21087 50         if (!it->vafftrans->incs) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
263 21087           it->vafftrans->ndims = it->ndims;
264             }
265 21087           return PDL_err;
266             }
267              
268             /* Recursive! */
269 26965           void pdl_vafftrans_remove(pdl * it, char this_one)
270             {
271 26965 50         PDLDEBUG_f(printf("pdl_vafftrans_remove: %p, this_one=%d\n", it, (int)this_one));
272             PDL_Indx i, j;
273 188755 100         for (i = 0; i < it->ntrans_children_allocated; i++) {
274 161790           pdl_trans *t = it->trans_children[i];
275 161790 100         if (!t || !(t->flags & PDL_ITRANS_ISAFFINE)) continue;
    100          
276 52 100         for (j=t->vtable->nparents; jvtable->npdls; j++)
277 26           pdl_vafftrans_remove(t->pdls[j], 1);
278             }
279 26965 100         if (this_one) pdl_vafftrans_free(it);
280 26965           }
281              
282             /* Explicit free. Do not use, use destroy instead, which causes this
283             to be called when the time is right */
284 96868           pdl_error pdl__free(pdl *it) {
285 96868           pdl_error PDL_err = {0, NULL, 0};
286 96868 50         PDLDEBUG_f(printf("pdl__free %p\n",it));
287 96868 50         PDL_CHKMAGIC(it);
    0          
288             /* now check if magic is still there */
289 96868 100         if (pdl__ismagic(it))
290 65 50         PDLDEBUG_f(printf("%p is still magic\n",it);pdl__print_magic(it));
291 96868           it->magicno = 0x42424245;
292 96868 100         if (it->dims != it->def_dims) free(it->dims);
293 96868 100         if (it->dimincs != it->def_dimincs) free(it->dimincs);
294 96868 50         if (it->broadcastids != it->def_broadcastids) free(it->broadcastids);
295 96868 100         if (it->trans_children != it->def_trans_children) free(it->trans_children);
296 96868 50         if (it->vafftrans) {
297 0           pdl_vafftrans_free(it);
298             }
299             /* Call special freeing magic, if exists */
300 96868 100         if (PDL_ISMAGIC(it)) {
301 65           pdl__call_magic(it, PDL_MAGIC_DELETEDATA);
302 65           pdl__magic_free(it);
303             }
304 96868 100         if (it->datasv) {
305 15043 50         PDLDEBUG_f(printf("SvREFCNT_dec datasv=%p\n",it->datasv));
306 15043           SvREFCNT_dec(it->datasv);
307 15043           it->data=0;
308             }
309 96868 100         if (it->hdrsv) {
310 3745 50         PDLDEBUG_f(printf("SvREFCNT_dec hdrsv=%p\n",it->hdrsv));
311 3745           SvREFCNT_dec(it->hdrsv);
312 3745           it->hdrsv = 0;
313             }
314 96868 50         PDLDEBUG_f(printf("pdl__free end %p\n",it));
315 96868           free(it);
316 96868           return PDL_err;
317             }
318              
319             /* NULL out the pdl from the trans's inputs, and the trans from the
320             pdl's trans_children */
321 91656           void pdl__remove_pdl_as_trans_input(pdl *it,pdl_trans *trans, PDL_Indx param_ind)
322             {
323 91656           pdl_transvtable *vtable = trans->vtable;
324 91656 50         PDLDEBUG_f(printf("pdl__remove_pdl_as_trans_input(%s=%p, pdl=%p, param_ind=%td): \n",
325             vtable->name, trans, it, param_ind));
326 91656           PDL_Indx trans_children_index = trans->ind_sizes[vtable->ninds + param_ind];
327 91656 50         if (it->trans_children[trans_children_index] != trans) {
328             /* this might be due to a croak when performing the trans; so
329             warn only for now, otherwise we leave trans undestructed ! */
330 0           pdl_pdl_warn("Child not found for pdl %p, trans %p=%s\n",it, trans, vtable->name);
331 0           return;
332             }
333 91656           it->trans_children[trans_children_index] = NULL;
334 91656           it->ntrans_children--;
335 91656 100         if (trans_children_index < it->first_trans_child_available)
336 6423           it->first_trans_child_available = trans_children_index;
337             }
338              
339             /* NULL out the trans's nth pdl in/output, and this trans as pdl's
340             trans_parent */
341 83885           void pdl__remove_pdl_as_trans_output(pdl *it, pdl_trans *trans, PDL_Indx nth)
342             {
343 83885 50         PDLDEBUG_f(printf("pdl__remove_pdl_as_trans_output from %p (%s=%p): %"IND_FLAG"\n",
344             it, trans->vtable->name, trans, nth));
345 83885           trans->pdls[nth] = 0;
346 83885 100         if (it->trans_parent != trans) return; /* only do rest if trans is parent */
347 77905           it->trans_parent = 0;
348 77905 50         PDLDEBUG_f(printf("pdl__remove_pdl_as_trans_output turning off MYDIMS_TRANS and ANYCHANGED, was: "); pdl_dump_flags_fixspace(it->state, 0, PDL_FLAGS_PDL));
349 77905           it->state &= ~(PDL_MYDIMS_TRANS | PDL_ANYCHANGED);
350             }
351              
352 82663           pdl_error pdl_trans_finaldestroy(pdl_trans *trans)
353             {
354 82663           pdl_error PDL_err = {0, NULL, 0};
355 82663 50         PDLDEBUG_f(printf("pdl_trans_finaldestroy %p\n", trans));
356 105758 100         FREETRANS(trans, 1);
    50          
    50          
357 82663 100         if (trans->vtable->flags & PDL_TRANS_DO_BROADCAST)
358 33707           pdl_freebroadcaststruct(&trans->broadcast);
359 82663           trans->vtable = 0; /* Make sure no-one uses this */
360 82663 50         PDLDEBUG_f(printf("call free\n"));
361 82663 100         if (trans->params) free(trans->params);
362 82663           free(trans->ind_sizes);
363 82663           free(trans->inc_sizes);
364 82663           free(trans);
365 82663           return PDL_err;
366             }
367              
368             pdl_error pdl__destroy_recprotect(pdl *it, int recurse_count);
369 82658           pdl_error pdl_destroytransform(pdl_trans *trans, int ensure, int recurse_count)
370 82658           {
371 82658           pdl_error PDL_err = {0, NULL, 0};
372 82658 50         PDL_TR_CHKMAGIC(trans);
    0          
373             PDL_Indx j;
374 82658           pdl_transvtable *vtable = trans->vtable;
375 82658 50         if (!vtable)
376 0           return pdl_make_error(PDL_EFATAL, "ZERO VTABLE DESTTRAN 0x%p %d\n",trans,ensure);
377 82658           char ismutual = (trans->flags & PDL_ITRANS_DO_DATAFLOW_ANY);
378 82658 50         PDLDEBUG_f(printf("pdl_destroytransform %s=%p (ensure=%d ismutual=%d)\n",
379             vtable->name,trans,ensure,(int)ismutual));
380 82658 100         if (ensure)
381 11926 50         PDL_ACCUMERROR(PDL_err, pdl__ensure_trans(trans, ismutual ? 0 : PDL_PARENTDIMSCHANGED, 0, recurse_count+1));
    50          
382 82658           pdl *destbuffer[vtable->npdls];
383 82658           int ndest = 0;
384 174314 100         for (j=0; jnparents; j++) {
385 91656           pdl *parent = trans->pdls[j];
386 91656 50         if (!parent) continue;
387 91656 50         PDL_CHKMAGIC(parent);
    0          
388 91656           pdl__remove_pdl_as_trans_input(parent,trans,j);
389 91656 100         if (!(parent->state & PDL_DESTROYING) && !parent->sv) {
    100          
390 35363           parent->state |= PDL_DESTROYING; /* so no mark twice */
391 35363           destbuffer[ndest++] = parent;
392             }
393             }
394 166543 100         for (j=vtable->nparents; jnpdls; j++) {
395 83885           pdl *child = trans->pdls[j];
396 83885 50         PDL_CHKMAGIC(child);
    0          
397 83885           pdl__remove_pdl_as_trans_output(child,trans,j);
398 83885 100         if (ismutual && child->vafftrans) pdl_vafftrans_remove(child, 1);
    100          
399 83885 100         if ((!(child->state & PDL_DESTROYING) && !child->sv) ||
    100          
400 77873 50         (vtable->par_flags[j] & PDL_PARAM_ISTEMP)) {
401 6012           child->state |= PDL_DESTROYING; /* so no mark twice */
402 6012           destbuffer[ndest++] = child;
403             }
404             }
405 82658 50         PDL_ACCUMERROR(PDL_err, pdl_trans_finaldestroy(trans));
406 124033 100         for (j=0; j
407 41375           destbuffer[j]->state &= ~PDL_DESTROYING; /* safe, set by us */
408 41375 50         PDL_ACCUMERROR(PDL_err, pdl__destroy_recprotect(destbuffer[j], recurse_count+1));
409             }
410 82658 50         PDLDEBUG_f(printf("pdl_destroytransform leaving %p\n", trans));
411 82658           return PDL_err;
412             }
413              
414             /*
415             A ndarray may be
416             - a parent of something - just ensure & destroy
417             - a child of something - just ensure & destroy
418             - parent of two pdls which both propagate backwards - mustn't destroy.
419             - both parent and child at same time, to something that propagates.
420             Therefore, simple rules:
421             - allowed to destroy if
422             1. a parent with max. 1 backwards propagating transformation
423             2. a child with no trans_children
424             When an ndarray is destroyed, it must tell its trans_children and/or
425             parent.
426             */
427 116457           pdl_error pdl__destroy_recprotect(pdl *it, int recurse_count) {
428 116457           pdl_error PDL_err = {0, NULL, 0};
429 116457           int nback=0,nback2=0,nforw=0,nforw2=0;
430 116457           int nafn=0;
431 116457 50         PDL_CHKMAGIC(it);
    0          
432 116457 50         PDLDEBUG_f(printf("pdl_destroy: ");pdl_dump(it));
433 116457 50         if (it->state & PDL_DESTROYING) {
434 0 0         PDLDEBUG_f(printf(" already destroying, returning\n"));
435 0           return PDL_err;
436             }
437 116457           it->state |= PDL_DESTROYING;
438             /* Clear the sv field so that there will be no dangling ptrs */
439 116457 100         if (it->sv) {
440 75035           mg_free((SV *)it->sv);
441 75035           sv_setiv(it->sv, 0);
442 75035           it->sv = NULL;
443             }
444             /* 1. count the trans_children that do flow */
445             PDL_Indx i;
446 816533 100         for (i = 0; i < it->ntrans_children_allocated; i++) {
447 700076           pdl_trans *curt = it->trans_children[i];
448 700076 100         if (!curt) continue;
449 25691 50         PDL_TR_CHKMAGIC(curt);
    0          
450 25691 50         if (curt->flags & PDL_ITRANS_DO_DATAFLOW_F) {
451 25691           nforw++;
452             /* where more than two inputs must always be soft-destroyed */
453 25691 100         if (curt->vtable->nparents > 1) nforw2++;
454             }
455 25691 100         if (curt->flags & PDL_ITRANS_DO_DATAFLOW_B) {
456 25661           nback++;
457             /* where more than two in relationship must always be soft-destroyed */
458 25661 100         if (curt->vtable->npdls > 2) nback2++;
459             }
460 25691 100         if ((curt->flags & PDL_ITRANS_ISAFFINE) && !(curt->pdls[1]->state & PDL_ALLOCATED))
    100          
461 6992           nafn++;
462             }
463 116457           char soft_destroy = 0;
464 116457 50         PDLDEBUG_f(printf(" nba(%d, %d), nforw(%d, %d), tra(%p=%s), nafn(%d)\n",
    0          
465             nback, nback2, nforw, nforw2, it->trans_parent, it->trans_parent?it->trans_parent->vtable->name:"", nafn));
466 116457 100         if (nback2 > 0) { PDLDEBUG_f(printf(" soft_destroy: nback2=%d\n", nback2)); soft_destroy = 1; }
    50          
467 116457 100         if (nback > 1) { PDLDEBUG_f(printf(" soft_destroy: nback=%d\n", nback)); soft_destroy = 1; }
    50          
468 116457 100         if (it->trans_parent && nforw) { PDLDEBUG_f(printf(" soft_destroy: has parent and nforw=%d\n", nforw)); soft_destroy = 1; }
    100          
    50          
469 116457 100         if (nforw2 > 0) { PDLDEBUG_f(printf(" soft_destroy: nforw2=%d\n", nforw2)); soft_destroy = 1; }
    50          
470             /* Also, we do not wish to destroy if the trans_children would be larger
471             * than the parent and are currently not allocated (e.g. lags).
472             * Because this is too much work to check, we refrain from destroying
473             * for now if there is an affine child that is not allocated
474             */
475 116457 100         if (nafn) { PDLDEBUG_f(printf(" soft_destroy: nafn=%d\n", nafn)); soft_destroy = 1; }
    50          
476 116457 50         if (pdl__magic_isundestroyable(it)) {
477 0 0         PDLDEBUG_f(printf(" not destroying as magic %p\n", it));
478 0           soft_destroy = 1;
479             }
480 116457 100         if (soft_destroy) {
481 19589           it->state &= ~PDL_DESTROYING;
482 19589           return PDL_err;
483             }
484 679232 100         for (i = 0; i < it->ntrans_children_allocated; i++) {
485 582364           pdl_trans *t = it->trans_children[i];
486 582364 100         if (!t) continue;
487 6025 50         PDL_RETERROR(PDL_err, pdl_destroytransform(t, 1, recurse_count+1));
488             }
489 96868           pdl_trans *trans = it->trans_parent;
490 96868 100         if (trans)
491             /* Ensure only if there are other children! */
492 44497 50         PDL_RETERROR(PDL_err, pdl_destroytransform(trans,
493             trans->vtable->npdls - trans->vtable->nparents > 1, recurse_count+1));
494             /* Here, this is a child but has no children - fall through to hard_destroy */
495 96868 50         PDL_RETERROR(PDL_err, pdl__free(it));
496 96868 50         PDLDEBUG_f(printf("pdl_destroy end %p\n",it));
497 96868           return PDL_err;
498             }
499              
500 75082           pdl_error pdl_destroy(pdl *it) {
501 75082           return pdl__destroy_recprotect(it, 0);
502             }
503              
504             /* Straight copy, no dataflow */
505 47           pdl *pdl_hard_copy(pdl *src) {
506 47 50         PDLDEBUG_f(printf("pdl_hard_copy (src=%p): ", src));
507 47           pdl *it = pdl_pdlnew();
508 47 50         if (!it) return it;
509 47           pdl_error PDL_err = {0, NULL, 0};
510 47 50         PDL_RETERROR2(PDL_err, pdl_affine_new(src, it, 0, src->dims, src->ndims, src->dimincs, src->ndims), pdl_destroy(it); return NULL;);
511 47 50         PDLDEBUG_f(printf("pdl_hard_copy (src=%p): ", src);pdl_dump(it));
512 47           it->sv = (void *)1; /* stop sever from tidying it up */
513 47 50         PDL_RETERROR2(PDL_err, pdl_sever(it), pdl_destroy(it); return NULL;);
514 47           it->sv = NULL; /* destroyable again */
515 47           return it;
516             }
517              
518             /* Reallocate this PDL to have ndims dimensions. */
519 92995           pdl_error pdl_reallocdims(pdl *it, PDL_Indx ndims) {
520 92995           pdl_error PDL_err = {0, NULL, 0};
521 92995 100         if (it->ndims < ndims) { /* Need to realloc for more */
522 10586 50         if (it->dims != it->def_dims) free(it->dims);
523 10586 50         if (it->dimincs != it->def_dimincs) free(it->dimincs);
524 10586 100         if (ndims>PDL_NDIMS) { /* Need to malloc */
525 5 50         if (!(it->dims = malloc(ndims*sizeof(*(it->dims)))))
526 0           return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
527 5 50         if (!(it->dimincs = malloc(ndims*sizeof(*(it->dimincs))))) {
528 0           free(it->dims);
529 0           return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
530             }
531             }
532             else {
533 10581           it->dims = it->def_dims;
534 10581           it->dimincs = it->def_dimincs;
535             }
536             }
537 92995           it->ndims = ndims;
538 92995           return PDL_err;
539             }
540              
541             /* Reallocate n broadcastids. Set the new extra ones to the end */
542 104882           pdl_error pdl_reallocbroadcastids(pdl *it, PDL_Indx n) {
543 104882           pdl_error PDL_err = {0, NULL, 0};
544             PDL_Indx i;
545             PDL_Indx *olds; PDL_Indx nold;
546 104882 100         if (n <= it->nbroadcastids) {
547 104826           it->nbroadcastids = n;
548 104826           it->broadcastids[n-1] = it->ndims;
549 104826           return PDL_err;
550             }
551 56           nold = it->nbroadcastids; olds = it->broadcastids;
552 56 50         if (n > PDL_NBROADCASTIDS) {
553 0           it->broadcastids = malloc(sizeof(*(it->broadcastids))*n);
554 0 0         if (!it->broadcastids) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
555             } else {
556 56           it->broadcastids = it->def_broadcastids;
557             }
558 56           it->nbroadcastids = n;
559 56 50         if (it->broadcastids != olds) {
560 0 0         for (i=0; i
    0          
561 0           it->broadcastids[i] = olds[i];
562             }
563 56 50         if (olds != it->def_broadcastids) { free(olds); }
564 113 100         for (i=nold; inbroadcastids; i++) {
565 57           it->broadcastids[i] = it->ndims;
566             }
567 56           return PDL_err;
568             }
569              
570             /* Recalculate default increments */
571 101526           void pdl_resize_defaultincs(pdl *it) {
572 101526           PDL_Indx inc = 1, i = 0;
573 178300 100         for (i=0; indims; i++) {
574 76774           it->dimincs[i] = inc; inc *= it->dims[i];
575             }
576 101526 100         if (it->nvals != inc) /* Need to realloc only if nvals changed */
577 94314           it->state &= ~PDL_ALLOCATED;
578 101526           it->nvals = inc;
579 101526           }
580              
581             /* Init dims & incs - if *incs is NULL ignored (but space is always same for both) */
582 17654           pdl_error pdl_setdims(pdl* it, PDL_Indx * dims, PDL_Indx ndims) {
583 17654           pdl_error PDL_err = {0, NULL, 0};
584 17654 50         PDLDEBUG_f(printf("pdl_setdims %p: ", it);pdl_print_iarr(dims, ndims);printf("\n"));
585 17654 100         if (it->trans_parent)
586 1           return pdl_make_error(PDL_EUSERERROR,
587             "setdims called on %p but has trans_parent %s",
588 1           it, it->trans_parent->vtable->name
589             );
590 17653           PDL_Indx i, old_nvals = it->nvals, new_nvals = 1;
591 29544 100         for (i=0; i
592 17653 100         int what = (old_nvals == new_nvals) ? 0 : PDL_PARENTDATACHANGED;
593 17653 100         if ((it->state & PDL_NOMYDIMS) || ndims != it->ndims)
    100          
594 17591           what |= PDL_PARENTDIMSCHANGED;
595             else
596 135 100         for (i=0; i
597 88 100         if (dims[i] != it->dims[i]) { what |= PDL_PARENTDIMSCHANGED; break; }
598 17653 100         if (!what) { PDLDEBUG_f(printf("pdl_setdims NOOP\n")); return PDL_err; }
    50          
599 17606 50         PDL_RETERROR(PDL_err, pdl_reallocdims(it,ndims));
600 29432 100         for (i=0; idims[i] = dims[i];
601 17606           pdl_resize_defaultincs(it);
602 17606 50         PDL_RETERROR(PDL_err, pdl_reallocbroadcastids(it,1));
603 17606           it->broadcastids[0] = ndims;
604 17606           it->state &= ~PDL_NOMYDIMS;
605 17606 50         CHANGED(it,what,0);
606 17606           return PDL_err;
607             }
608              
609             /* This is *not* careful! */
610 47707           pdl_error pdl_setdims_careful(pdl *it)
611             {
612 47707           pdl_error PDL_err = {0, NULL, 0};
613 47707           pdl_resize_defaultincs(it);
614 47707           PDL_err = pdl_reallocbroadcastids(it,1); /* XXX For now */
615 47707           return PDL_err;
616             }
617              
618             /*CORE21 unused*/
619 0           PDL_Anyval pdl_get_offs(pdl *it, PDL_Indx offs) {
620 0           PDL_Anyval result = { PDL_INVALID, {0} };
621 0           ANYVAL_FROM_CTYPE_OFFSET(result, it->datatype, it->data, offs);
622 0           return result;
623             }
624              
625 91663           pdl_error pdl__add_pdl_as_trans_input(pdl *it,pdl_trans *trans, PDL_Indx param_ind)
626             {
627 91663           pdl_error PDL_err = {0, NULL, 0};
628 91663           pdl_transvtable *vtable = trans->vtable;
629 91663 50         PDLDEBUG_f(printf("pdl__add_pdl_as_trans_input add to %p trans=%s param_ind=%td\n", it, vtable->name, param_ind));
630 91663           PDL_Indx i, trans_children_index = 0;
631 98195 100         for (trans_children_index = it->first_trans_child_available; trans_children_index < it->ntrans_children_allocated; trans_children_index++)
632 98188 100         if (!it->trans_children[trans_children_index]) break;
633 91663 100         if (trans_children_index >= it->ntrans_children_allocated) {
634 7 50         if (it->trans_children == it->def_trans_children) {
635 7           it->trans_children = malloc(
636 7           sizeof(pdl_trans*) * (it->ntrans_children_allocated += PDL_NCHILDREN)
637             );
638 7 50         if (!it->trans_children) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
639 49 100         for (i = 0; i < PDL_NCHILDREN; i++)
640 42           it->trans_children[i] = it->def_trans_children[i];
641 49 100         for (; i < it->ntrans_children_allocated; i++)
642 42           it->trans_children[i] = NULL;
643             } else {
644 0           it->trans_children = realloc(it->trans_children,
645 0           sizeof(pdl_trans*) * (it->ntrans_children_allocated += PDL_NCHILDREN)
646             );
647 0 0         if (!it->trans_children) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
648 0 0         for (i = trans_children_index+1; i < it->ntrans_children_allocated; i++)
649 0           it->trans_children[i] = NULL;
650             }
651             }
652 91663 100         if (trans_children_index > it->first_trans_child_available)
653 6530           it->first_trans_child_available = trans_children_index;
654 91663           it->ntrans_children++;
655 91663           trans->ind_sizes[vtable->ninds + param_ind] = trans_children_index;
656 91663           it->trans_children[trans_children_index] = trans;
657 91663           return PDL_err;
658             }
659              
660 45           pdl_error pdl_prealloc_trans_children(pdl *it, PDL_Indx howmany) {
661 45           pdl_error PDL_err = {0, NULL, 0};
662 45           PDL_Indx i, oldval = it->ntrans_children_allocated;
663 45 50         if (howmany > oldval) {
664 45 100         if (it->trans_children == it->def_trans_children) {
665 42           it->trans_children = malloc(
666 42           sizeof(pdl_trans*) * (it->ntrans_children_allocated = howmany)
667             );
668 42 50         if (!it->trans_children) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
669 294 100         for (i = 0; i < PDL_NCHILDREN; i++)
670 252           it->trans_children[i] = it->def_trans_children[i];
671             } else {
672 3           it->trans_children = realloc(it->trans_children,
673 3           sizeof(pdl_trans*) * (it->ntrans_children_allocated = howmany)
674             );
675 3 50         if (!it->trans_children) return pdl_make_error_simple(PDL_EFATAL, "Out of Memory\n");
676             }
677 1159 100         for (i = oldval; i < howmany; i++)
678 1114           it->trans_children[i] = NULL;
679             }
680 45           return PDL_err;
681             }
682              
683 194402           pdl_error pdl__make_physdims_recprotect(pdl *it, int recurse_count) {
684 194402           pdl_error PDL_err = {0, NULL, 0};
685 194402 50         PDL_RECURSE_CHECK(recurse_count);
686 194402 50         if (!it) return pdl_make_error_simple(PDL_EFATAL, "make_physdims called with NULL");
687 194402 50         PDLDEBUG_f(printf("make_physdims %p state=", it);pdl_dump_flags_fixspace(it->state, 0, PDL_FLAGS_PDL));
688 194402 50         PDL_CHKMAGIC(it);
    0          
689 194402 100         if (!(it->state & PDL_PARENTDIMSCHANGED)) {
690 145060 50         PDLDEBUG_f(printf("make_physdims exit (NOP) %p\n", it));
691 145060           return PDL_err;
692             }
693 49342           pdl_trans *trans = it->trans_parent;
694 49342 50         PDLDEBUG_f(printf("make_physdims %p TRANS: ",it);pdl_dump_trans_fixspace(trans,3));
695             PDL_Indx i;
696 106132 100         for (i=0; ivtable->nparents; i++)
697 56790 100         if (trans->pdls[i]->state & PDL_PARENTDIMSCHANGED)
698 14154 50         PDL_RETERROR(PDL_err, pdl__make_physdims_recprotect(trans->pdls[i], recurse_count+1));
699 49342 50         PDLDEBUG_f(printf("make_physdims: calling redodims trans=%p on pdl=%p\n", trans, it));
700 238088 100         REDODIMS(PDL_RETERROR, trans);
    100          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    100          
    100          
    50          
    0          
    100          
    50          
    0          
    50          
    100          
701 49285 50         PDLDEBUG_f(printf("make_physdims exit pdl=%p\n", it));
702 49285           return PDL_err;
703             }
704 52165           pdl_error pdl_make_physdims(pdl *it) {
705 52165           return pdl__make_physdims_recprotect(it, 0);
706             }
707              
708 175561           static inline char _trans_forward_only(pdl *p) {
709 175561           pdl_trans *tp = p->trans_parent;
710 175561 100         return !!(tp && (tp->flags & PDL_ITRANS_DO_DATAFLOW_ANY) == PDL_ITRANS_DO_DATAFLOW_F);
    100          
711             }
712 82667           static inline pdl_error pdl_trans_flow_null_checks(pdl_trans *trans, char *disable_back) {
713 82667           pdl_error PDL_err = {0, NULL, 0};
714             PDL_Indx i;
715 82667           pdl_transvtable *vtable = trans->vtable;
716 82667           char input_forward_only = 0;
717 174334 100         for (i=0; inparents; i++) {
718 91669           pdl *parent = trans->pdls[i];
719 91669 100         if (_trans_forward_only(parent))
720 21           input_forward_only = 1;
721 91669 100         if (parent->state & PDL_NOMYDIMS && !(vtable->par_flags[i] & PDL_PARAM_ALLOW_NULL))
    100          
722 2           return pdl_make_error(PDL_EUSERERROR,
723             "Error in %s: input parameter '%s' is null",
724 2           vtable->name, vtable->par_names[i]
725             );
726             }
727 166554 100         for (; inpdls; i++) {
728 83892           pdl *child = trans->pdls[i];
729 83892 100         if (_trans_forward_only(child))
730 2           return pdl_make_error(PDL_EUSERERROR, "%s: cannot output to parameter '%s' with inward but no backward flow", vtable->name, vtable->par_names[i]);
731 83890 100         if (child->state & PDL_NOMYDIMS && !(vtable->par_flags[i] & PDL_PARAM_ISCREAT))
    100          
732 1           return pdl_make_error(PDL_EUSERERROR,
733             "Error in %s: io parameter '%s' is null",
734 1           vtable->name, vtable->par_names[i]
735             );
736             }
737 82662           *disable_back = input_forward_only;
738 82662           return PDL_err;
739             }
740              
741             /* Called with a filled pdl_trans struct.
742             * Sets the parent and trans fields of the ndarrays correctly,
743             * creating families and the like if necessary.
744             * Alternatively may just execute transformation
745             * that would require families but is not dataflowed.
746             */
747 82667           pdl_error pdl_make_trans_mutual(pdl_trans *trans)
748 82667           {
749 82667           pdl_error PDL_err = {0, NULL, 0};
750 82667 50         PDLDEBUG_f(printf("make_trans_mutual ");pdl_dump_trans_fixspace(trans,0));
751 82667           pdl_transvtable *vtable = trans->vtable;
752 82667           pdl **pdls = trans->pdls;
753 82667           PDL_Indx i, npdls=vtable->npdls, nparents=vtable->nparents;
754 82667 50         PDL_TR_CHKMAGIC(trans);
    0          
755 82667           char disable_back = 0, inputs_bad = 0;
756 248289 100         for (i=0; i
757 170334           pdl *pdl = pdls[i];
758 170334 100         if ((vtable->par_flags[i] & (PDL_PARAM_ISOUT|PDL_PARAM_ISTEMP)) ||
759 170334 100         !(pdl->state & PDL_BADVAL)) continue;
760 4712           inputs_bad = trans->bvalflag = 1;
761 4712           break;
762             }
763 82667 100         if (trans->bvalflag && (vtable->flags & PDL_TRANS_BADIGNORE)) {
    50          
764 0           pdl_pdl_warn("WARNING: %s does not handle bad values", vtable->name);
765 0           trans->bvalflag = 0; /* but still return true */
766             }
767 82667           PDL_err = pdl_trans_flow_null_checks(trans, &disable_back);
768 82667 100         if (PDL_err.error) {
769 5 50         PDL_ACCUMERROR(PDL_err, pdl_trans_finaldestroy(trans));
770 5           return PDL_err;
771             }
772 174325 100         for (i=0; i
773 91663           pdl *parent = pdls[i];
774 91663 50         PDL_RETERROR(PDL_err, pdl__add_pdl_as_trans_input(parent,trans,i));
775 91663 100         if (parent->state & PDL_DATAFLOW_F) {
776 25           parent->state &= ~PDL_DATAFLOW_F;
777 25           trans->flags |= PDL_ITRANS_DO_DATAFLOW_F;
778             }
779             }
780 82662           char dataflow = !!(trans->flags & PDL_ITRANS_DO_DATAFLOW_ANY);
781 82662 50         PDLDEBUG_f(printf("make_trans_mutual dataflow=%d disable_back=%d\n", (int)dataflow, (int)disable_back));
782 82662 100         if (dataflow && disable_back)
    100          
783 3           trans->flags &= ~PDL_ITRANS_DO_DATAFLOW_B;
784 82662           PDL_BITFIELD_ENT wasnull[PDL_BITFIELD_SIZE(npdls)];
785 165327 100         PDL_BITFIELD_ZEROISE(wasnull, npdls);
786 166551 100         for (i=nparents; i
787 83889           pdl *child = pdls[i];
788 83889 100         if (child->state & PDL_NOMYDIMS) PDL_BITFIELD_SET(wasnull, i);
789 83889 50         PDLDEBUG_f(printf("make_trans_mutual child=%p wasnull[%"IND_FLAG"]=%d\n", child, i, PDL_BITFIELD_ISSET(wasnull, i)));
790 83889 100         if (dataflow) {
791             /* This is because for "+=" (a = a + b) we must check for
792             previous parent transformations and mutate if they exist
793             if no dataflow. */
794 56427 50         PDLDEBUG_f(printf("make_trans_mutual turning on allchanged, before="); pdl_dump_flags_fixspace(child->state, 0, PDL_FLAGS_PDL));
795 56427 100         child->state |= PDL_PARENTDIMSCHANGED | ((trans->flags & PDL_ITRANS_ISAFFINE) ? 0 : PDL_PARENTDATACHANGED);
796 56427 50         PDLDEBUG_f(printf("make_trans_mutual after change="); pdl_dump_flags_fixspace(child->state, 0, PDL_FLAGS_PDL));
797             }
798 83889 100         if (!child->trans_parent || PDL_BITFIELD_ISSET(wasnull, i)) child->trans_parent = trans;
    50          
799 83889 100         if (PDL_BITFIELD_ISSET(wasnull, i))
800 70223           child->state = (child->state & ~PDL_NOMYDIMS) | PDL_MYDIMS_TRANS;
801             }
802 82662 100         if (inputs_bad)
803 9497 100         for (i=nparents; i
804 4785           pdl_propagate_badflag_dir(pdls[i], 1, 1, 1);
805 82662 100         if (!dataflow) {
806 26235 100         PDL_ACCUMERROR(PDL_err, pdl__ensure_trans(trans, PDL_PARENTDIMSCHANGED, 0, 0));
807 26235 100         if (PDL_err.error)
808 41 50         PDLDEBUG_f(printf("make_trans_mutual got error in ensure, not calling CHANGED on children\n"));
809             else
810 53597 100         for (i=vtable->nparents; inpdls; i++) {
811 27403           pdl *child = trans->pdls[i];
812 27403           char isvaffine = !!PDL_VAFFOK(child);
813 27403 50         PDLDEBUG_f(printf("make_trans_mutual isvaffine=%d wasnull=%d\n", (int)isvaffine, PDL_BITFIELD_ISSET(wasnull, i)));
814 27403 100         if (!isvaffine || PDL_BITFIELD_ISSET(wasnull, i))
    50          
815 22457 100         CHANGED(child, PDL_BITFIELD_ISSET(wasnull, i) ? PDL_PARENTDIMSCHANGED : PDL_PARENTDATACHANGED, 0);
    50          
816 27403 100         if (isvaffine)
817 4946 50         CHANGED(child->vafftrans->from,PDL_PARENTDATACHANGED,0);
818             }
819 26235 50         PDL_ACCUMERROR(PDL_err, pdl_destroytransform(trans,0,0));
820             }
821 82662 50         PDLDEBUG_f(printf("make_trans_mutual exit %p\n",trans));
822 82662           return PDL_err;
823             } /* pdl_make_trans_mutual() */
824              
825 40038           pdl_error pdl_redodims_default(pdl_trans *trans) {
826 40038           pdl_error PDL_err = {0, NULL, 0};
827 40038 50         PDLDEBUG_f(printf("pdl_redodims_default ");pdl_dump_trans_fixspace(trans,0));
828 40038           pdl_transvtable *vtable = trans->vtable;
829 40038 100         if (vtable->flags & PDL_TRANS_DO_BROADCAST) {
830 40034           PDL_Indx creating[vtable->npdls], i, j;
831 40034           pdl **pdls = trans->pdls;
832 136669 100         for (i=0; inpdls; i++)
833 131811 100         creating[i] = (vtable->par_flags[i] & PDL_PARAM_ISCREAT) &&
834 35176 100         PDL_DIMS_FROM_TRANS(trans,pdls[i]);
    100          
835 40051 100         PDL_RETERROR(PDL_err, pdl_initbroadcaststruct(2, pdls,
836             vtable->par_realdims, creating, vtable->npdls, vtable,
837             &trans->broadcast, NULL, NULL,
838             NULL, vtable->flags & PDL_TRANS_NO_PARALLEL));
839 40021 100         PDL_RETERROR(PDL_err, pdl_dim_checks(vtable, pdls, &trans->broadcast, trans->broadcast.nimpl, creating, trans->ind_sizes, 0));
840 136549 100         for (i=0; inpdls; i++) {
841 96545           PDL_Indx ninds = vtable->par_realdims[i];
842 96545           short flags = vtable->par_flags[i];
843 96545 100         if (!creating[i]) continue;
844 27621           PDL_Indx dims[PDLMAX(ninds+1, 1)];
845 41308 100         for (j=0; j
846 13687           dims[j] = trans->ind_sizes[PDL_IND_ID(vtable, i, j)];
847 27621 100         if (flags & PDL_PARAM_ISTEMP)
848 181           dims[ninds] = 1;
849 27621 50         PDL_RETERROR(PDL_err, pdl_broadcast_create_parameter(
850             &trans->broadcast,i,dims,
851             flags & PDL_PARAM_ISTEMP
852             ));
853             }
854 136549 100         for (i=0; inpdls; i++) {
855 96545           pdl *pdl = pdls[i];
856 143748 100         for (j=0; jpar_realdims[i]; j++)
857 47203           trans->inc_sizes[PDL_INC_ID(vtable,i,j)] =
858 47203 100         (pdl->ndims <= j || pdl->dims[j] <= 1) ? 0 :
    100          
859 22055 100         PDL_REPRINC(pdl,j);
860             }
861             }
862 40008           pdl_hdr_childcopy(trans);
863 40008           trans->dims_redone = 1;
864 40008           return PDL_err;
865             }
866              
867 196508           pdl_error pdl__make_physical_recprotect(pdl *it, int recurse_count) {
868 196508           pdl_error PDL_err = {0, NULL, 0};
869 196508 50         PDL_RECURSE_CHECK(recurse_count);
870 196508 50         PDLDEBUG_f(printf("make_physical %p\n",it));
871 196508           pdl_trans *trans = it->trans_parent;
872 196508 50         PDL_CHKMAGIC(it);
    0          
873 196508           if (
874 196508 100         !(it->state & PDL_ANYCHANGED) && /* unchanged and */
    100          
875 34959 100         !(trans && !(it->state & PDL_ALLOCATED) && (trans->flags & PDL_ITRANS_ISAFFINE)) /* not pure vaffine in waiting */
    100          
876             ) {
877 156907 100         PDL_ENSURE_ALLOCATED(it);
    100          
878             } else {
879 39601 50         if (!trans)
880 0           return pdl_make_error_simple(PDL_EFATAL, "PDL Not physical but doesn't have parent");
881 39601 100         if (trans->flags & PDL_ITRANS_ISAFFINE) {
882 5940 50         PDLDEBUG_f(printf("make_physical: affine\n"));
883 5940           trans->pdls[1]->state |= PDL_PARENTDATACHANGED;
884 5940 100         PDL_RETERROR(PDL_err, pdl__make_physvaffine_recprotect(it, recurse_count+1));
885             } else
886 33661 100         PDL_RETERROR(PDL_err, pdl__ensure_trans(trans,0,1,recurse_count+1));
887             }
888 196502 50         PDLDEBUG_f(printf("make_physical exiting: "); pdl_dump(it));
889 196502           return PDL_err;
890             }
891              
892 21647           pdl_error pdl_make_physical(pdl *it) {
893 21647           return pdl__make_physical_recprotect(it, 0);
894             }
895              
896             /* recursing = 0 when heading upwards, 1 when it reaches top and starts going downwards */
897 86680           pdl_error pdl_changed(pdl *it, int what, int recursing) {
898 86680           pdl_error PDL_err = {0, NULL, 0};
899             PDL_Indx i, j;
900 86680 50         PDLDEBUG_f(
901             printf("pdl_changed: entry for pdl %p recursing: %d, what=",it,recursing);
902             pdl_dump_flags_fixspace(what,0,PDL_FLAGS_PDL);
903             );
904 86680           pdl_trans *trans = it->trans_parent;
905 86680 100         if (recursing) {
906 15818 50         PDLDEBUG_f(printf("pdl_changed: adding what to state except pure vaff, currently="); pdl_dump_flags_fixspace(it->state,0,PDL_FLAGS_PDL));
907 6096 50         it->state |= !( /* neither */
908 15818           ((it->state & (PDL_OPT_VAFFTRANSOK|PDL_ALLOCATED)) == PDL_OPT_VAFFTRANSOK) || /* already pure vaff nor */
909 6096 100         (trans && !(it->state & PDL_ALLOCATED) && (trans->flags & PDL_ITRANS_ISAFFINE)) /* pure vaffine in waiting */
    100          
910 21914 100         ) ? what : what & ~PDL_PARENTDATACHANGED;
911 15818 100         if (pdl__ismagic(it)) pdl__call_magic(it,PDL_MAGIC_MARKCHANGED);
912             }
913 86680 100         if (trans && !recursing && (trans->flags & PDL_ITRANS_DO_DATAFLOW_B)
    100          
    100          
914 5732 50         && (what & PDL_PARENTDATACHANGED)) {
915 5732 100         if (it->vafftrans) {
916 132 100         if (it->state & PDL_ALLOCATED) {
917 131 50         PDLDEBUG_f(printf("pdl_changed: calling writebackdata_vaffine (pdl %p)\n",it));
918 131 50         PDL_ACCUMERROR(PDL_err, pdl_writebackdata_vaffine(it));
919             }
920 132 50         CHANGED(it->vafftrans->from,what,0);
921             } else {
922 5600 50         PDLDEBUG_f(printf("pdl_changed: calling writebackdata from vtable, triggered by pdl %p, using trans %p\n",it,trans));
923 31930 50         WRITEDATA(trans);
    100          
    50          
    100          
    100          
    50          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
924 15965 100         for (i=0; ivtable->nparents; i++) {
925 10365           pdl *pdl = trans->pdls[i];
926 10365 100         CHANGED(PDL_VAFFOK(pdl) ? pdl->vafftrans->from : pdl, what, 0);
    50          
927             }
928             }
929             } else {
930             PDL_Indx i;
931 566877 100         for (i = 0; i < it->ntrans_children_allocated; i++) {
932 485929           pdl_trans *trans = it->trans_children[i];
933 485929 100         if (!trans || !(trans->flags & PDL_ITRANS_DO_DATAFLOW_F)) continue;
    100          
934 41592 100         for (j=trans->vtable->nparents; jvtable->npdls; j++)
935 20796 50         if (trans->pdls[j] != it && (trans->pdls[j]->state & what) != what)
    100          
936 15818 50         CHANGED(trans->pdls[j],what,1);
937             }
938             }
939 86680 50         PDLDEBUG_f(printf("pdl_changed: exiting for pdl %p\n", it));
940 86680           return PDL_err;
941             }
942              
943             /* pdl_make_physvaffine can be called on *any* pdl -- vaffine or not --
944             it will call make_physical as needed on those
945             this function is the right one to call in any case if you want to
946             make only those physical (i.e. allocating their own data, etc) which
947             have to be and leave those vaffine with updated dims, etc, that do
948             have an appropriate transformation of which they are a child.
949             should probably have been called make_physcareful to point out what
950             it really does
951             */
952 128083           pdl_error pdl__make_physvaffine_recprotect(pdl *it, int recurse_count)
953             {
954 128083           pdl_error PDL_err = {0, NULL, 0};
955             PDL_Indx i,j;
956 128083 50         PDLDEBUG_f(printf("make_physvaffine %p calling ",it)); PDL_RETERROR(PDL_err, pdl__make_physdims_recprotect(it, recurse_count+1));
    100          
957 128063 100         if (!it->trans_parent || !(it->trans_parent->flags & PDL_ITRANS_ISAFFINE)) {
    100          
958 101267 50         PDLDEBUG_f(printf("make_physvaffine handing off to make_physical %p\n",it));
959 101267           return pdl__make_physical_recprotect(it, recurse_count+1);
960             }
961 26796 100         if (!it->vafftrans || it->vafftrans->ndims < it->ndims) {
    100          
962 21087 50         PDL_RETERROR(PDL_err, pdl_vafftrans_alloc(it));
963 47255 100         for (i=0; indims; i++) it->vafftrans->incs[i] = it->dimincs[i];
964 21087           it->vafftrans->offs = 0;
965 21087           pdl *current = it;
966 21087           pdl_trans *t=it->trans_parent;
967 24293           do {
968 24293 50         if (!t->incs)
969 0           return pdl_make_error(PDL_EUSERERROR, "make_physvaffine: affine trans %p has NULL incs\n", t);
970 24293           pdl *parent = t->pdls[0];
971 24293           PDL_Indx incsleft[it->ndims];
972             /* For all dimensions of the childest ndarray */
973 56507 100         for (i=0; indims; i++) {
974             /* inc = the increment at the current stage */
975 32214 100         PDL_Indx inc = it->vafftrans->incs[i], incsign = (inc >= 0 ? 1:-1), newinc = 0;
976 32214           inc *= incsign;
977             /* For all dimensions of the current ndarray */
978 83979 100         for (j=current->ndims-1; j>=0 && current->dimincs[j] != 0; j--) {
    100          
979             /* If the absolute value > this so */
980             /* we have a contribution from this dimension */
981 51765 100         if (inc < current->dimincs[j]) continue;
982             /* We used this many of this dim */
983 32066           PDL_Indx ninced = inc / current->dimincs[j];
984 32066           newinc += t->incs[j]*ninced;
985 32066           inc %= current->dimincs[j];
986             }
987 32214           incsleft[i] = incsign*newinc;
988             }
989 56507 100         for (i=0; indims; i++) it->vafftrans->incs[i] = incsleft[i];
990 24293           PDL_Indx offset_left = it->vafftrans->offs;
991 24293           PDL_Indx newinc = 0;
992 56739 100         for (j=current->ndims-1; j>=0 && current->dimincs[j] != 0; j--) {
    100          
993 32446           PDL_Indx cur_offset = offset_left / current->dimincs[j];
994 32446           offset_left -= cur_offset * current->dimincs[j];
995 32446           newinc += t->incs[j]*cur_offset;
996             }
997 24293           it->vafftrans->offs = newinc + t->offs;
998 24293           t = (current = parent)->trans_parent;
999 24293 100         } while (t && (t->flags & PDL_ITRANS_ISAFFINE) && !(current->state & PDL_ALLOCATED));
    100          
    100          
1000 21087           it->vafftrans->from = current;
1001 21087           it->state |= PDL_OPT_VAFFTRANSOK;
1002             }
1003 26796 50         PDLDEBUG_f(printf("make_physvaffine %p, physicalising final parent=%p\n", it, it->vafftrans->from));
1004 26796 50         PDL_RETERROR(PDL_err, pdl__make_physical_recprotect(it->vafftrans->from, recurse_count+1));
1005 26796 100         if (it->state & PDL_PARENTDATACHANGED) {
1006 6000           char already_allocated = (it->state & PDL_ALLOCATED);
1007 6000 100         PDL_ENSURE_ALLOCATED(it);
    50          
1008 6000 50         PDL_RETERROR(PDL_err, pdl_readdata_vaffine(it));
1009 6000 50         PDLDEBUG_f(printf("make_physvaffine pdl=%p turning off datachanged and OPT_VAFFTRANSOK, before=", it); pdl_dump_flags_fixspace(it->state, 0, PDL_FLAGS_PDL));
1010 6000           it->state &= ~(PDL_PARENTDATACHANGED|PDL_OPT_VAFFTRANSOK);
1011 6000 100         if (!already_allocated) pdl_vafftrans_remove(it, 0);
1012             }
1013 26796 50         PDLDEBUG_f(printf("make_physvaffine exit %p\n", it));
1014 26796           return PDL_err;
1015             }
1016              
1017 51996           pdl_error pdl_make_physvaffine(pdl *it)
1018             {
1019 51996           return pdl__make_physvaffine_recprotect(it, 0);
1020             }
1021              
1022 8680           pdl_error pdl_set_datatype(pdl *a, pdl_datatypes datatype)
1023             {
1024 8680           pdl_error PDL_err = {0, NULL, 0};
1025             PDL_Indx i;
1026 60754 100         for (i = 0; i < a->ntrans_children_allocated; i++) {
1027 52075 100         if (a->trans_children[i])
1028 1           return pdl_make_error_simple(PDL_EUSERERROR, "set_datatype: ndarray has child transform");
1029             }
1030 8679 100         if (a->trans_parent)
1031 1 50         PDL_RETERROR(PDL_err, pdl_destroytransform(a->trans_parent,1,0));
1032 8679 100         if (a->state & PDL_NOMYDIMS)
1033 8594           a->datatype = datatype;
1034             else
1035 85 50         PDL_RETERROR(PDL_err, pdl_converttype( a, datatype ));
1036 8679           return PDL_err;
1037             }
1038              
1039 6037           pdl_error pdl_sever(pdl *src)
1040             {
1041 6037           pdl_error PDL_err = {0, NULL, 0};
1042 6037 100         if (!src->trans_parent) return PDL_err;
1043 5900 50         PDL_RETERROR(PDL_err, pdl_make_physvaffine(src));
1044 5900 50         PDL_RETERROR(PDL_err, pdl_destroytransform(src->trans_parent,1,0));
1045 5900           return PDL_err;
1046             }
1047              
1048             /* this resembles the pdl_changed logic and maybe should be in that */
1049             #define PDL_MAYBE_PROPAGATE_BADFLAG(t, newval, is_fwd) do { \
1050             pdl_transvtable *vtable = (t)->vtable; \
1051             PDL_Indx i, istart = is_fwd ? vtable->nparents : 0, iend = is_fwd ? vtable->npdls : vtable->nparents; \
1052             for (i = istart; i < iend; i++) { \
1053             pdl *tpdl = (t)->pdls[i]; \
1054             /* make sure we propagate if changed */ \
1055             if (!!newval != !!(tpdl->state & PDL_BADVAL)) \
1056             pdl_propagate_badflag_dir(tpdl, newval, is_fwd, recurse_count + 1); \
1057             } \
1058             } while (0)
1059             /* newval = 1 means set flag, 0 means clear it */
1060 5612           pdl_error pdl_propagate_badflag_dir(pdl *it, int newval, char is_fwd, int recurse_count) {
1061 5612 50         PDL_RECURSE_CHECK(recurse_count);
1062 5612 50         PDLDEBUG_f(printf("pdl_propagate_badflag_dir pdl=%p newval=%d is_fwd=%d already=%d\n", it, newval, (int)is_fwd, !!(it->state & PDL_BADVAL)));
1063 5612           pdl_error PDL_err = {0, NULL, 0};
1064 5612 100         if (newval)
1065 5186           it->state |= PDL_BADVAL;
1066             else
1067 426           it->state &= ~PDL_BADVAL;
1068 5612           pdl_trans *tp = it->trans_parent;
1069 5612 100         if (!is_fwd) {
1070 7 100         if (tp)
1071 4 50         PDL_MAYBE_PROPAGATE_BADFLAG(tp, newval, 0);
    100          
1072             } else {
1073 5605 50         PDLDEBUG_f(printf("pdl_propagate_badflag_dir forward pdl state="); pdl_dump_flags_fixspace(it->state, 0, PDL_FLAGS_PDL));
1074             PDL_Indx j;
1075 5605           if ((
1076 5605 100         (it->state & (PDL_OPT_VAFFTRANSOK|PDL_ALLOCATED)) == PDL_OPT_VAFFTRANSOK || /* pure vaff */
    100          
1077 5029 100         (tp && !(it->state & PDL_ALLOCATED) && (tp->flags & PDL_ITRANS_ISAFFINE)) /* pure vaffine in waiting */
    100          
1078 192 100         ) && newval) /* expansive - if slice gets badflag, whole does */
1079 380 100         PDL_MAYBE_PROPAGATE_BADFLAG(tp, newval, 0);
    100          
1080 39243 100         for (j = 0; j < it->ntrans_children_allocated; j++) {
1081 33638           pdl_trans *trans = it->trans_children[j];
1082 33638 100         if (!trans) continue;
1083 456 100         PDL_MAYBE_PROPAGATE_BADFLAG(trans, newval, 1);
    100          
1084             }
1085             }
1086 5612           return PDL_err;
1087             }
1088 0           void pdl_propagate_badflag(pdl *it, int newval) { /* CORE21 get rid */
1089 0           return; /* nerfed as replaced with directional version */
1090             }
1091              
1092             /*CORE21 use pdl_error, replace fprintf*/
1093 44           void pdl_propagate_badvalue( pdl *it ) {
1094             PDL_Indx j;
1095 308 100         for (j = 0; j < it->ntrans_children_allocated; j++) {
1096 264           pdl_trans *trans = it->trans_children[j];
1097 264 100         if (!trans) continue;
1098             PDL_Indx i;
1099 4 100         for ( i = trans->vtable->nparents; i < trans->vtable->npdls; i++ ) {
1100 2           pdl *child = trans->pdls[i];
1101             PDL_Anyval typedval;
1102 2           ANYVAL_TO_ANYVAL_NEWTYPE(it->badvalue, typedval, child->datatype);
1103 2 50         if (typedval.type < 0) {
1104 0           fprintf(stderr, "propagate_badvalue: error making typedval\n");
1105 0           return;
1106             }
1107 2           child->has_badvalue = 1;
1108 2           child->badvalue = typedval;
1109             /* make sure we propagate to grandchildren, etc */
1110 2           pdl_propagate_badvalue( child );
1111             } /* for: i */
1112             }
1113             } /* pdl_propagate_badvalue */
1114              
1115             /*CORE21 unused*/
1116 0           PDL_Anyval pdl_get_badvalue( pdl_datatypes datatype ) {
1117 0           PDL_Anyval retval = { PDL_INVALID, {0} };
1118             #define X(datatype, ctype, ppsym, ...) \
1119             retval.type = datatype; retval.value.ppsym = PDL.bvals.ppsym;
1120 0           PDL_GENERICSWITCH(PDL_TYPELIST_ALL, datatype, X, return retval)
1121             #undef X
1122 0           return retval;
1123             }
1124              
1125             /*CORE21 unused*/
1126 0           PDL_Anyval pdl_get_pdl_badvalue( pdl *it ) {
1127 0 0         if (it->has_badvalue && it->badvalue.type != it->datatype)
    0          
1128 0           return (PDL_Anyval){ PDL_INVALID, {0} };
1129 0 0         return it->has_badvalue ? it->badvalue : pdl_get_badvalue( it->datatype );
1130             }
1131              
1132 82677           pdl_trans *pdl_create_trans(pdl_transvtable *vtable) {
1133 82677           size_t it_sz = sizeof(pdl_trans)+(sizeof(pdl *) * vtable->npdls);
1134 82677           pdl_trans *it = malloc(it_sz);
1135 82677 50         if (!it) return it;
1136 82677           memset(it, 0, it_sz);
1137 82677           PDL_TR_SETMAGIC(it);
1138 82677 100         if (vtable->structsize) {
1139 51035           it->params = malloc(vtable->structsize);
1140 51035 50         if (!it->params) return NULL;
1141 51035           memset(it->params, 0, vtable->structsize);
1142             }
1143 82677           it->flags = vtable->iflags;
1144 82677           it->dims_redone = 0;
1145 82677           it->bvalflag = 0;
1146 82677           it->vtable = vtable;
1147 82677           PDL_CLRMAGIC(&it->broadcast);
1148 82677           it->broadcast.inds = 0;
1149 82677           it->broadcast.gflags = 0;
1150 82677           it->ind_sizes = (PDL_Indx *)malloc(sizeof(PDL_Indx) * (
1151 82677           vtable->ninds +
1152 82677           vtable->nparents /* CORE21 make separate member "trans_children_indices" */
1153             ));
1154 82677 50         if (!it->ind_sizes) return NULL;
1155 194996 100         int i; for (i=0; ininds + vtable->nparents; i++) it->ind_sizes[i] = -1;
1156 82677           it->inc_sizes = (PDL_Indx *)malloc(sizeof(PDL_Indx) * vtable->nind_ids);
1157 82677 50         if (!it->inc_sizes) return NULL;
1158 111879 100         for (i=0; inind_ids; i++) it->inc_sizes[i] = -1;
1159 82677           it->offs = -1;
1160 82677           it->incs = NULL;
1161 82677           it->__datatype = PDL_INVALID;
1162 82677           return it;
1163             }
1164              
1165             #define PDL_TYPE_ADJUST_FROM_SUPPLIED(type, f) ( \
1166             /* opposite test/actions from convert, complex only */ \
1167             ((f) & PDL_PARAM_ISREAL && (type) < PDL_CF) ? PDLMAX(PDL_CF,(type)+PDL_CF-PDL_F) : \
1168             ((f) & PDL_PARAM_ISCOMPLEX && (type) >= PDL_CF) ? (type)-PDL_CF+PDL_F : \
1169             (type))
1170             #define PDL_TYPE_ADJUST_FROM_TRANS(ttype, f, par_type) ( \
1171             ((f) & PDL_PARAM_ISTYPED) ? \
1172             (!((f) & PDL_PARAM_ISTPLUS) ? (par_type) : PDLMAX((par_type), (ttype))) : \
1173             ((f) & (PDL_PARAM_ISREAL|PDL_PARAM_ISNOTCOMPLEX) && (ttype) >= PDL_CF) ? \
1174             (ttype) - PDL_CF + PDL_F : \
1175             ((f) & PDL_PARAM_ISCOMPLEX && (ttype) < PDL_CF) ? \
1176             PDLMAX(PDL_CF, trans_dtype + PDL_CF - PDL_F) : \
1177             (ttype))
1178 68700           static inline pdl_error pdl__transtype_select(
1179             pdl_trans *trans, pdl_datatypes *retval
1180             ) {
1181 68700           pdl_error PDL_err = {0, NULL, 0};
1182 68700           *retval = PDL_INVALID;
1183 68700           pdl_transvtable *vtable = trans->vtable;
1184 68700           PDL_Indx i, nparents = vtable->nparents;
1185 216323 100         for (i=0; inpdls; i++) {
1186 147630           pdl *pdl = trans->pdls[i];
1187 147630 100         if (i >= nparents && pdl->state & PDL_READONLY)
    100          
1188 2           return pdl_make_error(PDL_EUSERERROR,
1189             "%s error: output parameter %s is read-only",
1190 2           vtable->name, vtable->par_names[i]);
1191 147628 100         if (pdl->state & PDL_NOMYDIMS)
1192 56277           continue;
1193 91351           short flags = vtable->par_flags[i];
1194 91351           pdl_datatypes dtype = pdl->datatype;
1195 91351 100         if (flags & PDL_PARAM_ISNOTREAL && dtype < PDL_CF)
    100          
1196 2           return pdl_make_error(PDL_EUSERERROR,
1197             "%s: ndarray %s must be complex, but is type %s",
1198 2 50         vtable->name, vtable->par_names[i], PDL_TYPENAME(dtype));
    50          
    50          
1199 91350 100         if (flags & PDL_PARAM_ISNOTCOMPLEX && dtype >= PDL_CF)
    100          
1200 8           return pdl_make_error(PDL_EUSERERROR,
1201             "%s: ndarray %s must be real, but is type %s",
1202 8 50         vtable->name, vtable->par_names[i], PDL_TYPENAME(dtype));
    50          
    50          
1203             }
1204             PDL_BITFIELD_ENT type_avail[PDL_BITFIELD_SIZE(PDL_NTYPES)];
1205 206079 100         PDL_BITFIELD_ZEROISE(type_avail, PDL_NTYPES);
1206 68693           pdl_datatypes last_dtype = PDL_INVALID;
1207 1061901 100         for (i=0; vtable->gentypes[i] != PDL_INVALID; i++)
1208 993208           PDL_BITFIELD_SET(type_avail, last_dtype = vtable->gentypes[i]);
1209 68693 100         if (vtable->gentypes[0] == last_dtype) {
1210 102           *retval = vtable->gentypes[0]; /* only one allowed type, use that */
1211 102           return PDL_err;
1212             }
1213 68591           char use_last_dtype = 0;
1214 193659 100         for (i=vtable->npdls-1; i>= 0; i--) {
1215 138594           pdl *pdl = trans->pdls[i];
1216 138594           short flags = vtable->par_flags[i];
1217 138594 100         if (!(pdl->state & PDL_NOMYDIMS) &&
1218 82496 100         !(flags & (PDL_PARAM_ISIGNORE|PDL_PARAM_ISTYPED|PDL_PARAM_ISCREATEALWAYS))
1219             ) {
1220 74901 50         pdl_datatypes new_transtype = PDL_TYPE_ADJUST_FROM_SUPPLIED(pdl->datatype, flags);
    0          
    100          
    50          
1221 74901           char newtype_is_avail = PDL_BITFIELD_ISSET(type_avail, new_transtype);
1222 74901 100         if (!newtype_is_avail && new_transtype > last_dtype)
    100          
1223 118           use_last_dtype = 1;
1224 74901 50         if (new_transtype != PDL_INVALID && newtype_is_avail && *retval < new_transtype)
    100          
    100          
1225 69693           *retval = new_transtype;
1226             }
1227 138594 100         if (i == nparents && *retval != PDL_INVALID) return PDL_err;
    100          
1228             }
1229 55065 100         if (use_last_dtype || *retval == PDL_INVALID || !PDL_BITFIELD_ISSET(type_avail, *retval))
    100          
    50          
1230 249           *retval = last_dtype;
1231 55065           return PDL_err;
1232             }
1233              
1234             #define PDL_HAS_OTHER_PARENT(p, t) \
1235             ((p)->trans_parent && (p)->trans_parent != (t))
1236 82668           pdl_error pdl__set_output_type_badvalue(pdl_trans *trans, int recurse_count) {
1237 82668           pdl_error PDL_err = {0, NULL, 0};
1238 82668 50         PDL_RECURSE_CHECK(recurse_count);
1239 82668           pdl_datatypes trans_dtype = trans->__datatype;
1240 82668           pdl_transvtable *vtable = trans->vtable;
1241 82668           pdl **pdls = trans->pdls;
1242             PDL_Indx i;
1243 61068 100         char p2child_has_badvalue = (vtable->npdls == 2 && pdls[0]->has_badvalue
1244 143736 100         && (vtable->par_flags[1] & PDL_PARAM_ISCREATEALWAYS));
    100          
1245 82668 100         PDL_Anyval parent_badvalue = p2child_has_badvalue ? pdls[0]->badvalue : (PDL_Anyval){PDL_INVALID, {0}};
1246 258236 100         for (i=0; inpdls; i++) {
1247 175568           short flags = vtable->par_flags[i];
1248 175568 100         if (flags & PDL_PARAM_ISIGNORE) continue;
1249 161593           pdl *pdl = pdls[i];
1250 161593 100         if (!(pdl->state & PDL_NOMYDIMS) || PDL_HAS_OTHER_PARENT(pdl, trans)) continue;
    50          
    0          
1251 56299           pdl->badvalue = parent_badvalue;
1252 56299           pdl->has_badvalue = p2child_has_badvalue;
1253 56299 100         pdl->datatype = PDL_TYPE_ADJUST_FROM_TRANS(trans_dtype, flags, vtable->par_types[i]);
    100          
    100          
    100          
    100          
    100          
1254             }
1255 82668           return PDL_err;
1256             }
1257              
1258 68693           pdl_error pdl__type_convert(pdl_trans *trans, int recurse_count) {
1259 68693           pdl_error PDL_err = {0, NULL, 0};
1260 68693 50         PDL_RECURSE_CHECK(recurse_count);
1261 68693           pdl_datatypes trans_dtype = trans->__datatype;
1262 68693           pdl_transvtable *vtable = trans->vtable;
1263 68693           pdl **pdls = trans->pdls;
1264 68693           PDL_Indx i, nparents = vtable->nparents, nchildren = vtable->npdls - nparents;
1265 68693           PDL_Indx j, inplace_input_ind = -1, inplace_output_ind = -1;
1266 68693           PDL_BITFIELD_ENT is_inout[PDL_BITFIELD_SIZE(nchildren)];
1267 137325 100         PDL_BITFIELD_ZEROISE(is_inout, nchildren);
1268 138615 100         for (i=0; i < nchildren; i++) {
1269 69922 100         if (!(vtable->par_flags[i + nparents] & PDL_PARAM_ISCREAT)) {
1270 6091           PDL_BITFIELD_SET(is_inout, i);
1271 6091           continue;
1272             }
1273 63831           pdl *child = trans->pdls[i + nparents];
1274 139965 100         for (j=0; j < nparents; j++) {
1275 78199           pdl *parent = trans->pdls[j];
1276 78199 100         if (parent != child) continue;
1277 2065           PDL_BITFIELD_SET(is_inout, i);
1278 2065           inplace_output_ind = nparents + i, inplace_input_ind = j;
1279 2065           break;
1280             }
1281             }
1282 216308 100         for (i=vtable->npdls-1; i>=0; i--) {
1283 147616           short flags = vtable->par_flags[i];
1284 281599 50         if (flags & PDL_PARAM_ISIGNORE) continue;
1285 147616           pdl *pdl = pdls[i];
1286 147616 100         if ((pdl->state & PDL_NOMYDIMS) && !PDL_HAS_OTHER_PARENT(pdl, trans)) continue;
    50          
    0          
1287 91339 100         pdl_datatypes new_dtype = PDL_TYPE_ADJUST_FROM_TRANS(trans_dtype, flags, vtable->par_types[i]);
    100          
    100          
    100          
    100          
    50          
1288 91339 100         if (new_dtype == pdl->datatype) continue;
1289 13633 50         PDLDEBUG_f(printf("pdl_type_coerce (%s) pdl=%"IND_FLAG" from %d to %d\n", vtable->name, i, pdl->datatype, new_dtype));
1290 13633 100         if (i >= nparents && PDL_HAS_OTHER_PARENT(pdl, trans))
    100          
    50          
1291 3           return pdl_make_error(PDL_EUSERERROR,
1292             "%s: cannot convert output ndarray %s from type %s to %s with parent",
1293 1           vtable->name, vtable->par_names[i],
1294 2 50         PDL_TYPENAME(pdl->datatype), PDL_TYPENAME(new_dtype));
    50          
    50          
    50          
    50          
    50          
1295 13632 100         PDL_RETERROR(PDL_err, pdl__get_convertedpdl_recprotect(
    100          
    50          
1296             pdl, &pdl, new_dtype,
1297             (i < nparents) ? 0 : 1 + PDL_BITFIELD_ISSET(is_inout, i-nparents),
1298             recurse_count + 1
1299             ));
1300 13632 50         if (pdl->datatype != new_dtype)
1301 0           return pdl_make_error_simple(PDL_EFATAL, "type not expected value after get_convertedpdl\n");
1302 13632 100         if (i == inplace_output_ind)
1303 7           pdls[inplace_input_ind] = pdl;
1304 13632           pdls[i] = pdl;
1305             }
1306 68692           return PDL_err;
1307             }
1308              
1309             pdl_error pdl__trans_check_pdls_actual(pdl_trans *trans);
1310 68702           pdl_error pdl__type_coerce_recprotect(pdl_trans *trans, int recurse_count) {
1311 68702           pdl_error PDL_err = {0, NULL, 0};
1312 68702 50         PDL_RECURSE_CHECK(recurse_count);
1313 68702 100         PDL_RETERROR(PDL_err, pdl__trans_check_pdls_actual(trans));
1314             pdl_datatypes trans_dtype;
1315 68700 100         PDL_RETERROR(PDL_err, pdl__transtype_select(trans, &trans_dtype));
1316 68693           trans->__datatype = trans_dtype;
1317 68693 50         PDL_RETERROR(PDL_err, pdl__set_output_type_badvalue(trans, recurse_count+1));
1318 68693 100         PDL_RETERROR(PDL_err, pdl__type_convert(trans, recurse_count+1));
1319 68692           return PDL_err;
1320             }
1321 68702           pdl_error pdl_type_coerce(pdl_trans *trans) {
1322 68702           return pdl__type_coerce_recprotect(trans, 0);
1323             }
1324              
1325 0           char pdl_trans_badflag_from_inputs(pdl_trans *trans) {
1326 0           return 0; /* CORE21 get rid */
1327             }
1328              
1329 68702           pdl_error pdl__trans_check_pdls_actual(pdl_trans *trans) {
1330 68702           pdl_error PDL_err = {0, NULL, 0};
1331             PDL_Indx i;
1332 68702           pdl_transvtable *vtable = trans->vtable;
1333 68702           pdl **pdls = trans->pdls;
1334 216348 100         for (i=0; inpdls; i++) {
1335 147646 100         if (vtable->par_flags[i] & PDL_PARAM_ISTEMP)
1336 181 50         if (!(pdls[i] = pdl_pdlnew()))
1337 0           return pdl_make_error_simple(PDL_EFATAL, "Error in pdlnew");
1338 147646 50         if (!pdls[i])
1339 0           return pdl_make_error(PDL_EFATAL, "%s got NULL pointer on param %s", vtable->name, vtable->par_names[i]);
1340             }
1341 68702 100         if (vtable->flags & PDL_TRANS_OUTPUT_OTHERPAR)
1342 23 100         for (i = 0; i < vtable->npdls; i++)
1343 14 100         if (!(trans->pdls[i]->state & PDL_NOMYDIMS) && trans->pdls[i]->ndims > vtable->par_realdims[i])
    100          
1344 2           return pdl_make_error(PDL_EUSERERROR,
1345             "Can't broadcast with output OtherPars but par '%s' has %"IND_FLAG" dims, > %"IND_FLAG"!",
1346 2           vtable->par_names[i], trans->pdls[i]->ndims, vtable->par_realdims[i]
1347             );
1348 68700           return PDL_err;
1349             }
1350 0           pdl_error pdl_trans_check_pdls(pdl_trans *trans) {
1351 0           pdl_error PDL_err = {0, NULL, 0};
1352 0           return PDL_err; /* CORE21 get rid */
1353             }