Ancient
view release on metacpan or search on metacpan
t/7014-nvec-simd-sizes.t view on Meta::CPAN
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;
use lib 'blib/lib', 'blib/arch';
use_ok('nvec');
# ============================================
# SIMD correctness tests across different sizes
# Tests various vector sizes to ensure correct
# handling of SIMD lanes and scalar tails
# ============================================
# SIMD lane sizes:
# - NEON: 2 doubles (128-bit)
# - SSE2: 2 doubles (128-bit)
# - AVX: 4 doubles (256-bit)
# - AVX2: 4 doubles (256-bit)
my @test_sizes = (
1, 2, 3, 4, # Small, around SIMD boundaries
5, 6, 7, 8, # One full AVX vector
9, 15, 16, 17, # Around 2x AVX
31, 32, 33, # Around 4x AVX
63, 64, 65, # Around 8x AVX
100, 127, 128, 129, # Larger
255, 256, 257, # Power of 2 boundaries
1000, 1023, 1024, 1025, # Large
);
my $tol = 1e-10;
sub is_float {
my ($got, $expected, $name) = @_;
if (abs($expected) < $tol) {
ok(abs($got) < $tol, $name)
or diag("got: $got, expected: ~0");
} else {
ok(abs($got - $expected) / abs($expected) < $tol, $name)
or diag("got: $got, expected: $expected, diff: " . abs($got - $expected));
}
}
# ============================================
# Sum correctness across sizes
# ============================================
subtest 'sum across sizes' => sub {
for my $n (@test_sizes) {
my $v = nvec::fill($n, 1.0);
is($v->sum, $n, "sum of $n ones = $n");
}
};
subtest 'sum of range' => sub {
for my $n (1, 10, 100, 1000) {
my $v = nvec::range(1, $n + 1); # 1 to n
my $expected = $n * ($n + 1) / 2; # Gauss formula
is_float($v->sum, $expected, "sum 1..$n = $expected");
}
};
# ============================================
# Dot product correctness across sizes
# ============================================
subtest 'dot product across sizes' => sub {
for my $n (@test_sizes) {
my $a = nvec::ones($n);
my $b = nvec::fill($n, 2.0);
is_float($a->dot($b), 2.0 * $n, "dot: ones · 2s for n=$n");
}
};
subtest 'dot product self' => sub {
for my $n (1, 7, 8, 9, 31, 32, 33, 100) {
my $v = nvec::fill($n, 3.0);
is_float($v->dot($v), 9.0 * $n, "dot: 3s · 3s for n=$n");
}
};
# ============================================
# Element-wise operations across sizes
# ============================================
subtest 'add across sizes' => sub {
for my $n (@test_sizes) {
my $a = nvec::fill($n, 1.0);
my $b = nvec::fill($n, 2.0);
my $c = $a->add($b);
is($c->len, $n, "add len for n=$n");
is($c->get(0), 3.0, "add first for n=$n");
is($c->get($n-1), 3.0, "add last for n=$n");
is($c->sum, 3.0 * $n, "add sum for n=$n");
}
};
subtest 'sub across sizes' => sub {
for my $n (@test_sizes) {
my $a = nvec::fill($n, 5.0);
my $b = nvec::fill($n, 2.0);
my $c = $a->sub($b);
is($c->get(0), 3.0, "sub first for n=$n");
is($c->get($n-1), 3.0, "sub last for n=$n");
}
};
subtest 'mul across sizes' => sub {
for my $n (@test_sizes) {
my $a = nvec::fill($n, 3.0);
my $b = nvec::fill($n, 4.0);
my $c = $a->mul($b);
is($c->get(0), 12.0, "mul first for n=$n");
is($c->get($n-1), 12.0, "mul last for n=$n");
}
( run in 0.664 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )