Acme-ExtUtils-XSOne-Test-Calculator

 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 {



( run in 0.360 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )