float_spec.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <gtest/gtest.h>
  5. #include <limits>
  6. #include <uavcan/marshal/types.hpp>
  7. #include <uavcan/transport/transfer_buffer.hpp>
  8. TEST(FloatSpec, Sizes)
  9. {
  10. uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<16>::Type) == 4>::check();
  11. uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<32>::Type) == 4>::check();
  12. uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<64>::Type) == 8>::check();
  13. uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<80>::Type) >= 10>::check();
  14. }
  15. TEST(FloatSpec, Limits)
  16. {
  17. using uavcan::FloatSpec;
  18. using uavcan::CastModeSaturate;
  19. using uavcan::CastModeTruncate;
  20. typedef FloatSpec<16, CastModeSaturate> F16S;
  21. typedef FloatSpec<32, CastModeTruncate> F32T;
  22. typedef FloatSpec<64, CastModeSaturate> F64S;
  23. ASSERT_FALSE(F16S::IsExactRepresentation);
  24. ASSERT_FLOAT_EQ(65504.0F, F16S::max());
  25. ASSERT_FLOAT_EQ(9.77e-04F, F16S::epsilon());
  26. ASSERT_TRUE(F32T::IsExactRepresentation);
  27. ASSERT_FLOAT_EQ(std::numeric_limits<float>::max(), F32T::max());
  28. ASSERT_FLOAT_EQ(std::numeric_limits<float>::epsilon(), F32T::epsilon());
  29. ASSERT_TRUE(F64S::IsExactRepresentation);
  30. ASSERT_DOUBLE_EQ(std::numeric_limits<double>::max(), F64S::max());
  31. ASSERT_DOUBLE_EQ(std::numeric_limits<double>::epsilon(), F64S::epsilon());
  32. }
  33. TEST(FloatSpec, Basic)
  34. {
  35. using uavcan::FloatSpec;
  36. using uavcan::CastModeSaturate;
  37. using uavcan::CastModeTruncate;
  38. using uavcan::StorageType;
  39. typedef FloatSpec<16, CastModeSaturate> F16S;
  40. typedef FloatSpec<16, CastModeTruncate> F16T;
  41. typedef FloatSpec<32, CastModeSaturate> F32S;
  42. typedef FloatSpec<32, CastModeTruncate> F32T;
  43. typedef FloatSpec<64, CastModeSaturate> F64S;
  44. typedef FloatSpec<64, CastModeTruncate> F64T;
  45. static const long double Values[] =
  46. {
  47. 0.0,
  48. 1.0,
  49. M_PI,
  50. 123,
  51. -123,
  52. 99999,
  53. -999999,
  54. std::numeric_limits<float>::max(),
  55. -std::numeric_limits<float>::max(),
  56. std::numeric_limits<double>::infinity(),
  57. -std::numeric_limits<double>::infinity(),
  58. nanl("")
  59. };
  60. static const int NumValues = int(sizeof(Values) / sizeof(Values[0]));
  61. static const long double ValuesF16S[] =
  62. {
  63. 0.0,
  64. 1.0,
  65. 3.140625,
  66. 123,
  67. -123,
  68. F16S::max(),
  69. -F16S::max(),
  70. F16S::max(),
  71. -F16S::max(),
  72. std::numeric_limits<F16S::StorageType>::infinity(),
  73. -std::numeric_limits<F16S::StorageType>::infinity(),
  74. nanl("")
  75. };
  76. static const long double ValuesF16T[] =
  77. {
  78. 0.0,
  79. 1.0,
  80. 3.140625,
  81. 123,
  82. -123,
  83. std::numeric_limits<F16S::StorageType>::infinity(),
  84. -std::numeric_limits<F16S::StorageType>::infinity(),
  85. std::numeric_limits<F16S::StorageType>::infinity(),
  86. -std::numeric_limits<F16S::StorageType>::infinity(),
  87. std::numeric_limits<F16S::StorageType>::infinity(),
  88. -std::numeric_limits<F16S::StorageType>::infinity(),
  89. nanl("")
  90. };
  91. /*
  92. * Writing
  93. */
  94. uavcan::StaticTransferBuffer<NumValues * (2 + 4 + 8) * 2> buf;
  95. uavcan::BitStream bs_wr(buf);
  96. uavcan::ScalarCodec sc_wr(bs_wr);
  97. for (int i = 0; i < NumValues; i++)
  98. {
  99. ASSERT_EQ(1, F16S::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
  100. ASSERT_EQ(1, F16T::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
  101. ASSERT_EQ(1, F32S::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
  102. ASSERT_EQ(1, F32T::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
  103. ASSERT_EQ(1, F64S::encode(double(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
  104. ASSERT_EQ(1, F64T::encode(double(Values[i]), sc_wr, uavcan::TailArrayOptDisabled));
  105. }
  106. ASSERT_EQ(0, F16S::encode(0, sc_wr, uavcan::TailArrayOptDisabled)); // Out of buffer space now
  107. /*
  108. * Reading
  109. */
  110. uavcan::BitStream bs_rd(buf);
  111. uavcan::ScalarCodec sc_rd(bs_rd);
  112. #define CHECK(FloatType, expected_value) \
  113. do { \
  114. StorageType<FloatType>::Type var = StorageType<FloatType>::Type(); \
  115. ASSERT_EQ(1, FloatType::decode(var, sc_rd, uavcan::TailArrayOptDisabled)); \
  116. if (!std::isnan(expected_value)) { \
  117. ASSERT_DOUBLE_EQ(expected_value, var); } \
  118. else { \
  119. ASSERT_EQ(!!std::isnan(expected_value), !!std::isnan(var)); } \
  120. } while (0)
  121. for (int i = 0; i < NumValues; i++)
  122. {
  123. CHECK(F16S, float(ValuesF16S[i]));
  124. CHECK(F16T, float(ValuesF16T[i]));
  125. CHECK(F32S, float(Values[i]));
  126. CHECK(F32T, float(Values[i]));
  127. CHECK(F64S, double(Values[i]));
  128. CHECK(F64T, double(Values[i]));
  129. }
  130. #undef CHECK
  131. }
  132. TEST(FloatSpec, Float16Representation)
  133. {
  134. using uavcan::FloatSpec;
  135. using uavcan::CastModeSaturate;
  136. using uavcan::CastModeTruncate;
  137. typedef FloatSpec<16, CastModeSaturate> F16S;
  138. typedef FloatSpec<16, CastModeTruncate> F16T;
  139. uavcan::StaticTransferBuffer<2 * 6> buf;
  140. uavcan::BitStream bs_wr(buf);
  141. uavcan::ScalarCodec sc_wr(bs_wr);
  142. ASSERT_EQ(1, F16S::encode(0.0, sc_wr, uavcan::TailArrayOptDisabled));
  143. ASSERT_EQ(1, F16S::encode(1.0, sc_wr, uavcan::TailArrayOptDisabled));
  144. ASSERT_EQ(1, F16S::encode(-2.0, sc_wr, uavcan::TailArrayOptDisabled));
  145. ASSERT_EQ(1, F16T::encode(999999, sc_wr, uavcan::TailArrayOptDisabled)); // +inf
  146. ASSERT_EQ(1, F16S::encode(-999999, sc_wr, uavcan::TailArrayOptDisabled)); // -max
  147. ASSERT_EQ(1, F16S::encode(float(nan("")), sc_wr, uavcan::TailArrayOptDisabled)); // nan
  148. ASSERT_EQ(0, F16S::encode(0, sc_wr, uavcan::TailArrayOptDisabled)); // Out of buffer space now
  149. // Keep in mind that this is LITTLE ENDIAN representation
  150. static const std::string Reference =
  151. "00000000 00000000 " // 0.0
  152. "00000000 00111100 " // 1.0
  153. "00000000 11000000 " // -2.0
  154. "00000000 01111100 " // +inf
  155. "11111111 11111011 " // -max
  156. "11111111 01111111"; // nan
  157. ASSERT_EQ(Reference, bs_wr.toString());
  158. }