File Coverage

lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.xs
Criterion Covered Total %
statement 31 31 100.0
branch 19 24 79.1
condition n/a
subroutine n/a
pod n/a
total 50 55 90.9


line stmt bran cond sub pod time code
1             /*
2             * Acme::ExtUtils::XSOne::Test::Calculator::Scientific - Scientific/advanced operations
3             */
4              
5             #include
6              
7 4           /* C helper functions for Scientific package */
8 4 100         static double sci_safe_log(double a, int *error) {
9 2           if (a <= 0.0) {
10 2           *error = 1;
11             return 0.0;
12 2           }
13 2           *error = 0;
14             return log(a);
15             }
16 4            
17 4 100         static double sci_safe_sqrt(double a, int *error) {
18 2           if (a < 0.0) {
19 2           *error = 1;
20             return 0.0;
21 2           }
22 2           *error = 0;
23             return sqrt(a);
24             }
25 4            
26             static double sci_ipow(double base, int exp) {
27 4 50         /* Integer power - faster than pow() for integer exponents */
28 4           if (exp == 0) return 1.0;
29 4 100         int neg = 0;
30 2           if (exp < 0) {
31 2           neg = 1;
32             exp = -exp;
33 4           }
34 16 100         double result = 1.0;
35 12 100         while (exp > 0) {
36 12           if (exp & 1) result *= base;
37 12           base *= base;
38             exp >>= 1;
39 4 100         }
40             return neg ? 1.0 / result : result;
41             }
42 4            
43 4 50         static double sci_combination(int n, int r) {
    50          
44 4 50         if (r > n || r < 0) return 0.0;
    50          
45 4           if (r == 0 || r == n) return 1.0;
46 12 100         double result = 1.0;
47 8           for (int i = 0; i < r; i++) {
48             result = result * (n - i) / (i + 1);
49 4           }
50             return result;
51             }
52              
53             MODULE = Acme::ExtUtils::XSOne::Test::Calculator PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator::Scientific
54              
55             PROTOTYPES: DISABLE
56              
57             double
58             power(base, exp)
59             double base
60             double exp
61             CODE:
62             RETVAL = pow(base, exp);
63             add_to_history('^', base, exp, RETVAL);
64             OUTPUT:
65             RETVAL
66              
67             double
68             sqrt_val(a)
69             double a
70             CODE:
71             if (a < 0.0) {
72             croak("Cannot take square root of negative number");
73             }
74             RETVAL = sqrt(a);
75             add_to_history('r', a, 0.5, RETVAL);
76             OUTPUT:
77             RETVAL
78              
79             double
80             cbrt_val(a)
81             double a
82             CODE:
83             RETVAL = cbrt(a);
84             add_to_history('r', a, 1.0/3.0, RETVAL);
85             OUTPUT:
86             RETVAL
87              
88             double
89             nth_root(a, n)
90             double a
91             double n
92             CODE:
93             if (n == 0.0) {
94             croak("Cannot take 0th root");
95             }
96             if (a < 0.0 && fmod(n, 2.0) == 0.0) {
97             croak("Cannot take even root of negative number");
98             }
99             RETVAL = pow(a, 1.0/n);
100             add_to_history('r', a, n, RETVAL);
101             OUTPUT:
102             RETVAL
103              
104             double
105             log_natural(a)
106             double a
107             CODE:
108             if (a <= 0.0) {
109             croak("Cannot take log of non-positive number");
110             }
111             RETVAL = log(a);
112             add_to_history('l', a, M_E, RETVAL);
113             OUTPUT:
114             RETVAL
115              
116             double
117             log10_val(a)
118             double a
119             CODE:
120             if (a <= 0.0) {
121             croak("Cannot take log of non-positive number");
122             }
123             RETVAL = log10(a);
124             add_to_history('L', a, 10, RETVAL);
125             OUTPUT:
126             RETVAL
127              
128             double
129             log_base(a, base)
130             double a
131             double base
132             CODE:
133             if (a <= 0.0 || base <= 0.0 || base == 1.0) {
134             croak("Invalid logarithm arguments");
135             }
136             RETVAL = log(a) / log(base);
137             add_to_history('L', a, base, RETVAL);
138             OUTPUT:
139             RETVAL
140              
141             double
142             exp_val(a)
143             double a
144             CODE:
145             RETVAL = exp(a);
146             add_to_history('e', a, 0, RETVAL);
147             OUTPUT:
148             RETVAL
149              
150             double
151             factorial(n)
152             int n
153             CODE:
154             if (n < 0) {
155             croak("Cannot take factorial of negative number");
156             }
157             if (n > 170) {
158             croak("Factorial overflow (max 170)");
159             }
160             RETVAL = 1.0;
161             for (int i = 2; i <= n; i++) {
162             RETVAL *= i;
163             }
164             add_to_history('!', (double)n, 0, RETVAL);
165             OUTPUT:
166             RETVAL
167              
168             double
169             ipow(base, exp)
170             double base
171             int exp
172             CODE:
173             RETVAL = sci_ipow(base, exp);
174             add_to_history('^', base, (double)exp, RETVAL);
175             OUTPUT:
176             RETVAL
177              
178             double
179             safe_sqrt(a)
180             double a
181             CODE:
182             int error;
183             RETVAL = sci_safe_sqrt(a, &error);
184             if (!error) {
185             add_to_history('r', a, 0.5, RETVAL);
186             }
187             OUTPUT:
188             RETVAL
189              
190             double
191             safe_log(a)
192             double a
193             CODE:
194             int error;
195             RETVAL = sci_safe_log(a, &error);
196             if (!error) {
197             add_to_history('l', a, M_E, RETVAL);
198             }
199             OUTPUT:
200             RETVAL
201              
202             double
203             combination(n, r)
204             int n
205             int r
206             CODE:
207             RETVAL = sci_combination(n, r);
208             add_to_history('C', (double)n, (double)r, RETVAL);
209             OUTPUT:
210             RETVAL
211              
212             double
213             permutation(n, r)
214             int n
215             int r
216             CODE:
217             if (r > n || r < 0 || n < 0) {
218             RETVAL = 0.0;
219             } else {
220             RETVAL = sci_combination(n, r);
221             for (int i = 2; i <= r; i++) {
222             RETVAL *= i;
223             }
224             }
225             add_to_history('P', (double)n, (double)r, RETVAL);
226             OUTPUT:
227             RETVAL
228              
229             void
230             import(...)
231             CODE:
232             {
233             static const char *scientific_exports[] = {
234             "power", "sqrt_val", "cbrt_val", "nth_root",
235             "log_natural", "log10_val", "log_base", "exp_val",
236             "factorial", "ipow", "safe_sqrt", "safe_log",
237             "combination", "permutation"
238             };
239             do_import(aTHX_ "Acme::ExtUtils::XSOne::Test::Calculator::Scientific",
240             scientific_exports, 14, items, ax);
241             }