Acme-ExtUtils-XSOne-Test-Calculator

 view release on metacpan or  search on metacpan

Calculator.xs  view on Meta::CPAN

    *error = 0;
    return a / b;
}

static double basic_clamp(double value, double min_val, double max_val) {
    if (value < min_val) return min_val;
    if (value > max_val) return max_val;
    return value;
}

static double basic_percent(double value, double percent) {
    return value * percent / 100.0;
}
/* C code from: Calculator/Memory.xs */
#line 1 "lib/Acme/ExtUtils/XSOne/Test/Calculator/Memory.xs"
/*
 * Acme::ExtUtils::XSOne::Test::Calculator::Memory - Memory and history functions
 *
 * This module accesses the shared state defined in _header.xs
 */

/* Memory package helpers - need access to memory_slots */

Calculator.xs  view on Meta::CPAN

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

lib/Acme/ExtUtils/XSOne/Test/Calculator.pm  view on Meta::CPAN


=head1 PACKAGES

All submodules support importing functions by name via C<use Module qw(func1 func2)>.

=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>,

lib/Acme/ExtUtils/XSOne/Test/Calculator/Basic.pm  view on Meta::CPAN

    # Or use fully qualified names
    use Acme::ExtUtils::XSOne::Test::Calculator;

    my $quot = Acme::ExtUtils::XSOne::Test::Calculator::Basic::divide(15, 3);   # 5
    my $mod  = Acme::ExtUtils::XSOne::Test::Calculator::Basic::modulo(17, 5);   # 2

=head1 EXPORTABLE FUNCTIONS

All functions can be imported by name:

    add subtract multiply divide modulo negate absolute safe_divide clamp percent

=head1 DESCRIPTION

This module provides basic arithmetic 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 add

lib/Acme/ExtUtils/XSOne/Test/Calculator/Basic.pm  view on Meta::CPAN


Returns C<$a> divided by C<$b>, or C<0> if C<$b> is zero
(instead of croaking).

=head2 clamp

    my $result = clamp($value, $min, $max);

Returns C<$value> constrained to the range C<[$min, $max]>.

=head2 percent

    my $result = percent($value, $pct);

Returns C<$pct> percent of C<$value> (i.e., C<$value * $pct / 100>).

=head1 SEE ALSO

L<Acme::ExtUtils::XSOne::Test::Calculator>,
L<Acme::ExtUtils::XSOne::Test::Calculator::Scientific>,
L<Acme::ExtUtils::XSOne::Test::Calculator::Trig>,
L<Acme::ExtUtils::XSOne::Test::Calculator::Memory>

=cut

lib/Acme/ExtUtils/XSOne/Test/Calculator/Basic.xs  view on Meta::CPAN

    *error = 0;
    return a / b;
}

static double basic_clamp(double value, double min_val, double max_val) {
    if (value < min_val) return min_val;
    if (value > max_val) return max_val;
    return value;
}

static double basic_percent(double value, double percent) {
    return value * percent / 100.0;
}

MODULE = Acme::ExtUtils::XSOne::Test::Calculator    PACKAGE = Acme::ExtUtils::XSOne::Test::Calculator::Basic

PROTOTYPES: DISABLE

double
add(a, b)
    double a
    double b

lib/Acme/ExtUtils/XSOne/Test/Calculator/Basic.xs  view on Meta::CPAN

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);
}

t/01-calculator.t  view on Meta::CPAN

    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::absolute(4), 4, 'absolute(4) = 4');

    # Test C helper functions (defined in basic.xs preamble)
    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::safe_divide(10, 2), 5, 'safe_divide(10, 2) = 5');
    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::safe_divide(10, 0), 0, 'safe_divide(10, 0) = 0 (no croak)');

    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::clamp(5, 0, 10), 5, 'clamp(5, 0, 10) = 5');
    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::clamp(15, 0, 10), 10, 'clamp(15, 0, 10) = 10');
    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::clamp(-5, 0, 10), 0, 'clamp(-5, 0, 10) = 0');

    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::percent(200, 15), 30, 'percent(200, 15) = 30');
    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::percent(50, 50), 25, 'percent(50, 50) = 25');
    is(Acme::ExtUtils::XSOne::Test::Calculator::Basic::percent(100, 100), 100, 'percent(100, 100) = 100');
};

subtest 'Division by zero' => sub {
    plan tests => 2;

    eval { Acme::ExtUtils::XSOne::Test::Calculator::Basic::divide(5, 0) };
    like($@, qr/Division by zero/, 'divide by zero croaks');

    eval { Acme::ExtUtils::XSOne::Test::Calculator::Basic::modulo(5, 0) };
    like($@, qr/Modulo by zero/, 'modulo by zero croaks');

t/02-import.t  view on Meta::CPAN

# t/02-import.t - Test import functionality for Calculator submodules

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(absolute(-7), 7, 'absolute(-7) = 7');
    is(absolute(4), 4, 'absolute(4) = 4');

    is(safe_divide(10, 2), 5, 'safe_divide(10, 2) = 5');
    is(safe_divide(10, 0), 0, 'safe_divide(10, 0) = 0 (no croak)');

    is(clamp(5, 0, 10), 5, 'clamp(5, 0, 10) = 5');
    is(clamp(15, 0, 10), 10, 'clamp(15, 0, 10) = 10');
    is(clamp(-5, 0, 10), 0, 'clamp(-5, 0, 10) = 0');

    is(percent(200, 15), 30, 'percent(200, 15) = 30');
    is(percent(50, 50), 25, 'percent(50, 50) = 25');
    is(percent(100, 100), 100, 'percent(100, 100) = 100');
};

subtest 'Division by zero' => sub {
    plan tests => 2;

    eval { divide(5, 0) };
    like($@, qr/Division by zero/, 'divide by zero croaks');

    eval { modulo(5, 0) };
    like($@, qr/Modulo by zero/, 'modulo by zero croaks');



( run in 1.577 second using v1.01-cache-2.11-cpan-39bf76dae61 )