Medical Imaging Interaction Toolkit  2016.11.0
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkTestFixture.h"
18 #include "mitkTestingMacros.h"
19 
20 #include <boost/lexical_cast.hpp>
21 
22 #include "mitkEqual.h"
23 #include <math.h>
24 
25 #include "mitkLog.h"
26 
27 #include <functional>
28 #include <limits>
29 
40 class mitkFloatToStringTestSuite : public mitk::TestFixture
41 {
42  CPPUNIT_TEST_SUITE(mitkFloatToStringTestSuite);
43  MITK_TEST(ConfirmStringValues<float>);
44  MITK_TEST(ConfirmStringValues<double>);
45  MITK_TEST(TestConversions<float>);
46  MITK_TEST(TestConversions<double>);
47  CPPUNIT_TEST_SUITE_END();
48 
49 public:
50  template <typename DATATYPE>
51  void ConfirmNumberToString(DATATYPE number, const std::string &s)
52 
53  {
54  CPPUNIT_ASSERT_EQUAL(boost::lexical_cast<std::string>(number), s);
55  }
56 
57  template <typename DATATYPE>
58  void ConfirmStringToNumber(const std::string &s, DATATYPE number)
59 
60  {
61  CPPUNIT_ASSERT_EQUAL(number, boost::lexical_cast<DATATYPE>(s));
62  }
63 
64  template <typename DATATYPE>
65  void ConfirmStringValues()
66  {
67  // we want to make sure that the following strings will be accepted and returned
68  // by our conversion functions. This must not change in the future to ensure compatibility
69  DATATYPE nan = boost::lexical_cast<DATATYPE>("nan");
70  CPPUNIT_ASSERT_MESSAGE("nan==nan must be false", !(nan == nan));
71  nan = boost::lexical_cast<DATATYPE>("NAN");
72  CPPUNIT_ASSERT_MESSAGE("NAN==NAN must be false", !(nan == nan));
73 
74  std::string s_nan = boost::lexical_cast<std::string>(nan);
75  CPPUNIT_ASSERT_EQUAL(std::string("nan"), s_nan);
76 
77  ConfirmStringToNumber("inf", std::numeric_limits<DATATYPE>::infinity());
78  ConfirmStringToNumber("INF", std::numeric_limits<DATATYPE>::infinity());
79  ConfirmStringToNumber("infinity", std::numeric_limits<DATATYPE>::infinity());
80  ConfirmStringToNumber("INFINITY", std::numeric_limits<DATATYPE>::infinity());
81 
82  ConfirmStringToNumber("-inf", -std::numeric_limits<DATATYPE>::infinity());
83  ConfirmStringToNumber("-INF", -std::numeric_limits<DATATYPE>::infinity());
84  ConfirmStringToNumber("-infinity", -std::numeric_limits<DATATYPE>::infinity());
85  ConfirmStringToNumber("-INFINITY", -std::numeric_limits<DATATYPE>::infinity());
86 
87  ConfirmNumberToString(std::numeric_limits<DATATYPE>::infinity(), "inf");
88  ConfirmNumberToString(-std::numeric_limits<DATATYPE>::infinity(), "-inf");
89  }
90 
91  template <typename DATATYPE>
92  void CheckRoundTrip(DATATYPE number, DATATYPE tolerance)
93  {
94  std::string s = boost::lexical_cast<std::string>(number);
95  DATATYPE number2 = boost::lexical_cast<DATATYPE>(s);
96 
97  CPPUNIT_ASSERT_MESSAGE(std::string("Must not parse string ") + s + " as NaN", number2 == number2);
98  if (tolerance == 0)
99  {
100  CPPUNIT_ASSERT_EQUAL(number, number2);
101  }
102  else // mitk::Equal cannot take 0 as tolerance
103  {
104  CPPUNIT_ASSERT(mitk::Equal(number, number2, tolerance));
105  }
106  }
107 
108  template <typename DATATYPE>
109  void CheckRoundTrip(const std::string &input)
110  {
111  DATATYPE number = boost::lexical_cast<DATATYPE>(input);
112  std::string result = boost::lexical_cast<std::string>(number);
113 
114  // There are normal imprecisions when converting to string
115  // We do only compare if the numeric values match "close enough"
116  DATATYPE number2 = boost::lexical_cast<DATATYPE>(result);
117  CPPUNIT_ASSERT(mitk::Equal(number, number2));
118  }
119 
120  template <typename DATATYPE>
121  void TestConversions()
122  {
123  // we cannot test the NaN roundtrip because nan == nan will never be true
124  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::infinity(), 0.0);
125  CheckRoundTrip<DATATYPE>(-std::numeric_limits<DATATYPE>::infinity(), 0.0);
126 
127  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::denorm_min(), mitk::eps);
128  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::epsilon(), mitk::eps);
129  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::lowest(), mitk::eps);
130  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::min(), mitk::eps);
131  CheckRoundTrip<DATATYPE>(std::numeric_limits<DATATYPE>::max(), mitk::eps);
132  CheckRoundTrip<DATATYPE>(sqrt(2), mitk::eps);
133  CheckRoundTrip<DATATYPE>(0.000000042, mitk::eps);
134  CheckRoundTrip<DATATYPE>(422345678.2345678, mitk::eps);
135  CheckRoundTrip<DATATYPE>(0.0, 0);
136  CheckRoundTrip<DATATYPE>(-0.0, 0);
137 
138  CheckRoundTrip<DATATYPE>("1");
139  CheckRoundTrip<DATATYPE>("1.1");
140  CheckRoundTrip<DATATYPE>("1.12121212");
141  CheckRoundTrip<DATATYPE>("1.1e-2");
142  }
143 
144 }; // class
145 
146 MITK_TEST_SUITE_REGISTRATION(mitkFloatToString)
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
#define MITK_TEST(TESTMETHOD)
Adds a test to the current test suite.
Test fixture for parameterized tests.
static T max(T x, T y)
Definition: svm.cpp:70
static T min(T x, T y)
Definition: svm.cpp:67
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