mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare/unit] Fix rational exponent rounding
In metric, sqrt(N) would be simplified to _N_kg^-0.5_m^-0.5_s instead of _kg^0.5_m^0.5_s^-1. We solve this issue by preventing simplification using derived units in presence of rational exponents. Change-Id: I97118bb32c963809c8d176b7b297d1682965e9af
This commit is contained in:
committed by
Émilie Feral
parent
4ba0603e0c
commit
d862d5503c
@@ -440,10 +440,9 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu
|
||||
* - Repeat those steps until no more simplification is possible.
|
||||
*/
|
||||
Multiplication unitsAccu = Multiplication::Builder();
|
||||
/* If exponents are not integers, FromBaseUnits will return the closest
|
||||
* representation of units with base units and integer exponents.
|
||||
* It cause no problem because once the best derived units are found,
|
||||
* units is divided then multiplied by them. */
|
||||
/* If exponents are not integers, FromBaseUnits will return a null
|
||||
* vector, preventing any attempt at simplification. This protects us
|
||||
* against undue "simplifications" such as _C^1.3 -> _C*_A^0.3*_s^0.3 */
|
||||
UnitNode::Vector<int> unitsExponents = UnitNode::Vector<int>::FromBaseUnits(units);
|
||||
size_t unitsSupportSize = unitsExponents.supportSize();
|
||||
UnitNode::Vector<int> bestRemainderExponents;
|
||||
|
||||
@@ -128,6 +128,12 @@ UnitNode::Vector<int> UnitNode::Vector<int>::FromBaseUnits(const Expression base
|
||||
assert(exp.type() == ExpressionNode::Type::Rational);
|
||||
// Using the closest integer to the exponent.
|
||||
float exponentFloat = static_cast<const Rational &>(exp).node()->templatedApproximate<float>();
|
||||
if (exponentFloat != std::round(exponentFloat)) {
|
||||
/* If non-integer exponents are found, we round a null vector so that
|
||||
* Multiplication::shallowBeautify will not attempt to find derived
|
||||
* units. */
|
||||
return vector;
|
||||
}
|
||||
/* We limit to INT_MAX / 3 because an exponent might get bigger with
|
||||
* simplification. As a worst case scenario, (_s²_m²_kg/_A²)^n should be
|
||||
* simplified to (_s^5_S)^n. If 2*n is under INT_MAX, 5*n might not. */
|
||||
|
||||
@@ -361,6 +361,13 @@ QUIZ_CASE(poincare_simplification_units) {
|
||||
assert_parsed_expression_simplify_to("1/(-3_°C)", Undefined::Name());
|
||||
assert_parsed_expression_simplify_to("-1×100×_°C→_K", Undefined::Name());
|
||||
|
||||
/* Rational exponents */
|
||||
assert_parsed_expression_simplify_to("√(_m)", "1×_m^\u00121/2\u0013");
|
||||
assert_parsed_expression_simplify_to("√(_N)", "1×_kg^\u00121/2\u0013×_m^\u00121/2\u0013×_s^\u0012-1\u0013");
|
||||
assert_parsed_expression_simplify_to("√(_N)", "1.5527410012845×_lb^\u00121/2\u0013×_yd^\u00121/2\u0013×_s^\u0012-1\u0013", User, Radian, Imperial);
|
||||
assert_parsed_expression_simplify_to("_C^0.3", "1×_A^\u00123/10\u0013×_s^\u00123/10\u0013");
|
||||
assert_parsed_expression_simplify_to("_kat_kg^-2.8", "1×_mol×_kg^\u0012-14/5\u0013×_s^\u0012-1\u0013");
|
||||
|
||||
/* Unit sum/subtract */
|
||||
assert_parsed_expression_simplify_to("_m+_m", "2×_m");
|
||||
assert_parsed_expression_simplify_to("_m-_m", "0×_m");
|
||||
@@ -528,6 +535,7 @@ QUIZ_CASE(poincare_simplification_units) {
|
||||
assert_parsed_expression_simplify_to("-2×_A", "-2×_A");
|
||||
assert_parsed_expression_simplify_to("cos(1_s/1_s)", "cos(1)");
|
||||
assert_parsed_expression_simplify_to("1_m+π_m+√(2)_m-cos(15)_m", "6.3154941288217×_m");
|
||||
assert_parsed_expression_simplify_to("√(16×_m^2)", "4×_m");
|
||||
}
|
||||
|
||||
QUIZ_CASE(poincare_simplification_power) {
|
||||
|
||||
Reference in New Issue
Block a user