libuav original
Dependents: UAVCAN UAVCAN_Subscriber
float_spec.cpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #include <gtest/gtest.h> 00006 #include <limits> 00007 #include <uavcan/marshal/types.hpp> 00008 #include <uavcan/transport/transfer_buffer.hpp> 00009 00010 00011 TEST(FloatSpec, Sizes) 00012 { 00013 uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<16>::Type) == 4>::check(); 00014 uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<32>::Type) == 4>::check(); 00015 uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<64>::Type) == 8>::check(); 00016 uavcan::StaticAssert<sizeof(uavcan::NativeFloatSelector<80>::Type) >= 10>::check(); 00017 } 00018 00019 TEST(FloatSpec, Limits) 00020 { 00021 using uavcan::FloatSpec; 00022 using uavcan::CastModeSaturate; 00023 using uavcan::CastModeTruncate; 00024 00025 typedef FloatSpec<16, CastModeSaturate> F16S; 00026 typedef FloatSpec<32, CastModeTruncate> F32T; 00027 typedef FloatSpec<64, CastModeSaturate> F64S; 00028 00029 ASSERT_FALSE(F16S::IsExactRepresentation); 00030 ASSERT_FLOAT_EQ(65504.0F, F16S::max()); 00031 ASSERT_FLOAT_EQ(9.77e-04F, F16S::epsilon()); 00032 00033 ASSERT_TRUE(F32T::IsExactRepresentation); 00034 ASSERT_FLOAT_EQ(std::numeric_limits<float>::max(), F32T::max()); 00035 ASSERT_FLOAT_EQ(std::numeric_limits<float>::epsilon(), F32T::epsilon()); 00036 00037 ASSERT_TRUE(F64S::IsExactRepresentation); 00038 ASSERT_DOUBLE_EQ(std::numeric_limits<double>::max(), F64S::max()); 00039 ASSERT_DOUBLE_EQ(std::numeric_limits<double>::epsilon(), F64S::epsilon()); 00040 } 00041 00042 TEST(FloatSpec, Basic) 00043 { 00044 using uavcan::FloatSpec; 00045 using uavcan::CastModeSaturate; 00046 using uavcan::CastModeTruncate; 00047 using uavcan::StorageType; 00048 00049 typedef FloatSpec<16, CastModeSaturate> F16S; 00050 typedef FloatSpec<16, CastModeTruncate> F16T; 00051 typedef FloatSpec<32, CastModeSaturate> F32S; 00052 typedef FloatSpec<32, CastModeTruncate> F32T; 00053 typedef FloatSpec<64, CastModeSaturate> F64S; 00054 typedef FloatSpec<64, CastModeTruncate> F64T; 00055 00056 static const long double Values[] = 00057 { 00058 0.0, 00059 1.0, 00060 M_PI, 00061 123, 00062 -123, 00063 99999, 00064 -999999, 00065 std::numeric_limits<float>::max(), 00066 -std::numeric_limits<float>::max(), 00067 std::numeric_limits<double>::infinity(), 00068 -std::numeric_limits<double>::infinity(), 00069 nanl("") 00070 }; 00071 static const int NumValues = int(sizeof(Values) / sizeof(Values[0])); 00072 00073 static const long double ValuesF16S[] = 00074 { 00075 0.0, 00076 1.0, 00077 3.140625, 00078 123, 00079 -123, 00080 F16S::max(), 00081 -F16S::max(), 00082 F16S::max(), 00083 -F16S::max(), 00084 std::numeric_limits<F16S::StorageType>::infinity(), 00085 -std::numeric_limits<F16S::StorageType>::infinity(), 00086 nanl("") 00087 }; 00088 static const long double ValuesF16T[] = 00089 { 00090 0.0, 00091 1.0, 00092 3.140625, 00093 123, 00094 -123, 00095 std::numeric_limits<F16S::StorageType>::infinity(), 00096 -std::numeric_limits<F16S::StorageType>::infinity(), 00097 std::numeric_limits<F16S::StorageType>::infinity(), 00098 -std::numeric_limits<F16S::StorageType>::infinity(), 00099 std::numeric_limits<F16S::StorageType>::infinity(), 00100 -std::numeric_limits<F16S::StorageType>::infinity(), 00101 nanl("") 00102 }; 00103 00104 /* 00105 * Writing 00106 */ 00107 uavcan::StaticTransferBuffer<NumValues * (2 + 4 + 8) * 2> buf; 00108 uavcan::BitStream bs_wr(buf); 00109 uavcan::ScalarCodec sc_wr(bs_wr); 00110 00111 for (int i = 0; i < NumValues; i++) 00112 { 00113 ASSERT_EQ(1, F16S::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled)); 00114 ASSERT_EQ(1, F16T::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled)); 00115 ASSERT_EQ(1, F32S::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled)); 00116 ASSERT_EQ(1, F32T::encode(float(Values[i]), sc_wr, uavcan::TailArrayOptDisabled)); 00117 ASSERT_EQ(1, F64S::encode(double(Values[i]), sc_wr, uavcan::TailArrayOptDisabled)); 00118 ASSERT_EQ(1, F64T::encode(double(Values[i]), sc_wr, uavcan::TailArrayOptDisabled)); 00119 } 00120 00121 ASSERT_EQ(0, F16S::encode(0, sc_wr, uavcan::TailArrayOptDisabled)); // Out of buffer space now 00122 00123 /* 00124 * Reading 00125 */ 00126 uavcan::BitStream bs_rd(buf); 00127 uavcan::ScalarCodec sc_rd(bs_rd); 00128 00129 #define CHECK(FloatType, expected_value) \ 00130 do { \ 00131 StorageType<FloatType>::Type var = StorageType<FloatType>::Type(); \ 00132 ASSERT_EQ(1, FloatType::decode(var, sc_rd, uavcan::TailArrayOptDisabled)); \ 00133 if (!std::isnan(expected_value)) { \ 00134 ASSERT_DOUBLE_EQ(expected_value, var); } \ 00135 else { \ 00136 ASSERT_EQ(!!std::isnan(expected_value), !!std::isnan(var)); } \ 00137 } while (0) 00138 00139 for (int i = 0; i < NumValues; i++) 00140 { 00141 CHECK(F16S, float(ValuesF16S[i])); 00142 CHECK(F16T, float(ValuesF16T[i])); 00143 CHECK(F32S, float(Values[i])); 00144 CHECK(F32T, float(Values[i])); 00145 CHECK(F64S, double(Values[i])); 00146 CHECK(F64T, double(Values[i])); 00147 } 00148 00149 #undef CHECK 00150 } 00151 00152 TEST(FloatSpec, Float16Representation) 00153 { 00154 using uavcan::FloatSpec; 00155 using uavcan::CastModeSaturate; 00156 using uavcan::CastModeTruncate; 00157 00158 typedef FloatSpec<16, CastModeSaturate> F16S; 00159 typedef FloatSpec<16, CastModeTruncate> F16T; 00160 00161 uavcan::StaticTransferBuffer<2 * 6> buf; 00162 uavcan::BitStream bs_wr(buf); 00163 uavcan::ScalarCodec sc_wr(bs_wr); 00164 00165 ASSERT_EQ(1, F16S::encode(0.0, sc_wr, uavcan::TailArrayOptDisabled)); 00166 ASSERT_EQ(1, F16S::encode(1.0, sc_wr, uavcan::TailArrayOptDisabled)); 00167 ASSERT_EQ(1, F16S::encode(-2.0, sc_wr, uavcan::TailArrayOptDisabled)); 00168 ASSERT_EQ(1, F16T::encode(999999, sc_wr, uavcan::TailArrayOptDisabled)); // +inf 00169 ASSERT_EQ(1, F16S::encode(-999999, sc_wr, uavcan::TailArrayOptDisabled)); // -max 00170 ASSERT_EQ(1, F16S::encode(float(nan("")), sc_wr, uavcan::TailArrayOptDisabled)); // nan 00171 00172 ASSERT_EQ(0, F16S::encode(0, sc_wr, uavcan::TailArrayOptDisabled)); // Out of buffer space now 00173 00174 // Keep in mind that this is LITTLE ENDIAN representation 00175 static const std::string Reference = 00176 "00000000 00000000 " // 0.0 00177 "00000000 00111100 " // 1.0 00178 "00000000 11000000 " // -2.0 00179 "00000000 01111100 " // +inf 00180 "11111111 11111011 " // -max 00181 "11111111 01111111"; // nan 00182 00183 ASSERT_EQ(Reference, bs_wr.toString()); 00184 }
Generated on Tue Jul 12 2022 17:17:31 by 1.7.2