/*
replaced: TEST_ASSERT_EQUAL_MEMORY(&a, &b, sizeof(a))
with: TEST_ASSERT_EQUAL_l_fp(a, b).
It's safer this way, because structs can be compared even if they
aren't initiated with memset (due to padding bytes).
*/
#define TEST_ASSERT_EQUAL_l_fp(a, b) { \
TEST_ASSERT_EQUAL_MESSAGE(a.l_i, b.l_i, "Field l_i"); \
TEST_ASSERT_EQUAL_UINT_MESSAGE(a.l_uf, b.l_uf, "Field l_uf"); \
}
//----------------------------------------------------------------------
// reference comparision
// This is implementad as a full signed MP-subtract in 3 limbs, where
// the operands are zero or sign extended before the subtraction is
// executed.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// imlementation of the LFP stuff
// This should be easy enough...
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// testing the relational macros works better with proper predicate
// formatting functions; it slows down the tests a bit, but makes for
// readable failure messages.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// test data table for add/sub and compare
//----------------------------------------------------------------------
static const lfp_hl addsub_tab[][3] = {
// trivial idendity:
{{0 ,0 }, { 0,0 }, { 0,0}},
// with carry from fraction and sign change:
{{-1,0x80000000}, { 0,0x80000000}, { 0,0}},
// without carry from fraction
{{ 1,0x40000000}, { 1,0x40000000}, { 2,0x80000000}},
// with carry from fraction:
{{ 1,0xC0000000}, { 1,0xC0000000}, { 3,0x80000000}},
// with carry from fraction and sign change:
{{0x7FFFFFFF, 0x7FFFFFFF}, {0x7FFFFFFF,0x7FFFFFFF}, {0xFFFFFFFE,0xFFFFFFFE}},
// two tests w/o carry (used for l_fp<-->double):
{{0x55555555,0xAAAAAAAA}, {0x11111111,0x11111111}, {0x66666666,0xBBBBBBBB}},
{{0x55555555,0x55555555}, {0x11111111,0x11111111}, {0x66666666,0x66666666}},
// wide-range test, triggers compare trouble
{{0x80000000,0x00000001}, {0xFFFFFFFF,0xFFFFFFFE}, {0x7FFFFFFF,0xFFFFFFFF}}
};
static const size_t addsub_cnt = (sizeof(addsub_tab)/sizeof(addsub_tab[0]));
static const size_t addsub_tot = (sizeof(addsub_tab)/sizeof(addsub_tab[0][0]));
//----------------------------------------------------------------------
// epsilon estimation for the precision of a conversion double --> l_fp
//
// The error estimation limit is as follows:
// * The 'l_fp' fixed point fraction has 32 bits precision, so we allow
// for the LSB to toggle by clamping the epsilon to be at least 2^(-31)
//
// * The double mantissa has a precsion 54 bits, so the other minimum is
// dval * (2^(-53))
//
// The maximum of those two boundaries is used for the check.
//
// Note: once there are more than 54 bits between the highest and lowest
// '1'-bit of the l_fp value, the roundtrip *will* create truncation
// errors. This is an inherent property caused by the 54-bit mantissa of
// the 'double' type.
double
eps(double d)
{
//----------------------------------------------------------------------
// test negation
//----------------------------------------------------------------------
// There is one special case we have to check: the minimum
// value cannot be negated, or, to be more precise, the
// negation reproduces the original pattern.
l_fp minVal = l_fp_init(0x80000000, 0x00000000);
l_fp minAbs = l_fp_abs(minVal);
TEST_ASSERT_EQUAL(-1, l_fp_signum(minVal));
// since a l_fp has 64 bits in it's mantissa and a double has
// only 54 bits available (including the hidden '1') we have to
// make a few concessions on the roundtrip precision. The 'eps()'
// function makes an educated guess about the avilable precision
// and checks the difference in the two 'l_fp' values against
// that limit.
//----------------------------------------------------------------------
// test the compare stuff
//
// This uses the local compare and checks if the operations using the
// macros in 'ntp_fp.h' produce mathing results.
// ----------------------------------------------------------------------
void
test_SignedRelOps(void)
{
const lfp_hl * tv = (&addsub_tab[0][0]);
size_t lc ;
//----------------------------------------------------------------------
// that's all folks... but feel free to add things!
//----------------------------------------------------------------------