message: Use single implementation for `combine_table_entry`
diff: @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
  use serde_with::serde_as;
  use std::collections::{hash_map::Entry, HashMap, HashSet};
  use std::io::{Result as IoResult, Write};
  -use std::ops::{AddAssign, Mul};
  +use std::ops::{Add, Mul};
  type Evaluations<Field> = E<Field, D<Field>>;
  @@ -69,16 +69,24 @@ pub struct SingleLookup<F> {
  /// analogously using `joint_combiner`.
  ///
  /// This function computes that combined value.
  -pub fn combine_table_entry<'a, F: Field, I: DoubleEndedIterator<Item = &'a F>>(
  +pub fn combine_table_entry<
  + 'a,
  + F: 'a + Zero + One + Add + Mul + Clone,
  + I: DoubleEndedIterator<Item = &'a F>,
  +>(
  joint_combiner: F,
  v: I,
  ) -> F {
  - v.rev().fold(F::zero(), |acc, x| joint_combiner * acc + x)
  + v.rev()
  + .fold(F::zero(), |acc, x| joint_combiner.clone() * acc + x.clone())
  }
  impl<F: Copy> SingleLookup<F> {
  /// Evaluate the linear combination specifying the lookup value to a field element.
  - pub fn evaluate<K: Zero + Mul<F, Output = K>, G: Fn(LocalPosition) -> K>(&self, eval: G) -> K {
  + pub fn evaluate<K: Zero + Add + Mul<F, Output = K>, G: Fn(LocalPosition) -> K>(
  + &self,
  + eval: G,
  + ) -> K {
  self.value
  .iter()
  .fold(K::zero(), |acc, (c, p)| acc + eval(*p) * *c)
  @@ -94,6 +102,14 @@ pub struct JointLookup<SingleLookup> {
  pub type JointLookupSpec<F> = JointLookup<SingleLookup<F>>;
  +impl<F: Zero + One + Add + Mul + Clone> JointLookup<F> {
  + // TODO: Support multiple tables
  + /// Evaluate the combined value of a joint-lookup.
  + pub fn evaluate(&self, joint_combiner: F) -> F {
  + combine_table_entry(joint_combiner, self.entry.iter())
  + }
  +}
  +
  impl<F: Copy> JointLookup<SingleLookup<F>> {
  pub fn reduce<K: Zero + Mul<F, Output = K>, G: Fn(LocalPosition) -> K>(
  &self,
  @@ -104,20 +120,16 @@ impl<F: Copy> JointLookup<SingleLookup<F>> {
  entry: self.entry.iter().map(|s| s.evaluate(eval)).collect(),
  }
  }
  -}
  -impl<F: Zero + One + AddAssign + Clone> JointLookup<F> {
  - // TODO: Support multiple tables
  - /// Evaluate the combined value of a joint-lookup.
  - pub fn evaluate(&self, joint_combiner: F) -> F {
  - let mut res = F::zero();
  - for s in self.entry.iter().rev() {
  - if !res.is_zero() {
  - res = res * joint_combiner.clone()
  - }
  - res += s.clone();
  - }
  - res
  + pub fn evaluate<
  + K: Zero + One + Add + Mul + Mul<F, Output = K> + Clone,
  + G: Fn(LocalPosition) -> K,
  + >(
  + &self,
  + joint_combiner: K,
  + eval: &G,
  + ) -> K {
  + self.reduce(eval).evaluate(joint_combiner)
  }
  }
  