Skip to content

Commit cbafbac

Browse files
committed
Introduced SimdCast
1 parent 8ca44c0 commit cbafbac

File tree

10 files changed

+77
-10
lines changed

10 files changed

+77
-10
lines changed

fearless_simd/src/generated/fallback.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is autogenerated by fearless_simd_gen
22

3-
use crate::{Level, Simd, SimdInto, seal::Seal};
3+
use crate::{Level, Simd, SimdCast, SimdInto, seal::Seal};
44
use crate::{
55
f32x4, f32x8, f32x16, i8x16, i8x32, i8x64, i16x8, i16x16, i16x32, i32x4, i32x8, i32x16,
66
mask8x16, mask8x32, mask8x64, mask16x8, mask16x16, mask16x32, mask32x4, mask32x8, mask32x16,
@@ -4887,3 +4887,12 @@ impl Simd for Fallback {
48874887
(b0.simd_into(self), b1.simd_into(self))
48884888
}
48894889
}
4890+
impl SimdCast<f32x4<Fallback>> for u32x4<Fallback> {
4891+
#[inline(always)]
4892+
fn cast_from(x: f32x4<Fallback>) -> Self {
4893+
Self {
4894+
val: x.val.map(|e| e as u32),
4895+
simd: x.simd,
4896+
}
4897+
}
4898+
}

fearless_simd/src/generated/neon.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is autogenerated by fearless_simd_gen
22

3-
use crate::{Level, Simd, SimdFrom, SimdInto, seal::Seal};
3+
use crate::{Level, Simd, SimdCast, SimdFrom, SimdInto, seal::Seal};
44
use crate::{
55
f32x4, f32x8, f32x16, i8x16, i8x32, i8x64, i16x8, i16x16, i16x32, i32x4, i32x8, i32x16,
66
mask8x16, mask8x32, mask8x64, mask16x8, mask16x16, mask16x32, mask32x4, mask32x8, mask32x16,
@@ -3166,6 +3166,12 @@ impl Simd for Neon {
31663166
(b0.simd_into(self), b1.simd_into(self))
31673167
}
31683168
}
3169+
impl SimdCast<f32x4<Neon>> for u32x4<Neon> {
3170+
#[inline(always)]
3171+
fn cast_from(x: f32x4<Neon>) -> Self {
3172+
unsafe { vcvtq_u32_f32(x.into()).simd_into(x.simd) }
3173+
}
3174+
}
31693175
impl<S: Simd> SimdFrom<float32x4_t, S> for f32x4<S> {
31703176
#[inline(always)]
31713177
fn simd_from(arch: float32x4_t, simd: S) -> Self {

fearless_simd/src/generated/simd_trait.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is autogenerated by fearless_simd_gen
22

3-
use crate::{Level, SimdElement, SimdInto, seal::Seal};
3+
use crate::{Level, SimdCast, SimdElement, SimdInto, seal::Seal};
44
use crate::{
55
f32x4, f32x8, f32x16, i8x16, i8x32, i8x64, i16x8, i16x16, i16x32, i32x4, i32x8, i32x16,
66
mask8x16, mask8x32, mask8x64, mask16x8, mask16x16, mask16x32, mask32x4, mask32x8, mask32x16,
@@ -13,7 +13,7 @@ pub trait Simd: Sized + Clone + Copy + Send + Sync + Seal + 'static {
1313
type i8s: SimdInt<i8, Self, Block = i8x16<Self>>;
1414
type u16s: SimdInt<u16, Self, Block = u16x8<Self>>;
1515
type i16s: SimdInt<i16, Self, Block = i16x8<Self>>;
16-
type u32s: SimdInt<u32, Self, Block = u32x4<Self>>;
16+
type u32s: SimdInt<u32, Self, Block = u32x4<Self>> + SimdCast<Self::f32s>;
1717
type i32s: SimdInt<i32, Self, Block = i32x4<Self>>;
1818
type mask8s: SimdMask<i8, Self, Block = mask8x16<Self>>;
1919
type mask16s: SimdMask<i16, Self, Block = mask16x8<Self>>;
@@ -648,6 +648,10 @@ pub trait SimdBase<Element: SimdElement, S: Simd>:
648648
fn from_slice(simd: S, slice: &[Element]) -> Self;
649649
fn splat(simd: S, val: Element) -> Self;
650650
fn block_splat(block: Self::Block) -> Self;
651+
#[inline(always)]
652+
fn cast<T: SimdCast<Self>>(self) -> T {
653+
T::cast_from(self)
654+
}
651655
}
652656
pub trait SimdFloat<Element: SimdElement, S: Simd>:
653657
SimdBase<Element, S>

fearless_simd/src/generated/wasm.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is autogenerated by fearless_simd_gen
22

3-
use crate::{Level, Simd, SimdFrom, SimdInto, seal::Seal};
3+
use crate::{Level, Simd, SimdCast, SimdFrom, SimdInto, seal::Seal};
44
use crate::{
55
f32x4, f32x8, f32x16, i8x16, i8x32, i8x64, i16x8, i16x16, i16x32, i32x4, i32x8, i32x16,
66
mask8x16, mask8x32, mask8x64, mask16x8, mask16x16, mask16x32, mask32x4, mask32x8, mask32x16,
@@ -3305,6 +3305,12 @@ impl Simd for WasmSimd128 {
33053305
(b0.simd_into(self), b1.simd_into(self))
33063306
}
33073307
}
3308+
impl SimdCast<f32x4<WasmSimd128>> for u32x4<WasmSimd128> {
3309+
#[inline(always)]
3310+
fn cast_from(x: f32x4<WasmSimd128>) -> Self {
3311+
u32x4_trunc_sat_f32x4(x.into()).simd_into(x.simd)
3312+
}
3313+
}
33083314
impl<S: Simd> SimdFrom<v128, S> for f32x4<S> {
33093315
#[inline(always)]
33103316
fn simd_from(arch: v128, simd: S) -> Self {

fearless_simd/src/traits.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,8 @@ impl SimdElement for u32 {
105105
impl SimdElement for i32 {
106106
type Mask = i32;
107107
}
108+
109+
/// Vectors that can be constructed from another vector `T` with Rust `as` semantics
110+
pub trait SimdCast<T> {
111+
fn cast_from(x: T) -> Self;
112+
}

fearless_simd_gen/src/mk_fallback.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub fn mk_fallback_impl() -> TokenStream {
3232

3333
quote! {
3434
use core::ops::*;
35-
use crate::{seal::Seal, Level, Simd, SimdInto};
35+
use crate::{seal::Seal, Level, Simd, SimdInto, SimdCast};
3636

3737
#imports
3838

@@ -385,6 +385,16 @@ fn mk_simd_impl() -> TokenStream {
385385

386386
#( #methods )*
387387
}
388+
389+
impl SimdCast<f32x4<#level_tok>> for u32x4<#level_tok> {
390+
#[inline(always)]
391+
fn cast_from(x: f32x4<#level_tok>) -> Self {
392+
Self {
393+
val: x.val.map(|e| e as u32),
394+
simd: x.simd,
395+
}
396+
}
397+
}
388398
}
389399
}
390400

fearless_simd_gen/src/mk_neon.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn mk_neon_impl(level: Level) -> TokenStream {
4545
quote! {
4646
use core::arch::aarch64::*;
4747

48-
use crate::{seal::Seal, Level, Simd, SimdFrom, SimdInto};
48+
use crate::{seal::Seal, Level, Simd, SimdFrom, SimdInto, SimdCast};
4949

5050
#imports
5151

@@ -397,6 +397,15 @@ fn mk_simd_impl(level: Level) -> TokenStream {
397397

398398
#( #methods )*
399399
}
400+
401+
impl SimdCast<f32x4<#level_tok>> for u32x4<#level_tok> {
402+
#[inline(always)]
403+
fn cast_from(x: f32x4<#level_tok>) -> Self {
404+
unsafe {
405+
vcvtq_u32_f32(x.into()).simd_into(x.simd)
406+
}
407+
}
408+
}
400409
}
401410
}
402411

fearless_simd_gen/src/mk_simd_trait.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub fn mk_simd_trait() -> TokenStream {
2727
}
2828
}
2929
let mut code = quote! {
30-
use crate::{seal::Seal, Level, SimdElement, SimdInto};
30+
use crate::{seal::Seal, Level, SimdElement, SimdInto, SimdCast};
3131
#imports
3232
/// TODO: docstring
3333
// TODO: Seal
@@ -37,7 +37,7 @@ pub fn mk_simd_trait() -> TokenStream {
3737
type i8s: SimdInt<i8, Self, Block = i8x16<Self>>;
3838
type u16s: SimdInt<u16, Self, Block = u16x8<Self>>;
3939
type i16s: SimdInt<i16, Self, Block = i16x8<Self>>;
40-
type u32s: SimdInt<u32, Self, Block = u32x4<Self>>;
40+
type u32s: SimdInt<u32, Self, Block = u32x4<Self>> + SimdCast<Self::f32s>;
4141
type i32s: SimdInt<i32, Self, Block = i32x4<Self>>;
4242
type mask8s: SimdMask<i8, Self, Block = mask8x16<Self>>;
4343
type mask16s: SimdMask<i16, Self, Block = mask16x8<Self>>;
@@ -84,6 +84,9 @@ fn mk_simd_base() -> TokenStream {
8484
fn from_slice(simd: S, slice: &[Element]) -> Self;
8585
fn splat(simd: S, val: Element) -> Self;
8686
fn block_splat(block: Self::Block) -> Self;
87+
88+
#[inline(always)]
89+
fn cast<T: SimdCast<Self>>(self) -> T { T::cast_from(self) }
8790
}
8891
}
8992
}

fearless_simd_gen/src/mk_wasm.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,13 @@ fn mk_simd_impl(level: Level) -> TokenStream {
501501

502502
#( #methods )*
503503
}
504+
505+
impl SimdCast<f32x4<#level_tok>> for u32x4<#level_tok> {
506+
#[inline(always)]
507+
fn cast_from(x: f32x4<#level_tok>) -> Self {
508+
u32x4_trunc_sat_f32x4(x.into()).simd_into(x.simd)
509+
}
510+
}
504511
}
505512
}
506513

@@ -513,7 +520,7 @@ pub fn mk_wasm128_impl(level: Level) -> TokenStream {
513520
quote! {
514521
use core::arch::wasm32::*;
515522

516-
use crate::{seal::Seal, Level, Simd, SimdFrom, SimdInto};
523+
use crate::{seal::Seal, Level, Simd, SimdFrom, SimdInto, SimdCast};
517524

518525
#imports
519526

fearless_simd_tests/tests/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
// Copyright 2025 the Fearless_SIMD Authors
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

4+
use fearless_simd::{Simd, SimdBase, SimdCast};
5+
46
#[cfg(target_arch = "wasm32")]
57
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
68

79
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
810
mod wasm;
11+
12+
// Ensure that we can cast between generic native-width vectors
13+
#[allow(dead_code)]
14+
fn generic_cast<S: Simd>(x: S::f32s) -> S::u32s {
15+
x.cast()
16+
}

0 commit comments

Comments
 (0)