ttmath.h 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843
  1. /*
  2. * This file is a part of TTMath Bignum Library
  3. * and is distributed under the (new) BSD licence.
  4. * Author: Tomasz Sowa <[email protected]>
  5. */
  6. /*
  7. * Copyright (c) 2006-2012, Tomasz Sowa
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * * Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. *
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * * Neither the name Tomasz Sowa nor the names of contributors to this
  21. * project may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  34. * THE POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. #ifndef headerfilettmathmathtt
  37. #define headerfilettmathmathtt
  38. /*!
  39. \file ttmath.h
  40. \brief Mathematics functions.
  41. */
  42. #ifdef _MSC_VER
  43. //warning C4127: conditional expression is constant
  44. #pragma warning( disable: 4127 )
  45. //warning C4702: unreachable code
  46. #pragma warning( disable: 4702 )
  47. //warning C4800: forcing value to bool 'true' or 'false' (performance warning)
  48. #pragma warning( disable: 4800 )
  49. #endif
  50. #define TTMATH_DONT_USE_WCHAR
  51. #include "ttmathint.h"
  52. #include "ttmathobjects.h"
  53. namespace ttmath
  54. {
  55. /*
  56. *
  57. * functions defined here are used only with Big<> types
  58. *
  59. *
  60. */
  61. /*
  62. *
  63. * functions for rounding
  64. *
  65. *
  66. */
  67. /*!
  68. this function skips the fraction from x
  69. e.g 2.2 = 2
  70. 2.7 = 2
  71. -2.2 = 2
  72. -2.7 = 2
  73. */
  74. template<class ValueType>
  75. ValueType SkipFraction(const ValueType & x)
  76. {
  77. ValueType result( x );
  78. result.SkipFraction();
  79. return result;
  80. }
  81. /*!
  82. this function rounds to the nearest integer value
  83. e.g 2.2 = 2
  84. 2.7 = 3
  85. -2.2 = -2
  86. -2.7 = -3
  87. */
  88. template<class ValueType>
  89. ValueType Round(const ValueType & x, ErrorCode * err = 0)
  90. {
  91. if( x.IsNan() )
  92. {
  93. if( err )
  94. *err = err_improper_argument;
  95. return x; // NaN
  96. }
  97. ValueType result( x );
  98. uint c = result.Round();
  99. if( err )
  100. *err = c ? err_overflow : err_ok;
  101. return result;
  102. }
  103. /*!
  104. this function returns a value representing the smallest integer
  105. that is greater than or equal to x
  106. Ceil(-3.7) = -3
  107. Ceil(-3.1) = -3
  108. Ceil(-3.0) = -3
  109. Ceil(4.0) = 4
  110. Ceil(4.2) = 5
  111. Ceil(4.8) = 5
  112. */
  113. template<class ValueType>
  114. ValueType Ceil(const ValueType & x, ErrorCode * err = 0)
  115. {
  116. if( x.IsNan() )
  117. {
  118. if( err )
  119. *err = err_improper_argument;
  120. return x; // NaN
  121. }
  122. ValueType result(x);
  123. uint c = 0;
  124. result.SkipFraction();
  125. if( result != x )
  126. {
  127. // x is with fraction
  128. // if x is negative we don't have to do anything
  129. if( !x.IsSign() )
  130. {
  131. ValueType one;
  132. one.SetOne();
  133. c += result.Add(one);
  134. }
  135. }
  136. if( err )
  137. *err = c ? err_overflow : err_ok;
  138. return result;
  139. }
  140. /*!
  141. this function returns a value representing the largest integer
  142. that is less than or equal to x
  143. Floor(-3.6) = -4
  144. Floor(-3.1) = -4
  145. Floor(-3) = -3
  146. Floor(2) = 2
  147. Floor(2.3) = 2
  148. Floor(2.8) = 2
  149. */
  150. template<class ValueType>
  151. ValueType Floor(const ValueType & x, ErrorCode * err = 0)
  152. {
  153. if( x.IsNan() )
  154. {
  155. if( err )
  156. *err = err_improper_argument;
  157. return x; // NaN
  158. }
  159. ValueType result(x);
  160. uint c = 0;
  161. result.SkipFraction();
  162. if( result != x )
  163. {
  164. // x is with fraction
  165. // if x is positive we don't have to do anything
  166. if( x.IsSign() )
  167. {
  168. ValueType one;
  169. one.SetOne();
  170. c += result.Sub(one);
  171. }
  172. }
  173. if( err )
  174. *err = c ? err_overflow : err_ok;
  175. return result;
  176. }
  177. /*
  178. *
  179. * logarithms and the exponent
  180. *
  181. *
  182. */
  183. /*!
  184. this function calculates the natural logarithm (logarithm with the base 'e')
  185. */
  186. template<class ValueType>
  187. ValueType Ln(const ValueType & x, ErrorCode * err = 0)
  188. {
  189. if( x.IsNan() )
  190. {
  191. if( err )
  192. *err = err_improper_argument;
  193. return x; // NaN
  194. }
  195. ValueType result;
  196. uint state = result.Ln(x);
  197. if( err )
  198. {
  199. switch( state )
  200. {
  201. case 0:
  202. *err = err_ok;
  203. break;
  204. case 1:
  205. *err = err_overflow;
  206. break;
  207. case 2:
  208. *err = err_improper_argument;
  209. break;
  210. default:
  211. *err = err_internal_error;
  212. break;
  213. }
  214. }
  215. return result;
  216. }
  217. /*!
  218. this function calculates the logarithm
  219. */
  220. template<class ValueType>
  221. ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
  222. {
  223. if( x.IsNan() )
  224. {
  225. if( err ) *err = err_improper_argument;
  226. return x;
  227. }
  228. if( base.IsNan() )
  229. {
  230. if( err ) *err = err_improper_argument;
  231. return base;
  232. }
  233. ValueType result;
  234. uint state = result.Log(x, base);
  235. if( err )
  236. {
  237. switch( state )
  238. {
  239. case 0:
  240. *err = err_ok;
  241. break;
  242. case 1:
  243. *err = err_overflow;
  244. break;
  245. case 2:
  246. case 3:
  247. *err = err_improper_argument;
  248. break;
  249. default:
  250. *err = err_internal_error;
  251. break;
  252. }
  253. }
  254. return result;
  255. }
  256. /*!
  257. this function calculates the expression e^x
  258. */
  259. template<class ValueType>
  260. ValueType Exp(const ValueType & x, ErrorCode * err = 0)
  261. {
  262. if( x.IsNan() )
  263. {
  264. if( err )
  265. *err = err_improper_argument;
  266. return x; // NaN
  267. }
  268. ValueType result;
  269. uint c = result.Exp(x);
  270. if( err )
  271. *err = c ? err_overflow : err_ok;
  272. return result;
  273. }
  274. /*!
  275. *
  276. * trigonometric functions
  277. *
  278. */
  279. /*
  280. this namespace consists of auxiliary functions
  281. (something like 'private' in a class)
  282. */
  283. namespace auxiliaryfunctions
  284. {
  285. /*!
  286. an auxiliary function for calculating the Sine
  287. (you don't have to call this function)
  288. */
  289. template<class ValueType>
  290. uint PrepareSin(ValueType & x, bool & change_sign)
  291. {
  292. ValueType temp;
  293. change_sign = false;
  294. if( x.IsSign() )
  295. {
  296. // we're using the formula 'sin(-x) = -sin(x)'
  297. change_sign = !change_sign;
  298. x.ChangeSign();
  299. }
  300. // we're reducing the period 2*PI
  301. // (for big values there'll always be zero)
  302. temp.Set2Pi();
  303. if( x.Mod(temp) )
  304. return 1;
  305. // we're setting 'x' as being in the range of <0, 0.5PI>
  306. temp.SetPi();
  307. if( x > temp )
  308. {
  309. // x is in (pi, 2*pi>
  310. x.Sub( temp );
  311. change_sign = !change_sign;
  312. }
  313. temp.Set05Pi();
  314. if( x > temp )
  315. {
  316. // x is in (0.5pi, pi>
  317. x.Sub( temp );
  318. x = temp - x;
  319. }
  320. return 0;
  321. }
  322. /*!
  323. an auxiliary function for calculating the Sine
  324. (you don't have to call this function)
  325. it returns Sin(x) where 'x' is from <0, PI/2>
  326. we're calculating the Sin with using Taylor series in zero or PI/2
  327. (depending on which point of these two points is nearer to the 'x')
  328. Taylor series:
  329. sin(x) = sin(a) + cos(a)*(x-a)/(1!)
  330. - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!)
  331. + sin(a)*((x-a)^4)/(4!) + ...
  332. when a=0 it'll be:
  333. sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ...
  334. and when a=PI/2:
  335. sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ...
  336. */
  337. template<class ValueType>
  338. ValueType Sin0pi05(const ValueType & x)
  339. {
  340. ValueType result;
  341. ValueType numerator, denominator;
  342. ValueType d_numerator, d_denominator;
  343. ValueType one, temp, old_result;
  344. // temp = pi/4
  345. temp.Set05Pi();
  346. temp.exponent.SubOne();
  347. one.SetOne();
  348. if( x < temp )
  349. {
  350. // we're using the Taylor series with a=0
  351. result = x;
  352. numerator = x;
  353. denominator = one;
  354. // d_numerator = x^2
  355. d_numerator = x;
  356. d_numerator.Mul(x);
  357. d_denominator = 2;
  358. }
  359. else
  360. {
  361. // we're using the Taylor series with a=PI/2
  362. result = one;
  363. numerator = one;
  364. denominator = one;
  365. // d_numerator = (x-pi/2)^2
  366. ValueType pi05;
  367. pi05.Set05Pi();
  368. temp = x;
  369. temp.Sub( pi05 );
  370. d_numerator = temp;
  371. d_numerator.Mul( temp );
  372. d_denominator = one;
  373. }
  374. uint c = 0;
  375. bool addition = false;
  376. old_result = result;
  377. for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
  378. {
  379. // we're starting from a second part of the formula
  380. c += numerator. Mul( d_numerator );
  381. c += denominator. Mul( d_denominator );
  382. c += d_denominator.Add( one );
  383. c += denominator. Mul( d_denominator );
  384. c += d_denominator.Add( one );
  385. temp = numerator;
  386. c += temp.Div(denominator);
  387. if( c )
  388. // Sin is from <-1,1> and cannot make an overflow
  389. // but the carry can be from the Taylor series
  390. // (then we only break our calculations)
  391. break;
  392. if( addition )
  393. result.Add( temp );
  394. else
  395. result.Sub( temp );
  396. addition = !addition;
  397. // we're testing whether the result has changed after adding
  398. // the next part of the Taylor formula, if not we end the loop
  399. // (it means 'x' is zero or 'x' is PI/2 or this part of the formula
  400. // is too small)
  401. if( result == old_result )
  402. break;
  403. old_result = result;
  404. }
  405. return result;
  406. }
  407. } // namespace auxiliaryfunctions
  408. /*!
  409. this function calculates the Sine
  410. */
  411. template<class ValueType>
  412. ValueType Sin(ValueType x, ErrorCode * err = 0)
  413. {
  414. using namespace auxiliaryfunctions;
  415. ValueType one, result;
  416. bool change_sign;
  417. if( x.IsNan() )
  418. {
  419. if( err )
  420. *err = err_improper_argument;
  421. return x;
  422. }
  423. if( err )
  424. *err = err_ok;
  425. if( PrepareSin( x, change_sign ) )
  426. {
  427. // x is too big, we cannnot reduce the 2*PI period
  428. // prior to version 0.8.5 the result was zero
  429. // result has NaN flag set by default
  430. if( err )
  431. *err = err_overflow; // maybe another error code? err_improper_argument?
  432. return result; // NaN is set by default
  433. }
  434. result = Sin0pi05( x );
  435. one.SetOne();
  436. // after calculations there can be small distortions in the result
  437. if( result > one )
  438. result = one;
  439. else
  440. if( result.IsSign() )
  441. // we've calculated the sin from <0, pi/2> and the result
  442. // should be positive
  443. result.SetZero();
  444. if( change_sign )
  445. result.ChangeSign();
  446. return result;
  447. }
  448. /*!
  449. this function calulates the Cosine
  450. we're using the formula cos(x) = sin(x + PI/2)
  451. */
  452. template<class ValueType>
  453. ValueType Cos(ValueType x, ErrorCode * err = 0)
  454. {
  455. if( x.IsNan() )
  456. {
  457. if( err )
  458. *err = err_improper_argument;
  459. return x; // NaN
  460. }
  461. ValueType pi05;
  462. pi05.Set05Pi();
  463. uint c = x.Add( pi05 );
  464. if( c )
  465. {
  466. if( err )
  467. *err = err_overflow;
  468. return ValueType(); // result is undefined (NaN is set by default)
  469. }
  470. return Sin(x, err);
  471. }
  472. /*!
  473. this function calulates the Tangent
  474. we're using the formula tan(x) = sin(x) / cos(x)
  475. it takes more time than calculating the Tan directly
  476. from for example Taylor series but should be a bit preciser
  477. because Tan receives its values from -infinity to +infinity
  478. and when we calculate it from any series then we can make
  479. a greater mistake than calculating 'sin/cos'
  480. */
  481. template<class ValueType>
  482. ValueType Tan(const ValueType & x, ErrorCode * err = 0)
  483. {
  484. ValueType result = Cos(x, err);
  485. if( err && *err != err_ok )
  486. return result;
  487. if( result.IsZero() )
  488. {
  489. if( err )
  490. *err = err_improper_argument;
  491. result.SetNan();
  492. return result;
  493. }
  494. return Sin(x, err) / result;
  495. }
  496. /*!
  497. this function calulates the Tangent
  498. look at the description of Tan(...)
  499. (the abbreviation of Tangent can be 'tg' as well)
  500. */
  501. template<class ValueType>
  502. ValueType Tg(const ValueType & x, ErrorCode * err = 0)
  503. {
  504. return Tan(x, err);
  505. }
  506. /*!
  507. this function calulates the Cotangent
  508. we're using the formula tan(x) = cos(x) / sin(x)
  509. (why do we make it in this way?
  510. look at information in Tan() function)
  511. */
  512. template<class ValueType>
  513. ValueType Cot(const ValueType & x, ErrorCode * err = 0)
  514. {
  515. ValueType result = Sin(x, err);
  516. if( err && *err != err_ok )
  517. return result;
  518. if( result.IsZero() )
  519. {
  520. if( err )
  521. *err = err_improper_argument;
  522. result.SetNan();
  523. return result;
  524. }
  525. return Cos(x, err) / result;
  526. }
  527. /*!
  528. this function calulates the Cotangent
  529. look at the description of Cot(...)
  530. (the abbreviation of Cotangent can be 'ctg' as well)
  531. */
  532. template<class ValueType>
  533. ValueType Ctg(const ValueType & x, ErrorCode * err = 0)
  534. {
  535. return Cot(x, err);
  536. }
  537. /*
  538. *
  539. * inverse trigonometric functions
  540. *
  541. *
  542. */
  543. namespace auxiliaryfunctions
  544. {
  545. /*!
  546. an auxiliary function for calculating the Arc Sine
  547. we're calculating asin from the following formula:
  548. asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ...
  549. where abs(x) <= 1
  550. we're using this formula when x is from <0, 1/2>
  551. */
  552. template<class ValueType>
  553. ValueType ASin_0(const ValueType & x)
  554. {
  555. ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x;
  556. ValueType two, result(x), x2(x);
  557. ValueType nominator_temp, denominator_temp, old_result = result;
  558. uint c = 0;
  559. x2.Mul(x);
  560. two = 2;
  561. nominator.SetOne();
  562. denominator = two;
  563. nominator_add = nominator;
  564. denominator_add = denominator;
  565. nominator_x = x;
  566. denominator_x = 3;
  567. for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
  568. {
  569. c += nominator_x.Mul(x2);
  570. nominator_temp = nominator_x;
  571. c += nominator_temp.Mul(nominator);
  572. denominator_temp = denominator;
  573. c += denominator_temp.Mul(denominator_x);
  574. c += nominator_temp.Div(denominator_temp);
  575. // if there is a carry somewhere we only break the calculating
  576. // the result should be ok -- it's from <-pi/2, pi/2>
  577. if( c )
  578. break;
  579. result.Add(nominator_temp);
  580. if( result == old_result )
  581. // there's no sense to calculate more
  582. break;
  583. old_result = result;
  584. c += nominator_add.Add(two);
  585. c += denominator_add.Add(two);
  586. c += nominator.Mul(nominator_add);
  587. c += denominator.Mul(denominator_add);
  588. c += denominator_x.Add(two);
  589. }
  590. return result;
  591. }
  592. /*!
  593. an auxiliary function for calculating the Arc Sine
  594. we're calculating asin from the following formula:
  595. asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp
  596. asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ...
  597. where abs(x) <= 1
  598. we're using this formula when x is from (1/2, 1>
  599. */
  600. template<class ValueType>
  601. ValueType ASin_1(const ValueType & x)
  602. {
  603. ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x;
  604. ValueType denominator2;
  605. ValueType one, two, result;
  606. ValueType nominator_temp, denominator_temp, old_result;
  607. uint c = 0;
  608. two = 2;
  609. one.SetOne();
  610. nominator = one;
  611. result = one;
  612. old_result = result;
  613. denominator = two;
  614. nominator_add = nominator;
  615. denominator_add = denominator;
  616. nominator_x = one;
  617. nominator_x.Sub(x);
  618. nominator_x_add = nominator_x;
  619. denominator_x = 3;
  620. denominator2 = two;
  621. for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
  622. {
  623. nominator_temp = nominator_x;
  624. c += nominator_temp.Mul(nominator);
  625. denominator_temp = denominator;
  626. c += denominator_temp.Mul(denominator_x);
  627. c += denominator_temp.Mul(denominator2);
  628. c += nominator_temp.Div(denominator_temp);
  629. // if there is a carry somewhere we only break the calculating
  630. // the result should be ok -- it's from <-pi/2, pi/2>
  631. if( c )
  632. break;
  633. result.Add(nominator_temp);
  634. if( result == old_result )
  635. // there's no sense to calculate more
  636. break;
  637. old_result = result;
  638. c += nominator_x.Mul(nominator_x_add);
  639. c += nominator_add.Add(two);
  640. c += denominator_add.Add(two);
  641. c += nominator.Mul(nominator_add);
  642. c += denominator.Mul(denominator_add);
  643. c += denominator_x.Add(two);
  644. c += denominator2.Mul(two);
  645. }
  646. nominator_x_add.exponent.AddOne(); // *2
  647. one.exponent.SubOne(); // =0.5
  648. nominator_x_add.Pow(one); // =sqrt(nominator_x_add)
  649. result.Mul(nominator_x_add);
  650. one.Set05Pi();
  651. one.Sub(result);
  652. return one;
  653. }
  654. } // namespace auxiliaryfunctions
  655. /*!
  656. this function calculates the Arc Sine
  657. x is from <-1,1>
  658. */
  659. template<class ValueType>
  660. ValueType ASin(ValueType x, ErrorCode * err = 0)
  661. {
  662. using namespace auxiliaryfunctions;
  663. ValueType result, one;
  664. one.SetOne();
  665. bool change_sign = false;
  666. if( x.IsNan() )
  667. {
  668. if( err )
  669. *err = err_improper_argument;
  670. return x;
  671. }
  672. if( x.GreaterWithoutSignThan(one) )
  673. {
  674. if( err )
  675. *err = err_improper_argument;
  676. return result; // NaN is set by default
  677. }
  678. if( x.IsSign() )
  679. {
  680. change_sign = true;
  681. x.Abs();
  682. }
  683. one.exponent.SubOne(); // =0.5
  684. // asin(-x) = -asin(x)
  685. if( x.GreaterWithoutSignThan(one) )
  686. result = ASin_1(x);
  687. else
  688. result = ASin_0(x);
  689. if( change_sign )
  690. result.ChangeSign();
  691. if( err )
  692. *err = err_ok;
  693. return result;
  694. }
  695. /*!
  696. this function calculates the Arc Cosine
  697. we're using the formula:
  698. acos(x) = pi/2 - asin(x)
  699. */
  700. template<class ValueType>
  701. ValueType ACos(const ValueType & x, ErrorCode * err = 0)
  702. {
  703. ValueType temp;
  704. temp.Set05Pi();
  705. temp.Sub(ASin(x, err));
  706. return temp;
  707. }
  708. namespace auxiliaryfunctions
  709. {
  710. /*!
  711. an auxiliary function for calculating the Arc Tangent
  712. arc tan (x) where x is in <0; 0.5)
  713. (x can be in (-0.5 ; 0.5) too)
  714. we're using the Taylor series expanded in zero:
  715. atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...
  716. */
  717. template<class ValueType>
  718. ValueType ATan0(const ValueType & x)
  719. {
  720. ValueType nominator, denominator, nominator_add, denominator_add, temp;
  721. ValueType result, old_result;
  722. bool adding = false;
  723. uint c = 0;
  724. result = x;
  725. old_result = result;
  726. nominator = x;
  727. nominator_add = x;
  728. nominator_add.Mul(x);
  729. denominator.SetOne();
  730. denominator_add = 2;
  731. for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
  732. {
  733. c += nominator.Mul(nominator_add);
  734. c += denominator.Add(denominator_add);
  735. temp = nominator;
  736. c += temp.Div(denominator);
  737. if( c )
  738. // the result should be ok
  739. break;
  740. if( adding )
  741. result.Add(temp);
  742. else
  743. result.Sub(temp);
  744. if( result == old_result )
  745. // there's no sense to calculate more
  746. break;
  747. old_result = result;
  748. adding = !adding;
  749. }
  750. return result;
  751. }
  752. /*!
  753. an auxiliary function for calculating the Arc Tangent
  754. where x is in <0 ; 1>
  755. */
  756. template<class ValueType>
  757. ValueType ATan01(const ValueType & x)
  758. {
  759. ValueType half;
  760. half.Set05();
  761. /*
  762. it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here
  763. because as you can see below:
  764. when x = sqrt(2)-1
  765. abs(x) = abs( (x-1)/(1+x) )
  766. so when we're calculating values around x
  767. then they will be better converged to each other
  768. for example if we have x=0.4999 then during calculating ATan0(0.4999)
  769. we have to make about 141 iterations but when we have x=0.5
  770. then during calculating ATan0( (x-1)/(1+x) ) we have to make
  771. only about 89 iterations (both for Big<3,9>)
  772. in the future this 0.5 can be changed
  773. */
  774. if( x.SmallerWithoutSignThan(half) )
  775. return ATan0(x);
  776. /*
  777. x>=0.5 and x<=1
  778. (x can be even smaller than 0.5)
  779. y = atac(x)
  780. x = tan(y)
  781. tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b))
  782. y-b = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) )
  783. y = b + atan( (x-tab(b)) / (1+x*tan(b)) )
  784. let b = pi/4
  785. tan(b) = tan(pi/4) = 1
  786. y = pi/4 + atan( (x-1)/(1+x) )
  787. so
  788. atac(x) = pi/4 + atan( (x-1)/(1+x) )
  789. when x->1 (x converges to 1) the (x-1)/(1+x) -> 0
  790. and we can use ATan0() function here
  791. */
  792. ValueType n(x),d(x),one,result;
  793. one.SetOne();
  794. n.Sub(one);
  795. d.Add(one);
  796. n.Div(d);
  797. result = ATan0(n);
  798. n.Set05Pi();
  799. n.exponent.SubOne(); // =pi/4
  800. result.Add(n);
  801. return result;
  802. }
  803. /*!
  804. an auxiliary function for calculating the Arc Tangent
  805. where x > 1
  806. we're using the formula:
  807. atan(x) = pi/2 - atan(1/x) for x>0
  808. */
  809. template<class ValueType>
  810. ValueType ATanGreaterThanPlusOne(const ValueType & x)
  811. {
  812. ValueType temp, atan;
  813. temp.SetOne();
  814. if( temp.Div(x) )
  815. {
  816. // if there was a carry here that means x is very big
  817. // and atan(1/x) fast converged to 0
  818. atan.SetZero();
  819. }
  820. else
  821. atan = ATan01(temp);
  822. temp.Set05Pi();
  823. temp.Sub(atan);
  824. return temp;
  825. }
  826. } // namespace auxiliaryfunctions
  827. /*!
  828. this function calculates the Arc Tangent
  829. */
  830. template<class ValueType>
  831. ValueType ATan(ValueType x)
  832. {
  833. using namespace auxiliaryfunctions;
  834. ValueType one, result;
  835. one.SetOne();
  836. bool change_sign = false;
  837. if( x.IsNan() )
  838. return x;
  839. // if x is negative we're using the formula:
  840. // atan(-x) = -atan(x)
  841. if( x.IsSign() )
  842. {
  843. change_sign = true;
  844. x.Abs();
  845. }
  846. if( x.GreaterWithoutSignThan(one) )
  847. result = ATanGreaterThanPlusOne(x);
  848. else
  849. result = ATan01(x);
  850. if( change_sign )
  851. result.ChangeSign();
  852. return result;
  853. }
  854. /*!
  855. this function calculates the Arc Tangent
  856. look at the description of ATan(...)
  857. (the abbreviation of Arc Tangent can be 'atg' as well)
  858. */
  859. template<class ValueType>
  860. ValueType ATg(const ValueType & x)
  861. {
  862. return ATan(x);
  863. }
  864. /*!
  865. this function calculates the Arc Cotangent
  866. we're using the formula:
  867. actan(x) = pi/2 - atan(x)
  868. */
  869. template<class ValueType>
  870. ValueType ACot(const ValueType & x)
  871. {
  872. ValueType result;
  873. result.Set05Pi();
  874. result.Sub(ATan(x));
  875. return result;
  876. }
  877. /*!
  878. this function calculates the Arc Cotangent
  879. look at the description of ACot(...)
  880. (the abbreviation of Arc Cotangent can be 'actg' as well)
  881. */
  882. template<class ValueType>
  883. ValueType ACtg(const ValueType & x)
  884. {
  885. return ACot(x);
  886. }
  887. /*
  888. *
  889. * hyperbolic functions
  890. *
  891. *
  892. */
  893. /*!
  894. this function calculates the Hyperbolic Sine
  895. we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2
  896. */
  897. template<class ValueType>
  898. ValueType Sinh(const ValueType & x, ErrorCode * err = 0)
  899. {
  900. if( x.IsNan() )
  901. {
  902. if( err )
  903. *err = err_improper_argument;
  904. return x; // NaN
  905. }
  906. ValueType ex, emx;
  907. uint c = 0;
  908. c += ex.Exp(x);
  909. c += emx.Exp(-x);
  910. c += ex.Sub(emx);
  911. c += ex.exponent.SubOne();
  912. if( err )
  913. *err = c ? err_overflow : err_ok;
  914. return ex;
  915. }
  916. /*!
  917. this function calculates the Hyperbolic Cosine
  918. we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2
  919. */
  920. template<class ValueType>
  921. ValueType Cosh(const ValueType & x, ErrorCode * err = 0)
  922. {
  923. if( x.IsNan() )
  924. {
  925. if( err )
  926. *err = err_improper_argument;
  927. return x; // NaN
  928. }
  929. ValueType ex, emx;
  930. uint c = 0;
  931. c += ex.Exp(x);
  932. c += emx.Exp(-x);
  933. c += ex.Add(emx);
  934. c += ex.exponent.SubOne();
  935. if( err )
  936. *err = c ? err_overflow : err_ok;
  937. return ex;
  938. }
  939. /*!
  940. this function calculates the Hyperbolic Tangent
  941. we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) )
  942. */
  943. template<class ValueType>
  944. ValueType Tanh(const ValueType & x, ErrorCode * err = 0)
  945. {
  946. if( x.IsNan() )
  947. {
  948. if( err )
  949. *err = err_improper_argument;
  950. return x; // NaN
  951. }
  952. ValueType ex, emx, nominator, denominator;
  953. uint c = 0;
  954. c += ex.Exp(x);
  955. c += emx.Exp(-x);
  956. nominator = ex;
  957. c += nominator.Sub(emx);
  958. denominator = ex;
  959. c += denominator.Add(emx);
  960. c += nominator.Div(denominator);
  961. if( err )
  962. *err = c ? err_overflow : err_ok;
  963. return nominator;
  964. }
  965. /*!
  966. this function calculates the Hyperbolic Tangent
  967. look at the description of Tanh(...)
  968. (the abbreviation of Hyperbolic Tangent can be 'tgh' as well)
  969. */
  970. template<class ValueType>
  971. ValueType Tgh(const ValueType & x, ErrorCode * err = 0)
  972. {
  973. return Tanh(x, err);
  974. }
  975. /*!
  976. this function calculates the Hyperbolic Cotangent
  977. we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) )
  978. */
  979. template<class ValueType>
  980. ValueType Coth(const ValueType & x, ErrorCode * err = 0)
  981. {
  982. if( x.IsNan() )
  983. {
  984. if( err )
  985. *err = err_improper_argument;
  986. return x; // NaN
  987. }
  988. if( x.IsZero() )
  989. {
  990. if( err )
  991. *err = err_improper_argument;
  992. return ValueType(); // NaN is set by default
  993. }
  994. ValueType ex, emx, nominator, denominator;
  995. uint c = 0;
  996. c += ex.Exp(x);
  997. c += emx.Exp(-x);
  998. nominator = ex;
  999. c += nominator.Add(emx);
  1000. denominator = ex;
  1001. c += denominator.Sub(emx);
  1002. c += nominator.Div(denominator);
  1003. if( err )
  1004. *err = c ? err_overflow : err_ok;
  1005. return nominator;
  1006. }
  1007. /*!
  1008. this function calculates the Hyperbolic Cotangent
  1009. look at the description of Coth(...)
  1010. (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well)
  1011. */
  1012. template<class ValueType>
  1013. ValueType Ctgh(const ValueType & x, ErrorCode * err = 0)
  1014. {
  1015. return Coth(x, err);
  1016. }
  1017. /*
  1018. *
  1019. * inverse hyperbolic functions
  1020. *
  1021. *
  1022. */
  1023. /*!
  1024. inverse hyperbolic sine
  1025. asinh(x) = ln( x + sqrt(x^2 + 1) )
  1026. */
  1027. template<class ValueType>
  1028. ValueType ASinh(const ValueType & x, ErrorCode * err = 0)
  1029. {
  1030. if( x.IsNan() )
  1031. {
  1032. if( err )
  1033. *err = err_improper_argument;
  1034. return x; // NaN
  1035. }
  1036. ValueType xx(x), one, result;
  1037. uint c = 0;
  1038. one.SetOne();
  1039. c += xx.Mul(x);
  1040. c += xx.Add(one);
  1041. one.exponent.SubOne(); // one=0.5
  1042. // xx is >= 1
  1043. c += xx.PowFrac(one); // xx=sqrt(xx)
  1044. c += xx.Add(x);
  1045. c += result.Ln(xx); // xx > 0
  1046. // here can only be a carry
  1047. if( err )
  1048. *err = c ? err_overflow : err_ok;
  1049. return result;
  1050. }
  1051. /*!
  1052. inverse hyperbolic cosine
  1053. acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity)
  1054. */
  1055. template<class ValueType>
  1056. ValueType ACosh(const ValueType & x, ErrorCode * err = 0)
  1057. {
  1058. if( x.IsNan() )
  1059. {
  1060. if( err )
  1061. *err = err_improper_argument;
  1062. return x; // NaN
  1063. }
  1064. ValueType xx(x), one, result;
  1065. uint c = 0;
  1066. one.SetOne();
  1067. if( x < one )
  1068. {
  1069. if( err )
  1070. *err = err_improper_argument;
  1071. return result; // NaN is set by default
  1072. }
  1073. c += xx.Mul(x);
  1074. c += xx.Sub(one);
  1075. // xx is >= 0
  1076. // we can't call a PowFrac when the 'x' is zero
  1077. // if x is 0 the sqrt(0) is 0
  1078. if( !xx.IsZero() )
  1079. {
  1080. one.exponent.SubOne(); // one=0.5
  1081. c += xx.PowFrac(one); // xx=sqrt(xx)
  1082. }
  1083. c += xx.Add(x);
  1084. c += result.Ln(xx); // xx >= 1
  1085. // here can only be a carry
  1086. if( err )
  1087. *err = c ? err_overflow : err_ok;
  1088. return result;
  1089. }
  1090. /*!
  1091. inverse hyperbolic tangent
  1092. atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1)
  1093. */
  1094. template<class ValueType>
  1095. ValueType ATanh(const ValueType & x, ErrorCode * err = 0)
  1096. {
  1097. if( x.IsNan() )
  1098. {
  1099. if( err )
  1100. *err = err_improper_argument;
  1101. return x; // NaN
  1102. }
  1103. ValueType nominator(x), denominator, one, result;
  1104. uint c = 0;
  1105. one.SetOne();
  1106. if( !x.SmallerWithoutSignThan(one) )
  1107. {
  1108. if( err )
  1109. *err = err_improper_argument;
  1110. return result; // NaN is set by default
  1111. }
  1112. c += nominator.Add(one);
  1113. denominator = one;
  1114. c += denominator.Sub(x);
  1115. c += nominator.Div(denominator);
  1116. c += result.Ln(nominator);
  1117. c += result.exponent.SubOne();
  1118. // here can only be a carry
  1119. if( err )
  1120. *err = c ? err_overflow : err_ok;
  1121. return result;
  1122. }
  1123. /*!
  1124. inverse hyperbolic tantent
  1125. */
  1126. template<class ValueType>
  1127. ValueType ATgh(const ValueType & x, ErrorCode * err = 0)
  1128. {
  1129. return ATanh(x, err);
  1130. }
  1131. /*!
  1132. inverse hyperbolic cotangent
  1133. acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity)
  1134. */
  1135. template<class ValueType>
  1136. ValueType ACoth(const ValueType & x, ErrorCode * err = 0)
  1137. {
  1138. if( x.IsNan() )
  1139. {
  1140. if( err )
  1141. *err = err_improper_argument;
  1142. return x; // NaN
  1143. }
  1144. ValueType nominator(x), denominator(x), one, result;
  1145. uint c = 0;
  1146. one.SetOne();
  1147. if( !x.GreaterWithoutSignThan(one) )
  1148. {
  1149. if( err )
  1150. *err = err_improper_argument;
  1151. return result; // NaN is set by default
  1152. }
  1153. c += nominator.Add(one);
  1154. c += denominator.Sub(one);
  1155. c += nominator.Div(denominator);
  1156. c += result.Ln(nominator);
  1157. c += result.exponent.SubOne();
  1158. // here can only be a carry
  1159. if( err )
  1160. *err = c ? err_overflow : err_ok;
  1161. return result;
  1162. }
  1163. /*!
  1164. inverse hyperbolic cotantent
  1165. */
  1166. template<class ValueType>
  1167. ValueType ACtgh(const ValueType & x, ErrorCode * err = 0)
  1168. {
  1169. return ACoth(x, err);
  1170. }
  1171. /*
  1172. *
  1173. * functions for converting between degrees, radians and gradians
  1174. *
  1175. *
  1176. */
  1177. /*!
  1178. this function converts degrees to radians
  1179. it returns: x * pi / 180
  1180. */
  1181. template<class ValueType>
  1182. ValueType DegToRad(const ValueType & x, ErrorCode * err = 0)
  1183. {
  1184. ValueType result, temp;
  1185. uint c = 0;
  1186. if( x.IsNan() )
  1187. {
  1188. if( err )
  1189. *err = err_improper_argument;
  1190. return x;
  1191. }
  1192. result = x;
  1193. // it is better to make division first and then multiplication
  1194. // the result is more accurate especially when x is: 90,180,270 or 360
  1195. temp = 180;
  1196. c += result.Div(temp);
  1197. temp.SetPi();
  1198. c += result.Mul(temp);
  1199. if( err )
  1200. *err = c ? err_overflow : err_ok;
  1201. return result;
  1202. }
  1203. /*!
  1204. this function converts radians to degrees
  1205. it returns: x * 180 / pi
  1206. */
  1207. template<class ValueType>
  1208. ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0)
  1209. {
  1210. ValueType result, delimiter;
  1211. uint c = 0;
  1212. if( x.IsNan() )
  1213. {
  1214. if( err )
  1215. *err = err_improper_argument;
  1216. return x;
  1217. }
  1218. result = 180;
  1219. c += result.Mul(x);
  1220. delimiter.SetPi();
  1221. c += result.Div(delimiter);
  1222. if( err )
  1223. *err = c ? err_overflow : err_ok;
  1224. return result;
  1225. }
  1226. /*!
  1227. this function converts degrees in the long format into one value
  1228. long format: (degrees, minutes, seconds)
  1229. minutes and seconds must be greater than or equal zero
  1230. result:
  1231. if d>=0 : result= d + ((s/60)+m)/60
  1232. if d<0 : result= d - ((s/60)+m)/60
  1233. ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because
  1234. there's only one division)
  1235. for example:
  1236. DegToDeg(10, 30, 0) = 10.5
  1237. DegToDeg(10, 24, 35.6)=10.4098(8)
  1238. */
  1239. template<class ValueType>
  1240. ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s,
  1241. ErrorCode * err = 0)
  1242. {
  1243. ValueType delimiter, multipler;
  1244. uint c = 0;
  1245. if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() )
  1246. {
  1247. if( err )
  1248. *err = err_improper_argument;
  1249. delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable
  1250. return delimiter;
  1251. }
  1252. multipler = 60;
  1253. delimiter = 3600;
  1254. c += multipler.Mul(m);
  1255. c += multipler.Add(s);
  1256. c += multipler.Div(delimiter);
  1257. if( d.IsSign() )
  1258. multipler.ChangeSign();
  1259. c += multipler.Add(d);
  1260. if( err )
  1261. *err = c ? err_overflow : err_ok;
  1262. return multipler;
  1263. }
  1264. /*!
  1265. this function converts degrees in the long format to radians
  1266. */
  1267. template<class ValueType>
  1268. ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s,
  1269. ErrorCode * err = 0)
  1270. {
  1271. ValueType temp_deg = DegToDeg(d,m,s,err);
  1272. if( err && *err!=err_ok )
  1273. return temp_deg;
  1274. return DegToRad(temp_deg, err);
  1275. }
  1276. /*!
  1277. this function converts gradians to radians
  1278. it returns: x * pi / 200
  1279. */
  1280. template<class ValueType>
  1281. ValueType GradToRad(const ValueType & x, ErrorCode * err = 0)
  1282. {
  1283. ValueType result, temp;
  1284. uint c = 0;
  1285. if( x.IsNan() )
  1286. {
  1287. if( err )
  1288. *err = err_improper_argument;
  1289. return x;
  1290. }
  1291. result = x;
  1292. // it is better to make division first and then multiplication
  1293. // the result is more accurate especially when x is: 100,200,300 or 400
  1294. temp = 200;
  1295. c += result.Div(temp);
  1296. temp.SetPi();
  1297. c += result.Mul(temp);
  1298. if( err )
  1299. *err = c ? err_overflow : err_ok;
  1300. return result;
  1301. }
  1302. /*!
  1303. this function converts radians to gradians
  1304. it returns: x * 200 / pi
  1305. */
  1306. template<class ValueType>
  1307. ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0)
  1308. {
  1309. ValueType result, delimiter;
  1310. uint c = 0;
  1311. if( x.IsNan() )
  1312. {
  1313. if( err )
  1314. *err = err_improper_argument;
  1315. return x;
  1316. }
  1317. result = 200;
  1318. c += result.Mul(x);
  1319. delimiter.SetPi();
  1320. c += result.Div(delimiter);
  1321. if( err )
  1322. *err = c ? err_overflow : err_ok;
  1323. return result;
  1324. }
  1325. /*!
  1326. this function converts degrees to gradians
  1327. it returns: x * 200 / 180
  1328. */
  1329. template<class ValueType>
  1330. ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0)
  1331. {
  1332. ValueType result, temp;
  1333. uint c = 0;
  1334. if( x.IsNan() )
  1335. {
  1336. if( err )
  1337. *err = err_improper_argument;
  1338. return x;
  1339. }
  1340. result = x;
  1341. temp = 200;
  1342. c += result.Mul(temp);
  1343. temp = 180;
  1344. c += result.Div(temp);
  1345. if( err )
  1346. *err = c ? err_overflow : err_ok;
  1347. return result;
  1348. }
  1349. /*!
  1350. this function converts degrees in the long format to gradians
  1351. */
  1352. template<class ValueType>
  1353. ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s,
  1354. ErrorCode * err = 0)
  1355. {
  1356. ValueType temp_deg = DegToDeg(d,m,s,err);
  1357. if( err && *err!=err_ok )
  1358. return temp_deg;
  1359. return DegToGrad(temp_deg, err);
  1360. }
  1361. /*!
  1362. this function converts degrees to gradians
  1363. it returns: x * 180 / 200
  1364. */
  1365. template<class ValueType>
  1366. ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0)
  1367. {
  1368. ValueType result, temp;
  1369. uint c = 0;
  1370. if( x.IsNan() )
  1371. {
  1372. if( err )
  1373. *err = err_improper_argument;
  1374. return x;
  1375. }
  1376. result = x;
  1377. temp = 180;
  1378. c += result.Mul(temp);
  1379. temp = 200;
  1380. c += result.Div(temp);
  1381. if( err )
  1382. *err = c ? err_overflow : err_ok;
  1383. return result;
  1384. }
  1385. /*
  1386. *
  1387. * another functions
  1388. *
  1389. *
  1390. */
  1391. /*!
  1392. this function calculates the square root
  1393. Sqrt(9) = 3
  1394. */
  1395. template<class ValueType>
  1396. ValueType Sqrt(ValueType x, ErrorCode * err = 0)
  1397. {
  1398. if( x.IsNan() || x.IsSign() )
  1399. {
  1400. if( err )
  1401. *err = err_improper_argument;
  1402. x.SetNan();
  1403. return x;
  1404. }
  1405. uint c = x.Sqrt();
  1406. if( err )
  1407. *err = c ? err_overflow : err_ok;
  1408. return x;
  1409. }
  1410. namespace auxiliaryfunctions
  1411. {
  1412. template<class ValueType>
  1413. bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err)
  1414. {
  1415. if( index.IsSign() )
  1416. {
  1417. // index cannot be negative
  1418. if( err )
  1419. *err = err_improper_argument;
  1420. x.SetNan();
  1421. return true;
  1422. }
  1423. return false;
  1424. }
  1425. template<class ValueType>
  1426. bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err)
  1427. {
  1428. if( index.IsZero() )
  1429. {
  1430. if( x.IsZero() )
  1431. {
  1432. // there isn't root(0;0) - we assume it's not defined
  1433. if( err )
  1434. *err = err_improper_argument;
  1435. x.SetNan();
  1436. return true;
  1437. }
  1438. // root(x;0) is 1 (if x!=0)
  1439. x.SetOne();
  1440. if( err )
  1441. *err = err_ok;
  1442. return true;
  1443. }
  1444. return false;
  1445. }
  1446. template<class ValueType>
  1447. bool RootCheckIndexOne(const ValueType & index, ErrorCode * err)
  1448. {
  1449. ValueType one;
  1450. one.SetOne();
  1451. if( index == one )
  1452. {
  1453. //root(x;1) is x
  1454. // we do it because if we used the PowFrac function
  1455. // we would lose the precision
  1456. if( err )
  1457. *err = err_ok;
  1458. return true;
  1459. }
  1460. return false;
  1461. }
  1462. template<class ValueType>
  1463. bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err)
  1464. {
  1465. if( index == 2 )
  1466. {
  1467. x = Sqrt(x, err);
  1468. return true;
  1469. }
  1470. return false;
  1471. }
  1472. template<class ValueType>
  1473. bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err)
  1474. {
  1475. if( !index.IsInteger() )
  1476. {
  1477. // index must be integer
  1478. if( err )
  1479. *err = err_improper_argument;
  1480. x.SetNan();
  1481. return true;
  1482. }
  1483. return false;
  1484. }
  1485. template<class ValueType>
  1486. bool RootCheckXZero(ValueType & x, ErrorCode * err)
  1487. {
  1488. if( x.IsZero() )
  1489. {
  1490. // root(0;index) is zero (if index!=0)
  1491. // RootCheckIndexZero() must be called beforehand
  1492. x.SetZero();
  1493. if( err )
  1494. *err = err_ok;
  1495. return true;
  1496. }
  1497. return false;
  1498. }
  1499. template<class ValueType>
  1500. bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign)
  1501. {
  1502. *change_sign = false;
  1503. if( index.Mod2() )
  1504. {
  1505. // index is odd (1,3,5...)
  1506. if( x.IsSign() )
  1507. {
  1508. *change_sign = true;
  1509. x.Abs();
  1510. }
  1511. }
  1512. else
  1513. {
  1514. // index is even
  1515. // x cannot be negative
  1516. if( x.IsSign() )
  1517. {
  1518. if( err )
  1519. *err = err_improper_argument;
  1520. x.SetNan();
  1521. return true;
  1522. }
  1523. }
  1524. return false;
  1525. }
  1526. template<class ValueType>
  1527. uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index)
  1528. {
  1529. if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() )
  1530. return 0;
  1531. // old_x is integer,
  1532. // x is not integer,
  1533. // index is relatively small (index.exponent<0 or index.exponent<=0)
  1534. // (because we're using a special powering algorithm Big::PowUInt())
  1535. uint c = 0;
  1536. ValueType temp(x);
  1537. c += temp.Round();
  1538. ValueType temp_round(temp);
  1539. c += temp.PowUInt(index);
  1540. if( temp == old_x )
  1541. x = temp_round;
  1542. return (c==0)? 0 : 1;
  1543. }
  1544. } // namespace auxiliaryfunctions
  1545. /*!
  1546. indexth Root of x
  1547. index must be integer and not negative <0;1;2;3....)
  1548. if index==0 the result is one
  1549. if x==0 the result is zero and we assume root(0;0) is not defined
  1550. if index is even (2;4;6...) the result is x^(1/index) and x>0
  1551. if index is odd (1;2;3;...) the result is either
  1552. -(abs(x)^(1/index)) if x<0 or
  1553. x^(1/index)) if x>0
  1554. (for index==1 the result is equal x)
  1555. */
  1556. template<class ValueType>
  1557. ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0)
  1558. {
  1559. using namespace auxiliaryfunctions;
  1560. if( x.IsNan() || index.IsNan() )
  1561. {
  1562. if( err )
  1563. *err = err_improper_argument;
  1564. x.SetNan();
  1565. return x;
  1566. }
  1567. if( RootCheckIndexSign(x, index, err) ) return x;
  1568. if( RootCheckIndexZero(x, index, err) ) return x;
  1569. if( RootCheckIndexOne ( index, err) ) return x;
  1570. if( RootCheckIndexTwo (x, index, err) ) return x;
  1571. if( RootCheckIndexFrac(x, index, err) ) return x;
  1572. if( RootCheckXZero (x, err) ) return x;
  1573. // index integer and index!=0
  1574. // x!=0
  1575. ValueType old_x(x);
  1576. bool change_sign;
  1577. if( RootCheckIndex(x, index, err, &change_sign ) ) return x;
  1578. ValueType temp;
  1579. uint c = 0;
  1580. // we're using the formula: root(x ; n) = exp( ln(x) / n )
  1581. c += temp.Ln(x);
  1582. c += temp.Div(index);
  1583. c += x.Exp(temp);
  1584. if( change_sign )
  1585. {
  1586. // x is different from zero
  1587. x.SetSign();
  1588. }
  1589. c += RootCorrectInteger(old_x, x, index);
  1590. if( err )
  1591. *err = c ? err_overflow : err_ok;
  1592. return x;
  1593. }
  1594. /*!
  1595. absolute value of x
  1596. e.g. -2 = 2
  1597. 2 = 2
  1598. */
  1599. template<class ValueType>
  1600. ValueType Abs(const ValueType & x)
  1601. {
  1602. ValueType result( x );
  1603. result.Abs();
  1604. return result;
  1605. }
  1606. /*!
  1607. it returns the sign of the value
  1608. e.g. -2 = -1
  1609. 0 = 0
  1610. 10 = 1
  1611. */
  1612. template<class ValueType>
  1613. ValueType Sgn(ValueType x)
  1614. {
  1615. x.Sgn();
  1616. return x;
  1617. }
  1618. /*!
  1619. the remainder from a division
  1620. e.g.
  1621. mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6
  1622. mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
  1623. mod( 12.6 ; -3) = 0.6
  1624. mod(-12.6 ; -3) = -0.6
  1625. */
  1626. template<class ValueType>
  1627. ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0)
  1628. {
  1629. if( a.IsNan() || b.IsNan() )
  1630. {
  1631. if( err )
  1632. *err = err_improper_argument;
  1633. a.SetNan();
  1634. return a;
  1635. }
  1636. uint c = a.Mod(b);
  1637. if( err )
  1638. *err = c ? err_overflow : err_ok;
  1639. return a;
  1640. }
  1641. namespace auxiliaryfunctions
  1642. {
  1643. /*!
  1644. this function is used to store factorials in a given container
  1645. 'more' means how many values should be added at the end
  1646. e.g.
  1647. std::vector<ValueType> fact;
  1648. SetFactorialSequence(fact, 3);
  1649. // now the container has three values: 1 1 2
  1650. SetFactorialSequence(fact, 2);
  1651. // now the container has five values: 1 1 2 6 24
  1652. */
  1653. template<class ValueType>
  1654. void SetFactorialSequence(std::vector<ValueType> & fact, uint more = 20)
  1655. {
  1656. if( more == 0 )
  1657. more = 1;
  1658. uint start = static_cast<uint>(fact.size());
  1659. fact.resize(fact.size() + more);
  1660. if( start == 0 )
  1661. {
  1662. fact[0] = 1;
  1663. ++start;
  1664. }
  1665. for(uint i=start ; i<fact.size() ; ++i)
  1666. {
  1667. fact[i] = fact[i-1];
  1668. fact[i].MulInt(i);
  1669. }
  1670. }
  1671. /*!
  1672. an auxiliary function used to calculate Bernoulli numbers
  1673. this function returns a sum:
  1674. sum(m) = sum_{k=0}^{m-1} {2^k * (m k) * B(k)} k in [0, m-1] (m k) means binomial coefficient = (m! / (k! * (m-k)!))
  1675. you should have sufficient factorials in cgamma.fact
  1676. (cgamma.fact should have at least m items)
  1677. n_ should be equal 2
  1678. */
  1679. template<class ValueType>
  1680. ValueType SetBernoulliNumbersSum(CGamma<ValueType> & cgamma, const ValueType & n_, uint m,
  1681. const volatile StopCalculating * stop = 0)
  1682. {
  1683. ValueType k_, temp, temp2, temp3, sum;
  1684. sum.SetZero();
  1685. for(uint k=0 ; k<m ; ++k) // k<m means k<=m-1
  1686. {
  1687. if( stop && (k & 15)==0 ) // means: k % 16 == 0
  1688. if( stop->WasStopSignal() )
  1689. return ValueType(); // NaN
  1690. if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero
  1691. continue;
  1692. k_ = k;
  1693. temp = n_; // n_ is equal 2
  1694. temp.Pow(k_);
  1695. // temp = 2^k
  1696. temp2 = cgamma.fact[m];
  1697. temp3 = cgamma.fact[k];
  1698. temp3.Mul(cgamma.fact[m-k]);
  1699. temp2.Div(temp3);
  1700. // temp2 = (m k) = m! / ( k! * (m-k)! )
  1701. temp.Mul(temp2);
  1702. temp.Mul(cgamma.bern[k]);
  1703. sum.Add(temp);
  1704. // sum += 2^k * (m k) * B(k)
  1705. if( sum.IsNan() )
  1706. break;
  1707. }
  1708. return sum;
  1709. }
  1710. /*!
  1711. an auxiliary function used to calculate Bernoulli numbers
  1712. start is >= 2
  1713. we use the recurrence formula:
  1714. B(m) = 1 / (2*(1 - 2^m)) * sum(m)
  1715. where sum(m) is calculated by SetBernoulliNumbersSum()
  1716. */
  1717. template<class ValueType>
  1718. bool SetBernoulliNumbersMore(CGamma<ValueType> & cgamma, uint start, const volatile StopCalculating * stop = 0)
  1719. {
  1720. ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_;
  1721. const uint n = 2;
  1722. n_ = n;
  1723. // start is >= 2
  1724. for(uint m=start ; m<cgamma.bern.size() ; ++m)
  1725. {
  1726. if( (m & 1) == 1 )
  1727. {
  1728. cgamma.bern[m].SetZero();
  1729. }
  1730. else
  1731. {
  1732. m_ = m;
  1733. temp = n_; // n_ = 2
  1734. temp.Pow(m_);
  1735. // temp = 2^m
  1736. denominator.SetOne();
  1737. denominator.Sub(temp);
  1738. if( denominator.exponent.AddOne() ) // it means: denominator.MulInt(2)
  1739. denominator.SetNan();
  1740. // denominator = 2 * (1 - 2^m)
  1741. cgamma.bern[m] = SetBernoulliNumbersSum(cgamma, n_, m, stop);
  1742. if( stop && stop->WasStopSignal() )
  1743. {
  1744. cgamma.bern.resize(m); // valid numbers are in [0, m-1]
  1745. return false;
  1746. }
  1747. cgamma.bern[m].Div(denominator);
  1748. }
  1749. }
  1750. return true;
  1751. }
  1752. /*!
  1753. this function is used to calculate Bernoulli numbers,
  1754. returns false if there was a stop signal,
  1755. 'more' means how many values should be added at the end
  1756. e.g.
  1757. typedef Big<1,2> MyBig;
  1758. CGamma<MyBig> cgamma;
  1759. SetBernoulliNumbers(cgamma, 3);
  1760. // now we have three first Bernoulli numbers: 1 -0.5 0.16667
  1761. SetBernoulliNumbers(cgamma, 4);
  1762. // now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238
  1763. */
  1764. template<class ValueType>
  1765. bool SetBernoulliNumbers(CGamma<ValueType> & cgamma, uint more = 20, const volatile StopCalculating * stop = 0)
  1766. {
  1767. if( more == 0 )
  1768. more = 1;
  1769. uint start = static_cast<uint>(cgamma.bern.size());
  1770. cgamma.bern.resize(cgamma.bern.size() + more);
  1771. if( start == 0 )
  1772. {
  1773. cgamma.bern[0].SetOne();
  1774. ++start;
  1775. }
  1776. if( cgamma.bern.size() == 1 )
  1777. return true;
  1778. if( start == 1 )
  1779. {
  1780. cgamma.bern[1].Set05();
  1781. cgamma.bern[1].ChangeSign();
  1782. ++start;
  1783. }
  1784. // we should have sufficient factorials in cgamma.fact
  1785. if( cgamma.fact.size() < cgamma.bern.size() )
  1786. SetFactorialSequence(cgamma.fact, static_cast<uint>(cgamma.bern.size() - cgamma.fact.size()));
  1787. return SetBernoulliNumbersMore(cgamma, start, stop);
  1788. }
  1789. /*!
  1790. an auxiliary function used to calculate the Gamma() function
  1791. we calculate a sum:
  1792. sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ...
  1793. B(m) means a mth Bernoulli number
  1794. the sum starts from m=2, we calculate as long as the value will not change after adding a next part
  1795. */
  1796. template<class ValueType>
  1797. ValueType GammaFactorialHighSum(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
  1798. const volatile StopCalculating * stop)
  1799. {
  1800. ValueType temp, temp2, denominator, sum, oldsum;
  1801. sum.SetZero();
  1802. for(uint m=2 ; m<TTMATH_ARITHMETIC_MAX_LOOP ; m+=2)
  1803. {
  1804. if( stop && (m & 3)==0 ) // (m & 3)==0 means: (m % 4)==0
  1805. if( stop->WasStopSignal() )
  1806. {
  1807. err = err_interrupt;
  1808. return ValueType(); // NaN
  1809. }
  1810. temp = (m-1);
  1811. denominator = n;
  1812. denominator.Pow(temp);
  1813. // denominator = n ^ (m-1)
  1814. temp = m;
  1815. temp2 = temp;
  1816. temp.Mul(temp2);
  1817. temp.Sub(temp2);
  1818. // temp = m^2 - m
  1819. denominator.Mul(temp);
  1820. // denominator = (m^2 - m) * n ^ (m-1)
  1821. if( m >= cgamma.bern.size() )
  1822. {
  1823. if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed
  1824. {
  1825. // there was the stop signal
  1826. err = err_interrupt;
  1827. return ValueType(); // NaN
  1828. }
  1829. }
  1830. temp = cgamma.bern[m];
  1831. temp.Div(denominator);
  1832. oldsum = sum;
  1833. sum.Add(temp);
  1834. if( sum.IsNan() || oldsum==sum )
  1835. break;
  1836. }
  1837. return sum;
  1838. }
  1839. /*!
  1840. an auxiliary function used to calculate the Gamma() function
  1841. we calculate a helper function GammaFactorialHigh() by using Stirling's series:
  1842. n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) )
  1843. where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY)
  1844. and sum(n) is calculated by GammaFactorialHighSum()
  1845. */
  1846. template<class ValueType>
  1847. ValueType GammaFactorialHigh(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err,
  1848. const volatile StopCalculating * stop)
  1849. {
  1850. ValueType temp, temp2, temp3, denominator, sum;
  1851. temp.Set2Pi();
  1852. temp.Mul(n);
  1853. temp2 = Sqrt(temp);
  1854. // temp2 = sqrt(2*pi*n)
  1855. temp = n;
  1856. temp3.SetE();
  1857. temp.Div(temp3);
  1858. temp.Pow(n);
  1859. // temp = (n/e)^n
  1860. sum = GammaFactorialHighSum(n, cgamma, err, stop);
  1861. temp3.Exp(sum);
  1862. // temp3 = exp(sum)
  1863. temp.Mul(temp2);
  1864. temp.Mul(temp3);
  1865. return temp;
  1866. }
  1867. /*!
  1868. an auxiliary function used to calculate the Gamma() function
  1869. Gamma(x) = GammaFactorialHigh(x-1)
  1870. */
  1871. template<class ValueType>
  1872. ValueType GammaPlusHigh(ValueType n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
  1873. {
  1874. ValueType one;
  1875. one.SetOne();
  1876. n.Sub(one);
  1877. return GammaFactorialHigh(n, cgamma, err, stop);
  1878. }
  1879. /*!
  1880. an auxiliary function used to calculate the Gamma() function
  1881. we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
  1882. we use the formula:
  1883. gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1)
  1884. */
  1885. template<class ValueType>
  1886. ValueType GammaPlusLowIntegerInt(uint n, CGamma<ValueType> & cgamma)
  1887. {
  1888. TTMATH_ASSERT( n > 0 )
  1889. if( n - 1 < static_cast<uint>(cgamma.fact.size()) )
  1890. return cgamma.fact[n - 1];
  1891. ValueType res;
  1892. uint start = 2;
  1893. if( cgamma.fact.size() < 2 )
  1894. {
  1895. res.SetOne();
  1896. }
  1897. else
  1898. {
  1899. start = static_cast<uint>(cgamma.fact.size());
  1900. res = cgamma.fact[start-1];
  1901. }
  1902. for(uint i=start ; i<n ; ++i)
  1903. res.MulInt(i);
  1904. return res;
  1905. }
  1906. /*!
  1907. an auxiliary function used to calculate the Gamma() function
  1908. we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
  1909. */
  1910. template<class ValueType>
  1911. ValueType GammaPlusLowInteger(const ValueType & n, CGamma<ValueType> & cgamma)
  1912. {
  1913. sint n_;
  1914. n.ToInt(n_);
  1915. return GammaPlusLowIntegerInt(n_, cgamma);
  1916. }
  1917. /*!
  1918. an auxiliary function used to calculate the Gamma() function
  1919. we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY]
  1920. we use a recurrence formula:
  1921. gamma(z+1) = z * gamma(z)
  1922. then: gamma(z) = gamma(z+1) / z
  1923. e.g.
  1924. gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 )
  1925. */
  1926. template<class ValueType>
  1927. ValueType GammaPlusLow(ValueType n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
  1928. {
  1929. ValueType one, denominator, temp, boundary;
  1930. if( n.IsInteger() )
  1931. return GammaPlusLowInteger(n, cgamma);
  1932. one.SetOne();
  1933. denominator = n;
  1934. boundary = TTMATH_GAMMA_BOUNDARY;
  1935. while( n < boundary )
  1936. {
  1937. n.Add(one);
  1938. denominator.Mul(n);
  1939. }
  1940. n.Add(one);
  1941. // now n is sufficient big
  1942. temp = GammaPlusHigh(n, cgamma, err, stop);
  1943. temp.Div(denominator);
  1944. return temp;
  1945. }
  1946. /*!
  1947. an auxiliary function used to calculate the Gamma() function
  1948. */
  1949. template<class ValueType>
  1950. ValueType GammaPlus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
  1951. {
  1952. if( n > TTMATH_GAMMA_BOUNDARY )
  1953. return GammaPlusHigh(n, cgamma, err, stop);
  1954. return GammaPlusLow(n, cgamma, err, stop);
  1955. }
  1956. /*!
  1957. an auxiliary function used to calculate the Gamma() function
  1958. this function is used when n is negative
  1959. we use the reflection formula:
  1960. gamma(1-z) * gamma(z) = pi / sin(pi*z)
  1961. then: gamma(z) = pi / (sin(pi*z) * gamma(1-z))
  1962. */
  1963. template<class ValueType>
  1964. ValueType GammaMinus(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode & err, const volatile StopCalculating * stop)
  1965. {
  1966. ValueType pi, denominator, temp, temp2;
  1967. if( n.IsInteger() )
  1968. {
  1969. // gamma function is not defined when n is negative and integer
  1970. err = err_improper_argument;
  1971. return temp; // NaN
  1972. }
  1973. pi.SetPi();
  1974. temp = pi;
  1975. temp.Mul(n);
  1976. temp2 = Sin(temp);
  1977. // temp2 = sin(pi * n)
  1978. temp.SetOne();
  1979. temp.Sub(n);
  1980. temp = GammaPlus(temp, cgamma, err, stop);
  1981. // temp = gamma(1 - n)
  1982. temp.Mul(temp2);
  1983. pi.Div(temp);
  1984. return pi;
  1985. }
  1986. } // namespace auxiliaryfunctions
  1987. /*!
  1988. this function calculates the Gamma function
  1989. it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma()
  1990. e.g.
  1991. typedef Big<1,2> MyBig;
  1992. MyBig x=234, y=345.53;
  1993. CGamma<MyBig> cgamma;
  1994. std::cout << Gamma(x, cgamma) << std::endl;
  1995. std::cout << Gamma(y, cgamma) << std::endl;
  1996. in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers),
  1997. and they will be reused in next calls to the function
  1998. each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too
  1999. */
  2000. template<class ValueType>
  2001. ValueType Gamma(const ValueType & n, CGamma<ValueType> & cgamma, ErrorCode * err = 0,
  2002. const volatile StopCalculating * stop = 0)
  2003. {
  2004. using namespace auxiliaryfunctions;
  2005. ValueType result;
  2006. ErrorCode err_tmp;
  2007. if( n.IsNan() )
  2008. {
  2009. if( err )
  2010. *err = err_improper_argument;
  2011. return n;
  2012. }
  2013. if( cgamma.history.Get(n, result, err_tmp) )
  2014. {
  2015. if( err )
  2016. *err = err_tmp;
  2017. return result;
  2018. }
  2019. err_tmp = err_ok;
  2020. if( n.IsSign() )
  2021. {
  2022. result = GammaMinus(n, cgamma, err_tmp, stop);
  2023. }
  2024. else
  2025. if( n.IsZero() )
  2026. {
  2027. err_tmp = err_improper_argument;
  2028. result.SetNan();
  2029. }
  2030. else
  2031. {
  2032. result = GammaPlus(n, cgamma, err_tmp, stop);
  2033. }
  2034. if( result.IsNan() && err_tmp==err_ok )
  2035. err_tmp = err_overflow;
  2036. if( err )
  2037. *err = err_tmp;
  2038. if( stop && !stop->WasStopSignal() )
  2039. cgamma.history.Add(n, result, err_tmp);
  2040. return result;
  2041. }
  2042. /*!
  2043. this function calculates the Gamma function
  2044. note: this function should be used only in a single-thread environment
  2045. */
  2046. template<class ValueType>
  2047. ValueType Gamma(const ValueType & n, ErrorCode * err = 0)
  2048. {
  2049. // warning: this static object is not thread safe
  2050. static CGamma<ValueType> cgamma;
  2051. return Gamma(n, cgamma, err);
  2052. }
  2053. namespace auxiliaryfunctions
  2054. {
  2055. /*!
  2056. an auxiliary function for calculating the factorial function
  2057. we use the formula:
  2058. x! = gamma(x+1)
  2059. */
  2060. template<class ValueType>
  2061. ValueType Factorial2(ValueType x,
  2062. CGamma<ValueType> * cgamma = 0,
  2063. ErrorCode * err = 0,
  2064. const volatile StopCalculating * stop = 0)
  2065. {
  2066. ValueType result, one;
  2067. if( x.IsNan() || x.IsSign() || !x.IsInteger() )
  2068. {
  2069. if( err )
  2070. *err = err_improper_argument;
  2071. x.SetNan();
  2072. return x;
  2073. }
  2074. one.SetOne();
  2075. x.Add(one);
  2076. if( cgamma )
  2077. return Gamma(x, *cgamma, err, stop);
  2078. return Gamma(x, err);
  2079. }
  2080. } // namespace auxiliaryfunctions
  2081. /*!
  2082. the factorial from given 'x'
  2083. e.g.
  2084. Factorial(4) = 4! = 1*2*3*4
  2085. it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial()
  2086. e.g.
  2087. typedef Big<1,2> MyBig;
  2088. MyBig x=234, y=54345;
  2089. CGamma<MyBig> cgamma;
  2090. std::cout << Factorial(x, cgamma) << std::endl;
  2091. std::cout << Factorial(y, cgamma) << std::endl;
  2092. in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers),
  2093. and they will be reused in next calls to the function
  2094. each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too
  2095. */
  2096. template<class ValueType>
  2097. ValueType Factorial(const ValueType & x, CGamma<ValueType> & cgamma, ErrorCode * err = 0,
  2098. const volatile StopCalculating * stop = 0)
  2099. {
  2100. return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop);
  2101. }
  2102. /*!
  2103. the factorial from given 'x'
  2104. e.g.
  2105. Factorial(4) = 4! = 1*2*3*4
  2106. note: this function should be used only in a single-thread environment
  2107. */
  2108. template<class ValueType>
  2109. ValueType Factorial(const ValueType & x, ErrorCode * err = 0)
  2110. {
  2111. return auxiliaryfunctions::Factorial2(x, (CGamma<ValueType>*)0, err, 0);
  2112. }
  2113. /*!
  2114. this method prepares some coefficients: factorials and Bernoulli numbers
  2115. stored in 'fact' and 'bern' objects
  2116. we're defining the method here because we're using Gamma() function which
  2117. is not available in ttmathobjects.h
  2118. read the doc info in ttmathobjects.h file where CGamma<> struct is declared
  2119. */
  2120. template<class ValueType>
  2121. void CGamma<ValueType>::InitAll()
  2122. {
  2123. ValueType x = TTMATH_GAMMA_BOUNDARY + 1;
  2124. // history.Remove(x) removes only one object
  2125. // we must be sure that there are not others objects with the key 'x'
  2126. while( history.Remove(x) )
  2127. {
  2128. }
  2129. // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1)
  2130. // when x is larger then fewer coefficients we need
  2131. Gamma(x, *this);
  2132. }
  2133. } // namespace
  2134. #ifdef _MSC_VER
  2135. //warning C4127: conditional expression is constant
  2136. #pragma warning( default: 4127 )
  2137. //warning C4702: unreachable code
  2138. #pragma warning( default: 4702 )
  2139. //warning C4800: forcing value to bool 'true' or 'false' (performance warning)
  2140. #pragma warning( default: 4800 )
  2141. #endif
  2142. #endif