ngsolve 6.2.2506.post74.dev0__cp314-cp314-macosx_10_15_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ngsolve might be problematic. Click here for more details.

Files changed (315) hide show
  1. netgen/include/analytic_integrals.hpp +10 -0
  2. netgen/include/arnoldi.hpp +55 -0
  3. netgen/include/bandmatrix.hpp +334 -0
  4. netgen/include/basematrix.hpp +957 -0
  5. netgen/include/basevector.hpp +1268 -0
  6. netgen/include/bdbequations.hpp +2805 -0
  7. netgen/include/bdbintegrator.hpp +1660 -0
  8. netgen/include/bem_diffops.hpp +475 -0
  9. netgen/include/bessel.hpp +1064 -0
  10. netgen/include/bilinearform.hpp +963 -0
  11. netgen/include/bla.hpp +29 -0
  12. netgen/include/blockalloc.hpp +95 -0
  13. netgen/include/blockjacobi.hpp +328 -0
  14. netgen/include/bspline.hpp +116 -0
  15. netgen/include/calcinverse.hpp +141 -0
  16. netgen/include/cg.hpp +368 -0
  17. netgen/include/chebyshev.hpp +44 -0
  18. netgen/include/cholesky.hpp +720 -0
  19. netgen/include/clapack.h +7254 -0
  20. netgen/include/code_generation.hpp +296 -0
  21. netgen/include/coefficient.hpp +2033 -0
  22. netgen/include/coefficient_impl.hpp +19 -0
  23. netgen/include/coefficient_stdmath.hpp +167 -0
  24. netgen/include/commutingAMG.hpp +106 -0
  25. netgen/include/comp.hpp +79 -0
  26. netgen/include/compatibility.hpp +41 -0
  27. netgen/include/complex_wrapper.hpp +73 -0
  28. netgen/include/compressedfespace.hpp +110 -0
  29. netgen/include/contact.hpp +235 -0
  30. netgen/include/diagonalmatrix.hpp +154 -0
  31. netgen/include/differentialoperator.hpp +276 -0
  32. netgen/include/diffop.hpp +1286 -0
  33. netgen/include/diffop_impl.hpp +328 -0
  34. netgen/include/diffopwithfactor.hpp +123 -0
  35. netgen/include/discontinuous.hpp +84 -0
  36. netgen/include/dump.hpp +949 -0
  37. netgen/include/ectypes.hpp +121 -0
  38. netgen/include/eigen.hpp +60 -0
  39. netgen/include/eigensystem.hpp +18 -0
  40. netgen/include/elasticity_equations.hpp +595 -0
  41. netgen/include/elementbyelement.hpp +195 -0
  42. netgen/include/elementtopology.hpp +1760 -0
  43. netgen/include/elementtransformation.hpp +339 -0
  44. netgen/include/evalfunc.hpp +405 -0
  45. netgen/include/expr.hpp +1686 -0
  46. netgen/include/facetfe.hpp +175 -0
  47. netgen/include/facetfespace.hpp +180 -0
  48. netgen/include/facethofe.hpp +111 -0
  49. netgen/include/facetsurffespace.hpp +112 -0
  50. netgen/include/fe_interfaces.hpp +32 -0
  51. netgen/include/fem.hpp +87 -0
  52. netgen/include/fesconvert.hpp +14 -0
  53. netgen/include/fespace.hpp +1449 -0
  54. netgen/include/finiteelement.hpp +286 -0
  55. netgen/include/globalinterfacespace.hpp +77 -0
  56. netgen/include/globalspace.hpp +115 -0
  57. netgen/include/gridfunction.hpp +525 -0
  58. netgen/include/h1amg.hpp +124 -0
  59. netgen/include/h1hofe.hpp +188 -0
  60. netgen/include/h1hofe_impl.hpp +1262 -0
  61. netgen/include/h1hofefo.hpp +148 -0
  62. netgen/include/h1hofefo_impl.hpp +185 -0
  63. netgen/include/h1hofespace.hpp +167 -0
  64. netgen/include/h1lofe.hpp +1240 -0
  65. netgen/include/h1lumping.hpp +41 -0
  66. netgen/include/hcurl_equations.hpp +1381 -0
  67. netgen/include/hcurlcurlfe.hpp +2241 -0
  68. netgen/include/hcurlcurlfespace.hpp +78 -0
  69. netgen/include/hcurlfe.hpp +259 -0
  70. netgen/include/hcurlfe_utils.hpp +107 -0
  71. netgen/include/hcurlhdiv_dshape.hpp +857 -0
  72. netgen/include/hcurlhdivfes.hpp +308 -0
  73. netgen/include/hcurlhofe.hpp +175 -0
  74. netgen/include/hcurlhofe_impl.hpp +1871 -0
  75. netgen/include/hcurlhofespace.hpp +193 -0
  76. netgen/include/hcurllofe.hpp +1146 -0
  77. netgen/include/hdiv_equations.hpp +880 -0
  78. netgen/include/hdivdivfe.hpp +2923 -0
  79. netgen/include/hdivdivsurfacespace.hpp +76 -0
  80. netgen/include/hdivfe.hpp +206 -0
  81. netgen/include/hdivfe_utils.hpp +717 -0
  82. netgen/include/hdivfes.hpp +75 -0
  83. netgen/include/hdivhofe.hpp +447 -0
  84. netgen/include/hdivhofe_impl.hpp +1107 -0
  85. netgen/include/hdivhofefo.hpp +229 -0
  86. netgen/include/hdivhofespace.hpp +177 -0
  87. netgen/include/hdivhosurfacefespace.hpp +106 -0
  88. netgen/include/hdivlofe.hpp +773 -0
  89. netgen/include/hidden.hpp +74 -0
  90. netgen/include/householder.hpp +181 -0
  91. netgen/include/hypre_ams_precond.hpp +123 -0
  92. netgen/include/hypre_precond.hpp +73 -0
  93. netgen/include/integrator.hpp +2012 -0
  94. netgen/include/integratorcf.hpp +253 -0
  95. netgen/include/interpolate.hpp +49 -0
  96. netgen/include/intrule.hpp +2542 -0
  97. netgen/include/intrules_SauterSchwab.hpp +25 -0
  98. netgen/include/irspace.hpp +49 -0
  99. netgen/include/jacobi.hpp +153 -0
  100. netgen/include/kernels.hpp +762 -0
  101. netgen/include/l2hofe.hpp +194 -0
  102. netgen/include/l2hofe_impl.hpp +564 -0
  103. netgen/include/l2hofefo.hpp +542 -0
  104. netgen/include/l2hofespace.hpp +344 -0
  105. netgen/include/la.hpp +38 -0
  106. netgen/include/linearform.hpp +266 -0
  107. netgen/include/matrix.hpp +2140 -0
  108. netgen/include/memusage.hpp +41 -0
  109. netgen/include/meshaccess.hpp +1359 -0
  110. netgen/include/mgpre.hpp +204 -0
  111. netgen/include/mp_coefficient.hpp +145 -0
  112. netgen/include/mptools.hpp +2281 -0
  113. netgen/include/multigrid.hpp +42 -0
  114. netgen/include/multivector.hpp +447 -0
  115. netgen/include/mumpsinverse.hpp +187 -0
  116. netgen/include/mycomplex.hpp +361 -0
  117. netgen/include/ng_lapack.hpp +1661 -0
  118. netgen/include/ngblas.hpp +1232 -0
  119. netgen/include/ngs_defines.hpp +30 -0
  120. netgen/include/ngs_stdcpp_include.hpp +106 -0
  121. netgen/include/ngs_utils.hpp +121 -0
  122. netgen/include/ngsobject.hpp +1019 -0
  123. netgen/include/ngsstream.hpp +113 -0
  124. netgen/include/ngstd.hpp +72 -0
  125. netgen/include/nodalhofe.hpp +96 -0
  126. netgen/include/nodalhofe_impl.hpp +141 -0
  127. netgen/include/normalfacetfe.hpp +223 -0
  128. netgen/include/normalfacetfespace.hpp +98 -0
  129. netgen/include/normalfacetsurfacefespace.hpp +84 -0
  130. netgen/include/order.hpp +251 -0
  131. netgen/include/parallel_matrices.hpp +222 -0
  132. netgen/include/paralleldofs.hpp +340 -0
  133. netgen/include/parallelngs.hpp +23 -0
  134. netgen/include/parallelvector.hpp +269 -0
  135. netgen/include/pardisoinverse.hpp +200 -0
  136. netgen/include/periodic.hpp +129 -0
  137. netgen/include/plateaufespace.hpp +25 -0
  138. netgen/include/pml.hpp +275 -0
  139. netgen/include/pmltrafo.hpp +631 -0
  140. netgen/include/postproc.hpp +142 -0
  141. netgen/include/potentialtools.hpp +22 -0
  142. netgen/include/precomp.hpp +60 -0
  143. netgen/include/preconditioner.hpp +602 -0
  144. netgen/include/prolongation.hpp +377 -0
  145. netgen/include/python_comp.hpp +107 -0
  146. netgen/include/python_fem.hpp +89 -0
  147. netgen/include/python_linalg.hpp +58 -0
  148. netgen/include/python_ngstd.hpp +386 -0
  149. netgen/include/recursive_pol.hpp +4896 -0
  150. netgen/include/recursive_pol_tet.hpp +395 -0
  151. netgen/include/recursive_pol_trig.hpp +492 -0
  152. netgen/include/reorderedfespace.hpp +81 -0
  153. netgen/include/sample_sort.hpp +105 -0
  154. netgen/include/scalarfe.hpp +335 -0
  155. netgen/include/shapefunction_utils.hpp +113 -0
  156. netgen/include/simd_complex.hpp +329 -0
  157. netgen/include/smoother.hpp +253 -0
  158. netgen/include/solve.hpp +89 -0
  159. netgen/include/sparsecholesky.hpp +313 -0
  160. netgen/include/sparsematrix.hpp +1038 -0
  161. netgen/include/sparsematrix_dyn.hpp +90 -0
  162. netgen/include/sparsematrix_impl.hpp +1013 -0
  163. netgen/include/special_matrix.hpp +463 -0
  164. netgen/include/specialelement.hpp +125 -0
  165. netgen/include/statushandler.hpp +33 -0
  166. netgen/include/stringops.hpp +12 -0
  167. netgen/include/superluinverse.hpp +136 -0
  168. netgen/include/symbolicintegrator.hpp +850 -0
  169. netgen/include/symmetricmatrix.hpp +144 -0
  170. netgen/include/tangentialfacetfe.hpp +224 -0
  171. netgen/include/tangentialfacetfespace.hpp +91 -0
  172. netgen/include/tensor.hpp +522 -0
  173. netgen/include/tensorcoefficient.hpp +446 -0
  174. netgen/include/tensorproductintegrator.hpp +113 -0
  175. netgen/include/thcurlfe.hpp +128 -0
  176. netgen/include/thcurlfe_impl.hpp +380 -0
  177. netgen/include/thdivfe.hpp +80 -0
  178. netgen/include/thdivfe_impl.hpp +492 -0
  179. netgen/include/tpdiffop.hpp +461 -0
  180. netgen/include/tpfes.hpp +133 -0
  181. netgen/include/tpintrule.hpp +224 -0
  182. netgen/include/triangular.hpp +465 -0
  183. netgen/include/tscalarfe.hpp +245 -0
  184. netgen/include/tscalarfe_impl.hpp +1029 -0
  185. netgen/include/umfpackinverse.hpp +148 -0
  186. netgen/include/vector.hpp +1273 -0
  187. netgen/include/voxelcoefficientfunction.hpp +41 -0
  188. netgen/include/vtkoutput.hpp +198 -0
  189. netgen/include/vvector.hpp +208 -0
  190. netgen/include/webgui.hpp +92 -0
  191. netgen/libngbla.dylib +0 -0
  192. netgen/libngcomp.dylib +0 -0
  193. netgen/libngfem.dylib +0 -0
  194. netgen/libngla.dylib +0 -0
  195. netgen/libngsbem.dylib +0 -0
  196. netgen/libngsolve.dylib +0 -0
  197. netgen/libngstd.dylib +0 -0
  198. ngsolve/TensorProductTools.py +210 -0
  199. ngsolve/__console.py +94 -0
  200. ngsolve/__expr.py +181 -0
  201. ngsolve/__init__.py +148 -0
  202. ngsolve/__init__.pyi +233 -0
  203. ngsolve/_scikit_build_core_dependencies.py +30 -0
  204. ngsolve/bla.pyi +1153 -0
  205. ngsolve/bvp.py +78 -0
  206. ngsolve/bvp.pyi +32 -0
  207. ngsolve/cmake/NGSolveConfig.cmake +102 -0
  208. ngsolve/cmake/ngsolve-targets-release.cmake +79 -0
  209. ngsolve/cmake/ngsolve-targets.cmake +163 -0
  210. ngsolve/comp/__init__.pyi +5449 -0
  211. ngsolve/comp/pml.pyi +89 -0
  212. ngsolve/config/__init__.py +1 -0
  213. ngsolve/config/__init__.pyi +43 -0
  214. ngsolve/config/__main__.py +4 -0
  215. ngsolve/config/config.py +60 -0
  216. ngsolve/config/config.pyi +45 -0
  217. ngsolve/demos/TensorProduct/__init__.py +0 -0
  218. ngsolve/demos/TensorProduct/tp_dg_1d_1d.py +80 -0
  219. ngsolve/demos/TensorProduct/tp_dg_1d_2d.py +73 -0
  220. ngsolve/demos/TensorProduct/tp_dg_2d_1d.py +72 -0
  221. ngsolve/demos/TensorProduct/tp_dg_2d_2d.py +66 -0
  222. ngsolve/demos/__init__.py +0 -0
  223. ngsolve/demos/howto/__init__.py +0 -0
  224. ngsolve/demos/howto/hhj.py +44 -0
  225. ngsolve/demos/howto/hybrid_dg.py +53 -0
  226. ngsolve/demos/howto/mixed.py +30 -0
  227. ngsolve/demos/howto/nonlin.py +29 -0
  228. ngsolve/demos/howto/pickling.py +26 -0
  229. ngsolve/demos/howto/pml.py +31 -0
  230. ngsolve/demos/howto/taskmanager.py +20 -0
  231. ngsolve/demos/howto/tdnns.py +47 -0
  232. ngsolve/demos/howto/timeDG-skeleton.py +45 -0
  233. ngsolve/demos/howto/timeDG.py +38 -0
  234. ngsolve/demos/howto/timeDGlap.py +42 -0
  235. ngsolve/demos/howto/timeDGwave.py +61 -0
  236. ngsolve/demos/intro/__init__.py +0 -0
  237. ngsolve/demos/intro/adaptive.py +123 -0
  238. ngsolve/demos/intro/cmagnet.py +59 -0
  239. ngsolve/demos/intro/elasticity.py +76 -0
  240. ngsolve/demos/intro/navierstokes.py +74 -0
  241. ngsolve/demos/intro/poisson.ipynb +170 -0
  242. ngsolve/demos/intro/poisson.py +41 -0
  243. ngsolve/demos/mpi/__init__.py +0 -0
  244. ngsolve/demos/mpi/mpi_cmagnet.py +87 -0
  245. ngsolve/demos/mpi/mpi_navierstokes.py +117 -0
  246. ngsolve/demos/mpi/mpi_poisson.py +89 -0
  247. ngsolve/demos/mpi/mpi_timeDG.py +82 -0
  248. ngsolve/directsolvers.py +26 -0
  249. ngsolve/directsolvers.pyi +15 -0
  250. ngsolve/eigenvalues.py +364 -0
  251. ngsolve/eigenvalues.pyi +30 -0
  252. ngsolve/fem.pyi +1647 -0
  253. ngsolve/internal.py +89 -0
  254. ngsolve/krylovspace.py +1013 -0
  255. ngsolve/krylovspace.pyi +298 -0
  256. ngsolve/la.pyi +1230 -0
  257. ngsolve/meshes.py +748 -0
  258. ngsolve/ngs2petsc.py +310 -0
  259. ngsolve/ngscxx.py +42 -0
  260. ngsolve/ngslib.so +0 -0
  261. ngsolve/ngstd.pyi +59 -0
  262. ngsolve/nonlinearsolvers.py +203 -0
  263. ngsolve/nonlinearsolvers.pyi +95 -0
  264. ngsolve/preconditioners.py +11 -0
  265. ngsolve/preconditioners.pyi +7 -0
  266. ngsolve/solve.pyi +109 -0
  267. ngsolve/solve_implementation.py +168 -0
  268. ngsolve/solve_implementation.pyi +42 -0
  269. ngsolve/solvers.py +7 -0
  270. ngsolve/solvers.pyi +14 -0
  271. ngsolve/timestepping.py +185 -0
  272. ngsolve/timestepping.pyi +28 -0
  273. ngsolve/timing.py +108 -0
  274. ngsolve/timing.pyi +54 -0
  275. ngsolve/utils.py +167 -0
  276. ngsolve/utils.pyi +273 -0
  277. ngsolve/webgui.py +670 -0
  278. ngsolve-6.2.2506.post74.dev0.data/data/Netgen.icns +0 -0
  279. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngscxx +17 -0
  280. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngsld +13 -0
  281. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngsolve.tcl +648 -0
  282. ngsolve-6.2.2506.post74.dev0.data/data/bin/ngspy +2 -0
  283. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/beam.geo +17 -0
  284. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/beam.vol +240 -0
  285. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/chip.in2d +41 -0
  286. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/chip.vol +614 -0
  287. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coil.geo +12 -0
  288. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coil.vol +2560 -0
  289. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coilshield.geo +24 -0
  290. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/coilshield.vol +3179 -0
  291. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/cube.geo +19 -0
  292. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/cube.vol +1832 -0
  293. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d10_DGdoubleglazing.pde +50 -0
  294. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d11_chip_nitsche.pde +40 -0
  295. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d1_square.pde +43 -0
  296. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d2_chip.pde +35 -0
  297. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d3_helmholtz.pde +22 -0
  298. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d4_cube.pde +46 -0
  299. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d5_beam.pde +74 -0
  300. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d6_shaft.pde +73 -0
  301. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d7_coil.pde +50 -0
  302. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d8_coilshield.pde +49 -0
  303. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/d9_hybridDG.pde +72 -0
  304. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/doubleglazing.in2d +27 -0
  305. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/doubleglazing.vol +737 -0
  306. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
  307. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/shaft.geo +73 -0
  308. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/shaft.vol +4291 -0
  309. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/square.in2d +17 -0
  310. ngsolve-6.2.2506.post74.dev0.data/data/share/ngsolve/square.vol +149 -0
  311. ngsolve-6.2.2506.post74.dev0.dist-info/METADATA +13 -0
  312. ngsolve-6.2.2506.post74.dev0.dist-info/RECORD +315 -0
  313. ngsolve-6.2.2506.post74.dev0.dist-info/WHEEL +5 -0
  314. ngsolve-6.2.2506.post74.dev0.dist-info/licenses/LICENSE +504 -0
  315. ngsolve-6.2.2506.post74.dev0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,4896 @@
1
+ #ifndef FILE_RECURSIVE_POL
2
+ #define FILE_RECURSIVE_POL
3
+
4
+ /*********************************************************************/
5
+ /* File: recursive_pol.hpp */
6
+ /* Author: Start */
7
+ /* Date: 6. Feb. 2003 */
8
+ /*********************************************************************/
9
+
10
+
11
+ #include <bla.hpp>
12
+
13
+
14
+ namespace ngfem
15
+ {
16
+ using namespace ngbla;
17
+
18
+
19
+ /*
20
+ Recursive Polynomials
21
+ */
22
+
23
+
24
+ // Use Lambda function with square-bracket assignment
25
+ template <typename TI, typename FUNC>
26
+ class SBLambdaElement
27
+ {
28
+ FUNC f;
29
+ TI i;
30
+ public:
31
+ INLINE SBLambdaElement (const SBLambdaElement & e2) = default;
32
+ INLINE SBLambdaElement (FUNC af, TI hi) : f(af), i(hi) { ; }
33
+ template <typename VAL>
34
+ INLINE VAL operator= (VAL v) { f(i, v); return v; }
35
+ };
36
+
37
+ template <typename TI, typename FUNC>
38
+ class Class_SBLambda
39
+ {
40
+ FUNC func;
41
+ TI offset;
42
+ public:
43
+ INLINE Class_SBLambda (const Class_SBLambda & l2) = default;
44
+ INLINE Class_SBLambda (FUNC f, TI ao) : func(f), offset(ao) { ; }
45
+
46
+ template <typename TI2>
47
+ INLINE auto operator[] (TI2 i) const -> SBLambdaElement<decltype(offset+i),FUNC>
48
+ {
49
+ return SBLambdaElement<decltype(offset+i),FUNC> (func, offset+i);
50
+ }
51
+
52
+ template <typename TI2>
53
+ INLINE auto operator+ (TI2 i) const -> Class_SBLambda<decltype(offset+i),FUNC>
54
+ { return Class_SBLambda<decltype(offset+i),FUNC> (func, offset+i); }
55
+
56
+ template <typename TI2>
57
+ INLINE auto Addr (TI2 i) const -> Class_SBLambda<decltype(offset+i),FUNC>
58
+ {return Class_SBLambda<decltype(offset+i),FUNC> (func, offset+i); }
59
+ };
60
+
61
+ template <typename FUNC>
62
+ INLINE const Class_SBLambda<IC<0>,FUNC> SBLambda (FUNC f)
63
+ {
64
+ return Class_SBLambda<IC<0>,FUNC> (f, IC<0>());
65
+ }
66
+
67
+
68
+
69
+
70
+ template <typename FUNC, typename FUNC2>
71
+ class Class_SBLambdaDuo
72
+ {
73
+ FUNC func;
74
+ FUNC2 func2;
75
+ int offset;
76
+ public:
77
+ INLINE Class_SBLambdaDuo (const Class_SBLambdaDuo & l2) : func(l2.func), func2(l2.func2), offset(l2.offset) { ; }
78
+ INLINE Class_SBLambdaDuo (FUNC f, FUNC2 f2, int ao = 0) : func(f), func2(f2), offset(ao) { ; }
79
+ INLINE SBLambdaElement<int,FUNC> operator[] (int i) const { return SBLambdaElement<int,FUNC> (func, offset+i); }
80
+ INLINE Class_SBLambdaDuo<FUNC, FUNC2> operator+ (int i) const { return Class_SBLambdaDuo<FUNC,FUNC2> (func, func2, offset+i); }
81
+ INLINE Class_SBLambdaDuo<FUNC, FUNC2> Addr (int i) const { return Class_SBLambdaDuo<FUNC,FUNC2> (func, func2, offset+i); }
82
+ template <typename VAL1, typename VAL2>
83
+ void operator() (int i1, VAL1 v1, int i2, VAL2 v2) const { func2(i1, v1, i2, v2); }
84
+ };
85
+
86
+ template <typename FUNC, typename FUNC2>
87
+ INLINE const Class_SBLambdaDuo<FUNC, FUNC2> SBLambdaDuo (FUNC f, FUNC2 f2)
88
+ {
89
+ return Class_SBLambdaDuo<FUNC,FUNC2> (f, f2);
90
+ }
91
+
92
+
93
+
94
+
95
+
96
+ /// a helper class for fixed order evaluation
97
+ template <class REC, int N>
98
+ class CEvalFO
99
+ {
100
+ public:
101
+ template <class S, class T>
102
+ INLINE static void Eval (S x, T && values, S & p1, S & p2)
103
+ {
104
+ S p3;
105
+ CEvalFO<REC,N-1>::Eval (x, values, p2, p3);
106
+ if (REC::ZERO_B)
107
+ values[N] = p1 = ( REC::CalcA(N) * x ) * p2 + REC::CalcC(N) * p3;
108
+ else
109
+ values[N] = p1 = ( REC::CalcA(N) * x + REC::CalcB(N)) * p2 + REC::CalcC(N) * p3;
110
+ }
111
+
112
+
113
+ template <class S, class Sc, class T>
114
+ INLINE static void EvalMult (S x, Sc c, T && values, S & p1, S & p2)
115
+ {
116
+ S p3;
117
+ CEvalFO<REC,N-1>::EvalMult (x, c, values, p2, p3);
118
+ if (REC::ZERO_B)
119
+ values[N] = p1 = ( REC::CalcA(N) * x ) * p2 + REC::CalcC(N) * p3;
120
+ else
121
+ values[N] = p1 = ( REC::CalcA(N) * x + REC::CalcB(N)) * p2 + REC::CalcC(N) * p3;
122
+ }
123
+
124
+
125
+ template <class S, class Sy, class T>
126
+ INLINE static void EvalScaled (S x, Sy y, T && values, S & p1, S & p2)
127
+ {
128
+ S p3;
129
+ CEvalFO<REC,N-1>::EvalScaled (x, y, values, p2, p3);
130
+ values[N] = p1 = ( REC::CalcA(N) * x + REC::CalcB(N) * y) * p2 + REC::CalcC(N)*(y*y) * p3;
131
+ }
132
+
133
+
134
+ template <class S, class Sy, class Sc, class T>
135
+ INLINE static void EvalScaledMult (S x, Sy y, Sc c, T && values, S & p1, S & p2)
136
+ {
137
+ S p3;
138
+ CEvalFO<REC,N-1>::EvalScaledMult (x, y, c, values, p2, p3);
139
+ values[N] = p1 = ( REC::CalcA(N) * x + REC::CalcB(N) * y) * p2 + REC::CalcC(N)*(y*y) * p3;
140
+ }
141
+ };
142
+
143
+
144
+ template <class REC>
145
+ class CEvalFO<REC, -1>
146
+ {
147
+ public:
148
+ template <class S, class T>
149
+ INLINE static void Eval (S x, T && values, S & /* p1 */, S & /* p2 */)
150
+ { ; }
151
+
152
+ template <class S, class Sc, class T>
153
+ INLINE static void EvalMult (S x, Sc c, T && values, S & /* p1 */, S & /* p2 */)
154
+ { ; }
155
+
156
+
157
+ template <class S, class Sy, class T>
158
+ INLINE static void EvalScaled (S x, Sy y, T && values, S & /* p1 */, S & /* p2 */)
159
+ { ; }
160
+
161
+ template <class S, class Sy, class Sc, class T>
162
+ INLINE static void EvalScaledMult (S x, Sy y, Sc c, T && values, S & /* p1 */, S & /* p2 */)
163
+ { ; }
164
+
165
+ };
166
+
167
+
168
+ template <class REC>
169
+ class CEvalFO<REC, 0>
170
+ {
171
+ public:
172
+ template <class S, class T>
173
+ INLINE static void Eval (S x, T && values, S & p1, S & /* p2 */)
174
+ {
175
+ values[0] = p1 = REC::P0(x);
176
+ }
177
+
178
+ template <class S, class Sc, class T>
179
+ INLINE static void EvalMult (S x, Sc c, T && values, S & p1, S & /* p2 */)
180
+ {
181
+ values[0] = p1 = c * REC::P0(x);
182
+ }
183
+
184
+
185
+ template <class S, class Sy, class T>
186
+ INLINE static void EvalScaled (S x, Sy y, T && values, S & p1, S & /* p2 */)
187
+ {
188
+ values[0] = p1 = REC::P0(x);
189
+ }
190
+
191
+ template <class S, class Sy, class Sc, class T>
192
+ INLINE static void EvalScaledMult (S x, Sy y, Sc c, T && values, S & p1, S & /* p2 */)
193
+ {
194
+ values[0] = p1 = c * REC::P0(x);
195
+ }
196
+
197
+ };
198
+
199
+ template <class REC>
200
+ class CEvalFO<REC, 1>
201
+ {
202
+ public:
203
+ template <class S, class T>
204
+ INLINE static void Eval (S x, T && values, S & p1, S & p2)
205
+ {
206
+ values[0] = p2 = REC::P0(x);
207
+ values[1] = p1 = REC::P1(x);
208
+ }
209
+
210
+ template <class S, class Sc, class T>
211
+ INLINE static void EvalMult (S x, Sc c, T && values, S & p1, S & p2)
212
+ {
213
+ values[0] = p2 = c * REC::P0(x);
214
+ values[1] = p1 = c * REC::P1(x);
215
+ }
216
+
217
+ template <class S, class Sy, class T>
218
+ INLINE static void EvalScaled (S x, Sy y, T && values, S & p1, S & p2)
219
+ {
220
+ values[0] = p2 = REC::P0(x);
221
+ values[1] = p1 = REC::P1(x,y);
222
+ }
223
+
224
+ template <class S, class Sy, class Sc, class T>
225
+ INLINE static void EvalScaledMult (S x, Sy y, Sc c, T && values, S & p1, S & p2)
226
+ {
227
+ values[0] = p2 = c * REC::P0(x);
228
+ values[1] = p1 = c * REC::P1(x,y);
229
+ }
230
+ };
231
+
232
+
233
+
234
+
235
+
236
+ // P_i = (a_i x + b_i) P_{i-1} + c_i P_{i-2}
237
+ template<class REC>
238
+ class RecursivePolynomial
239
+ {
240
+ public:
241
+ template <typename TINT, class S>
242
+ INLINE static S EvalNext2 (TINT i, S x, S & p1, S & p2)
243
+ {
244
+ if (REC::ZERO_B)
245
+ {
246
+ // S pnew = REC::A(i) * x * p1 + REC::C(i) * p2; // maybe ?
247
+ // S pnew = FMA(REC::C(i), p2, REC::A(i) * x * p1); // bad
248
+ S pnew = FMA(REC::A(i) * x, p1, REC::C(i) * p2); // good
249
+ p2 = p1;
250
+ p1 = pnew;
251
+ }
252
+ else
253
+ {
254
+ S pnew = (REC::A(i) * x + REC::B(i)) * p1 + REC::C(i) * p2;
255
+ p2 = p1;
256
+ p1 = pnew;
257
+ }
258
+ return p1;
259
+ }
260
+
261
+ #ifdef OLD
262
+ template <class S>
263
+ INLINE static S EvalNext (int i, S x, S & p1, S & p2)
264
+ {
265
+ if (i == 0)
266
+ {
267
+ p1 = REC::P0(x);
268
+ return p1;
269
+ }
270
+ if (i == 1)
271
+ {
272
+ p2 = p1;
273
+ p1 = REC::P1(x);
274
+ return p1;
275
+ }
276
+ return EvalNext2 (i, x, p1, p2);
277
+ /*
278
+ if (REC::ZERO_B)
279
+ {
280
+ S pnew = REC::A(i) * x * p1 + REC::C(i) * p2;
281
+ p2 = p1;
282
+ p1 = pnew;
283
+ }
284
+ else
285
+ {
286
+ S pnew = (REC::A(i) * x + REC::B(i)) * p1 + REC::C(i) * p2;
287
+ p2 = p1;
288
+ p1 = pnew;
289
+ }
290
+ return p1;
291
+ */
292
+ }
293
+ #endif
294
+
295
+
296
+
297
+ template <class S>
298
+ INLINE static S EvalNextTicTac (int i, S x, S & p1, S & p2)
299
+ {
300
+ switch (i)
301
+ {
302
+ case 0: return p1 = REC::P0(x);
303
+ case 1: return p1 = REC::P1(x);
304
+ default:
305
+ {
306
+ if (REC::ZERO_B)
307
+ {
308
+ p1 *= REC::C(i);
309
+ p1 += REC::A(i) * x * p2;
310
+ return p1;
311
+ }
312
+ else
313
+ {
314
+ p1 *= REC::C(i);
315
+ p1 += (REC::A(i) * x + REC::B(i)) * p2;
316
+ return p1;
317
+ }
318
+ }
319
+ }
320
+ }
321
+
322
+ template <typename TI, class S>
323
+ INLINE static S EvalNextTicTac2 (TI i, S x, S & p1, S & p2)
324
+ {
325
+ if (REC::ZERO_B)
326
+ {
327
+ /*
328
+ p1 *= REC::C(i);
329
+ p1 += REC::A(i) * x * p2;
330
+ return p1;
331
+ */
332
+ p1 = FMA (REC::A(i)*x, p2, REC::C(i)*p1);
333
+ return p1;
334
+ }
335
+ else
336
+ {
337
+ p1 *= REC::C(i);
338
+ p1 += (REC::A(i) * x + REC::B(i)) * p2;
339
+ return p1;
340
+ }
341
+ }
342
+
343
+ template <typename TI, class S, class Sy>
344
+ INLINE static S EvalScaledNextTicTac2 (TI i, S x, Sy y, S & p1, S & p2)
345
+ {
346
+ // p1 = (y*y) * REC::C(i) * p1;
347
+ if (REC::ZERO_B)
348
+ {
349
+ // p1 = (y*y) * REC::C(i) * p1;
350
+ // p1 += REC::A(i) * x * p2;
351
+ double a = REC::A(i);
352
+ double c = REC::C(i);
353
+ p1 = FMA(a*x, p2, c*(y*y)*p1);
354
+ }
355
+ else
356
+ {
357
+ p1 = (y*y) * REC::C(i) * p1;
358
+ p1 += (REC::A(i) * x + REC::B(i) * y) * p2;
359
+ }
360
+ return p1;
361
+ }
362
+
363
+ /*
364
+ template <class S, class Sc>
365
+ INLINE static S EvalNextMultTicTac (int i, S x, Sc c, S & p1, S & p2)
366
+ {
367
+ switch (i)
368
+ {
369
+ case 0: return p1 = c * REC::P0(x);
370
+ case 1: return p1 = c * REC::P1(x);
371
+ default: return EvalNextTicTac2 (i, x, p1, p2);
372
+ }
373
+ }
374
+ */
375
+
376
+ template <class S, class Sy>
377
+ INLINE static void EvalScaledNext (int i, S x, Sy y, S & p1, S & p2)
378
+ {
379
+ if (i == 0)
380
+ {
381
+ p1 = REC::P0(x);
382
+ return;
383
+ }
384
+ if (i == 1)
385
+ {
386
+ p2 = p1;
387
+ p1 = REC::P1(x,y);
388
+ return;
389
+ }
390
+
391
+ if (REC::ZERO_B)
392
+ {
393
+ S pnew = REC::A(i) * x * p1 + REC::C(i) * (y*y)*p2;
394
+ p2 = p1;
395
+ p1 = pnew;
396
+ }
397
+ else
398
+ {
399
+ S pnew = (REC::A(i) * x + REC::B(i) * y) * p1 + REC::C(i) * (y*y)*p2;
400
+ p2 = p1;
401
+ p1 = pnew;
402
+ }
403
+ }
404
+
405
+ template <typename TINT, class S, class Sy>
406
+ INLINE static S EvalScaledNext2 (TINT i, S x, Sy y, S & p1, S & p2)
407
+ {
408
+ if (REC::ZERO_B)
409
+ {
410
+ // S pnew = REC::A(i) * x * p1 + REC::C(i) * (y*y)*p2;
411
+ S pnew = FMA( REC::A(i)*x, p1, REC::C(i)*(y*y)*p2);
412
+ p2 = p1;
413
+ p1 = pnew;
414
+ }
415
+ else
416
+ {
417
+ S pnew = (REC::A(i) * x + REC::B(i) * y) * p1 + REC::C(i) * (y*y)*p2;
418
+ p2 = p1;
419
+ p1 = pnew;
420
+ }
421
+ return p1;
422
+ /*
423
+ // switch (i)
424
+ {
425
+ // case 0: return p1 = REC::P0(x);
426
+ // case 1: return p1 = REC::P1(x);
427
+ // default:
428
+ {
429
+ if (REC::ZERO_B)
430
+ {
431
+ p1 *= REC::C(i) *(y*y);
432
+ p1 += REC::A(i) * x * p2;
433
+ return p1;
434
+ }
435
+ else
436
+ {
437
+ p1 *= REC::C(i) *(y*y);
438
+ p1 += (REC::A(i) * x + REC::B(i) * y) * p2;
439
+ return p1;
440
+ }
441
+ }
442
+ }
443
+ */
444
+ }
445
+
446
+ template <class S, class Sy>
447
+ static INLINE S P1(S x, Sy y) { return REC::P1(x); }
448
+
449
+ public:
450
+
451
+ template <typename TI, class S, class T>
452
+ INLINE static void Eval (TI n, S x, T && values)
453
+ {
454
+ // if (n < 0) return;
455
+ EvalMult (n, x, 1.0, values);
456
+ }
457
+
458
+ template <typename TI, class S, class Sc, class T>
459
+ INLINE static void EvalMult (TI n, S x, Sc c, T && values)
460
+ {
461
+ /*
462
+ S p1, p2;
463
+ if (n < 0) return;
464
+
465
+ values[0] = EvalNextMultTicTac(0, x, c, p1, p2);
466
+ if (n < 1) return;
467
+
468
+ values[1] = EvalNextMultTicTac(1, x, c, p2, p1);
469
+ if (n < 2) return;
470
+
471
+ for (int i = 2; i < n; i+=2)
472
+ {
473
+ values[i] = EvalNextTicTac2 (i, x, p1, p2);
474
+ values[i+1] = EvalNextTicTac2 (i+1, x, p2, p1);
475
+ }
476
+ if ( (n&1) == 0 )
477
+ values[n] = EvalNextTicTac2 (n, x, p1, p2);
478
+ */
479
+
480
+
481
+
482
+ S p1(c * REC::P0(x));
483
+ S p2 = c * REC::P1(x);
484
+
485
+ TI i = 0;
486
+ for ( ; i < n; i+=2)
487
+ {
488
+ values[i] = p1;
489
+ values[i+1] = p2;
490
+
491
+ EvalNextTicTac2 (i+2, x, p1, p2);
492
+ EvalNextTicTac2 (i+3, x, p2, p1);
493
+ }
494
+ if (i == n)
495
+ values[n] = p1;
496
+ }
497
+
498
+
499
+ template <typename TI, class S, class Sc, class T1, class T2>
500
+ INLINE static void EvalMult (TI n, S x, Sc c, const Class_SBLambdaDuo<T1,T2> & values)
501
+ {
502
+ /*
503
+ S p1, p2;
504
+ if (n < 0) return;
505
+ values[0] = EvalNextMultTicTac(0, x, c, p1, p2);
506
+ if (n < 1) return;
507
+ values[1] = EvalNextMultTicTac(1, x, c, p2, p1);
508
+ if (n < 2) return;
509
+ */
510
+
511
+ S p1(c * REC::P0(x));
512
+ S p2 = c * REC::P1(x);
513
+
514
+ if (n < 0) return;
515
+ if (n == 0) { values [0] = p1; return; }
516
+ values (0, p1, 1, p2);
517
+ TI i = 2;
518
+ for ( ; i < n; i+=2)
519
+ {
520
+ S v1 = EvalNextTicTac2 (i, x, p1, p2);
521
+ S v2 = EvalNextTicTac2 (i+1, x, p2, p1);
522
+ values (i, v1, i+1, v2);
523
+ }
524
+ if (i <= n)
525
+ values[i] = EvalNextTicTac2 (i, x, p1, p2);
526
+ }
527
+
528
+
529
+ template <int N, class S, class Sc, class T>
530
+ INLINE static void EvalMult (IC<N> n, S x, Sc c, T && values)
531
+ {
532
+ S p1(c * REC::P0(x));
533
+ S p2 = c * REC::P1(x);
534
+
535
+ int i = 0;
536
+ for ( ; i < n; i+=2)
537
+ {
538
+ values[i] = p1;
539
+ values[i+1] = p2;
540
+
541
+ EvalNextTicTac2 (i+2, x, p1, p2);
542
+ EvalNextTicTac2 (i+3, x, p2, p1);
543
+ }
544
+ if (i == n)
545
+ values[n] = p1;
546
+
547
+ /*
548
+ // needs checking, code looks the same
549
+ S p2(c * REC::P0(x));
550
+ S p1(c * REC::P1(x));
551
+
552
+ Iterate<N+1> ([&] (auto i)
553
+ {
554
+ values[i] = p2;
555
+ EvalNext2 (i+2, x, p1, p2);
556
+ });
557
+ */
558
+ }
559
+
560
+
561
+ template <typename TI, class S, class T>
562
+ INLINE static void Eval1Assign (TI n, S x, T && values)
563
+ {
564
+ EvalMult1Assign (n, x, 1.0, values);
565
+ }
566
+
567
+ template <typename TI, class S, class Sc, class T>
568
+ INLINE static void EvalMult1Assign (TI n, S x, Sc c, T && values)
569
+ {
570
+ S p1 = c*REC::P1(x), p2(c * REC::P0(x));
571
+ for (TI i = 0; i <= n; i++)
572
+ {
573
+ values[i] = p2;
574
+ EvalNext2 (i+2, x, p1, p2);
575
+ }
576
+ }
577
+
578
+
579
+
580
+ template <typename TI, class S, class Sy, class T>
581
+ INLINE static void EvalScaled (TI n, S x, Sy y, T && values)
582
+ {
583
+ if (n < 0) return;
584
+ EvalScaledMult (n, x, y, 1.0, values);
585
+ }
586
+
587
+ template <typename TI, class S, class Sy, class Sc, class T>
588
+ INLINE static void EvalScaledMult (TI n, S x, Sy y, Sc c, T && values)
589
+ {
590
+ /*
591
+ S p1, p2;
592
+
593
+ // if (n < 0) return;
594
+
595
+ values[0] = p2 = c * REC::P0(x);
596
+
597
+ if (n < 1) return;
598
+ values[1] = p1 = c * REC::P1(x);
599
+
600
+ for (int i = 2; i <= n; i++)
601
+ {
602
+ EvalScaledNext2 (i, x, y, p1, p2);
603
+ values[i] = p1;
604
+ }
605
+ */
606
+
607
+
608
+ S p1(c * REC::P0(x));
609
+ S p2(c * REC::P1(x,y));
610
+
611
+ TI i = 0;
612
+ for ( ; i < n; i+=2)
613
+ {
614
+ values[i] = p1;
615
+ values[i+1] = p2;
616
+
617
+ EvalScaledNextTicTac2 (i+2, x, y, p1, p2);
618
+ EvalScaledNextTicTac2 (i+3, x, y, p2, p1);
619
+ }
620
+ if (i == n)
621
+ values[n] = p1;
622
+
623
+
624
+ // EvalScaledMult1Assign (n, x, y, c, values);
625
+ }
626
+
627
+
628
+ template <int N, class S, class Sy, class Sc, class T>
629
+ HD INLINE static void EvalScaledMult (IC<N> n, S x, Sy y, Sc c, T && values)
630
+ {
631
+ S p1(c*REC::P1(x,y)), p2(c * REC::P0(x));
632
+ Iterate<N+1> ([&] (auto i) LAMBDA_INLINE
633
+ {
634
+ values[i] = p2;
635
+ EvalScaledNext2 (i+2, x, y, p1, p2);
636
+ });
637
+ }
638
+
639
+
640
+ template <typename TI, class S, class Sy, class T>
641
+ INLINE static void EvalScaled1Assign (TI n, S x, Sy y, T && values)
642
+ {
643
+ // if (n < 0) return;
644
+ EvalScaledMult1Assign (n, x, y, 1.0, values);
645
+ }
646
+
647
+ template <typename TI, class S, class Sy, class Sc, class T>
648
+ INLINE static void EvalScaledMult1Assign (TI n, S x, Sy y, Sc c, T && values)
649
+ {
650
+ S p1(c*REC::P1(x,y)), p2(c * REC::P0(x));
651
+ if (n < 0) return;
652
+
653
+ TI i = 0;
654
+ while (true)
655
+ {
656
+ values[i] = p2;
657
+ if (i == n) break;
658
+ EvalScaledNext2 (i+2, x, y, p1, p2);
659
+ i++;
660
+ }
661
+
662
+ /*
663
+ TI i = 0;
664
+ goto lab1;
665
+ while (i <= n)
666
+ {
667
+ EvalScaledNext2 (i+1, x, y, p1, p2);
668
+ lab1:
669
+ values[i] = p2;
670
+ i++;
671
+ }
672
+ */
673
+
674
+ }
675
+
676
+
677
+ // C++14 only
678
+ #if __cplusplus > 201103L
679
+ template <int N, class S, class T>
680
+ INLINE static void Eval (IC<N> n, S x, T && values)
681
+ {
682
+ // S p1, p2;
683
+ // CEvalFO<REC, N>::Eval (x, values, p1, p2);
684
+
685
+ S p1 = REC::P1(x), p2 = REC::P0(x);
686
+ Iterate<n+1> ( [&] (auto i) LAMBDA_INLINE
687
+ {
688
+ values[i] = p2;
689
+ RecursivePolynomial<REC>::EvalNext2 (IC<i+2>(), x, p1, p2);
690
+ } );
691
+ }
692
+
693
+ template <int N, class S, class Sy, class T>
694
+ INLINE static void EvalScaled (IC<N> n,
695
+ S x, Sy y, T && values)
696
+ {
697
+ S p1(REC::P1(x,y)), p2(REC::P0(x));
698
+ Iterate<n+1> ( [&] (auto i) LAMBDA_INLINE
699
+ {
700
+ // cout << "eval scaled, type(i) = " << typeid(i).name() << endl;
701
+ values[i] = p2;
702
+ RecursivePolynomial<REC>::EvalScaledNext2 (i+IC<2>(), x, y, p1, p2);
703
+ });
704
+ }
705
+ #endif
706
+
707
+ template <int N, class S, class T>
708
+ INLINE static void EvalFO (S x, T && values)
709
+ {
710
+ S p1, p2;
711
+ CEvalFO<REC, N>::Eval (x, values, p1, p2);
712
+ }
713
+
714
+ template <int N, class S, class Sc, class T>
715
+ INLINE static void EvalMultFO (S x, Sc c, T && values)
716
+ {
717
+ S p1, p2;
718
+ CEvalFO<REC, N>::EvalMult (x, c, values, p1, p2);
719
+ }
720
+
721
+ template <int N, class S, class Sy, class T>
722
+ INLINE static void EvalScaledFO (S x, Sy y, T && values)
723
+ {
724
+ S p1, p2;
725
+ CEvalFO<REC, N>::EvalScaled (x, y, values, p1, p2);
726
+ }
727
+
728
+ template <int N, class S, class Sy, class Sc, class T>
729
+ INLINE static void EvalScaledMultFO (S x, Sy y, Sc c,T && values)
730
+ {
731
+ S p1, p2;
732
+ CEvalFO<REC, N>::EvalScaledMult (x, y, c, values, p1, p2);
733
+ }
734
+
735
+ enum { ZERO_B = 0 };
736
+ };
737
+
738
+
739
+
740
+
741
+
742
+
743
+
744
+ // P_i = ( (a_i x + b_i) P_{i-1} + c_i P_{i-2} ) / d_i
745
+ template<class REC>
746
+ class RecursivePolynomialNonStatic
747
+ {
748
+ public:
749
+
750
+ template <typename TI>
751
+ INLINE void ABC (TI i, double & a, double & b, double & c) const
752
+ {
753
+ a = static_cast<const REC&>(*this).A(i);
754
+ b = static_cast<const REC&>(*this).B(i);
755
+ c = static_cast<const REC&>(*this).C(i);
756
+ double d = 1.0 / static_cast<const REC&>(*this).D(i);
757
+ a *= d; b *= d; c *= d;
758
+ }
759
+
760
+ INLINE const REC & Cast() const { return static_cast<const REC &> (*this); }
761
+
762
+ template <typename TI, class S>
763
+ INLINE S EvalNext2 (TI i, S x, S & p1, S & p2) const
764
+ {
765
+ if (REC::ZERO_B)
766
+ {
767
+ S pnew = Cast().A(i) * x * p1 + Cast().C(i)*p2;
768
+ p2 = p1;
769
+ p1 = pnew;
770
+ return p1;
771
+ }
772
+ else
773
+ {
774
+ // S pnew = (Cast().A(i) * x + Cast().B(i)) * p1 + Cast().C(i)*p2;
775
+ // S pnew = FMA(Cast().C(i), p2, (Cast().A(i) * x + Cast().B(i)) * p1); // bad
776
+ S pnew = FMA( FMA(Cast().A(i), x, S(Cast().B(i))), p1, Cast().C(i) * p2); // good
777
+ /*
778
+ S axpb = (Cast().A(i) * x + Cast().B(i));
779
+ S hv = Cast().C(i)*p2;
780
+ S pnew = hv + axpb * p1;
781
+ */
782
+ p2 = p1;
783
+ p1 = pnew;
784
+ return p1;
785
+ }
786
+ }
787
+
788
+
789
+ /*
790
+ template <class S>
791
+ INLINE S EvalNext (int i, S x, S & p1, S & p2) const
792
+ {
793
+ switch (i)
794
+ {
795
+ case 0: return p1 = Cast().P0(x);
796
+ case 1: p2 = p1; return p1 = Cast().P1(x);
797
+ default:
798
+ {
799
+ if (REC::ZERO_B)
800
+ {
801
+ S pnew = Cast().A(i) * x * p1 + Cast().C(i)*p2;
802
+ p2 = p1;
803
+ p1 = pnew;
804
+ return p1;
805
+ }
806
+ else
807
+ {
808
+ S pnew = (Cast().A(i) * x + Cast().B(i)) * p1 + Cast().C(i)*p2;
809
+ p2 = p1;
810
+ p1 = pnew;
811
+ return p1;
812
+ }
813
+ }
814
+ }
815
+ }
816
+ */
817
+
818
+
819
+ template <class S, class Sc>
820
+ INLINE S EvalNextMult (int i, S x, Sc c, S & p1, S & p2)
821
+ {
822
+ switch (i)
823
+ {
824
+ case 0: return p1 = c * Cast().P0(x);
825
+ case 1: p2 = p1; return p1 = c * Cast().P1(x);
826
+ default:
827
+ {
828
+ S pnew = REC::ZERO_B ?
829
+ Cast().A(i) * x * p1 + Cast().C(i)*p2 :
830
+ (Cast().A(i) * x + Cast().B(i)) * p1 + Cast().C(i)*p2;
831
+ p2 = p1; p1 = pnew;
832
+ return p1;
833
+ }
834
+ }
835
+ }
836
+
837
+
838
+ template <typename TI, class S>
839
+ INLINE S EvalNextTicTac2 (TI i, S x, S & p1, S & p2) const
840
+ {
841
+ double a,b,c;
842
+ static_cast<const REC&> (*this).ABC (i, a, b, c);
843
+ if (REC::ZERO_B)
844
+ {
845
+ p1 *= c;
846
+ p1 += a*x*p2;
847
+ return p1;
848
+ }
849
+ else
850
+ {
851
+ /*
852
+ p1 *= c;
853
+ p1 += (a * x + b) * p2;
854
+ */
855
+ p1 = FMA(FMA(a,x,S(b)), p2, c*p1);
856
+ return p1;
857
+ }
858
+ }
859
+
860
+ /*
861
+ template <class S>
862
+ INLINE S EvalNextTicTac (int i, S x, S & p1, S & p2) const
863
+ {
864
+ switch (i)
865
+ {
866
+ case 0: return p1 = static_cast<const REC&>(*this).P0(x);
867
+ case 1: return p1 = static_cast<const REC&>(*this).P1(x);
868
+ default:
869
+ {
870
+ double a,b,c;
871
+ static_cast<const REC&> (*this).ABC (i, a, b, c);
872
+
873
+ if (REC::ZERO_B)
874
+ {
875
+ p1 *= c;
876
+ p1 += a*x*p2;
877
+ return p1;
878
+ }
879
+ else
880
+ {
881
+ p1 *= c;
882
+ p1 += (a * x + b) * p2;
883
+ return p1;
884
+ }
885
+ }
886
+ }
887
+ }
888
+ */
889
+
890
+ /*
891
+ template <class S, class Sc>
892
+ INLINE S EvalNextMultTicTac (int i, S x, Sc c, S & p1, S & p2) const
893
+ {
894
+ switch (i)
895
+ {
896
+ case 0: return p1 = c * static_cast<const REC&>(*this).P0(x);
897
+ case 1: return p1 = c * static_cast<const REC&>(*this).P1(x);
898
+ default: return EvalNextTicTac2 (i, x, p1, p2);
899
+ }
900
+ }
901
+ */
902
+
903
+ template <typename TI, class S, class Sy>
904
+ INLINE S EvalScaledNext2 (TI i, S x, Sy y, S & p1, S & p2) const
905
+ {
906
+ if (REC::ZERO_B)
907
+ {
908
+ S pnew = Cast().A(i) * x * p1 + Cast().C(i) * (y*y)*p2;
909
+ // pnew *= 1.0 / Cast().D(i);
910
+ p2 = p1;
911
+ p1 = pnew;
912
+ }
913
+ else
914
+ {
915
+ S pnew = (Cast().A(i) * x + Cast().B(i) * y) * p1 + Cast().C(i) * (y*y)*p2;
916
+ // pnew *= 1.0 / static_cast<const REC&>(*this).D(i);
917
+ p2 = p1;
918
+ p1 = pnew;
919
+ }
920
+ return p1;
921
+ }
922
+
923
+ /*
924
+ // new
925
+ template <class S, class Sy, class Tc>
926
+ INLINE S EvalScaledMultNext (int i, S x, Sy y, Tc c, S & p1, S & p2) const
927
+ {
928
+ switch (i)
929
+ {
930
+ case 0:
931
+ return p1 = c * static_cast<const REC&>(*this).P0(x);
932
+ case 1:
933
+ p2 = p1; return p1 = c * static_cast<const REC&>(*this).P1(x,y);
934
+ default:
935
+ {
936
+ if (REC::ZERO_B)
937
+ {
938
+ S pnew = Cast().A(i) * x * p1 + Cast().C(i) * (y*y)*p2;
939
+ pnew *= 1.0 / Cast().D(i);
940
+ p2 = p1;
941
+ p1 = pnew;
942
+ }
943
+ else
944
+ {
945
+ S pnew = (Cast().A(i) * x + Cast().B(i) * y) * p1 + Cast().C(i) * (y*y)*p2;
946
+ pnew *= 1.0 / static_cast<const REC&>(*this).D(i);
947
+ p2 = p1;
948
+ p1 = pnew;
949
+ }
950
+ return p1;
951
+ }
952
+ }
953
+ }
954
+ */
955
+
956
+
957
+ public:
958
+
959
+ template <typename TI, class S, class T>
960
+ INLINE void Eval (TI n, S x, T && values) const
961
+ {
962
+ if (n < 0) return;
963
+ EvalMult (n, x, 1.0, values);
964
+ }
965
+
966
+ template <typename TI, class S, class T>
967
+ INLINE void Eval1Assign (TI n, S x, T && values) const
968
+ {
969
+ // if (n < 0) return;
970
+ EvalMult1Assign (n, x, 1.0, values);
971
+ }
972
+
973
+ template <typename TI, class S, class Sc, class T>
974
+ INLINE void EvalMult (TI n, S x, Sc c, T && values) const
975
+ {
976
+ /*
977
+ S p1, p2;
978
+
979
+ if (n < 0) return;
980
+
981
+ values[0] = EvalNextMultTicTac(0, x, c, p1, p2);
982
+ if (n < 1) return;
983
+
984
+ values[1] = EvalNextMultTicTac(1, x, c, p2, p1);
985
+ if (n < 2) return;
986
+
987
+ // for (int i = 2; i <= n; i++)
988
+ // values[i] = EvalNext2 (i, x, p1, p2);
989
+
990
+ for (int i = 2; i <= n; i+=2)
991
+ {
992
+ values[i] = EvalNextTicTac2 (i, x, p1, p2);
993
+ if (i == n) break;
994
+ values[i+1] = EvalNextTicTac2 (i+1, x, p2, p1);
995
+ }
996
+ */
997
+
998
+ /*
999
+ // leading !!!!
1000
+ // if (n < 0) return;
1001
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1002
+ values[0] = p1;
1003
+ if (n < 1) return;
1004
+
1005
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1006
+ values[1] = p2;
1007
+
1008
+ for (int i = 2; i <= n; i+=2)
1009
+ {
1010
+ values[i] = EvalNextTicTac2 (i, x, p1, p2);
1011
+ if (i == n) break;
1012
+ values[i+1] = EvalNextTicTac2 (i+1, x, p2, p1);
1013
+ }
1014
+ */
1015
+
1016
+
1017
+ // if (n < 0) return;
1018
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1019
+ values[0] = p1;
1020
+ if (n < 1) return;
1021
+
1022
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1023
+ values[1] = p2;
1024
+
1025
+ TI i = 2;
1026
+ if ( (n&1) == 0)
1027
+ {
1028
+ values[i] = EvalNext2 (i, x, p2, p1);
1029
+ i++;
1030
+ }
1031
+ for ( ; i < n; i+=2)
1032
+ {
1033
+ values[i] = EvalNextTicTac2 (i, x, p1, p2);
1034
+ values[i+1] = EvalNextTicTac2 (i+1, x, p2, p1);
1035
+ }
1036
+
1037
+
1038
+
1039
+ /*
1040
+ // if (n < 0) return;
1041
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1042
+ values[0] = p1;
1043
+ if (n < 1) return;
1044
+
1045
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1046
+ values[1] = p2;
1047
+ // if (n < 2) return;
1048
+
1049
+ for (int i = 2; i <= n; i++)
1050
+ values[i] = EvalNext2 (i, x, p2, p1);
1051
+ */
1052
+
1053
+ /*
1054
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1055
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1056
+ TI i = 0;
1057
+ for ( ; i < n; i+=2)
1058
+ {
1059
+ values[i] = p1;
1060
+ EvalNextTicTac2 (i+2, x, p1, p2);
1061
+ values[i+1] = p2;
1062
+ EvalNextTicTac2 (i+3, x, p2, p1);
1063
+ }
1064
+ if (i == n)
1065
+ values[n] = p1;
1066
+ */
1067
+
1068
+
1069
+ /*
1070
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1071
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1072
+ TI i = 0;
1073
+ for ( ; i <= n; i+=2)
1074
+ {
1075
+ values[i] = p1;
1076
+ if (i == n) break;
1077
+ EvalNextTicTac2 (i+2, x, p1, p2);
1078
+ values[i+1] = p2;
1079
+ EvalNextTicTac2 (i+3, x, p2, p1);
1080
+ }
1081
+ */
1082
+ }
1083
+
1084
+ template <int N, class S, class Sc, class T>
1085
+ INLINE void EvalMult (IC<N> n, S x, Sc c, T && values) const
1086
+ {
1087
+ // S p1(c*REC::P1(x)), p2(c * REC::P0(x));
1088
+
1089
+ S p2(c * static_cast<const REC&>(*this).P0(x));
1090
+ S p1(c * static_cast<const REC&>(*this).P1(x));
1091
+
1092
+ Iterate<N+1> ([&] (auto i)
1093
+ {
1094
+ values[i] = p2;
1095
+ this->EvalNext2 (i+2, x, p1, p2);
1096
+ });
1097
+ }
1098
+
1099
+ template <int N, class S, class Sc, class T1, class T2>
1100
+ INLINE void EvalMult (IC<N> n, S x, Sc c, Class_SBLambdaDuo<T1,T2> && values) const
1101
+ {
1102
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1103
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1104
+
1105
+ size_t i = 0;
1106
+ for ( ; i < n; i+=2)
1107
+ {
1108
+ values (i, p1, i+1, p2);
1109
+ EvalNextTicTac2 (i+2, x, p1, p2);
1110
+ EvalNextTicTac2 (i+3, x, p2, p1);
1111
+ }
1112
+ if (i == n)
1113
+ values[n] = p1;
1114
+ }
1115
+
1116
+
1117
+
1118
+
1119
+ template <typename TI, class S, class Sc, class T>
1120
+ INLINE void EvalMult1Assign (TI n, S x, Sc c, T && values) const
1121
+ {
1122
+ /*
1123
+ S p1(0.0), p2(0.0); // initialize for suppressing warning
1124
+ for (int i = 0; i <= n; i++)
1125
+ values[i] = EvalNextMult (i, x, c, p1, p2);
1126
+ */
1127
+
1128
+ S p1(c * static_cast<const REC&>(*this).P1(x)),
1129
+ p2(c * static_cast<const REC&>(*this).P0(x));
1130
+ for (TI i = 0; i <= n; i++)
1131
+ {
1132
+ values[i] = p2;
1133
+ EvalNext2 (i+2, x, p1, p2);
1134
+ }
1135
+
1136
+ }
1137
+
1138
+ template <typename TI, class S, class Sc, class T1, class T2>
1139
+ INLINE void EvalMult (TI n, S x, Sc c, Class_SBLambdaDuo<T1,T2> && values) const
1140
+ {
1141
+ S p1(c * static_cast<const REC&>(*this).P0(x));
1142
+ S p2(c * static_cast<const REC&>(*this).P1(x));
1143
+
1144
+ TI i = 0;
1145
+ for ( ; i < n; i+=2)
1146
+ {
1147
+ values (i, p1, i+1, p2);
1148
+ EvalNextTicTac2 (i+2, x, p1, p2);
1149
+ EvalNextTicTac2 (i+3, x, p2, p1);
1150
+ }
1151
+ if (i == n)
1152
+ values[n] = p1;
1153
+ }
1154
+
1155
+
1156
+ template <typename TI, class S, class Sy, class T>
1157
+ INLINE void EvalScaled (TI n, S x, Sy y, T && values) const
1158
+ {
1159
+ EvalScaledMult (n, x, y, 1.0, values);
1160
+ }
1161
+
1162
+ template <class S, class Sy>
1163
+ INLINE S P1(S x, Sy y) const
1164
+ {
1165
+ return static_cast<const REC&>(*this).P1(x);
1166
+ }
1167
+
1168
+ template <typename TI, class S, class Sy, class Sc, class T>
1169
+ INLINE void EvalScaledMult (TI n, S x, Sy y, Sc c, T && values) const
1170
+ {
1171
+ S p1, p2;
1172
+
1173
+ if (n < 0) return;
1174
+
1175
+ values[0] = p2 = c * static_cast<const REC&>(*this).P0(x);
1176
+ if (n < 1) return;
1177
+
1178
+ values[1] = p1 = c * static_cast<const REC&>(*this).P1(x,y);
1179
+
1180
+ for (TI i = 2; i <= n; i++)
1181
+ values[i] = EvalScaledNext2 (i, x, y, p1, p2);
1182
+ }
1183
+
1184
+ template <int N, class S, class Sy, class Sc, class T>
1185
+ INLINE void EvalScaledMult (IC<N> n, S x, Sy y, Sc c, T && values) const
1186
+ {
1187
+ S p1(c*Cast().P1(x,y)), p2(c * Cast().P0(x));
1188
+ Iterate<N+1> ([&] (auto i) LAMBDA_INLINE
1189
+ {
1190
+ values[i] = p2;
1191
+ this->EvalScaledNext2 (i+2, x, y, p1, p2);
1192
+ });
1193
+ }
1194
+
1195
+ template <typename TI, class S, class Sy, class Sc, class T>
1196
+ INLINE void EvalScaledMult1Assign (TI n, S x, Sy y, Sc c, T && values) const
1197
+ {
1198
+ /*
1199
+ S p1(0.0), p2(0.0);
1200
+ for (int i = 0; i <= n; i++)
1201
+ values[i] = EvalScaledMultNext (i, x, y, c, p1, p2);
1202
+ */
1203
+
1204
+
1205
+ S p1 = c*static_cast<const REC&>(*this).P1(x,y),
1206
+ p2 = c * static_cast<const REC&>(*this).P0(x);
1207
+ for (TI i = 0; i <= n; i++)
1208
+ {
1209
+ values[i] = p2;
1210
+ EvalScaledNext2 (i+2, x, y, p1, p2);
1211
+ }
1212
+
1213
+ }
1214
+
1215
+ template <typename TI, class S>
1216
+ INLINE S CalcHighestOrder (TI n, S x) const
1217
+ {
1218
+ return CalcHighestOrderMult (n, x, 1.0);
1219
+ }
1220
+
1221
+ template <typename TI, class S, class Sc>
1222
+ INLINE S CalcHighestOrderMult (TI n, S x, Sc c) const
1223
+ {
1224
+ S p1(c * static_cast<const REC&>(*this).P1(x)),
1225
+ p2(c * static_cast<const REC&>(*this).P0(x));
1226
+ for (TI i = 0; i < n; i++)
1227
+ EvalNext2 (i+2, x, p1, p2);
1228
+ return p2;
1229
+ }
1230
+
1231
+ enum { ZERO_B = 0 };
1232
+ };
1233
+
1234
+
1235
+
1236
+
1237
+
1238
+
1239
+
1240
+
1241
+
1242
+ /* ******************** Legendre Polynomial ****************** */
1243
+
1244
+ class LegendrePolynomial_CalcCoefficient : public RecursivePolynomial<LegendrePolynomial_CalcCoefficient>
1245
+ {
1246
+ public:
1247
+ INLINE LegendrePolynomial_CalcCoefficient () { ; }
1248
+
1249
+ template <class S, class T>
1250
+ INLINE LegendrePolynomial_CalcCoefficient (int n, S x, T && values)
1251
+ {
1252
+ Eval (n, x, values);
1253
+ }
1254
+
1255
+ template <class S>
1256
+ static INLINE S P0(S x) { return S(1.0); }
1257
+ template <class S>
1258
+ static INLINE S P1(S x) { return x; }
1259
+ template <class S, class Sy>
1260
+ static INLINE S P1(S x, Sy y) { return P1(x); }
1261
+
1262
+ static INLINE double A (int i) { return 2.0-1.0/i; }
1263
+ static INLINE double B (int i) { return 0; }
1264
+ static INLINE double C (int i) { return 1.0/i-1.0; }
1265
+ enum { ZERO_B = 1 };
1266
+ };
1267
+
1268
+
1269
+
1270
+ class NGS_DLL_HEADER LegendrePolynomial : public RecursivePolynomial<LegendrePolynomial>
1271
+ {
1272
+ static Array< Vec<2> > coefs;
1273
+
1274
+ public:
1275
+ INLINE LegendrePolynomial () { ; }
1276
+
1277
+ template <class S, class T>
1278
+ INLINE LegendrePolynomial (int n, S x, T && values)
1279
+ {
1280
+ Eval (n, x, values);
1281
+ }
1282
+
1283
+ static void Calc (int n);
1284
+ static FlatArray<Vec<2>> GetCoefs() { return coefs; }
1285
+
1286
+ template <class S>
1287
+ static INLINE double P0(S x) { return 1.0; }
1288
+ template <class S>
1289
+ static INLINE S P1(S x) { return x; }
1290
+ template <class S, class Sy>
1291
+ static INLINE S P1(S x, Sy y) { return P1(x); }
1292
+
1293
+
1294
+ static INLINE double CalcA (int i) { return 2.0-1.0/i; }
1295
+ static INLINE double CalcB (int i) { return 0; }
1296
+ static INLINE double CalcC (int i) { return 1.0/i-1.0; }
1297
+
1298
+ template <typename TI>
1299
+ static INLINE double A (TI i) { return coefs[i][0]; }
1300
+ template <typename TI>
1301
+ static INLINE double B (TI i) { return 0; }
1302
+ template <typename TI>
1303
+ static INLINE double C (TI i) { return coefs[i][1]; }
1304
+
1305
+ template <int I>
1306
+ static INLINE double A (IC<I> i) { return 2.0-1.0/i; }
1307
+ template <int I>
1308
+ static INLINE double B (IC<I> i) { return 0; }
1309
+ template <int I>
1310
+ static INLINE double C (IC<I> i) { return 1.0/i-1.0; }
1311
+
1312
+
1313
+ enum { ZERO_B = 1 };
1314
+ };
1315
+
1316
+
1317
+ class LegendrePolynomialNonStatic : public RecursivePolynomialNonStatic<LegendrePolynomialNonStatic>
1318
+ {
1319
+ FlatArray<Vec<2>> coefs;
1320
+ public:
1321
+ LegendrePolynomialNonStatic ()
1322
+ : coefs(LegendrePolynomial::GetCoefs()) { ; }
1323
+
1324
+ template <class S>
1325
+ INLINE double P0(S x) const { return 1.0; }
1326
+ template <class S>
1327
+ INLINE S P1(S x) const { return x; }
1328
+ template <class S, class Sy>
1329
+ INLINE S P1(S x, Sy y) const { return P1(x); }
1330
+
1331
+ template <typename TI>
1332
+ INLINE double A (TI i) const { return coefs[i][0]; }
1333
+ template <typename TI>
1334
+ INLINE double B (TI i) const { return 0; }
1335
+ template <typename TI>
1336
+ INLINE double C (TI i) const { return coefs[i][1]; }
1337
+ };
1338
+
1339
+
1340
+ #ifdef __CUDACC__
1341
+ extern __device__ Vec<2> * intlegnobubble_coefs;
1342
+ #endif
1343
+
1344
+ class IntLegNoBubble : public RecursivePolynomial<IntLegNoBubble>
1345
+ {
1346
+ static Array< Vec<2> > coefs;
1347
+
1348
+ public:
1349
+ IntLegNoBubble () { ; }
1350
+
1351
+ template <class S, class T>
1352
+ inline IntLegNoBubble (int n, S x, T && values)
1353
+ {
1354
+ Eval (n, x, values);
1355
+ }
1356
+
1357
+ static void Calc (int n);
1358
+
1359
+ template <class S>
1360
+ static INLINE double P0(S x) { return -0.5; }
1361
+ template <class S>
1362
+ static INLINE S P1(S x) { return -0.5*x; }
1363
+ template <class S, class Sy>
1364
+ static INLINE S P1(S x, Sy y) { return P1(x); }
1365
+
1366
+ static INLINE double A (int i) { return coefs[i][0]; }
1367
+ static INLINE double B (int i) { return 0; }
1368
+ static INLINE double C (int i) { return coefs[i][1]; }
1369
+
1370
+ static INLINE double CalcA (int i) { i+=2; return (2*i-3)/double(i); }
1371
+ static INLINE double CalcB (int i) { return 0; }
1372
+ static INLINE double CalcC (int i) { i+=2; return -(i-3.0)/i; }
1373
+ enum { ZERO_B = 1 };
1374
+ };
1375
+
1376
+
1377
+
1378
+
1379
+ class IntegratedLegendrePolynomial : public RecursivePolynomial<IntegratedLegendrePolynomial>
1380
+ {
1381
+ // static Array< double[2] > coefs;
1382
+
1383
+ public:
1384
+ IntegratedLegendrePolynomial () { ; }
1385
+
1386
+ template <class S, class T>
1387
+ inline IntegratedLegendrePolynomial (int n, S x, T && values)
1388
+ {
1389
+ Eval (n, x, values);
1390
+ }
1391
+
1392
+ static void Calc (int n);
1393
+
1394
+ template <class S>
1395
+ static INLINE S P0(S x) { return S(-1.0); }
1396
+ template <class S>
1397
+ static INLINE S P1(S x) { return x; }
1398
+
1399
+ static INLINE double A (int i) { return (2*i-3)/double(i); }
1400
+ static INLINE double B (int i) { return 0; }
1401
+ static INLINE double C (int i) { return -(i-3.0)/i; }
1402
+ enum { ZERO_B = 1 };
1403
+ };
1404
+
1405
+
1406
+
1407
+ class ChebyPolynomial : public RecursivePolynomial<ChebyPolynomial>
1408
+ {
1409
+ public:
1410
+ ChebyPolynomial () { ; }
1411
+
1412
+ template <class S, class T>
1413
+ inline ChebyPolynomial (int n, S x, T && values)
1414
+ {
1415
+ Eval (n, x, values);
1416
+ }
1417
+
1418
+ template <class S>
1419
+ static INLINE double P0(S x) { return 1.0; }
1420
+ template <class S>
1421
+ static INLINE S P1(S x) { return x; }
1422
+ template <class S, class Sy>
1423
+ static INLINE S P1(S x, Sy y) { return P1(x); }
1424
+
1425
+ static INLINE double A (int i) { return 2; }
1426
+ static INLINE double B (int i) { return 0; }
1427
+ static INLINE double C (int i) { return -1; }
1428
+
1429
+ static INLINE double CalcA (int i) { return 2; }
1430
+ static INLINE double CalcB (int i) { return 0; }
1431
+ static INLINE double CalcC (int i) { return -1; }
1432
+
1433
+ enum { ZERO_B = 1 };
1434
+ };
1435
+
1436
+
1437
+
1438
+
1439
+
1440
+ /*
1441
+ LegendreFunctions(m).Eval(n, x, values)
1442
+ evaluates the first (n+1) non-zero associated Legendre functions of order m,
1443
+ which are P_m^m(x) ... P_{m+n}^m
1444
+ */
1445
+ class LegendreFunctions : public RecursivePolynomialNonStatic<LegendreFunctions>
1446
+ {
1447
+ int m;
1448
+ public:
1449
+ LegendreFunctions (size_t _m) : m(_m) { }
1450
+
1451
+ template <typename T, typename S>
1452
+ LegendreFunctions (size_t mmax, size_t n, T x, S && values)
1453
+ {
1454
+ values.Rows(m+1).Cols(n+1) = 0.0;
1455
+ for (size_t i = 0; i <= mmax; i++)
1456
+ {
1457
+ LegendreFunctions l2(i);
1458
+ l2.Eval(n-i, x, values.Row(i).Range(i,n-i+1));
1459
+ }
1460
+ }
1461
+
1462
+ template <class S>
1463
+ INLINE double P0(S x) const
1464
+ {
1465
+ S prod = 1.0;
1466
+ double factor = 1;
1467
+ S somx2 = sqrt(1.0-x*x);
1468
+ for (size_t i = 1; i <= m; i++)
1469
+ {
1470
+ prod *= -factor * somx2;
1471
+ factor += 2;
1472
+ }
1473
+ return prod;
1474
+ }
1475
+
1476
+ template <class S>
1477
+ INLINE S P1(S x) const
1478
+ {
1479
+ return (2*m+1)*x * P0(x);
1480
+ }
1481
+
1482
+ template <typename TI>
1483
+ // INLINE const double A (TI i) const { return (2*(i+m)-1)/double(i); }
1484
+ INLINE const double A (TI i) const
1485
+ {
1486
+ int ii = i; int im = m;
1487
+ double a = (2*(ii+im)-1)/double(i); return a;
1488
+ }
1489
+ template <typename TI>
1490
+ INLINE const double B (TI i) const { return 0; }
1491
+ template <typename TI>
1492
+ // INLINE const double C (TI i) const { return (-i-2*m+1)/double(i); }
1493
+ INLINE const double C (TI i) const
1494
+ {
1495
+ int ii = i; int im = m;
1496
+ double c = (-ii-2*im+1)/double(ii); return c;
1497
+ }
1498
+ template <typename TI>
1499
+ INLINE const double D (TI i) const { return 1; }
1500
+ };
1501
+
1502
+
1503
+
1504
+ /*
1505
+ sqrt( (2n+1) * (n-m)! / (n+m)! ) * P^m_n
1506
+ */
1507
+ class NormalizedLegendreFunctions : public RecursivePolynomialNonStatic<NormalizedLegendreFunctions>
1508
+ {
1509
+ int m;
1510
+ static Matrix<double,ColMajor> matA, matB;
1511
+ public:
1512
+ NormalizedLegendreFunctions (size_t _m) : m(_m) { }
1513
+
1514
+
1515
+ static void Calc(int mmax)
1516
+ {
1517
+ if (matA.Height() >= mmax+1) return;
1518
+ matA.SetSize(mmax+1, mmax+1);
1519
+ matB.SetSize(mmax+1, mmax+1);
1520
+ for (int m = 0; m <= mmax; m++)
1521
+ for (int n = m+2; n <= mmax; n++)
1522
+ {
1523
+ matA(n,m) = (2*n-1) / sqrt((n-m+0.0)*(n+m));
1524
+ matB(n,m) = sqrt((n+m-1.0)*(n-m-1.0)) / sqrt((n-m+0.0)*(n+m));
1525
+ }
1526
+ }
1527
+
1528
+ template <typename T, typename S>
1529
+ NormalizedLegendreFunctions (size_t mmax, size_t nmax, T x, S && values)
1530
+ {
1531
+ /*
1532
+ values.Rows(mmax+1).Cols(nmax+1) = 0.0;
1533
+ for (size_t i = 0; i <= mmax; i++)
1534
+ NormalizedLegendreFunctions(i).Eval(nmax-i, x, values.Row(i).Range(i,nmax+1));
1535
+ */
1536
+
1537
+ // better stability for m > 1000
1538
+
1539
+ auto y = Trans(values);
1540
+
1541
+ y = 0.0;
1542
+ T u = -sqrt((1-x)*(1+x));
1543
+ y(0,0)=1;
1544
+
1545
+ if (mmax+1 > matA.Height() || nmax > matA.Width())
1546
+ {
1547
+ for (int m = 0; m <= mmax; m++)
1548
+ {
1549
+ if (m > 0)
1550
+ y(m,m)=y(m-1,m-1)*u*sqrt((2*m-1.0)/(2*m));
1551
+ if (m < nmax)
1552
+ y(m+1,m)=x*y(m,m)*sqrt(2*m+1.0);
1553
+ for (int n = m+2; n <= nmax; n++)
1554
+ y(n,m)=((2*n-1)*x*y(n-1,m) -
1555
+ sqrt((n+m-1.0)*(n-m-1.0))*y(n-2,m))
1556
+ /sqrt((n-m+0.0)*(n+m));
1557
+ }
1558
+ }
1559
+ else
1560
+ {
1561
+ for (int m = 0; m <= mmax; m++)
1562
+ {
1563
+ if (m > 0)
1564
+ y(m,m)=y(m-1,m-1)*u*sqrt((2*m-1.0)/(2*m));
1565
+ if (m < nmax)
1566
+ {
1567
+ T valold = y(m,m);
1568
+
1569
+ T val = x*valold*sqrt(2*m+1.0);
1570
+ y(m+1,m)=val;
1571
+
1572
+ auto coefsA = matA.Col(m);
1573
+ auto coefsB = matB.Col(m);
1574
+
1575
+ for (int n = m+2; n <= nmax; n++)
1576
+ {
1577
+ T valnew = coefsA(n) * x * val - coefsB(n) * valold;
1578
+ y(n,m) = valnew;
1579
+ valold = val;
1580
+ val = valnew;
1581
+ }
1582
+ }
1583
+ /*
1584
+ for (int n = m+2; n <= nmax; n++)
1585
+ y(n,m) = matA(n,m) * x * y(n-1,m) - matB(n,m) * y(n-2,m);
1586
+ */
1587
+ }
1588
+ }
1589
+
1590
+ for (int n = 0; n <= nmax; n++)
1591
+ y.Row(n).Range(0,n+1) *= sqrt(2*n+1.0);
1592
+ /*
1593
+ for (int m = 0; m <= n; m++)
1594
+ y(n,m)=y(n,m)*sqrt(2*n+1.0);
1595
+ */
1596
+ }
1597
+
1598
+ template <class S>
1599
+ INLINE double P0(S x) const
1600
+ {
1601
+ S prod = 2*m+1;
1602
+ for (size_t i = 1; i <= m; i++)
1603
+ prod *= (1-x*x) * (1 - 1.0/(2*i));
1604
+ return sqrt(prod) * ( (m%2) ? -1 : 1 );
1605
+ }
1606
+
1607
+ template <class S>
1608
+ INLINE S P1(S x) const
1609
+ {
1610
+ return sqrt(2*m+3.0)*x * P0(x);
1611
+ }
1612
+
1613
+ template <typename TI>
1614
+ INLINE const double A (TI i) const
1615
+ {
1616
+ int ii = i, im = m;
1617
+ return sqrt( (2*ii+2*im-1.0)*(2*ii+2*im+1.0) / (ii*(ii+2*im)) );
1618
+ }
1619
+ template <typename TI>
1620
+ INLINE double B (TI i) const { return 0; }
1621
+ template <typename TI>
1622
+ INLINE const double C (TI i) const
1623
+ {
1624
+ int ii = i, im = m;
1625
+ return -sqrt( (ii-1)*(ii+2*im-1.0)*(2*ii+2*im+1.0) / (ii*(ii+2*im)*(2*ii+2*im-3.0)) );
1626
+ }
1627
+
1628
+ template <typename TI>
1629
+ INLINE const double D (TI i) const { return 1; }
1630
+ };
1631
+
1632
+
1633
+
1634
+
1635
+
1636
+
1637
+
1638
+ /* ******************** Jacobi Polynomial (with fixed alpha, beta) ************ */
1639
+
1640
+ template <int al, int be>
1641
+ class JacobiPolynomialFix : public RecursivePolynomial<JacobiPolynomialFix<al,be> >
1642
+ {
1643
+ public:
1644
+ JacobiPolynomialFix () { ; }
1645
+
1646
+ template <class S, class T>
1647
+ inline JacobiPolynomialFix (int n, S x, T && values)
1648
+ {
1649
+ Eval (n, x, values);
1650
+ }
1651
+
1652
+ // typedef RecursivePolynomial<JacobiPolynomialFix<al,be> > BASE;
1653
+ // using BASE::EvalFO;
1654
+
1655
+ template <class S>
1656
+ static INLINE S P0(S x) { return S(1.0); }
1657
+ template <class S>
1658
+ // static INLINE S P1(S x) { return 0.5 * (2*(al+1)+(al+be+2)*(x-1)); }
1659
+ static INLINE S P1(S x) { return 0.5*(2*(al+1)-(al+be+2)) + 0.5*(al+be+2)*x; }
1660
+
1661
+ template <class S>
1662
+ // static INLINE S P1(S x, S y) { return 0.5 * (2*(al+1)*y+(al+be+2)*(x-y)); }
1663
+ static INLINE S P1(S x, S y) { return 0.5*(al+be+2)*x+0.5*(al-be)*y; }
1664
+
1665
+ static INLINE double CalcA (int i)
1666
+ { i--; return (2.0*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1667
+ static INLINE double CalcB (int i)
1668
+ { i--; return (2.0*i+al+be+1)*(al*al-be*be) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1669
+ static INLINE double CalcC (int i)
1670
+ { i--; return -2.0*(i+al)*(i+be) * (2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1671
+
1672
+ static INLINE double A (int i) { return CalcA (i); }
1673
+ static INLINE double B (int i) { return CalcB (i); }
1674
+ static INLINE double C (int i) { return CalcC (i); }
1675
+ };
1676
+
1677
+
1678
+
1679
+ class JacobiPolynomial2 : public RecursivePolynomialNonStatic<JacobiPolynomial2>
1680
+ {
1681
+ double al, be;
1682
+ public:
1683
+ JacobiPolynomial2 (double a, double b) : al(a), be(b) { ; }
1684
+
1685
+ template <class S, class T>
1686
+ inline JacobiPolynomial2 (int n, S x, double alpha, double beta, T && values)
1687
+ : al(alpha), be(beta)
1688
+ {
1689
+ Eval (n, x, values);
1690
+ }
1691
+
1692
+ template <class S>
1693
+ INLINE S P0(S x) const { return S(1.0); }
1694
+ template <class S>
1695
+ INLINE S P1(S x) const { return 0.5 * (2*(al+1)+(al+be+2)*(x-1)); }
1696
+ template <class S>
1697
+ INLINE S P1(S x, S y) const { return 0.5 * (2*(al+1)*y+(al+be+2)*(x-y)); }
1698
+
1699
+ INLINE double A (int i) const
1700
+ { i--; return (2.0*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1701
+ INLINE double B (int i) const
1702
+ { i--; return (2.0*i+al+be+1)*(al*al-be*be) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1703
+ INLINE double C (int i) const
1704
+ { i--; return -2.0*(i+al)*(i+be) * (2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1705
+ INLINE double D (int i) const { return 1; }
1706
+ };
1707
+
1708
+
1709
+
1710
+
1711
+ #ifdef __CUDACC__
1712
+ // __device__ Vec<3> * jacobialpha_coefs;
1713
+ extern __device__ double jacobialpha_coefs[100][100][4];
1714
+ extern __device__ int jacobialpha_maxn;
1715
+ #endif
1716
+
1717
+
1718
+ class JacobiPolynomialAlpha : public RecursivePolynomialNonStatic<JacobiPolynomialAlpha>
1719
+ {
1720
+ public:
1721
+ /*
1722
+ static Array< Vec<4> > coefs;
1723
+ static int maxnp;
1724
+ */
1725
+ static constexpr size_t maxnp = 128;
1726
+ static constexpr size_t maxalpha = 128;
1727
+ static Vec<4> coefs[maxnp*maxalpha];
1728
+ size_t n2;
1729
+ Vec<4> * coefsal;
1730
+ public:
1731
+ INLINE JacobiPolynomialAlpha (size_t a)
1732
+ {
1733
+ // offset = alpha*maxnp;
1734
+ coefsal = &coefs[a*maxnp];
1735
+ n2 = 2*maxnp;
1736
+ // coefsal = &jacobialpha_coefs[alpha*(jacobialpha_maxn+1)];
1737
+ }
1738
+
1739
+ template <class S, class T>
1740
+ INLINE JacobiPolynomialAlpha (int n, S x, int a, T && values)
1741
+ {
1742
+ // offset = alpha*(maxn+1);
1743
+ coefsal = &coefs[a*maxnp];
1744
+ n2 = 2*maxnp;
1745
+ Eval (n, x, values);
1746
+ }
1747
+
1748
+ void IncAlpha2 () { coefsal += n2; }
1749
+ static void Calc (int n, int maxalpha);
1750
+
1751
+ template <class S>
1752
+ INLINE double P0(S x) const { return 1.0; }
1753
+ template <class S>
1754
+ INLINE S P1(S x) const
1755
+ {
1756
+ return FMA (coefsal[1][0],x,S(coefsal[1][1]));
1757
+ }
1758
+ template <class S, class Sy>
1759
+ INLINE S P1(S x, Sy y) const
1760
+ {
1761
+ return FMA(coefsal[1][0],x,coefsal[1][1]*y);
1762
+ }
1763
+
1764
+
1765
+ template <typename TI>
1766
+ INLINE const double & A (TI i) const { return coefsal[i][0]; }
1767
+ template <typename TI>
1768
+ INLINE const double & B (TI i) const { return coefsal[i][1]; }
1769
+ template <typename TI>
1770
+ INLINE const double & C (TI i) const { return coefsal[i][2]; }
1771
+
1772
+ template <typename TI>
1773
+ INLINE void ABC (TI i, double & a, double & b, double & c) const
1774
+ {
1775
+ a = A(i);
1776
+ b = B(i);
1777
+ c = C(i);
1778
+ }
1779
+
1780
+ enum { ZERO_B = 0 };
1781
+
1782
+
1783
+ static INLINE double CalcA (int i, double al, double be)
1784
+ { i--; return (2.0*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1785
+ static INLINE double CalcB (int i, double al, double be)
1786
+ { i--; return (2.0*i+al+be+1)*(al*al-be*be) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1787
+ static INLINE double CalcC (int i, double al, double be)
1788
+ { i--; return -2.0*(i+al)*(i+be) * (2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1789
+
1790
+ static INLINE double D (int i) { return 1; }
1791
+ };
1792
+
1793
+
1794
+
1795
+ /*
1796
+ // see Beuchler+Schoeberl : New shape functions for trigs, formula (2.11)
1797
+ class IntJacobiPolynomialAlpha : public RecursivePolynomialNonStatic<IntJacobiPolynomialAlpha>
1798
+ {
1799
+ public:
1800
+ int alpha;
1801
+
1802
+ public:
1803
+ IntJacobiPolynomialAlpha (int a) : alpha(a)
1804
+ {
1805
+ ;
1806
+ }
1807
+
1808
+ template <class S, class T>
1809
+ inline IntJacobiPolynomialAlpha (int n, S x, int a, T && values)
1810
+ : alpha(a)
1811
+ {
1812
+ Eval (n, x, values);
1813
+ }
1814
+
1815
+ template <class S>
1816
+ INLINE double P0(S x) const { return 1.0; }
1817
+
1818
+ // d/dx ( (x+1) P1) = 0.5*(alpha+2) x + 0.5 * alpha;
1819
+ // (x+1) P1 = 0.25*(alpha+2) x^2 + 0.5 * alpha * x - 0.25*(alpha+2) (-1)^2 - 0.5*alpha*(-1)
1820
+ // = 0.25*(alpha+2) (x-1)*(x+1) + 0.5 * alpha (x+1)
1821
+ // P1 = 0.25*(alpha+2)(x-1) + 0.5 * alpha
1822
+
1823
+ template <class S>
1824
+ INLINE S P1(S x) const
1825
+ {
1826
+ return 0.25 * (alpha+2)*x + 0.25*(alpha-2);
1827
+ }
1828
+
1829
+ template <class S, class Sy>
1830
+ INLINE S P1(S x, Sy y) const
1831
+ {
1832
+ return 0.25 * (alpha+2)*x + 0.25*(alpha-2) * y;
1833
+ }
1834
+
1835
+ INLINE double A (int i) const { return CalcA (i, alpha, 0); }
1836
+ INLINE double B (int i) const { return CalcB (i, alpha, 0); }
1837
+ INLINE double C (int i) const { return CalcC (i, alpha, 0); }
1838
+
1839
+ enum { ZERO_B = 0 };
1840
+
1841
+ static double CalcA (int n, double al, double be)
1842
+ { return (2.0*n+al-1)*(2*n+al-2)*(2*n+al) / ( (2*n+2) * (n+al) * (2*n+al-2) ); }
1843
+ static double CalcB (int n, double al, double be)
1844
+ { return (2.0*n+al-1)*al * (al-2) / ( (2*n+2) * (n+al) * (2*n+al-2) ); }
1845
+ static double CalcC (int n, double al, double be)
1846
+ { return - 2*(n-1)*(n+al-2)*(2*n+al) / ( (2*n+2) * (n+al) * (2*n+al-2) ); }
1847
+
1848
+ INLINE double D (int i) const { return 1; }
1849
+ };
1850
+ */
1851
+
1852
+
1853
+
1854
+
1855
+ // see Beuchler+Schoeberl : New shape functions for trigs, formula (2.11)
1856
+ // \int_(-1)^x P^(alpha,0)(s) ds / (1-s)
1857
+ class IntegratedJacobiPolynomialAlpha : public RecursivePolynomialNonStatic<IntegratedJacobiPolynomialAlpha>
1858
+ {
1859
+ public:
1860
+ static Array< Vec<4> > coefs;
1861
+ int alpha;
1862
+ static int maxn;
1863
+ Vec<4> * coefsal;
1864
+
1865
+ public:
1866
+ IntegratedJacobiPolynomialAlpha (int a) : alpha(a)
1867
+ {
1868
+ coefsal = &coefs[alpha*(maxn+1)];
1869
+ }
1870
+
1871
+ template <class S, class T>
1872
+ inline IntegratedJacobiPolynomialAlpha (int n, S x, int a, T && values)
1873
+ : alpha(a)
1874
+ {
1875
+ coefsal = &coefs[alpha*(maxn+1)];
1876
+ Eval (n, x, values);
1877
+ }
1878
+
1879
+ static void Calc (int n, int maxalpha);
1880
+
1881
+ template <class S>
1882
+ INLINE double P0(S x) const { return 1.0; }
1883
+
1884
+ // d/dx ( (x+1) P1) = 0.5*(alpha+2) x + 0.5 * alpha;
1885
+ // (x+1) P1 = 0.25*(alpha+2) x^2 + 0.5 * alpha * x - 0.25*(alpha+2) (-1)^2 - 0.5*alpha*(-1)
1886
+ // = 0.25*(alpha+2) (x-1)*(x+1) + 0.5 * alpha (x+1)
1887
+ // P1 = 0.25*(alpha+2)(x-1) + 0.5 * alpha
1888
+
1889
+ template <class S>
1890
+ INLINE S P1(S x) const
1891
+ {
1892
+ return coefsal[1][0]*x+coefsal[1][1];
1893
+ // return 0.25 * (alpha+2)*x + 0.25*(alpha-2);
1894
+ }
1895
+
1896
+ template <class S, class Sy>
1897
+ INLINE S P1(S x, Sy y) const
1898
+ {
1899
+ return coefsal[1][0]*x+coefsal[1][1]*y;
1900
+ // return 0.25 * (alpha+2)*x + 0.25*(alpha-2) * y;
1901
+ }
1902
+
1903
+
1904
+ INLINE double A (int i) const { return coefsal[i][0]; }
1905
+ INLINE double B (int i) const { return coefsal[i][1]; }
1906
+ INLINE double C (int i) const { return coefsal[i][2]; }
1907
+ /*
1908
+ INLINE double A (int i) const { return CalcA (i, alpha, 0); }
1909
+ INLINE double B (int i) const { return CalcB (i, alpha, 0); }
1910
+ INLINE double C (int i) const { return CalcC (i, alpha, 0); }
1911
+ */
1912
+ enum { ZERO_B = 0 };
1913
+
1914
+ static double CalcA (int n, double al, double be)
1915
+ { return (2.0*n+al-1)*(2*n+al-2)*(2*n+al) / ( (2*n+2) * (n+al) * (2*n+al-2) ); }
1916
+ static double CalcB (int n, double al, double be)
1917
+ { return (2.0*n+al-1)*al * (al-2) / ( (2*n+2) * (n+al) * (2*n+al-2) ); }
1918
+ static double CalcC (int n, double al, double be)
1919
+ { return - 2*(n-1)*(n+al-2)*(2*n+al) / ( (2*n+2) * (n+al) * (2*n+al-2) ); }
1920
+
1921
+ INLINE double D (int i) const { return 1; }
1922
+ };
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1933
+ class JacobiPolynomialNew : public RecursivePolynomialNonStatic<JacobiPolynomialNew>
1934
+ {
1935
+ protected:
1936
+ double al, be;
1937
+
1938
+ public:
1939
+ INLINE JacobiPolynomialNew (double alpha, double beta) : al(alpha), be(beta) { ; }
1940
+
1941
+ template <class S>
1942
+ INLINE double P0(S x) const { return 1.0; }
1943
+ template <class S>
1944
+ INLINE S P1(S x) const
1945
+ {
1946
+ return 0.5 * (2*(al+1)+(al+be+2)*(x-1));
1947
+ }
1948
+ template <class S>
1949
+ INLINE S P1(S x, S y) const
1950
+ {
1951
+ return 0.5 * (2*(al+1)*y+(al+be+2)*(x-y));
1952
+ }
1953
+
1954
+ enum { ZERO_B = 0 };
1955
+
1956
+ INLINE double A (int i) const
1957
+ { i--; return (2.0*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1958
+ INLINE double B (int i) const
1959
+ { i--; return (2.0*i+al+be+1)*(al*al-be*be) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1960
+ INLINE double C (int i) const
1961
+ { i--; return -2.0*(i+al)*(i+be) * (2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1962
+
1963
+ INLINE double D (int i) const { return 1; }
1964
+ };
1965
+
1966
+
1967
+
1968
+
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+ /*
1975
+ class JacobiPolynomial2 : public RecursivePolynomial<JacobiPolynomial2>
1976
+ {
1977
+ double al, be;
1978
+ public:
1979
+ JacobiPolynomial2 (double aal, double abe) : al(aal), be(abe) { ; }
1980
+
1981
+ template <class S>
1982
+ S P0(S x) const { return S(1.0); }
1983
+ template <class S>
1984
+ S P1(S x) const { return 0.5 * (2*(al+1)+(al+be+2)*(x-1)); }
1985
+
1986
+ double A (int i) const
1987
+ { i--; return (2.0*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1988
+ double B (int i) const
1989
+ { i--; return (2.0*i+al+be+1)*(al*al-be*be) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1990
+ double C (int i) const
1991
+ { i--; return -2.0*(i+al)*(i+be) * (2*i+al+be+2) / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be)); }
1992
+ };
1993
+ */
1994
+
1995
+
1996
+
1997
+
1998
+
1999
+ template <class S, class Sc, class T>
2000
+ INLINE void LegendrePolynomialMult (int n, S x, Sc c , T && values)
2001
+ {
2002
+ LegendrePolynomial leg;
2003
+ leg.EvalMult (n, x, c, values);
2004
+ }
2005
+
2006
+
2007
+
2008
+
2009
+ template <class S, class T>
2010
+ inline void JacobiPolynomial (int n, S x, double alpha, double beta, T && values)
2011
+ {
2012
+ S p1(1.0), p2(0.0), p3;
2013
+
2014
+ if (n >= 0)
2015
+ values[0] = p2 = 1.0;
2016
+ if (n >= 1)
2017
+ values[1] = p1 = 0.5 * (2*(alpha+1)+(alpha+beta+2)*(x-1));
2018
+
2019
+ for (int i = 1; i < n; i++)
2020
+ {
2021
+ p3 = p2; p2=p1;
2022
+ p1 =
2023
+ 1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *
2024
+ (
2025
+ ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) +
2026
+ (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)
2027
+ * p2
2028
+ - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * p3
2029
+ );
2030
+ values[i+1] = p1;
2031
+ }
2032
+ }
2033
+
2034
+
2035
+
2036
+
2037
+
2038
+ template <class S, class Sc, class T>
2039
+ inline void JacobiPolynomialMult (int n, S x, double alpha, double beta, Sc c, T && values)
2040
+ {
2041
+ S p1 = c, p2(0.0), p3;
2042
+
2043
+ if (n >= 0)
2044
+ p2 = values[0] = c;
2045
+ if (n >= 1)
2046
+ p1 = values[1] = 0.5 * c * (2*(alpha+1)+(alpha+beta+2)*(x-1));
2047
+
2048
+ for (int i = 1; i < n; i++)
2049
+ {
2050
+ p3 = p2; p2=p1;
2051
+ p1 =
2052
+ 1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *
2053
+ (
2054
+ ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) +
2055
+ (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)
2056
+ * p2
2057
+ - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * p3
2058
+ );
2059
+ values[i+1] = p1;
2060
+ }
2061
+ }
2062
+
2063
+
2064
+
2065
+
2066
+
2067
+
2068
+
2069
+ template <class S, class St, class T>
2070
+ inline void ScaledJacobiPolynomial (int n, S x, St t, double alpha, double beta, T && values)
2071
+ {
2072
+ /*
2073
+ S p1 = 1.0, p2 = 0.0, p3;
2074
+
2075
+ if (n >= 0) values[0] = 1.0;
2076
+ */
2077
+
2078
+ S p1(1.0), p2(0.0), p3;
2079
+
2080
+ if (n >= 0)
2081
+ p2 = values[0] = 1.0;
2082
+ if (n >= 1)
2083
+ p1 = values[1] = 0.5 * (2*(alpha+1)*t+(alpha+beta+2)*(x-t));
2084
+
2085
+ for (int i=1; i < n; i++)
2086
+ {
2087
+ p3 = p2; p2=p1;
2088
+ p1 =
2089
+ 1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *
2090
+ (
2091
+ ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) * t +
2092
+ (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)
2093
+ * p2
2094
+ - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * t * t * p3
2095
+ );
2096
+ values[i+1] = p1;
2097
+ }
2098
+ }
2099
+
2100
+
2101
+
2102
+
2103
+
2104
+
2105
+ template <class S, class St, class Sc, class T>
2106
+ inline void ScaledJacobiPolynomialMult (int n, S x, St t, double alpha, double beta, Sc c, T && values)
2107
+ {
2108
+ /*
2109
+ S p1 = 1.0, p2 = 0.0, p3;
2110
+ if (n >= 0) values[0] = 1.0;
2111
+ */
2112
+
2113
+ S p1 = c, p2(0.0), p3;
2114
+
2115
+ if (n >= 0)
2116
+ p2 = values[0] = c;
2117
+ if (n >= 1)
2118
+ p1 = values[1] = 0.5 * c * (2*(alpha+1)*t+(alpha+beta+2)*(x-t));
2119
+
2120
+ for (int i=1; i < n; i++)
2121
+ {
2122
+ p3 = p2; p2=p1;
2123
+ p1 =
2124
+ 1.0 / ( 2 * (i+1) * (i+alpha+beta+1) * (2*i+alpha+beta) ) *
2125
+ (
2126
+ ( (2*i+alpha+beta+1)*(alpha*alpha-beta*beta) * t +
2127
+ (2*i+alpha+beta)*(2*i+alpha+beta+1)*(2*i+alpha+beta+2) * x)
2128
+ * p2
2129
+ - 2*(i+alpha)*(i+beta) * (2*i+alpha+beta+2) * t * t * p3
2130
+ );
2131
+ values[i+1] = p1;
2132
+ }
2133
+ }
2134
+
2135
+
2136
+
2137
+
2138
+
2139
+
2140
+
2141
+
2142
+
2143
+
2144
+
2145
+
2146
+
2147
+
2148
+
2149
+ template <int n, int i, int alpha0, int beta>
2150
+ class DubinerJacobiPolynomialsFO
2151
+ {
2152
+ public:
2153
+ template <class S, class T>
2154
+ static void Eval (S x, T && values)
2155
+ {
2156
+ DubinerJacobiPolynomialsFO<n, i-1, alpha0, beta>::Eval (x, values);
2157
+
2158
+ S p1, p2;
2159
+ CEvalFO<JacobiPolynomialFix<alpha0+2*i, beta>, n-i>::Eval (x, values.Row(i), p1, p2);
2160
+
2161
+ // why not ???
2162
+ // JacobiPolynomialFix<alpha0+2*i, beta>::EvalFO<n-i> (x, values.Row(i));
2163
+
2164
+
2165
+ // typedef JacobiPolynomialFix<alpha0+2*i, beta> JAC;
2166
+ // JAC::EvalFO<n-i> (x, values.Row(i));
2167
+ // JacobiPolynomialFix<1,2>::EvalFO<n-i> (hx, hmat.Row(i));
2168
+ }
2169
+
2170
+
2171
+ template <class S, class St, class T>
2172
+ static void EvalScaled (S x, St t, T && values)
2173
+ {
2174
+ DubinerJacobiPolynomialsFO<n, i-1, alpha0, beta>::EvalScaled (x, t, values);
2175
+ // JacobiPolynomialFO<n-i, alpha0+2*i, beta>::Eval (x, values.Row(i));
2176
+
2177
+ JacobiPolynomialFix<alpha0+2*i, beta> jac;
2178
+ S p1, p2;
2179
+ CEvalFO<JacobiPolynomialFix<alpha0+2*i, beta>, n-i>::EvalScaled (x, t, values.Row(i), p1, p2);
2180
+ }
2181
+ };
2182
+
2183
+ template <int n, int alpha0, int beta>
2184
+ class DubinerJacobiPolynomialsFO<n, -1, alpha0, beta>
2185
+ {
2186
+ public:
2187
+ template <class S, class T>
2188
+ static void Eval (S x, T && values)
2189
+ { ; }
2190
+ template <class S, class St, class T>
2191
+ static void EvalScaled (S x, St t, T && values)
2192
+ { ; }
2193
+ };
2194
+
2195
+
2196
+
2197
+
2198
+ template <int n, int i, int alpha0, int beta>
2199
+ class DubinerJacobiPolynomialsPowFO
2200
+ {
2201
+ public:
2202
+ template <class S, class T>
2203
+ static S Eval (S x, T && values)
2204
+ {
2205
+ S power = DubinerJacobiPolynomialsPowFO<n, i-1, alpha0, beta>::Eval (x, values);
2206
+ S p1, p2;
2207
+ CEvalFO<JacobiPolynomialFix<alpha0+2*i, beta>, n-i>::EvalMult (x, power, values.Row(i), p1, p2);
2208
+ return power * (1.0-x)*0.5;
2209
+ }
2210
+
2211
+
2212
+ template <class S, class St, class T>
2213
+ static S EvalScaled (S x, St t, T && values)
2214
+ {
2215
+ S power = DubinerJacobiPolynomialsPowFO<n, i-1, alpha0, beta>::EvalScaled (x, t, values);
2216
+ S p1, p2;
2217
+ CEvalFO<JacobiPolynomialFix<alpha0+2*i, beta>, n-i>::EvalScaledMult (x, t, power, values.Row(i), p1, p2);
2218
+ return power * (1.0-x)*0.5;
2219
+ }
2220
+ };
2221
+
2222
+ template <int n, int alpha0, int beta>
2223
+ class DubinerJacobiPolynomialsPowFO<n, -1, alpha0, beta>
2224
+ {
2225
+ public:
2226
+ template <class S, class T>
2227
+ static S Eval (S x, T && values)
2228
+ { return 1.0; }
2229
+ template <class S, class St, class T>
2230
+ static S EvalScaled (S x, St t, T && values)
2231
+ { return 1.0; }
2232
+ };
2233
+
2234
+
2235
+
2236
+
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+
2244
+
2245
+
2246
+
2247
+
2248
+
2249
+ #ifdef OLD
2250
+ template <int ALPHA0, int BETA, class S, class T>
2251
+ void DubinerJacobiPolynomials2 (int n, S x, T && values)
2252
+ {
2253
+ switch (n)
2254
+ {
2255
+ case 0: DubinerJacobiPolynomialsFO<0, 0, ALPHA0, BETA>::Eval (x, values); break;
2256
+ case 1: DubinerJacobiPolynomialsFO<1, 1, ALPHA0, BETA>::Eval (x, values); break;
2257
+ case 2: DubinerJacobiPolynomialsFO<2, 2, ALPHA0, BETA>::Eval (x, values); break;
2258
+ case 3: DubinerJacobiPolynomialsFO<3, 3, ALPHA0, BETA>::Eval (x, values); break;
2259
+ case 4: DubinerJacobiPolynomialsFO<4, 4, ALPHA0, BETA>::Eval (x, values); break;
2260
+ case 5: DubinerJacobiPolynomialsFO<5, 5, ALPHA0, BETA>::Eval (x, values); break;
2261
+ case 6: DubinerJacobiPolynomialsFO<6, 6, ALPHA0, BETA>::Eval (x, values); break;
2262
+ case 7: DubinerJacobiPolynomialsFO<7, 7, ALPHA0, BETA>::Eval (x, values); break;
2263
+ case 8: DubinerJacobiPolynomialsFO<8, 8, ALPHA0, BETA>::Eval (x, values); break;
2264
+ case 9: DubinerJacobiPolynomialsFO<9, 9, ALPHA0, BETA>::Eval (x, values); break;
2265
+ case 10: DubinerJacobiPolynomialsFO<10, 10, ALPHA0, BETA>::Eval (x, values); break;
2266
+ default: DubinerJacobiPolynomials1 (n, x, ALPHA0, BETA, values);
2267
+ }
2268
+ }
2269
+ #endif
2270
+
2271
+
2272
+
2273
+
2274
+
2275
+ // compute J_j^{2i+alpha0, beta} (x), for i+j <= n
2276
+
2277
+ template <class S, class T>
2278
+ void DubinerJacobiPolynomials1 (int n, S x, int alpha0, int beta, T && values)
2279
+ {
2280
+ for (int i = 0; i <= n; i++)
2281
+ JacobiPolynomial (n-i, x, alpha0+2*i, beta, values.Row(i));
2282
+ }
2283
+
2284
+
2285
+ template <class S, class St, class T>
2286
+ void DubinerJacobiPolynomialsScaled1 (int n, S x, St t, int alpha0, int beta, T && values)
2287
+ {
2288
+ for (int i = 0; i <= n; i++)
2289
+ ScaledJacobiPolynomial (n-i, x, t, alpha0+2*i, beta, values.Row(i));
2290
+ }
2291
+
2292
+
2293
+
2294
+
2295
+
2296
+
2297
+
2298
+ template <int ALPHA0, int BETA, int DIAG, int ORDER = DIAG>
2299
+ class DubinerJacobiPolynomialsDiag
2300
+ {
2301
+ public:
2302
+ template<class S, class Thelp, class T>
2303
+ INLINE static void Step (S x, Thelp & help, T & values)
2304
+ {
2305
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, DIAG, ORDER-1>::Step (x, help, values);
2306
+ typedef JacobiPolynomialFix<ALPHA0+2*(DIAG-ORDER), BETA> REC;
2307
+
2308
+ if (ORDER == 0)
2309
+ help[DIAG-ORDER][0] = REC::P0(x);
2310
+ else if (ORDER == 1)
2311
+ {
2312
+ help[DIAG-ORDER][0] = REC::P1(x);
2313
+ help[DIAG-ORDER][1] = REC::P0(x);
2314
+ }
2315
+ else
2316
+ {
2317
+ Swap (help[DIAG-ORDER][0], help[DIAG-ORDER][1]);
2318
+ REC::EvalNextTicTac (ORDER, x, help[DIAG-ORDER][0], help[DIAG-ORDER][1]);
2319
+ }
2320
+ values(DIAG-ORDER, ORDER) = help[DIAG-ORDER][0];
2321
+ }
2322
+ };
2323
+
2324
+ template <int ALPHA0, int BETA, int DIAG>
2325
+ class DubinerJacobiPolynomialsDiag<ALPHA0, BETA, DIAG, -1>
2326
+ {
2327
+ public:
2328
+ template<class S, class Thelp, class T>
2329
+ INLINE static void Step (S x, Thelp & help, T & values) {;}
2330
+ };
2331
+
2332
+
2333
+ template <int ALPHA0, int BETA, class S, class T>
2334
+ void DubinerJacobiPolynomials (int n, S x, T && values)
2335
+ {
2336
+ S help[20][2];
2337
+ if (n < 0) return;
2338
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 0>::Step (x, help, values);
2339
+
2340
+ if (n < 1) return;
2341
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 1>::Step (x, help, values);
2342
+
2343
+ if (n < 2) return;
2344
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 2>::Step (x, help, values);
2345
+
2346
+ if (n < 3) return;
2347
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 3>::Step (x, help, values);
2348
+
2349
+ if (n < 4) return;
2350
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 4>::Step (x, help, values);
2351
+
2352
+ if (n < 5) return;
2353
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 5>::Step (x, help, values);
2354
+
2355
+ if (n < 6) return;
2356
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 6>::Step (x, help, values);
2357
+
2358
+ if (n < 7) return;
2359
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 7>::Step (x, help, values);
2360
+
2361
+ if (n < 8) return;
2362
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 8>::Step (x, help, values);
2363
+
2364
+ if (n < 9) return;
2365
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 9>::Step (x, help, values);
2366
+
2367
+ if (n < 10) return;
2368
+ DubinerJacobiPolynomialsDiag<ALPHA0, BETA, 10>::Step (x, help, values);
2369
+
2370
+ if (n < 11) return;
2371
+
2372
+ DubinerJacobiPolynomials1 (n, x, ALPHA0, BETA, values);
2373
+ }
2374
+
2375
+
2376
+
2377
+
2378
+
2379
+
2380
+
2381
+
2382
+
2383
+
2384
+
2385
+
2386
+
2387
+ template <int ALPHA0, int BETA, int DIAG, int ORDER = DIAG>
2388
+ class DubinerJacobiPolynomialsScaledDiag
2389
+ {
2390
+ public:
2391
+ template<class S, class St, class Thelp, class T>
2392
+ INLINE static void Step (S x, St t, Thelp & help, T & values)
2393
+ {
2394
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, DIAG, ORDER-1>::Step (x, t, help, values);
2395
+ typedef JacobiPolynomialFix<ALPHA0+2*(DIAG-ORDER), BETA> REC;
2396
+
2397
+ if (ORDER == 0)
2398
+ help[DIAG-ORDER][0] = REC::P0(x);
2399
+ else if (ORDER == 1)
2400
+ {
2401
+ help[DIAG-ORDER][0] = REC::P1(x,t);
2402
+ help[DIAG-ORDER][1] = REC::P0(x);
2403
+ }
2404
+ else
2405
+ {
2406
+ REC::EvalScaledNext (ORDER, x, t, help[DIAG-ORDER][0], help[DIAG-ORDER][1]);
2407
+ }
2408
+ values(DIAG-ORDER, ORDER) = help[DIAG-ORDER][0];
2409
+ }
2410
+ };
2411
+
2412
+ template <int ALPHA0, int BETA, int DIAG>
2413
+ class DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, DIAG, -1>
2414
+ {
2415
+ public:
2416
+ template<class S, class St, class Thelp, class T>
2417
+ INLINE static void Step (S x, St t, Thelp & help, T & values) {;}
2418
+ };
2419
+
2420
+
2421
+ template <int ALPHA0, int BETA, class S, class St, class T>
2422
+ void DubinerJacobiPolynomialsScaled (int n, S x, St t, T && values)
2423
+ {
2424
+ S help[20][2];
2425
+ if (n < 0) return;
2426
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 0>::Step (x, t, help, values);
2427
+
2428
+ if (n < 1) return;
2429
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 1>::Step (x, t, help, values);
2430
+
2431
+ if (n < 2) return;
2432
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 2>::Step (x, t, help, values);
2433
+
2434
+ if (n < 3) return;
2435
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 3>::Step (x, t, help, values);
2436
+
2437
+ if (n < 4) return;
2438
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 4>::Step (x, t, help, values);
2439
+
2440
+ if (n < 5) return;
2441
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 5>::Step (x, t, help, values);
2442
+
2443
+ if (n < 6) return;
2444
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 6>::Step (x, t, help, values);
2445
+
2446
+ if (n < 7) return;
2447
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 7>::Step (x, t, help, values);
2448
+
2449
+ if (n < 8) return;
2450
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 8>::Step (x, t, help, values);
2451
+
2452
+ if (n < 9) return;
2453
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 9>::Step (x, t, help, values);
2454
+
2455
+ if (n < 10) return;
2456
+ DubinerJacobiPolynomialsScaledDiag<ALPHA0, BETA, 10>::Step (x, t, help, values);
2457
+
2458
+ if (n < 11) return;
2459
+
2460
+ DubinerJacobiPolynomialsScaled1 (n, x, t, ALPHA0, BETA, values);
2461
+ }
2462
+
2463
+
2464
+
2465
+
2466
+
2467
+
2468
+
2469
+
2470
+
2471
+
2472
+ inline int TrigIndex(int i, int j, int n)
2473
+ {
2474
+ return j + i*(2*n+3-i)/2;
2475
+ }
2476
+
2477
+
2478
+
2479
+ template <int ALPHA0, int BETA, int DIAG, int ORDER = DIAG>
2480
+ class DubinerJacobiPolynomialsDiag_Linear
2481
+ {
2482
+ public:
2483
+ template<class S, class Thelp, class T>
2484
+ INLINE static void Step (S x, Thelp & help, T & values)
2485
+ {
2486
+ DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, DIAG, ORDER-1>::Step (x, help, values);
2487
+ typedef JacobiPolynomialFix<ALPHA0+2*(DIAG-ORDER), BETA> REC;
2488
+
2489
+
2490
+ if (ORDER == 0)
2491
+ help(DIAG-ORDER,0) *= REC::P0(x);
2492
+ else if (ORDER == 1)
2493
+ {
2494
+ help(DIAG-ORDER,1) = help(DIAG-ORDER,0);
2495
+ help(DIAG-ORDER,0) *= REC::P1(x) / REC::P0(x);
2496
+ }
2497
+ else
2498
+ {
2499
+ Swap (help(DIAG-ORDER,0), help(DIAG-ORDER,1));
2500
+ REC::EvalNextTicTac (ORDER, x, help(DIAG-ORDER,0), help(DIAG-ORDER,1));
2501
+ }
2502
+ values[TrigIndex(ORDER,DIAG-ORDER,help.Height()-1)] = help(DIAG-ORDER,0);
2503
+
2504
+
2505
+ /*
2506
+ .// hat aber nichts gebracht ...
2507
+ if (ORDER == 0)
2508
+ help(DIAG-ORDER,0) *= REC::P0(x);
2509
+ else if (ORDER == 1)
2510
+ {
2511
+ // help(DIAG-ORDER,1) = help(DIAG-ORDER,0);
2512
+ help(DIAG-ORDER,1) = REC::P1(x) / REC::P0(x) * help(DIAG-ORDER,0);
2513
+ }
2514
+ else
2515
+ {
2516
+ // Swap (help(DIAG-ORDER,0), help(DIAG-ORDER,1));
2517
+ if ( ((DIAG-ORDER) % 2) == 0 )
2518
+ REC::EvalNext (ORDER, x, help(DIAG-ORDER,0), help(DIAG-ORDER,1));
2519
+ else
2520
+ REC::EvalNext (ORDER, x, help(DIAG-ORDER,1), help(DIAG-ORDER,0));
2521
+ }
2522
+ if ( (DIAG-ORDER) % 2 )
2523
+ values[TrigIndex(ORDER,DIAG-ORDER,help.Height()-1)] = help(DIAG-ORDER,1);
2524
+ else
2525
+ values[TrigIndex(ORDER,DIAG-ORDER,help.Height()-1)] = help(DIAG-ORDER,0);
2526
+ */
2527
+ }
2528
+ };
2529
+
2530
+ template <int ALPHA0, int BETA, int DIAG>
2531
+ class DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, DIAG, -1>
2532
+ {
2533
+ public:
2534
+ template<class S, class Thelp, class T>
2535
+ INLINE static void Step (S x, Thelp & help, T & values) {;}
2536
+ };
2537
+
2538
+
2539
+ template<class S, class Thelp, class T>
2540
+ void DubinerJacobiPolynomialsDiag_Linear1 (double alpha0, double beta0,
2541
+ int diag, S x, Thelp & help, T & values)
2542
+ {
2543
+ for (int order = 0; order <= diag; order++)
2544
+ {
2545
+ double al = alpha0 + 2*(diag-order);
2546
+ double be = beta0;
2547
+
2548
+ if (order == 0)
2549
+ help(diag-order,0) *= 1; // REC::P0(x);
2550
+ else if (order == 1)
2551
+ {
2552
+ help(diag-order,1) = help(diag-order,0);
2553
+ help(diag-order,0) *= 0.5 * (2*(al+1)+(al+be+2)*(x-1));
2554
+ }
2555
+ else
2556
+ {
2557
+ // REC::EvalNext (ORDER, x, help(DIAG-ORDER,0), help(DIAG-ORDER,1));
2558
+ // S pnew = (REC::A(i) * x + REC::B(i)) * p1 + REC::C(i) * p2;
2559
+
2560
+ S p1 = help(diag-order,0);
2561
+ S p2 = help(diag-order,1);
2562
+
2563
+ int i = order-1;
2564
+ S pnew =
2565
+ 1.0 / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be) ) *
2566
+ (
2567
+ ( (2*i+al+be+1)*(al*al-be*be) +
2568
+ (2*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) * x)
2569
+ * p1
2570
+ - 2*(i+al)*(i+be) * (2*i+al+be+2) * p2
2571
+ );
2572
+
2573
+ help(diag-order,0) = pnew;
2574
+ help(diag-order,1) = p1;
2575
+ }
2576
+ values[TrigIndex(order,diag-order,help.Height()-1)] = help(diag-order,0);
2577
+
2578
+ }
2579
+ }
2580
+
2581
+ template <int ALPHA0, int BETA, class S, class Sy, class Sc, class T>
2582
+ void DubinerJacobiPolynomials_Linear (int n, S x, Sy y, Sc c, T & values)
2583
+ {
2584
+ ArrayMem<S,40> hmem(2*(n+1));
2585
+ FlatMatrixFixWidth<2,S> help(n+1, &hmem[0]);
2586
+
2587
+ LegendrePolynomial leg;
2588
+ leg.EvalScaledMult (n, 2*y+x-1, 1-x, c, help.Col(0));
2589
+
2590
+ x = 2*x-1;
2591
+ if (n >= 0) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 0>::Step (x, help, values);
2592
+ if (n >= 1) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 1>::Step (x, help, values);
2593
+ if (n >= 2) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 2>::Step (x, help, values);
2594
+ if (n >= 3) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 3>::Step (x, help, values);
2595
+ if (n >= 4) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 4>::Step (x, help, values);
2596
+ if (n >= 5) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 5>::Step (x, help, values);
2597
+ if (n >= 6) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 6>::Step (x, help, values);
2598
+ if (n >= 7) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 7>::Step (x, help, values);
2599
+ if (n >= 8) DubinerJacobiPolynomialsDiag_Linear<ALPHA0, BETA, 8>::Step (x, help, values);
2600
+
2601
+ for (int i = 9; i <= n; i++)
2602
+ DubinerJacobiPolynomialsDiag_Linear1 (ALPHA0, BETA, i, x, help, values);
2603
+ }
2604
+
2605
+
2606
+
2607
+
2608
+
2609
+
2610
+
2611
+
2612
+
2613
+ template <int ALPHA0, int BETA, int DIAG, int ORDER = DIAG>
2614
+ class DubinerJacobiPolynomialsScaledDiag_Linear
2615
+ {
2616
+ public:
2617
+ template<class S, class St, class Thelp, class T>
2618
+ INLINE static void Step (S x, St t, Thelp & help, T & values)
2619
+ {
2620
+ DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, DIAG, ORDER-1>::Step (x, t, help, values);
2621
+ typedef JacobiPolynomialFix<ALPHA0+2*(DIAG-ORDER), BETA> REC;
2622
+
2623
+ if (ORDER == 0)
2624
+ help(DIAG-ORDER,0) *= REC::P0(x);
2625
+ else if (ORDER == 1)
2626
+ {
2627
+ help(DIAG-ORDER,1) = help(DIAG-ORDER,0);
2628
+ help(DIAG-ORDER,0) *= REC::P1(x,t) / REC::P0(x);
2629
+ }
2630
+ else
2631
+ {
2632
+ REC::EvalScaledNext (ORDER, x, t, help(DIAG-ORDER,0), help(DIAG-ORDER,1));
2633
+ }
2634
+ values[TrigIndex(ORDER,DIAG-ORDER,help.Height()-1)] = help(DIAG-ORDER,0);
2635
+ }
2636
+ };
2637
+
2638
+ template <int ALPHA0, int BETA, int DIAG>
2639
+ class DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, DIAG, -1>
2640
+ {
2641
+ public:
2642
+ template<class S, class St, class Thelp, class T>
2643
+ INLINE static void Step (S x, St t, Thelp & help, T & values) {;}
2644
+ };
2645
+
2646
+
2647
+ template<class S, class St, class Thelp, class T>
2648
+ void DubinerJacobiPolynomialsScaledDiag_Linear1 (double alpha0, double beta0,
2649
+ int diag, S x, St t, Thelp & help, T & values)
2650
+ {
2651
+ for (int order = 0; order <= diag; order++)
2652
+ {
2653
+ double al = alpha0 + 2*(diag-order);
2654
+ double be = beta0;
2655
+
2656
+ if (order == 0)
2657
+ help(diag-order,0) *= 1; // REC::P0(x);
2658
+ else if (order == 1)
2659
+ {
2660
+ help(diag-order,1) = help(diag-order,0);
2661
+ help(diag-order,0) *= 0.5 * (2*(al+1)+(al+be+2)*(x-1));
2662
+ }
2663
+ else
2664
+ {
2665
+ S p1 = help(diag-order,0);
2666
+ S p2 = help(diag-order,1);
2667
+
2668
+ int i = order-1;
2669
+ S pnew =
2670
+ 1.0 / ( 2 * (i+1) * (i+al+be+1) * (2*i+al+be) ) *
2671
+ (
2672
+ ( (2*i+al+be+1)*(al*al-be*be) * t +
2673
+ (2*i+al+be)*(2*i+al+be+1)*(2*i+al+be+2) * x)
2674
+ * p1
2675
+ - 2*(i+al)*(i+be) * (2*i+al+be+2) * t*t*p2
2676
+ );
2677
+
2678
+ help(diag-order,0) = pnew;
2679
+ help(diag-order,1) = p1;
2680
+ }
2681
+ values[TrigIndex(order,diag-order,help.Height()-1)] = help(diag-order,0);
2682
+
2683
+ }
2684
+ }
2685
+
2686
+ template <int ALPHA0, int BETA, class S, class Sy, class Sc, class St, class T>
2687
+ void DubinerJacobiPolynomialsScaled_Linear (int n, S x, Sy y, St t, Sc c, T & values)
2688
+ {
2689
+ ArrayMem<S,40> hmem(2*(n+1));
2690
+ FlatMatrixFixWidth<2,S> help(n+1, &hmem[0]);
2691
+
2692
+ LegendrePolynomial leg;
2693
+ leg.EvalScaledMult (n, 2*y+x-1, t-x, c, help.Col(0));
2694
+
2695
+ x = 2*x-1;
2696
+ if (n >= 0) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 0>::Step (x, t, help, values);
2697
+ if (n >= 1) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 1>::Step (x, t, help, values);
2698
+ if (n >= 2) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 2>::Step (x, t, help, values);
2699
+ if (n >= 3) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 3>::Step (x, t, help, values);
2700
+ if (n >= 4) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 4>::Step (x, t, help, values);
2701
+ if (n >= 5) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 5>::Step (x, t, help, values);
2702
+ if (n >= 6) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 6>::Step (x, t, help, values);
2703
+ if (n >= 7) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 7>::Step (x, t, help, values);
2704
+ if (n >= 8) DubinerJacobiPolynomialsScaledDiag_Linear<ALPHA0, BETA, 8>::Step (x, t, help, values);
2705
+
2706
+ for (int i = 9; i <= n; i++)
2707
+ DubinerJacobiPolynomialsScaledDiag_Linear1 (ALPHA0, BETA, i, x, t, help, values);
2708
+ }
2709
+
2710
+
2711
+
2712
+ /*
2713
+ class DubinerBasis
2714
+ {
2715
+ public:
2716
+ template <class S, class T>
2717
+ static void Eval (int n, S x, S y, T && values)
2718
+ {
2719
+ EvalMult (n, x, y, 1.0, values);
2720
+ }
2721
+
2722
+ template <class S, class Sc, class T>
2723
+ static void EvalMult (int n, S x, S y, Sc c, T && values)
2724
+ {
2725
+ DubinerJacobiPolynomials_Linear<1,0> (n, x, y, c, values);
2726
+ }
2727
+
2728
+ template <class S, class St, class Sc, class T>
2729
+ static void EvalScaledMult (int n, S x, S y, St t, Sc c, T && values)
2730
+ {
2731
+ DubinerJacobiPolynomialsScaled_Linear<1,0> (n, x, y, t, c, values);
2732
+ }
2733
+ };
2734
+ */
2735
+
2736
+
2737
+
2738
+
2739
+ class DubinerBasis
2740
+ {
2741
+ public:
2742
+ template <typename TI, class S, class T>
2743
+ INLINE static void Eval (TI n, S x, S y, T && values)
2744
+ {
2745
+ EvalMult (n, x, y, 1, values);
2746
+ }
2747
+
2748
+ template <typename TI, class S, class Sc, class T>
2749
+ INLINE static void EvalMult (TI n, S x, S y, Sc c, T && values)
2750
+ {
2751
+ LegendrePolynomial leg;
2752
+ TI ii = 0;
2753
+ JacobiPolynomialAlpha jac(1);
2754
+ leg.EvalScaledMult1Assign (n, y-(1-x-y), 1-x, c,
2755
+ SBLambda ([&] (TI i, S val) LAMBDA_INLINE
2756
+ {
2757
+ jac.EvalMult (n-i, 2*x-1, val, values+ii);
2758
+ ii += n-i+1;
2759
+ jac.IncAlpha2();
2760
+ }));
2761
+ }
2762
+
2763
+ template <class S, class Sc, class T>
2764
+ INLINE static void EvalScaled (int n, S x, S y, Sc t, T && values)
2765
+ {
2766
+ EvalScaledMult (n, x, y, t, 1, values);
2767
+ }
2768
+
2769
+ template <class S, class St, class Sc, class T>
2770
+ INLINE static void EvalScaledMult (int n, S x, S y, St t, Sc c, T && values)
2771
+ {
2772
+ LegendrePolynomial leg;
2773
+ int ii = 0;
2774
+ leg.EvalScaledMult1Assign (n, y-(t-x-y), t-x, c,
2775
+ SBLambda ([&] (int i, S val) LAMBDA_INLINE // clang
2776
+ {
2777
+ JacobiPolynomialAlpha jac(1+2*i);
2778
+ jac.EvalScaledMult1Assign (n-i, 2*x-t, t, val, values+ii);
2779
+ ii += n-i+1;
2780
+ }));
2781
+ }
2782
+
2783
+
2784
+ // evaluate basis functions of hightest order only
2785
+ template <typename TI, class S, class T>
2786
+ INLINE static void EvalHighestOrder (TI n, S x, S y, T && values)
2787
+ {
2788
+ EvalHighestOrderMult (n, x, y, 1, values);
2789
+ }
2790
+
2791
+ template <typename TI, class S, class Sc, class T>
2792
+ INLINE static void EvalHighestOrderMult (TI n, S x, S y, Sc c, T && values)
2793
+ {
2794
+ LegendrePolynomial leg;
2795
+ TI ii = 0;
2796
+ JacobiPolynomialAlpha jac(1);
2797
+ leg.EvalScaledMult1Assign (n, y-(1-x-y), 1-x, c,
2798
+ SBLambda ([&] (TI i, S val) LAMBDA_INLINE
2799
+ {
2800
+ values[ii++] = jac.CalcHighestOrderMult(n-i, 2*x-1, val);
2801
+ jac.IncAlpha2();
2802
+ }));
2803
+ }
2804
+
2805
+ };
2806
+
2807
+
2808
+ // orthogonal w.r.t. cubic bubble
2809
+ class DubinerBasisOrthoBub
2810
+ {
2811
+ public:
2812
+ template <typename TI, class S, class T>
2813
+ INLINE static void Eval (TI n, S x, S y, T && values)
2814
+ {
2815
+ EvalMult (n, x, y, 1, values);
2816
+ }
2817
+
2818
+ template <typename TI, class S, class Sc, class T>
2819
+ INLINE static void EvalMult (TI n, S x, S y, Sc c, T && values)
2820
+ {
2821
+ JacobiPolynomialFix<1,1> leg;
2822
+ TI ii = 0;
2823
+ leg.EvalScaledMult1Assign (n, y-(1-x-y), 1-x, c,
2824
+ SBLambda ([&] (TI i, S val) LAMBDA_INLINE
2825
+ {
2826
+ IntegratedJacobiPolynomialAlpha jac(4+2*i);
2827
+ jac.EvalMult (n-i, 2*x-1, val, values+ii);
2828
+ ii += n-i+1;
2829
+ }));
2830
+ }
2831
+
2832
+ template <class S, class Sc, class T>
2833
+ INLINE static void EvalScaled (int n, S x, S y, Sc t, T && values)
2834
+ {
2835
+ EvalScaledMult (n, x, y, t, 1, values);
2836
+ }
2837
+
2838
+ template <class S, class St, class Sc, class T>
2839
+ INLINE static void EvalScaledMult (int n, S x, S y, St t, Sc c, T && values)
2840
+ {
2841
+ JacobiPolynomialFix<1,1> leg;
2842
+ int ii = 0;
2843
+ leg.EvalScaledMult1Assign (n, y-(t-x-y), t-x, c,
2844
+ SBLambda ([&] (int i, S val) LAMBDA_INLINE // clang
2845
+ {
2846
+ IntegratedJacobiPolynomialAlpha jac(4+2*i);
2847
+ jac.EvalScaledMult1Assign (n-i, 2*x-t, t, val, values+ii);
2848
+ ii += n-i+1;
2849
+ }));
2850
+ }
2851
+
2852
+
2853
+ template <class T>
2854
+ static size_t CalcNormInv (size_t n, T && norminv)
2855
+ {
2856
+ size_t ii = 0;
2857
+ for (size_t i = 0; i <= n; i++)
2858
+ for (size_t j = 0; j <= n-i; j++)
2859
+ norminv[ii++] =
2860
+ 0.5 * (5+2*i+2*j)*(4+2*i+j)*(j+1) * (2*i+3)*(2*i+4) / (i+1);
2861
+ return ii;
2862
+ }
2863
+
2864
+
2865
+ /*
2866
+ // evaluate basis functions of hightest order only
2867
+ template <typename TI, class S, class T>
2868
+ INLINE static void EvalHighestOrder (TI n, S x, S y, T && values)
2869
+ {
2870
+ EvalHighestOrderMult (n, x, y, 1, values);
2871
+ }
2872
+
2873
+ template <typename TI, class S, class Sc, class T>
2874
+ INLINE static void EvalHighestOrderMult (TI n, S x, S y, Sc c, T && values)
2875
+ {
2876
+ LegendrePolynomial leg;
2877
+ TI ii = 0;
2878
+ JacobiPolynomialAlpha jac(1);
2879
+ leg.EvalScaledMult1Assign (n, y-(1-x-y), 1-x, c,
2880
+ SBLambda ([&] (TI i, S val) LAMBDA_INLINE
2881
+ {
2882
+ values[ii++] = jac.CalcHighestOrderMult(n-i, 2*x-1, val);
2883
+ jac.IncAlpha2();
2884
+ }));
2885
+ }
2886
+ */
2887
+ };
2888
+
2889
+
2890
+
2891
+ class DubinerBasis3D
2892
+ {
2893
+ public:
2894
+ template <typename TI, class S, class T>
2895
+ INLINE static void Eval (TI n, S x, S y, S z, T && values)
2896
+ {
2897
+ EvalMult (n, x, y, z, 1, values);
2898
+ }
2899
+
2900
+ template <typename TI, class S, class Sc, class T>
2901
+ INLINE static void EvalMult (TI n, S x, S y, S z, Sc c, T && values)
2902
+ {
2903
+ size_t ii = 0;
2904
+ S lam4 = 1.0 - x-y-z;
2905
+ LegendrePolynomial leg;
2906
+ JacobiPolynomialAlpha jac1(1);
2907
+ leg.EvalScaledMult1Assign
2908
+ (n, z-lam4, z+lam4, c,
2909
+ SBLambda ([&](size_t k, S polz) LAMBDA_INLINE
2910
+ {
2911
+ // JacobiPolynomialAlpha jac(2*k+1);
2912
+ JacobiPolynomialAlpha jac2(2*k+2);
2913
+
2914
+ jac1.EvalScaledMult1Assign
2915
+ (n-k, y-z-lam4, 1-x, polz,
2916
+ SBLambda ([&] (size_t j, S polsy) LAMBDA_INLINE
2917
+ {
2918
+ jac2.EvalMult1Assign(n-k-j, 2*x - 1, polsy, values+ii);
2919
+ ii += n-k-j+1;
2920
+ jac2.IncAlpha2();
2921
+ }));
2922
+ jac1.IncAlpha2();
2923
+ }));
2924
+ }
2925
+
2926
+
2927
+ // evaluate basis functions of hightest order only
2928
+ template <typename TI, class S, class T>
2929
+ INLINE static void EvalHighestOrder (TI n, S x, S y, S z, T && values)
2930
+ {
2931
+ EvalHighestOrderMult (n, x, y, z, 1, values);
2932
+ }
2933
+
2934
+ template <typename TI, class S, class Sc, class T>
2935
+ INLINE static void EvalHighestOrderMult (TI n, S x, S y, S z, Sc c, T && values)
2936
+ {
2937
+ size_t ii = 0;
2938
+ S lam4 = 1.0 - x-y-z;
2939
+ LegendrePolynomial leg;
2940
+ JacobiPolynomialAlpha jac1(1);
2941
+ leg.EvalScaledMult1Assign
2942
+ (n, z-lam4, z+lam4, c,
2943
+ SBLambda ([&](size_t k, S polz) LAMBDA_INLINE
2944
+ {
2945
+ JacobiPolynomialAlpha jac2(2*k+2);
2946
+
2947
+ jac1.EvalScaledMult1Assign
2948
+ (n-k, y-z-lam4, 1-x, polz,
2949
+ SBLambda ([&] (size_t j, S polsy) LAMBDA_INLINE
2950
+ {
2951
+ values[ii++] =
2952
+ jac2.CalcHighestOrderMult(n-k-j, 2*x - 1, polsy);
2953
+ jac2.IncAlpha2();
2954
+ }));
2955
+ jac1.IncAlpha2();
2956
+ }));
2957
+ }
2958
+
2959
+ };
2960
+
2961
+
2962
+
2963
+ class DubinerBasis3DOrthoBub
2964
+ {
2965
+ public:
2966
+ template <typename TI, class S, class T>
2967
+ INLINE static void Eval (TI n, S x, S y, S z, T && values)
2968
+ {
2969
+ EvalMult (n, x, y, z, 1, values);
2970
+ }
2971
+
2972
+ template <typename TI, class S, class Sc, class T>
2973
+ INLINE static void EvalMult (TI n, S x, S y, S z, Sc c, T && values)
2974
+ {
2975
+ size_t ii = 0;
2976
+ S lam4 = 1.0 - x-y-z;
2977
+ // JacobiPolynomialAlpha jac1(1);
2978
+ JacobiPolynomialFix<1,1> leg;
2979
+ leg.EvalScaledMult1Assign
2980
+ (n, z-lam4, z+lam4, c,
2981
+ SBLambda ([&](size_t k, S polz) LAMBDA_INLINE
2982
+ {
2983
+ // JacobiPolynomialAlpha jac(2*k+1);
2984
+ // JacobiPolynomialAlpha jac2(2*k+2);
2985
+
2986
+ IntegratedJacobiPolynomialAlpha jac1(4+2*k);
2987
+ jac1.EvalScaledMult1Assign
2988
+ (n-k, y-z-lam4, 1-x, polz,
2989
+ SBLambda ([&] (size_t j, S polsy) LAMBDA_INLINE
2990
+ {
2991
+ IntegratedJacobiPolynomialAlpha jac2(6+2*k+2*j);
2992
+ jac2.EvalMult1Assign(n-k-j, 2*x - 1, polsy, values+ii);
2993
+ ii += n-k-j+1;
2994
+ }));
2995
+ }));
2996
+ }
2997
+
2998
+ template <class T>
2999
+ static size_t CalcNormInv (size_t n, T && norminv)
3000
+ {
3001
+ size_t ii = 0;
3002
+ for (size_t i = 0; i <= n; i++)
3003
+ for (size_t j = 0; j <= n-i; j++)
3004
+ for (size_t k = 0; k <= n-i-j; k++)
3005
+ norminv[ii++] =
3006
+ 0.5 * (7+2*i+2*j+2*k)*(6+2*i+2*j+k)*(k+1) *
3007
+ (5+2*i+2*j)*(4+2*i+j)*(j+1) *
3008
+ (2*i+3)*(2*i+4) / (i+1);
3009
+ return ii;
3010
+ }
3011
+ /*
3012
+ // evaluate basis functions of hightest order only
3013
+ template <typename TI, class S, class T>
3014
+ INLINE static void EvalHighestOrder (TI n, S x, S y, S z, T && values)
3015
+ {
3016
+ EvalHighestOrderMult (n, x, y, z, 1, values);
3017
+ }
3018
+
3019
+ template <typename TI, class S, class Sc, class T>
3020
+ INLINE static void EvalHighestOrderMult (TI n, S x, S y, S z, Sc c, T && values)
3021
+ {
3022
+ size_t ii = 0;
3023
+ S lam4 = 1.0 - x-y-z;
3024
+ LegendrePolynomial leg;
3025
+ JacobiPolynomialAlpha jac1(1);
3026
+ leg.EvalScaledMult1Assign
3027
+ (n, z-lam4, z+lam4, c,
3028
+ SBLambda ([&](size_t k, S polz) LAMBDA_INLINE
3029
+ {
3030
+ JacobiPolynomialAlpha jac2(2*k+2);
3031
+
3032
+ jac1.EvalScaledMult1Assign
3033
+ (n-k, y-z-lam4, 1-x, polz,
3034
+ SBLambda ([&] (size_t j, S polsy) LAMBDA_INLINE
3035
+ {
3036
+ values[ii++] =
3037
+ jac2.CalcHighestOrderMult(n-k-j, 2*x - 1, polsy);
3038
+ jac2.IncAlpha2();
3039
+ }));
3040
+ jac1.IncAlpha2();
3041
+ }));
3042
+ }
3043
+ */
3044
+ };
3045
+
3046
+
3047
+
3048
+
3049
+
3050
+
3051
+
3052
+
3053
+ template <class S, class T>
3054
+ inline void GegenbauerPolynomial (int n, S x, double lam, T && values)
3055
+ {
3056
+ S p1 = 1.0, p2 = 0.0, p3;
3057
+
3058
+ if (n >= 0)
3059
+ values[0] = 1.0;
3060
+
3061
+ for (int j=1; j<=n; j++)
3062
+ {
3063
+ p3=p2; p2=p1;
3064
+ p1=( 2.0*(j+lam-1.0) * x * p2 - (j+2*lam-2.0) * p3) / j;
3065
+ values[j] = p1;
3066
+ }
3067
+ }
3068
+
3069
+
3070
+ /**
3071
+ Integrated Legendre polynomials on (-1,1)
3072
+
3073
+ value[0] = -1
3074
+ value[1] = x
3075
+ value[i] (x) = \int_{-1}^x P_{i-1} (s) ds for i >= 2
3076
+
3077
+ WARNING: is not \int P_i
3078
+ */
3079
+ template <class S, class T>
3080
+ INLINE void IntegratedLegendrePolynomial_Old (int n, S x, T && values)
3081
+ {
3082
+ S p1 = -1.0;
3083
+ S p2 = 0.0;
3084
+ S p3;
3085
+
3086
+ if (n >= 0)
3087
+ values[0] = (S)-1.0;
3088
+
3089
+ for (int j=1; j<=n; j++)
3090
+ {
3091
+ p3=p2; p2=p1;
3092
+ p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;
3093
+ values[j] = p1;
3094
+
3095
+ }
3096
+ }
3097
+
3098
+
3099
+
3100
+
3101
+
3102
+
3103
+
3104
+ /**
3105
+ Hermite polynomials H_i, orthogonal w.r.t. \int_R exp(-x*x)
3106
+ up to order n --> n+1 values
3107
+
3108
+ H_l = 2 x H_{l-1} - 2 (l-1) H_{l-2}
3109
+
3110
+ P_0 = 1
3111
+ P_1 = 2*x
3112
+ P_2 = 4*x*x - 2
3113
+ P_2 = 8*x*x*x - 12 x
3114
+ */
3115
+
3116
+ template <class S, class T>
3117
+ inline void HermitePolynomial (int n, S x, T && values)
3118
+ {
3119
+ S p1, p2, p3;
3120
+
3121
+ p2 = 0;
3122
+ if (n >= 0)
3123
+ p1 = values[0] = 1.0;
3124
+ for (int j=1; j<=n; j++)
3125
+ {
3126
+ p3 = p2; p2 = p1;
3127
+ p1 = 2*x*p2 - 2*(j-1)*p3;
3128
+ values[j] = p1;
3129
+ }
3130
+ }
3131
+
3132
+
3133
+
3134
+
3135
+
3136
+
3137
+
3138
+
3139
+
3140
+
3141
+
3142
+
3143
+ /**
3144
+ Compute triangle edge-shape functions
3145
+
3146
+ functions vanish on upper two edges
3147
+
3148
+ x,y: coordinates in triangle (-1, 0), (1, 0), (0, 1)
3149
+
3150
+ f_i (x, 0) = IntegratedLegendrePol_i (x)
3151
+
3152
+ f_i ... pol of order i
3153
+
3154
+
3155
+ Monomial extension:
3156
+ */
3157
+ template <class Sx, class Sy, class T>
3158
+ inline void TriangleExtensionMonomial (int n, Sx x, Sy y, T & values)
3159
+ {
3160
+ Sx p1 = -1.0, p2 = 0.0, p3;
3161
+ values[0] = -1.0;
3162
+ Sy fy = (1-y)*(1-y);
3163
+ for (int j=1; j<=n; j++)
3164
+ {
3165
+ p3=p2; p2=p1;
3166
+ p1=( (2*j-3) * x * p2 - (j-3) * fy * p3) / j;
3167
+ values[j] = p1;
3168
+ }
3169
+ }
3170
+
3171
+ template <class Sx, class Sy, class T>
3172
+ inline void DiffTriangleExtensionMonomial (int n, Sx x, Sy y, T & values)
3173
+ {
3174
+ Array<AutoDiff<2> > ad_values(n+1);
3175
+ AutoDiff<2> ad_x(x, 0);
3176
+ AutoDiff<2> ad_y(y, 1);
3177
+
3178
+ TriangleExtensionMonomial (n, ad_x, ad_y, ad_values);
3179
+
3180
+ for (int i = 0; i <= n; i++)
3181
+ for (int j = 0; j < 2; j++)
3182
+ values(i,j) = ad_values[i].DValue(j);
3183
+ }
3184
+
3185
+
3186
+
3187
+ /**
3188
+ Extension is the optimal averaging extension:
3189
+ */
3190
+ template <class Sx, class Sy, class T>
3191
+ inline void TriangleExtensionJacobi (int n, Sx x, Sy y, T & values)
3192
+ {
3193
+ if ( (1-y) != 0.0)
3194
+ {
3195
+ int j;
3196
+
3197
+ JacobiPolynomial (n-2, x / (1-y), 2, 2, values);
3198
+ Sy fac = (1.-x-y) * (1.+x-y);
3199
+ for (j = 0; j <= n-2; j++)
3200
+ {
3201
+ values[j] *= fac;
3202
+ fac *= 1-y;
3203
+ }
3204
+ for (j = n; j >= 2; j--)
3205
+ values[j] = values[j-2];
3206
+ if (n >= 0) values[0] = 0;
3207
+ if (n >= 1) values[1] = 0;
3208
+ }
3209
+ else
3210
+ {
3211
+ for (int j = 0; j <= n; j++)
3212
+ values[j] = 0;
3213
+ }
3214
+ }
3215
+
3216
+ template <class Sx, class Sy, class T>
3217
+ inline void DiffTriangleExtensionJacobi (int n, Sx x, Sy y, T & values)
3218
+ {
3219
+ Array<AutoDiff<2> > ad_values(n+1);
3220
+ AutoDiff<2> ad_x(x, 0);
3221
+ AutoDiff<2> ad_y(y, 1);
3222
+
3223
+ TriangleExtensionJacobi (n, ad_x, ad_y, ad_values);
3224
+ for (int i = 0; i <= n; i++)
3225
+ for (int j = 0; j < 2; j++)
3226
+ values(i,j) = ad_values[i].DValue(j);
3227
+ }
3228
+
3229
+
3230
+
3231
+
3232
+
3233
+
3234
+
3235
+ /**
3236
+ Extension is the optimal averaging extension:
3237
+ */
3238
+ template <class Sx, class Sy, class T>
3239
+ inline void TriangleExtensionOpt (int n, Sx x, Sy y, T & values)
3240
+ {
3241
+ if (y < 1e-10)
3242
+ {
3243
+ IntegratedLegendrePolynomial (n, x, values);
3244
+ }
3245
+ else
3246
+ {
3247
+ Array<Sx> ge1(n+2);
3248
+ Array<Sx> ge2(n+2);
3249
+ Array<Sx> ge3(n+2);
3250
+ Array<Sx> ge4(n+2);
3251
+
3252
+ GegenbauerPolynomial (n+1, Sx(-1.0), -1.5, ge1);
3253
+ GegenbauerPolynomial (n+1, x-y, -1.5, ge2);
3254
+ GegenbauerPolynomial (n+1, x+y, -1.5, ge3);
3255
+ GegenbauerPolynomial (n+1, Sx(1.0), -1.5, ge4);
3256
+
3257
+ for (int i = 0; i <= n; i++)
3258
+ values[i] = 1.0/3.0 *
3259
+ ( (2*y/(1+x+y)/(1+x+y) - y/2) * ge1[i+1] +
3260
+ (-1/(2*y) + 2*y/(1-x+y)/(1-x+y)) * ge2[i+1] +
3261
+ (1/(2*y) - 2*y/(1+x+y)/(1+x+y) ) * ge3[i+1] +
3262
+ (-2*y/(1-x+y)/(1-x+y) + y/2 ) * ge4[i+1] );
3263
+ }
3264
+ }
3265
+
3266
+ template <class Sx, class Sy, class T>
3267
+ inline void DiffTriangleExtensionOpt (int n, Sx x, Sy y, T & values)
3268
+ {
3269
+ Array<AutoDiff<2> > ad_values(n+1);
3270
+ AutoDiff<2> ad_x(x, 0);
3271
+ AutoDiff<2> ad_y(y, 1);
3272
+
3273
+ if (y < 1e-10)
3274
+ {
3275
+ values = 0.;
3276
+ }
3277
+ else
3278
+ {
3279
+ TriangleExtensionOpt (n, ad_x, ad_y, ad_values);
3280
+
3281
+ for (int i = 0; i <= n; i++)
3282
+ for (int j = 0; j < 2; j++)
3283
+ values(i,j) = ad_values[i].DValue(j);
3284
+ }
3285
+ }
3286
+
3287
+
3288
+
3289
+ template <class S1, class S2, class S3>
3290
+ inline void StdOp (S1 & v1, const S2 & tt, const S3 & v2, double fac)
3291
+ {
3292
+ v1 = fac * (v1*tt - v2) + v2;
3293
+ // v1 = fac * (v1*tt) + (1-fac) * v2;
3294
+ }
3295
+
3296
+ template <int D>
3297
+ inline void StdOp (AutoDiff<D> & v1, const AutoDiff<D> & tt, const AutoDiff<D> & v2, double fac)
3298
+ {
3299
+ for (int j = 0; j < D; j++)
3300
+ v1.DValue(j) = fac * (v1.DValue(j) * tt.Value() + v1.Value() * tt.DValue(j) - v2.DValue(j)) + v2.DValue(j);
3301
+ v1.Value() = fac * (v1.Value()*tt.Value()-v2.Value()) + v2.Value();
3302
+ }
3303
+
3304
+
3305
+ /*
3306
+ E_i(x,y) = P_i(x/t) * t^i
3307
+ */
3308
+ template <class Sx, class St, class T>
3309
+ inline void ScaledLegendrePolynomial (int n, Sx x, St t, T && values)
3310
+ {
3311
+ // St tt = t*t;
3312
+ St tt = sqr(t);
3313
+
3314
+ Sx p1, p2;
3315
+
3316
+ if (n < 0) return;
3317
+ values[0] = p2 = 1.0;
3318
+ if (n < 1) return;
3319
+ values[1] = p1 = x;
3320
+ if (n < 2) return;
3321
+
3322
+ for (int j=2; j < n; j+=2)
3323
+ {
3324
+ /*
3325
+ double invj = 1.0/j;
3326
+ p2 *= (invj-1) * tt;
3327
+ p2 += (2-invj) * x * p1;
3328
+ values[j] = p2;
3329
+
3330
+ double invj2 = 1.0/(j+1);
3331
+ p1 *= (invj2-1) * tt;
3332
+ p1 += (2-invj2) * x * p2;
3333
+ values[j+1] = p1;
3334
+ */
3335
+
3336
+ StdOp (p2, tt, x*p1, 1.0/j-1);
3337
+ values[j] = p2;
3338
+ StdOp (p1, tt, x*p2, 1.0/(j+1)-1);
3339
+ values[j+1] = p1;
3340
+ }
3341
+
3342
+ if (n % 2 == 0)
3343
+ {
3344
+ double invn = 1.0/n;
3345
+ values[n] = (2-invn)*x*p1 - (1-invn) * tt*p2;
3346
+ }
3347
+
3348
+
3349
+ /*
3350
+ if (n < 0) return;
3351
+ values[0] = 1.0;
3352
+ if (n < 1) return;
3353
+ values[1] = x;
3354
+ if (n < 2) return;
3355
+ values[2] = p2 = 1.5 * x * x - 0.5 * tt;
3356
+ if (n < 3) return;
3357
+ values[3] = p1 = (5.0/3.0) * p2 * x - (2.0/3.0) * tt * x;
3358
+ if (n < 4) return;
3359
+
3360
+ for (int j=4; j < n; j+=2)
3361
+ {
3362
+ double invj = 1.0/j;
3363
+ p2 *= (invj-1) * tt;
3364
+ p2 += (2-invj) * x * p1;
3365
+ values[j] = p2;
3366
+
3367
+ invj = 1.0/(j+1);
3368
+ p1 *= (invj-1) * tt;
3369
+ p1 += (2-invj) * x * p2;
3370
+ values[j+1] = p1;
3371
+ }
3372
+
3373
+ if (n % 2 == 0)
3374
+ {
3375
+ double invn = 1.0/n;
3376
+ values[n] = (2-invn)*x*p1 - (invn-1) * tt*p2;
3377
+ }
3378
+ */
3379
+
3380
+
3381
+
3382
+
3383
+
3384
+ /*
3385
+ Sx p1 = 1.0, p2 = 0.0, p3;
3386
+
3387
+ if (n>=0) values[0] = 1.0;
3388
+
3389
+ for (int j=1; j<=n; j++)
3390
+ {
3391
+ p3=p2; p2=p1;
3392
+ p1=((2.0*j-1.0) * x*p2 - tt*(j-1.0)*p3)/j;
3393
+ values[j] = p1;
3394
+ }
3395
+ */
3396
+ }
3397
+
3398
+
3399
+
3400
+ /*
3401
+ E_i(x,y) = c * P_i(x/t) * t^i
3402
+ */
3403
+ template <class Sx, class St, class Sc, class T>
3404
+ inline void ScaledLegendrePolynomialMult (int n, Sx x, St t, Sc c, T && values)
3405
+ {
3406
+ St tt = sqr(t);
3407
+ Sx p1, p2;
3408
+
3409
+ if (n < 0) return;
3410
+ values[0] = p2 = c;
3411
+ if (n < 1) return;
3412
+ values[1] = p1 = c * x;
3413
+ if (n < 2) return;
3414
+
3415
+ for (int j=2; j < n; j+=2)
3416
+ {
3417
+ StdOp (p2, tt, x*p1, 1.0/j-1);
3418
+ values[j] = p2;
3419
+ StdOp (p1, tt, x*p2, 1.0/(j+1)-1);
3420
+ values[j+1] = p1;
3421
+ /*
3422
+ double invj = 1.0/j;
3423
+ p2 *= (invj-1) * tt;
3424
+ p2 += (2-invj) * x * p1;
3425
+ values[j] = p2;
3426
+
3427
+ invj = 1.0/(j+1);
3428
+ p1 *= (invj-1) * tt;
3429
+ p1 += (2-invj) * x * p2;
3430
+ values[j+1] = p1;
3431
+ */
3432
+ }
3433
+
3434
+ if (n % 2 == 0)
3435
+ {
3436
+ StdOp (p2, tt, x*p1, 1.0/n-1);
3437
+ values[n] = p2;
3438
+
3439
+ // double invn = 1.0/n;
3440
+ // values[n] = (2-invn)*x*p1 - (1-invn) * tt*p2;
3441
+ }
3442
+ }
3443
+
3444
+
3445
+
3446
+
3447
+
3448
+
3449
+
3450
+
3451
+
3452
+
3453
+
3454
+
3455
+
3456
+
3457
+
3458
+
3459
+
3460
+
3461
+
3462
+ template <class T>
3463
+ inline void DiffScaledLegendrePolynomial (int n, double x, double t, T && values)
3464
+ {
3465
+ ArrayMem<AutoDiff<2>,10> ad_values(n+1);
3466
+ AutoDiff<2> ad_x(x, 0);
3467
+ AutoDiff<2> ad_t(t, 1);
3468
+
3469
+ ScaledLegendrePolynomial(n, ad_x, ad_t, ad_values);
3470
+
3471
+ for (int i = 0; i <= n; i++)
3472
+ for (int j = 0; j < 2; j++)
3473
+ values(i,j) = ad_values[i].DValue(j);
3474
+ }
3475
+
3476
+
3477
+ template <class Sx, class St, class T>
3478
+ inline void ScaledIntegratedLegendrePolynomial (int n, Sx x, St t, T & values)
3479
+ {
3480
+ Sx p1 = -1.0;
3481
+ Sx p2 = 0.0;
3482
+ Sx p3;
3483
+ St tt = t*t;
3484
+ if (n >= 0)
3485
+ values[0] = -1.0;
3486
+
3487
+ for (int j=1; j<=n; j++)
3488
+ {
3489
+ p3=p2; p2=p1;
3490
+ p1=((2.0*j-3.0) * x*p2 - tt*(j-3.0)*p3)/j;
3491
+ values[j] = p1;
3492
+ }
3493
+ }
3494
+
3495
+
3496
+
3497
+
3498
+
3499
+
3500
+ template <class T>
3501
+ inline void ScaledLegendrePolynomialandDiff(int n, double x, double t, T & P, T & Px, T & Pt)
3502
+ {
3503
+ /*
3504
+ ArrayMem<AutoDiff<2>,10> ad_values(n+1);
3505
+ AutoDiff<2> ad_x(x, 0);
3506
+ AutoDiff<2> ad_t(t, 1);
3507
+
3508
+ ScaledLegendrePolynomial(n, ad_x, ad_t, ad_values);
3509
+
3510
+ for (int i = 0; i <= n; i++)
3511
+ {
3512
+ P[i] = ad_values[i].Value();
3513
+ Px[i] = ad_values[i].DValue(0);
3514
+ Pt[i] = ad_values[i].DValue(1);
3515
+ }
3516
+ */
3517
+ if(n>=0)
3518
+ {
3519
+ P[0] = 1.;
3520
+ Px[0] = 0.;
3521
+ Pt[0] = 0.;
3522
+ if(n>=1)
3523
+ {
3524
+ P[1] = x;
3525
+ Px[1] = 1.;
3526
+ Pt[1] = 0.;
3527
+ }
3528
+
3529
+ double px0 = 0., px1 = 0., px2 =1.;
3530
+ double sqt = t*t;
3531
+ for(int l = 2; l<=n; l++)
3532
+ {
3533
+ px0=px1;
3534
+ px1=px2;
3535
+ px2= ( (2*l-1)*x*px1 - l*sqt*px0)/(l-1);
3536
+ Px[l] = px2;
3537
+ Pt[l] = -t*px1;
3538
+ P[l] = (x*px2-sqt*px1)/l;
3539
+ }
3540
+ }
3541
+
3542
+ }
3543
+
3544
+ template <class T>
3545
+ INLINE void LegendrePolynomialandDiff(int n, double x, T & P, T & Px)
3546
+ {
3547
+ /*
3548
+ ArrayMem<AutoDiff<1>,10> ad_values(n+1);
3549
+ AutoDiff<1> ad_x(x, 0);
3550
+ LegendrePolynomial(n, ad_x, ad_values);
3551
+
3552
+ for (int i = 0; i <= n; i++)
3553
+ {
3554
+ P[i] = ad_values[i].Value();
3555
+ Px[i] = ad_values[i].DValue(0);
3556
+ }
3557
+
3558
+ (*testout) << "P = " << endl << P << endl
3559
+ << "Px = " << endl << Px << endl;
3560
+ */
3561
+ if(n>=0)
3562
+ {
3563
+ P[0] = 1.;
3564
+ Px[0] = 0.;
3565
+ if(n>=1)
3566
+ {
3567
+ P[1] = x;
3568
+ Px[1] = 1.;
3569
+ }
3570
+ double px0 = 0., px1 = 0., px2 =1.;
3571
+ for(int l = 2; l<=n; l++)
3572
+ {
3573
+ px0=px1;
3574
+ px1=px2;
3575
+
3576
+ px2= ( (2*l-1)*x*px1 - l*px0)/(l-1);
3577
+ Px[l] = px2;
3578
+ P[l] = (x*px2 - px1)/l;
3579
+ }
3580
+ }
3581
+ }
3582
+
3583
+
3584
+
3585
+
3586
+ #ifdef OLD
3587
+
3588
+
3589
+ /*
3590
+ u(0) = 0, u(1) = 1,
3591
+ min \int_0^1 (1-x)^{DIM-1} (u')^2 dx
3592
+
3593
+ representation as
3594
+ \sum c_i P_i(2x-1)
3595
+ */
3596
+
3597
+ template <int DIM>
3598
+ class VertexExtensionOptimal
3599
+ {
3600
+ enum { SIZE = 50 };
3601
+ static double coefs[SIZE][SIZE];
3602
+ static bool initialized;
3603
+ public:
3604
+
3605
+ VertexExtensionOptimal ();
3606
+
3607
+ template <typename Tx>
3608
+ inline static Tx Calc (int p, Tx x)
3609
+ {
3610
+ Tx p1 = 1.0, p2 = 0.0, p3;
3611
+ Tx sum = 0;
3612
+
3613
+ x = 2*x-1;
3614
+
3615
+ if (p >= 0)
3616
+ sum += coefs[0][p];
3617
+
3618
+ for (int j=1; j<=p; j++)
3619
+ {
3620
+ p3 = p2; p2 = p1;
3621
+ p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j;
3622
+ sum += coefs[j][p] * p1;
3623
+ }
3624
+
3625
+ return sum;
3626
+ }
3627
+
3628
+ inline static double CalcDeriv (int p, double x)
3629
+ {
3630
+ AutoDiff<1> p1 = 1.0, p2 = 0.0, p3;
3631
+ AutoDiff<1> sum = 0;
3632
+ AutoDiff<1> adx (x, 0); // \nabla adx = e_0
3633
+
3634
+ adx = 2.0*adx-1;
3635
+
3636
+ if (p >= 0)
3637
+ sum += coefs[0][p];
3638
+
3639
+ for (int j=1; j<=p; j++)
3640
+ {
3641
+ p3 = p2; p2 = p1;
3642
+ p1 = ((2.0*j-1.0)*adx*p2 - (j-1.0)*p3) / j;
3643
+ sum += coefs[j][p] * p1;
3644
+ }
3645
+
3646
+ return sum.DValue(0);
3647
+ }
3648
+
3649
+
3650
+ /*
3651
+ // Based on Jacobi pols, 3D only
3652
+ template <typename Tx>
3653
+ inline static Tx Calc (int p, Tx x)
3654
+ {
3655
+ ArrayMem<Tx,20> jacpol(p+1);
3656
+
3657
+ JacobiPolynomial (p, 2*x-1, 1, -1, jacpol);
3658
+
3659
+ Tx sum = 0;
3660
+ for (int j = 0; j <= p; j++)
3661
+ sum += coefs[j][p] * jacpol[j];
3662
+
3663
+ return sum;
3664
+ }
3665
+
3666
+ inline static double CalcDeriv (int p, double x)
3667
+ {
3668
+ ArrayMem<double,20> jacpol(p+1);
3669
+
3670
+ JacobiPolynomial (p, 2*x-1, 2, 0, jacpol);
3671
+
3672
+ double sum = 0;
3673
+ for (int j = 1; j <= p; j++)
3674
+ sum += coefs[j][p] * 0.5 * (j+1) * jacpol[j-1];
3675
+
3676
+ return sum;
3677
+ }
3678
+ */
3679
+ };
3680
+
3681
+
3682
+
3683
+
3684
+ /*
3685
+ u(-1) = 0, u(1) = 1,
3686
+ min \int_-1^1 (1-x)^{DIM-1} (u')^2 dx
3687
+ */
3688
+
3689
+ template <class Tx, class T>
3690
+ inline void LowEnergyVertexPolynomials2D (int n, Tx x, T & values)
3691
+ {
3692
+ JacobiPolynomial (n, x, 0, -1, values);
3693
+ Tx sum1 = 0.0, sum2 = 0.0;
3694
+ for (int i = 1; i <= n; i++)
3695
+ {
3696
+ sum1 += 1.0/i;
3697
+ sum2 += values[i] / i;
3698
+ values[i] = sum2/sum1;
3699
+ }
3700
+ values[0] = 1;
3701
+ }
3702
+
3703
+ template <class Tx, class T>
3704
+ inline void LowEnergyVertexPolynomials3D (int n, Tx x, T & values)
3705
+ {
3706
+ JacobiPolynomial (n, x, 1, -1, values);
3707
+ Tx sum = 0.0;
3708
+ for (int i = 1; i <= n; i++)
3709
+ {
3710
+ sum += (2.0*i+1)/(i+1) * values[i];
3711
+ values[i] = 1.0/(i*(i+2)) * sum;
3712
+ }
3713
+ values[0] = 1;
3714
+ }
3715
+
3716
+
3717
+
3718
+
3719
+
3720
+ class VertexStandard
3721
+ {
3722
+ public:
3723
+ template <typename Tx>
3724
+ inline static Tx Calc (int p, Tx x)
3725
+ {
3726
+ return x;
3727
+ }
3728
+
3729
+ inline static double CalcDeriv (int p, double x)
3730
+ {
3731
+ return 1;
3732
+ }
3733
+ };
3734
+
3735
+ #endif
3736
+
3737
+
3738
+ /**
3739
+ Compute triangle edge-shape functions
3740
+
3741
+ functions vanish on upper two edges
3742
+
3743
+ x,y: coordinates in triangle (-1, 0), (1, 0), (0, 1)
3744
+
3745
+ f_i-2 (x, 0) = IntegratedLegendrePol_i (x)
3746
+
3747
+ f_i-2 ... pol of order i, max order = n
3748
+
3749
+ Monomial extension:
3750
+ */
3751
+
3752
+ class IntegratedLegendreMonomialExt
3753
+ {
3754
+ enum { SIZE = 1000 };
3755
+ static double coefs[SIZE][2];
3756
+
3757
+ public:
3758
+
3759
+ static void CalcCoeffs ()
3760
+ {
3761
+ for (int j = 1; j < SIZE; j++)
3762
+ {
3763
+ coefs[j][0] = double(2*j-3)/j;
3764
+ coefs[j][1] = double(j-3)/j;
3765
+ }
3766
+ }
3767
+
3768
+ template <class Sx, class Sy, class T>
3769
+ inline static int CalcScaled (int n, Sx x, Sy y, T && values)
3770
+ {
3771
+ Sy fy = y*y;
3772
+ Sx p3 = 0;
3773
+ Sx p2 = -1;
3774
+ Sx p1 = x;
3775
+
3776
+ for (int j=2; j<=n; j++)
3777
+ {
3778
+ p3=p2; p2=p1;
3779
+ p1 = double(2*j-3)/j * x * p2 - double(j-3)/j * fy * p3;
3780
+ values[j-2] = p1;
3781
+ }
3782
+
3783
+ return n-1;
3784
+ }
3785
+
3786
+
3787
+ template <int n, class Sx, class Sy, class T>
3788
+ inline static int CalcScaled (Sx x, Sy y, T && values)
3789
+ {
3790
+ Sy fy = y*y;
3791
+ Sx p3 = 0;
3792
+ Sx p2 = -1;
3793
+ Sx p1 = x;
3794
+
3795
+ for (int j=2; j<=n; j++)
3796
+ {
3797
+ p3=p2; p2=p1;
3798
+ p1 = double(2*j-3)/j * x * p2 - double(j-3)/j * fy * p3;
3799
+ values[j-2] = p1;
3800
+ }
3801
+
3802
+ return n-1;
3803
+ }
3804
+
3805
+
3806
+
3807
+
3808
+
3809
+ template <class Sx, class Sy, class T>
3810
+ inline static int CalcTrigExt (int n, Sx x, Sy y, T && values)
3811
+ {
3812
+ Sy fy = (1-y)*(1-y);
3813
+ Sx p3(0);
3814
+ Sx p2(-1);
3815
+ Sx p1 = x;
3816
+
3817
+ for (int j=2; j<=n; j++)
3818
+ {
3819
+ p3=p2; p2=p1;
3820
+ p1 = double(2*j-3)/j * x * p2 - double(j-3)/j * fy * p3;
3821
+ values[j-2] = p1;
3822
+ }
3823
+
3824
+ return n-1;
3825
+ }
3826
+
3827
+ template <class Sx, class Sy, class Sf, class T>
3828
+ inline static int CalcTrigExtMult (int n, Sx x, Sy y, Sf fac, T && values)
3829
+ {
3830
+ Sy fy = (1-y)*(1-y);
3831
+ Sx p3 = 0;
3832
+ Sx p2 = -fac;
3833
+ Sx p1 = x * fac;
3834
+
3835
+ for (int j=2; j<=n; j++)
3836
+ {
3837
+ p3=p2; p2=p1;
3838
+ // p1=( (2*j-3) * x * p2 - (j-3) * fy * p3) / j;
3839
+ p1 = double(2*j-3)/j * x * p2 - double(j-3)/j * fy * p3;
3840
+ // p1= coefs[j][0] * x * p2 - coefs[j][1] * fy * p3;
3841
+ values[j-2] = p1;
3842
+ }
3843
+
3844
+ return n-1;
3845
+ }
3846
+
3847
+
3848
+
3849
+
3850
+ template <class T>
3851
+ inline static int CalcTrigExtDeriv (int n, double x, double y, T && values)
3852
+ {
3853
+ double fy = (1-y)*(1-y);
3854
+ double p3 = 0, p3x = 0, p3y = 0;
3855
+ double p2 = -1, p2x = 0, p2y = 0;
3856
+ double p1 = x, p1x = 1, p1y = 0;
3857
+
3858
+ for (int j=2; j<=n; j++)
3859
+ {
3860
+ p3=p2; p3x = p2x; p3y = p2y;
3861
+ p2=p1; p2x = p1x; p2y = p1y;
3862
+ double c1 = (2.0*j-3) / j;
3863
+ double c2 = (j-3.0) / j;
3864
+
3865
+ p1 = c1 * x * p2 - c2 * fy * p3;
3866
+ p1x = c1 * p2 + c1 * x * p2x - c2 * fy * p3x;
3867
+ p1y = c1 * x * p2y - (c2 * 2 * (y-1) * p3 + c2 * fy * p3y);
3868
+ values (j-2, 0) = p1x;
3869
+ values (j-2, 1) = p1y;
3870
+ }
3871
+ return n-1;
3872
+ }
3873
+
3874
+
3875
+ template <class Sx, class T>
3876
+ inline static int Calc (int n, Sx x, T & values)
3877
+ {
3878
+ Sx p3(0.0);
3879
+ Sx p2(-1.0);
3880
+ Sx p1 = x;
3881
+
3882
+ for (int j=2; j<=n; j++)
3883
+ {
3884
+ p3=p2; p2=p1;
3885
+ p1=( (2*j-3)/double(j) * x * p2 - (j-3)/double(j) * p3); // / double(j);
3886
+ values[j-2] = p1;
3887
+ }
3888
+ return n-1;
3889
+ }
3890
+
3891
+ template <class Sx, class Sf, class T>
3892
+ inline static int CalcMult (int n, Sx x, Sf fac, T & values)
3893
+ {
3894
+ Sx p3 = 0;
3895
+ Sx p2 = -fac;
3896
+ Sx p1 = x*fac;
3897
+
3898
+ for (int j=2; j<=n; j++)
3899
+ {
3900
+ p3=p2; p2=p1;
3901
+ p1=( (2*j-3) * x * p2 - (j-3) * p3) / j;
3902
+ values[j-2] = p1;
3903
+ }
3904
+ return n-1;
3905
+ }
3906
+
3907
+
3908
+
3909
+ template <class T>
3910
+ inline static int CalcDeriv (int n, double x, T && values)
3911
+ {
3912
+ double p1 = 1.0, p2 = 0.0, p3;
3913
+
3914
+ for (int j=1; j<=n-1; j++)
3915
+ {
3916
+ p3 = p2; p2 = p1;
3917
+ p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j;
3918
+ values[j-1] = p1;
3919
+ }
3920
+ return n-1;
3921
+ }
3922
+
3923
+
3924
+ };
3925
+
3926
+
3927
+
3928
+
3929
+
3930
+
3931
+ /* Conversion of orthogonal polynomials */
3932
+
3933
+ // given: \sum u_i P^{al,0}
3934
+ // find: \sum v_i P^{al-1, 0}
3935
+ template <class T>
3936
+ void ConvertJacobiReduceAlpha (int n, int alpha, T & inout)
3937
+ {
3938
+ for (int i = n; i >= 1; i--)
3939
+ {
3940
+ double val = inout(i) / (i+alpha);
3941
+ inout(i) = (2*i+alpha) * val;
3942
+ inout(i-1) += i * val;
3943
+ }
3944
+ }
3945
+
3946
+ // given: \sum u_i (1-x) P^{al+1,0} 0 <= i < n
3947
+ // find: \sum v_i P^{al, 0} 0 <= i <= n
3948
+ template <class T>
3949
+ void ConvertJacobiReduceAlphaFactor (int n, double alpha, T & inout)
3950
+ {
3951
+ inout(n) = 0;
3952
+ for (int i = n; i > 0; i--)
3953
+ {
3954
+ double val = inout(i-1) / (i+alpha/2);
3955
+ inout(i-1) = (i+alpha) * val;
3956
+ inout(i) -= i * val;
3957
+ }
3958
+ }
3959
+
3960
+
3961
+
3962
+
3963
+
3964
+ // Differentiate Jacobi
3965
+ // (P_i^alpha)'
3966
+
3967
+ template <class T>
3968
+ void DifferentiateJacobi (int n, double alpha, T & inout)
3969
+ {
3970
+ for (int i = n; i >= 1; i--)
3971
+ {
3972
+ double val = inout(i);
3973
+ inout(i-1) -= alpha*(2*i+alpha-1) / ( (i+alpha)*(2*i+alpha-2)) * val;
3974
+ if (i > 1)
3975
+ inout(i-2) += (i-1)*(2*i+alpha) / ( (i+alpha)*(2*i+alpha-2)) * val;
3976
+
3977
+ inout(i) *= (2*i+alpha)*(2*i+alpha-1) / ( 2 * (i+alpha) );
3978
+ }
3979
+ for (int i = 0; i < n; i++)
3980
+ inout(i) = inout(i+1);
3981
+ inout(n) = 0;
3982
+ }
3983
+
3984
+
3985
+ template <class T>
3986
+ void DifferentiateJacobiTrans (int n, double alpha, T & inout)
3987
+ {
3988
+ for (int i = n-1; i >= 0; i--)
3989
+ inout(i+1) = inout(i);
3990
+ inout(0) = 0;
3991
+
3992
+ for (int i = 1; i <= n; i++)
3993
+ {
3994
+ inout(i) *= (2*i+alpha)*(2*i+alpha-1) / ( 2 * (i+alpha) );
3995
+
3996
+ inout(i) -= alpha*(2*i+alpha-1) / ( (i+alpha)*(2*i+alpha-2)) * inout(i-1);
3997
+ if (i > 1)
3998
+ inout(i) += (i-1)*(2*i+alpha) / ( (i+alpha)*(2*i+alpha-2)) * inout(i-2);
3999
+ }
4000
+ }
4001
+
4002
+
4003
+ template <class T>
4004
+ void DifferentiateLegendre (int n, T & inout)
4005
+ {
4006
+ for (int i = n; i >= 1; i--)
4007
+ {
4008
+ if (i > 1) inout(i-2) += inout(i);
4009
+ inout(i) *= 2*i-1;
4010
+ }
4011
+ for (int i = 0; i < n; i++)
4012
+ inout(i) = inout(i+1);
4013
+ inout(n) = 0;
4014
+ }
4015
+
4016
+ template <class T>
4017
+ void DifferentiateLegendreTrans (int n, T & inout)
4018
+ {
4019
+ for (int i = n-1; i >= 0; i--)
4020
+ inout(i+1) = inout(i);
4021
+ inout(0) = 0;
4022
+
4023
+ for (int i = 1; i <= n; i++)
4024
+ {
4025
+ inout(i) *= (2*i-1);
4026
+ if (i > 1)
4027
+ inout(i) += inout(i-2);
4028
+ }
4029
+ }
4030
+
4031
+
4032
+
4033
+
4034
+
4035
+
4036
+ class ConvertJacobi
4037
+ {
4038
+ typedef double d2[2];
4039
+ NGS_DLL_HEADER static Array<d2*> coefs_increasealpha;
4040
+ NGS_DLL_HEADER static Array<d2*> coefs_reducealpha;
4041
+ NGS_DLL_HEADER static Array<d2*> coefs_reducealphafac;
4042
+
4043
+ public:
4044
+ ConvertJacobi ();
4045
+ ~ConvertJacobi ();
4046
+
4047
+ template <class T>
4048
+ static void ReduceAlpha (int n, int alpha, T & inout) // alpha of input
4049
+ {
4050
+ d2 * c = coefs_reducealpha[alpha];
4051
+
4052
+ double val = inout[n];
4053
+ for (int i = n; i >= 1; i--)
4054
+ {
4055
+ inout[i] = c[i][1] * val;
4056
+ val = c[i][0] * val + inout[i-1];
4057
+ }
4058
+ inout[0] = val;
4059
+
4060
+ /*
4061
+ for (int i = n; i >= 1; i--)
4062
+ {
4063
+ inout[i-1] += c[i][0] * inout[i];
4064
+ inout[i] *= c[i][1];
4065
+ }
4066
+ */
4067
+ }
4068
+
4069
+ template <class T>
4070
+ static void ReduceAlphaFactor (int n, int alpha, T & inout) // alpha of output
4071
+ {
4072
+ d2 * c = coefs_reducealphafac[alpha];
4073
+
4074
+ inout(n) = c[n][0] * inout[n-1];
4075
+ for (int i = n-1; i >= 1; i--)
4076
+ inout[i] = c[i+1][1] * inout[i] + c[i][0] * inout[i-1];
4077
+ inout[0] = c[1][1] * inout[0];
4078
+
4079
+ /*
4080
+ for (int i = n; i >= 1; i--)
4081
+ {
4082
+ inout[i] += c[i][0] * inout[i-1];
4083
+ inout[i-1] *= c[i][1];
4084
+ }
4085
+ */
4086
+ }
4087
+
4088
+
4089
+ template <class T>
4090
+ static void ReduceAlphaTrans (int n, int alpha, T & inout) // alpha of input
4091
+ {
4092
+ d2 * c = coefs_reducealpha[alpha];
4093
+
4094
+ /*
4095
+ for (int i = n; i >= 1; i--)
4096
+ {
4097
+ inout[i-1] += c[i][0] * inout[i];
4098
+ inout[i] *= c[i][1];
4099
+ }
4100
+ */
4101
+ for (int i = 1; i <= n; i++)
4102
+ {
4103
+ inout[i] *= c[i][1];
4104
+ inout[i] += c[i][0] * inout[i-1];
4105
+ }
4106
+
4107
+ }
4108
+
4109
+ template <class T>
4110
+ static void ReduceAlphaFactorTrans (int n, int alpha, T & inout) // alpha of output
4111
+ {
4112
+ d2 * c = coefs_reducealphafac[alpha];
4113
+ /*
4114
+ for (int i = n; i >= 1; i--)
4115
+ {
4116
+ inout[i] += c[i][0] * inout[i-1];
4117
+ inout[i-1] *= c[i][1];
4118
+ }
4119
+ */
4120
+ for (int i = 1; i <= n; i++)
4121
+ {
4122
+ inout[i-1] *= c[i][1];
4123
+ inout[i-1] += c[i][0] * inout[i];
4124
+ }
4125
+ inout[n] = 0;
4126
+ }
4127
+
4128
+
4129
+
4130
+
4131
+
4132
+
4133
+
4134
+
4135
+
4136
+
4137
+
4138
+
4139
+
4140
+
4141
+
4142
+
4143
+
4144
+ // reduce, fac
4145
+ // P_i^alpha(x) (1-x)/2 = c_i^{alpha} P_i^{\alpha-1} + hatc_i^{alpha} P_{i+1}^{\alpha-1}
4146
+ static double c (int i, int alpha) { return double(i+alpha)/double(2*i+alpha+1); }
4147
+ static double hatc (int i, int alpha) { return -double(i+1)/double(2*i+alpha+1); }
4148
+
4149
+ // increase alpha
4150
+ // P_i^alpha(x) = d_i^{alpha} P_i^{\alpha+1} + hatd_i^{alpha} P_{i-1}^{\alpha+1}
4151
+ static double d (int i, int alpha) { return double(i+alpha+1)/double(2*i+alpha+1); }
4152
+ static double hatd (int i, int alpha) { return -double(i)/double(2*i+alpha+1); }
4153
+
4154
+ // decrease alpha
4155
+ // P_i^alpha(x) = e_i^{alpha} P_i^{\alpha-1} + hate_i^{alpha} P_{i-1}^{\alpha}
4156
+ static double e (int i, int alpha) { return double(2*i+alpha)/double(i+alpha); }
4157
+ static double hate (int i, int alpha) { return double(i)/double(i+alpha); }
4158
+
4159
+
4160
+ static Array<d2*> coefs_c, coefs_d, coefs_e;
4161
+
4162
+ // alpha,beta of input,
4163
+ // order of input
4164
+ // reduce alpha, reduce beta, reduce factor (1-x)/2 (1-y)/2
4165
+ template <class T>
4166
+ static void TriangularReduceFactor (int order, int alpha, int beta, T & inout)
4167
+ {
4168
+ for (int i = 0; i <= order+1; i++)
4169
+ inout(i, order+1-i) = 0;
4170
+
4171
+ for (int j = order; j >= 0; j--)
4172
+ {
4173
+ d2 * calpha = coefs_c[alpha+2*j];
4174
+ d2 * cbeta = coefs_c[beta];
4175
+ d2 * dalpha = coefs_d[alpha+2*j];
4176
+
4177
+ for (int i = order-j; i >= 0; i--)
4178
+ {
4179
+ double val = inout(i,j);
4180
+ inout(i,j) = val * calpha[i][0] * cbeta[j][0];
4181
+ inout(i+1,j) += val * calpha[i][1] * cbeta[j][0];
4182
+ inout(i,j+1) += val * dalpha[i][0] * cbeta[j][1];
4183
+ if (i > 0)
4184
+ inout(i-1,j+1) += val * dalpha[i][1] * cbeta[j][1];
4185
+ }
4186
+
4187
+ /*
4188
+ for (int i = order-j; i >= 0; i--)
4189
+ {
4190
+ double val = inout(i,j);
4191
+ inout(i,j) = val * c(i,alpha+2*j) * c(j,beta);
4192
+ inout(i+1,j) += val * hatc(i, alpha+2*j) * c(j, beta);
4193
+ inout(i,j+1) += val * d(i, alpha+2*j) * hatc (j,beta);
4194
+ if (i > 0)
4195
+ inout(i-1,j+1) += val * hatd(i, alpha+2*j) * hatc(j,beta);
4196
+ }
4197
+ */
4198
+ }
4199
+ }
4200
+
4201
+ // alpha,beta of input,
4202
+ // const alpha, dec beta
4203
+ // order is constant
4204
+ template <class T, class S>
4205
+ static void TriangularReduceBeta (int order, int alpha, int beta, T & inout, S & hv)
4206
+ {
4207
+ d2 * ebeta = coefs_e[beta];
4208
+
4209
+ for (int j = order; j > 0; j--)
4210
+ {
4211
+ d2 * calpha = coefs_c[alpha+2*j];
4212
+
4213
+ hv = 0.0;
4214
+ for (int i = 0; i <= order-j; i++)
4215
+ {
4216
+ double val = inout(i,j);
4217
+ inout(i,j) = val * ebeta[j][0];
4218
+
4219
+ hv(i) += val * calpha[i][0] * ebeta[j][1];
4220
+ hv(i+1) += val * calpha[i][1] * ebeta[j][1];
4221
+ }
4222
+
4223
+ ReduceAlpha (order-j+1, alpha+2*j-1, hv);
4224
+ inout.Col(j-1) += hv;
4225
+ }
4226
+ }
4227
+ };
4228
+
4229
+
4230
+
4231
+
4232
+
4233
+
4234
+
4235
+
4236
+
4237
+
4238
+
4239
+
4240
+ // template meta-programming
4241
+
4242
+ template <int N, int AL>
4243
+ class TReduceAlpha
4244
+ {
4245
+ public:
4246
+ enum { FLOP = TReduceAlpha<N-1,AL>::FLOP + 2 };
4247
+
4248
+ template <class T>
4249
+ static INLINE void Do (T & inout)
4250
+ {
4251
+ inout[N-1] += double(N)/double(N+AL) * inout[N];
4252
+ inout[N] *= double(2*N+AL)/double(N+AL);
4253
+ TReduceAlpha<N-1,AL>::Do(inout);
4254
+ }
4255
+
4256
+ template <class T>
4257
+ static INLINE void Trans (T & inout)
4258
+ {
4259
+ TReduceAlpha<N-1,AL>::Trans(inout);
4260
+ inout[N] *= double(2*N+AL)/double(N+AL);
4261
+ inout[N] += double(N)/double(N+AL) * inout[N-1];
4262
+ }
4263
+ };
4264
+
4265
+ template <int AL>
4266
+ class TReduceAlpha<0,AL>
4267
+ {
4268
+ public:
4269
+ enum { FLOP = 0 };
4270
+ template <class T>
4271
+ static void Do (T & inout) { ; }
4272
+
4273
+ template <class T>
4274
+ static void Trans (T & inout) { ; }
4275
+ };
4276
+
4277
+
4278
+
4279
+
4280
+
4281
+ template <int N, int AL, int HIGHEST = 1>
4282
+ class TReduceAlphaFactor
4283
+ {
4284
+ public:
4285
+ enum { FLOP = TReduceAlphaFactor<N-1,AL>::FLOP + 2 };
4286
+
4287
+ template <class T>
4288
+ static INLINE void Do (T & inout)
4289
+ {
4290
+ if (HIGHEST)
4291
+ inout[N] = double(-N)/double(2*N+AL) * inout[N-1];
4292
+ else
4293
+ inout[N] += double(-N)/double(2*N+AL) * inout[N-1];
4294
+ inout[N-1] *= double(N+AL)/double(2*N+AL);
4295
+ TReduceAlphaFactor<N-1,AL,0>::Do(inout);
4296
+ }
4297
+
4298
+ template <class T>
4299
+ static INLINE void Trans (T & inout)
4300
+ {
4301
+ TReduceAlphaFactor<N-1,AL,0>::Trans(inout);
4302
+ inout[N-1] *= double(N+AL)/double(2*N+AL);
4303
+ inout[N-1] += double(-N)/double(2*N+AL) * inout[N];
4304
+ }
4305
+ };
4306
+
4307
+ template <int AL, int HIGHEST>
4308
+ class TReduceAlphaFactor<0,AL,HIGHEST>
4309
+ {
4310
+ public:
4311
+ enum { FLOP = 0 };
4312
+
4313
+ template <class T>
4314
+ static inline void Do (T & inout)
4315
+ {
4316
+ if (HIGHEST) inout[0] = 0.0;
4317
+ }
4318
+
4319
+ template <class T>
4320
+ static inline void Trans (T & inout) { ; }
4321
+ };
4322
+
4323
+
4324
+
4325
+
4326
+
4327
+
4328
+ /*
4329
+ template <class T>
4330
+ void DifferentiateJacobi (int n, double alpha, T & inout)
4331
+ {
4332
+ for (int i = n; i >= 1; i--)
4333
+ {
4334
+ double val = inout(i);
4335
+ inout(i-1) -= alpha*(2*i+alpha-1) / ( (i+alpha)*(2*i+alpha-2)) * val;
4336
+ if (i > 1)
4337
+ inout(i-2) += (i-1)*(2*i+alpha) / ( (i+alpha)*(2*i+alpha-2)) * val;
4338
+
4339
+ inout(i) *= (2*i+alpha)*(2*i+alpha-1) / ( 2 * (i+alpha) );
4340
+ }
4341
+ for (int i = 0; i < n; i++)
4342
+ inout(i) = inout(i+1);
4343
+ inout(n) = 0;
4344
+ }
4345
+ */
4346
+
4347
+
4348
+
4349
+ template <int N, int AL>
4350
+ class TDifferentiateJacobi
4351
+ {
4352
+ public:
4353
+ enum { FLOP = TDifferentiateJacobi<N-1,AL>::FLOP + 3 };
4354
+
4355
+ // (P_i^Al)' = c1 P_i^AL + c2 (P_{i-1}^AL)' + c3 (P_{i-2}^AL)'
4356
+
4357
+ static double c1() { return double ( (2*N+AL)*(2*N+AL-1) ) / double( 2 * (N+AL) ); }
4358
+ static double c2() { return -double (AL*(2*N+AL-1)) / double( (N+AL)*(2*N+AL-2)); }
4359
+ static double c3() { return double((N-1)*(2*N+AL)) / double( (N+AL)*(2*N+AL-2)); }
4360
+ /*
4361
+ enum { c2 = -double (AL*(2*N+AL-1)) / double( (N+AL)*(2*N+AL-2)) };
4362
+ enum { c3 = double((N-1)*(2*N+AL)) / double( (N+AL)*(2*N+AL-2)) };
4363
+ */
4364
+ template <class T>
4365
+ static INLINE void Do (T & inout)
4366
+ {
4367
+ double val = inout(N);
4368
+ inout(N-1) += c2() * val;
4369
+ if (N > 1)
4370
+ inout(N-2) += c3() * val;
4371
+
4372
+ inout(N) *= c1();
4373
+ /*
4374
+ double val = inout(N);
4375
+ inout(N-1) -= double (AL*(2*N+AL-1)) / double( (N+AL)*(2*N+AL-2)) * val;
4376
+ if (N > 1)
4377
+ inout(N-2) += double((N-1)*(2*N+AL)) / double( (N+AL)*(2*N+AL-2)) * val;
4378
+
4379
+ inout(N) *= double ( (2*N+AL)*(2*N+AL-1) ) / double( 2 * (N+AL) );
4380
+ */
4381
+ TDifferentiateJacobi<N-1,AL>::Do(inout);
4382
+
4383
+ inout(N-1) = inout(N);
4384
+ inout(N) = 0;
4385
+ }
4386
+
4387
+ template <class T>
4388
+ static INLINE void Trans (T & inout)
4389
+ {
4390
+ inout(N) = inout(N-1);
4391
+ inout(N-1) = 0;
4392
+
4393
+ TDifferentiateJacobi<N-1,AL>::Trans(inout);
4394
+
4395
+ inout(N) *= double ((2*N+AL)*(2*N+AL-1)) / ( 2 * (N+AL) );
4396
+
4397
+ inout(N) -= double (AL*(2*N+AL-1)) / ( (N+AL)*(2*N+AL-2)) * inout(N-1);
4398
+ if (N > 1)
4399
+ inout(N) += double ((N-1)*(2*N+AL)) / ( (N+AL)*(2*N+AL-2)) * inout(N-2);
4400
+
4401
+ /*
4402
+ double val = inout(N);
4403
+ inout(N-1) -= double (AL*(2*N+AL-1)) / double( (N+AL)*(2*N+AL-2)) * val;
4404
+ if (N > 1)
4405
+ inout(N-2) += double((N-1)*(2*N+AL)) / double( (N+AL)*(2*N+AL-2)) * val;
4406
+
4407
+ inout(N) *= double ( (2*N+AL)*(2*N+AL-1) ) / double( 2 * (N+AL) );
4408
+ */
4409
+
4410
+ }
4411
+
4412
+
4413
+ };
4414
+
4415
+ template <int AL>
4416
+ class TDifferentiateJacobi<0,AL>
4417
+ {
4418
+ public:
4419
+ enum { FLOP = 0 };
4420
+
4421
+ template <class T>
4422
+ static inline void Do (T & inout) { ; }
4423
+
4424
+ template <class T>
4425
+ static inline void Trans (T & inout) { ; }
4426
+ };
4427
+
4428
+
4429
+
4430
+
4431
+
4432
+
4433
+
4434
+
4435
+
4436
+ template <int N>
4437
+ class TDifferentiateLegendre
4438
+ {
4439
+ public:
4440
+ enum { FLOP = TDifferentiateLegendre<N-1>::FLOP + 3 };
4441
+
4442
+ // (P_i^Al)' = c1 P_i^AL + c2 (P_{i-1}^AL)' + c3 (P_{i-2}^AL)'
4443
+
4444
+ template <class T>
4445
+ static INLINE void Do (T & inout)
4446
+ {
4447
+ double val = inout(N);
4448
+ if (N > 1) inout(N-2) += val;
4449
+
4450
+ inout(N) *= double (2*N-1);
4451
+ TDifferentiateLegendre<N-1>::Do(inout);
4452
+
4453
+ inout(N-1) = inout(N);
4454
+ inout(N) = 0;
4455
+ }
4456
+
4457
+ template <class T>
4458
+ static INLINE void Trans (T & inout)
4459
+ {
4460
+ inout(N) = inout(N-1);
4461
+ inout(N-1) = 0;
4462
+
4463
+ TDifferentiateLegendre<N-1>::Trans(inout);
4464
+
4465
+ inout(N) *= double (2*N-1);
4466
+ if (N > 1) inout(N) += inout(N-2);
4467
+ }
4468
+
4469
+ };
4470
+
4471
+ template <>
4472
+ class TDifferentiateLegendre<0>
4473
+ {
4474
+ public:
4475
+ enum { FLOP = 0 };
4476
+
4477
+ template <class T>
4478
+ static inline void Do (T & inout) { ; }
4479
+
4480
+ template <class T>
4481
+ static inline void Trans (T & inout) { ; }
4482
+ };
4483
+
4484
+
4485
+
4486
+
4487
+
4488
+
4489
+
4490
+
4491
+
4492
+
4493
+
4494
+
4495
+
4496
+
4497
+
4498
+
4499
+
4500
+
4501
+
4502
+
4503
+ template <int N, int J, int I, int AL, int BE>
4504
+ class TTriangleReduceFactorCol
4505
+ {
4506
+ // reduce, fac
4507
+ // P_i^alpha(x) (1-x)/2 = c_i^{alpha} P_i^{\alpha-1} + hatc_i^{alpha} P_{i+1}^{\alpha-1}
4508
+ static double c (int i, int alpha) { return double(i+alpha)/double(2*i+alpha+1); }
4509
+ static double hatc (int i, int alpha) { return -double(i+1)/double(2*i+alpha+1); }
4510
+
4511
+ // increase alpha
4512
+ // P_i^alpha(x) = d_i^{alpha} P_i^{\alpha+1} + hatd_i^{alpha} P_{i-1}^{\alpha+1}
4513
+ static double d (int i, int alpha) { return double(i+alpha+1)/double(2*i+alpha+1); }
4514
+ static double hatd (int i, int alpha) { return -double(i)/double(2*i+alpha+1); }
4515
+
4516
+ public:
4517
+ enum { FLOP = TTriangleReduceFactorCol<N,J,I-1,AL,BE>::FLOP + 4 };
4518
+
4519
+ template <class T>
4520
+ static INLINE void Do (T & inout)
4521
+ {
4522
+ double val = inout(I,J);
4523
+
4524
+ inout(I,J) = val * c(I,AL+2*J) * c(J,BE);
4525
+ inout(I+1,J) += val * hatc(I, AL+2*J) * c(J, BE);
4526
+ inout(I,J+1) += val * d(I, AL+2*J) * hatc (J, BE);
4527
+ if (I > 0)
4528
+ inout(I-1,J+1) += val * hatd(I, AL+2*J) * hatc(J,BE);
4529
+
4530
+ TTriangleReduceFactorCol<N,J,I-1,AL,BE> ::Do(inout);
4531
+ }
4532
+
4533
+
4534
+ template <class T>
4535
+ static INLINE void Trans (T & inout)
4536
+ {
4537
+ TTriangleReduceFactorCol<N,J,I-1,AL,BE> ::Trans(inout);
4538
+
4539
+ double val =
4540
+ c(I,AL+2*J) * c(J,BE) * inout(I,J)
4541
+ + hatc(I, AL+2*J) * c(J, BE) * inout(I+1,J)
4542
+ + d(I, AL+2*J) * hatc (J, BE) * inout(I,J+1);
4543
+
4544
+ if (I > 0)
4545
+ val += hatd(I, AL+2*J) * hatc(J,BE) * inout(I-1,J+1);
4546
+
4547
+ inout(I,J) = val;
4548
+ }
4549
+
4550
+ };
4551
+
4552
+
4553
+ template <int N, int J, int AL, int BE>
4554
+ class TTriangleReduceFactorCol<N,J,-1,AL,BE>
4555
+ {
4556
+ public:
4557
+ enum { FLOP = 0 };
4558
+ template <class T>
4559
+ static void Do (T & inout) { ; }
4560
+ template <class T>
4561
+ static void Trans (T & inout) { ; }
4562
+ };
4563
+
4564
+
4565
+ template <int N, int J, int AL, int BE>
4566
+ class TTriangleReduceFactor
4567
+ {
4568
+ public:
4569
+ enum { FLOP = TTriangleReduceFactor<N,J-1,AL,BE>::FLOP +
4570
+ TTriangleReduceFactorCol<N,J,N-J,AL,BE>::FLOP };
4571
+
4572
+ template <class T>
4573
+ static INLINE void Do (T & inout)
4574
+ {
4575
+ if (J == N)
4576
+ for (int i = 0; i <= N+1; i++)
4577
+ inout(i, N+1-i) = 0;
4578
+
4579
+ TTriangleReduceFactorCol<N,J,N-J,AL,BE> ::Do(inout);
4580
+ TTriangleReduceFactor<N,J-1,AL,BE> ::Do(inout);
4581
+ }
4582
+
4583
+ template <class T>
4584
+ static INLINE void Trans (T & inout)
4585
+ {
4586
+ /*
4587
+ if (J == N)
4588
+ for (int i = 0; i <= N+1; i++)
4589
+ inout(i, N+1-i) = 0;
4590
+ */
4591
+ TTriangleReduceFactor<N,J-1,AL,BE> ::Trans(inout);
4592
+ TTriangleReduceFactorCol<N,J,N-J,AL,BE> ::Trans(inout);
4593
+ }
4594
+ };
4595
+
4596
+
4597
+ template <int N, int AL, int BE>
4598
+ class TTriangleReduceFactor<N,-1,AL,BE>
4599
+ {
4600
+ public:
4601
+ enum { FLOP = 0 };
4602
+ template <class T>
4603
+ static void Do (T & inout) { ; }
4604
+ template <class T>
4605
+ static void Trans (T & inout) { ; }
4606
+ };
4607
+
4608
+
4609
+
4610
+
4611
+
4612
+
4613
+
4614
+
4615
+ /*
4616
+
4617
+
4618
+ template <int N, int J, int AL, int BE>
4619
+ class TTriangleReduce
4620
+ {
4621
+ // reduce, fac
4622
+ // P_i^alpha(x) (1-x)/2 = c_i^{alpha} P_i^{\alpha-1} + hatc_i^{alpha} P_{i+1}^{\alpha-1}
4623
+ static double c (int i, int alpha) { return double(i+alpha)/double(2*i+alpha+1); }
4624
+ static double hatc (int i, int alpha) { return -double(i+1)/double(2*i+alpha+1); }
4625
+
4626
+ // decrease alpha
4627
+ // P_i^alpha(x) = e_i^{alpha} P_i^{\alpha-1} + hate_i^{alpha} P_{i-1}^{\alpha}
4628
+ static double e (int i, int alpha) { return double(2*i+alpha)/double(i+alpha); }
4629
+ static double hate (int i, int alpha) { return double(i)/double(i+alpha); }
4630
+
4631
+
4632
+ public:
4633
+ enum { FLOP = TTriangleReduce<N,J-1,AL,BE>::FLOP + 3*(N-J+1) +
4634
+ TReduceAlpha<N-J+1, AL+2*J-1>::FLOP
4635
+ };
4636
+
4637
+
4638
+ template <class T>
4639
+ static INLINE void Do (T & inout)
4640
+ {
4641
+ Vec<N-J+2> hv;
4642
+ hv(0) = 0.0;
4643
+
4644
+ for (int i = 0; i <= N-J; i++)
4645
+ {
4646
+ double val = inout(i,J);
4647
+ inout(i,J) = val * e(J,BE);
4648
+ hv(i) += val * c(i, AL+2*J) * hate(J, BE);
4649
+ hv(i+1) = val * hatc(i, AL+2*J) * hate(J, BE);
4650
+ }
4651
+
4652
+ TReduceAlpha<N-J+1, AL+2*J-1>::Do(hv);
4653
+
4654
+ for (int i = 0; i <= N-J+1; i++)
4655
+ inout(i,J-1) += hv(i);
4656
+
4657
+ TTriangleReduce<N,J-1,AL,BE> ::Do(inout);
4658
+
4659
+ TReduceAlpha<N-J, AL+2*J>::Do(inout.Col(J));
4660
+ }
4661
+
4662
+
4663
+
4664
+
4665
+ template <class T>
4666
+ static INLINE void Trans (T & inout)
4667
+ {
4668
+ Vec<N-J+2> hv;
4669
+
4670
+ TReduceAlpha<N-J, AL+2*J>::Trans(inout.Col(J));
4671
+
4672
+ TTriangleReduce<N,J-1,AL,BE>::Trans(inout);
4673
+
4674
+ for (int i = 0; i <= N-J+1; i++)
4675
+ hv(i) = inout(i,J-1);
4676
+
4677
+ TReduceAlpha<N-J+1, AL+2*J-1>::Trans(hv);
4678
+
4679
+ for (int i = 0; i <= N-J; i++)
4680
+ {
4681
+ inout(i,J) =
4682
+ e(J,BE) * inout(i,J)
4683
+ + c(i, AL+2*J) * hate(J, BE) * hv(i)
4684
+ + hatc(i, AL+2*J) * hate(J, BE) * hv(i+1);
4685
+ }
4686
+ }
4687
+ };
4688
+
4689
+
4690
+ template <int N, int AL, int BE>
4691
+ class TTriangleReduce<N,0,AL,BE>
4692
+ {
4693
+ public:
4694
+ enum { FLOP = 0 };
4695
+ template <class T>
4696
+ static void Do (T & inout)
4697
+ {
4698
+ TReduceAlpha<N, AL>::Do(inout.Col(0));
4699
+ }
4700
+
4701
+ template <class T>
4702
+ static void Trans (T & inout)
4703
+ {
4704
+ TReduceAlpha<N, AL>::Trans(inout.Col(0));
4705
+ }
4706
+ };
4707
+ */
4708
+
4709
+
4710
+
4711
+
4712
+
4713
+
4714
+
4715
+
4716
+ template <int N, int I, int J, int AL, int BE>
4717
+ class TTriangleReduceLoop2New
4718
+ {
4719
+ public:
4720
+ template <class T>
4721
+ static INLINE void Do (T & inout)
4722
+ {
4723
+ if (BE+I == 0) cout << "is 0" << endl;
4724
+ double fac = 1.0 / ( (BE + I)*(4 + AL-1 + 2*I-2 + J-1) );
4725
+ double val = inout(J,I);
4726
+ inout(J,I) = fac * (BE + 2*I)*(5 + AL-1 + 2*I-2 + 2*J-2) * val;
4727
+ if (I >= 1)
4728
+ {
4729
+ inout(J,I-1) += fac * I*(3 + AL-1 + 2*I-2 + J-1) * val;
4730
+ inout(1+J,I-1) -= fac * I*(2 + J-1) * val;
4731
+ }
4732
+ if (J >= 1)
4733
+ inout(J-1, I) += fac * (BE + I)*(1 + J-1) * val;
4734
+
4735
+ TTriangleReduceLoop2New<N,I,J-1,AL,BE>::Do(inout);
4736
+ }
4737
+
4738
+
4739
+ template <class T>
4740
+ static INLINE void Trans (T & inout)
4741
+ {
4742
+ TTriangleReduceLoop2New<N,I,J-1,AL,BE>::Trans(inout);
4743
+
4744
+ double fac = 1.0 / ( (BE + I)*(4 + AL-1 + 2*I-2 + J-1) );
4745
+ double val = inout(J,I) * ( fac * (BE + 2*I)*(5 + AL-1 + 2*I-2 + 2*J-2) );
4746
+ if (I >= 1)
4747
+ {
4748
+ val += inout(J,I-1) * ( fac * I*(3 + AL-1 + 2*I-2 + J-1) );
4749
+ val -= inout(1+J,I-1) * ( fac * I*(2 + J-1));
4750
+ }
4751
+ if (J >= 1)
4752
+ val += inout(J-1, I) * (fac * (BE + I)*(1 + J-1));
4753
+
4754
+ inout(J,I) = val;
4755
+ }
4756
+
4757
+ };
4758
+
4759
+ template <int N, int AL, int I, int BE>
4760
+ class TTriangleReduceLoop2New<N,I,-1,AL,BE>
4761
+ {
4762
+ public:
4763
+ enum { FLOP = 0 };
4764
+ template <class T>
4765
+ static void Do (T & inout) { ; }
4766
+
4767
+ template <class T>
4768
+ static void Trans (T & inout) { ; }
4769
+ };
4770
+
4771
+
4772
+
4773
+ template <int N, int I, int AL, int BE>
4774
+ class TTriangleReduceNew
4775
+ {
4776
+ public:
4777
+ enum { FLOP = TTriangleReduceNew<N,I-1,AL,BE>::FLOP + 4*(N-I+1) };
4778
+
4779
+
4780
+ template <class T>
4781
+ static INLINE void Do (T & inout)
4782
+ {
4783
+ TTriangleReduceLoop2New<N,I,N-I,AL,BE>::Do(inout);
4784
+ TTriangleReduceNew<N,I-1,AL,BE>::Do(inout);
4785
+ }
4786
+
4787
+ template <class T>
4788
+ static INLINE void Trans (T & inout)
4789
+ {
4790
+ TTriangleReduceNew<N,I-1,AL,BE>::Trans(inout);
4791
+ TTriangleReduceLoop2New<N,I,N-I,AL,BE>::Trans(inout);
4792
+ }
4793
+ };
4794
+
4795
+ template <int N, int AL, int BE>
4796
+ class TTriangleReduceNew<N,-1,AL,BE>
4797
+ {
4798
+ public:
4799
+ enum { FLOP = 0 };
4800
+
4801
+ template <class T>
4802
+ static void Do (T & inout) { ; }
4803
+
4804
+ template <class T>
4805
+ static void Trans (T & inout) { ; }
4806
+ };
4807
+
4808
+
4809
+
4810
+
4811
+
4812
+ /*
4813
+
4814
+ template <int N, int I, int AL, int BE>
4815
+ class TTriangleReduceNew
4816
+ {
4817
+ public:
4818
+
4819
+ template <class T>
4820
+ static INLINE void Do (T & inout)
4821
+ {
4822
+ for (int J = N-I; J >= 0; J--)
4823
+ {
4824
+ double fac = 1.0 / ( (2 + BE-1 + I-1)*(4 + AL-1 + 2*I-2 + J-1) );
4825
+ double val = inout(J,I);
4826
+ inout(J,I) = fac * (3 + BE-1 + 2*I-2)*(5 + AL-1 + 2*I-2 + 2*J-2) * val;
4827
+ if (I >= 1)
4828
+ {
4829
+ inout(1+J,I-1) += -fac * I*(2 + J-1) * val;
4830
+ inout(J,I-1) += fac * I*(3 + AL-1 + 2*I-2 + J-1) * val;
4831
+ }
4832
+ if (J >= 1)
4833
+ inout(J-1, I) += fac * (2 + BE-1 + I-1)*(1 + J-1) * val;
4834
+ }
4835
+
4836
+ TTriangleReduceNew<N,I-1,AL,BE>::Do(inout);
4837
+ }
4838
+
4839
+
4840
+ template <class T>
4841
+ static INLINE void Trans (T & inout)
4842
+ {
4843
+ TTriangleReduceNew<N,I-1,AL,BE>::Trans(inout);
4844
+
4845
+ for (int J = 0; J <= N-I; J++)
4846
+ {
4847
+ double fac = 1.0 / ( (2 + BE-1 + I-1)*(4 + AL-1 + 2*I-2 + J-1) );
4848
+ double val = inout(J,I) * ( fac * (3 + BE-1 + 2*I-2)*(5 + AL-1 + 2*I-2 + 2*J-2) );
4849
+ if (I >= 1)
4850
+ {
4851
+ val += inout(J,I-1) * ( fac * I*(3 + AL-1 + 2*I-2 + J-1) );
4852
+ val -= inout(1+J,I-1) * ( fac * I*(2 + J-1));
4853
+ }
4854
+
4855
+ if (J >= 1)
4856
+ val += inout(J-1, I) * (fac * (2 + BE-1 + I-1)*(1 + J-1));
4857
+
4858
+ inout(J,I) = val;
4859
+ }
4860
+ }
4861
+
4862
+ };
4863
+
4864
+ template <int N, int AL, int BE>
4865
+ class TTriangleReduceNew<N,-1,AL,BE>
4866
+ {
4867
+ public:
4868
+ enum { FLOP = 0 };
4869
+ template <class T>
4870
+ static void Do (T & inout)
4871
+ { ; }
4872
+
4873
+ template <class T>
4874
+ static void Trans (T & inout)
4875
+ { ; }
4876
+ };
4877
+ */
4878
+
4879
+
4880
+
4881
+
4882
+
4883
+
4884
+
4885
+
4886
+
4887
+
4888
+
4889
+
4890
+ }
4891
+
4892
+
4893
+ #include "recursive_pol_trig.hpp"
4894
+ #include "recursive_pol_tet.hpp"
4895
+
4896
+ #endif