zkcrypto / pairing

Pairing-friendly elliptic curve library.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Operator Overloading

afck opened this issue · comments

Would it make sense to overload the arithmetic operators (std::ops) for everything that has an add, add_assign, mul or mul_assign method? I would love being able to write x += y; instead of x.add_assign(y), but I know that there are arguments against it, too. It certainly would make some heavy computation "feel" more lightweight than it is.

What's your opinion on this? If you are fine with it, I'd be happy to try and make e.g. Field: AddAssign + MulAssign + SubAssign + Neg, and CurveAffine: Mul + Neg.

I would have loved to do that at the time. I don't think Rust had AddAssign when I first wrote this implementation as part of another library, and the alternative overloading was impossible to express as a supertrait.

I would definitely love to see the impact of that and would be happy to merge it, though I would rather not import MulAssign at callsites and rather just have all code that invokes add_assign,sub_assign,mul_assign throughout the library switch to use the operator overloading instead.

Great, I'll give it a try, probably some time next week.

Thank you for the warnings, @burdges! 😄

My plan for now is just to only add the operators whose implementations are already there: If there's an add_assign(&mut self, Self), use it in AddAssign<RHS = Self> etc. I wouldn't try to add lots of variants for different combinations of references right away, or hide multiple operations (e.g. clone and add_assign) behind an innocent-looking symbol ("+").
Those kinds of ergonomics improvements should probably be added separately and discussed case-by-case.

I made a start with AddAssign: afck@15169b6
It makes Field require for<'r> ops::AddAssign<&'r Self> and removes the trait's own (conflicting) add_assign method.

Could you please have a look whether you'd be okay with that kind of implementation? Then I'll do the same for MulAssign, SubAssign, ShrAssign and ShlAssign, where appropriate. (I'm not sure whether it will be feasible for e.g. Mul.)

One good test is to see how it impacts downstream libraries and benchmarks. I'll do this when I get a chance.

I am very busy but I submitted a partial review.

One good test is to see how it impacts downstream libraries and benchmarks.

Unfortunately it will be backwards-incompatible, since the existing method add_assign conflicts with the trait's method. (A quick fix for dependent crates is to just import the AddAssign trait; no need to replace all calls with operators.)

I'm hoping that performance shouldn't change: The implementations are identical and I carried over all the #[inline] attributes.

I am very busy but I submitted a partial review.

I can't see any comments (and didn't open a PR for this).

I can't see any comments (and didn't open a PR for this).

Yeah, I don't know where my review was or what I was even referring to! :octocat: