PageRenderTime 30ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/include/VPL/Math/LogNum.h

https://bitbucket.org/RomanCizmarik/vpl_gdcm_fixes
C Header | 586 lines | 358 code | 146 blank | 82 comment | 18 complexity | 1f5047d60497ccd18786ab5322068f9c MD5 | raw file
Possible License(s): BSD-3-Clause
  1. //==============================================================================
  2. /* This file comes from MDSTk software and was modified for
  3. *
  4. * VPL - Voxel Processing Library
  5. * Changes are Copyright 2014 3Dim Laboratory s.r.o.
  6. * All rights reserved.
  7. *
  8. * Use of this source code is governed by a BSD-style license that can be
  9. * found in the LICENSE file.
  10. *
  11. * The original MDSTk legal notice can be found below.
  12. *
  13. * Medical Data Segmentation Toolkit (MDSTk) \n
  14. * Copyright (c) 2003-2006 by Michal Spanel \n
  15. *
  16. * Author: Michal Spanel, spanel@fit.vutbr.cz \n
  17. * Date: 2006/09/02 \n
  18. *
  19. * Description:
  20. * - Operations with numbers in logarithmic space.
  21. */
  22. #ifndef VPL_LOGNUM_H
  23. #define VPL_LOGNUM_H
  24. #include <VPL/Base/Exception.h>
  25. #include <VPL/Math/Base.h>
  26. #include "MathTraits.h"
  27. // STL
  28. #include <cmath>
  29. #include <iostream>
  30. namespace vpl
  31. {
  32. namespace math
  33. {
  34. //==============================================================================
  35. /*
  36. * Global definitions.
  37. */
  38. namespace LogNum
  39. {
  40. //! Enum used to initialize number in the logarithmic space.
  41. enum ELogValue { LOG_VALUE };
  42. //! Exception thrown on negative result.
  43. VPL_DECLARE_EXCEPTION(CNegativeResult, "Subtraction has failed (negative result)")
  44. }
  45. //==============================================================================
  46. /*!
  47. * Class representing a number in logarithmic space.
  48. * - T is type representing the number (most frequently float or double).
  49. */
  50. template <typename T>
  51. class CLogNum
  52. {
  53. public:
  54. //! Type of the number.
  55. typedef T tNumber;
  56. public:
  57. //! Value stored in the logarithmic space.
  58. T value;
  59. public:
  60. //! Default constructor.
  61. CLogNum() { value = CMathTraits<T>::getLogZero(); }
  62. //! Constructor.
  63. //! - Creates number in the logarithmic space.
  64. CLogNum(const T& v) { value = getSafeLog(v); }
  65. //! Constructor.
  66. //! - Initializes number in the logarithmic space.
  67. CLogNum(const T& v, LogNum::ELogValue) : value(v) {}
  68. //! Copy constructor.
  69. template <typename U>
  70. CLogNum(const CLogNum<U>& n) : value(n.value) {}
  71. //! Destructor.
  72. ~CLogNum() {}
  73. //! Assignment operator.
  74. template <typename U>
  75. CLogNum& operator =(const CLogNum<U>& n)
  76. {
  77. value = n.value;
  78. return *this;
  79. }
  80. //! Assignment operator.
  81. CLogNum& operator =(const T& v)
  82. {
  83. value = getSafeLog(v);
  84. return *this;
  85. }
  86. //! Returns current value in original space.
  87. T get() const { return getSafeExp(value); }
  88. //! Returns current value in logarithmic space.
  89. T get(LogNum::ELogValue) const { return value; }
  90. //! Sets the current value in original space.
  91. //! - Safe computation of the log(x) function.
  92. void set(const T& v) { value = getSafeLog(v); }
  93. //! Sets the current value in logarithmic space.
  94. void set(const T& v, LogNum::ELogValue) { value = getSafeLog(v); }
  95. //! Combined assignment operators.
  96. inline CLogNum& operator +=(const CLogNum& n);
  97. inline CLogNum& operator -=(const CLogNum& n);
  98. inline CLogNum& operator *=(const CLogNum& n);
  99. inline CLogNum& operator /=(const CLogNum& n);
  100. //! Others combined assignment operators.
  101. inline CLogNum& operator +=(const T& c);
  102. inline CLogNum& operator -=(const T& c);
  103. inline CLogNum& operator *=(const T& c);
  104. inline CLogNum& operator /=(const T& c);
  105. //! Safe computation of the log(x) function.
  106. inline static T getSafeLog(T x);
  107. //! Safe computation of the exp(x) function.
  108. inline static T getSafeExp(T x);
  109. //! Returns x + y in the logarithmic space.
  110. inline static T logAdd(T x, T y);
  111. //! Returns x - y in the logarithmic space.
  112. //! - Throws LogNum::CNegativeResult exception on failure.
  113. inline static T logSub(T x, T y);
  114. };
  115. //==============================================================================
  116. /*
  117. * Implementation of the class CLogNum.
  118. */
  119. template <typename T>
  120. inline T CLogNum<T>::getSafeLog(T x)
  121. {
  122. if( x == T(0) )
  123. {
  124. return CMathTraits<T>::getLogZero();
  125. }
  126. T Result = std::log(x);
  127. if( Result < CMathTraits<T>::getLogSmall() )
  128. {
  129. Result = CMathTraits<T>::getLogZero();
  130. }
  131. return Result;
  132. }
  133. template <typename T>
  134. inline T CLogNum<T>::getSafeExp(T x)
  135. {
  136. if( x <= CMathTraits<T>::getLogZero() )
  137. {
  138. return T(0);
  139. }
  140. else
  141. {
  142. return std::exp(x);
  143. }
  144. }
  145. template <typename T>
  146. inline T CLogNum<T>::logAdd(T x, T y)
  147. {
  148. if( x < y )
  149. {
  150. vpl::math::swap2(x, y);
  151. }
  152. T Diff = y - x;
  153. if( Diff < CMathTraits<T>::getMinLogExp() )
  154. {
  155. if( x < CMathTraits<T>::getLogSmall() )
  156. {
  157. return CMathTraits<T>::getLogZero();
  158. }
  159. else
  160. {
  161. return x;
  162. }
  163. }
  164. else
  165. {
  166. T Exp = std::exp(Diff);
  167. return x + std::log(1 + Exp);
  168. }
  169. }
  170. template <typename T>
  171. inline T CLogNum<T>::logSub(T x, T y)
  172. {
  173. if( x < y )
  174. {
  175. throw LogNum::CNegativeResult();
  176. }
  177. T Diff = y - x;
  178. if( Diff < CMathTraits<T>::getMinLogExp() )
  179. {
  180. if( x < CMathTraits<T>::getLogSmall() )
  181. {
  182. return CMathTraits<T>::getLogZero();
  183. }
  184. else
  185. {
  186. return x;
  187. }
  188. }
  189. else
  190. {
  191. T Exp = 1 - std::exp(Diff);
  192. if( Exp < CMathTraits<T>::getMinLogArg() )
  193. {
  194. return CMathTraits<T>::getLogZero();
  195. }
  196. else
  197. {
  198. return x + std::log(Exp);
  199. }
  200. }
  201. }
  202. //==============================================================================
  203. /*
  204. * Combined assignment operators.
  205. */
  206. template <typename T>
  207. inline CLogNum<T>& CLogNum<T>::operator +=(const CLogNum<T>& n)
  208. {
  209. value = logAdd(value, n.value);
  210. return *this;
  211. }
  212. template <typename T>
  213. inline CLogNum<T>& CLogNum<T>::operator -=(const CLogNum<T>& n)
  214. {
  215. value = logSub(value, n.value);
  216. return *this;
  217. }
  218. template <typename T>
  219. inline CLogNum<T>& CLogNum<T>::operator *=(const CLogNum<T>& n)
  220. {
  221. value += n.value;
  222. return *this;
  223. }
  224. template <typename T>
  225. inline CLogNum<T>& CLogNum<T>::operator /=(const CLogNum<T>& n)
  226. {
  227. value -= n.value;
  228. return *this;
  229. }
  230. template <typename T>
  231. inline CLogNum<T>& CLogNum<T>::operator +=(const T& c)
  232. {
  233. value = logAdd(value, getSafeLog(c));
  234. return *this;
  235. }
  236. template <typename T>
  237. inline CLogNum<T>& CLogNum<T>::operator -=(const T& c)
  238. {
  239. value = logSub(value, getSafeLog(c));
  240. return *this;
  241. }
  242. template <typename T>
  243. inline CLogNum<T>& CLogNum<T>::operator *=(const T& c)
  244. {
  245. value += getSafeLog(c);
  246. return *this;
  247. }
  248. template <typename T>
  249. inline CLogNum<T>& CLogNum<T>::operator /=(const T& c)
  250. {
  251. value -= getSafeLog(c);
  252. return *this;
  253. }
  254. //==============================================================================
  255. /*
  256. * Others operators.
  257. */
  258. template <typename T>
  259. inline CLogNum<T> operator +(const CLogNum<T>& x, const CLogNum<T>& y)
  260. {
  261. return CLogNum<T>(CLogNum<T>::logAdd(x.value, y.value), LogNum::LOG_VALUE);
  262. }
  263. template <typename T>
  264. inline CLogNum<T> operator +(const CLogNum<T>& x, T y)
  265. {
  266. return CLogNum<T>(CLogNum<T>::logAdd(x.value, CLogNum<T>::getSafeLog(y)), LogNum::LOG_VALUE);
  267. }
  268. template <typename T>
  269. inline CLogNum<T> operator +(T x, const CLogNum<T>& y)
  270. {
  271. return CLogNum<T>(CLogNum<T>::logAdd(CLogNum<T>::getSafeLog(x), y.value), LogNum::LOG_VALUE);
  272. }
  273. template <typename T>
  274. inline CLogNum<T> operator -(const CLogNum<T>& x, const CLogNum<T>& y)
  275. {
  276. return CLogNum<T>(CLogNum<T>::logSub(x.value, y.value), LogNum::LOG_VALUE);
  277. }
  278. template <typename T>
  279. inline CLogNum<T> operator -(const CLogNum<T>& x, T y)
  280. {
  281. return CLogNum<T>(CLogNum<T>::logSub(x.value, CLogNum<T>::getSafeLog(y)), LogNum::LOG_VALUE);
  282. }
  283. template <typename T>
  284. inline CLogNum<T> operator -(T x, const CLogNum<T>& y)
  285. {
  286. return CLogNum<T>(CLogNum<T>::logSub(CLogNum<T>::getSafeLog(x), y.value), LogNum::LOG_VALUE);
  287. }
  288. template <typename T>
  289. inline CLogNum<T> operator *(const CLogNum<T>& x, const CLogNum<T>& y)
  290. {
  291. return CLogNum<T>(x.value + y.value, LogNum::LOG_VALUE);
  292. }
  293. template <typename T>
  294. inline CLogNum<T> operator *(const CLogNum<T>& x, T y)
  295. {
  296. return CLogNum<T>(x.value + CLogNum<T>::getSafeLog(y), LogNum::LOG_VALUE);
  297. }
  298. template <typename T>
  299. inline CLogNum<T> operator *(T x, const CLogNum<T>& y)
  300. {
  301. return CLogNum<T>(CLogNum<T>::getSafeLog(x) + y.value, LogNum::LOG_VALUE);
  302. }
  303. template <typename T>
  304. inline CLogNum<T> operator /(const CLogNum<T>& x, const CLogNum<T>& y)
  305. {
  306. return CLogNum<T>(x.value - y.value, LogNum::LOG_VALUE);
  307. }
  308. template <typename T>
  309. inline CLogNum<T> operator /(const CLogNum<T>& x, T y)
  310. {
  311. return CLogNum<T>(x.value - CLogNum<T>::getSafeLog(y), LogNum::LOG_VALUE);
  312. }
  313. template <typename T>
  314. inline CLogNum<T> operator /(T x, const CLogNum<T>& y)
  315. {
  316. return CLogNum<T>(CLogNum<T>::getSafeLog(x) - y.value, LogNum::LOG_VALUE);
  317. }
  318. template <typename T>
  319. inline bool operator ==(const CLogNum<T>& x, const CLogNum<T>& y)
  320. {
  321. return x.value == y.value;
  322. }
  323. template <typename T>
  324. inline bool operator ==(const CLogNum<T>& x, T y)
  325. {
  326. return x.value == CLogNum<T>::getSafeLog(y);
  327. }
  328. template <typename T>
  329. inline bool operator ==(T x, const CLogNum<T>& y)
  330. {
  331. return CLogNum<T>::getSafeLog(x) == y.value;
  332. }
  333. template <typename T>
  334. inline bool operator !=(const CLogNum<T>& x, const CLogNum<T>& y)
  335. {
  336. return x.value != y.value;
  337. }
  338. template <typename T>
  339. inline bool operator !=(const CLogNum<T>& x, T y)
  340. {
  341. return x.value != CLogNum<T>::getSafeLog(y);
  342. }
  343. template <typename T>
  344. inline bool operator != (T x, const CLogNum<T>& y)
  345. {
  346. return CLogNum<T>::getSafeLog(x) != y.value;
  347. }
  348. template <typename T>
  349. inline bool operator <(const CLogNum<T>& x, const CLogNum<T>& y)
  350. {
  351. return x.value < y.value;
  352. }
  353. template <typename T>
  354. inline bool operator <(const CLogNum<T>& x, T y)
  355. {
  356. return x.value < CLogNum<T>::getSafeLog(y);
  357. }
  358. template <typename T>
  359. inline bool operator <(T x, const CLogNum<T>& y)
  360. {
  361. return CLogNum<T>::getSafeLog(x) < y.value;
  362. }
  363. template <typename T>
  364. inline bool operator <=(const CLogNum<T>& x, const CLogNum<T>& y)
  365. {
  366. return x.value <= y.value;
  367. }
  368. template <typename T>
  369. inline bool operator <=(const CLogNum<T>& x, T y)
  370. {
  371. return x.value <= CLogNum<T>::getSafeLog(y);
  372. }
  373. template <typename T>
  374. inline bool operator <=(T x, const CLogNum<T>& y)
  375. {
  376. return CLogNum<T>::getSafeLog(x) <= y.value;
  377. }
  378. template <typename T>
  379. inline bool operator >(const CLogNum<T>& x, const CLogNum<T>& y)
  380. {
  381. return x.value > y.value;
  382. }
  383. template <typename T>
  384. inline bool operator >(const CLogNum<T>& x, T y)
  385. {
  386. return x.value > CLogNum<T>::getSafeLog(y);
  387. }
  388. template <typename T>
  389. inline bool operator >(T x, const CLogNum<T>& y)
  390. {
  391. return CLogNum<T>::getSafeLog(x) > y.value;
  392. }
  393. template <typename T>
  394. inline bool operator >=(const CLogNum<T>& x, const CLogNum<T>& y)
  395. {
  396. return x.value >= y.value;
  397. }
  398. template <typename T>
  399. inline bool operator >=(const CLogNum<T>& x, T y)
  400. {
  401. return x.value >= CLogNum<T>::getSafeLog(y);
  402. }
  403. template <typename T>
  404. inline bool operator >=(T x, const CLogNum<T>& y)
  405. {
  406. return CLogNum<T>::getSafeLog(x) >= y.value;
  407. }
  408. //==============================================================================
  409. /*
  410. * Global functions.
  411. */
  412. //! Writes number in the logarithmic space to an output stream.
  413. template <typename T>
  414. inline std::ostream& operator <<(std::ostream& Stream, const CLogNum<T>& n)
  415. {
  416. Stream << n.value;
  417. return Stream;
  418. }
  419. //! Reads number in the logarithmic space to an input stream.
  420. template <typename T>
  421. inline std::istream& operator >> (std::istream& Stream, CLogNum<T>& n)
  422. {
  423. Stream >> n.value;
  424. return Stream;
  425. }
  426. //=============================================================================
  427. /*
  428. * Basic template instances and type definitions.
  429. */
  430. //! Float number in logarithmic space.
  431. typedef CLogNum<float> CFLogNum;
  432. //! Double number in logarithmic space.
  433. typedef CLogNum<double> CDLogNum;
  434. //! Float number in logarithmic space.
  435. typedef CFLogNum tFLogNum;
  436. //! Double number in logarithmic space.
  437. typedef CDLogNum tDLogNum;
  438. } // namespace math
  439. } // namespace vpl
  440. #endif // VPL_LOGNUM_H