summaryrefslogtreecommitdiff
path: root/cesar/lib/src/utils.c
blob: 4ca7b39654d214e6e5996205c83837b4e448a438 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Cesar project {{{
 *
 * Copyright (C) 2011 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    lib/src/utils.c
 * \brief   Common utilities.
 * \ingroup lib
 */
#include "common/std.h"

/* See
 * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
 */
bool
almost_eqf (float a, float b, int max_ulps)
{
    union
    {
        float f;
        s32 i;
    } aInt, bInt;
    /* Make sure max_ulps is non-negative and small enough that the default
     * NAN won't compare as equal to anything. */
    dbg_assert (max_ulps > 0 && max_ulps < 4 * 1024 * 1024);
    aInt.f = a;
    /* Make aInt lexicographically ordered as a twos-complement int. */
    if (aInt.i < 0)
        aInt.i = 0x80000000 - aInt.i;
    /* Make bInt lexicographically ordered as a twos-complement int. */
    bInt.f = b;
    if (bInt.i < 0)
        bInt.i = 0x80000000 - bInt.i;
    s32 intDiff = ABS (aInt.i - bInt.i);
    if (intDiff <= max_ulps)
        return true;
    return false;
}