File Coverage

/usr/local/lib/perl5/site_perl/5.42.0/x86_64-linux/PDL/Core/pdlperl.h
Criterion Covered Total %
statement 10 19 52.6
branch 4 14 28.5
condition n/a
subroutine n/a
pod n/a
total 14 33 42.4


line stmt bran cond sub pod time code
1             #ifndef __PDLPERL_H
2             #define __PDLPERL_H
3              
4             #define PDL_XS_PREAMBLE(nret) \
5             char *objname = "PDL"; /* XXX maybe that class should actually depend on the value set \
6             by pp_bless ? (CS) */ \
7             HV *bless_stash = 0; \
8             SV *parent = 0; \
9             int nreturn = (nret); \
10             (void)nreturn; \
11             /* Check if you can get a package name for this input value. */ \
12             /* It can be either a PDL (SVt_PVMG) or a hash which is a */ \
13             /* derived PDL subclass (SVt_PVHV) */ \
14             do { \
15             if (SvROK(ST(0)) && ((SvTYPE(SvRV(ST(0))) == SVt_PVMG) || (SvTYPE(SvRV(ST(0))) == SVt_PVHV))) { \
16             parent = ST(0); \
17             if (sv_isobject(parent)){ \
18             bless_stash = SvSTASH(SvRV(parent)); \
19             objname = HvNAME((bless_stash)); /* The package to bless output vars into is taken from the first input var */ \
20             } \
21             } \
22             } while (0)
23              
24 13           static inline pdl *PDL_XS_pdlinit(pTHX_ char *objname, HV *bless_stash, SV *to_push, char *method, SV **svp, Core *core) {
25 13           dSP;
26             pdl *ret;
27 13 50         if (strcmp(objname,"PDL") == 0) { /* shortcut if just PDL */
28 13           ret = core->pdlnew();
29 13 50         if (!ret) core->pdl_barf("Error making null pdl");
30 13 50         if (svp) {
31 13           *svp = sv_newmortal();
32 13           core->SetSV_PDL(*svp, ret);
33 13 50         if (bless_stash) *svp = sv_bless(*svp, bless_stash);
34             }
35             } else {
36 0 0         PUSHMARK(SP);
37 0 0         XPUSHs(to_push);
38 0           PUTBACK;
39 0           perl_call_method(method, G_SCALAR);
40 0           SPAGAIN;
41 0           SV *sv = POPs;
42 0           PUTBACK;
43 0           ret = core->SvPDLV(sv);
44 0 0         if (svp) *svp = sv;
45             }
46 13           return ret;
47             }
48             #define PDL_XS_PERLINIT_initsv(sv) \
49             PDL_XS_pdlinit(aTHX_ objname, bless_stash, parent ? parent : sv_2mortal(newSVpv(objname, 0)), "initialize", &sv, PDL)
50              
51             #define PDL_XS_RETURN(clause1) \
52             if (nreturn) { \
53             if (nreturn > 0) EXTEND (SP, nreturn); \
54             clause1; \
55             XSRETURN(nreturn); \
56             } else { \
57             if (GIMME_V == G_SCALAR) XSRETURN_UNDEF; /* GH#551 */ \
58             else XSRETURN(0); \
59             }
60              
61             #define PDL_IS_INPLACE(in) ((in)->state & PDL_INPLACE)
62             #define PDL_XS_INPLACE(in, out) \
63             if (PDL_IS_INPLACE(in)) { \
64             if (out ## _SV) barf("inplace input but different output given"); \
65             out ## _SV = sv_newmortal(); \
66             in->state &= ~PDL_INPLACE; \
67             out = in; \
68             PDL->SetSV_PDL(out ## _SV,out); \
69             } else \
70             out = out ## _SV ? PDL_CORE_(SvPDLV)(out ## _SV) : \
71             PDL_XS_PERLINIT_initsv(out ## _SV);
72              
73             #define PDL_XS_SCALAR(thistype, ppsym, val) \
74             PDL_Anyval av = {PDL_CLD, {.H=0}}; /* guarantee all bits set */ \
75             av.type = thistype; av.value.ppsym=val; \
76             pdl *b = pdl_scalar(av); \
77             if (!b) XSRETURN_UNDEF; \
78             SV *b_SV = sv_newmortal(); \
79             pdl_SetSV_PDL(b_SV, b); \
80             EXTEND(SP, 1); \
81             ST(0) = b_SV; \
82             XSRETURN(1);
83              
84             #define PDL_MAKE_PERL_COMPLEX(output,r,i) { \
85             dSP; NV rval = r, ival = i; \
86             perl_require_pv("PDL/Complex/Overloads.pm"); \
87             ENTER; SAVETMPS; \
88             PUSHMARK(SP); mXPUSHn(rval); mXPUSHn(ival); PUTBACK; \
89             int count = perl_call_pv("PDL::Complex::Overloads::cplx", G_SCALAR); \
90             SPAGAIN; \
91             if (count != 1) croak("Failed to create PDL::Complex::Overloads object (%.9" NVgf ", %.9" NVgf ")", rval, ival); \
92             sv_setsv(output, POPs); \
93             PUTBACK; \
94             FREETMPS; LEAVE; \
95             }
96              
97             /***************
98             * So many ways to be undefined...
99             */
100             #define PDL_SV_IS_UNDEF(sv) ( (!(sv) || ((sv)==&PL_sv_undef)) || !(SvNIOK(sv) || (SvTYPE(sv)==SVt_PVMG) || SvPOK(sv) || SvROK(sv)))
101              
102             #define ANYVAL_FROM_SV(outany,insv,use_undefval,forced_type,warn_undef) do { \
103             SV *sv2 = insv; \
104             if (PDL_SV_IS_UNDEF(sv2)) { \
105             if (!use_undefval) { \
106             outany.type = forced_type >=0 ? forced_type : -1; \
107             outany.value.H = 0; \
108             break; \
109             } \
110             sv2 = get_sv("PDL::undefval",1); \
111             if ((warn_undef) && SvIV(get_sv("PDL::debug",1))) \
112             fprintf(stderr,"Warning: SvPDLV converted undef to $PDL::undefval (%"NVgf").\n",SvNV(sv2)); \
113             if (PDL_SV_IS_UNDEF(sv2)) { \
114             outany.type = forced_type >=0 ? forced_type : PDL_B; \
115             outany.value.H = 0; \
116             break; \
117             } \
118             } \
119             if (SvROK(sv2)) { \
120             if (sv_derived_from(sv2, "PDL")) { \
121             pdl *it = PDL_CORE_(SvPDLV)(sv2); \
122             outany.type = PDL_INVALID; \
123             if (it->nvals == 1) \
124             ANYVAL_FROM_CTYPE_OFFSET(outany, it->datatype, PDL_REPRP(it), PDL_REPROFFS(it)); \
125             if (outany.type < 0) PDL_CORE_(pdl_barf)("Position out of range"); \
126             break; \
127             } \
128             if (sv_derived_from(sv2, "Math::Complex")) { \
129             ANYVAL_FROM_MCOMPLEX(outany, sv2); \
130             break; \
131             } \
132             PDL_CORE_(pdl_barf)("Can't convert ref '%s' to Anyval", sv_reftype(SvRV(sv2), 1)); \
133             } else if (!SvIOK(sv2)) { /* Perl Double (e.g. 2.0) */ \
134             NV tmp_NV = SvNV(sv2); \
135             int datatype = forced_type >=0 ? forced_type : _pdl_whichdatatype_double(tmp_NV); \
136             ANYVAL_FROM_CTYPE(outany, datatype, tmp_NV); \
137             } else if (SvIsUV(sv2)) { /* Perl unsigned int */ \
138             UV tmp_UV = SvUV(sv2); \
139             int datatype = forced_type >=0 ? forced_type : _pdl_whichdatatype_uint(tmp_UV); \
140             ANYVAL_FROM_CTYPE(outany, datatype, tmp_UV); \
141             } else { /* Perl Int (e.g. 2) */ \
142             IV tmp_IV = SvIV(sv2); \
143             int datatype = forced_type >=0 ? forced_type : _pdl_whichdatatype_int(tmp_IV); \
144             ANYVAL_FROM_CTYPE(outany, datatype, tmp_IV); \
145             } \
146             } while (0)
147              
148             /* only to CD, same as whichdatatype_double only D. only if know is M:C */
149             #define ANYVAL_FROM_MCOMPLEX(outany,insv) do { \
150             dSP; \
151             int i; \
152             double vals[2]; \
153             char *meths[] = { "Re", "Im" }; \
154             ENTER; SAVETMPS; \
155             for (i = 0; i < 2; i++) { \
156             PUSHMARK(SP); XPUSHs(insv); PUTBACK; \
157             int count = perl_call_method(meths[i], G_SCALAR); \
158             SPAGAIN; \
159             if (count != 1) PDL_CORE_(pdl_barf)("Failed Math::Complex method '%s'", meths[i]); \
160             vals[i] = (double)POPn; \
161             PUTBACK; \
162             } \
163             FREETMPS; LEAVE; \
164             outany.type = PDL_CD; \
165             outany.value.C = (PDL_CDouble)(vals[0] + I * vals[1]); \
166             } while (0)
167              
168             #define ANYVAL_UNSIGNED_X(outsv, inany, sym, ctype, ppsym, ...) \
169             sv_setuv(outsv, (UV)(inany.value.ppsym));
170             #define ANYVAL_SIGNED_X(outsv, inany, sym, ctype, ppsym, ...) \
171             sv_setiv(outsv, (IV)(inany.value.ppsym));
172             #define ANYVAL_FLOATREAL_X(outsv, inany, sym, ctype, ppsym, ...) \
173             sv_setnv(outsv, (NV)(inany.value.ppsym));
174             #define ANYVAL_COMPLEX_X(outsv, inany, sym, ctype, ppsym, shortctype, defbval, realctype, convertfunc, floatsuffix, ...) \
175             PDL_MAKE_PERL_COMPLEX(outsv, creal ## floatsuffix(inany.value.ppsym), cimag ## floatsuffix(inany.value.ppsym));
176             #define ANYVAL_TO_SV(outsv,inany) do { switch (inany.type) { \
177             PDL_TYPELIST_UNSIGNED(PDL_GENERICSWITCH_CASE, ANYVAL_UNSIGNED_X, (outsv,inany,),) \
178             PDL_TYPELIST_SIGNED(PDL_GENERICSWITCH_CASE, ANYVAL_SIGNED_X, (outsv,inany,),) \
179             PDL_TYPELIST_FLOATREAL(PDL_GENERICSWITCH_CASE, ANYVAL_FLOATREAL_X, (outsv,inany,),) \
180             PDL_TYPELIST_COMPLEX(PDL_GENERICSWITCH_CASE, ANYVAL_COMPLEX_X, (outsv,inany,),) \
181             default: outsv = &PL_sv_undef; \
182             } \
183             } while (0)
184              
185             /* Check minimum datatype required to represent number */
186             #define PDL_TESTTYPE(sym, ctype, v) {ctype foo = v; if (v == foo) return sym;}
187             static inline int _pdl_whichdatatype_uint(UV uv) {
188             #define X(sym, ctype, ...) PDL_TESTTYPE(sym, ctype, uv)
189             PDL_TYPELIST_UNSIGNED(X)
190             #undef X
191             croak("Something's gone wrong: %llu cannot be converted by whichdatatype", (unsigned long long)uv);
192             }
193             static inline int _pdl_whichdatatype_int(IV iv) {
194             #define X(sym, ctype, ...) PDL_TESTTYPE(sym, ctype, iv)
195             PDL_TYPELIST_SIGNED(X)
196             #undef X
197             croak("Something's gone wrong: %lld cannot be converted by whichdatatype", (long long)iv);
198             }
199             /* Check minimum, at least double, datatype required to represent number */
200             static inline int _pdl_whichdatatype_double(NV nv) {
201             PDL_TESTTYPE(PDL_D,PDL_Double, nv)
202             PDL_TESTTYPE(PDL_D,PDL_LDouble, nv)
203             #undef PDL_TESTTYPE
204             return PDL_D; /* handles NaN */
205             }
206              
207             /* __PDLPERL_H */
208             #endif