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