Standard Perl scalars are designed for flexibility, not raw math throughput. When you need to process millions of coordinates, pixels, or audio samples, you want SIMD (Single Instruction, Multiple Data).

Affix makes SIMD vectors (like __m128, __m256, float32x4_t) first-class citizens and properly manages support on both x84 and ARM64.

The Recipe

Let's write a hypothetical 3D math library that uses 128-bit vectors (4 floats).

use v5.40;
use Affix qw[:all];
use Affix::Build;

# 1. Compile C Library
# We use GCC/Clang vector extensions for this example.
my $c = Affix::Build->new( flags => { cflags => '-O3 -mavx' } );
$c->add( \<<~'END', lang => 'c', );
    #if defined(__GNUC__) || defined(__clang__)
        typedef float v4f __attribute__((vector_size(16)));

        // Add two vectors
        v4f add_vecs(v4f a, v4f b) {
            return a + b;
        }

        // Scale a vector by a scalar
        v4f scale_vec(v4f v, float s) {
            return v * s;
        }

        // Dot product (returns scalar)
        float dot_vec(v4f a, v4f b) {
            v4f res = a * b;
            return res[0] + res[1] + res[2] + res[3];
        }
    #endif
END
my $lib = $c->link;

# 2. Bind
# We define a generic "Vec4" type: v[4:float]
typedef Vec4 => Vector [ 4, Float ];
affix $lib, 'add_vecs',  [ Vec4(), Vec4() ] => Vec4();
affix $lib, 'scale_vec', [ Vec4(), Float ]  => Vec4();
affix $lib, 'dot_vec',   [ Vec4(), Vec4() ] => Float;

# 3. Use (Packed Strings - The Fast Way)
# Pack 4 floats into a 16-byte string
my $v1 = pack( 'f4', 1.0, 2.0, 3.0, 4.0 );
my $v2 = pack( 'f4', 5.0, 6.0, 7.0, 8.0 );

# Add
my $sum_ref = add_vecs( $v1, $v2 );

# Results come back as ArrayRefs by default (for convenience)
say 'Sum: ' . join ', ', @$sum_ref;    # 6, 8, 10, 12

# 4. Use (ArrayRefs - The Convenient Way)
# You can also pass ArrayRefs directly. Affix handles the packing.
my $scaled_ref = scale_vec( [ 1.0, 1.0, 1.0, 1.0 ], 0.5 );
say 'Scaled: ' . join( ', ', @$scaled_ref );    # 0.5, 0.5, 0.5, 0.5

# 5. Dot Product
my $dot = dot_vec( $v1, $v2 );
say 'Dot Product: ' . $dot;                     # 1*5 + 2*6 + 3*7 + 4*8 = 70

How It Works

Kitchen Reminders