summaryrefslogtreecommitdiff
path: root/libs/geometry/test/util/math_sqrt.cpp
blob: 2ca4834a156bca912fc774787d90aecee864feb5 (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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test

// Copyright (c) 2014, Oracle and/or its affiliates.

// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle

// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html

#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_math_sqrt
#endif

#include <cmath>
#include <iostream>

#include <boost/test/included/unit_test.hpp>

#include <boost/config.hpp>
#include <boost/type_traits/is_fundamental.hpp>

#include "number_types.hpp"

// important: the include above must precede the include below,
// otherwise the test will fail for the custom number type:
// custom_with_global_sqrt

#include <boost/geometry/util/math.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>

#ifdef HAVE_TTMATH
#  include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
#endif

namespace bg = boost::geometry;




// call BOOST_CHECK
template <typename Argument, bool IsFundamental /* true */>
struct check
{
    template <typename Result>
    static inline void apply(Argument const& arg, Result const& result)
    {
        BOOST_CHECK_CLOSE(static_cast<double>(bg::math::sqrt(arg)),
                          static_cast<double>(result),
                          0.00001);        
    }
};


template <typename Argument>
struct check<Argument, false>
{
    template <typename Result>
    static inline void apply(Argument const& arg, Result const& result)
    {
        Result const tol(0.00001);
        BOOST_CHECK( bg::math::abs(bg::math::sqrt(arg) - result) < tol );
    }
};






// test sqrt return type and value
template
<
    typename Argument,
    typename ExpectedResult,
    typename Result = typename bg::math::detail::square_root
        <
            Argument
        >::return_type,
    bool IsFundamental = boost::is_fundamental<Argument>::value
>
struct check_sqrt
    : bg::not_implemented<Argument, Result, ExpectedResult>
{};


template <typename Argument, typename Result, bool IsFundamental>
struct check_sqrt<Argument, Result, Result, IsFundamental>
{
    static inline void apply(Argument const& arg, Result const& result)
    {
#ifdef BOOST_GEOMETRY_TEST_DEBUG
        std::cout << "testing: " << typeid(Result).name()
                  << " sqrt(" << typeid(Argument).name()
                  << ")" << std::endl;
#endif
        check<Argument, IsFundamental>::apply(arg, result);
    }
};






// test cases
BOOST_AUTO_TEST_CASE( test_math_sqrt_fundamental )
{
    static const double sqrt2 = std::sqrt(2.0);
    static const long double sqrt2L = std::sqrt(2.0L);
    static const float sqrt2F = std::sqrt(2.0F);

    check_sqrt<float, float>::apply(2.0F, sqrt2F);
    check_sqrt<double, double>::apply(2.0, sqrt2);
    check_sqrt<long double, long double>::apply(2.0L, sqrt2L);

    check_sqrt<char, double>::apply(2, sqrt2);
    check_sqrt<signed char, double>::apply(2, sqrt2);
    check_sqrt<short, double>::apply(2, sqrt2);
    check_sqrt<int, double>::apply(2, sqrt2);
    check_sqrt<long, double>::apply(2L, sqrt2);
#if !defined(BOOST_NO_LONG_LONG)
    check_sqrt<long long, double>::apply(2LL, sqrt2);
#endif
#ifdef BOOST_HAS_LONG_LONG
    check_sqrt
        <
            boost::long_long_type, double
        >::apply(boost::long_long_type(2), sqrt2);
#endif
}


BOOST_AUTO_TEST_CASE( test_math_sqrt_custom )
{
    typedef number_types::custom<double> custom1;
    typedef custom_global<double> custom2;
    typedef number_types::custom_with_global_sqrt<double> custom3;

    static const double sqrt2 = std::sqrt(2.0);

    check_sqrt<custom1, custom1>::apply(custom1(2.0), custom1(sqrt2));
    check_sqrt<custom2, custom2>::apply(custom2(2.0), custom2(sqrt2));
    check_sqrt<custom3, custom3>::apply(custom3(2.0), custom3(sqrt2));

#ifdef HAVE_TTMATH
    typedef ttmath_big custom4;
    typedef ttmath::Big<1, 4> custom5;

    check_sqrt<custom4, custom4>::apply(custom4(2.0), custom4(sqrt2));
    check_sqrt<custom5, custom5>::apply(custom5(2.0), custom5(sqrt2));
#endif
}