libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers float_spec.cpp Source File

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 }