ngsolve 6.2.2506.post216.dev0__cp314-cp314-manylinux_2_28_x86_64.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.
- ngsolve-6.2.2506.post216.dev0.data/data/bin/ngs_nvcc +22 -0
- ngsolve-6.2.2506.post216.dev0.data/data/bin/ngs_nvlink +17 -0
- ngsolve-6.2.2506.post216.dev0.data/data/bin/ngscxx +15 -0
- ngsolve-6.2.2506.post216.dev0.data/data/bin/ngsld +11 -0
- ngsolve-6.2.2506.post216.dev0.data/data/bin/ngsolve.tcl +648 -0
- ngsolve-6.2.2506.post216.dev0.data/data/bin/ngspy +2 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/analytic_integrals.hpp +10 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/arnoldi.hpp +55 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bandmatrix.hpp +334 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/basematrix.hpp +963 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/basevector.hpp +1268 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bdbequations.hpp +2807 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bdbintegrator.hpp +1660 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bem_diffops.hpp +475 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bessel.hpp +1064 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bilinearform.hpp +966 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bla.hpp +29 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/blockalloc.hpp +95 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/blockjacobi.hpp +328 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/bspline.hpp +116 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/calcinverse.hpp +141 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cg.hpp +368 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/chebyshev.hpp +44 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cholesky.hpp +720 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/clapack.h +7254 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/code_generation.hpp +296 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/coefficient.hpp +2033 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/coefficient_impl.hpp +19 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/coefficient_stdmath.hpp +167 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/commutingAMG.hpp +106 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/comp.hpp +79 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/compatibility.hpp +41 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/complex_wrapper.hpp +101 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/compressedfespace.hpp +110 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/contact.hpp +239 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cuda_core.hpp +216 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cuda_linalg.hpp +185 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cuda_ngbla.hpp +317 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cuda_ngstd.hpp +414 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/cuda_profiler.hpp +240 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/diagonalmatrix.hpp +160 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/differentialoperator.hpp +276 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/diffop.hpp +1286 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/diffop_impl.hpp +328 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/diffopwithfactor.hpp +123 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/discontinuous.hpp +84 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/dump.hpp +949 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ectypes.hpp +121 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/eigen.hpp +60 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/eigensystem.hpp +18 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/elasticity_equations.hpp +595 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/elementbyelement.hpp +201 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/elementtopology.hpp +1760 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/elementtransformation.hpp +339 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/evalfunc.hpp +405 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/expr.hpp +1693 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/facetfe.hpp +175 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/facetfespace.hpp +180 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/facethofe.hpp +111 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/facetsurffespace.hpp +112 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/fe_interfaces.hpp +32 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/fem.hpp +87 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/fesconvert.hpp +14 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/fespace.hpp +1454 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/finiteelement.hpp +286 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/globalinterfacespace.hpp +77 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/globalspace.hpp +115 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/gridfunction.hpp +525 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1amg.hpp +124 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1hofe.hpp +188 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1hofe_impl.hpp +1262 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1hofefo.hpp +148 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1hofefo_impl.hpp +185 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1hofespace.hpp +167 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1lofe.hpp +1240 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/h1lumping.hpp +41 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurl_equations.hpp +1381 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlcurlfe.hpp +2241 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlcurlfespace.hpp +78 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlfe.hpp +259 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlfe_utils.hpp +107 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlhdiv_dshape.hpp +857 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlhdivfes.hpp +308 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlhofe.hpp +175 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlhofe_impl.hpp +1871 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurlhofespace.hpp +193 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hcurllofe.hpp +1146 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdiv_equations.hpp +880 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivdivfe.hpp +2923 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivdivsurfacespace.hpp +76 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivfe.hpp +206 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivfe_utils.hpp +717 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivfes.hpp +75 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivhofe.hpp +447 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivhofe_impl.hpp +1107 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivhofefo.hpp +229 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivhofespace.hpp +177 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivhosurfacefespace.hpp +106 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hdivlofe.hpp +773 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hidden.hpp +74 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/householder.hpp +181 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hypre_ams_precond.hpp +123 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/hypre_precond.hpp +73 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/integrator.hpp +2012 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/integratorcf.hpp +253 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/interpolate.hpp +49 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/intrule.hpp +2542 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/intrules_SauterSchwab.hpp +25 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/irspace.hpp +49 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/jacobi.hpp +153 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/kernels.hpp +724 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/l2hofe.hpp +194 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/l2hofe_impl.hpp +564 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/l2hofefo.hpp +542 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/l2hofespace.hpp +344 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/la.hpp +38 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/linalg_kernels.hpp +70 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/linearform.hpp +266 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/matrix.hpp +2145 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/memusage.hpp +41 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/meshaccess.hpp +1359 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/mgpre.hpp +204 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/mp_coefficient.hpp +145 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/mptools.hpp +2281 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/multigrid.hpp +42 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/multivector.hpp +447 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/mumpsinverse.hpp +187 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/mycomplex.hpp +361 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ng_lapack.hpp +1661 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngblas.hpp +1232 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngs_defines.hpp +30 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngs_stdcpp_include.hpp +106 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngs_utils.hpp +121 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngsobject.hpp +1019 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngsstream.hpp +113 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/ngstd.hpp +72 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/nodalhofe.hpp +96 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/nodalhofe_impl.hpp +141 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/normalfacetfe.hpp +223 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/normalfacetfespace.hpp +98 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/normalfacetsurfacefespace.hpp +84 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/order.hpp +251 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/parallel_matrices.hpp +222 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/paralleldofs.hpp +340 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/parallelngs.hpp +23 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/parallelvector.hpp +269 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/pardisoinverse.hpp +200 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/periodic.hpp +129 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/plateaufespace.hpp +25 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/pml.hpp +275 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/pmltrafo.hpp +631 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/postproc.hpp +142 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/potentialtools.hpp +22 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/precomp.hpp +60 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/preconditioner.hpp +602 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/prolongation.hpp +380 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/python_comp.hpp +107 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/python_fem.hpp +89 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/python_linalg.hpp +58 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/python_ngstd.hpp +386 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/recursive_pol.hpp +4896 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/recursive_pol_tet.hpp +395 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/recursive_pol_trig.hpp +492 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/reorderedfespace.hpp +81 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/sample_sort.hpp +105 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/scalarfe.hpp +335 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/shapefunction_utils.hpp +113 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/simd_complex.hpp +329 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/smoother.hpp +253 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/solve.hpp +89 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/sparsecholesky.hpp +317 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/sparsefactorization_interface.hpp +159 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/sparsematrix.hpp +1052 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/sparsematrix_dyn.hpp +90 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/sparsematrix_impl.hpp +1055 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/special_matrix.hpp +463 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/specialelement.hpp +125 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/statushandler.hpp +33 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/stringops.hpp +12 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/superluinverse.hpp +136 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/symbolicintegrator.hpp +850 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/symmetricmatrix.hpp +144 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tangentialfacetfe.hpp +224 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tangentialfacetfespace.hpp +91 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tensor.hpp +522 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tensorcoefficient.hpp +446 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tensorproductintegrator.hpp +113 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/thcurlfe.hpp +128 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/thcurlfe_impl.hpp +380 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/thdivfe.hpp +80 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/thdivfe_impl.hpp +492 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tpdiffop.hpp +461 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tpfes.hpp +133 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tpintrule.hpp +224 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/triangular.hpp +465 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tscalarfe.hpp +245 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/tscalarfe_impl.hpp +1029 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/umfpackinverse.hpp +148 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/unifiedvector.hpp +103 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/vector.hpp +1452 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/voxelcoefficientfunction.hpp +41 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/vtkoutput.hpp +198 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/vvector.hpp +208 -0
- ngsolve-6.2.2506.post216.dev0.data/data/include/netgen/webgui.hpp +92 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/cmake/ngsolve/NGSolveConfig.cmake +102 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/cmake/ngsolve/ngsolve-targets-release.cmake +89 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/cmake/ngsolve/ngsolve-targets.cmake +180 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngbla.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngcomp.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngfem.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngla.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngsbem.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngscudalib.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngsolve.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/netgen_mesher.libs/libngstd.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/TensorProductTools.py +210 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/__console.py +94 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/__expr.py +181 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/__init__.py +148 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/_scikit_build_core_dependencies.py +30 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/bvp.py +78 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/config/__init__.py +1 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/config/__main__.py +4 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/config/config.py +60 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/TensorProduct/__init__.py +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/TensorProduct/tp_dg_1d_1d.py +80 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/TensorProduct/tp_dg_1d_2d.py +73 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/TensorProduct/tp_dg_2d_1d.py +72 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/TensorProduct/tp_dg_2d_2d.py +66 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/__init__.py +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/__init__.py +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/hhj.py +44 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/hybrid_dg.py +53 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/mixed.py +30 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/nonlin.py +29 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/pickling.py +26 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/pml.py +31 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/taskmanager.py +20 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/tdnns.py +47 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/timeDG-skeleton.py +45 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/timeDG.py +38 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/timeDGlap.py +42 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/howto/timeDGwave.py +61 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/__init__.py +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/adaptive.py +123 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/cmagnet.py +59 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/elasticity.py +76 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/navierstokes.py +74 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/poisson.ipynb +170 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/intro/poisson.py +41 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/mpi/__init__.py +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/mpi/mpi_cmagnet.py +87 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/mpi/mpi_navierstokes.py +117 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/mpi/mpi_poisson.py +89 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/demos/mpi/mpi_timeDG.py +82 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/directsolvers.py +14 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/eigenvalues.py +364 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/internal.py +89 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/krylovspace.py +1182 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/meshes.py +748 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/ngs2petsc.py +310 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/ngscuda.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/ngscxx.py +42 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/ngslib.so +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/nonlinearsolvers.py +203 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/preconditioners.py +11 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/solve_implementation.py +168 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/solvers/__init__.py +7 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/solvers/cudss.py +112 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/timestepping.py +185 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/timing.py +108 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/utils.py +167 -0
- ngsolve-6.2.2506.post216.dev0.data/data/lib/python3.14/site-packages/ngsolve/webgui.py +671 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/beam.geo +17 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/beam.vol +240 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/chip.in2d +41 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/chip.vol +614 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/coil.geo +12 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/coil.vol +2560 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/coilshield.geo +24 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/coilshield.vol +3179 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/cube.geo +19 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/cube.vol +1832 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d10_DGdoubleglazing.pde +50 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d11_chip_nitsche.pde +40 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d1_square.pde +43 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d2_chip.pde +35 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d3_helmholtz.pde +22 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d4_cube.pde +46 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d5_beam.pde +74 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d6_shaft.pde +73 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d7_coil.pde +50 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d8_coilshield.pde +49 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/d9_hybridDG.pde +72 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/doubleglazing.in2d +27 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/doubleglazing.vol +737 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/piezo2d40round4.vol.gz +0 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/shaft.geo +73 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/shaft.vol +4291 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/square.in2d +17 -0
- ngsolve-6.2.2506.post216.dev0.data/data/share/ngsolve/square.vol +149 -0
- ngsolve-6.2.2506.post216.dev0.dist-info/METADATA +14 -0
- ngsolve-6.2.2506.post216.dev0.dist-info/RECORD +306 -0
- ngsolve-6.2.2506.post216.dev0.dist-info/WHEEL +5 -0
- ngsolve-6.2.2506.post216.dev0.dist-info/licenses/LICENSE +504 -0
- ngsolve-6.2.2506.post216.dev0.dist-info/top_level.txt +1 -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
|