Skip to content

Commit

Permalink
value: Tidy
Browse files Browse the repository at this point in the history
  • Loading branch information
lhmouse committed Dec 4, 2023
1 parent e4c9158 commit 2b9f5f3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 69 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ END =
AM_CPPFLAGS = -pipe -Wall -Wextra @host_asm_opt@ -Iasteria \
-U_FORTIFY_SOURCE -D_FILE_OFFSET_BITS=64 -D_POSIX_C_SOURCE=200809 \
-D_BSD_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -D_DARWIN_C_SOURCE \
-f{strict-{aliasing,overflow},merge-all-constants} \
-f{strict-{aliasing,overflow},merge-all-constants,rounding-math} \
-fno-{stack-protector,align-{functions,jumps,loops}} \
-fno-{math-errno,trapping-math} \
-fno-{devirtualize-speculatively,semantic-interposition,ident} \
Expand Down
134 changes: 66 additions & 68 deletions asteria/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,6 @@ struct Rbr_object

using Rbr_Element = ::rocket::variant<Rbr_array, Rbr_object>;

char
do_compare_real_integer(V_real xreal, V_integer yint)
{
// Cast `yint` to a real number. The result is exact if `yint` contains
// no more than significant 53 bits. If that is not the case, it will
// have to be rounded towards negative infinity.
::fesetround(FE_DOWNWARD);
V_real yreal = static_cast<V_real>(yint);
V_integer ytest = static_cast<V_integer>(yreal);
::fesetround(FE_TONEAREST);

// Perform plain comparison now.
if(::std::isunordered(xreal, yreal))
return '?';
else if(::std::isgreater(xreal, yreal))
return '>';
else if(::std::isless(xreal, yreal) || (yint != ytest)) // imprecise
return '<';
else
return '=';
}

} // namespace

ROCKET_NEVER_INLINE void
Expand Down Expand Up @@ -229,66 +207,86 @@ Compare
Value::
compare_numeric_partial(V_integer other) const noexcept
{
switch(this->m_stor.index()) {
case type_integer: {
V_integer value = this->m_stor.as<V_integer>();
if(value < other)
return compare_less;
else if(value > other)
return compare_greater;
else
return compare_equal;
}
if(this->m_stor.index() == type_integer) {
// total
V_integer value = this->m_stor.as<V_integer>();

case type_real: {
char r = do_compare_real_integer(this->m_stor.as<V_real>(), other);
if(r == '<')
return compare_less;
else if(r == '>')
return compare_greater;
else if(r == '?')
return compare_unordered;
else
return compare_equal;
}
if(value < other)
return compare_less;
else if(value > other)
return compare_greater;
else
return compare_equal;
}

default:
if(this->m_stor.index() == type_real) {
// partial
V_real value = this->m_stor.as<V_real>();

// assert `otest <= oreal <= other`
::std::fesetround(FE_DOWNWARD);
V_real oreal = static_cast<V_real>(other);
V_integer otest = static_cast<V_integer>(oreal);
::std::fesetround(FE_TONEAREST);

if(::std::isless(value, oreal))
return compare_less;
else if(::std::isgreater(value, oreal))
return compare_greater;
else if(::std::isunordered(value, oreal))
return compare_unordered;
else if(otest != other)
return compare_less;
else
return compare_equal;
}

// incomparable
return compare_unordered;
}

Compare
Value::
compare_numeric_partial(V_real other) const noexcept
{
switch(this->m_stor.index()) {
case type_integer: {
char r = do_compare_real_integer(other, this->m_stor.as<V_integer>());
if(r == '>')
return compare_less;
else if(r == '<')
return compare_greater;
else if(r == '?')
return compare_unordered;
else
return compare_equal;
}
if(this->m_stor.index() == type_integer) {
// partial
V_integer value = this->m_stor.as<V_integer>();

case type_real: {
V_real value = this->m_stor.as<V_real>();
if(::std::isless(value, other))
return compare_less;
else if(::std::isgreater(value, other))
return compare_greater;
else if(::std::isunordered(value, other))
return compare_unordered;
else
return compare_equal;
}
// assert `vtest <= vreal <= value`
::std::fesetround(FE_DOWNWARD);
V_real vreal = static_cast<V_real>(value);
V_integer vtest = static_cast<V_integer>(vreal);
::std::fesetround(FE_TONEAREST);

default:
if(::std::isless(vreal, other))
return compare_less;
else if(::std::isgreater(vreal, other))
return compare_greater;
else if(::std::isunordered(vreal, other))
return compare_unordered;
else if(vtest != value)
return compare_greater;
else
return compare_equal;
}

if(this->m_stor.index() == type_real) {
// partial
V_real value = this->m_stor.as<V_real>();

if(::std::isless(value, other))
return compare_less;
else if(::std::isgreater(value, other))
return compare_greater;
else if(::std::isunordered(value, other))
return compare_unordered;
else
return compare_equal;
}

// incomparable
return compare_unordered;
}

Compare
Expand Down
9 changes: 9 additions & 0 deletions test/operators_o0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,15 @@ int main()
assert (nan </> 1.0) == true;
assert (nan </> 1) == true;
assert 0x7ffffffffffffc00 == 0x7ffffffffffffc00.0;
assert 0x7ffffffffffffc00 == 0x7ffffffffffffc01.0;
assert 0x7ffffffffffffc01 > 0x7ffffffffffffc00.0;
assert 0x7ffffffffffffc01 * 1.0 == 0x7ffffffffffffc00.0; // precision lost
assert 0x7ffffffffffffc00.0 == 0x7ffffffffffffc00;
assert 0x7ffffffffffffc01.0 == 0x7ffffffffffffc00;
assert 0x7ffffffffffffc00.0 < 0x7ffffffffffffc01;
assert 0x7ffffffffffffc00.0 == 0x7ffffffffffffc01 * 1.0; // precision lost
assert (true & true) == true;
assert (false & true) == false;
assert (true & false) == false;
Expand Down

0 comments on commit 2b9f5f3

Please sign in to comment.