Evaluate a compiled `FlatExpr` over input arguments, producing a new Buffer.
(flat: &FlatExpr, args: &[ArgValue])
| 73 | |
| 74 | /// Evaluate a compiled `FlatExpr` over input arguments, producing a new Buffer. |
| 75 | pub(crate) fn eval_flat_elementwise(flat: &FlatExpr, args: &[ArgValue]) -> ParsecResult<Buffer> { |
| 76 | let len = infer_output_len(args)?; |
| 77 | |
| 78 | if len == 0 { |
| 79 | return Ok(Buffer::empty_f64()); |
| 80 | } |
| 81 | |
| 82 | let arg_slices: Vec<Option<&[f64]>> = args |
| 83 | .iter() |
| 84 | .map(|a| match a { |
| 85 | ArgValue::Scalar(_) => None, |
| 86 | ArgValue::Buffer(b) => Some(b.as_f64_slice()), |
| 87 | }) |
| 88 | .collect(); |
| 89 | |
| 90 | const PAR_THRESHOLD: usize = 4096; |
| 91 | |
| 92 | let result: Vec<f64> = if len >= PAR_THRESHOLD { |
| 93 | (0..len) |
| 94 | .into_par_iter() |
| 95 | .with_min_len(1024) |
| 96 | .map_init( |
| 97 | || Vec::with_capacity(flat.max_stack_depth), |
| 98 | |scratch, i| eval_flat_at(flat, i, &arg_slices, args, scratch), |
| 99 | ) |
| 100 | .collect() |
| 101 | } else { |
| 102 | let mut scratch = Vec::with_capacity(flat.max_stack_depth); |
| 103 | (0..len) |
| 104 | .map(|i| eval_flat_at(flat, i, &arg_slices, args, &mut scratch)) |
| 105 | .collect() |
| 106 | }; |
| 107 | |
| 108 | Ok(Buffer::from_f64_vec(result)) |
| 109 | } |
| 110 | |
| 111 | /// Evaluate the stack machine at element index `i`, reusing `scratch` as the operand stack. |
| 112 | #[inline] |