Scaled channel ints (#4129)

* test that fails today

* Revert "int32 scaled_channel has float precision #4128"

This reverts commit 03d44b75ea.

* fix the problem

* format

* x

* s
This commit is contained in:
Matthew Kennedy 2022-05-02 12:20:02 -07:00 committed by GitHub
parent aa8e0859d7
commit 58619b4115
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 14 deletions

View File

@ -32,19 +32,30 @@ class scaled_channel : scaled_channel_base {
using TSelf = scaled_channel<T, mul, div>;
public:
struct IncompleteType;
constexpr scaled_channel() : m_value(static_cast<T>(0)) { }
constexpr scaled_channel(float val)
{
val *= float(mul) / div;
if (std::is_integral_v<T>) {
m_value = std::roundf(val);
} else {
m_value = val;
}
// Only allow conversion directly to T when mul/div are both 1, otherwise this constructor doesn't exist and the float conversion is used.
constexpr scaled_channel(std::conditional_t<mul == 1 && div == 1, T, IncompleteType> val) {
m_value = val;
}
// Scale the float in to our scaled channel
constexpr scaled_channel(std::conditional_t<mul != 1 || div != 1, float, IncompleteType> val) {
// If there are scale factors, it must NOT be a float. Why would you scale a float?
static_assert(std::is_integral_v<T>);
m_value = std::roundf(val * float(mul) / div);
}
// Only allow conversion directly to T when mul/div are both 1, otherwise this operator doesn't exist and the float conversion is used.
constexpr operator typename std::conditional_t<mul == 1 && div == 1, T, IncompleteType>() const {
return m_value;
}
// Allow reading back out as a float (note: this may be lossy!)
constexpr operator float() const {
constexpr operator typename std::conditional_t<mul != 1 || div != 1, float, IncompleteType>() const {
return m_value * (float(div) / mul);
}
@ -56,7 +67,6 @@ public:
static_assert(mul == 1 && div == 1,
"Increment operator only supported for non-scaled integer types");
static_assert(std::is_integral_v<T>, "Increment operator only supported for non-scaled integer types");
m_value++;
}

View File

@ -9,7 +9,8 @@ import org.junit.Test;
import java.nio.ByteBuffer;
import static com.rusefi.config.generated.Fields.*;
import static com.rusefi.config.generated.Fields.TS_FILE_VERSION;
import static com.rusefi.config.generated.Fields.engine_type_e_MRE_MIATA_NB2_MAP;
import static com.rusefi.shared.FileUtil.littleEndianWrap;
import static junit.framework.Assert.*;
@ -24,10 +25,7 @@ public class JniUnitTest {
engineLogic.invokePeriodicCallback();
/*
todo: fix me https://github.com/rusefi/rusefi/issues/4128
assertEquals(TS_FILE_VERSION, (int) getValue(engineLogic.getOutputs(), Sensor.FIRMWARE_VERSION));
*/
assertEquals(14.0, getValue(engineLogic.getOutputs(), Sensor.TARGET_AFR));
double veValue = getValue(engineLogic.getOutputs(), Sensor.veValue);

View File

@ -32,3 +32,14 @@ TEST(ScaledChannel, Basic) {
i2 = -11; EXPECT_FLOAT_EQ(i2, -10); // round
}
}
TEST(ScaledChannel, IntegerBehavior) {
scaled_channel<uint32_t, 1, 1> test;
// Check that a round trip thru scaled_channel gets us back the same integer
uint32_t a = 20210311;
test = a;
uint32_t b = test;
EXPECT_EQ(a, b);
}