123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- /*
- * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
- */
- #include <gtest/gtest.h>
- #include <limits>
- #include <uavcan/marshal/types.hpp>
- #include <uavcan/transport/transfer_buffer.hpp>
- TEST(FloatSpec, Sizes)
- {
- uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<16>::Type) == 4>::check();
- uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<32>::Type) == 4>::check();
- uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<64>::Type) == 8>::check();
- uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<80>::Type) >= 10>::check();
- }
- TEST(FloatSpec, Limits)
- {
- using uavcan::FloatSpec;
- using uavcan::CastModeSaturate;
- using uavcan::CastModeTruncate;
- typedef FloatSpec<16, CastModeSaturate> F16S;
- typedef FloatSpec<32, CastModeTruncate> F32T;
- typedef FloatSpec<64, CastModeSaturate> F64S;
- ASSERT_FALSE(F16S::IsExactRepresentation);
- ASSERT_FLOAT_EQ(65504.0F, F16S::max());
- ASSERT_FLOAT_EQ(9.77e-04F, F16S::epsilon());
- ASSERT_TRUE(F32T::IsExactRepresentation);
- ASSERT_FLOAT_EQ(std::numeric_limits<float>::max(), F32T::max());
- ASSERT_FLOAT_EQ(std::numeric_limits<float>::epsilon(), F32T::epsilon());
- ASSERT_TRUE(F64S::IsExactRepresentation);
- ASSERT_DOUBLE_EQ(std::numeric_limits<double>::max(), F64S::max());
- ASSERT_DOUBLE_EQ(std::numeric_limits<double>::epsilon(), F64S::epsilon());
- }
- TEST(FloatSpec, Basic)
- {
- using uavcan::FloatSpec;
- using uavcan::CastModeSaturate;
- using uavcan::CastModeTruncate;
- using uavcan::StorageType;
- typedef FloatSpec<16, CastModeSaturate> F16S;
- typedef FloatSpec<16, CastModeTruncate> F16T;
- typedef FloatSpec<32, CastModeSaturate> F32S;
- typedef FloatSpec<32, CastModeTruncate> F32T;
- typedef FloatSpec<64, CastModeSaturate> F64S;
- typedef FloatSpec<64, CastModeTruncate> F64T;
- static const long double Values[] =
- {
- 0.0,
- 1.0,
- M_PI,
- 123,
- -123,
- 99999,
- -999999,
- std::numeric_limits<float>::max(),
- -std::numeric_limits<float>::max(),
- std::numeric_limits<double>::infinity(),
- -std::numeric_limits<double>::infinity(),
- nanl("")
- };
- static const int NumValues = int(sizeof(Values) / sizeof(Values[0]));
- static const long double ValuesF16S[] =
- {
- 0.0,
- 1.0,
- 3.140625,
- 123,
- -123,
- F16S::max(),
- -F16S::max(),
- F16S::max(),
- -F16S::max(),
- std::numeric_limits<F16S::StorageType>::infinity(),
- -std::numeric_limits<F16S::StorageType>::infinity(),
- nanl("")
- };
- static const long double ValuesF16T[] =
- {
- 0.0,
- 1.0,
- 3.140625,
- 123,
- -123,
- std::numeric_limits<F16S::StorageType>::infinity(),
- -std::numeric_limits<F16S::StorageType>::infinity(),
- std::numeric_limits<F16S::StorageType>::infinity(),
- -std::numeric_limits<F16S::StorageType>::infinity(),
- std::numeric_limits<F16S::StorageType>::infinity(),
- -std::numeric_limits<F16S::StorageType>::infinity(),
- nanl("")
- };
- /*
- * Writing
- */
- uavcan::StaticTransferBuffer<NumValues * (2 + 4 + 8) * 2> buf;
- uavcan::BitStream bs_wr(buf);
- uavcan::ScalarCodec sc_wr(bs_wr);
- for (int i = 0; i < NumValues; i++)
- {
- ASSERT_EQ(1, F16S::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F16T::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F32S::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F32T::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F64S::encode(double(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F64T::encode(double(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
- }
- ASSERT_EQ(0, F16S::encode(0, sc_wr, uavcan::TailArrayOptDisabled)); // Out of buffer space now
- /*
- * Reading
- */
- uavcan::BitStream bs_rd(buf);
- uavcan::ScalarCodec sc_rd(bs_rd);
- #define CHECK(FloatType, expected_value) \
- do { \
- StorageType<FloatType>::Type var = StorageType<FloatType>::Type(); \
- ASSERT_EQ(1, FloatType::decode(var, sc_rd, uavcan::TailArrayOptDisabled)); \
- if (!std::isnan(expected_value)) { \
- ASSERT_DOUBLE_EQ(expected_value, var); } \
- else { \
- ASSERT_EQ(!!std::isnan(expected_value), !!std::isnan(var)); } \
- } while (0)
- for (int i = 0; i < NumValues; i++)
- {
- CHECK(F16S, float(ValuesF16S[i]));
- CHECK(F16T, float(ValuesF16T[i]));
- CHECK(F32S, float(Values[i]));
- CHECK(F32T, float(Values[i]));
- CHECK(F64S, double(Values[i]));
- CHECK(F64T, double(Values[i]));
- }
- #undef CHECK
- }
- TEST(FloatSpec, Float16Representation)
- {
- using uavcan::FloatSpec;
- using uavcan::CastModeSaturate;
- using uavcan::CastModeTruncate;
- typedef FloatSpec<16, CastModeSaturate> F16S;
- typedef FloatSpec<16, CastModeTruncate> F16T;
- uavcan::StaticTransferBuffer<2 * 6> buf;
- uavcan::BitStream bs_wr(buf);
- uavcan::ScalarCodec sc_wr(bs_wr);
- ASSERT_EQ(1, F16S::encode(0.0, sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F16S::encode(1.0, sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F16S::encode(-2.0, sc_wr, uavcan::TailArrayOptDisabled));
- ASSERT_EQ(1, F16T::encode(999999, sc_wr, uavcan::TailArrayOptDisabled)); // +inf
- ASSERT_EQ(1, F16S::encode(-999999, sc_wr, uavcan::TailArrayOptDisabled)); // -max
- ASSERT_EQ(1, F16S::encode(float(nan("")), sc_wr, uavcan::TailArrayOptDisabled)); // nan
- ASSERT_EQ(0, F16S::encode(0, sc_wr, uavcan::TailArrayOptDisabled)); // Out of buffer space now
- // Keep in mind that this is LITTLE ENDIAN representation
- static const std::string Reference =
- "00000000 00000000 " // 0.0
- "00000000 00111100 " // 1.0
- "00000000 11000000 " // -2.0
- "00000000 01111100 " // +inf
- "11111111 11111011 " // -max
- "11111111 01111111"; // nan
- ASSERT_EQ(Reference, bs_wr.toString());
- }
|