Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkFloatToStringTest.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkTestFixture.h"
14 #include "mitkTestingMacros.h"
15 
16 #include <mitkLexicalCast.h>
17 
18 #include "mitkEqual.h"
19 #include <cmath>
20 
21 #include "mitkLog.h"
22 
23 #include <functional>
24 #include <limits>
25 
36 class mitkFloatToStringTestSuite : public mitk::TestFixture
37 {
38  CPPUNIT_TEST_SUITE(mitkFloatToStringTestSuite);
39  MITK_TEST(ConfirmStringValues<float>);
40  MITK_TEST(ConfirmStringValues<double>);
41  MITK_TEST(TestConversions<float>);
42  MITK_TEST(TestConversions<double>);
43  CPPUNIT_TEST_SUITE_END();
44 
45 public:
46  template <typename DATATYPE>
47  void ConfirmNumberToString(DATATYPE number, const std::string &s)
48 
49  {
50  CPPUNIT_ASSERT_EQUAL(boost::lexical_cast<std::string>(number), s);
51  }
52 
53  template <typename DATATYPE>
54  void ConfirmStringToNumber(const std::string &s, DATATYPE number)
55 
56  {
57  CPPUNIT_ASSERT_EQUAL(number, boost::lexical_cast<DATATYPE>(s));
58  }
59 
60  template <typename DATATYPE>
61  void ConfirmStringValues()
62  {
63  // we want to make sure that the following strings will be accepted and returned
64  // by our conversion functions. This must not change in the future to ensure compatibility
65  auto nan = boost::lexical_cast<DATATYPE>("nan");
66  CPPUNIT_ASSERT_MESSAGE("nan==nan must be false", !(nan == nan));
67  nan = boost::lexical_cast<DATATYPE>("NAN");
68  CPPUNIT_ASSERT_MESSAGE("NAN==NAN must be false", !(nan == nan));
69 
70  std::string s_nan = boost::lexical_cast<std::string>(nan);
71  CPPUNIT_ASSERT_EQUAL(std::string("nan"), s_nan);
72 
73  ConfirmStringToNumber("inf", std::numeric_limits<DATATYPE>::infinity());
74  ConfirmStringToNumber("INF", std::numeric_limits<DATATYPE>::infinity());
75  ConfirmStringToNumber("infinity", std::numeric_limits<DATATYPE>::infinity());
76  ConfirmStringToNumber("INFINITY", std::numeric_limits<DATATYPE>::infinity());
77 
78  ConfirmStringToNumber("-inf", -std::numeric_limits<DATATYPE>::infinity());
79  ConfirmStringToNumber("-INF", -std::numeric_limits<DATATYPE>::infinity());
80  ConfirmStringToNumber("-infinity", -std::numeric_limits<DATATYPE>::infinity());
81  ConfirmStringToNumber("-INFINITY", -std::numeric_limits<DATATYPE>::infinity());
82 
83  ConfirmNumberToString(std::numeric_limits<DATATYPE>::infinity(), "inf");
84  ConfirmNumberToString(-std::numeric_limits<DATATYPE>::infinity(), "-inf");
85  }
86 
87  template <typename DATATYPE>
88  void CheckRoundTrip(DATATYPE number, DATATYPE tolerance)
89  {
90  std::string s = boost::lexical_cast<std::string>(number);
91  auto number2 = boost::lexical_cast<DATATYPE>(s);
92 
93  CPPUNIT_ASSERT_MESSAGE(std::string("Must not parse string ") + s + " as NaN", number2 == number2);
94  if (tolerance == 0)
95  {
96  CPPUNIT_ASSERT_EQUAL(number, number2);
97  }
98  else // mitk::Equal cannot take 0 as tolerance
99  {
100  CPPUNIT_ASSERT(mitk::Equal(number, number2, tolerance));
101  }
102  }
103 
104  template <typename DATATYPE>
105  void CheckRoundTrip(const std::string &input)
106  {
107  auto number = boost::lexical_cast<DATATYPE>(input);
108  std::string result = boost::lexical_cast<std::string>(number);
109 
110  // There are normal imprecisions when converting to string
111  // We do only compare if the numeric values match "close enough"
112  auto number2 = boost::lexical_cast<DATATYPE>(result);
113  CPPUNIT_ASSERT(mitk::Equal(number, number2));
114  }
115 
116  template <typename DATATYPE>
117  void TestConversions()
118  {
119  // we cannot test the NaN roundtrip because nan == nan will never be true
120  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::infinity(), 0.0);
121  CheckRoundTrip<DATATYPE>(-std::numeric_limits<DATATYPE>::infinity(), 0.0);
122 
123  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::denorm_min(), mitk::eps);
124  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::epsilon(), mitk::eps);
125  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::lowest(), mitk::eps);
126  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::min(), mitk::eps);
127  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::max(), mitk::eps);
128  CheckRoundTrip<DATATYPE>(sqrt(2), mitk::eps);
129  CheckRoundTrip<DATATYPE>(0.000000042, mitk::eps);
130  CheckRoundTrip<DATATYPE>(422345678.2345678, mitk::eps);
131  CheckRoundTrip<DATATYPE>(0.0, 0);
132  CheckRoundTrip<DATATYPE>(-0.0, 0);
133 
134  CheckRoundTrip<DATATYPE>("1");
135  CheckRoundTrip<DATATYPE>("1.1");
136  CheckRoundTrip<DATATYPE>("1.12121212");
137  CheckRoundTrip<DATATYPE>("1.1e-2");
138  }
139 
140 }; // class
141 
142 MITK_TEST_SUITE_REGISTRATION(mitkFloatToString)
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
#define MITK_TEST(TESTMETHOD)
Adds a test to the current test suite.
Target lexical_cast(const std::string &arg)
Test fixture for parameterized tests.
static T max(T x, T y)
Definition: svm.cpp:56
static T min(T x, T y)
Definition: svm.cpp:53
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
MITKCORE_EXPORT const ScalarType eps