use super::*;
pub(super) fn rm_strides(shape: &[usize]) -> DimI {
let n = shape.len();
let mut st = DimI::from_elem(0, n);
let mut acc = 1i64;
for d in (0..n).rev() {
st[d] = acc;
acc *= shape[d] as i64;
}
st
}
pub(super) fn cm_strides(shape: &[usize]) -> DimI {
let n = shape.len();
let mut st = DimI::from_elem(0, n);
let mut acc = 1i64;
for d in 0..n {
st[d] = acc;
acc *= shape[d] as i64;
}
st
}
pub(super) fn state_ptr(env: &Env, ix: u32) -> *const f64 {
let sv = &env.prog.state_vars[ix as usize];
if env.mirror[ix as usize] {
unsafe { env.state_rm.as_ptr().add(sv.flat_offset) }
} else {
unsafe { env.state.as_ptr().add(sv.flat_offset) }
}
}
pub(super) enum Rv {
S(f64),
V { ptr: *const f64, strides: DimI },
}
pub(super) struct SrcView {
pub(super) ptr: *const f64,
pub(super) shape: DimU,
pub(super) strides: DimI,
}
pub(super) fn resolve_scalar(
op: &Operand,
env: &Env,
slab_ptr: *const f64,
slot_off: &[usize],
) -> f64 {
match op {
Operand::Lit(v) => *v,
Operand::Param(p) => env.params[*p as usize],
Operand::Time => env.t,
Operand::Slot(s) => {
debug_assert!(
env.prog.slots[*s as usize].scalar,
"scalar read of array slot"
);
unsafe { *slab_ptr.add(slot_off[*s as usize]) }
}
Operand::State(ix) => {
let sv = &env.prog.state_vars[*ix as usize];
debug_assert!(sv.shape.is_empty(), "scalar read of array state");
env.state[sv.flat_offset]
}
}
}
pub(super) fn resolve_rv(
op: &Operand,
shape: &[usize],
env: &Env,
slab_ptr: *const f64,
slot_off: &[usize],
) -> Rv {
match op {
Operand::Lit(v) => Rv::S(*v),
Operand::Param(p) => Rv::S(env.params[*p as usize]),
Operand::Time => Rv::S(env.t),
Operand::Slot(s) => {
let desc = &env.prog.slots[*s as usize];
let off = slot_off[*s as usize];
if desc.scalar {
Rv::S(unsafe { *slab_ptr.add(off) })
} else {
debug_assert_eq!(&desc.shape[..], shape, "slot box mismatch");
Rv::V {
ptr: unsafe { slab_ptr.add(off) },
strides: rm_strides(shape),
}
}
}
Operand::State(ix) => {
let sv = &env.prog.state_vars[*ix as usize];
if sv.shape.is_empty() {
Rv::S(env.state[sv.flat_offset])
} else {
debug_assert_eq!(&sv.shape[..], shape, "state box mismatch");
Rv::V {
ptr: state_ptr(env, *ix),
strides: rm_strides(&sv.shape),
}
}
}
}
}
pub(super) fn resolve_src(
src: &SrcRef,
env: &Env,
slab_ptr: *const f64,
slot_off: &[usize],
) -> SrcView {
match src {
SrcRef::Slot(s) => {
let desc = &env.prog.slots[*s as usize];
SrcView {
ptr: unsafe { slab_ptr.add(slot_off[*s as usize]) },
shape: desc.shape.clone(),
strides: rm_strides(&desc.shape),
}
}
SrcRef::State(ix) => {
let sv = &env.prog.state_vars[*ix as usize];
SrcView {
ptr: state_ptr(env, *ix),
shape: sv.shape.clone(),
strides: rm_strides(&sv.shape),
}
}
}
}