arma_cmath.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
  2. // Copyright 2008-2016 National ICT Australia (NICTA)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ------------------------------------------------------------------------
  15. //! \addtogroup arma_cmath
  16. //! @{
  17. //
  18. // wrappers for isfinite
  19. template<typename eT>
  20. arma_inline
  21. bool
  22. arma_isfinite(eT val)
  23. {
  24. arma_ignore(val);
  25. return true;
  26. }
  27. template<>
  28. arma_inline
  29. bool
  30. arma_isfinite(float x)
  31. {
  32. #if defined(ARMA_USE_CXX11)
  33. {
  34. return std::isfinite(x);
  35. }
  36. #elif defined(ARMA_HAVE_TR1)
  37. {
  38. return std::tr1::isfinite(x);
  39. }
  40. #elif defined(ARMA_HAVE_ISFINITE)
  41. {
  42. return (std::isfinite(x) != 0);
  43. }
  44. #else
  45. {
  46. const float y = (std::numeric_limits<float>::max)();
  47. const volatile float xx = x;
  48. return (xx == xx) && (x >= -y) && (x <= y);
  49. }
  50. #endif
  51. }
  52. template<>
  53. arma_inline
  54. bool
  55. arma_isfinite(double x)
  56. {
  57. #if defined(ARMA_USE_CXX11)
  58. {
  59. return std::isfinite(x);
  60. }
  61. #elif defined(ARMA_HAVE_TR1)
  62. {
  63. return std::tr1::isfinite(x);
  64. }
  65. #elif defined(ARMA_HAVE_ISFINITE)
  66. {
  67. return (std::isfinite(x) != 0);
  68. }
  69. #else
  70. {
  71. const double y = (std::numeric_limits<double>::max)();
  72. const volatile double xx = x;
  73. return (xx == xx) && (x >= -y) && (x <= y);
  74. }
  75. #endif
  76. }
  77. template<typename T>
  78. arma_inline
  79. bool
  80. arma_isfinite(const std::complex<T>& x)
  81. {
  82. if( (arma_isfinite(x.real()) == false) || (arma_isfinite(x.imag()) == false) )
  83. {
  84. return false;
  85. }
  86. else
  87. {
  88. return true;
  89. }
  90. }
  91. //
  92. // wrappers for isinf
  93. template<typename eT>
  94. arma_inline
  95. bool
  96. arma_isinf(eT val)
  97. {
  98. arma_ignore(val);
  99. return false;
  100. }
  101. template<>
  102. arma_inline
  103. bool
  104. arma_isinf(float x)
  105. {
  106. #if defined(ARMA_USE_CXX11)
  107. {
  108. return std::isinf(x);
  109. }
  110. #elif defined(ARMA_HAVE_ISINF)
  111. {
  112. return (std::isinf(x) != 0);
  113. }
  114. #else
  115. {
  116. const float y = (std::numeric_limits<float>::max)();
  117. const volatile float xx = x;
  118. return (xx == xx) && ((x < -y) || (x > y));
  119. }
  120. #endif
  121. }
  122. template<>
  123. arma_inline
  124. bool
  125. arma_isinf(double x)
  126. {
  127. #if defined(ARMA_USE_CXX11)
  128. {
  129. return std::isinf(x);
  130. }
  131. #elif defined(ARMA_HAVE_ISINF)
  132. {
  133. return (std::isinf(x) != 0);
  134. }
  135. #else
  136. {
  137. const double y = (std::numeric_limits<double>::max)();
  138. const volatile double xx = x;
  139. return (xx == xx) && ((x < -y) || (x > y));
  140. }
  141. #endif
  142. }
  143. template<typename T>
  144. arma_inline
  145. bool
  146. arma_isinf(const std::complex<T>& x)
  147. {
  148. return ( arma_isinf(x.real()) || arma_isinf(x.imag()) );
  149. }
  150. //
  151. // wrappers for isnan
  152. template<typename eT>
  153. arma_inline
  154. bool
  155. arma_isnan(eT val)
  156. {
  157. arma_ignore(val);
  158. return false;
  159. }
  160. template<>
  161. arma_inline
  162. bool
  163. arma_isnan(float x)
  164. {
  165. #if defined(ARMA_USE_CXX11)
  166. {
  167. return std::isnan(x);
  168. }
  169. #elif defined(ARMA_HAVE_ISNAN)
  170. {
  171. return (std::isnan(x) != 0);
  172. }
  173. #else
  174. {
  175. const volatile float xx = x;
  176. return (xx != xx);
  177. }
  178. #endif
  179. }
  180. template<>
  181. arma_inline
  182. bool
  183. arma_isnan(double x)
  184. {
  185. #if defined(ARMA_USE_CXX11)
  186. {
  187. return std::isnan(x);
  188. }
  189. #elif defined(ARMA_HAVE_ISNAN)
  190. {
  191. return (std::isnan(x) != 0);
  192. }
  193. #else
  194. {
  195. const volatile double xx = x;
  196. return (xx != xx);
  197. }
  198. #endif
  199. }
  200. template<typename T>
  201. arma_inline
  202. bool
  203. arma_isnan(const std::complex<T>& x)
  204. {
  205. return ( arma_isnan(x.real()) || arma_isnan(x.imag()) );
  206. }
  207. // rudimentary wrappers for log1p()
  208. arma_inline
  209. float
  210. arma_log1p(const float x)
  211. {
  212. #if defined(ARMA_USE_CXX11)
  213. {
  214. return std::log1p(x);
  215. }
  216. #else
  217. {
  218. if((x >= float(0)) && (x < std::numeric_limits<float>::epsilon()))
  219. {
  220. return x;
  221. }
  222. else
  223. if((x < float(0)) && (-x < std::numeric_limits<float>::epsilon()))
  224. {
  225. return x;
  226. }
  227. else
  228. {
  229. return std::log(float(1) + x);
  230. }
  231. }
  232. #endif
  233. }
  234. arma_inline
  235. double
  236. arma_log1p(const double x)
  237. {
  238. #if defined(ARMA_USE_CXX11)
  239. {
  240. return std::log1p(x);
  241. }
  242. #elif defined(ARMA_HAVE_LOG1P)
  243. {
  244. return log1p(x);
  245. }
  246. #else
  247. {
  248. if((x >= double(0)) && (x < std::numeric_limits<double>::epsilon()))
  249. {
  250. return x;
  251. }
  252. else
  253. if((x < double(0)) && (-x < std::numeric_limits<double>::epsilon()))
  254. {
  255. return x;
  256. }
  257. else
  258. {
  259. return std::log(double(1) + x);
  260. }
  261. }
  262. #endif
  263. }
  264. //
  265. // implementation of arma_sign()
  266. template<typename eT>
  267. arma_inline
  268. typename arma_unsigned_integral_only<eT>::result
  269. arma_sign(const eT x)
  270. {
  271. return (x > eT(0)) ? eT(+1) : eT(0);
  272. }
  273. template<typename eT>
  274. arma_inline
  275. typename arma_signed_integral_only<eT>::result
  276. arma_sign(const eT x)
  277. {
  278. return (x > eT(0)) ? eT(+1) : ( (x < eT(0)) ? eT(-1) : eT(0) );
  279. }
  280. template<typename eT>
  281. arma_inline
  282. typename arma_real_only<eT>::result
  283. arma_sign(const eT x)
  284. {
  285. return (x > eT(0)) ? eT(+1) : ( (x < eT(0)) ? eT(-1) : ((x == eT(0)) ? eT(0) : x) );
  286. }
  287. template<typename eT>
  288. arma_inline
  289. typename arma_cx_only<eT>::result
  290. arma_sign(const eT& x)
  291. {
  292. typedef typename eT::value_type T;
  293. const T abs_x = std::abs(x);
  294. return (abs_x != T(0)) ? (x / abs_x) : x;
  295. }
  296. //
  297. // wrappers for trigonometric functions
  298. //
  299. // wherever possible, try to use C++11 or TR1 versions of the following functions:
  300. //
  301. // complex acos
  302. // complex asin
  303. // complex atan
  304. //
  305. // real acosh
  306. // real asinh
  307. // real atanh
  308. //
  309. // complex acosh
  310. // complex asinh
  311. // complex atanh
  312. //
  313. //
  314. // if C++11 or TR1 are not available, we have rudimentary versions of:
  315. //
  316. // real acosh
  317. // real asinh
  318. // real atanh
  319. template<typename T>
  320. arma_inline
  321. std::complex<T>
  322. arma_acos(const std::complex<T>& x)
  323. {
  324. #if defined(ARMA_USE_CXX11)
  325. {
  326. return std::acos(x);
  327. }
  328. #elif defined(ARMA_HAVE_TR1)
  329. {
  330. return std::tr1::acos(x);
  331. }
  332. #else
  333. {
  334. arma_ignore(x);
  335. arma_stop_logic_error("acos(): C++11 compiler required");
  336. return std::complex<T>(0);
  337. }
  338. #endif
  339. }
  340. template<typename T>
  341. arma_inline
  342. std::complex<T>
  343. arma_asin(const std::complex<T>& x)
  344. {
  345. #if defined(ARMA_USE_CXX11)
  346. {
  347. return std::asin(x);
  348. }
  349. #elif defined(ARMA_HAVE_TR1)
  350. {
  351. return std::tr1::asin(x);
  352. }
  353. #else
  354. {
  355. arma_ignore(x);
  356. arma_stop_logic_error("asin(): C++11 compiler required");
  357. return std::complex<T>(0);
  358. }
  359. #endif
  360. }
  361. template<typename T>
  362. arma_inline
  363. std::complex<T>
  364. arma_atan(const std::complex<T>& x)
  365. {
  366. #if defined(ARMA_USE_CXX11)
  367. {
  368. return std::atan(x);
  369. }
  370. #elif defined(ARMA_HAVE_TR1)
  371. {
  372. return std::tr1::atan(x);
  373. }
  374. #else
  375. {
  376. arma_ignore(x);
  377. arma_stop_logic_error("atan(): C++11 compiler required");
  378. return std::complex<T>(0);
  379. }
  380. #endif
  381. }
  382. template<typename eT>
  383. arma_inline
  384. eT
  385. arma_acosh(const eT x)
  386. {
  387. #if defined(ARMA_USE_CXX11)
  388. {
  389. return std::acosh(x);
  390. }
  391. #elif defined(ARMA_HAVE_TR1)
  392. {
  393. return std::tr1::acosh(x);
  394. }
  395. #else
  396. {
  397. if(x >= eT(1))
  398. {
  399. // http://functions.wolfram.com/ElementaryFunctions/ArcCosh/02/
  400. return std::log( x + std::sqrt(x*x - eT(1)) );
  401. }
  402. else
  403. {
  404. if(std::numeric_limits<eT>::has_quiet_NaN)
  405. {
  406. return -(std::numeric_limits<eT>::quiet_NaN());
  407. }
  408. else
  409. {
  410. return eT(0);
  411. }
  412. }
  413. }
  414. #endif
  415. }
  416. template<typename eT>
  417. arma_inline
  418. eT
  419. arma_asinh(const eT x)
  420. {
  421. #if defined(ARMA_USE_CXX11)
  422. {
  423. return std::asinh(x);
  424. }
  425. #elif defined(ARMA_HAVE_TR1)
  426. {
  427. return std::tr1::asinh(x);
  428. }
  429. #else
  430. {
  431. // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/
  432. return std::log( x + std::sqrt(x*x + eT(1)) );
  433. }
  434. #endif
  435. }
  436. template<typename eT>
  437. arma_inline
  438. eT
  439. arma_atanh(const eT x)
  440. {
  441. #if defined(ARMA_USE_CXX11)
  442. {
  443. return std::atanh(x);
  444. }
  445. #elif defined(ARMA_HAVE_TR1)
  446. {
  447. return std::tr1::atanh(x);
  448. }
  449. #else
  450. {
  451. if( (x >= eT(-1)) && (x <= eT(+1)) )
  452. {
  453. // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
  454. return std::log( ( eT(1)+x ) / ( eT(1)-x ) ) / eT(2);
  455. }
  456. else
  457. {
  458. if(std::numeric_limits<eT>::has_quiet_NaN)
  459. {
  460. return -(std::numeric_limits<eT>::quiet_NaN());
  461. }
  462. else
  463. {
  464. return eT(0);
  465. }
  466. }
  467. }
  468. #endif
  469. }
  470. template<typename T>
  471. arma_inline
  472. std::complex<T>
  473. arma_acosh(const std::complex<T>& x)
  474. {
  475. #if defined(ARMA_USE_CXX11)
  476. {
  477. return std::acosh(x);
  478. }
  479. #elif defined(ARMA_HAVE_TR1)
  480. {
  481. return std::tr1::acosh(x);
  482. }
  483. #else
  484. {
  485. arma_ignore(x);
  486. arma_stop_logic_error("acosh(): C++11 compiler required");
  487. return std::complex<T>(0);
  488. }
  489. #endif
  490. }
  491. template<typename T>
  492. arma_inline
  493. std::complex<T>
  494. arma_asinh(const std::complex<T>& x)
  495. {
  496. #if defined(ARMA_USE_CXX11)
  497. {
  498. return std::asinh(x);
  499. }
  500. #elif defined(ARMA_HAVE_TR1)
  501. {
  502. return std::tr1::asinh(x);
  503. }
  504. #else
  505. {
  506. arma_ignore(x);
  507. arma_stop_logic_error("asinh(): C++11 compiler required");
  508. return std::complex<T>(0);
  509. }
  510. #endif
  511. }
  512. template<typename T>
  513. arma_inline
  514. std::complex<T>
  515. arma_atanh(const std::complex<T>& x)
  516. {
  517. #if defined(ARMA_USE_CXX11)
  518. {
  519. return std::atanh(x);
  520. }
  521. #elif defined(ARMA_HAVE_TR1)
  522. {
  523. return std::tr1::atanh(x);
  524. }
  525. #else
  526. {
  527. arma_ignore(x);
  528. arma_stop_logic_error("atanh(): C++11 compiler required");
  529. return std::complex<T>(0);
  530. }
  531. #endif
  532. }
  533. //
  534. // wrappers for hypot(x, y) = sqrt(x^2 + y^2)
  535. template<typename eT>
  536. inline
  537. eT
  538. arma_hypot_generic(const eT x, const eT y)
  539. {
  540. #if defined(ARMA_USE_CXX11)
  541. {
  542. return std::hypot(x, y);
  543. }
  544. #elif defined(ARMA_HAVE_TR1)
  545. {
  546. return std::tr1::hypot(x, y);
  547. }
  548. #else
  549. {
  550. const eT xabs = std::abs(x);
  551. const eT yabs = std::abs(y);
  552. eT larger;
  553. eT ratio;
  554. if(xabs > yabs)
  555. {
  556. larger = xabs;
  557. ratio = yabs / xabs;
  558. }
  559. else
  560. {
  561. larger = yabs;
  562. ratio = xabs / yabs;
  563. }
  564. return (larger == eT(0)) ? eT(0) : (larger * std::sqrt(eT(1) + ratio * ratio));
  565. }
  566. #endif
  567. }
  568. template<typename eT>
  569. inline
  570. eT
  571. arma_hypot(const eT x, const eT y)
  572. {
  573. arma_ignore(x);
  574. arma_ignore(y);
  575. arma_stop_runtime_error("arma_hypot(): not implemented for integer or complex element types");
  576. return eT(0);
  577. }
  578. template<>
  579. arma_inline
  580. float
  581. arma_hypot(const float x, const float y)
  582. {
  583. return arma_hypot_generic(x,y);
  584. }
  585. template<>
  586. arma_inline
  587. double
  588. arma_hypot(const double x, const double y)
  589. {
  590. return arma_hypot_generic(x,y);
  591. }
  592. //
  593. // implementation of arma_sinc()
  594. template<typename eT>
  595. arma_inline
  596. eT
  597. arma_sinc_generic(const eT x)
  598. {
  599. typedef typename get_pod_type<eT>::result T;
  600. const eT tmp = Datum<T>::pi * x;
  601. return (tmp == eT(0)) ? eT(1) : eT( std::sin(tmp) / tmp );
  602. }
  603. template<typename eT>
  604. arma_inline
  605. eT
  606. arma_sinc(const eT x)
  607. {
  608. return eT( arma_sinc_generic( double(x) ) );
  609. }
  610. template<>
  611. arma_inline
  612. float
  613. arma_sinc(const float x)
  614. {
  615. return arma_sinc_generic(x);
  616. }
  617. template<>
  618. arma_inline
  619. double
  620. arma_sinc(const double x)
  621. {
  622. return arma_sinc_generic(x);
  623. }
  624. template<typename T>
  625. arma_inline
  626. std::complex<T>
  627. arma_sinc(const std::complex<T>& x)
  628. {
  629. return arma_sinc_generic(x);
  630. }
  631. //
  632. // wrappers for arg()
  633. template<typename eT>
  634. struct arma_arg
  635. {
  636. static
  637. inline
  638. eT
  639. eval(const eT x)
  640. {
  641. #if defined(ARMA_USE_CXX11)
  642. {
  643. return eT( std::arg(x) );
  644. }
  645. #else
  646. {
  647. arma_ignore(x);
  648. arma_stop_logic_error("arg(): C++11 compiler required");
  649. return eT(0);
  650. }
  651. #endif
  652. }
  653. };
  654. template<>
  655. struct arma_arg<float>
  656. {
  657. static
  658. arma_inline
  659. float
  660. eval(const float x)
  661. {
  662. #if defined(ARMA_USE_CXX11)
  663. {
  664. return std::arg(x);
  665. }
  666. #else
  667. {
  668. return std::arg( std::complex<float>( x, float(0) ) );
  669. }
  670. #endif
  671. }
  672. };
  673. template<>
  674. struct arma_arg<double>
  675. {
  676. static
  677. arma_inline
  678. double
  679. eval(const double x)
  680. {
  681. #if defined(ARMA_USE_CXX11)
  682. {
  683. return std::arg(x);
  684. }
  685. #else
  686. {
  687. return std::arg( std::complex<double>( x, double(0) ) );
  688. }
  689. #endif
  690. }
  691. };
  692. template<>
  693. struct arma_arg< std::complex<float> >
  694. {
  695. static
  696. arma_inline
  697. float
  698. eval(const std::complex<float>& x)
  699. {
  700. return std::arg(x);
  701. }
  702. };
  703. template<>
  704. struct arma_arg< std::complex<double> >
  705. {
  706. static
  707. arma_inline
  708. double
  709. eval(const std::complex<double>& x)
  710. {
  711. return std::arg(x);
  712. }
  713. };
  714. //! @}