[Suggestion] feat: roll our own Pixel-to-integer conversions#72
[Suggestion] feat: roll our own Pixel-to-integer conversions#72FreezyLemon wants to merge 12 commits intorust-av:mainfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #72 +/- ##
==========================================
- Coverage 99.53% 97.66% -1.87%
==========================================
Files 7 9 +2
Lines 639 643 +4
==========================================
- Hits 636 628 -8
- Misses 3 15 +12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
These are infallible and very cheap. Also removes our num-traits dependency.
6a0d430 to
8b00589
Compare
|
Already found some problems with this while trying it on av-metrics.. Let me make this a draft for now. |
|
I think the |
|
I almost thought we could get away with the std traits Might still be good enough if we omit the fallible conversions.. that would mean: For any type >= u16 or >= i32 (infallible): let x: u16 = t.into();For u8, i16, etc. (fallible): // intermediary:
let x: i32 = t.into();
let x = i16::try_from(x).expect("fits into i16");I think T -> u8 is going to be common enough that the meh ergonomics could become a problem.
|
|
What a pain. I can't really find a sweet spot here. Pixel -> integers:
Integers -> Pixel:
Maybe I need to take another look at some of the common usage patterns or something, I don't think we can make everyone happy here. Or maybe we need to add more unsafe code for performance-sensitive stuff... We often assume that Footnotes
|
|
I missed that it's actually very possible to add a trait bound to the error type of TryFrom/TryInto 🤦 |
This is not one of my "let's remove dependencies because I want fewer dependencies" PRs.
When porting av-metrics to v_frame 0.5, I noticed a performance regression that I couldn't resolve.
related code:
in v_frame 0.3, these integer casts were implemented in-crate and infallible. Now we use the
num-traitscode and could use.to_i32().expect("pixel fits into i32"), but this is slower for some reason.Adding a simple
Pixel::as_u16()function into the trait fixes this immediately for a very small amount of boilerplate. My question now: Do we expect downstream users to use the generic math fromnum-traits?T: Pixelimplies you can do a lot of math onT,+ - * / % | & !are all implemented for it vianum_traits::PrimInt. But is this actually useful for crate users?For example,
(i32::cast_from(*a) - i32::cast_from(*b)).unsigned_abs() as u64could be reimplemented with math overTas something likebut in the end, you'd always need to convert back to a concrete type anyways. And it can be a real problem to not know the real size of the type. Can you sum in
Tor do you need to convert to u64? Can you square inTor do you need to widen the type? etc.ASM code does transmutation based on byte width anyways, and
byte_data()is still available for the case thatu16is too large for what you'd want. So it feels a bit difficult to justify keeping all thenum-traitstraits there IMHO.