Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add pad and padded to FixedDecimal #1195

Merged
merged 4 commits into from
Nov 5, 2021

Conversation

younies
Copy link
Member

@younies younies commented Oct 20, 2021

Fixes #1176

@younies younies requested a review from sffc as a code owner October 20, 2021 21:00
Copy link
Member

@sffc sffc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is about right, but let's sync on the details

utils/fixed_decimal/src/decimal.rs Outdated Show resolved Hide resolved
/// dec.pad(2);
/// assert_eq!("042", dec.to_string());
///
/// dec.pad(-2);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be additive with multiply_pow10()? E.g. suppose I had:

let mut dec = FixedDecimal::from(1234);
dec.multiply_pow10(-1);  // "123.4"
dec.pad(-2);  // "123.400" ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should be normalizing before we pad, i.e. convert everything into (n digits) + n magnitude.

We should definitely add doctests for the behavior here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, well, if minus padding, we first put it in a form where it is not already padded on the right, and if plus-padding, put it in a form where it's not already padded on the left

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually wait I think the data model doesn't need this 😄

@younies younies requested a review from sffc October 21, 2021 23:22
let cut = self.magnitude - self.upper_magnitude;

self.magnitude = self.upper_magnitude;
self.digits.drain(0..(cut as usize));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Please add a test case that triggers the case where cut is larger than self.digits.len()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

Ordering::Greater => self.upper_magnitude = magnitude,
_ => (),
pub fn pad_or_trunc_left(&mut self, shift: i16) {
self.upper_magnitude = match self.upper_magnitude + shift >= 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Please use checked_add instead of +. You may need to make the function return Result; see multiply_pow10. Add a test case for this behavior at the bottom of the file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Ordering::Less => self.lower_magnitude = magnitude,
Ordering::Greater => self.upper_magnitude = magnitude,
_ => (),
pub fn pad_or_trunc_left(&mut self, shift: i16) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn pad_or_trunc_left(&mut self, shift: i16) {
pub fn pad_or_truncate_left(&mut self, shift: i16) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

/// ```
pub fn padded(mut self, magnitude: i16) -> Self {
self.pad(magnitude);
pub fn padded_or_trunced_left(mut self, magnitude: i16) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn padded_or_trunced_left(mut self, magnitude: i16) -> Self {
pub fn padded_or_truncated_left(mut self, magnitude: i16) -> Self {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

@younies younies requested a review from sffc October 26, 2021 01:56
utils/fixed_decimal/src/decimal.rs Show resolved Hide resolved
/// assert_eq!("000", dec.to_string());
///
/// dec.pad_or_truncate_left(-1000);
/// assert_eq!("", dec.to_string());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: don't put the FixedDecimal in a state where it returns empty strings.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, what should we do if the user is deleting all the numbers? shall we consider returning an error?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, we should leave a 0 in the ones place and never remove it.

0042.10 --> 042.10 --> 42.10 --> 2.10 --> 0.10

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could consider allowing the removal of the zero digit, but I'd like that to be a separate PR, because right now FixedDecimal is defined in such a way that we always guarantee at least one digit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, done

/// dec.pad_or_truncate_left(-1);
/// assert_eq!("2", dec.to_string());
///
/// let mut dec = FixedDecimal::from(1000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The exhaustive behavior tests should go in a unit test at the bottom of the file. Only use docs tests for the main illustrative tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@younies younies requested a review from sffc October 26, 2021 23:34
Copy link
Member

@Manishearth Manishearth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this looks good, but it occurs to me that the user may need non-padding truncation as well (WearOS does)

I think we need functions that provide both:

  • the ability to say "make this have exactly X digits before/after the decimal point"
  • the ability to say "make this have at most X digits after the decimal point"
  • the ability to say "make this have at least X digits before the decimal point"

I don't think truncating on the LHS is that useful, and I think padding on the RHS is somewhat useful but you need a way to opt out.

I wonder if the API should be:

  • pad_left()
  • truncate_right()
  • pad_or_truncate_right()

We could also get by with pad(), truncate(), and pad_or_truncate() all accepting negative integers though I don't see much of a use case for each one so I'd prefer having them, by default, working on the direction this is more useful for. @sffc thoughts?

@sffc
Copy link
Member

sffc commented Oct 30, 2021

@Manishearth #1176 has my thoughts on the current proposed algorithm. The API that @younies proposed already allows for either either left* padding (positive argument) or left truncation (negative argument). Right* padding and right truncation should be handled by #1177.

A use case for left truncation is removing the century from year values, like in short date formatting ("today's date is 11/29/21").

* I say "left" and "right" even though certain scripts like Adlam write their digits in the opposite direction. I'm happy to bikeshed the name of these functions.

@younies younies merged commit 11288c3 into unicode-org:main Nov 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Convenience functions for FixedDecimal
4 participants