File Coverage

lib/Number/Equation/XS.xs
Criterion Covered Total %
statement 115 128 89.8
branch 39 56 69.6
condition n/a
subroutine n/a
pod n/a
total 154 184 83.7


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT // we'll define thread context if necessary (faster)
2             #include "EXTERN.h" // globals/constant import locations
3             #include "perl.h" // Perl symbols, structures and constants definition
4             #include "XSUB.h" // xsubpp functions and macros
5             #include // rand()
6             #include
7              
8             double PRECISION = 0;
9             double OFFSET = 0.5555555;
10              
11 4           static SV * new (double num) {
12             dTHX;
13 4           AV * n = newAV();
14 4           av_push(n, newSVnv(num));
15 4           AV * e = newAV();
16 4           av_push(e, newSVnv(num));
17 4           av_push(n, newRV_noinc((SV*)e));
18 4           return sv_bless(newRV_noinc((SV*)n), gv_stashsv(newSVpv("Number::Equation::XS", 20), 0));
19             }
20              
21 7           static double precise (double num) {
22 7 100         if (PRECISION) {
23 3           num = num >= 0
24 3           ? PRECISION * floor(( num + ( OFFSET * PRECISION )) / PRECISION)
25 3 50         : PRECISION * ceil(( num - OFFSET * PRECISION) / PRECISION);
26             }
27 7           return num;
28             }
29              
30             MODULE = Number::Equation::XS PACKAGE = Number::Equation::XS
31             PROTOTYPES: ENABLE
32             FALLBACK: TRUE
33              
34             SV * new (...)
35             CODE:
36 4           double num = SvNV(ST(1));
37 4 50         if (ST(2) && SvOK(ST(2)) && (SvTYPE(ST(2)) == SVt_NV || SvTYPE(ST(2)) == SVt_IV)) {
    50          
    100          
    50          
38 4           PRECISION = SvNV(ST(2));
39             }
40 4 50         if (ST(3) && SvOK(ST(3)) && SvTYPE(ST(3)) == SVt_NV) {
    50          
    50          
41 0           OFFSET = SvNV(ST(3));
42             }
43 4           RETVAL = new(num);
44             OUTPUT:
45             RETVAL
46              
47              
48             SV * stringify (self, ...)
49             SV * self
50             OVERLOAD: \"\"
51             CODE:
52 2           AV * s = (AV*)SvRV(self);
53 2           double val = SvNV(*av_fetch(s, 0, 0));
54 2           RETVAL = newSVnv(precise(val));
55             OUTPUT:
56             RETVAL
57              
58              
59             SV * add (self, num, ...)
60             SV * self
61             SV * num
62             OVERLOAD: +
63             CODE:
64 1           AV * s = (AV*)SvRV(self);
65 1           AV * last = (AV*)SvRV(*av_fetch(s, -1, 0));
66 1           av_push(last, newSVpv("+", 1));
67 1           av_push(last, newSVsv(num));
68 1           double val = SvNV(*av_fetch(s, 0, 0));
69 1           val = val + SvNV(num);
70 1           av_store(s, 0, newSVnv(val));
71 1           RETVAL = newSVsv(self);
72             OUTPUT:
73             RETVAL
74              
75             SV * mult (self, num, ...)
76             SV * self
77             SV * num
78             OVERLOAD: *
79             CODE:
80 1           AV * s = (AV*)SvRV(self);
81 1           AV * last = (AV*)SvRV(*av_fetch(s, -1, 0));
82 1           av_push(last, newSVpv("*", 1));
83 1           av_push(last, newSVsv(num));
84 1           double val = SvNV(*av_fetch(s, 0, 0));
85 1           val = val * SvNV(num);
86 1           av_store(s, 0, newSVnv(val));
87 1           RETVAL = newSVsv(self);
88             OUTPUT:
89             RETVAL
90              
91             SV * subt (self, num, ...)
92             SV * self
93             SV * num
94             OVERLOAD: -
95             CODE:
96 2           AV * s = (AV*)SvRV(self);
97 2           double val = SvNV(*av_fetch(s, 0, 0));
98 2 50         if (ST(2) && SvOK(ST(2)) && SvIV(ST(2)) > 0) {
    50          
    100          
99 1           av_unshift(s, 1);
100 1           AV * n = newAV();
101 1           av_push(n, newSVsv(num));
102 1           av_push(n, newSVpv("-", 1));
103 1           av_store(s, 1, newRV_noinc((SV*)n));
104 1           val = SvNV(num) - val;
105             } else {
106 1           AV * last = (AV*)SvRV(*av_fetch(s, -1, 0));
107 1           av_push(last, newSVpv("-", 1));
108 1           av_push(last, newSVsv(num));
109 1           val = val - SvNV(num);
110             }
111 2           av_store(s, 0, newSVnv(val));
112 2           RETVAL = newSVsv(self);
113             OUTPUT:
114             RETVAL
115              
116             SV * div (self, num, ...)
117             SV * self
118             SV * num
119             OVERLOAD: /
120             CODE:
121 3           AV * s = (AV*)SvRV(self);
122 3           double val = SvNV(*av_fetch(s, 0, 0));
123 3 50         if (ST(2) && SvOK(ST(2)) && SvIV(ST(2)) > 0) {
    100          
    50          
124 1           av_unshift(s, 1);
125 1           AV * n = newAV();
126 1           av_push(n, newSVsv(num));
127 1           av_push(n, newSVpv("/", 1));
128 1           av_store(s, 1, newRV_noinc((SV*)n));
129 1           val = SvNV(num) / val;
130             } else {
131 2           AV * last = (AV*)SvRV(*av_fetch(s, -1, 0));
132 2           av_push(last, newSVpv("/", 1));
133 2           av_push(last, newSVsv(num));
134 2           val = val / SvNV(num);
135             }
136 3           av_store(s, 0, newSVnv(val));
137 3           RETVAL = newSVsv(self);
138             OUTPUT:
139             RETVAL
140              
141              
142             SV * mod (self, num, ...)
143             SV * self
144             SV * num
145             OVERLOAD: %
146             CODE:
147 1           AV * s = (AV*)SvRV(self);
148 1           long val = SvIV(*av_fetch(s, 0, 0));
149 1 50         if (ST(2) && SvOK(ST(2)) && SvIV(ST(2)) > 0) {
    50          
    50          
150 0           av_unshift(s, 1);
151 0           AV * n = newAV();
152 0           av_push(n, newSVsv(num));
153 0           av_push(n, newSVpv("%", 1));
154 0           av_store(s, 1, newRV_noinc((SV*)n));
155 0           val = SvIV(num) % val;
156             } else {
157 1           AV * last = (AV*)SvRV(*av_fetch(s, -1, 0));
158 1           av_push(last, newSVpv("%", 1));
159 1           av_push(last, newSVsv(num));
160 1           val = val % SvIV(num);
161             }
162 1           av_store(s, 0, newSVnv(val));
163 1           RETVAL = newSVsv(self);
164             OUTPUT:
165             RETVAL
166              
167             SV * exp (self, num, ...)
168             SV * self
169             SV * num
170             OVERLOAD: **
171             CODE:
172 1           AV * s = (AV*)SvRV(self);
173 1           double val = SvNV(*av_fetch(s, 0, 0));
174 1 50         if (ST(2) && SvOK(ST(2)) && SvIV(ST(2)) > 0) {
    50          
    50          
175 0           av_unshift(s, 1);
176 0           AV * n = newAV();
177 0           av_push(n, newSVsv(num));
178 0           av_push(n, newSVpv("**", 2));
179 0           av_store(s, 1, newRV_noinc((SV*)n));
180 0           val = pow(SvNV(num), val);
181             } else {
182 1           AV * last = (AV*)SvRV(*av_fetch(s, -1, 0));
183 1           av_push(last, newSVpv("**", 2));
184 1           av_push(last, newSVsv(num));
185 1           val = pow(val, SvNV(num));
186             }
187 1           av_store(s, 0, newSVnv(val));
188 1           RETVAL = newSVsv(self);
189             OUTPUT:
190             RETVAL
191              
192              
193             SV * equation (self, ...)
194             SV * self
195             CODE:
196             STRLEN retlen;
197 5           AV * s = (AV*)SvRV(self);
198 5           char query[4321] = "";
199 5           int closing = 0;
200 5           int l = av_len(s);
201 13 100         for (int i = 1; i <= l; i++) {
202 8           AV * equation = (AV*)SvRV(*av_fetch(s, i, 0));
203 8           int el = av_len(equation) + 1;
204 22 100         for (int x = 0; x < el / 2; x++) {
205 14           strcat(query, "(");
206             }
207 8           strcat(query, SvPV(*av_fetch(equation, 0, 0), retlen));
208 22 100         for (int x = 1; x <= el - 1; x++) {
209 14           char * operator = SvPV(*av_fetch(equation, x, 0), retlen);
210 14           x++;
211 14 100         char * val = x <= el - 1 ? SvPV(*av_fetch(equation, x, 0), retlen) : "";
212 14           strcat(query, " ");
213 14           strcat(query, operator);
214 14           strcat(query, " ");
215 14 100         if (val != "") {
216 11           strcat(query, val);
217 11           strcat(query, ")");
218             } else {
219 3           closing++;
220             }
221             }
222             }
223              
224 8 100         for (int x = 0; x < closing; x++) {
225 3           strcat(query, ")");
226             }
227              
228 5 100         if (PRECISION) {
229 3           strcat(query, " ≈ ");
230             } else {
231 2           strcat(query, " = ");
232             }
233              
234 5           double p = precise(SvNV(*av_fetch(s, 0, 0)));
235 5           SV * fun = newSVnv(p);
236 5           strcat(query, SvPV(fun, retlen));
237              
238 5           RETVAL = newSVpv(query, strlen(query));
239             OUTPUT:
240             RETVAL