Skip to main content

polydat_core/numeric/
register.rs

1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! The register-lane bodies: the bounds-checked gathers, lane reads,
5//! and lane writes the `reg_*` nodes and their native lowerings share,
6//! on the word as the slots hold it, so both produce the same bits and
7//! the same message on a bad lane or window.
8
9use crate::ast::Bits128;
10
11/// The word of lanes `[offset, offset+4)` of `v`; panics past the end.
12pub fn gather_f32(v: &[f32], offset: u64) -> Bits128 {
13    let o = offset as usize;
14    if o + 4 > v.len() {
15        panic!(
16            "reg_gather_f32: window [{o}, {}) exceeds slice length {}",
17            o + 4,
18            v.len()
19        );
20    }
21    Bits128::from_lanes_f32([v[o], v[o + 1], v[o + 2], v[o + 3]])
22}
23
24/// The word of a four-element `v`.
25pub fn to_reg_f32(v: &[f32]) -> Bits128 {
26    if v.len() != 4 {
27        panic!(
28            "vec_to_reg_f32: expected exactly 4 elements, got {}",
29            v.len()
30        );
31    }
32    Bits128::from_lanes_f32([v[0], v[1], v[2], v[3]])
33}
34
35/// Lane `i` of `r` as f32 lanes, widened.
36pub fn lane_f32(r: Bits128, i: u64) -> f64 {
37    if i >= 4 {
38        panic!("reg_lane_f32: lane {i} out of range 0..4");
39    }
40    r.lanes_f32()[i as usize] as f64
41}
42
43/// `r` with f32 lane `i` replaced by `v`.
44pub fn with_lane_f32(r: Bits128, i: u64, v: f64) -> Bits128 {
45    if i >= 4 {
46        panic!("reg_with_lane_f32: lane {i} out of range 0..4");
47    }
48    let mut out = r.lanes_f32();
49    out[i as usize] = v as f32;
50    Bits128::from_lanes_f32(out)
51}
52
53/// Lane `i` of `r` as i16 lanes.
54pub fn lane_i16(r: Bits128, i: u64) -> i16 {
55    if i >= 8 {
56        panic!("reg_lane_i16: lane {i} out of range 0..8");
57    }
58    r.lanes_i16()[i as usize]
59}
60
61/// Lane `i` of `r` as i64 lanes.
62pub fn lane_i64(r: Bits128, i: u64) -> i64 {
63    if i >= 2 {
64        panic!("reg_lane_i64: lane {i} out of range 0..2");
65    }
66    r.lanes_i64()[i as usize]
67}
68
69/// The wrapping product of `a` and `b` as i8 lanes.
70pub fn mul_i8(a: Bits128, b: Bits128) -> Bits128 {
71    let (a, b) = (a.lanes_i8(), b.lanes_i8());
72    Bits128::from_lanes_i8(core::array::from_fn(|i| a[i].wrapping_mul(b[i])))
73}