Closed terrorfisch closed 9 months ago
When I created the value
feature I thought about adding a tuple type. But I dismissed it because the code looked too bloated. I think one would need to extend the parser and give a special meaning to the comma.
I can have a look at it. Do you think adding such an operation is feasible:
struct NAry<T> {
// bit field that signifies with how many arguments this function can be called (used for parsing)
allowed_argument_count: u64,
// Implementation of the n-ary operation
apply: fn(&[T]) -> T,
}
impl<T> NAry<T> {
fn is_allowed_argument_count(&self, n: usize) -> bool {
self.allowed_argument_count & (1 << n) != 0
}
}
EDIT: After revisiting the evaluation code: This might be hard to integrate witout performance degradation.
EDIT2: Something along these lines should have litte performance impact if the branch predictor catches up:
fn eval_flatex_u64<T: Clone + Debug>(
numbers: &mut [T],
ops: &[FlatOp<T>],
prio_indices: &[(usize, usize)],
) {
let mut ignore = 0_u64;
for (&idx, &additional) in prio_indices {
let mut rotated = ignore.rotate_right(idx as u32 + 1);
let mut shift_right = rotated.trailing_ones() as usize + 1;
let shift_left = rotated.leading_ones() as usize;
let num_1 = numbers[idx - shift_left].clone();
let num_2 = numbers[idx + shift_right].clone();
let mut additional_nums = Vec::new();
for add in 0..additional {
let next_shift = todo!();
additional_nums.push(numbers[idx + next_shift]);
ignore |= todo!();
}
numbers[idx - shift_left] = {
let bop_res = (ops[idx].nary_op.apply)(num_1, num_2, &additional_nums[..]);
ops[idx].unary_op.apply(bop_res)
};
ignore |= 1 << (idx + shift_right);
}
}
This might even able to speed up evaluations of binary operations if we are able to flatten "a*b*c"
into a single n-ary operation.
Hmmm... I need to have a closer look, but Vec::new
looks expensive to me.
Oh, the Vec
is just a placeholder. Vec::new
by itself is a const fn that is very cheap especially if moved out of the loop. The Vec::push
is potentially more expensive but it is not called for regular binary ops and one could use a SmallVec.
Yes sure. But still slower than no Vec
. Benchmarks could tell if this is relevant.
Oh. The vector would only increases in case someone would really have more than 2 operands. Ok Agreed. Shouldn't be a performance problem compared to what we have right now.
Binary function call syntax has been implemented with #52. N-ary function call syntax might come some time in the future. Feel free to create a separate issue for that in case of demand.
Is it possible to add function call syntax to binary operators? Possibly extended to n-ary operations.
My motivating example is that I want to support
max
andmin
functions.A possible workaround for me is to add a tuple variant to my
Value
type which is built through a,
operator and use unary operators for this. Unfortunately this blows up all other code because then there are a lots of non-sensical states representable in the type system as not all values are allowed as operator inputs.As I see there are the following alternatives:
Value
type if required