Acme-ExtUtils-XSOne-Test-Calculator
view release on metacpan or search on metacpan
Calculator.xs view on Meta::CPAN
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;
}
/* C code from: Calculator/Trig.xs */
#line 1 "lib/Acme/ExtUtils/XSOne/Test/Calculator/Trig.xs"
/*
* Acme::ExtUtils::XSOne::Test::Calculator::Trig - Trigonometric functions
*/
/* C helper functions for Trig package */
static double trig_normalize_angle(double radians) {
/* Normalize angle to [-PI, PI] */
while (radians > M_PI) radians -= 2.0 * M_PI;
while (radians < -M_PI) radians += 2.0 * M_PI;
return radians;
}
static int trig_is_valid_asin_arg(double x) {
return (x >= -1.0 && x <= 1.0);
}
static double trig_sec(double x) {
return 1.0 / cos(x);
}
static double trig_csc(double x) {
return 1.0 / sin(x);
}
static double trig_cot(double x) {
return cos(x) / sin(x);
}
/* C code from: _footer.xs */
#line 1 "lib/Acme/ExtUtils/XSOne/Test/_footer.xs"
/*
* Acme::ExtUtils::XSOne::Test::Calculator - Main module and BOOT section
*/
/* ========== END COMBINED C PREAMBLE ========== */
MODULE = Acme::ExtUtils::XSOne::Test::Calculator PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator::Basic
PROTOTYPES: DISABLE
double
add(a, b)
double a
double b
CODE:
RETVAL = a + b;
add_to_history('+', a, b, RETVAL);
OUTPUT:
RETVAL
double
subtract(a, b)
double a
double b
CODE:
RETVAL = a - b;
add_to_history('-', a, b, RETVAL);
OUTPUT:
RETVAL
double
multiply(a, b)
double a
double b
CODE:
RETVAL = a * b;
add_to_history('*', a, b, RETVAL);
OUTPUT:
RETVAL
double
divide(a, b)
double a
double b
CODE:
if (b == 0.0) {
croak("Division by zero");
}
RETVAL = a / b;
add_to_history('/', a, b, RETVAL);
OUTPUT:
RETVAL
double
modulo(a, b)
double a
double b
CODE:
if (b == 0.0) {
croak("Modulo by zero");
}
RETVAL = fmod(a, b);
add_to_history('%', a, b, RETVAL);
OUTPUT:
RETVAL
double
negate(a)
double a
CODE:
RETVAL = -a;
add_to_history('n', a, 0, RETVAL);
OUTPUT:
RETVAL
double
absolute(a)
double a
CODE:
RETVAL = fabs(a);
add_to_history('a', a, 0, RETVAL);
OUTPUT:
RETVAL
double
safe_divide(a, b)
double a
double b
CODE:
int error;
RETVAL = basic_safe_divide(a, b, &error);
if (error) {
RETVAL = 0.0; /* Return 0 instead of croak */
}
add_to_history('/', a, b, RETVAL);
OUTPUT:
RETVAL
double
clamp(value, min_val, max_val)
double value
double min_val
double max_val
CODE:
RETVAL = basic_clamp(value, min_val, max_val);
OUTPUT:
RETVAL
double
percent(value, pct)
double value
double pct
CODE:
RETVAL = basic_percent(value, pct);
add_to_history('%', value, pct, RETVAL);
OUTPUT:
RETVAL
void
import(...)
CODE:
{
static const char *basic_exports[] = {
"add", "subtract", "multiply", "divide", "modulo",
"negate", "absolute", "safe_divide", "clamp", "percent"
};
do_import(aTHX_ "Acme::ExtUtils::XSOne::Test::Calculator::Basic",
basic_exports, 10, items, ax);
}
MODULE = Acme::ExtUtils::XSOne::Test::Calculator PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator::Memory
PROTOTYPES: DISABLE
int
store(slot, value)
int slot
double value
CODE:
RETVAL = store_memory(slot, value);
if (!RETVAL) {
warn("Invalid memory slot %d (valid: 0-%d)", slot, MAX_MEMORY_SLOTS - 1);
}
OUTPUT:
RETVAL
double
recall(slot)
int slot
CODE:
if (slot < 0 || slot >= MAX_MEMORY_SLOTS) {
warn("Invalid memory slot %d (valid: 0-%d)", slot, MAX_MEMORY_SLOTS - 1);
RETVAL = 0.0;
} else {
RETVAL = recall_memory(slot);
}
OUTPUT:
RETVAL
void
clear()
CODE:
clear_all_memory();
double
ans()
CODE:
RETVAL = get_last_result();
OUTPUT:
RETVAL
int
history_count()
CODE:
RETVAL = history_count;
OUTPUT:
RETVAL
void
get_history_entry(index)
int index
PPCODE:
if (index < 0 || index >= history_count) {
croak("Invalid history index %d (valid: 0-%d)", index, history_count - 1);
}
EXTEND(SP, 4);
PUSHs(sv_2mortal(newSVpvf("%c", history[index].operation)));
PUSHs(sv_2mortal(newSVnv(history[index].operand1)));
PUSHs(sv_2mortal(newSVnv(history[index].operand2)));
PUSHs(sv_2mortal(newSVnv(history[index].result)));
int
max_memory_slots()
CODE:
RETVAL = MAX_MEMORY_SLOTS;
OUTPUT:
RETVAL
int
max_history_entries()
CODE:
RETVAL = MAX_HISTORY;
OUTPUT:
RETVAL
int
is_valid_slot(slot)
int slot
CODE:
RETVAL = mem_is_valid_slot(slot);
OUTPUT:
RETVAL
int
used_slots()
CODE:
RETVAL = mem_get_used_slots();
OUTPUT:
RETVAL
double
sum_all_slots()
CODE:
RETVAL = mem_sum_all();
OUTPUT:
RETVAL
void
add_to(slot, value)
int slot
double value
CODE:
mem_add_to_slot(slot, value);
void
import(...)
CODE:
{
static const char *memory_exports[] = {
"store", "recall", "clear", "ans",
"history_count", "get_history_entry",
"max_memory_slots", "max_history_entries",
"is_valid_slot", "used_slots", "sum_all_slots", "add_to"
};
do_import(aTHX_ "Acme::ExtUtils::XSOne::Test::Calculator::Memory",
memory_exports, 12, items, ax);
}
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);
}
MODULE = Acme::ExtUtils::XSOne::Test::Calculator PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator::Trig
PROTOTYPES: DISABLE
double
sin_val(a)
double a
CODE:
RETVAL = sin(a);
add_to_history('s', a, 0, RETVAL);
OUTPUT:
RETVAL
double
cos_val(a)
double a
CODE:
RETVAL = cos(a);
add_to_history('c', a, 0, RETVAL);
OUTPUT:
RETVAL
double
tan_val(a)
double a
CODE:
RETVAL = tan(a);
add_to_history('t', a, 0, RETVAL);
OUTPUT:
RETVAL
double
asin_val(a)
double a
CODE:
if (a < -1.0 || a > 1.0) {
croak("asin argument must be in [-1, 1]");
}
RETVAL = asin(a);
add_to_history('S', a, 0, RETVAL);
OUTPUT:
RETVAL
double
acos_val(a)
double a
CODE:
if (a < -1.0 || a > 1.0) {
croak("acos argument must be in [-1, 1]");
}
RETVAL = acos(a);
add_to_history('C', a, 0, RETVAL);
OUTPUT:
RETVAL
double
atan_val(a)
double a
CODE:
RETVAL = atan(a);
add_to_history('T', a, 0, RETVAL);
OUTPUT:
RETVAL
double
atan2_val(y, x)
double y
double x
CODE:
RETVAL = atan2(y, x);
add_to_history('A', y, x, RETVAL);
OUTPUT:
RETVAL
double
deg_to_rad(degrees)
double degrees
CODE:
RETVAL = degrees * M_PI / 180.0;
OUTPUT:
RETVAL
double
rad_to_deg(radians)
double radians
CODE:
RETVAL = radians * 180.0 / M_PI;
OUTPUT:
RETVAL
double
hypot_val(a, b)
double a
double b
CODE:
RETVAL = hypot(a, b);
add_to_history('h', a, b, RETVAL);
OUTPUT:
RETVAL
double
normalize_angle(radians)
double radians
CODE:
RETVAL = trig_normalize_angle(radians);
OUTPUT:
RETVAL
double
sec_val(a)
double a
CODE:
RETVAL = trig_sec(a);
add_to_history('E', a, 0, RETVAL);
OUTPUT:
RETVAL
double
csc_val(a)
double a
CODE:
RETVAL = trig_csc(a);
add_to_history('O', a, 0, RETVAL);
OUTPUT:
RETVAL
double
cot_val(a)
double a
CODE:
RETVAL = trig_cot(a);
add_to_history('G', a, 0, RETVAL);
OUTPUT:
RETVAL
int
is_valid_asin_arg(x)
double x
CODE:
RETVAL = trig_is_valid_asin_arg(x);
OUTPUT:
RETVAL
void
import(...)
CODE:
{
static const char *trig_exports[] = {
"sin_val", "cos_val", "tan_val",
"asin_val", "acos_val", "atan_val", "atan2_val",
"deg_to_rad", "rad_to_deg", "hypot_val",
"normalize_angle", "sec_val", "csc_val", "cot_val",
"is_valid_asin_arg"
};
do_import(aTHX_ "Acme::ExtUtils::XSOne::Test::Calculator::Trig",
trig_exports, 15, items, ax);
}
MODULE = Acme::ExtUtils::XSOne::Test::Calculator PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator
PROTOTYPES: DISABLE
double
pi()
CODE:
RETVAL = M_PI;
OUTPUT:
RETVAL
double
e()
CODE:
RETVAL = M_E;
OUTPUT:
RETVAL
const char *
version()
CODE:
RETVAL = "0.01";
OUTPUT:
RETVAL
BOOT:
/* Initialize memory on module load */
init_memory();
( run in 1.056 second using v1.01-cache-2.11-cpan-13bb782fe5a )