Acme-ExtUtils-XSOne-Test-Calculator
view release on metacpan or search on metacpan
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.xs view on Meta::CPAN
/*
* Acme::ExtUtils::XSOne::Test::Calculator::Scientific - Scientific/advanced operations
*/
#include <math.h>
/* C helper functions for Scientific package */
static double sci_safe_log(double a, int *error) {
if (a <= 0.0) {
*error = 1;
return 0.0;
}
*error = 0;
return log(a);
}
static double sci_safe_sqrt(double a, int *error) {
if (a < 0.0) {
*error = 1;
return 0.0;
}
*error = 0;
return sqrt(a);
}
static double sci_ipow(double base, int exp) {
/* Integer power - faster than pow() for integer exponents */
if (exp == 0) return 1.0;
int neg = 0;
if (exp < 0) {
neg = 1;
exp = -exp;
}
double result = 1.0;
while (exp > 0) {
if (exp & 1) result *= base;
base *= base;
exp >>= 1;
}
return neg ? 1.0 / result : result;
}
static double sci_combination(int n, int r) {
if (r > n || r < 0) return 0.0;
if (r == 0 || r == n) return 1.0;
double result = 1.0;
for (int i = 0; i < r; i++) {
result = result * (n - i) / (i + 1);
}
return result;
}
MODULE = Acme::ExtUtils::XSOne::Test::Calculator PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator::Scientific
PROTOTYPES: DISABLE
double
power(base, exp)
double base
double exp
CODE:
RETVAL = pow(base, exp);
add_to_history('^', base, exp, RETVAL);
OUTPUT:
RETVAL
double
sqrt_val(a)
double a
CODE:
if (a < 0.0) {
croak("Cannot take square root of negative number");
}
RETVAL = sqrt(a);
add_to_history('r', a, 0.5, RETVAL);
OUTPUT:
RETVAL
double
cbrt_val(a)
double a
CODE:
RETVAL = cbrt(a);
add_to_history('r', a, 1.0/3.0, RETVAL);
OUTPUT:
RETVAL
double
nth_root(a, n)
double a
double n
CODE:
if (n == 0.0) {
croak("Cannot take 0th root");
}
if (a < 0.0 && fmod(n, 2.0) == 0.0) {
croak("Cannot take even root of negative number");
}
RETVAL = pow(a, 1.0/n);
add_to_history('r', a, n, RETVAL);
OUTPUT:
RETVAL
double
log_natural(a)
double a
CODE:
if (a <= 0.0) {
croak("Cannot take log of non-positive number");
}
RETVAL = log(a);
add_to_history('l', a, M_E, RETVAL);
OUTPUT:
RETVAL
double
log10_val(a)
double a
CODE:
if (a <= 0.0) {
croak("Cannot take log of non-positive number");
}
RETVAL = log10(a);
add_to_history('L', a, 10, RETVAL);
OUTPUT:
RETVAL
double
log_base(a, base)
double a
double base
CODE:
if (a <= 0.0 || base <= 0.0 || base == 1.0) {
croak("Invalid logarithm arguments");
}
RETVAL = log(a) / log(base);
add_to_history('L', a, base, RETVAL);
OUTPUT:
RETVAL
double
exp_val(a)
double a
CODE:
RETVAL = exp(a);
add_to_history('e', a, 0, RETVAL);
OUTPUT:
RETVAL
double
factorial(n)
int n
CODE:
if (n < 0) {
croak("Cannot take factorial of negative number");
}
if (n > 170) {
croak("Factorial overflow (max 170)");
}
RETVAL = 1.0;
for (int i = 2; i <= n; i++) {
RETVAL *= i;
}
add_to_history('!', (double)n, 0, RETVAL);
OUTPUT:
RETVAL
double
ipow(base, exp)
double base
int exp
CODE:
RETVAL = sci_ipow(base, exp);
add_to_history('^', base, (double)exp, RETVAL);
OUTPUT:
RETVAL
double
safe_sqrt(a)
double a
CODE:
int error;
RETVAL = sci_safe_sqrt(a, &error);
if (!error) {
add_to_history('r', a, 0.5, RETVAL);
}
OUTPUT:
RETVAL
double
safe_log(a)
double a
CODE:
int error;
RETVAL = sci_safe_log(a, &error);
if (!error) {
add_to_history('l', a, M_E, RETVAL);
}
OUTPUT:
RETVAL
double
combination(n, r)
int n
int r
CODE:
RETVAL = sci_combination(n, r);
add_to_history('C', (double)n, (double)r, RETVAL);
OUTPUT:
RETVAL
double
permutation(n, r)
int n
int r
CODE:
if (r > n || r < 0 || n < 0) {
RETVAL = 0.0;
} else {
RETVAL = sci_combination(n, r);
for (int i = 2; i <= r; i++) {
RETVAL *= i;
}
}
add_to_history('P', (double)n, (double)r, RETVAL);
OUTPUT:
RETVAL
void
import(...)
CODE:
{
static const char *scientific_exports[] = {
"power", "sqrt_val", "cbrt_val", "nth_root",
"log_natural", "log10_val", "log_base", "exp_val",
"factorial", "ipow", "safe_sqrt", "safe_log",
"combination", "permutation"
};
do_import(aTHX_ "Acme::ExtUtils::XSOne::Test::Calculator::Scientific",
scientific_exports, 14, items, ax);
}
( run in 0.420 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )