mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 08:27:46 +00:00
AK: Make Duration arithmetic constexpr
This is a trivial change, and since this batch of commits will make a large-scale rebuild necessary anyways, it seems sensible. The feature is useful for e.g. building compound constant durations at compile time in a readable way.
This commit is contained in:
parent
213025f210
commit
0dfcaf1389
2 changed files with 76 additions and 80 deletions
71
AK/Time.cpp
71
AK/Time.cpp
|
@ -185,77 +185,6 @@ timeval Duration::to_timeval() const
|
|||
return { static_cast<sec_type>(m_seconds), static_cast<usec_type>(m_nanoseconds) / 1000 };
|
||||
}
|
||||
|
||||
Duration Duration::operator+(Duration const& other) const
|
||||
{
|
||||
VERIFY(m_nanoseconds < 1'000'000'000);
|
||||
VERIFY(other.m_nanoseconds < 1'000'000'000);
|
||||
|
||||
u32 new_nsecs = m_nanoseconds + other.m_nanoseconds;
|
||||
u32 extra_secs = new_nsecs / 1'000'000'000;
|
||||
new_nsecs %= 1'000'000'000;
|
||||
|
||||
i64 this_secs = m_seconds;
|
||||
i64 other_secs = other.m_seconds;
|
||||
// We would like to just add "this_secs + other_secs + extra_secs".
|
||||
// However, computing this naively may overflow even though the result is in-bounds.
|
||||
// Example in 8-bit: (-127) + (-2) + (+1) = (-128), which fits in an i8.
|
||||
// Example in 8-bit, the other way around: (-2) + (127) + (+1) = 126.
|
||||
// So we do something more sophisticated:
|
||||
if (extra_secs) {
|
||||
VERIFY(extra_secs == 1);
|
||||
if (this_secs != 0x7fff'ffff'ffff'ffff) {
|
||||
this_secs += 1;
|
||||
} else if (other_secs != 0x7fff'ffff'ffff'ffff) {
|
||||
other_secs += 1;
|
||||
} else {
|
||||
/* If *both* are INT64_MAX, then adding them will overflow in any case. */
|
||||
return Duration::max();
|
||||
}
|
||||
}
|
||||
|
||||
Checked<i64> new_secs { this_secs };
|
||||
new_secs += other_secs;
|
||||
if (new_secs.has_overflow()) {
|
||||
if (other_secs > 0)
|
||||
return Duration::max();
|
||||
else
|
||||
return Duration::min();
|
||||
}
|
||||
|
||||
return Duration { new_secs.value(), new_nsecs };
|
||||
}
|
||||
|
||||
Duration& Duration::operator+=(Duration const& other)
|
||||
{
|
||||
*this = *this + other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Duration Duration::operator-(Duration const& other) const
|
||||
{
|
||||
VERIFY(m_nanoseconds < 1'000'000'000);
|
||||
VERIFY(other.m_nanoseconds < 1'000'000'000);
|
||||
|
||||
if (other.m_nanoseconds)
|
||||
return *this + Duration((i64) ~(u64)other.m_seconds, 1'000'000'000 - other.m_nanoseconds);
|
||||
|
||||
if (other.m_seconds != (i64)-0x8000'0000'0000'0000)
|
||||
return *this + Duration(-other.m_seconds, 0);
|
||||
|
||||
// Only remaining case: We want to subtract -0x8000'0000'0000'0000 seconds,
|
||||
// i.e. add a very large number.
|
||||
|
||||
if (m_seconds >= 0)
|
||||
return Duration::max();
|
||||
return Duration { (m_seconds + 0x4000'0000'0000'0000) + 0x4000'0000'0000'0000, m_nanoseconds };
|
||||
}
|
||||
|
||||
Duration& Duration::operator-=(Duration const& other)
|
||||
{
|
||||
*this = *this - other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Duration Duration::from_half_sanitized(i64 seconds, i32 extra_seconds, u32 nanoseconds)
|
||||
{
|
||||
VERIFY(nanoseconds < 1'000'000'000);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue