view release on metacpan or search on metacpan
Calculator.xs view on Meta::CPAN
}
}
/* C code from: Calculator/Scientific.xs */
#line 1 "lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.xs"
/*
* Acme::ExtUtils::XSOne::Test::Calculator::Scientific - Scientific/advanced operations
*/
/* 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);
}
Calculator.xs view on Meta::CPAN
}
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);
Calculator.xs view on Meta::CPAN
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
Calculator.xs view on Meta::CPAN
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
lib/Acme/ExtUtils/XSOne/Test/Calculator.pm view on Meta::CPAN
=over 4
=item * L<Acme::ExtUtils::XSOne::Test::Calculator::Basic>
Basic arithmetic: C<add>, C<subtract>, C<multiply>, C<divide>, C<modulo>,
C<negate>, C<absolute>, C<safe_divide>, C<clamp>, C<percent>
=item * L<Acme::ExtUtils::XSOne::Test::Calculator::Scientific>
Scientific operations: C<power>, C<sqrt_val>, C<cbrt_val>, C<nth_root>,
C<log_natural>, C<log10_val>, C<log_base>, C<exp_val>, C<factorial>,
C<ipow>, C<safe_sqrt>, C<safe_log>, C<combination>, C<permutation>
=item * L<Acme::ExtUtils::XSOne::Test::Calculator::Trig>
Trigonometry: C<sin_val>, C<cos_val>, C<tan_val>, C<asin_val>, C<acos_val>,
C<atan_val>, C<atan2_val>, C<deg_to_rad>, C<rad_to_deg>, C<hypot_val>,
C<normalize_angle>, C<sec_val>, C<csc_val>, C<cot_val>, C<is_valid_asin_arg>
=item * L<Acme::ExtUtils::XSOne::Test::Calculator::Memory>
Memory and history: C<store>, C<recall>, C<clear>, C<ans>, C<history_count>,
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.pm view on Meta::CPAN
# Import specific functions
use Acme::ExtUtils::XSOne::Test::Calculator::Scientific qw(power sqrt_val factorial);
my $pow = power(2, 10); # 1024
my $sqrt = sqrt_val(16); # 4
my $fact = factorial(5); # 120
# Or use fully qualified names
use Acme::ExtUtils::XSOne::Test::Calculator;
my $log = Acme::ExtUtils::XSOne::Test::Calculator::Scientific::log_natural(10); # ~2.303
=head1 EXPORTABLE FUNCTIONS
All functions can be imported by name:
power sqrt_val cbrt_val nth_root log_natural log10_val log_base exp_val
factorial ipow safe_sqrt safe_log combination permutation
=head1 DESCRIPTION
This module provides scientific and advanced mathematical operations as part of the
L<Acme::ExtUtils::XSOne::Test::Calculator> distribution. All operations
record their results in the shared calculation history.
=head1 FUNCTIONS
=head2 power
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.pm view on Meta::CPAN
Returns the cube root of C<$a>.
=head2 nth_root
my $result = nth_root($a, $n);
Returns the C<$n>th root of C<$a>. Croaks if C<$n> is zero or if
taking an even root of a negative number.
=head2 log_natural
my $result = log_natural($a);
Returns the natural logarithm (base e) of C<$a>.
Croaks if C<$a> is not positive.
=head2 log10_val
my $result = log10_val($a);
Returns the base-10 logarithm of C<$a>.
Croaks if C<$a> is not positive.
=head2 log_base
my $result = log_base($a, $base);
Returns the logarithm of C<$a> with the specified C<$base>.
Croaks if arguments are invalid.
=head2 exp_val
my $result = exp_val($a);
Returns e raised to the power of C<$a>.
=head2 factorial
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.pm view on Meta::CPAN
Returns C<$base> raised to the integer power C<$exp>.
This is faster than C<power()> for integer exponents.
=head2 safe_sqrt
my $result = safe_sqrt($a);
Returns the square root of C<$a>, or C<0> if C<$a> is negative
(instead of croaking).
=head2 safe_log
my $result = safe_log($a);
Returns the natural logarithm of C<$a>, or C<0> if C<$a> is not positive
(instead of croaking).
=head2 combination
my $result = combination($n, $r);
Returns the number of combinations (binomial coefficient) C<C(n,r)>.
=head2 permutation
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);
}
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.xs view on Meta::CPAN
}
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);
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.xs view on Meta::CPAN
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
lib/Acme/ExtUtils/XSOne/Test/Calculator/Scientific.xs view on Meta::CPAN
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);
}
t/01-calculator.t view on Meta::CPAN
is(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::safe_sqrt(16), 4, 'safe_sqrt(16) = 4');
is(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::safe_sqrt(-1), 0, 'safe_sqrt(-1) = 0 (no croak)');
is(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::combination(5, 2), 10, 'combination(5, 2) = 10');
is(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::permutation(5, 2), 20, 'permutation(5, 2) = 20');
};
subtest 'Logarithms' => sub {
plan tests => 6;
ok(abs(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::log_natural(exp(1)) - 1) < 0.0001, 'ln(e) = 1');
ok(abs(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::log10_val(100) - 2) < 0.0001, 'log10(100) = 2');
ok(abs(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::log_base(8, 2) - 3) < 0.0001, 'log2(8) = 3');
is(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::nth_root(27, 3), 3, 'nth_root(27, 3) = 3');
# Test C helper function (defined in scientific.xs preamble)
ok(abs(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::safe_log(exp(1)) - 1) < 0.0001, 'safe_log(e) = 1');
is(Acme::ExtUtils::XSOne::Test::Calculator::Scientific::safe_log(-1), 0, 'safe_log(-1) = 0 (no croak)');
};
subtest 'Scientific error handling' => sub {
plan tests => 3;
eval { Acme::ExtUtils::XSOne::Test::Calculator::Scientific::sqrt_val(-1) };
like($@, qr/negative/, 'sqrt of negative croaks');
eval { Acme::ExtUtils::XSOne::Test::Calculator::Scientific::log_natural(-1) };
like($@, qr/non-positive/, 'log of negative croaks');
eval { Acme::ExtUtils::XSOne::Test::Calculator::Scientific::factorial(-1) };
like($@, qr/negative/, 'factorial of negative croaks');
};
# =============================================================================
# Test Trig operations
# =============================================================================
subtest 'Trigonometric functions' => sub {
t/02-import.t view on Meta::CPAN
use strict;
use warnings;
use Test::More;
# =============================================================================
# Test importing functions from each submodule
# =============================================================================
use_ok('Acme::ExtUtils::XSOne::Test::Calculator::Basic', qw(add subtract multiply divide modulo negate absolute safe_divide clamp percent));
use_ok('Acme::ExtUtils::XSOne::Test::Calculator::Scientific', qw(power sqrt_val cbrt_val nth_root log_natural log10_val log_base exp_val factorial ipow safe_sqrt safe_log combination permutation));
use_ok('Acme::ExtUtils::XSOne::Test::Calculator::Trig', qw(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));
use_ok('Acme::ExtUtils::XSOne::Test::Calculator::Memory', qw(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));
# Also load the main module for constants
use Acme::ExtUtils::XSOne::Test::Calculator;
# =============================================================================
# Test constants (using fully qualified - not exported)
# =============================================================================
t/02-import.t view on Meta::CPAN
is(safe_sqrt(16), 4, 'safe_sqrt(16) = 4');
is(safe_sqrt(-1), 0, 'safe_sqrt(-1) = 0 (no croak)');
is(combination(5, 2), 10, 'combination(5, 2) = 10');
is(permutation(5, 2), 20, 'permutation(5, 2) = 20');
};
subtest 'Logarithms' => sub {
plan tests => 6;
ok(abs(log_natural(exp(1)) - 1) < 0.0001, 'ln(e) = 1');
ok(abs(log10_val(100) - 2) < 0.0001, 'log10(100) = 2');
ok(abs(log_base(8, 2) - 3) < 0.0001, 'log2(8) = 3');
is(nth_root(27, 3), 3, 'nth_root(27, 3) = 3');
ok(abs(safe_log(exp(1)) - 1) < 0.0001, 'safe_log(e) = 1');
is(safe_log(-1), 0, 'safe_log(-1) = 0 (no croak)');
};
subtest 'Scientific error handling' => sub {
plan tests => 3;
eval { sqrt_val(-1) };
like($@, qr/negative/, 'sqrt of negative croaks');
eval { log_natural(-1) };
like($@, qr/non-positive/, 'log of negative croaks');
eval { factorial(-1) };
like($@, qr/negative/, 'factorial of negative croaks');
};
# =============================================================================
# Test Trig operations (using imported functions)
# =============================================================================
subtest 'Trigonometric functions' => sub {