-
Notifications
You must be signed in to change notification settings - Fork 185
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
Maintenance #460
Maintenance #460
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ mod diesel_mysql { | |
// internal types. | ||
let bytes = numeric.ok_or("Invalid decimal")?; | ||
let s = std::str::from_utf8(bytes)?; | ||
Decimal::from_str(&s).map_err(|e| e.into()) | ||
Decimal::from_str(s).map_err(|e| e.into()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clippy stuff |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,42 +15,46 @@ pub(crate) fn rescale_internal(value: &mut [u32; 3], value_scale: &mut u32, new_ | |
} | ||
|
||
if *value_scale > new_scale { | ||
let mut diff = *value_scale - new_scale; | ||
let mut diff = value_scale.wrapping_sub(new_scale); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// Scaling further isn't possible since we got an overflow | ||
// In this case we need to reduce the accuracy of the "side to keep" | ||
|
||
// Now do the necessary rounding | ||
let mut remainder = 0; | ||
while diff > 0 { | ||
while let Some(diff_minus_one) = diff.checked_sub(1) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same branch condition of |
||
if is_all_zero(value) { | ||
*value_scale = new_scale; | ||
return; | ||
} | ||
|
||
diff -= 1; | ||
diff = diff_minus_one; | ||
|
||
// Any remainder is discarded if diff > 0 still (i.e. lost precision) | ||
remainder = div_by_u32(value, 10); | ||
} | ||
if remainder >= 5 { | ||
for part in value.iter_mut() { | ||
let digit = u64::from(*part) + 1u64; | ||
remainder = if digit > 0xFFFF_FFFF { 1 } else { 0 }; | ||
*part = (digit & 0xFFFF_FFFF) as u32; | ||
remainder = if digit > U32_MASK { 1 } else { 0 }; | ||
*part = (digit & U32_MASK) as u32; | ||
if remainder == 0 { | ||
break; | ||
} | ||
} | ||
} | ||
*value_scale = new_scale; | ||
} else { | ||
let mut diff = new_scale - *value_scale; | ||
let mut diff = new_scale.wrapping_sub(*value_scale); | ||
let mut working = [value[0], value[1], value[2]]; | ||
while diff > 0 && mul_by_10(&mut working) == 0 { | ||
value.copy_from_slice(&working); | ||
diff -= 1; | ||
while let Some(diff_minus_one) = diff.checked_sub(1) { | ||
if mul_by_10(&mut working) == 0 { | ||
value.copy_from_slice(&working); | ||
diff = diff_minus_one; | ||
} else { | ||
break; | ||
} | ||
} | ||
*value_scale = new_scale - diff; | ||
*value_scale = new_scale.wrapping_sub(diff); | ||
} | ||
} | ||
|
||
|
@@ -94,32 +98,35 @@ pub(crate) fn add_by_internal(value: &mut [u32], by: &[u32]) -> u32 { | |
} | ||
|
||
pub(crate) fn add_by_internal_flattened(value: &mut [u32; 3], by: u32) -> u32 { | ||
let mut carry: u64; | ||
let mut sum: u64; | ||
sum = u64::from(value[0]) + u64::from(by); | ||
value[0] = (sum & U32_MASK) as u32; | ||
carry = sum >> 32; | ||
if carry > 0 { | ||
sum = u64::from(value[1]) + carry; | ||
value[1] = (sum & U32_MASK) as u32; | ||
carry = sum >> 32; | ||
if carry > 0 { | ||
sum = u64::from(value[2]) + carry; | ||
value[2] = (sum & U32_MASK) as u32; | ||
carry = sum >> 32; | ||
} | ||
} | ||
carry as u32 | ||
manage_add_by_internal(by, value) | ||
} | ||
|
||
#[inline] | ||
pub(crate) fn add_one_internal(value: &mut [u32]) -> u32 { | ||
let mut carry: u64 = 1; // Start with one, since adding one | ||
let mut sum: u64; | ||
for i in value.iter_mut() { | ||
sum = (*i as u64) + carry; | ||
*i = (sum & U32_MASK) as u32; | ||
carry = sum >> 32; | ||
pub(crate) fn add_one_internal(value: &mut [u32; 3]) -> u32 { | ||
manage_add_by_internal(1, value) | ||
} | ||
|
||
// `u64 as u32` are safe because of widening and 32bits shifts | ||
#[inline] | ||
pub(crate) fn manage_add_by_internal<const N: usize>(initial_carry: u32, value: &mut [u32; N]) -> u32 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Used by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think after we optimized |
||
let mut carry = u64::from(initial_carry); | ||
let mut iter = 0..value.len(); | ||
let mut sum = 0; | ||
|
||
let mut sum_fn = |local_carry: &mut u64, idx| { | ||
sum = u64::from(value[idx]).wrapping_add(*local_carry); | ||
value[idx] = (sum & U32_MASK) as u32; | ||
*local_carry = sum.wrapping_shr(32); | ||
}; | ||
|
||
if let Some(idx) = iter.next() { | ||
sum_fn(&mut carry, idx); | ||
} | ||
|
||
for idx in iter { | ||
if carry > 0 { | ||
sum_fn(&mut carry, idx); | ||
} | ||
} | ||
Comment on lines
+116
to
130
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://godbolt.org/z/qK5qzEK81 Both old and new versions have the same assembly output (taking aside an initial variable), i.e., the compiler is unrolling the loop. IMO, this new version is much more readable and flexible for any |
||
|
||
carry as u32 | ||
|
@@ -209,7 +216,7 @@ pub(crate) fn mul_part(left: u32, right: u32, high: u32) -> (u32, u32) { | |
} | ||
|
||
// Returns remainder | ||
pub(crate) fn div_by_u32(bits: &mut [u32], divisor: u32) -> u32 { | ||
pub(crate) fn div_by_u32<const N: usize>(bits: &mut [u32; N], divisor: u32) -> u32 { | ||
if divisor == 0 { | ||
// Divide by zero | ||
panic!("Internal error: divide by zero"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably signal an overflow instead of aborting the thread |
||
|
@@ -271,7 +278,7 @@ pub(crate) fn cmp_internal(left: &[u32; 3], right: &[u32; 3]) -> core::cmp::Orde | |
} | ||
|
||
#[inline] | ||
pub(crate) fn is_all_zero(bits: &[u32]) -> bool { | ||
pub(crate) fn is_all_zero<const N: usize>(bits: &[u32; N]) -> bool { | ||
bits.iter().all(|b| *b == 0) | ||
} | ||
Comment on lines
+281
to
283
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this will help the compiler unroll the loop. Not sure if it is already optimizing but such addition doesn't hurt. The same reasoning applies to the other There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this function is inline, it actually was unrolled (I checked on master). |
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -460,7 +460,7 @@ mod diesel_postgres { | |
} | ||
|
||
#[cfg(any(feature = "db-postgres", feature = "db-tokio-postgres"))] | ||
mod postgres { | ||
mod _postgres { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clippy stuff. Feel free to choose another name if desired There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had this in another project too. for now this should be fine since it's a private mod. |
||
use super::*; | ||
use ::postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; | ||
use byteorder::{BigEndian, ReadBytesExt}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,7 +94,7 @@ pub mod float { | |
/// | ||
/// #[derive(Serialize, Deserialize)] | ||
/// pub struct StringExample { | ||
/// #[serde(with = "rust_decimal::serde::string")] | ||
/// #[serde(with = "rust_decimal::serde::str")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CI is not currently testing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, interesting. This is the documentation tests in particular... I wonder if this would've been picked up in publish? I may see if we can capture this. Less blind spots the better! |
||
/// value: Decimal, | ||
/// } | ||
/// | ||
|
@@ -106,8 +106,12 @@ pub mod float { | |
/// ``` | ||
#[cfg(feature = "serde-with-str")] | ||
pub mod str { | ||
use crate::constants::MAX_STR_BUFFER_SIZE; | ||
|
||
use super::*; | ||
use serde::Serialize; | ||
use arrayvec::ArrayString; | ||
use core::convert::TryFrom; | ||
use serde::{ser::Error, Serialize}; | ||
|
||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error> | ||
where | ||
|
@@ -120,7 +124,9 @@ pub mod str { | |
where | ||
S: serde::Serializer, | ||
{ | ||
value.to_string().serialize(serializer) | ||
ArrayString::<MAX_STR_BUFFER_SIZE>::try_from(format_args!("{}", value)) | ||
.map_err(S::Error::custom)? | ||
.serialize(serializer) | ||
Comment on lines
+127
to
+129
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no need to perform a heap allocation.
|
||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More readable IMO