How-to guides

Each guide below is pulled directly from a compiled, executed Catch2 test (tagged [doc] in doc/snippets/), so it can’t drift out of sync with the API it demonstrates – if a guide stops matching reality, the docs build fails.

Add two float8 vectors

weaver::float8 behaves like a scalar float for the usual arithmetic operators, but computes on 8 lanes at once:

	weaver::float8 x{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
	weaver::float8 y{ 8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };

	weaver::float8 z = x + y;

That single + isn’t sugar over a loop – it’s one SIMD instruction. The function below is compiled and disassembled by the docs build itself (doc/snippets/float8_asm.cpp); its operands arrive as parameters rather than literals so the compiler can’t fold the addition away at compile time:

weaver::float8 add_float8(weaver::float8 a, weaver::float8 b)
{
	return a + b;
}

Which the configured toolchain (here: whatever WEAVER_VECTORIZE this docs build used) turns into:

; ymm0 = a, ymm1 = b
movaps xmm1,XMMWORD PTR [rsp+0x28]
movaps xmm0,XMMWORD PTR [rsp+0x38]
mov    rax,rdi
addps  xmm1,XMMWORD PTR [rsp+0x8]
addps  xmm0,XMMWORD PTR [rsp+0x18]
movaps XMMWORD PTR [rdi],xmm1
movaps XMMWORD PTR [rdi+0x10],xmm0
ret

The exact instructions depend on the compiler and target ISA – an AVX build emits a single vaddps on 8-wide ymm registers, while an SSE build splits the same 8 lanes across two 4-wide xmm registers instead. Either way, this is the real output of the currently configured toolchain, not a hand-picked example.

Pick a value without branching

FloatWeaver code has no real if: an if would have to pick one branch for the whole vector, but different lanes can want different answers. Instead you compute both possibilities and use select to keep, per lane, whichever one the (also per-lane) condition asked for – the branchless equivalent of a[i] < b[i] ? b[i] : a[i]:

	weaver::float8 a{ 1.0f, 5.0f, 3.0f, 8.0f, 2.0f, 9.0f, 4.0f, 0.0f };
	weaver::float8 b{ 4.0f, 2.0f, 6.0f, 1.0f, 7.0f, 3.0f, 5.0f, 9.0f };

	// Equivalent to "for each lane: a[i] < b[i] ? b[i] : a[i]" -- but with no
	// branch, so every lane is computed regardless of the others.
	weaver::float8 m = weaver::select(a < b, b, a);

Same isolate-and-disassemble treatment as above (doc/snippets/select_asm.cpp):

weaver::float8 select_max(weaver::float8 a, weaver::float8 b)
{
	return weaver::select(a < b, b, a);
}
; ymm0 = a, ymm1 = b
movaps xmm2,XMMWORD PTR [rsp+0x8]
movaps xmm1,XMMWORD PTR [rsp+0x18]
mov    rax,rdi
movaps xmm3,xmm2
movaps xmm0,xmm1
cmpltps xmm0,XMMWORD PTR [rsp+0x38]
cmpltps xmm3,XMMWORD PTR [rsp+0x28]
blendvps xmm1,XMMWORD PTR [rsp+0x38],xmm0
movdqa xmm0,xmm3
blendvps xmm2,XMMWORD PTR [rsp+0x28],xmm0
movaps XMMWORD PTR [rdi+0x10],xmm1
movaps XMMWORD PTR [rdi],xmm2
ret

Two instructions, no branch: a compare that produces a per-lane mask, then a blend that picks lanes from a or b according to that mask – every lane gets computed, and the “wrong” one is simply discarded rather than skipped.

Take a square root

Not just + compiles down to a single instruction – most of the <cmath>-style free functions in namespace weaver do too:

	weaver::float8 x{ 4.0f, 9.0f, 16.0f, 25.0f, 1.0f, 100.0f, 64.0f, 36.0f };

	weaver::float8 r = weaver::sqrt(x);
weaver::float8 sqrt_float8(weaver::float8 a)
{
	return weaver::sqrt(a);
}
; ymm0 = a
sqrtps xmm1,XMMWORD PTR [rsp+0x8]
sqrtps xmm0,XMMWORD PTR [rsp+0x18]
mov    rax,rdi
movaps XMMWORD PTR [rdi],xmm1
movaps XMMWORD PTR [rdi+0x10],xmm0
ret

Approximate reciprocal and reciprocal square root

rcp and rsqrt trade a couple of ULPs of accuracy for hardware approximation instructions that are cheaper than a real divide or square root – useful when normalizing a vector or computing a rough inverse where exactness doesn’t matter:

	weaver::float8 x{ 2.0f, 4.0f, 8.0f, 5.0f, 1.0f, 10.0f, 16.0f, 20.0f };

	// An approximation of `1 / x`, not an exact divide -- trades a couple of
	// ULPs of accuracy for a much cheaper instruction.
	weaver::float8 r = weaver::rcp(x);
weaver::float8 rcp_float8(weaver::float8 a)
{
	return weaver::rcp(a);
}
; ymm0 = a
movaps xmm4,XMMWORD PTR [rsp+0x8]
pxor   xmm2,xmm2
movaps xmm5,XMMWORD PTR [rsp+0x18]
mov    rax,rdi
rcpps  xmm1,xmm4
movaps xmm3,xmm4
cmpeqps xmm3,xmm2
cmpeqps xmm2,xmm5
movaps xmm0,xmm1
mulps  xmm0,xmm1
addps  xmm1,xmm1
mulps  xmm0,xmm4
andnps xmm3,xmm0
rcpps  xmm0,xmm5
subps  xmm1,xmm3
movaps xmm4,xmm0
movaps XMMWORD PTR [rdi],xmm1
mulps  xmm4,xmm0
addps  xmm0,xmm0
mulps  xmm4,xmm5
andnps xmm2,xmm4
subps  xmm0,xmm2
movaps XMMWORD PTR [rdi+0x10],xmm0
ret
	weaver::float8 x{ 4.0f, 9.0f, 16.0f, 25.0f, 1.0f, 100.0f, 64.0f, 36.0f };

	// An approximation of `1 / sqrt(x)` that avoids both the divide and the
	// square root -- the common case for normalizing a vector.
	weaver::float8 r = weaver::rsqrt(x);
weaver::float8 rsqrt_float8(weaver::float8 a)
{
	return weaver::rsqrt(a);
}
; ymm0 = a
rsqrtps xmm2,XMMWORD PTR [rsp+0x8]
movss  xmm0,DWORD PTR [rip+0x0]
rsqrtps xmm1,XMMWORD PTR [rsp+0x18]
mov    rax,rdi
shufps xmm0,xmm0,0x0
movaps xmm3,xmm0
movaps xmm4,xmm2
mulps  xmm4,xmm2
mulps  xmm4,XMMWORD PTR [rsp+0x8]
subps  xmm3,xmm4
movss  xmm4,DWORD PTR [rip+0x0]
shufps xmm4,xmm4,0x0
mulps  xmm2,xmm4
mulps  xmm2,xmm3
movaps XMMWORD PTR [rdi],xmm2
movaps xmm2,xmm1
mulps  xmm2,xmm1
mulps  xmm2,XMMWORD PTR [rsp+0x18]
mulps  xmm1,xmm4
subps  xmm0,xmm2
mulps  xmm0,xmm1
movaps XMMWORD PTR [rdi+0x10],xmm0
ret

Branchless sign

sgn is a real library function, not a contrived example – it’s what a branchless sign-without-abs costs in practice: a mask, an and, an or, and an and:

	weaver::float8 x{ -3.0f, 0.0f, 2.0f, -0.5f, 7.0f, -7.0f, 0.0f, 1.0f };

	// -1 / 0 / 1 per lane, with no per-lane branch on the sign.
	weaver::float8 s = weaver::sgn(x);
weaver::float8 sgn_float8(weaver::float8 a)
{
	return weaver::sgn(a);
}
; ymm0 = a
pxor   xmm0,xmm0
movaps xmm1,XMMWORD PTR [rsp+0x8]
mov    rax,rdi
movss  xmm4,DWORD PTR [rip+0x0]
movaps xmm2,xmm0
movss  xmm3,DWORD PTR [rip+0x0]
cmpneqps xmm2,XMMWORD PTR [rsp+0x8]
shufps xmm4,xmm4,0x0
andps  xmm1,xmm4
andps  xmm4,XMMWORD PTR [rsp+0x18]
shufps xmm3,xmm3,0x0
orps   xmm1,xmm3
andps  xmm1,xmm2
movaps xmm2,xmm0
movaps xmm0,xmm4
cmpneqps xmm2,XMMWORD PTR [rsp+0x18]
orps   xmm0,xmm3
movaps XMMWORD PTR [rdi],xmm1
andps  xmm0,xmm2
movaps XMMWORD PTR [rdi+0x10],xmm0
ret

Compare floats with a tolerance

Exact float equality is rarely what you want. weaver::equal implements a relative-tolerance compare per lane – a realistic idiom, a few instructions longer than a plain ==:

	weaver::float8 a{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
	weaver::float8 b{ 1.0000001f, 1.1f, 0.9f, 1.0f, 2.0f, 1.00001f, 1.0f, 1.0f };

	// A relative-tolerance compare, per lane -- see the reference this is
	// based on in vector_types.h.
	weaver::VectorScalar<bool, 8> close = weaver::equal(a, b, weaver::float8{ 1e-4f });
weaver::VectorScalar<bool, 8> equal_tol_float8(weaver::float8 a, weaver::float8 b, weaver::float8 tol)
{
	return weaver::equal(a, b, tol);
}
; ymm0 = a, ymm1 = b, ymm2 = tol
movss  xmm0,DWORD PTR [rip+0x0]
mov    rax,rdi
shufps xmm0,xmm0,0x0
movaps xmm1,xmm0
movaps xmm2,xmm0
andnps xmm1,XMMWORD PTR [rsp+0x38]
andnps xmm2,XMMWORD PTR [rsp+0x18]
movaps xmm4,xmm0
movaps xmm3,xmm0
andnps xmm4,XMMWORD PTR [rsp+0x28]
andnps xmm3,XMMWORD PTR [rsp+0x8]
maxps  xmm2,xmm1
movss  xmm1,DWORD PTR [rip+0x0]
maxps  xmm3,xmm4
shufps xmm1,xmm1,0x0
movaps xmm4,xmm1
maxps  xmm1,xmm2
movaps xmm2,XMMWORD PTR [rsp+0x8]
subps  xmm2,XMMWORD PTR [rsp+0x28]
mulps  xmm1,XMMWORD PTR [rsp+0x58]
maxps  xmm4,xmm3
movaps xmm3,xmm0
mulps  xmm4,XMMWORD PTR [rsp+0x48]
andnps xmm3,xmm2
movaps xmm2,XMMWORD PTR [rsp+0x18]
subps  xmm2,XMMWORD PTR [rsp+0x38]
andnps xmm0,xmm2
cmpleps xmm3,xmm4
cmpleps xmm0,xmm1
movaps XMMWORD PTR [rdi],xmm3
movaps XMMWORD PTR [rdi+0x10],xmm0
ret

Check a condition across all lanes

Individual lanes can never branch, but FloatWeaver code is still allowed a real if – as long as it branches on a single reduced bool, not on a per-lane result. any/all/none are how a per-lane comparison becomes that bool:

	weaver::float8 x{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 20.0f };
	weaver::float8 limit{ 9.0f };

	// Per-lane comparisons don't decide anything by themselves -- `any`
	// reduces the 8-wide result down to the single bool a real `if` needs.
	if (weaver::any(x > limit))
	{
		// at least one lane exceeded the limit
	}
bool any_greater_float8(weaver::float8 a, weaver::float8 b)
{
	return weaver::any(a > b);
}
; ymm0 = a, ymm1 = b
movaps xmm1,XMMWORD PTR [rsp+0x38]
movaps xmm0,XMMWORD PTR [rsp+0x28]
cmpltps xmm1,XMMWORD PTR [rsp+0x18]
cmpltps xmm0,XMMWORD PTR [rsp+0x8]
movmskps eax,xmm1
movmskps edx,xmm0
shl    eax,0x4
or     eax,edx
setne  al
ret

A compare, a movmsk to pull the per-lane mask bits into a scalar register, then a plain integer test – this is the one place in these guides where a scalar, not a vector, comes out the other end.

Horizontal reduction: dot product

Every example so far keeps 8 independent results, one per lane. dot doesn’t: it collapses all 8 lanes of both operands into a single float, so the instruction shape looks different from the rest of this guide – a multiply-reduce followed by a lane-extraction step, not a per-lane op:

	weaver::float8 x{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
	weaver::float8 y{ 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f };

	// Unlike the elementwise ops above, this collapses all 8 lanes into one
	// plain `float` -- a horizontal reduction, not a per-lane result.
	float d = x.dot(y);
float dot_float8(weaver::float8 a, weaver::float8 b)
{
	return a.dot(b);
}
; ymm0 = a, ymm1 = b
movaps xmm1,XMMWORD PTR [rsp+0x18]
dpps   xmm1,XMMWORD PTR [rsp+0x38],0xff
movaps xmm2,XMMWORD PTR [rsp+0x8]
dpps   xmm2,XMMWORD PTR [rsp+0x28],0xff
movaps xmm0,xmm1
addss  xmm0,xmm2
ret

Using FloatWeaver with Eigen

weaver::float4/float8/float16 work as the Scalar of an Eigen::Matrix directly (see include/weaver/eigen.h) – no separate vector type, no adapter code at the call site. The guides below show that this isn’t just type-level plumbing: ordinary Eigen algorithms, written with no knowledge of FloatWeaver, compile down to the same kind of vector instructions as the weaver-native examples above.

Eigen vector arithmetic

The baseline case: an Eigen::Matrix<weaver::float8, 3, 1> is a Vector3 holding 8 points at once, and operator+ works exactly as it would for Eigen::Vector3f:

	// weaver::float8 works as the Scalar of an Eigen::Matrix directly, no
	// special vector type required -- this Vector3 holds 8 3D points.
	Eigen::Matrix<weaver::float8, 3, 1> a{ weaver::float8{1.0f}, weaver::float8{2.0f}, weaver::float8{3.0f} };
	Eigen::Matrix<weaver::float8, 3, 1> b{ weaver::float8{4.0f}, weaver::float8{5.0f}, weaver::float8{6.0f} };

	Eigen::Matrix<weaver::float8, 3, 1> c = a + b;
Eigen::Matrix<weaver::float8, 3, 1> add_vec3_float8(
	Eigen::Matrix<weaver::float8, 3, 1> a,
	Eigen::Matrix<weaver::float8, 3, 1> b)
{
	return a + b;
}
; rdi = return-value pointer, rsi = &a, rdx = &b
movaps xmm0,XMMWORD PTR [rdx+0x10]
movaps xmm1,XMMWORD PTR [rdx]
mov    rax,rdi
addps  xmm0,XMMWORD PTR [rsi+0x10]
addps  xmm1,XMMWORD PTR [rsi]
movaps XMMWORD PTR [rdi+0x10],xmm0
movaps xmm0,XMMWORD PTR [rdx+0x30]
addps  xmm0,XMMWORD PTR [rsi+0x30]
movaps XMMWORD PTR [rdi],xmm1
movaps xmm1,XMMWORD PTR [rdx+0x20]
addps  xmm1,XMMWORD PTR [rsi+0x20]
movaps XMMWORD PTR [rdi+0x30],xmm0
movaps xmm0,XMMWORD PTR [rdx+0x50]
addps  xmm0,XMMWORD PTR [rsi+0x50]
movaps XMMWORD PTR [rdi+0x20],xmm1
movaps xmm1,XMMWORD PTR [rdx+0x40]
addps  xmm1,XMMWORD PTR [rsi+0x40]
movaps XMMWORD PTR [rdi+0x50],xmm0
movaps XMMWORD PTR [rdi+0x40],xmm1
ret

Three vaddps, one per vector component – proof the NumTraits/ numext wiring costs nothing over calling weaver::float8’s own operator+ directly.

Squared norm and Eigen algorithms

squaredNorm() was never written for weaver::float8 – Eigen builds it generically out of operator* and operator+, the same way it would for any other Scalar:

	Eigen::Matrix<weaver::float8, 3, 1> v{ weaver::float8{1.0f}, weaver::float8{2.0f}, weaver::float8{3.0f} };

	// squaredNorm() is an Eigen algorithm, not a FloatWeaver primitive --
	// nobody wrote it for this Scalar type, Eigen just calls operator* and
	// operator+ generically.
	weaver::float8 lenSq = v.squaredNorm();
weaver::float8 squared_norm_vec3_float8(Eigen::Matrix<weaver::float8, 3, 1> v)
{
	return v.squaredNorm();
}
; rdi = &v
movaps xmm1,XMMWORD PTR [rsi+0x40]
movaps xmm0,XMMWORD PTR [rsi+0x50]
mov    rax,rdi
movaps xmm5,XMMWORD PTR [rsi+0x20]
movaps xmm3,XMMWORD PTR [rsi+0x30]
mulps  xmm1,xmm1
movaps xmm4,XMMWORD PTR [rsi]
movaps xmm2,XMMWORD PTR [rsi+0x10]
mulps  xmm5,xmm5
mulps  xmm3,xmm3
mulps  xmm0,xmm0
mulps  xmm4,xmm4
mulps  xmm2,xmm2
addps  xmm1,xmm5
addps  xmm0,xmm3
addps  xmm1,xmm4
addps  xmm0,xmm2
movaps XMMWORD PTR [rdi],xmm1
movaps XMMWORD PTR [rdi+0x10],xmm0
ret

Cross product

cross() is the classic shuffle-and-multiply pattern – three multiplies and three fused multiply-subtracts, still one screenful of assembly:

	Eigen::Matrix<weaver::float8, 3, 1> a{ weaver::float8{1.0f}, weaver::float8{2.0f}, weaver::float8{3.0f} };
	Eigen::Matrix<weaver::float8, 3, 1> b{ weaver::float8{4.0f}, weaver::float8{5.0f}, weaver::float8{6.0f} };

	Eigen::Matrix<weaver::float8, 3, 1> c = a.cross(b);
Eigen::Matrix<weaver::float8, 3, 1> cross_vec3_float8(
	Eigen::Matrix<weaver::float8, 3, 1> a,
	Eigen::Matrix<weaver::float8, 3, 1> b)
{
	return a.cross(b);
}
; rdi = return-value pointer, rsi = &a, rdx = &b
movaps xmm9,XMMWORD PTR [rsi+0x20]
movaps xmm1,XMMWORD PTR [rdx+0x20]
mov    rax,rdi
movaps xmm11,XMMWORD PTR [rdx+0x40]
movaps xmm3,XMMWORD PTR [rsi+0x40]
movaps xmm12,xmm9
movaps xmm13,xmm1
movaps xmm7,XMMWORD PTR [rsi+0x30]
movaps xmm0,XMMWORD PTR [rdx+0x30]
mulps  xmm13,xmm3
movaps xmm5,XMMWORD PTR [rdx]
movaps xmm4,XMMWORD PTR [rdx+0x10]
mulps  xmm12,xmm11
movaps xmm10,XMMWORD PTR [rsi]
movaps xmm8,XMMWORD PTR [rsi+0x10]
movaps xmm6,XMMWORD PTR [rdx+0x50]
movaps xmm2,XMMWORD PTR [rsi+0x50]
mulps  xmm3,xmm5
mulps  xmm11,xmm10
mulps  xmm1,xmm10
mulps  xmm5,xmm9
subps  xmm12,xmm13
movaps xmm13,xmm0
mulps  xmm13,xmm2
mulps  xmm0,xmm8
subps  xmm3,xmm11
movaps XMMWORD PTR [rdi],xmm12
mulps  xmm2,xmm4
movaps xmm12,xmm7
mulps  xmm12,xmm6
subps  xmm1,xmm5
mulps  xmm6,xmm8
movaps XMMWORD PTR [rdi+0x20],xmm3
mulps  xmm4,xmm7
movaps XMMWORD PTR [rdi+0x40],xmm1
subps  xmm12,xmm13
subps  xmm2,xmm6
subps  xmm0,xmm4
movaps XMMWORD PTR [rdi+0x10],xmm12
movaps XMMWORD PTR [rdi+0x30],xmm2
movaps XMMWORD PTR [rdi+0x50],xmm0
ret

Branchless select over an Eigen vector

The same branchless pattern as “Pick a value without branching” above, but applied to a whole vector-valued quantity at once – e.g. choosing one of two candidate velocities for 8 particles in a single call, one blend per component:

	// Two candidate velocities for 8 particles at once.
	Eigen::Matrix<weaver::float8, 3, 1> fast{ weaver::float8{1.0f}, weaver::float8{2.0f}, weaver::float8{3.0f} };
	Eigen::Matrix<weaver::float8, 3, 1> slow{ weaver::float8{4.0f}, weaver::float8{5.0f}, weaver::float8{6.0f} };

	weaver::VectorScalar<bool, 8> useFast{ true, false, true, false, true, false, true, false };

	// The same branchless pattern as "Pick a value without branching", but
	// applied component-wise to a whole Eigen vector instead of one scalar.
	Eigen::Matrix<weaver::float8, 3, 1> v = weaver::select(useFast, fast, slow);
Eigen::Matrix<weaver::float8, 3, 1> select_vec3_float8(
	weaver::VectorScalar<bool, 8> mask,
	Eigen::Matrix<weaver::float8, 3, 1> a,
	Eigen::Matrix<weaver::float8, 3, 1> b)
{
	return weaver::select(mask, a, b);
}
; ymm0 = mask, rdi = return-value pointer, rsi = &a, rdx = &b
pxor   xmm1,xmm1
movaps xmm3,XMMWORD PTR [rdx+0x10]
movaps xmm4,XMMWORD PTR [rdx]
mov    rax,rdi
movdqa xmm2,xmm1
pcmpgtd xmm1,XMMWORD PTR [rsp+0x8]
pcmpgtd xmm2,XMMWORD PTR [rsp+0x18]
movaps xmm0,xmm2
blendvps xmm3,XMMWORD PTR [rsi+0x10],xmm0
movaps xmm0,xmm1
blendvps xmm4,XMMWORD PTR [rsi],xmm0
movaps XMMWORD PTR [rdi+0x10],xmm3
movaps xmm3,XMMWORD PTR [rdx+0x30]
movaps xmm0,xmm2
movaps XMMWORD PTR [rdi],xmm4
movaps xmm5,XMMWORD PTR [rdx+0x20]
blendvps xmm3,XMMWORD PTR [rsi+0x30],xmm0
movaps xmm0,xmm1
blendvps xmm5,XMMWORD PTR [rsi+0x20],xmm0
movaps XMMWORD PTR [rdi+0x30],xmm3
movaps xmm6,XMMWORD PTR [rdx+0x50]
movaps xmm0,xmm2
movaps XMMWORD PTR [rdi+0x20],xmm5
movaps xmm3,XMMWORD PTR [rdx+0x40]
blendvps xmm6,XMMWORD PTR [rsi+0x50],xmm0
movaps xmm0,xmm1
blendvps xmm3,XMMWORD PTR [rsi+0x40],xmm0
movaps XMMWORD PTR [rdi+0x50],xmm6
movaps XMMWORD PTR [rdi+0x40],xmm3
ret

Merge axis-aligned boxes

This is closer to why FloatWeaver exists than a toy example: Eigen::AlignedBox needs no changes at all to operate on 8 boxes simultaneously. merged() takes the componentwise min of both boxes’ minimums and the max of their maximums:

	// 8 independent 2D boxes, merged in one call -- Eigen::AlignedBox needs
	// no changes to work with weaver::float8 as its Scalar.
	Eigen::AlignedBox<weaver::float8, 2> a{
		Eigen::Matrix<weaver::float8, 2, 1>{ weaver::float8{-1.0f}, weaver::float8{-1.0f} },
		Eigen::Matrix<weaver::float8, 2, 1>{ weaver::float8{1.0f}, weaver::float8{1.0f} }
	};
	Eigen::AlignedBox<weaver::float8, 2> b{
		Eigen::Matrix<weaver::float8, 2, 1>{ weaver::float8{0.0f}, weaver::float8{0.0f} },
		Eigen::Matrix<weaver::float8, 2, 1>{ weaver::float8{2.0f}, weaver::float8{2.0f} }
	};

	Eigen::AlignedBox<weaver::float8, 2> merged = a.merged(b);
Eigen::AlignedBox<weaver::float8, 2> merge_box2_float8(
	Eigen::AlignedBox<weaver::float8, 2> a,
	Eigen::AlignedBox<weaver::float8, 2> b)
{
	return a.merged(b);
}
; rdi = return-value pointer, rsi = &a, rdx = &b
movaps xmm1,XMMWORD PTR [rsi]
movaps xmm0,XMMWORD PTR [rsi+0x10]
mov    rax,rdi
minps  xmm1,XMMWORD PTR [rdx]
minps  xmm0,XMMWORD PTR [rdx+0x10]
movaps XMMWORD PTR [rdi],xmm1
movaps xmm1,XMMWORD PTR [rsi+0x20]
minps  xmm1,XMMWORD PTR [rdx+0x20]
movaps XMMWORD PTR [rdi+0x10],xmm0
movaps xmm0,XMMWORD PTR [rsi+0x30]
minps  xmm0,XMMWORD PTR [rdx+0x30]
movaps XMMWORD PTR [rdi+0x20],xmm1
movaps xmm1,XMMWORD PTR [rsi+0x40]
maxps  xmm1,XMMWORD PTR [rdx+0x40]
movaps XMMWORD PTR [rdi+0x30],xmm0
movaps xmm0,XMMWORD PTR [rsi+0x50]
maxps  xmm0,XMMWORD PTR [rdx+0x50]
movaps XMMWORD PTR [rdi+0x40],xmm1
movaps xmm1,XMMWORD PTR [rsi+0x60]
maxps  xmm1,XMMWORD PTR [rdx+0x60]
movaps XMMWORD PTR [rdi+0x50],xmm0
movaps xmm0,XMMWORD PTR [rsi+0x70]
maxps  xmm0,XMMWORD PTR [rdx+0x70]
movaps XMMWORD PTR [rdi+0x60],xmm1
movaps XMMWORD PTR [rdi+0x70],xmm0
ret