• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright John Maddock 2006.
2 //  Use, modification and distribution are subject to the
3 //  Boost Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_MATH_SP_UC_FACTORIALS_HPP
7 #define BOOST_MATH_SP_UC_FACTORIALS_HPP
8 
9 #ifdef _MSC_VER
10 #pragma once
11 #endif
12 
13 #ifdef BOOST_MSVC
14 #pragma warning(push) // Temporary until lexical cast fixed.
15 #pragma warning(disable: 4127 4701)
16 #endif
17 #ifndef BOOST_MATH_NO_LEXICAL_CAST
18 #include <boost/lexical_cast.hpp>
19 #endif
20 #ifdef BOOST_MSVC
21 #pragma warning(pop)
22 #endif
23 #include <cmath>
24 #include <boost/math/special_functions/math_fwd.hpp>
25 #include <boost/math/tools/cxx03_warn.hpp>
26 
27 #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
28 #include <array>
29 #else
30 #include <boost/array.hpp>
31 #endif
32 
33 #if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
34 //
35 // This is the only way we can avoid
36 // warning: non-standard suffix on floating constant [-Wpedantic]
37 // when building with -Wall -pedantic.  Neither __extension__
38 // nor #pragma diagnostic ignored work :(
39 //
40 #pragma GCC system_header
41 #endif
42 
43 namespace boost { namespace math
44 {
45 // Forward declarations:
46 template <class T>
47 struct max_factorial;
48 
49 // Definitions:
50 template <>
unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC (float))51 inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION float unchecked_factorial<float>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
52 {
53 #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
54    constexpr std::array<float, 35> factorials = { {
55 #else
56    static const boost::array<float, 35> factorials = {{
57 #endif
58       1.0F,
59       1.0F,
60       2.0F,
61       6.0F,
62       24.0F,
63       120.0F,
64       720.0F,
65       5040.0F,
66       40320.0F,
67       362880.0F,
68       3628800.0F,
69       39916800.0F,
70       479001600.0F,
71       6227020800.0F,
72       87178291200.0F,
73       1307674368000.0F,
74       20922789888000.0F,
75       355687428096000.0F,
76       6402373705728000.0F,
77       121645100408832000.0F,
78       0.243290200817664e19F,
79       0.5109094217170944e20F,
80       0.112400072777760768e22F,
81       0.2585201673888497664e23F,
82       0.62044840173323943936e24F,
83       0.15511210043330985984e26F,
84       0.403291461126605635584e27F,
85       0.10888869450418352160768e29F,
86       0.304888344611713860501504e30F,
87       0.8841761993739701954543616e31F,
88       0.26525285981219105863630848e33F,
89       0.822283865417792281772556288e34F,
90       0.26313083693369353016721801216e36F,
91       0.868331761881188649551819440128e37F,
92       0.29523279903960414084761860964352e39F,
93    }};
94 
95    return factorials[i];
96 }
97 
98 template <>
99 struct max_factorial<float>
100 {
101    BOOST_STATIC_CONSTANT(unsigned, value = 34);
102 };
103 
104 
105 template <>
106 inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION long double unchecked_factorial<long double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
107 {
108 #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
109    constexpr std::array<long double, 171> factorials = { {
110 #else
111    static const boost::array<long double, 171> factorials = {{
112 #endif
113       1L,
114       1L,
115       2L,
116       6L,
117       24L,
118       120L,
119       720L,
120       5040L,
121       40320L,
122       362880.0L,
123       3628800.0L,
124       39916800.0L,
125       479001600.0L,
126       6227020800.0L,
127       87178291200.0L,
128       1307674368000.0L,
129       20922789888000.0L,
130       355687428096000.0L,
131       6402373705728000.0L,
132       121645100408832000.0L,
133       0.243290200817664e19L,
134       0.5109094217170944e20L,
135       0.112400072777760768e22L,
136       0.2585201673888497664e23L,
137       0.62044840173323943936e24L,
138       0.15511210043330985984e26L,
139       0.403291461126605635584e27L,
140       0.10888869450418352160768e29L,
141       0.304888344611713860501504e30L,
142       0.8841761993739701954543616e31L,
143       0.26525285981219105863630848e33L,
144       0.822283865417792281772556288e34L,
145       0.26313083693369353016721801216e36L,
146       0.868331761881188649551819440128e37L,
147       0.29523279903960414084761860964352e39L,
148       0.103331479663861449296666513375232e41L,
149       0.3719933267899012174679994481508352e42L,
150       0.137637530912263450463159795815809024e44L,
151       0.5230226174666011117600072241000742912e45L,
152       0.203978820811974433586402817399028973568e47L,
153       0.815915283247897734345611269596115894272e48L,
154       0.3345252661316380710817006205344075166515e50L,
155       0.1405006117752879898543142606244511569936e52L,
156       0.6041526306337383563735513206851399750726e53L,
157       0.265827157478844876804362581101461589032e55L,
158       0.1196222208654801945619631614956577150644e57L,
159       0.5502622159812088949850305428800254892962e58L,
160       0.2586232415111681806429643551536119799692e60L,
161       0.1241391559253607267086228904737337503852e62L,
162       0.6082818640342675608722521633212953768876e63L,
163       0.3041409320171337804361260816606476884438e65L,
164       0.1551118753287382280224243016469303211063e67L,
165       0.8065817517094387857166063685640376697529e68L,
166       0.427488328406002556429801375338939964969e70L,
167       0.2308436973392413804720927426830275810833e72L,
168       0.1269640335365827592596510084756651695958e74L,
169       0.7109985878048634518540456474637249497365e75L,
170       0.4052691950487721675568060190543232213498e77L,
171       0.2350561331282878571829474910515074683829e79L,
172       0.1386831185456898357379390197203894063459e81L,
173       0.8320987112741390144276341183223364380754e82L,
174       0.507580213877224798800856812176625227226e84L,
175       0.3146997326038793752565312235495076408801e86L,
176       0.1982608315404440064116146708361898137545e88L,
177       0.1268869321858841641034333893351614808029e90L,
178       0.8247650592082470666723170306785496252186e91L,
179       0.5443449390774430640037292402478427526443e93L,
180       0.3647111091818868528824985909660546442717e95L,
181       0.2480035542436830599600990418569171581047e97L,
182       0.1711224524281413113724683388812728390923e99L,
183       0.1197857166996989179607278372168909873646e101L,
184       0.8504785885678623175211676442399260102886e102L,
185       0.6123445837688608686152407038527467274078e104L,
186       0.4470115461512684340891257138125051110077e106L,
187       0.3307885441519386412259530282212537821457e108L,
188       0.2480914081139539809194647711659403366093e110L,
189       0.188549470166605025498793226086114655823e112L,
190       0.1451830920282858696340707840863082849837e114L,
191       0.1132428117820629783145752115873204622873e116L,
192       0.8946182130782975286851441715398316520698e117L,
193       0.7156945704626380229481153372318653216558e119L,
194       0.5797126020747367985879734231578109105412e121L,
195       0.4753643337012841748421382069894049466438e123L,
196       0.3945523969720658651189747118012061057144e125L,
197       0.3314240134565353266999387579130131288001e127L,
198       0.2817104114380550276949479442260611594801e129L,
199       0.2422709538367273238176552320344125971528e131L,
200       0.210775729837952771721360051869938959523e133L,
201       0.1854826422573984391147968456455462843802e135L,
202       0.1650795516090846108121691926245361930984e137L,
203       0.1485715964481761497309522733620825737886e139L,
204       0.1352001527678402962551665687594951421476e141L,
205       0.1243841405464130725547532432587355307758e143L,
206       0.1156772507081641574759205162306240436215e145L,
207       0.1087366156656743080273652852567866010042e147L,
208       0.103299784882390592625997020993947270954e149L,
209       0.9916779348709496892095714015418938011582e150L,
210       0.9619275968248211985332842594956369871234e152L,
211       0.942689044888324774562618574305724247381e154L,
212       0.9332621544394415268169923885626670049072e156L,
213       0.9332621544394415268169923885626670049072e158L,
214       0.9425947759838359420851623124482936749562e160L,
215       0.9614466715035126609268655586972595484554e162L,
216       0.990290071648618040754671525458177334909e164L,
217       0.1029901674514562762384858386476504428305e167L,
218       0.1081396758240290900504101305800329649721e169L,
219       0.1146280563734708354534347384148349428704e171L,
220       0.1226520203196137939351751701038733888713e173L,
221       0.132464181945182897449989183712183259981e175L,
222       0.1443859583202493582204882102462797533793e177L,
223       0.1588245541522742940425370312709077287172e179L,
224       0.1762952551090244663872161047107075788761e181L,
225       0.1974506857221074023536820372759924883413e183L,
226       0.2231192748659813646596607021218715118256e185L,
227       0.2543559733472187557120132004189335234812e187L,
228       0.2925093693493015690688151804817735520034e189L,
229       0.339310868445189820119825609358857320324e191L,
230       0.396993716080872089540195962949863064779e193L,
231       0.4684525849754290656574312362808384164393e195L,
232       0.5574585761207605881323431711741977155627e197L,
233       0.6689502913449127057588118054090372586753e199L,
234       0.8094298525273443739681622845449350829971e201L,
235       0.9875044200833601362411579871448208012564e203L,
236       0.1214630436702532967576624324188129585545e206L,
237       0.1506141741511140879795014161993280686076e208L,
238       0.1882677176888926099743767702491600857595e210L,
239       0.237217324288004688567714730513941708057e212L,
240       0.3012660018457659544809977077527059692324e214L,
241       0.3856204823625804217356770659234636406175e216L,
242       0.4974504222477287440390234150412680963966e218L,
243       0.6466855489220473672507304395536485253155e220L,
244       0.8471580690878820510984568758152795681634e222L,
245       0.1118248651196004307449963076076169029976e225L,
246       0.1487270706090685728908450891181304809868e227L,
247       0.1992942746161518876737324194182948445223e229L,
248       0.269047270731805048359538766214698040105e231L,
249       0.3659042881952548657689727220519893345429e233L,
250       0.5012888748274991661034926292112253883237e235L,
251       0.6917786472619488492228198283114910358867e237L,
252       0.9615723196941089004197195613529725398826e239L,
253       0.1346201247571752460587607385894161555836e242L,
254       0.1898143759076170969428526414110767793728e244L,
255       0.2695364137888162776588507508037290267094e246L,
256       0.3854370717180072770521565736493325081944e248L,
257       0.5550293832739304789551054660550388118e250L,
258       0.80479260574719919448490292577980627711e252L,
259       0.1174997204390910823947958271638517164581e255L,
260       0.1727245890454638911203498659308620231933e257L,
261       0.2556323917872865588581178015776757943262e259L,
262       0.380892263763056972698595524350736933546e261L,
263       0.571338395644585459047893286526105400319e263L,
264       0.8627209774233240431623188626544191544816e265L,
265       0.1311335885683452545606724671234717114812e268L,
266       0.2006343905095682394778288746989117185662e270L,
267       0.308976961384735088795856467036324046592e272L,
268       0.4789142901463393876335775239063022722176e274L,
269       0.7471062926282894447083809372938315446595e276L,
270       0.1172956879426414428192158071551315525115e279L,
271       0.1853271869493734796543609753051078529682e281L,
272       0.2946702272495038326504339507351214862195e283L,
273       0.4714723635992061322406943211761943779512e285L,
274       0.7590705053947218729075178570936729485014e287L,
275       0.1229694218739449434110178928491750176572e290L,
276       0.2004401576545302577599591653441552787813e292L,
277       0.3287218585534296227263330311644146572013e294L,
278       0.5423910666131588774984495014212841843822e296L,
279       0.9003691705778437366474261723593317460744e298L,
280       0.1503616514864999040201201707840084015944e301L,
281       0.2526075744973198387538018869171341146786e303L,
282       0.4269068009004705274939251888899566538069e305L,
283       0.7257415615307998967396728211129263114717e307L,
284    }};
285 
286    return factorials[i];
287 }
288 
289 template <>
290 struct max_factorial<long double>
291 {
292    BOOST_STATIC_CONSTANT(unsigned, value = 170);
293 };
294 
295 #ifdef BOOST_MATH_USE_FLOAT128
296 
297 template <>
298 inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION BOOST_MATH_FLOAT128_TYPE unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(unsigned i)
299 {
300 #ifdef BOOST_MATH_HAVE_CONSTEXPR_TABLES
301    constexpr std::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { {
302 #else
303    static const boost::array<BOOST_MATH_FLOAT128_TYPE, 171> factorials = { {
304 #endif
305       1,
306       1,
307       2,
308       6,
309       24,
310       120,
311       720,
312       5040,
313       40320,
314       362880.0Q,
315       3628800.0Q,
316       39916800.0Q,
317       479001600.0Q,
318       6227020800.0Q,
319       87178291200.0Q,
320       1307674368000.0Q,
321       20922789888000.0Q,
322       355687428096000.0Q,
323       6402373705728000.0Q,
324       121645100408832000.0Q,
325       0.243290200817664e19Q,
326       0.5109094217170944e20Q,
327       0.112400072777760768e22Q,
328       0.2585201673888497664e23Q,
329       0.62044840173323943936e24Q,
330       0.15511210043330985984e26Q,
331       0.403291461126605635584e27Q,
332       0.10888869450418352160768e29Q,
333       0.304888344611713860501504e30Q,
334       0.8841761993739701954543616e31Q,
335       0.26525285981219105863630848e33Q,
336       0.822283865417792281772556288e34Q,
337       0.26313083693369353016721801216e36Q,
338       0.868331761881188649551819440128e37Q,
339       0.29523279903960414084761860964352e39Q,
340       0.103331479663861449296666513375232e41Q,
341       0.3719933267899012174679994481508352e42Q,
342       0.137637530912263450463159795815809024e44Q,
343       0.5230226174666011117600072241000742912e45Q,
344       0.203978820811974433586402817399028973568e47Q,
345       0.815915283247897734345611269596115894272e48Q,
346       0.3345252661316380710817006205344075166515e50Q,
347       0.1405006117752879898543142606244511569936e52Q,
348       0.6041526306337383563735513206851399750726e53Q,
349       0.265827157478844876804362581101461589032e55Q,
350       0.1196222208654801945619631614956577150644e57Q,
351       0.5502622159812088949850305428800254892962e58Q,
352       0.2586232415111681806429643551536119799692e60Q,
353       0.1241391559253607267086228904737337503852e62Q,
354       0.6082818640342675608722521633212953768876e63Q,
355       0.3041409320171337804361260816606476884438e65Q,
356       0.1551118753287382280224243016469303211063e67Q,
357       0.8065817517094387857166063685640376697529e68Q,
358       0.427488328406002556429801375338939964969e70Q,
359       0.2308436973392413804720927426830275810833e72Q,
360       0.1269640335365827592596510084756651695958e74Q,
361       0.7109985878048634518540456474637249497365e75Q,
362       0.4052691950487721675568060190543232213498e77Q,
363       0.2350561331282878571829474910515074683829e79Q,
364       0.1386831185456898357379390197203894063459e81Q,
365       0.8320987112741390144276341183223364380754e82Q,
366       0.507580213877224798800856812176625227226e84Q,
367       0.3146997326038793752565312235495076408801e86Q,
368       0.1982608315404440064116146708361898137545e88Q,
369       0.1268869321858841641034333893351614808029e90Q,
370       0.8247650592082470666723170306785496252186e91Q,
371       0.5443449390774430640037292402478427526443e93Q,
372       0.3647111091818868528824985909660546442717e95Q,
373       0.2480035542436830599600990418569171581047e97Q,
374       0.1711224524281413113724683388812728390923e99Q,
375       0.1197857166996989179607278372168909873646e101Q,
376       0.8504785885678623175211676442399260102886e102Q,
377       0.6123445837688608686152407038527467274078e104Q,
378       0.4470115461512684340891257138125051110077e106Q,
379       0.3307885441519386412259530282212537821457e108Q,
380       0.2480914081139539809194647711659403366093e110Q,
381       0.188549470166605025498793226086114655823e112Q,
382       0.1451830920282858696340707840863082849837e114Q,
383       0.1132428117820629783145752115873204622873e116Q,
384       0.8946182130782975286851441715398316520698e117Q,
385       0.7156945704626380229481153372318653216558e119Q,
386       0.5797126020747367985879734231578109105412e121Q,
387       0.4753643337012841748421382069894049466438e123Q,
388       0.3945523969720658651189747118012061057144e125Q,
389       0.3314240134565353266999387579130131288001e127Q,
390       0.2817104114380550276949479442260611594801e129Q,
391       0.2422709538367273238176552320344125971528e131Q,
392       0.210775729837952771721360051869938959523e133Q,
393       0.1854826422573984391147968456455462843802e135Q,
394       0.1650795516090846108121691926245361930984e137Q,
395       0.1485715964481761497309522733620825737886e139Q,
396       0.1352001527678402962551665687594951421476e141Q,
397       0.1243841405464130725547532432587355307758e143Q,
398       0.1156772507081641574759205162306240436215e145Q,
399       0.1087366156656743080273652852567866010042e147Q,
400       0.103299784882390592625997020993947270954e149Q,
401       0.9916779348709496892095714015418938011582e150Q,
402       0.9619275968248211985332842594956369871234e152Q,
403       0.942689044888324774562618574305724247381e154Q,
404       0.9332621544394415268169923885626670049072e156Q,
405       0.9332621544394415268169923885626670049072e158Q,
406       0.9425947759838359420851623124482936749562e160Q,
407       0.9614466715035126609268655586972595484554e162Q,
408       0.990290071648618040754671525458177334909e164Q,
409       0.1029901674514562762384858386476504428305e167Q,
410       0.1081396758240290900504101305800329649721e169Q,
411       0.1146280563734708354534347384148349428704e171Q,
412       0.1226520203196137939351751701038733888713e173Q,
413       0.132464181945182897449989183712183259981e175Q,
414       0.1443859583202493582204882102462797533793e177Q,
415       0.1588245541522742940425370312709077287172e179Q,
416       0.1762952551090244663872161047107075788761e181Q,
417       0.1974506857221074023536820372759924883413e183Q,
418       0.2231192748659813646596607021218715118256e185Q,
419       0.2543559733472187557120132004189335234812e187Q,
420       0.2925093693493015690688151804817735520034e189Q,
421       0.339310868445189820119825609358857320324e191Q,
422       0.396993716080872089540195962949863064779e193Q,
423       0.4684525849754290656574312362808384164393e195Q,
424       0.5574585761207605881323431711741977155627e197Q,
425       0.6689502913449127057588118054090372586753e199Q,
426       0.8094298525273443739681622845449350829971e201Q,
427       0.9875044200833601362411579871448208012564e203Q,
428       0.1214630436702532967576624324188129585545e206Q,
429       0.1506141741511140879795014161993280686076e208Q,
430       0.1882677176888926099743767702491600857595e210Q,
431       0.237217324288004688567714730513941708057e212Q,
432       0.3012660018457659544809977077527059692324e214Q,
433       0.3856204823625804217356770659234636406175e216Q,
434       0.4974504222477287440390234150412680963966e218Q,
435       0.6466855489220473672507304395536485253155e220Q,
436       0.8471580690878820510984568758152795681634e222Q,
437       0.1118248651196004307449963076076169029976e225Q,
438       0.1487270706090685728908450891181304809868e227Q,
439       0.1992942746161518876737324194182948445223e229Q,
440       0.269047270731805048359538766214698040105e231Q,
441       0.3659042881952548657689727220519893345429e233Q,
442       0.5012888748274991661034926292112253883237e235Q,
443       0.6917786472619488492228198283114910358867e237Q,
444       0.9615723196941089004197195613529725398826e239Q,
445       0.1346201247571752460587607385894161555836e242Q,
446       0.1898143759076170969428526414110767793728e244Q,
447       0.2695364137888162776588507508037290267094e246Q,
448       0.3854370717180072770521565736493325081944e248Q,
449       0.5550293832739304789551054660550388118e250Q,
450       0.80479260574719919448490292577980627711e252Q,
451       0.1174997204390910823947958271638517164581e255Q,
452       0.1727245890454638911203498659308620231933e257Q,
453       0.2556323917872865588581178015776757943262e259Q,
454       0.380892263763056972698595524350736933546e261Q,
455       0.571338395644585459047893286526105400319e263Q,
456       0.8627209774233240431623188626544191544816e265Q,
457       0.1311335885683452545606724671234717114812e268Q,
458       0.2006343905095682394778288746989117185662e270Q,
459       0.308976961384735088795856467036324046592e272Q,
460       0.4789142901463393876335775239063022722176e274Q,
461       0.7471062926282894447083809372938315446595e276Q,
462       0.1172956879426414428192158071551315525115e279Q,
463       0.1853271869493734796543609753051078529682e281Q,
464       0.2946702272495038326504339507351214862195e283Q,
465       0.4714723635992061322406943211761943779512e285Q,
466       0.7590705053947218729075178570936729485014e287Q,
467       0.1229694218739449434110178928491750176572e290Q,
468       0.2004401576545302577599591653441552787813e292Q,
469       0.3287218585534296227263330311644146572013e294Q,
470       0.5423910666131588774984495014212841843822e296Q,
471       0.9003691705778437366474261723593317460744e298Q,
472       0.1503616514864999040201201707840084015944e301Q,
473       0.2526075744973198387538018869171341146786e303Q,
474       0.4269068009004705274939251888899566538069e305Q,
475       0.7257415615307998967396728211129263114717e307Q,
476    } };
477 
478    return factorials[i];
479 }
480 
481 template <>
482 struct max_factorial<BOOST_MATH_FLOAT128_TYPE>
483 {
484    BOOST_STATIC_CONSTANT(unsigned, value = 170);
485 };
486 
487 #endif
488 
489 template <>
490 inline BOOST_MATH_CONSTEXPR_TABLE_FUNCTION double unchecked_factorial<double>(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
491 {
492    return static_cast<double>(boost::math::unchecked_factorial<long double>(i));
493 }
494 
495 template <>
496 struct max_factorial<double>
497 {
498    BOOST_STATIC_CONSTANT(unsigned,
499       value = ::boost::math::max_factorial<long double>::value);
500 };
501 
502 #ifndef BOOST_MATH_NO_LEXICAL_CAST
503 
504 template <class T>
505 struct unchecked_factorial_initializer
506 {
507    struct init
508    {
509       init()
510       {
511          boost::math::unchecked_factorial<T>(3);
512       }
513       void force_instantiate()const {}
514    };
515    static const init initializer;
516    static void force_instantiate()
517    {
518       initializer.force_instantiate();
519    }
520 };
521 
522 template <class T>
523 const typename unchecked_factorial_initializer<T>::init unchecked_factorial_initializer<T>::initializer;
524 
525 
526 template <class T, int N>
527 inline T unchecked_factorial_imp(unsigned i, const boost::integral_constant<int, N>&)
528 {
529    BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
530    // factorial<unsigned int>(n) is not implemented
531    // because it would overflow integral type T for too small n
532    // to be useful. Use instead a floating-point type,
533    // and convert to an unsigned type if essential, for example:
534    // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
535    // See factorial documentation for more detail.
536 
537    unchecked_factorial_initializer<T>::force_instantiate();
538 
539    static const boost::array<T, 101> factorials = {{
540       T(boost::math::tools::convert_from_string<T>("1")),
541       T(boost::math::tools::convert_from_string<T>("1")),
542       T(boost::math::tools::convert_from_string<T>("2")),
543       T(boost::math::tools::convert_from_string<T>("6")),
544       T(boost::math::tools::convert_from_string<T>("24")),
545       T(boost::math::tools::convert_from_string<T>("120")),
546       T(boost::math::tools::convert_from_string<T>("720")),
547       T(boost::math::tools::convert_from_string<T>("5040")),
548       T(boost::math::tools::convert_from_string<T>("40320")),
549       T(boost::math::tools::convert_from_string<T>("362880")),
550       T(boost::math::tools::convert_from_string<T>("3628800")),
551       T(boost::math::tools::convert_from_string<T>("39916800")),
552       T(boost::math::tools::convert_from_string<T>("479001600")),
553       T(boost::math::tools::convert_from_string<T>("6227020800")),
554       T(boost::math::tools::convert_from_string<T>("87178291200")),
555       T(boost::math::tools::convert_from_string<T>("1307674368000")),
556       T(boost::math::tools::convert_from_string<T>("20922789888000")),
557       T(boost::math::tools::convert_from_string<T>("355687428096000")),
558       T(boost::math::tools::convert_from_string<T>("6402373705728000")),
559       T(boost::math::tools::convert_from_string<T>("121645100408832000")),
560       T(boost::math::tools::convert_from_string<T>("2432902008176640000")),
561       T(boost::math::tools::convert_from_string<T>("51090942171709440000")),
562       T(boost::math::tools::convert_from_string<T>("1124000727777607680000")),
563       T(boost::math::tools::convert_from_string<T>("25852016738884976640000")),
564       T(boost::math::tools::convert_from_string<T>("620448401733239439360000")),
565       T(boost::math::tools::convert_from_string<T>("15511210043330985984000000")),
566       T(boost::math::tools::convert_from_string<T>("403291461126605635584000000")),
567       T(boost::math::tools::convert_from_string<T>("10888869450418352160768000000")),
568       T(boost::math::tools::convert_from_string<T>("304888344611713860501504000000")),
569       T(boost::math::tools::convert_from_string<T>("8841761993739701954543616000000")),
570       T(boost::math::tools::convert_from_string<T>("265252859812191058636308480000000")),
571       T(boost::math::tools::convert_from_string<T>("8222838654177922817725562880000000")),
572       T(boost::math::tools::convert_from_string<T>("263130836933693530167218012160000000")),
573       T(boost::math::tools::convert_from_string<T>("8683317618811886495518194401280000000")),
574       T(boost::math::tools::convert_from_string<T>("295232799039604140847618609643520000000")),
575       T(boost::math::tools::convert_from_string<T>("10333147966386144929666651337523200000000")),
576       T(boost::math::tools::convert_from_string<T>("371993326789901217467999448150835200000000")),
577       T(boost::math::tools::convert_from_string<T>("13763753091226345046315979581580902400000000")),
578       T(boost::math::tools::convert_from_string<T>("523022617466601111760007224100074291200000000")),
579       T(boost::math::tools::convert_from_string<T>("20397882081197443358640281739902897356800000000")),
580       T(boost::math::tools::convert_from_string<T>("815915283247897734345611269596115894272000000000")),
581       T(boost::math::tools::convert_from_string<T>("33452526613163807108170062053440751665152000000000")),
582       T(boost::math::tools::convert_from_string<T>("1405006117752879898543142606244511569936384000000000")),
583       T(boost::math::tools::convert_from_string<T>("60415263063373835637355132068513997507264512000000000")),
584       T(boost::math::tools::convert_from_string<T>("2658271574788448768043625811014615890319638528000000000")),
585       T(boost::math::tools::convert_from_string<T>("119622220865480194561963161495657715064383733760000000000")),
586       T(boost::math::tools::convert_from_string<T>("5502622159812088949850305428800254892961651752960000000000")),
587       T(boost::math::tools::convert_from_string<T>("258623241511168180642964355153611979969197632389120000000000")),
588       T(boost::math::tools::convert_from_string<T>("12413915592536072670862289047373375038521486354677760000000000")),
589       T(boost::math::tools::convert_from_string<T>("608281864034267560872252163321295376887552831379210240000000000")),
590       T(boost::math::tools::convert_from_string<T>("30414093201713378043612608166064768844377641568960512000000000000")),
591       T(boost::math::tools::convert_from_string<T>("1551118753287382280224243016469303211063259720016986112000000000000")),
592       T(boost::math::tools::convert_from_string<T>("80658175170943878571660636856403766975289505440883277824000000000000")),
593       T(boost::math::tools::convert_from_string<T>("4274883284060025564298013753389399649690343788366813724672000000000000")),
594       T(boost::math::tools::convert_from_string<T>("230843697339241380472092742683027581083278564571807941132288000000000000")),
595       T(boost::math::tools::convert_from_string<T>("12696403353658275925965100847566516959580321051449436762275840000000000000")),
596       T(boost::math::tools::convert_from_string<T>("710998587804863451854045647463724949736497978881168458687447040000000000000")),
597       T(boost::math::tools::convert_from_string<T>("40526919504877216755680601905432322134980384796226602145184481280000000000000")),
598       T(boost::math::tools::convert_from_string<T>("2350561331282878571829474910515074683828862318181142924420699914240000000000000")),
599       T(boost::math::tools::convert_from_string<T>("138683118545689835737939019720389406345902876772687432540821294940160000000000000")),
600       T(boost::math::tools::convert_from_string<T>("8320987112741390144276341183223364380754172606361245952449277696409600000000000000")),
601       T(boost::math::tools::convert_from_string<T>("507580213877224798800856812176625227226004528988036003099405939480985600000000000000")),
602       T(boost::math::tools::convert_from_string<T>("31469973260387937525653122354950764088012280797258232192163168247821107200000000000000")),
603       T(boost::math::tools::convert_from_string<T>("1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000")),
604       T(boost::math::tools::convert_from_string<T>("126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000")),
605       T(boost::math::tools::convert_from_string<T>("8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000")),
606       T(boost::math::tools::convert_from_string<T>("544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000")),
607       T(boost::math::tools::convert_from_string<T>("36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000")),
608       T(boost::math::tools::convert_from_string<T>("2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000")),
609       T(boost::math::tools::convert_from_string<T>("171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000")),
610       T(boost::math::tools::convert_from_string<T>("11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000")),
611       T(boost::math::tools::convert_from_string<T>("850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000")),
612       T(boost::math::tools::convert_from_string<T>("61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000")),
613       T(boost::math::tools::convert_from_string<T>("4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000")),
614       T(boost::math::tools::convert_from_string<T>("330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000")),
615       T(boost::math::tools::convert_from_string<T>("24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000")),
616       T(boost::math::tools::convert_from_string<T>("1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000")),
617       T(boost::math::tools::convert_from_string<T>("145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000")),
618       T(boost::math::tools::convert_from_string<T>("11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000")),
619       T(boost::math::tools::convert_from_string<T>("894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000")),
620       T(boost::math::tools::convert_from_string<T>("71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000")),
621       T(boost::math::tools::convert_from_string<T>("5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000")),
622       T(boost::math::tools::convert_from_string<T>("475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000")),
623       T(boost::math::tools::convert_from_string<T>("39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000")),
624       T(boost::math::tools::convert_from_string<T>("3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000")),
625       T(boost::math::tools::convert_from_string<T>("281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000")),
626       T(boost::math::tools::convert_from_string<T>("24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000")),
627       T(boost::math::tools::convert_from_string<T>("2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000")),
628       T(boost::math::tools::convert_from_string<T>("185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000")),
629       T(boost::math::tools::convert_from_string<T>("16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000")),
630       T(boost::math::tools::convert_from_string<T>("1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000")),
631       T(boost::math::tools::convert_from_string<T>("135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000")),
632       T(boost::math::tools::convert_from_string<T>("12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000")),
633       T(boost::math::tools::convert_from_string<T>("1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000")),
634       T(boost::math::tools::convert_from_string<T>("108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000")),
635       T(boost::math::tools::convert_from_string<T>("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000")),
636       T(boost::math::tools::convert_from_string<T>("991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000")),
637       T(boost::math::tools::convert_from_string<T>("96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000")),
638       T(boost::math::tools::convert_from_string<T>("9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000")),
639       T(boost::math::tools::convert_from_string<T>("933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000")),
640       T(boost::math::tools::convert_from_string<T>("93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000")),
641    }};
642 
643    return factorials[i];
644 }
645 
646 template <class T>
647 inline T unchecked_factorial_imp(unsigned i, const boost::integral_constant<int, 0>&)
648 {
649    BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
650    // factorial<unsigned int>(n) is not implemented
651    // because it would overflow integral type T for too small n
652    // to be useful. Use instead a floating-point type,
653    // and convert to an unsigned type if essential, for example:
654    // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
655    // See factorial documentation for more detail.
656 #ifdef BOOST_NO_CXX11_THREAD_LOCAL
657    unchecked_factorial_initializer<T>::force_instantiate();
658 #endif
659    static const char* const factorial_strings[] = {
660          "1",
661          "1",
662          "2",
663          "6",
664          "24",
665          "120",
666          "720",
667          "5040",
668          "40320",
669          "362880",
670          "3628800",
671          "39916800",
672          "479001600",
673          "6227020800",
674          "87178291200",
675          "1307674368000",
676          "20922789888000",
677          "355687428096000",
678          "6402373705728000",
679          "121645100408832000",
680          "2432902008176640000",
681          "51090942171709440000",
682          "1124000727777607680000",
683          "25852016738884976640000",
684          "620448401733239439360000",
685          "15511210043330985984000000",
686          "403291461126605635584000000",
687          "10888869450418352160768000000",
688          "304888344611713860501504000000",
689          "8841761993739701954543616000000",
690          "265252859812191058636308480000000",
691          "8222838654177922817725562880000000",
692          "263130836933693530167218012160000000",
693          "8683317618811886495518194401280000000",
694          "295232799039604140847618609643520000000",
695          "10333147966386144929666651337523200000000",
696          "371993326789901217467999448150835200000000",
697          "13763753091226345046315979581580902400000000",
698          "523022617466601111760007224100074291200000000",
699          "20397882081197443358640281739902897356800000000",
700          "815915283247897734345611269596115894272000000000",
701          "33452526613163807108170062053440751665152000000000",
702          "1405006117752879898543142606244511569936384000000000",
703          "60415263063373835637355132068513997507264512000000000",
704          "2658271574788448768043625811014615890319638528000000000",
705          "119622220865480194561963161495657715064383733760000000000",
706          "5502622159812088949850305428800254892961651752960000000000",
707          "258623241511168180642964355153611979969197632389120000000000",
708          "12413915592536072670862289047373375038521486354677760000000000",
709          "608281864034267560872252163321295376887552831379210240000000000",
710          "30414093201713378043612608166064768844377641568960512000000000000",
711          "1551118753287382280224243016469303211063259720016986112000000000000",
712          "80658175170943878571660636856403766975289505440883277824000000000000",
713          "4274883284060025564298013753389399649690343788366813724672000000000000",
714          "230843697339241380472092742683027581083278564571807941132288000000000000",
715          "12696403353658275925965100847566516959580321051449436762275840000000000000",
716          "710998587804863451854045647463724949736497978881168458687447040000000000000",
717          "40526919504877216755680601905432322134980384796226602145184481280000000000000",
718          "2350561331282878571829474910515074683828862318181142924420699914240000000000000",
719          "138683118545689835737939019720389406345902876772687432540821294940160000000000000",
720          "8320987112741390144276341183223364380754172606361245952449277696409600000000000000",
721          "507580213877224798800856812176625227226004528988036003099405939480985600000000000000",
722          "31469973260387937525653122354950764088012280797258232192163168247821107200000000000000",
723          "1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000",
724          "126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000",
725          "8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000",
726          "544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000",
727          "36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000",
728          "2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000",
729          "171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000",
730          "11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000",
731          "850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000",
732          "61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000",
733          "4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000",
734          "330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000",
735          "24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000",
736          "1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000",
737          "145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000",
738          "11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000",
739          "894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000",
740          "71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000",
741          "5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000",
742          "475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000",
743          "39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000",
744          "3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000",
745          "281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000",
746          "24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000",
747          "2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000",
748          "185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000",
749          "16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000",
750          "1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000",
751          "135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000",
752          "12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000",
753          "1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000",
754          "108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000",
755          "10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000",
756          "991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000",
757          "96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000",
758          "9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000",
759          "933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000",
760          "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000",
761       };
762 
763       static BOOST_MATH_THREAD_LOCAL T factorials[sizeof(factorial_strings) / sizeof(factorial_strings[0])];
764       static BOOST_MATH_THREAD_LOCAL int digits = 0;
765 
766       int current_digits = boost::math::tools::digits<T>();
767 
768       if(digits != current_digits)
769       {
770          digits = current_digits;
771          for(unsigned k = 0; k < sizeof(factorials) / sizeof(factorials[0]); ++k)
772             factorials[k] = static_cast<T>(boost::math::tools::convert_from_string<T>(factorial_strings[k]));
773       }
774 
775    return factorials[i];
776 }
777 
778 template <class T>
779 inline T unchecked_factorial_imp(unsigned i, const boost::integral_constant<int, std::numeric_limits<float>::digits>&)
780 {
781    return unchecked_factorial<float>(i);
782 }
783 
784 template <class T>
785 inline T unchecked_factorial_imp(unsigned i, const boost::integral_constant<int, std::numeric_limits<double>::digits>&)
786 {
787    return unchecked_factorial<double>(i);
788 }
789 
790 #if DBL_MANT_DIG != LDBL_MANT_DIG
791 template <class T>
792 inline T unchecked_factorial_imp(unsigned i, const boost::integral_constant<int, LDBL_MANT_DIG>&)
793 {
794    return unchecked_factorial<long double>(i);
795 }
796 #endif
797 #ifdef BOOST_MATH_USE_FLOAT128
798 template <class T>
799 inline T unchecked_factorial_imp(unsigned i, const boost::integral_constant<int, 113>&)
800 {
801    return unchecked_factorial<BOOST_MATH_FLOAT128_TYPE>(i);
802 }
803 #endif
804 
805 template <class T>
806 inline T unchecked_factorial(unsigned i)
807 {
808    typedef typename boost::math::policies::precision<T, boost::math::policies::policy<> >::type tag_type;
809    return unchecked_factorial_imp<T>(i, tag_type());
810 }
811 
812 #ifdef BOOST_MATH_USE_FLOAT128
813 #define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL : std::numeric_limits<T>::digits == 113 ? max_factorial<BOOST_MATH_FLOAT128_TYPE>::value
814 #else
815 #define BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL
816 #endif
817 
818 template <class T>
819 struct max_factorial
820 {
821    BOOST_STATIC_CONSTANT(unsigned, value =
822       std::numeric_limits<T>::digits == std::numeric_limits<float>::digits ? max_factorial<float>::value
823       : std::numeric_limits<T>::digits == std::numeric_limits<double>::digits ? max_factorial<double>::value
824       : std::numeric_limits<T>::digits == std::numeric_limits<long double>::digits ? max_factorial<long double>::value
825       BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL
826       : 100);
827 };
828 
829 #undef BOOST_MATH_DETAIL_FLOAT128_MAX_FACTORIAL
830 
831 #else // BOOST_MATH_NO_LEXICAL_CAST
832 
833 template <class T>
834 inline T unchecked_factorial(unsigned i BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
835 {
836    return 1;
837 }
838 
839 template <class T>
840 struct max_factorial
841 {
842    BOOST_STATIC_CONSTANT(unsigned, value = 0);
843 };
844 
845 #endif
846 
847 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
848 template <class T>
849 const unsigned max_factorial<T>::value;
850 #endif
851 
852 } // namespace math
853 } // namespace boost
854 
855 #endif // BOOST_MATH_SP_UC_FACTORIALS_HPP
856 
857