react-native-executorch 0.10.6 → 0.10.7

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.
Files changed (237) hide show
  1. package/lib/module/fetcher/telemetry.js +1 -1
  2. package/package.json +1 -1
  3. package/react-native-executorch.podspec +2 -0
  4. package/src/fetcher/telemetry.ts +1 -1
  5. package/third-party/common/phonemis/CMakeLists.txt +70 -14
  6. package/third-party/common/phonemis/README.md +183 -33
  7. package/third-party/common/phonemis/THIRD_PARTY_NOTICES.md +57 -0
  8. package/third-party/common/phonemis/knowledge/code_style.md +642 -0
  9. package/third-party/common/phonemis/licenses/Unicode-3.0.txt +39 -0
  10. package/third-party/common/phonemis/licenses/misaki-Apache-2.0.txt +201 -0
  11. package/third-party/common/phonemis/licenses/nlohmann-json-MIT.txt +21 -0
  12. package/third-party/common/phonemis/licenses/xsimd-BSD-3-Clause.txt +29 -0
  13. package/third-party/common/phonemis/src/phonemis/base/config.h +6 -0
  14. package/third-party/common/phonemis/src/phonemis/base/ipipeline.cpp +75 -0
  15. package/third-party/common/phonemis/src/phonemis/base/ipipeline.h +21 -0
  16. package/third-party/common/phonemis/src/phonemis/base/phonemizer/constants.h +2 -5
  17. package/third-party/common/phonemis/src/phonemis/base/phonemizer/lexicon_phonemizer.cpp +3 -4
  18. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.cpp +17 -8
  19. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.h +4 -0
  20. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.cpp +21 -6
  21. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.h +13 -4
  22. package/third-party/common/phonemis/src/phonemis/base/pipeline.cpp +8 -0
  23. package/third-party/common/phonemis/src/phonemis/base/pipeline.h +19 -0
  24. package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.cpp +37 -0
  25. package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.h +45 -0
  26. package/third-party/common/phonemis/src/phonemis/base/processor/common/constants.h +10 -0
  27. package/third-party/common/phonemis/src/phonemis/base/processor/common/context.cpp +105 -0
  28. package/third-party/common/phonemis/src/phonemis/base/processor/common/context.h +49 -0
  29. package/third-party/common/phonemis/src/phonemis/base/processor/common/document.cpp +173 -0
  30. package/third-party/common/phonemis/src/phonemis/base/processor/common/document.h +67 -0
  31. package/third-party/common/phonemis/src/phonemis/base/processor/common/text.cpp +75 -0
  32. package/third-party/common/phonemis/src/phonemis/base/processor/common/text.h +60 -0
  33. package/third-party/common/phonemis/src/phonemis/base/processor/common/types.h +18 -0
  34. package/third-party/common/phonemis/src/phonemis/base/processor/config.h +53 -0
  35. package/third-party/common/phonemis/src/phonemis/base/processor/layer.h +9 -7
  36. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/constants.h +20 -0
  37. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.cpp +89 -0
  38. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.h +35 -0
  39. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/types.h +16 -0
  40. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/kind.h +40 -0
  41. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/layer.h +382 -0
  42. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/notation.h +30 -0
  43. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.cpp +51 -0
  44. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.h +31 -0
  45. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern.h +30 -0
  46. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.cpp +17 -0
  47. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.h +31 -0
  48. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.cpp +811 -0
  49. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.h +285 -0
  50. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.cpp +64 -0
  51. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.h +23 -0
  52. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/types.h +94 -0
  53. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sanitizer/layer.cpp +19 -0
  54. package/third-party/common/phonemis/src/phonemis/base/processor/{sanitizer_layer.h → layers/sanitizer/layer.h} +8 -8
  55. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.cpp +65 -0
  56. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.h +29 -0
  57. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.cpp +170 -0
  58. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.h +40 -0
  59. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/types.h +25 -0
  60. package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.cpp +47 -0
  61. package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.h +19 -0
  62. package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.cpp +60 -0
  63. package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.h +45 -0
  64. package/third-party/common/phonemis/src/phonemis/base/processor/processor.cpp +6 -7
  65. package/third-party/common/phonemis/src/phonemis/base/processor/processor.h +14 -10
  66. package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.cpp +89 -52
  67. package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.h +16 -9
  68. package/third-party/common/phonemis/src/phonemis/base/tokenizer/tokenizer.cpp +13 -12
  69. package/third-party/common/phonemis/src/phonemis/lang/de/constants.h +183 -19
  70. package/third-party/common/phonemis/src/phonemis/lang/de/num2word.cpp +355 -309
  71. package/third-party/common/phonemis/src/phonemis/lang/de/num2word.h +42 -17
  72. package/third-party/common/phonemis/src/phonemis/lang/de/patterns.cpp +56 -0
  73. package/third-party/common/phonemis/src/phonemis/lang/de/patterns.h +15 -0
  74. package/third-party/common/phonemis/src/phonemis/lang/de/pipeline.h +3 -3
  75. package/third-party/common/phonemis/src/phonemis/lang/en/constants.h +181 -30
  76. package/third-party/common/phonemis/src/phonemis/lang/en/hmm_tagger.cpp +5 -7
  77. package/third-party/common/phonemis/src/phonemis/lang/en/num2word.cpp +232 -135
  78. package/third-party/common/phonemis/src/phonemis/lang/en/num2word.h +41 -16
  79. package/third-party/common/phonemis/src/phonemis/lang/en/pipeline.h +3 -10
  80. package/third-party/common/phonemis/src/phonemis/lang/es/constants.h +182 -60
  81. package/third-party/common/phonemis/src/phonemis/lang/es/num2word.cpp +247 -212
  82. package/third-party/common/phonemis/src/phonemis/lang/es/num2word.h +38 -18
  83. package/third-party/common/phonemis/src/phonemis/lang/es/patterns.cpp +50 -0
  84. package/third-party/common/phonemis/src/phonemis/lang/es/patterns.h +15 -0
  85. package/third-party/common/phonemis/src/phonemis/lang/es/pipeline.h +3 -3
  86. package/third-party/common/phonemis/src/phonemis/lang/fr/constants.h +152 -26
  87. package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.cpp +252 -179
  88. package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.h +38 -15
  89. package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.cpp +83 -0
  90. package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.h +15 -0
  91. package/third-party/common/phonemis/src/phonemis/lang/fr/pipeline.h +3 -3
  92. package/third-party/common/phonemis/src/phonemis/lang/hi/constants.h +62 -10
  93. package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.cpp +74 -123
  94. package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.h +27 -16
  95. package/third-party/common/phonemis/src/phonemis/lang/hi/pipeline.h +5 -3
  96. package/third-party/common/phonemis/src/phonemis/lang/it/constants.h +122 -42
  97. package/third-party/common/phonemis/src/phonemis/lang/it/num2word.cpp +200 -207
  98. package/third-party/common/phonemis/src/phonemis/lang/it/num2word.h +30 -18
  99. package/third-party/common/phonemis/src/phonemis/lang/it/patterns.cpp +25 -0
  100. package/third-party/common/phonemis/src/phonemis/lang/it/patterns.h +15 -0
  101. package/third-party/common/phonemis/src/phonemis/lang/it/pipeline.h +3 -3
  102. package/third-party/common/phonemis/src/phonemis/lang/pl/constants.h +346 -77
  103. package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.cpp +631 -246
  104. package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.h +47 -15
  105. package/third-party/common/phonemis/src/phonemis/lang/pl/pipeline.h +6 -6
  106. package/third-party/common/phonemis/src/phonemis/lang/pt/constants.h +201 -0
  107. package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.cpp +365 -0
  108. package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.h +53 -0
  109. package/third-party/common/phonemis/src/phonemis/lang/pt/pipeline.h +4 -2
  110. package/third-party/common/phonemis/src/phonemis/main.cpp +42 -11
  111. package/third-party/common/phonemis/src/phonemis/protophone/meta.h +24 -0
  112. package/third-party/common/phonemis/src/phonemis/protophone/numeric.h +26 -0
  113. package/third-party/common/phonemis/src/phonemis/protophone/protophone.cpp +525 -0
  114. package/third-party/common/phonemis/src/phonemis/protophone/protophone.h +80 -0
  115. package/third-party/common/phonemis/src/phonemis/protophone/tensor.h +76 -0
  116. package/third-party/common/phonemis/src/phonemis/protophone/tensor_utils.h +89 -0
  117. package/third-party/common/phonemis/src/phonemis/protophone/tensor_view.h +125 -0
  118. package/third-party/common/phonemis/src/phonemis/protophone/types.h +43 -0
  119. package/third-party/common/phonemis/src/phonemis/utils/strings.h +20 -14
  120. package/third-party/common/phonemis/src/phonemis/utils/unicode.h +15 -1
  121. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_arithmetic.hpp +267 -0
  122. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_bit.hpp +232 -0
  123. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_cast.hpp +43 -0
  124. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_complex.hpp +112 -0
  125. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_details.hpp +386 -0
  126. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_logical.hpp +240 -0
  127. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_math.hpp +2601 -0
  128. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_memory.hpp +1006 -0
  129. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_rounding.hpp +72 -0
  130. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_swizzle.hpp +260 -0
  131. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_trigo.hpp +996 -0
  132. package/third-party/common/phonemis/src/third-party/xsimd/arch/utils/shifts.hpp +82 -0
  133. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx.hpp +2111 -0
  134. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2.hpp +1591 -0
  135. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2_128.hpp +170 -0
  136. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512bw.hpp +724 -0
  137. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512cd.hpp +28 -0
  138. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512dq.hpp +270 -0
  139. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512er.hpp +17 -0
  140. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512f.hpp +2919 -0
  141. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512ifma.hpp +17 -0
  142. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512pf.hpp +17 -0
  143. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi.hpp +76 -0
  144. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi2.hpp +130 -0
  145. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512bw.hpp +17 -0
  146. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512vbmi2.hpp +17 -0
  147. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx_128.hpp +164 -0
  148. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avxvnni.hpp +17 -0
  149. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common.hpp +26 -0
  150. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common_fwd.hpp +127 -0
  151. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_constants.hpp +393 -0
  152. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_emulated.hpp +787 -0
  153. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx.hpp +93 -0
  154. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx2.hpp +46 -0
  155. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_sse.hpp +97 -0
  156. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma4.hpp +92 -0
  157. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_i8mm_neon64.hpp +17 -0
  158. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_isa.hpp +148 -0
  159. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon.hpp +3580 -0
  160. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon64.hpp +1614 -0
  161. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_rvv.hpp +1515 -0
  162. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_scalar.hpp +1210 -0
  163. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse2.hpp +2333 -0
  164. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse3.hpp +66 -0
  165. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_1.hpp +510 -0
  166. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_2.hpp +44 -0
  167. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_ssse3.hpp +186 -0
  168. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sve.hpp +1186 -0
  169. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vsx.hpp +947 -0
  170. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vxe.hpp +787 -0
  171. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_wasm.hpp +1819 -0
  172. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_arch.hpp +242 -0
  173. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_config.hpp +633 -0
  174. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features.hpp +50 -0
  175. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_arm.hpp +132 -0
  176. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_ppc.hpp +54 -0
  177. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_riscv.hpp +95 -0
  178. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_s390x.hpp +56 -0
  179. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_x86.hpp +1121 -0
  180. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpuid.hpp +144 -0
  181. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_getauxval.hpp +159 -0
  182. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_macros.hpp +78 -0
  183. package/third-party/common/phonemis/src/third-party/xsimd/math/xsimd_rem_pio2.hpp +707 -0
  184. package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_aligned_allocator.hpp +349 -0
  185. package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_alignment.hpp +102 -0
  186. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_all_registers.hpp +57 -0
  187. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_api.hpp +3106 -0
  188. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx2_register.hpp +57 -0
  189. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512bw_register.hpp +51 -0
  190. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512cd_register.hpp +51 -0
  191. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512dq_register.hpp +51 -0
  192. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512er_register.hpp +51 -0
  193. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512f_register.hpp +77 -0
  194. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512ifma_register.hpp +51 -0
  195. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512pf_register.hpp +51 -0
  196. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi2_register.hpp +51 -0
  197. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi_register.hpp +51 -0
  198. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512bw_register.hpp +54 -0
  199. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512vbmi2_register.hpp +53 -0
  200. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx_register.hpp +79 -0
  201. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avxvnni_register.hpp +44 -0
  202. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch.hpp +1666 -0
  203. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_constant.hpp +572 -0
  204. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_fwd.hpp +41 -0
  205. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_common_arch.hpp +49 -0
  206. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_emulated_register.hpp +80 -0
  207. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx2_register.hpp +50 -0
  208. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx_register.hpp +50 -0
  209. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_sse_register.hpp +50 -0
  210. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma4_register.hpp +50 -0
  211. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_i8mm_neon64_register.hpp +55 -0
  212. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon64_register.hpp +55 -0
  213. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon_register.hpp +130 -0
  214. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_register.hpp +96 -0
  215. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_rvv_register.hpp +491 -0
  216. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse2_register.hpp +59 -0
  217. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse3_register.hpp +49 -0
  218. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_1_register.hpp +48 -0
  219. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_2_register.hpp +48 -0
  220. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_ssse3_register.hpp +48 -0
  221. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sve_register.hpp +216 -0
  222. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_traits.hpp +409 -0
  223. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_utils.hpp +462 -0
  224. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vsx_register.hpp +84 -0
  225. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vxe_register.hpp +86 -0
  226. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_wasm_register.hpp +59 -0
  227. package/third-party/common/phonemis/src/third-party/xsimd/utils/bits.hpp +122 -0
  228. package/third-party/common/phonemis/src/third-party/xsimd/utils/xsimd_type_traits.hpp +145 -0
  229. package/third-party/common/phonemis/src/third-party/xsimd/xsimd.hpp +43 -0
  230. package/third-party/common/phonemis/src/phonemis/base/processor/constants.h +0 -11
  231. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/config.h +0 -16
  232. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.cpp +0 -271
  233. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.h +0 -45
  234. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/types.h +0 -29
  235. package/third-party/common/phonemis/src/phonemis/base/processor/sanitizer_layer.cpp +0 -22
  236. package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.cpp +0 -40
  237. package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.h +0 -22
@@ -0,0 +1,2601 @@
1
+ /***************************************************************************
2
+ * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3
+ * Martin Renou *
4
+ * Copyright (c) QuantStack *
5
+ * Copyright (c) Serge Guelton *
6
+ * *
7
+ * Distributed under the terms of the BSD 3-Clause License. *
8
+ * *
9
+ * The full license is in the file LICENSE, distributed with this software. *
10
+ ****************************************************************************/
11
+
12
+ #ifndef XSIMD_COMMON_MATH_HPP
13
+ #define XSIMD_COMMON_MATH_HPP
14
+
15
+ #include "../xsimd_scalar.hpp"
16
+ #include "./xsimd_common_details.hpp"
17
+ #include "./xsimd_common_trigo.hpp"
18
+
19
+ #include <type_traits>
20
+
21
+ namespace xsimd
22
+ {
23
+
24
+ namespace kernel
25
+ {
26
+
27
+ using namespace types;
28
+ // abs
29
+ template <class A, class T, class>
30
+ XSIMD_INLINE batch<T, A> abs(batch<T, A> const& self, requires_arch<common>) noexcept
31
+ {
32
+ if (std::is_unsigned<T>::value)
33
+ return self;
34
+ else
35
+ {
36
+ auto sign = bitofsign(self);
37
+ auto inv = self ^ sign;
38
+ return inv - sign;
39
+ }
40
+ }
41
+
42
+ template <class A, class T>
43
+ XSIMD_INLINE batch<T, A> abs(batch<std::complex<T>, A> const& z, requires_arch<common>) noexcept
44
+ {
45
+ return hypot(z.real(), z.imag());
46
+ }
47
+
48
+ // avg
49
+ namespace detail
50
+ {
51
+ template <class A, class T>
52
+ XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::true_type, std::false_type) noexcept
53
+ {
54
+ return (x & y) + ((x ^ y) >> 1);
55
+ }
56
+
57
+ template <class A, class T>
58
+ XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::true_type, std::true_type) noexcept
59
+ {
60
+ // Inspired by
61
+ // https://stackoverflow.com/questions/5697500/take-the-average-of-two-signed-numbers-in-c
62
+ auto t = (x & y) + ((x ^ y) >> 1);
63
+ auto t_u = bitwise_cast<std::make_unsigned_t<T>>(t);
64
+ auto avg = t + (bitwise_cast<T>(t_u >> (8 * sizeof(T) - 1)) & (x ^ y));
65
+ return avg;
66
+ }
67
+
68
+ template <class A, class T>
69
+ XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, std::false_type, std::true_type) noexcept
70
+ {
71
+ return (x + y) / 2;
72
+ }
73
+ }
74
+
75
+ template <class A, class T>
76
+ XSIMD_INLINE batch<T, A> avg(batch<T, A> const& x, batch<T, A> const& y, requires_arch<common>) noexcept
77
+ {
78
+ return detail::avg(x, y, typename std::is_integral<T>::type {}, typename std::is_signed<T>::type {});
79
+ }
80
+
81
+ // avgr
82
+ namespace detail
83
+ {
84
+ template <class A, class T>
85
+ XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, std::true_type) noexcept
86
+ {
87
+ constexpr unsigned shift = 8 * sizeof(T) - 1;
88
+ auto adj = std::is_signed<T>::value ? ((x ^ y) & 0x1) : (((x ^ y) << shift) >> shift);
89
+ return ::xsimd::kernel::avg(x, y, A {}) + adj;
90
+ }
91
+
92
+ template <class A, class T>
93
+ XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, std::false_type) noexcept
94
+ {
95
+ return ::xsimd::kernel::avg(x, y, A {});
96
+ }
97
+ }
98
+
99
+ template <class A, class T>
100
+ XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& x, batch<T, A> const& y, requires_arch<common>) noexcept
101
+ {
102
+ return detail::avgr(x, y, typename std::is_integral<T>::type {});
103
+ }
104
+
105
+ // batch_cast
106
+ template <class A, class T>
107
+ XSIMD_INLINE batch<T, A> batch_cast(batch<T, A> const& self, batch<T, A> const&, requires_arch<common>) noexcept
108
+ {
109
+ return self;
110
+ }
111
+
112
+ namespace detail
113
+ {
114
+ template <class A, class T_out, class T_in>
115
+ XSIMD_INLINE batch<T_out, A> batch_cast(batch<T_in, A> const& self, batch<T_out, A> const& out, requires_arch<common>, with_fast_conversion) noexcept
116
+ {
117
+ return fast_cast(self, out, A {});
118
+ }
119
+ #if defined(__clang__) || __GNUC__
120
+ template <class A, class T_out, class T_in>
121
+ XSIMD_INLINE batch<T_out, A> batch_cast(batch<T_in, A> const& self, batch<T_out, A> const&, requires_arch<common>, with_slow_conversion) noexcept
122
+ __attribute__((no_sanitize("undefined")));
123
+ #endif
124
+ template <class A, class T_out, class T_in>
125
+ XSIMD_INLINE batch<T_out, A> batch_cast(batch<T_in, A> const& self, batch<T_out, A> const&, requires_arch<common>, with_slow_conversion) noexcept
126
+ {
127
+ static_assert(!std::is_same<T_in, T_out>::value, "there should be no conversion for this type combination");
128
+ using batch_type_in = batch<T_in, A>;
129
+ using batch_type_out = batch<T_out, A>;
130
+ static_assert(batch_type_in::size == batch_type_out::size, "compatible sizes");
131
+ alignas(A::alignment()) T_in buffer_in[batch_type_in::size];
132
+ alignas(A::alignment()) T_out buffer_out[batch_type_out::size];
133
+ self.store_aligned(&buffer_in[0]);
134
+ for (size_t i = 0; i < batch_type_in::size; ++i)
135
+ buffer_out[i] = static_cast<T_out>(buffer_in[i]);
136
+ return batch_type_out::load_aligned(buffer_out);
137
+ }
138
+
139
+ }
140
+
141
+ template <class A, class T_out, class T_in>
142
+ XSIMD_INLINE batch<T_out, A> batch_cast(batch<T_in, A> const& self, batch<T_out, A> const& out, requires_arch<common>) noexcept
143
+ {
144
+ return detail::batch_cast(self, out, A {}, detail::conversion_type<A, T_in, T_out> {});
145
+ }
146
+
147
+ // bitofsign
148
+ template <class A, class T>
149
+ XSIMD_INLINE batch<T, A> bitofsign(batch<T, A> const& self, requires_arch<common>) noexcept
150
+ {
151
+ static_assert(std::is_integral<T>::value, "int type implementation");
152
+ if (std::is_unsigned<T>::value)
153
+ return batch<T, A>(0);
154
+ else
155
+ return self >> (T)(8 * sizeof(T) - 1);
156
+ }
157
+
158
+ template <class A>
159
+ XSIMD_INLINE batch<float, A> bitofsign(batch<float, A> const& self, requires_arch<common>) noexcept
160
+ {
161
+ return self & constants::signmask<batch<float, A>>();
162
+ }
163
+ template <class A>
164
+ XSIMD_INLINE batch<double, A> bitofsign(batch<double, A> const& self, requires_arch<common>) noexcept
165
+ {
166
+ return self & constants::signmask<batch<double, A>>();
167
+ }
168
+
169
+ // bitwise_cast
170
+ template <class A, class T>
171
+ XSIMD_INLINE batch<T, A> bitwise_cast(batch<T, A> const& self, batch<T, A> const&, requires_arch<common>) noexcept
172
+ {
173
+ return self;
174
+ }
175
+
176
+ // cbrt
177
+ /* origin: boost/simd/arch/common/simd/function/cbrt.hpp */
178
+ /*
179
+ * ====================================================
180
+ * copyright 2016 NumScale SAS
181
+ *
182
+ * Distributed under the Boost Software License, Version 1.0.
183
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
184
+ * ====================================================
185
+ */
186
+ template <class A>
187
+ XSIMD_INLINE batch<float, A> cbrt(batch<float, A> const& self, requires_arch<common>) noexcept
188
+ {
189
+ using batch_type = batch<float, A>;
190
+ batch_type z = abs(self);
191
+ #ifndef XSIMD_NO_DENORMALS
192
+ auto denormal = z < constants::smallestposval<batch_type>();
193
+ z = select(denormal, z * constants::twotonmb<batch_type>(), z);
194
+ batch_type f = select(denormal, constants::twotonmbo3<batch_type>(), batch_type(1.));
195
+ #endif
196
+ const batch_type CBRT2(bit_cast<float>(0x3fa14518));
197
+ const batch_type CBRT4(bit_cast<float>(0x3fcb2ff5));
198
+ const batch_type CBRT2I(bit_cast<float>(0x3f4b2ff5));
199
+ const batch_type CBRT4I(bit_cast<float>(0x3f214518));
200
+ using i_type = as_integer_t<batch_type>;
201
+ i_type e;
202
+ batch_type x = frexp(z, e);
203
+ x = detail::horner<batch_type,
204
+ 0x3ece0609,
205
+ 0x3f91eb77,
206
+ 0xbf745265,
207
+ 0x3f0bf0fe,
208
+ 0xbe09e49a>(x);
209
+ auto flag = e >= i_type(0);
210
+ i_type e1 = abs(e);
211
+ i_type rem = e1;
212
+ e1 /= i_type(3);
213
+ rem -= e1 * i_type(3);
214
+ e = e1 * sign(e);
215
+ const batch_type cbrt2 = select(batch_bool_cast<float>(flag), CBRT2, CBRT2I);
216
+ const batch_type cbrt4 = select(batch_bool_cast<float>(flag), CBRT4, CBRT4I);
217
+ batch_type fact = select(batch_bool_cast<float>(rem == i_type(1)), cbrt2, batch_type(1.));
218
+ fact = select(batch_bool_cast<float>(rem == i_type(2)), cbrt4, fact);
219
+ x = ldexp(x * fact, e);
220
+ x -= (x - z / (x * x)) * batch_type(1.f / 3.f);
221
+ #ifndef XSIMD_NO_DENORMALS
222
+ x = (x | bitofsign(self)) * f;
223
+ #else
224
+ x = x | bitofsign(self);
225
+ #endif
226
+ #ifndef XSIMD_NO_INFINITIES
227
+ return select(self == batch_type(0.) || isinf(self), self, x);
228
+ #else
229
+ return select(self == batch_type(0.), self, x);
230
+ #endif
231
+ }
232
+
233
+ template <class A>
234
+ XSIMD_INLINE batch<double, A> cbrt(batch<double, A> const& self, requires_arch<common>) noexcept
235
+ {
236
+ using batch_type = batch<double, A>;
237
+ batch_type z = abs(self);
238
+ #ifndef XSIMD_NO_DENORMALS
239
+ auto denormal = z < constants::smallestposval<batch_type>();
240
+ z = select(denormal, z * constants::twotonmb<batch_type>(), z);
241
+ batch_type f = select(denormal, constants::twotonmbo3<batch_type>(), batch_type(1.));
242
+ #endif
243
+ const batch_type CBRT2(bit_cast<double>(int64_t(0x3ff428a2f98d728b)));
244
+ const batch_type CBRT4(bit_cast<double>(int64_t(0x3ff965fea53d6e3d)));
245
+ const batch_type CBRT2I(bit_cast<double>(int64_t(0x3fe965fea53d6e3d)));
246
+ const batch_type CBRT4I(bit_cast<double>(int64_t(0x3fe428a2f98d728b)));
247
+ using i_type = as_integer_t<batch_type>;
248
+ i_type e;
249
+ batch_type x = frexp(z, e);
250
+ x = detail::horner<batch_type,
251
+ 0x3fd9c0c12122a4feull,
252
+ 0x3ff23d6ee505873aull,
253
+ 0xbfee8a4ca3ba37b8ull,
254
+ 0x3fe17e1fc7e59d58ull,
255
+ 0xbfc13c93386fdff6ull>(x);
256
+ auto flag = e >= typename i_type::value_type(0);
257
+ i_type e1 = abs(e);
258
+ i_type rem = e1;
259
+ e1 /= i_type(3);
260
+ rem -= e1 * i_type(3);
261
+ e = e1 * sign(e);
262
+ const batch_type cbrt2 = select(batch_bool_cast<double>(flag), CBRT2, CBRT2I);
263
+ const batch_type cbrt4 = select(batch_bool_cast<double>(flag), CBRT4, CBRT4I);
264
+ batch_type fact = select(batch_bool_cast<double>(rem == i_type(1)), cbrt2, batch_type(1.));
265
+ fact = select(batch_bool_cast<double>(rem == i_type(2)), cbrt4, fact);
266
+ x = ldexp(x * fact, e);
267
+ x -= (x - z / (x * x)) * batch_type(1. / 3.);
268
+ x -= (x - z / (x * x)) * batch_type(1. / 3.);
269
+ #ifndef XSIMD_NO_DENORMALS
270
+ x = (x | bitofsign(self)) * f;
271
+ #else
272
+ x = x | bitofsign(self);
273
+ #endif
274
+ #ifndef XSIMD_NO_INFINITIES
275
+ return select(self == batch_type(0.) || isinf(self), self, x);
276
+ #else
277
+ return select(self == batch_type(0.), self, x);
278
+ #endif
279
+ }
280
+
281
+ // clip
282
+ template <class A, class T>
283
+ XSIMD_INLINE batch<T, A> clip(batch<T, A> const& self, batch<T, A> const& lo, batch<T, A> const& hi, requires_arch<common>) noexcept
284
+ {
285
+ return min(hi, max(self, lo));
286
+ }
287
+
288
+ // copysign
289
+ template <class A, class T, class = std::enable_if_t<std::is_floating_point<T>::value>>
290
+ XSIMD_INLINE batch<T, A> copysign(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
291
+ {
292
+ return abs(self) | bitofsign(other);
293
+ }
294
+
295
+ // erf
296
+
297
+ namespace detail
298
+ {
299
+ /* origin: boost/simd/arch/common/detail/common/erf_kernel.hpp */
300
+ /*
301
+ * ====================================================
302
+ * copyright 2016 NumScale SAS
303
+ *
304
+ * Distributed under the Boost Software License, Version 1.0.
305
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
306
+ * ====================================================
307
+ */
308
+ template <class B>
309
+ struct erf_kernel;
310
+
311
+ template <class A>
312
+ struct erf_kernel<batch<float, A>>
313
+ {
314
+ using batch_type = batch<float, A>;
315
+ // computes erf(a0)/a0
316
+ // x is sqr(a0) and 0 <= abs(a0) <= 2/3
317
+ static XSIMD_INLINE batch_type erf1(const batch_type& x) noexcept
318
+ {
319
+ return detail::horner<batch_type,
320
+ 0x3f906eba, // 1.128379154774254e+00
321
+ 0xbec0937e, // -3.761252839094832e-01
322
+ 0x3de70f22, // 1.128218315189123e-01
323
+ 0xbcdb61f4, // -2.678010670585737e-02
324
+ 0x3ba4468d, // 5.013293006147870e-03
325
+ 0xba1fc83b // -6.095205117313012e-04
326
+ >(x);
327
+ }
328
+
329
+ // computes erfc(x)*exp(sqr(x))
330
+ // x >= 2/3
331
+ static XSIMD_INLINE batch_type erfc2(const batch_type& x) noexcept
332
+ {
333
+ return detail::horner<batch_type,
334
+ 0x3f0a0e8b, // 5.392844046572836e-01
335
+ 0xbf918a62, // -1.137035586823118e+00
336
+ 0x3e243828, // 1.603704761054187e-01
337
+ 0x3ec4ca6e, // 3.843569094305250e-01
338
+ 0x3e1175c7, // 1.420508523645926e-01
339
+ 0x3e2006f0, // 1.562764709849380e-01
340
+ 0xbfaea865, // -1.364514006347145e+00
341
+ 0x4050b063, // 3.260765682222576e+00
342
+ 0xc0cd1a85, // -6.409487379234005e+00
343
+ 0x40d67e3b, // 6.702908785399893e+00
344
+ 0xc0283611 // -2.628299919293280e+00
345
+ >(x);
346
+ }
347
+
348
+ static XSIMD_INLINE batch_type erfc3(const batch_type& x) noexcept
349
+ {
350
+ return (batch_type(1.) - x) * detail::horner<batch_type,
351
+ 0x3f7ffffe, // 9.9999988e-01
352
+ 0xbe036d7e, // -1.2834737e-01
353
+ 0xbfa11698, // -1.2585020e+00
354
+ 0xbffc9284, // -1.9732213e+00
355
+ 0xc016c985, // -2.3560498e+00
356
+ 0x3f2cff3b, // 6.7576951e-01
357
+ 0xc010d956, // -2.2632651e+00
358
+ 0x401b5680, // 2.4271545e+00
359
+ 0x41aa8e55 // 2.1319498e+01
360
+ >(x);
361
+ }
362
+ };
363
+
364
+ template <class A>
365
+ struct erf_kernel<batch<double, A>>
366
+ {
367
+ using batch_type = batch<double, A>;
368
+ // computes erf(a0)/a0
369
+ // x is sqr(a0) and 0 <= abs(a0) <= 0.65
370
+ static XSIMD_INLINE batch_type erf1(const batch_type& x) noexcept
371
+ {
372
+ return detail::horner<batch_type,
373
+ 0x3ff20dd750429b61ull, // 1.12837916709551
374
+ 0x3fc16500f106c0a5ull, // 0.135894887627278
375
+ 0x3fa4a59a4f02579cull, // 4.03259488531795E-02
376
+ 0x3f53b7664358865aull, // 1.20339380863079E-03
377
+ 0x3f110512d5b20332ull // 6.49254556481904E-05
378
+ >(x)
379
+ / detail::horner<batch_type,
380
+ 0x3ff0000000000000ull, // 1
381
+ 0x3fdd0a84eb1ca867ull, // 0.453767041780003
382
+ 0x3fb64536ca92ea2full, // 8.69936222615386E-02
383
+ 0x3f8166f75999dbd1ull, // 8.49717371168693E-03
384
+ 0x3f37ea4332348252ull // 3.64915280629351E-04
385
+ >(x);
386
+ }
387
+
388
+ // computes erfc(x)*exp(x*x)
389
+ // 0.65 <= abs(x) <= 2.2
390
+ static XSIMD_INLINE batch_type erfc2(const batch_type& x) noexcept
391
+ {
392
+ return detail::horner<batch_type,
393
+ 0x3feffffffbbb552bull, // 0.999999992049799
394
+ 0x3ff54dfe9b258a60ull, // 1.33154163936765
395
+ 0x3fec1986509e687bull, // 0.878115804155882
396
+ 0x3fd53dd7a67c7e9full, // 0.331899559578213
397
+ 0x3fb2488a6b5cb5e5ull, // 7.14193832506776E-02
398
+ 0x3f7cf4cfe0aacbb4ull, // 7.06940843763253E-03
399
+ 0x0ull // 0
400
+ >(x)
401
+ / detail::horner<batch_type,
402
+ 0x3ff0000000000000ull, // 1
403
+ 0x4003adeae79b9708ull, // 2.45992070144246
404
+ 0x40053b1052dca8bdull, // 2.65383972869776
405
+ 0x3ff9e677c2777c3cull, // 1.61876655543871
406
+ 0x3fe307622fcff772ull, // 0.594651311286482
407
+ 0x3fc033c113a7deeeull, // 0.126579413030178
408
+ 0x3f89a996639b0d00ull // 1.25304936549413E-02
409
+ >(x);
410
+ }
411
+
412
+ // computes erfc(x)*exp(x*x)
413
+ // 2.2 <= abs(x) <= 6
414
+ static XSIMD_INLINE batch_type erfc3(const batch_type& x) noexcept
415
+ {
416
+ return detail::horner<batch_type,
417
+ 0x3fefff5a9e697ae2ull, // 0.99992114009714
418
+ 0x3ff9fa202deb88e5ull, // 1.62356584489367
419
+ 0x3ff44744306832aeull, // 1.26739901455873
420
+ 0x3fe29be1cff90d94ull, // 0.581528574177741
421
+ 0x3fc42210f88b9d43ull, // 0.157289620742839
422
+ 0x3f971d0907ea7a92ull, // 2.25716982919218E-02
423
+ 0x0ll // 0
424
+ >(x)
425
+ / detail::horner<batch_type,
426
+ 0x3ff0000000000000ull, // 1
427
+ 0x400602f24bf3fdb6ull, // 2.75143870676376
428
+ 0x400afd487397568full, // 3.37367334657285
429
+ 0x400315ffdfd5ce91ull, // 2.38574194785344
430
+ 0x3ff0cfd4cb6cde9full, // 1.05074004614827
431
+ 0x3fd1d7ab774bb837ull, // 0.278788439273629
432
+ 0x3fa47bd61bbb3843ull // 4.00072964526861E-02
433
+ >(x);
434
+ }
435
+
436
+ // computes erfc(rx)*exp(rx*rx)
437
+ // x >= 6 rx = 1/x
438
+ static XSIMD_INLINE batch_type erfc4(const batch_type& x) noexcept
439
+ {
440
+ return detail::horner<batch_type,
441
+ 0xbc7e4ad1ec7d0000ll, // -2.627435221016534e-17
442
+ 0x3fe20dd750429a16ll, // 5.641895835477182e-01
443
+ 0x3db60000e984b501ll, // 2.000889609806154e-11
444
+ 0xbfd20dd753ae5dfdll, // -2.820947949598745e-01
445
+ 0x3e907e71e046a820ll, // 2.457786367990903e-07
446
+ 0x3fdb1494cac06d39ll, // 4.231311779019112e-01
447
+ 0x3f34a451701654f1ll, // 3.149699042180451e-04
448
+ 0xbff105e6b8ef1a63ll, // -1.063940737150596e+00
449
+ 0x3fb505a857e9ccc8ll, // 8.211757799454056e-02
450
+ 0x40074fbabc514212ll, // 2.913930388669777e+00
451
+ 0x4015ac7631f7ac4fll, // 5.418419628850713e+00
452
+ 0xc0457e03041e9d8bll, // -4.298446704382794e+01
453
+ 0x4055803d26c4ec4fll, // 8.600373238783617e+01
454
+ 0xc0505fce04ec4ec5ll // -6.549694941594051e+01
455
+ >(x);
456
+ }
457
+ };
458
+ }
459
+ /* origin: boost/simd/arch/common/simd/function/erf.hpp */
460
+ /*
461
+ * ====================================================
462
+ * copyright 2016 NumScale SAS
463
+ *
464
+ * Distributed under the Boost Software License, Version 1.0.
465
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
466
+ * ====================================================
467
+ */
468
+
469
+ template <class A>
470
+ XSIMD_INLINE batch<float, A> erf(batch<float, A> const& self, requires_arch<common>) noexcept
471
+ {
472
+ using batch_type = batch<float, A>;
473
+ batch_type x = abs(self);
474
+ batch_type r1(0.);
475
+ auto test1 = x < batch_type(2.f / 3.f);
476
+ if (any(test1))
477
+ {
478
+ r1 = self * detail::erf_kernel<batch_type>::erf1(x * x);
479
+ if (all(test1))
480
+ return r1;
481
+ }
482
+ batch_type z = x / (batch_type(1.) + x);
483
+ z -= batch_type(0.4f);
484
+ batch_type r2 = batch_type(1.) - exp(-x * x) * detail::erf_kernel<batch_type>::erfc2(z);
485
+ r2 = select(self < batch_type(0.), -r2, r2);
486
+ r1 = select(test1, r1, r2);
487
+ #ifndef XSIMD_NO_INFINITIES
488
+ r1 = select(xsimd::isinf(self), sign(self), r1);
489
+ #endif
490
+ return r1;
491
+ }
492
+
493
+ template <class A>
494
+ XSIMD_INLINE batch<double, A> erf(batch<double, A> const& self, requires_arch<common>) noexcept
495
+ {
496
+ using batch_type = batch<double, A>;
497
+ batch_type x = abs(self);
498
+ batch_type xx = x * x;
499
+ batch_type lim1(0.65);
500
+ batch_type lim2(2.2);
501
+ auto test1 = x < lim1;
502
+ batch_type r1(0.);
503
+ if (any(test1))
504
+ {
505
+ r1 = self * detail::erf_kernel<batch_type>::erf1(xx);
506
+ if (all(test1))
507
+ return r1;
508
+ }
509
+ auto test2 = x < lim2;
510
+ auto test3 = test2 && !test1;
511
+ batch_type ex = exp(-xx);
512
+ if (any(test3))
513
+ {
514
+ batch_type z = batch_type(1.) - ex * detail::erf_kernel<batch_type>::erfc2(x);
515
+ batch_type r2 = select(self < batch_type(0.), -z, z);
516
+ r1 = select(test1, r1, r2);
517
+ if (all(test1 || test3))
518
+ return r1;
519
+ }
520
+ batch_type z = batch_type(1.) - ex * detail::erf_kernel<batch_type>::erfc3(x);
521
+ z = select(self < batch_type(0.), -z, z);
522
+ #ifndef XSIMD_NO_INFINITIES
523
+ z = select(xsimd::isinf(self), sign(self), z);
524
+ #endif
525
+ return select(test2, r1, z);
526
+ }
527
+
528
+ // erfc
529
+ template <class A>
530
+ XSIMD_INLINE batch<float, A> erfc(batch<float, A> const& self, requires_arch<common>) noexcept
531
+ {
532
+ using batch_type = batch<float, A>;
533
+ batch_type x = abs(self);
534
+ auto test0 = self < batch_type(0.);
535
+ batch_type r1(0.);
536
+ auto test1 = 3.f * x < 2.f;
537
+ batch_type z = x / (batch_type(1.) + x);
538
+ if (any(test1))
539
+ {
540
+ r1 = detail::erf_kernel<batch_type>::erfc3(z);
541
+ if (all(test1))
542
+ return select(test0, batch_type(2.) - r1, r1);
543
+ }
544
+
545
+ z -= batch_type(0.4f);
546
+ batch_type r2 = exp(-x * x) * detail::erf_kernel<batch_type>::erfc2(z);
547
+ r1 = select(test1, r1, r2);
548
+ #ifndef XSIMD_NO_INFINITIES
549
+ r1 = select(x == constants::infinity<batch_type>(), batch_type(0.), r1);
550
+ #endif
551
+ return select(test0, batch_type(2.) - r1, r1);
552
+ }
553
+
554
+ template <class A>
555
+ XSIMD_INLINE batch<double, A> erfc(batch<double, A> const& self, requires_arch<common>) noexcept
556
+ {
557
+ using batch_type = batch<double, A>;
558
+ batch_type x = abs(self);
559
+ batch_type xx = x * x;
560
+ batch_type lim1(0.65);
561
+ batch_type lim2(2.2);
562
+ auto test0 = self < batch_type(0.);
563
+ auto test1 = x < lim1;
564
+ batch_type r1(0.);
565
+ if (any(test1))
566
+ {
567
+ r1 = batch_type(1.) - x * detail::erf_kernel<batch_type>::erf1(xx);
568
+ if (all(test1))
569
+ return select(test0, batch_type(2.) - r1, r1);
570
+ }
571
+ auto test2 = x < lim2;
572
+ auto test3 = test2 && !test1;
573
+ batch_type ex = exp(-xx);
574
+ if (any(test3))
575
+ {
576
+ batch_type z = ex * detail::erf_kernel<batch_type>::erfc2(x);
577
+ r1 = select(test1, r1, z);
578
+ if (all(test1 || test3))
579
+ return select(test0, batch_type(2.) - r1, r1);
580
+ }
581
+ batch_type z = ex * detail::erf_kernel<batch_type>::erfc3(x);
582
+ r1 = select(test2, r1, z);
583
+ #ifndef XSIMD_NO_INFINITIES
584
+ r1 = select(x == constants::infinity<batch_type>(), batch_type(0.), r1);
585
+ #endif
586
+ return select(test0, batch_type(2.) - r1, r1);
587
+ }
588
+
589
+ // estrin
590
+ namespace detail
591
+ {
592
+
593
+ template <class B>
594
+ struct estrin
595
+ {
596
+ B x;
597
+
598
+ template <typename... Ts>
599
+ XSIMD_INLINE B operator()(const Ts&... coefs) noexcept
600
+ {
601
+ return eval(coefs...);
602
+ }
603
+
604
+ private:
605
+ XSIMD_INLINE B eval(const B& c0) noexcept
606
+ {
607
+ return c0;
608
+ }
609
+
610
+ XSIMD_INLINE B eval(const B& c0, const B& c1) noexcept
611
+ {
612
+ return fma(x, c1, c0);
613
+ }
614
+
615
+ template <size_t... Is, class Tuple>
616
+ XSIMD_INLINE B eval(std::index_sequence<Is...>, const Tuple& tuple)
617
+ {
618
+ return estrin { x * x }(std::get<Is>(tuple)...);
619
+ }
620
+
621
+ template <class... Args>
622
+ XSIMD_INLINE B eval(const std::tuple<Args...>& tuple) noexcept
623
+ {
624
+ return eval(std::make_index_sequence<sizeof...(Args)>(), tuple);
625
+ }
626
+
627
+ template <class... Args>
628
+ XSIMD_INLINE B eval(const std::tuple<Args...>& tuple, const B& c0) noexcept
629
+ {
630
+ return eval(std::tuple_cat(tuple, std::make_tuple(eval(c0))));
631
+ }
632
+
633
+ template <class... Args>
634
+ XSIMD_INLINE B eval(const std::tuple<Args...>& tuple, const B& c0, const B& c1) noexcept
635
+ {
636
+ return eval(std::tuple_cat(tuple, std::make_tuple(eval(c0, c1))));
637
+ }
638
+
639
+ template <class... Args, class... Ts>
640
+ XSIMD_INLINE B eval(const std::tuple<Args...>& tuple, const B& c0, const B& c1, const Ts&... coefs) noexcept
641
+ {
642
+ return eval(std::tuple_cat(tuple, std::make_tuple(eval(c0, c1))), coefs...);
643
+ }
644
+
645
+ template <class... Ts>
646
+ XSIMD_INLINE B eval(const B& c0, const B& c1, const Ts&... coefs) noexcept
647
+ {
648
+ return eval(std::make_tuple(eval(c0, c1)), coefs...);
649
+ }
650
+ };
651
+ }
652
+
653
+ template <class T, class A, uint64_t... Coefs>
654
+ XSIMD_INLINE batch<T, A> estrin(const batch<T, A>& self) noexcept
655
+ {
656
+ using batch_type = batch<T, A>;
657
+ return detail::estrin<batch_type> { self }(detail::coef<batch_type, Coefs>()...);
658
+ }
659
+
660
+ // exp
661
+ /* origin: boost/simd/arch/common/detail/simd/expo_base.hpp */
662
+ /*
663
+ * ====================================================
664
+ * copyright 2016 NumScale SAS
665
+ *
666
+ * Distributed under the Boost Software License, Version 1.0.
667
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
668
+ * ====================================================
669
+ */
670
+ namespace detail
671
+ {
672
+ enum exp_reduction_tag
673
+ {
674
+ exp_tag,
675
+ exp2_tag,
676
+ exp10_tag
677
+ };
678
+
679
+ template <class B, exp_reduction_tag Tag>
680
+ struct exp_reduction_base;
681
+
682
+ template <class B>
683
+ struct exp_reduction_base<B, exp_tag>
684
+ {
685
+ static constexpr B maxlog() noexcept
686
+ {
687
+ return constants::maxlog<B>();
688
+ }
689
+
690
+ static constexpr B minlog() noexcept
691
+ {
692
+ return constants::minlog<B>();
693
+ }
694
+ };
695
+
696
+ template <class B>
697
+ struct exp_reduction_base<B, exp10_tag>
698
+ {
699
+ static constexpr B maxlog() noexcept
700
+ {
701
+ return constants::maxlog10<B>();
702
+ }
703
+
704
+ static constexpr B minlog() noexcept
705
+ {
706
+ return constants::minlog10<B>();
707
+ }
708
+ };
709
+
710
+ template <class B>
711
+ struct exp_reduction_base<B, exp2_tag>
712
+ {
713
+ static constexpr B maxlog() noexcept
714
+ {
715
+ return constants::maxlog2<B>();
716
+ }
717
+
718
+ static constexpr B minlog() noexcept
719
+ {
720
+ return constants::minlog2<B>();
721
+ }
722
+ };
723
+
724
+ template <class T, class A, exp_reduction_tag Tag>
725
+ struct exp_reduction;
726
+
727
+ template <class A>
728
+ struct exp_reduction<float, A, exp_tag> : exp_reduction_base<batch<float, A>, exp_tag>
729
+ {
730
+ using batch_type = batch<float, A>;
731
+ static XSIMD_INLINE batch_type approx(const batch_type& x) noexcept
732
+ {
733
+ batch_type y = detail::horner<batch_type,
734
+ 0x3f000000, // 5.0000000e-01
735
+ 0x3e2aa9a5, // 1.6666277e-01
736
+ 0x3d2aa957, // 4.1665401e-02
737
+ 0x3c098d8b, // 8.3955629e-03
738
+ 0x3ab778cf // 1.3997796e-03
739
+ >(x);
740
+ return ++fma(y, x * x, x);
741
+ }
742
+
743
+ static XSIMD_INLINE batch_type reduce(const batch_type& a, batch_type& x) noexcept
744
+ {
745
+ batch_type k = nearbyint(constants::invlog_2<batch_type>() * a);
746
+ detail::reassociation_barrier(k, "compensated exp range reduction");
747
+ x = fnma(k, constants::log_2hi<batch_type>(), a);
748
+ detail::reassociation_barrier(x, "compensated exp range reduction");
749
+ x = fnma(k, constants::log_2lo<batch_type>(), x);
750
+ return k;
751
+ }
752
+ };
753
+
754
+ template <class A>
755
+ struct exp_reduction<float, A, exp10_tag> : exp_reduction_base<batch<float, A>, exp10_tag>
756
+ {
757
+ using batch_type = batch<float, A>;
758
+ static XSIMD_INLINE batch_type approx(const batch_type& x) noexcept
759
+ {
760
+ return ++(detail::horner<batch_type,
761
+ 0x40135d8e, // 2.3025851e+00
762
+ 0x4029a926, // 2.6509490e+00
763
+ 0x400237da, // 2.0346589e+00
764
+ 0x3f95eb4c, // 1.1712432e+00
765
+ 0x3f0aacef, // 5.4170126e-01
766
+ 0x3e54dff1 // 2.0788552e-01
767
+ >(x)
768
+ * x);
769
+ }
770
+
771
+ static XSIMD_INLINE batch_type reduce(const batch_type& a, batch_type& x) noexcept
772
+ {
773
+ batch_type k = nearbyint(constants::invlog10_2<batch_type>() * a);
774
+ detail::reassociation_barrier(k, "compensated exp10 range reduction");
775
+ x = fnma(k, constants::log10_2hi<batch_type>(), a);
776
+ detail::reassociation_barrier(x, "compensated exp10 range reduction");
777
+ x -= k * constants::log10_2lo<batch_type>();
778
+ return k;
779
+ }
780
+ };
781
+
782
+ template <class A>
783
+ struct exp_reduction<float, A, exp2_tag> : exp_reduction_base<batch<float, A>, exp2_tag>
784
+ {
785
+ using batch_type = batch<float, A>;
786
+ static XSIMD_INLINE batch_type approx(const batch_type& x) noexcept
787
+ {
788
+ batch_type y = detail::horner<batch_type,
789
+ 0x3e75fdf1, // 2.4022652e-01
790
+ 0x3d6356eb, // 5.5502813e-02
791
+ 0x3c1d9422, // 9.6178371e-03
792
+ 0x3ab01218, // 1.3433127e-03
793
+ 0x3922c8c4 // 1.5524315e-04
794
+ >(x);
795
+ return ++fma(y, x * x, x * constants::log_2<batch_type>());
796
+ }
797
+
798
+ static XSIMD_INLINE batch_type reduce(const batch_type& a, batch_type& x) noexcept
799
+ {
800
+ batch_type k = nearbyint(a);
801
+ detail::reassociation_barrier(k, "compensated exp2 range reduction");
802
+ x = (a - k);
803
+ return k;
804
+ }
805
+ };
806
+
807
+ template <class A>
808
+ struct exp_reduction<double, A, exp_tag> : exp_reduction_base<batch<double, A>, exp_tag>
809
+ {
810
+ using batch_type = batch<double, A>;
811
+ static XSIMD_INLINE batch_type approx(const batch_type& x) noexcept
812
+ {
813
+ batch_type t = x * x;
814
+ return fnma(t,
815
+ detail::horner<batch_type,
816
+ 0x3fc555555555553eull,
817
+ 0xbf66c16c16bebd93ull,
818
+ 0x3f11566aaf25de2cull,
819
+ 0xbebbbd41c5d26bf1ull,
820
+ 0x3e66376972bea4d0ull>(t),
821
+ x);
822
+ }
823
+
824
+ static XSIMD_INLINE batch_type reduce(const batch_type& a, batch_type& hi, batch_type& lo, batch_type& x) noexcept
825
+ {
826
+ batch_type k = nearbyint(constants::invlog_2<batch_type>() * a);
827
+ detail::reassociation_barrier(k, "compensated exp range reduction");
828
+ hi = fnma(k, constants::log_2hi<batch_type>(), a);
829
+ detail::reassociation_barrier(hi, "compensated exp range reduction");
830
+ lo = k * constants::log_2lo<batch_type>();
831
+ x = hi - lo;
832
+ return k;
833
+ }
834
+
835
+ static XSIMD_INLINE batch_type finalize(const batch_type& x, const batch_type& c, const batch_type& hi, const batch_type& lo) noexcept
836
+ {
837
+ return batch_type(1.) - (((lo - (x * c) / (batch_type(2.) - c)) - hi));
838
+ }
839
+ };
840
+
841
+ template <class A>
842
+ struct exp_reduction<double, A, exp10_tag> : exp_reduction_base<batch<double, A>, exp10_tag>
843
+ {
844
+ using batch_type = batch<double, A>;
845
+ static XSIMD_INLINE batch_type approx(const batch_type& x) noexcept
846
+ {
847
+ batch_type xx = x * x;
848
+ batch_type px = x * detail::horner<batch_type, 0x40a2b4798e134a01ull, 0x40796b7a050349e4ull, 0x40277d9474c55934ull, 0x3fa4fd75f3062dd4ull>(xx);
849
+ batch_type x2 = px / (detail::horner1<batch_type, 0x40a03f37650df6e2ull, 0x4093e05eefd67782ull, 0x405545fdce51ca08ull>(xx) - px);
850
+ return ++(x2 + x2);
851
+ }
852
+
853
+ static XSIMD_INLINE batch_type reduce(const batch_type& a, batch_type&, batch_type&, batch_type& x) noexcept
854
+ {
855
+ batch_type k = nearbyint(constants::invlog10_2<batch_type>() * a);
856
+ detail::reassociation_barrier(k, "compensated exp10 range reduction");
857
+ x = fnma(k, constants::log10_2hi<batch_type>(), a);
858
+ detail::reassociation_barrier(x, "compensated exp10 range reduction");
859
+ x = fnma(k, constants::log10_2lo<batch_type>(), x);
860
+ return k;
861
+ }
862
+
863
+ static XSIMD_INLINE batch_type finalize(const batch_type&, const batch_type& c, const batch_type&, const batch_type&) noexcept
864
+ {
865
+ return c;
866
+ }
867
+ };
868
+
869
+ template <class A>
870
+ struct exp_reduction<double, A, exp2_tag> : exp_reduction_base<batch<double, A>, exp2_tag>
871
+ {
872
+ using batch_type = batch<double, A>;
873
+ static XSIMD_INLINE batch_type approx(const batch_type& x) noexcept
874
+ {
875
+ batch_type t = x * x;
876
+ return fnma(t,
877
+ detail::horner<batch_type,
878
+ 0x3fc555555555553eull,
879
+ 0xbf66c16c16bebd93ull,
880
+ 0x3f11566aaf25de2cull,
881
+ 0xbebbbd41c5d26bf1ull,
882
+ 0x3e66376972bea4d0ull>(t),
883
+ x);
884
+ }
885
+
886
+ static XSIMD_INLINE batch_type reduce(const batch_type& a, batch_type&, batch_type&, batch_type& x) noexcept
887
+ {
888
+ batch_type k = nearbyint(a);
889
+ x = (a - k) * constants::log_2<batch_type>();
890
+ detail::reassociation_barrier(x, "keep reduced exponent ordered before finalize");
891
+ return k;
892
+ }
893
+
894
+ static XSIMD_INLINE batch_type finalize(const batch_type& x, const batch_type& c, const batch_type&, const batch_type&) noexcept
895
+ {
896
+ return batch_type(1.) + x + x * c / (batch_type(2.) - c);
897
+ }
898
+ };
899
+
900
+ template <exp_reduction_tag Tag, class A>
901
+ XSIMD_INLINE batch<float, A> exp(batch<float, A> const& self) noexcept
902
+ {
903
+ using batch_type = batch<float, A>;
904
+ using reducer_t = exp_reduction<float, A, Tag>;
905
+ batch_type x;
906
+ batch_type k = reducer_t::reduce(self, x);
907
+ x = reducer_t::approx(x);
908
+ x = select(self <= reducer_t::minlog(), batch_type(0.), ldexp(x, to_int(k)));
909
+ #ifndef __FAST_MATH__
910
+ x = select(self >= reducer_t::maxlog(), constants::infinity<batch_type>(), x);
911
+ #endif
912
+ return x;
913
+ }
914
+
915
+ template <exp_reduction_tag Tag, class A>
916
+ XSIMD_INLINE batch<double, A> exp(batch<double, A> const& self) noexcept
917
+ {
918
+ using batch_type = batch<double, A>;
919
+ using reducer_t = exp_reduction<double, A, Tag>;
920
+ batch_type hi, lo, x;
921
+ batch_type k = reducer_t::reduce(self, hi, lo, x);
922
+ batch_type c = reducer_t::approx(x);
923
+ c = reducer_t::finalize(x, c, hi, lo);
924
+ c = select(self <= reducer_t::minlog(), batch_type(0.), ldexp(c, to_int(k)));
925
+ #ifndef __FAST_MATH__
926
+ c = select(self >= reducer_t::maxlog(), constants::infinity<batch_type>(), c);
927
+ #endif
928
+ return c;
929
+ }
930
+ }
931
+
932
+ template <class A, class T>
933
+ XSIMD_INLINE batch<T, A> exp(batch<T, A> const& self, requires_arch<common>) noexcept
934
+ {
935
+ return detail::exp<detail::exp_tag>(self);
936
+ }
937
+
938
+ template <class A, class T>
939
+ XSIMD_INLINE batch<std::complex<T>, A> exp(batch<std::complex<T>, A> const& self, requires_arch<common>) noexcept
940
+ {
941
+ using batch_type = batch<std::complex<T>, A>;
942
+ auto isincos = sincos(self.imag());
943
+ return exp(self.real()) * batch_type(std::get<1>(isincos), std::get<0>(isincos));
944
+ }
945
+
946
+ // exp10
947
+ template <class A, class T>
948
+ XSIMD_INLINE batch<T, A> exp10(batch<T, A> const& self, requires_arch<common>) noexcept
949
+ {
950
+ using batch_type = batch<T, A>;
951
+ batch_type out = detail::exp<detail::exp10_tag>(self);
952
+ detail::reassociation_barrier(out, "prevent folding exp10 for literal inputs");
953
+ return out;
954
+ }
955
+
956
+ // exp2
957
+ template <class A, class T>
958
+ XSIMD_INLINE batch<T, A> exp2(batch<T, A> const& self, requires_arch<common>) noexcept
959
+ {
960
+ return detail::exp<detail::exp2_tag>(self);
961
+ }
962
+
963
+ // expm1
964
+ namespace detail
965
+ {
966
+ /* origin: boost/simd/arch/common/detail/common/expm1_kernel.hpp */
967
+ /*
968
+ * ====================================================
969
+ * copyright 2016 NumScale SAS
970
+ *
971
+ * Distributed under the Boost Software License, Version 1.0.
972
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
973
+ * ====================================================
974
+ */
975
+ template <class A>
976
+ static XSIMD_INLINE batch<float, A> expm1(const batch<float, A>& a) noexcept
977
+ {
978
+ using batch_type = batch<float, A>;
979
+ batch_type k = nearbyint(constants::invlog_2<batch_type>() * a);
980
+ batch_type x = fnma(k, constants::log_2hi<batch_type>(), a);
981
+ x = fnma(k, constants::log_2lo<batch_type>(), x);
982
+ batch_type hx = x * batch_type(0.5);
983
+ batch_type hxs = x * hx;
984
+ batch_type r = detail::horner<batch_type,
985
+ 0X3F800000UL, // 1
986
+ 0XBD08887FUL, // -3.3333298E-02
987
+ 0X3ACF6DB4UL // 1.582554
988
+ >(hxs);
989
+ batch_type t = fnma(r, hx, batch_type(3.));
990
+ batch_type e = hxs * ((r - t) / (batch_type(6.) - x * t));
991
+ e = fms(x, e, hxs);
992
+ using i_type = as_integer_t<batch_type>;
993
+ i_type ik = to_int(k);
994
+ batch_type two2mk = ::xsimd::bitwise_cast<float>((constants::maxexponent<batch_type>() - ik) << constants::nmb<batch_type>());
995
+ batch_type y = batch_type(1.) - two2mk - (e - x);
996
+ return ldexp(y, ik);
997
+ }
998
+
999
+ template <class A>
1000
+ static XSIMD_INLINE batch<double, A> expm1(const batch<double, A>& a) noexcept
1001
+ {
1002
+ using batch_type = batch<double, A>;
1003
+ batch_type k = nearbyint(constants::invlog_2<batch_type>() * a);
1004
+ batch_type hi = fnma(k, constants::log_2hi<batch_type>(), a);
1005
+ batch_type lo = k * constants::log_2lo<batch_type>();
1006
+ batch_type x = hi - lo;
1007
+ batch_type hxs = x * x * batch_type(0.5);
1008
+ batch_type r = detail::horner<batch_type,
1009
+ 0X3FF0000000000000ULL,
1010
+ 0XBFA11111111110F4ULL,
1011
+ 0X3F5A01A019FE5585ULL,
1012
+ 0XBF14CE199EAADBB7ULL,
1013
+ 0X3ED0CFCA86E65239ULL,
1014
+ 0XBE8AFDB76E09C32DULL>(hxs);
1015
+ batch_type t = batch_type(3.) - r * batch_type(0.5) * x;
1016
+ batch_type e = hxs * ((r - t) / (batch_type(6) - x * t));
1017
+ batch_type c = (hi - x) - lo;
1018
+ e = (x * (e - c) - c) - hxs;
1019
+ using i_type = as_integer_t<batch_type>;
1020
+ i_type ik = to_int(k);
1021
+ batch_type two2mk = ::xsimd::bitwise_cast<double>((constants::maxexponent<batch_type>() - ik) << constants::nmb<batch_type>());
1022
+ batch_type ct1 = batch_type(1.) - two2mk - (e - x);
1023
+ batch_type ct2 = ++(x - (e + two2mk));
1024
+ batch_type y = select(k < batch_type(20.), ct1, ct2);
1025
+ return ldexp(y, ik);
1026
+ }
1027
+
1028
+ }
1029
+
1030
+ template <class A, class T>
1031
+ XSIMD_INLINE batch<T, A> expm1(batch<T, A> const& self, requires_arch<common>) noexcept
1032
+ {
1033
+ using batch_type = batch<T, A>;
1034
+ auto x = detail::expm1(self);
1035
+ #ifndef __FAST_MATH__
1036
+ x = select(self > constants::maxlog<batch_type>(), constants::infinity<batch_type>(), x);
1037
+ #endif
1038
+ return select(self < constants::logeps<batch_type>(), batch_type(-1.), x);
1039
+ }
1040
+
1041
+ template <class A, class T>
1042
+ XSIMD_INLINE batch<std::complex<T>, A> expm1(const batch<std::complex<T>, A>& z, requires_arch<common>) noexcept
1043
+ {
1044
+ using batch_type = batch<std::complex<T>, A>;
1045
+ using real_batch = typename batch_type::real_batch;
1046
+ real_batch isin = sin(z.imag());
1047
+ real_batch rem1 = expm1(z.real());
1048
+ real_batch re = rem1 + 1.;
1049
+ real_batch si = sin(z.imag() * 0.5);
1050
+ return { rem1 - 2. * re * si * si, re * isin };
1051
+ }
1052
+
1053
+ // polar
1054
+ template <class A, class T>
1055
+ XSIMD_INLINE batch<std::complex<T>, A> polar(const batch<T, A>& r, const batch<T, A>& theta, requires_arch<common>) noexcept
1056
+ {
1057
+ auto sincosTheta = sincos(theta);
1058
+ return { r * sincosTheta.second, r * sincosTheta.first };
1059
+ }
1060
+
1061
+ // fdim
1062
+ template <class A, class T>
1063
+ XSIMD_INLINE batch<T, A> fdim(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
1064
+ {
1065
+ return fmax(batch<T, A>(0), self - other);
1066
+ }
1067
+
1068
+ // fmod
1069
+ template <class A, class T>
1070
+ XSIMD_INLINE batch<T, A> fmod(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
1071
+ {
1072
+ return fnma(trunc(self / other), other, self);
1073
+ }
1074
+
1075
+ // frexp
1076
+ /* origin: boost/simd/arch/common/simd/function/ifrexp.hpp */
1077
+ /*
1078
+ * ====================================================
1079
+ * copyright 2016 NumScale SAS
1080
+ *
1081
+ * Distributed under the Boost Software License, Version 1.0.
1082
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
1083
+ * ====================================================
1084
+ */
1085
+ template <class A, class T>
1086
+ XSIMD_INLINE batch<T, A> frexp(const batch<T, A>& self, batch<as_integer_t<T>, A>& exp, requires_arch<common>) noexcept
1087
+ {
1088
+ using batch_type = batch<T, A>;
1089
+ using int_type = as_integer_t<T>;
1090
+ using i_type = batch<int_type, A>;
1091
+ i_type m1f = constants::mask1frexp<batch_type>();
1092
+ i_type r1 = m1f & ::xsimd::bitwise_cast<int_type>(self);
1093
+ batch_type x = self & ::xsimd::bitwise_cast<T>(~m1f);
1094
+ exp = (r1 >> constants::nmb<batch_type>()) - constants::maxexponentm1<batch_type>();
1095
+ exp = select(batch_bool_cast<typename i_type::value_type>(self != batch_type(0.)), exp, i_type(typename i_type::value_type(0)));
1096
+ return select((self != batch_type(0.)), x | ::xsimd::bitwise_cast<T>(constants::mask2frexp<batch_type>()), batch_type(0.));
1097
+ }
1098
+
1099
+ // from bool
1100
+ template <class A, class T>
1101
+ XSIMD_INLINE batch<T, A> from_bool(batch_bool<T, A> const& self, requires_arch<common>) noexcept
1102
+ {
1103
+ return batch<T, A>((typename batch<T, A>::register_type)self.data) & batch<T, A>(1);
1104
+ }
1105
+
1106
+ // horner
1107
+ template <class T, class A, uint64_t... Coefs>
1108
+ XSIMD_INLINE batch<T, A> horner(const batch<T, A>& self) noexcept
1109
+ {
1110
+ return detail::horner<batch<T, A>, Coefs...>(self);
1111
+ }
1112
+
1113
+ // hypot
1114
+ template <class A, class T>
1115
+ XSIMD_INLINE batch<T, A> hypot(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
1116
+ {
1117
+ return sqrt(fma(self, self, other * other));
1118
+ }
1119
+
1120
+ // ipow
1121
+ template <class A, class T, class ITy>
1122
+ XSIMD_INLINE batch<T, A> ipow(batch<T, A> const& self, ITy other, requires_arch<common>) noexcept
1123
+ {
1124
+ return ::xsimd::detail::ipow(self, other);
1125
+ }
1126
+
1127
+ // ldexp
1128
+ /* origin: boost/simd/arch/common/simd/function/ldexp.hpp */
1129
+ /*
1130
+ * ====================================================
1131
+ * copyright 2016 NumScale SAS
1132
+ *
1133
+ * Distributed under the Boost Software License, Version 1.0.
1134
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
1135
+ * ====================================================
1136
+ */
1137
+ template <class A, class T>
1138
+ XSIMD_INLINE batch<T, A> ldexp(const batch<T, A>& self, const batch<as_integer_t<T>, A>& other, requires_arch<common>) noexcept
1139
+ {
1140
+ using batch_type = batch<T, A>;
1141
+ using itype = as_integer_t<batch_type>;
1142
+ itype ik = other + constants::maxexponent<T>();
1143
+ ik = ik << constants::nmb<T>();
1144
+ return self * ::xsimd::bitwise_cast<T>(ik);
1145
+ }
1146
+
1147
+ // lgamma
1148
+ template <class A, class T>
1149
+ XSIMD_INLINE batch<T, A> lgamma(batch<T, A> const& self, requires_arch<common>) noexcept;
1150
+
1151
+ namespace detail
1152
+ {
1153
+ /* origin: boost/simd/arch/common/detail/common/gammaln_kernel.hpp */
1154
+ /*
1155
+ * ====================================================
1156
+ * copyright 2016 NumScale SAS
1157
+ *
1158
+ * Distributed under the Boost Software License, Version 1.0.
1159
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
1160
+ * ====================================================
1161
+ */
1162
+ template <class A>
1163
+ static XSIMD_INLINE batch<float, A> gammalnB(const batch<float, A>& x) noexcept
1164
+ {
1165
+ return horner<batch<float, A>,
1166
+ 0x3ed87730, // 4.227843421859038E-001
1167
+ 0x3ea51a64, // 3.224669577325661E-001,
1168
+ 0xbd89f07e, // -6.735323259371034E-002,
1169
+ 0x3ca89ed8, // 2.058355474821512E-002,
1170
+ 0xbbf164fd, // -7.366775108654962E-003,
1171
+ 0x3b3ba883, // 2.863437556468661E-003,
1172
+ 0xbaabeab1, // -1.311620815545743E-003,
1173
+ 0x3a1ebb94 // 6.055172732649237E-004
1174
+ >(x);
1175
+ }
1176
+
1177
+ template <class A>
1178
+ static XSIMD_INLINE batch<float, A> gammalnC(const batch<float, A>& x) noexcept
1179
+ {
1180
+ return horner<batch<float, A>,
1181
+ 0xbf13c468, // -5.772156501719101E-001
1182
+ 0x3f528d34, // 8.224670749082976E-001,
1183
+ 0xbecd27a8, // -4.006931650563372E-001,
1184
+ 0x3e8a898b, // 2.705806208275915E-001,
1185
+ 0xbe53c04f, // -2.067882815621965E-001,
1186
+ 0x3e2d4dab, // 1.692415923504637E-001,
1187
+ 0xbe22d329, // -1.590086327657347E-001,
1188
+ 0x3e0c3c4f // 1.369488127325832E-001
1189
+ >(x);
1190
+ }
1191
+
1192
+ template <class A>
1193
+ static XSIMD_INLINE batch<float, A> gammaln2(const batch<float, A>& x) noexcept
1194
+ {
1195
+ return horner<batch<float, A>,
1196
+ 0x3daaaa94, // 8.333316229807355E-002f
1197
+ 0xbb358701, // -2.769887652139868E-003f,
1198
+ 0x3a31fd69 // 6.789774945028216E-004f
1199
+ >(x);
1200
+ }
1201
+
1202
+ template <class A>
1203
+ static XSIMD_INLINE batch<double, A> gammaln1(const batch<double, A>& x) noexcept
1204
+ {
1205
+ return horner<batch<double, A>,
1206
+ 0xc12a0c675418055eull, // -8.53555664245765465627E5
1207
+ 0xc13a45890219f20bull, // -1.72173700820839662146E6,
1208
+ 0xc131bc82f994db51ull, // -1.16237097492762307383E6,
1209
+ 0xc1143d73f89089e5ull, // -3.31612992738871184744E5,
1210
+ 0xc0e2f234355bb93eull, // -3.88016315134637840924E4,
1211
+ 0xc09589018ff36761ull // -1.37825152569120859100E3
1212
+ >(x)
1213
+ / horner<batch<double, A>,
1214
+ 0xc13ece4b6a11e14aull, // -2.01889141433532773231E6
1215
+ 0xc1435255892ff34cull, // -2.53252307177582951285E6,
1216
+ 0xc131628671950043ull, // -1.13933444367982507207E6,
1217
+ 0xc10aeb84b9744c9bull, // -2.20528590553854454839E5,
1218
+ 0xc0d0aa0d7b89d757ull, // -1.70642106651881159223E4,
1219
+ 0xc075fd0d1cf312b2ull, // -3.51815701436523470549E2,
1220
+ 0x3ff0000000000000ull // 1.00000000000000000000E0
1221
+ >(x);
1222
+ }
1223
+
1224
+ template <class A>
1225
+ static XSIMD_INLINE batch<double, A> gammalnA(const batch<double, A>& x) noexcept
1226
+ {
1227
+ return horner<batch<double, A>,
1228
+ 0x3fb555555555554bull, // 8.33333333333331927722E-2
1229
+ 0xbf66c16c16b0a5a1ull, // -2.77777777730099687205E-3,
1230
+ 0x3f4a019f20dc5ebbull, // 7.93650340457716943945E-4,
1231
+ 0xbf437fbdb580e943ull, // -5.95061904284301438324E-4,
1232
+ 0x3f4a985027336661ull // 8.11614167470508450300E-4
1233
+ >(x);
1234
+ }
1235
+
1236
+ /* origin: boost/simd/arch/common/simd/function/gammaln.hpp */
1237
+ /*
1238
+ * ====================================================
1239
+ * copyright 2016 NumScale SAS
1240
+ *
1241
+ * Distributed under the Boost Software License, Version 1.0.
1242
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
1243
+ * ====================================================
1244
+ */
1245
+ template <class B>
1246
+ struct lgamma_impl;
1247
+
1248
+ template <class A>
1249
+ struct lgamma_impl<batch<float, A>>
1250
+ {
1251
+ using batch_type = batch<float, A>;
1252
+ static XSIMD_INLINE batch_type compute(const batch_type& a) noexcept
1253
+ {
1254
+ auto inf_result = (a <= batch_type(0.)) && is_flint(a);
1255
+ batch_type x = select(inf_result, constants::nan<batch_type>(), a);
1256
+ batch_type q = abs(x);
1257
+ #ifndef XSIMD_NO_INFINITIES
1258
+ inf_result = (x == constants::infinity<batch_type>()) || inf_result;
1259
+ #endif
1260
+ auto ltza = a < batch_type(0.);
1261
+ batch_type r(0);
1262
+ batch_type r1 = other(q);
1263
+ if (any(ltza))
1264
+ {
1265
+ #ifdef __FAST_MATH__
1266
+ r = negative(q, r1);
1267
+ #else
1268
+ r = select(inf_result, constants::infinity<batch_type>(), negative(q, r1));
1269
+ #endif
1270
+ if (all(ltza))
1271
+ return r;
1272
+ }
1273
+ batch_type r2 = select(ltza, r, r1);
1274
+ #ifdef __FAST_MATH__
1275
+ return r2;
1276
+ #else
1277
+ return select(a == constants::minusinfinity<batch_type>(), constants::nan<batch_type>(), select(inf_result, constants::infinity<batch_type>(), r2));
1278
+ #endif
1279
+ }
1280
+
1281
+ private:
1282
+ static XSIMD_INLINE batch_type negative(const batch_type& q, const batch_type& w) noexcept
1283
+ {
1284
+ batch_type p = floor(q);
1285
+ batch_type z = q - p;
1286
+ auto test2 = z < batch_type(0.5);
1287
+ z = select(test2, z - batch_type(1.), z);
1288
+ z = q * sin(z, trigo_pi_tag());
1289
+ return -log(constants::invpi<batch_type>() * abs(z)) - w;
1290
+ }
1291
+
1292
+ static XSIMD_INLINE batch_type other(const batch_type& x) noexcept
1293
+ {
1294
+ auto xlt650 = (x < batch_type(6.5));
1295
+ batch_type r0x = x;
1296
+ batch_type r0z = x;
1297
+ batch_type r0s = batch_type(1.);
1298
+ batch_type r1 = batch_type(0.);
1299
+ batch_type p = constants::nan<batch_type>();
1300
+ if (any(xlt650))
1301
+ {
1302
+ batch_type z = batch_type(1.);
1303
+ batch_type tx = select(xlt650, x, batch_type(0.));
1304
+ batch_type nx = batch_type(0.);
1305
+ const batch_type _075 = batch_type(0.75);
1306
+ const batch_type _150 = batch_type(1.50);
1307
+ const batch_type _125 = batch_type(1.25);
1308
+ const batch_type _250 = batch_type(2.50);
1309
+ auto xge150 = (x >= _150);
1310
+ auto txgt250 = (tx > _250);
1311
+
1312
+ // x >= 1.5
1313
+ while (any(xge150 && txgt250))
1314
+ {
1315
+ nx = select(txgt250, nx - batch_type(1.), nx);
1316
+ tx = select(txgt250, x + nx, tx);
1317
+ z = select(txgt250, z * tx, z);
1318
+ txgt250 = (tx > _250);
1319
+ }
1320
+ r0x = select(xge150, x + nx - batch_type(2.), x);
1321
+ r0z = select(xge150, z, r0z);
1322
+ r0s = select(xge150, batch_type(1.), r0s);
1323
+
1324
+ // x >= 1.25 && x < 1.5
1325
+ auto xge125 = (x >= _125);
1326
+ auto xge125t = xge125 && !xge150;
1327
+ if (any(xge125))
1328
+ {
1329
+ r0x = select(xge125t, x - batch_type(1.), r0x);
1330
+ r0z = select(xge125t, z * x, r0z);
1331
+ r0s = select(xge125t, batch_type(-1.), r0s);
1332
+ }
1333
+
1334
+ // x >= 0.75 && x < 1.5
1335
+ batch_bool<float, A> kernelC(false);
1336
+ auto xge075 = (x >= _075);
1337
+ auto xge075t = xge075 && !xge125;
1338
+ if (any(xge075t))
1339
+ {
1340
+ kernelC = xge075t;
1341
+ r0x = select(xge075t, x - batch_type(1.), x);
1342
+ r0z = select(xge075t, batch_type(1.), r0z);
1343
+ r0s = select(xge075t, batch_type(-1.), r0s);
1344
+ p = gammalnC(r0x);
1345
+ }
1346
+
1347
+ // tx < 1.5 && x < 0.75
1348
+ auto txlt150 = (tx < _150) && !xge075;
1349
+ if (any(txlt150))
1350
+ {
1351
+ auto orig = txlt150;
1352
+ while (any(txlt150))
1353
+ {
1354
+ z = select(txlt150, z * tx, z);
1355
+ nx = select(txlt150, nx + batch_type(1.), nx);
1356
+ tx = select(txlt150, x + nx, tx);
1357
+ txlt150 = (tx < _150) && !xge075;
1358
+ }
1359
+ r0x = select(orig, r0x + nx - batch_type(2.), r0x);
1360
+ r0z = select(orig, z, r0z);
1361
+ r0s = select(orig, batch_type(-1.), r0s);
1362
+ }
1363
+ p = select(kernelC, p, gammalnB(r0x));
1364
+ if (all(xlt650))
1365
+ return fma(r0x, p, r0s * log(abs(r0z)));
1366
+ }
1367
+ r0z = select(xlt650, abs(r0z), x);
1368
+ batch_type m = log(r0z);
1369
+ r1 = fma(r0x, p, r0s * m);
1370
+ batch_type r2 = fma(x - batch_type(0.5), m, constants::logsqrt2pi<batch_type>() - x);
1371
+ r2 += gammaln2(batch_type(1.) / (x * x)) / x;
1372
+ return select(xlt650, r1, r2);
1373
+ }
1374
+ };
1375
+
1376
+ template <class A>
1377
+ struct lgamma_impl<batch<double, A>>
1378
+ {
1379
+ using batch_type = batch<double, A>;
1380
+
1381
+ static XSIMD_INLINE batch_type compute(const batch_type& a) noexcept
1382
+ {
1383
+ auto inf_result = (a <= batch_type(0.)) && is_flint(a);
1384
+ batch_type x = select(inf_result, constants::nan<batch_type>(), a);
1385
+ batch_type q = abs(x);
1386
+ #ifndef XSIMD_NO_INFINITIES
1387
+ inf_result = (q == constants::infinity<batch_type>());
1388
+ #endif
1389
+ auto test = (a < batch_type(-34.));
1390
+ batch_type r = constants::nan<batch_type>();
1391
+ if (any(test))
1392
+ {
1393
+ r = large_negative(q);
1394
+ if (all(test))
1395
+ return select(inf_result, constants::nan<batch_type>(), r);
1396
+ }
1397
+ batch_type r1 = other(a);
1398
+ batch_type r2 = select(test, r, r1);
1399
+ #ifdef __FAST_MATH__
1400
+ return r2;
1401
+ #else
1402
+ return select(a == constants::minusinfinity<batch_type>(), constants::nan<batch_type>(), select(inf_result, constants::infinity<batch_type>(), r2));
1403
+ #endif
1404
+ }
1405
+
1406
+ private:
1407
+ // FIXME: cannot mark this one as XSIMD_INLINE because there's a
1408
+ // recursive loop on `lgamma'.
1409
+ static inline batch_type large_negative(const batch_type& q) noexcept
1410
+ {
1411
+ batch_type w = lgamma(q);
1412
+ batch_type p = floor(q);
1413
+ batch_type z = q - p;
1414
+ auto test2 = (z < batch_type(0.5));
1415
+ z = select(test2, z - batch_type(1.), z);
1416
+ z = q * sin(z, trigo_pi_tag());
1417
+ z = abs(z);
1418
+ return constants::logpi<batch_type>() - log(z) - w;
1419
+ }
1420
+
1421
+ static XSIMD_INLINE batch_type other(const batch_type& xx) noexcept
1422
+ {
1423
+ batch_type x = xx;
1424
+ auto test = (x < batch_type(13.));
1425
+ batch_type r1 = batch_type(0.);
1426
+ if (any(test))
1427
+ {
1428
+ batch_type z = batch_type(1.);
1429
+ batch_type p = batch_type(0.);
1430
+ batch_type u = select(test, x, batch_type(0.));
1431
+ auto test1 = (u >= batch_type(3.));
1432
+ while (any(test1))
1433
+ {
1434
+ p = select(test1, p - batch_type(1.), p);
1435
+ u = select(test1, x + p, u);
1436
+ z = select(test1, z * u, z);
1437
+ test1 = (u >= batch_type(3.));
1438
+ }
1439
+
1440
+ auto test2 = (u < batch_type(2.));
1441
+ while (any(test2))
1442
+ {
1443
+ z = select(test2, z / u, z);
1444
+ p = select(test2, p + batch_type(1.), p);
1445
+ u = select(test2, x + p, u);
1446
+ test2 = (u < batch_type(2.));
1447
+ }
1448
+
1449
+ z = abs(z);
1450
+ x += p - batch_type(2.);
1451
+ r1 = x * gammaln1(x) + log(z);
1452
+ if (all(test))
1453
+ return r1;
1454
+ }
1455
+ batch_type r2 = fma(xx - batch_type(0.5), log(xx), constants::logsqrt2pi<batch_type>() - xx);
1456
+ batch_type p = batch_type(1.) / (xx * xx);
1457
+ r2 += gammalnA(p) / xx;
1458
+ return select(test, r1, r2);
1459
+ }
1460
+ };
1461
+ }
1462
+
1463
+ template <class A, class T>
1464
+ XSIMD_INLINE batch<T, A> lgamma(batch<T, A> const& self, requires_arch<common>) noexcept
1465
+ {
1466
+ return detail::lgamma_impl<batch<T, A>>::compute(self);
1467
+ }
1468
+
1469
+ // log
1470
+ /* origin: boost/simd/arch/common/simd/function/log.hpp */
1471
+ /*
1472
+ * ====================================================
1473
+ * copyright 2016 NumScale SAS
1474
+ *
1475
+ * Distributed under the Boost Software License, Version 1.0.
1476
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
1477
+ * ====================================================
1478
+ */
1479
+ template <class A>
1480
+ XSIMD_INLINE batch<float, A> log(batch<float, A> const& self, requires_arch<common>) noexcept
1481
+ {
1482
+ using batch_type = batch<float, A>;
1483
+ using int_type = as_integer_t<float>;
1484
+ using i_type = batch<int_type, A>;
1485
+ batch_type x = self;
1486
+ i_type k(0);
1487
+ auto isnez = (self != batch_type(0.));
1488
+ #ifndef XSIMD_NO_DENORMALS
1489
+ auto test = (self < constants::smallestposval<batch_type>()) && isnez;
1490
+ if (any(test))
1491
+ {
1492
+ k = select(batch_bool_cast<int_type>(test), k - i_type(23), k);
1493
+ x = select(test, x * batch_type(8388608ul), x);
1494
+ }
1495
+ #endif
1496
+ i_type ix = ::xsimd::bitwise_cast<int_type>(x);
1497
+ ix += 0x3f800000 - 0x3f3504f3;
1498
+ k += (ix >> 23) - 0x7f;
1499
+ ix = (ix & i_type(0x007fffff)) + 0x3f3504f3;
1500
+ x = ::xsimd::bitwise_cast<float>(ix);
1501
+ batch_type f = --x;
1502
+ batch_type s = f / (batch_type(2.) + f);
1503
+ batch_type z = s * s;
1504
+ batch_type w = z * z;
1505
+ batch_type t1 = w * detail::horner<batch_type, 0x3eccce13, 0x3e789e26>(w);
1506
+ batch_type t2 = z * detail::horner<batch_type, 0x3f2aaaaa, 0x3e91e9ee>(w);
1507
+ batch_type R = t2 + t1;
1508
+ batch_type hfsq = batch_type(0.5) * f * f;
1509
+ batch_type dk = to_float(k);
1510
+ detail::reassociation_barrier(dk, "keep compensated k conversion before split log(2) scaling");
1511
+ batch_type r = fma(dk, constants::log_2hi<batch_type>(), fma(s, (hfsq + R), dk * constants::log_2lo<batch_type>()) - hfsq + f);
1512
+ #ifdef __FAST_MATH__
1513
+ return r;
1514
+ #else
1515
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1516
+ return select(!(self >= batch_type(0.)), constants::nan<batch_type>(), zz);
1517
+ #endif
1518
+ }
1519
+
1520
+ template <class A>
1521
+ XSIMD_INLINE batch<double, A> log(batch<double, A> const& self, requires_arch<common>) noexcept
1522
+ {
1523
+ using batch_type = batch<double, A>;
1524
+ using int_type = as_integer_t<double>;
1525
+ using i_type = batch<int_type, A>;
1526
+
1527
+ batch_type x = self;
1528
+ i_type hx = ::xsimd::bitwise_cast<int_type>(x) >> 32;
1529
+ i_type k(0);
1530
+ auto isnez = (self != batch_type(0.));
1531
+ #ifndef XSIMD_NO_DENORMALS
1532
+ auto test = (self < constants::smallestposval<batch_type>()) && isnez;
1533
+ if (any(test))
1534
+ {
1535
+ k = select(batch_bool_cast<int_type>(test), k - i_type(54), k);
1536
+ x = select(test, x * batch_type(18014398509481984ull), x);
1537
+ }
1538
+ #endif
1539
+ hx += 0x3ff00000 - 0x3fe6a09e;
1540
+ k += (hx >> 20) - 0x3ff;
1541
+ batch_type dk = to_float(k);
1542
+ detail::reassociation_barrier(dk, "keep compensated k conversion before split log(2) scaling");
1543
+ hx = (hx & i_type(0x000fffff)) + 0x3fe6a09e;
1544
+ x = ::xsimd::bitwise_cast<double>(hx << 32 | (i_type(0xffffffff) & ::xsimd::bitwise_cast<int_type>(x)));
1545
+
1546
+ batch_type f = --x;
1547
+ batch_type hfsq = batch_type(0.5) * f * f;
1548
+ batch_type s = f / (batch_type(2.) + f);
1549
+ batch_type z = s * s;
1550
+ batch_type w = z * z;
1551
+
1552
+ batch_type t1 = w * detail::horner<batch_type, 0x3fd999999997fa04ll, 0x3fcc71c51d8e78afll, 0x3fc39a09d078c69fll>(w);
1553
+ batch_type t2 = z * detail::horner<batch_type, 0x3fe5555555555593ll, 0x3fd2492494229359ll, 0x3fc7466496cb03dell, 0x3fc2f112df3e5244ll>(w);
1554
+ batch_type R = t2 + t1;
1555
+ batch_type r = fma(dk, constants::log_2hi<batch_type>(), fma(s, (hfsq + R), dk * constants::log_2lo<batch_type>()) - hfsq + f);
1556
+ #ifdef __FAST_MATH__
1557
+ return r;
1558
+ #else
1559
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1560
+ return select(!(self >= batch_type(0.)), constants::nan<batch_type>(), zz);
1561
+ #endif
1562
+ }
1563
+
1564
+ template <class A, class T>
1565
+ XSIMD_INLINE batch<std::complex<T>, A> log(const batch<std::complex<T>, A>& z, requires_arch<common>) noexcept
1566
+ {
1567
+ return batch<std::complex<T>, A>(log(abs(z)), atan2(z.imag(), z.real()));
1568
+ }
1569
+
1570
+ // log2
1571
+ template <class A>
1572
+ XSIMD_INLINE batch<float, A> log2(batch<float, A> const& self, requires_arch<common>) noexcept
1573
+ {
1574
+ using batch_type = batch<float, A>;
1575
+ using int_type = as_integer_t<float>;
1576
+ using i_type = batch<int_type, A>;
1577
+ batch_type x = self;
1578
+ i_type k(0);
1579
+ auto isnez = (self != batch_type(0.));
1580
+ #ifndef XSIMD_NO_DENORMALS
1581
+ auto test = (self < constants::smallestposval<batch_type>()) && isnez;
1582
+ if (any(test))
1583
+ {
1584
+ k = select(batch_bool_cast<int_type>(test), k - i_type(25), k);
1585
+ x = select(test, x * batch_type(33554432ul), x);
1586
+ }
1587
+ #endif
1588
+ i_type ix = ::xsimd::bitwise_cast<int_type>(x);
1589
+ ix += 0x3f800000 - 0x3f3504f3;
1590
+ k += (ix >> 23) - 0x7f;
1591
+ ix = (ix & i_type(0x007fffff)) + 0x3f3504f3;
1592
+ x = ::xsimd::bitwise_cast<float>(ix);
1593
+ batch_type f = --x;
1594
+ batch_type s = f / (batch_type(2.) + f);
1595
+ batch_type z = s * s;
1596
+ batch_type w = z * z;
1597
+ batch_type t1 = w * detail::horner<batch_type, 0x3eccce13, 0x3e789e26>(w);
1598
+ batch_type t2 = z * detail::horner<batch_type, 0x3f2aaaaa, 0x3e91e9ee>(w);
1599
+ batch_type R = t1 + t2;
1600
+ batch_type hfsq = batch_type(0.5) * f * f;
1601
+ batch_type dk = to_float(k);
1602
+ detail::reassociation_barrier(dk, "prevent distributing multiplies through compensated exponent conversion");
1603
+ batch_type r = fma(fms(s, hfsq + R, hfsq) + f, constants::invlog_2<batch_type>(), dk);
1604
+ #ifdef __FAST_MATH__
1605
+ return r;
1606
+ #else
1607
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1608
+ return select(!(self >= batch_type(0.)), constants::nan<batch_type>(), zz);
1609
+ #endif
1610
+ }
1611
+
1612
+ template <class A>
1613
+ XSIMD_INLINE batch<double, A> log2(batch<double, A> const& self, requires_arch<common>) noexcept
1614
+ {
1615
+ using batch_type = batch<double, A>;
1616
+ using int_type = as_integer_t<double>;
1617
+ using i_type = batch<int_type, A>;
1618
+ batch_type x = self;
1619
+ i_type hx = ::xsimd::bitwise_cast<int_type>(x) >> 32;
1620
+ i_type k(0);
1621
+ auto isnez = (self != batch_type(0.));
1622
+ #ifndef XSIMD_NO_DENORMALS
1623
+ auto test = (self < constants::smallestposval<batch_type>()) && isnez;
1624
+ if (any(test))
1625
+ {
1626
+ k = select(batch_bool_cast<typename i_type::value_type>(test), k - i_type(54), k);
1627
+ x = select(test, x * batch_type(18014398509481984ull), x);
1628
+ }
1629
+ #endif
1630
+ hx += 0x3ff00000 - 0x3fe6a09e;
1631
+ k += (hx >> 20) - 0x3ff;
1632
+ hx = (hx & i_type(0x000fffff)) + 0x3fe6a09e;
1633
+ x = ::xsimd::bitwise_cast<double>(hx << 32 | (i_type(0xffffffff) & ::xsimd::bitwise_cast<int_type>(x)));
1634
+ batch_type f = --x;
1635
+ batch_type s = f / (batch_type(2.) + f);
1636
+ batch_type z = s * s;
1637
+ batch_type w = z * z;
1638
+ batch_type t1 = w * detail::horner<batch_type, 0x3fd999999997fa04ll, 0x3fcc71c51d8e78afll, 0x3fc39a09d078c69fll>(w);
1639
+ batch_type t2 = z * detail::horner<batch_type, 0x3fe5555555555593ll, 0x3fd2492494229359ll, 0x3fc7466496cb03dell, 0x3fc2f112df3e5244ll>(w);
1640
+ batch_type R = t2 + t1;
1641
+ batch_type hfsq = batch_type(0.5) * f * f;
1642
+ batch_type hi = f - hfsq;
1643
+ hi = hi & ::xsimd::bitwise_cast<double>((constants::allbits<i_type>() << 32));
1644
+ batch_type lo = fma(s, hfsq + R, f - hi - hfsq);
1645
+ batch_type val_hi = hi * constants::invlog_2hi<batch_type>();
1646
+ batch_type val_lo = fma(lo + hi, constants::invlog_2lo<batch_type>(), lo * constants::invlog_2hi<batch_type>());
1647
+ batch_type dk = to_float(k);
1648
+ detail::reassociation_barrier(dk, "Kahan compensated log2 summation");
1649
+ batch_type w1 = dk + val_hi;
1650
+ detail::reassociation_barrier(w1, "Kahan compensated log2 summation");
1651
+ val_lo += (dk - w1) + val_hi;
1652
+ val_hi = w1;
1653
+ batch_type r = val_lo + val_hi;
1654
+ #ifdef __FAST_MATH__
1655
+ return r;
1656
+ #else
1657
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1658
+ return select(!(self >= batch_type(0.)), constants::nan<batch_type>(), zz);
1659
+ #endif
1660
+ }
1661
+
1662
+ namespace detail
1663
+ {
1664
+ template <class T, class A>
1665
+ XSIMD_INLINE batch<T, A> logN_complex_impl(const batch<T, A>& z, typename batch<T, A>::value_type base) noexcept
1666
+ {
1667
+ using batch_type = batch<T, A>;
1668
+ using rv_type = typename batch_type::value_type;
1669
+ return log(z) / batch_type(rv_type(base));
1670
+ }
1671
+ }
1672
+
1673
+ template <class A, class T>
1674
+ XSIMD_INLINE batch<std::complex<T>, A> log2(batch<std::complex<T>, A> const& self, requires_arch<common>) noexcept
1675
+ {
1676
+ return detail::logN_complex_impl(self, std::log(2));
1677
+ }
1678
+
1679
+ // log10
1680
+ /* origin: FreeBSD /usr/src/lib/msun/src/e_log10f.c */
1681
+ /*
1682
+ * ====================================================
1683
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
1684
+ *
1685
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
1686
+ * Permission to use, copy, modify, and distribute this
1687
+ * software is freely granted, provided that this notice
1688
+ * is preserved.
1689
+ * ====================================================
1690
+ */
1691
+ template <class A>
1692
+ XSIMD_INLINE batch<float, A> log10(batch<float, A> const& self, requires_arch<common>) noexcept
1693
+ {
1694
+ using batch_type = batch<float, A>;
1695
+ const batch_type
1696
+ ivln10hi(4.3432617188e-01f),
1697
+ ivln10lo(-3.1689971365e-05f),
1698
+ log10_2hi(3.0102920532e-01f),
1699
+ log10_2lo(7.9034151668e-07f);
1700
+ using int_type = as_integer_t<float>;
1701
+ using i_type = batch<int_type, A>;
1702
+ batch_type x = self;
1703
+ i_type k(0);
1704
+ auto isnez = (self != batch_type(0.));
1705
+ #ifndef XSIMD_NO_DENORMALS
1706
+ auto test = (self < constants::smallestposval<batch_type>()) && isnez;
1707
+ if (any(test))
1708
+ {
1709
+ k = select(batch_bool_cast<int_type>(test), k - i_type(25), k);
1710
+ x = select(test, x * batch_type(33554432ul), x);
1711
+ }
1712
+ #endif
1713
+ i_type ix = ::xsimd::bitwise_cast<int_type>(x);
1714
+ ix += 0x3f800000 - 0x3f3504f3;
1715
+ k += (ix >> 23) - 0x7f;
1716
+ ix = (ix & i_type(0x007fffff)) + 0x3f3504f3;
1717
+ x = ::xsimd::bitwise_cast<float>(ix);
1718
+ batch_type f = --x;
1719
+ batch_type s = f / (batch_type(2.) + f);
1720
+ batch_type z = s * s;
1721
+ batch_type w = z * z;
1722
+ batch_type t1 = w * detail::horner<batch_type, 0x3eccce13, 0x3e789e26>(w);
1723
+ batch_type t2 = z * detail::horner<batch_type, 0x3f2aaaaa, 0x3e91e9ee>(w);
1724
+ batch_type R = t2 + t1;
1725
+ batch_type dk = to_float(k);
1726
+ detail::reassociation_barrier(dk, "prevent distributing multiplies through compensated exponent conversion");
1727
+ batch_type hfsq = batch_type(0.5) * f * f;
1728
+ batch_type hibits = f - hfsq;
1729
+ hibits &= ::xsimd::bitwise_cast<float>(i_type(0xfffff000));
1730
+ batch_type lobits = fma(s, hfsq + R, f - hibits - hfsq);
1731
+ batch_type r = fma(dk, log10_2hi,
1732
+ fma(hibits, ivln10hi,
1733
+ fma(lobits, ivln10hi,
1734
+ fma(lobits + hibits, ivln10lo, dk * log10_2lo))));
1735
+ #ifndef XSIMD_NO_INFINITIES
1736
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1737
+ #else
1738
+ assert(all(isnez) && "Calling log10 on a batch with zero value while XSIMD_NO_INFINITIES is active");
1739
+ batch_type zz = r;
1740
+ #endif
1741
+ #ifndef XSIMD_NO_NANS
1742
+ return select(!(self >= batch_type(0.)), constants::nan<batch_type>(), zz);
1743
+ #else
1744
+ assert(all(self >= batch_type(0.)) && "Calling log10 on a batch with negative value while XSIMD_NO_NANS is active");
1745
+ return zz;
1746
+ #endif
1747
+ }
1748
+
1749
+ template <class A>
1750
+ XSIMD_INLINE batch<double, A> log10(batch<double, A> const& self, requires_arch<common>) noexcept
1751
+ {
1752
+ using batch_type = batch<double, A>;
1753
+ const batch_type
1754
+ ivln10hi(4.34294481878168880939e-01),
1755
+ ivln10lo(2.50829467116452752298e-11),
1756
+ log10_2hi(3.01029995663611771306e-01),
1757
+ log10_2lo(3.69423907715893078616e-13);
1758
+ using int_type = as_integer_t<double>;
1759
+ using i_type = batch<int_type, A>;
1760
+ batch_type x = self;
1761
+ i_type hx = ::xsimd::bitwise_cast<int_type>(x) >> 32;
1762
+ i_type k(0);
1763
+ auto isnez = (self != batch_type(0.));
1764
+ #ifndef XSIMD_NO_DENORMALS
1765
+ auto test = (self < constants::smallestposval<batch_type>()) && isnez;
1766
+ if (any(test))
1767
+ {
1768
+ k = select(batch_bool_cast<int_type>(test), k - i_type(54), k);
1769
+ x = select(test, x * batch_type(18014398509481984ull), x);
1770
+ }
1771
+ #endif
1772
+ hx += 0x3ff00000 - 0x3fe6a09e;
1773
+ k += (hx >> 20) - 0x3ff;
1774
+ batch_type dk = to_float(k);
1775
+ detail::reassociation_barrier(dk, "prevent distributing multiplies through compensated exponent conversion");
1776
+ hx = (hx & i_type(0x000fffff)) + 0x3fe6a09e;
1777
+ x = ::xsimd::bitwise_cast<double>(hx << 32 | (i_type(0xffffffff) & ::xsimd::bitwise_cast<int_type>(x)));
1778
+ batch_type f = --x;
1779
+ batch_type s = f / (batch_type(2.) + f);
1780
+ batch_type z = s * s;
1781
+ batch_type w = z * z;
1782
+ batch_type t1 = w * detail::horner<batch_type, 0x3fd999999997fa04ll, 0x3fcc71c51d8e78afll, 0x3fc39a09d078c69fll>(w);
1783
+ batch_type t2 = z * detail::horner<batch_type, 0x3fe5555555555593ll, 0x3fd2492494229359ll, 0x3fc7466496cb03dell, 0x3fc2f112df3e5244ll>(w);
1784
+ batch_type R = t2 + t1;
1785
+ batch_type hfsq = batch_type(0.5) * f * f;
1786
+ batch_type hi = f - hfsq;
1787
+ hi = hi & ::xsimd::bitwise_cast<double>(constants::allbits<i_type>() << 32);
1788
+ batch_type lo = f - hi - hfsq + s * (hfsq + R);
1789
+ batch_type val_hi = hi * ivln10hi;
1790
+ batch_type y = dk * log10_2hi;
1791
+ batch_type val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
1792
+ batch_type w1 = y + val_hi;
1793
+ val_lo += (y - w1) + val_hi;
1794
+ val_hi = w1;
1795
+ batch_type r = val_lo + val_hi;
1796
+ #ifdef __FAST_MATH__
1797
+ return r;
1798
+ #else
1799
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1800
+ return select(!(self >= batch_type(0.)), constants::nan<batch_type>(), zz);
1801
+ #endif
1802
+ }
1803
+
1804
+ template <class A, class T>
1805
+ XSIMD_INLINE batch<std::complex<T>, A> log10(const batch<std::complex<T>, A>& z, requires_arch<common>) noexcept
1806
+ {
1807
+ return detail::logN_complex_impl(z, std::log(10));
1808
+ }
1809
+
1810
+ // log1p
1811
+ /* origin: boost/simd/arch/common/simd/function/log1p.hpp */
1812
+ /*
1813
+ * ====================================================
1814
+ * copyright 2016 NumScale SAS
1815
+ *
1816
+ * Distributed under the Boost Software License, Version 1.0.
1817
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
1818
+ * ====================================================
1819
+ */
1820
+ template <class A>
1821
+ XSIMD_INLINE batch<float, A> log1p(batch<float, A> const& self, requires_arch<common>) noexcept
1822
+ {
1823
+ using batch_type = batch<float, A>;
1824
+ using int_type = as_integer_t<float>;
1825
+ using i_type = batch<int_type, A>;
1826
+ const batch_type uf = self + batch_type(1.);
1827
+ auto isnez = (uf != batch_type(0.));
1828
+ i_type iu = ::xsimd::bitwise_cast<int_type>(uf);
1829
+ iu += 0x3f800000 - 0x3f3504f3;
1830
+ i_type k = (iu >> 23) - 0x7f;
1831
+ iu = (iu & i_type(0x007fffff)) + 0x3f3504f3;
1832
+ batch_type f = --(::xsimd::bitwise_cast<float>(iu));
1833
+ batch_type s = f / (batch_type(2.) + f);
1834
+ batch_type z = s * s;
1835
+ batch_type w = z * z;
1836
+ batch_type t1 = w * detail::horner<batch_type, 0x3eccce13, 0x3e789e26>(w);
1837
+ batch_type t2 = z * detail::horner<batch_type, 0x3f2aaaaa, 0x3e91e9ee>(w);
1838
+ batch_type R = t2 + t1;
1839
+ batch_type hfsq = batch_type(0.5) * f * f;
1840
+ batch_type dk = to_float(k);
1841
+ detail::reassociation_barrier(dk, "prevent distributing multiplies through compensated exponent conversion");
1842
+ /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
1843
+ batch_type c = select(batch_bool_cast<float>(k >= i_type(2)), batch_type(1.) - (uf - self), self - (uf - batch_type(1.))) / uf;
1844
+ batch_type r = fma(dk, constants::log_2hi<batch_type>(), fma(s, (hfsq + R), dk * constants::log_2lo<batch_type>() + c) - hfsq + f);
1845
+ #ifdef __FAST_MATH__
1846
+ return r;
1847
+ #else
1848
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1849
+ return select(!(uf >= batch_type(0.)), constants::nan<batch_type>(), zz);
1850
+ #endif
1851
+ }
1852
+
1853
+ template <class A>
1854
+ XSIMD_INLINE batch<double, A> log1p(batch<double, A> const& self, requires_arch<common>) noexcept
1855
+ {
1856
+ using batch_type = batch<double, A>;
1857
+ using int_type = as_integer_t<double>;
1858
+ using i_type = batch<int_type, A>;
1859
+ const batch_type uf = self + batch_type(1.);
1860
+ auto isnez = (uf != batch_type(0.));
1861
+ i_type hu = ::xsimd::bitwise_cast<int_type>(uf) >> 32;
1862
+ hu += 0x3ff00000 - 0x3fe6a09e;
1863
+ i_type k = (hu >> 20) - 0x3ff;
1864
+ /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
1865
+ batch_type c = select(batch_bool_cast<double>(k >= i_type(2)), batch_type(1.) - (uf - self), self - (uf - batch_type(1.))) / uf;
1866
+ hu = (hu & i_type(0x000fffff)) + 0x3fe6a09e;
1867
+ batch_type f = ::xsimd::bitwise_cast<double>((hu << 32) | (i_type(0xffffffff) & ::xsimd::bitwise_cast<int_type>(uf)));
1868
+ f = --f;
1869
+ batch_type hfsq = batch_type(0.5) * f * f;
1870
+ batch_type s = f / (batch_type(2.) + f);
1871
+ batch_type z = s * s;
1872
+ batch_type w = z * z;
1873
+ batch_type t1 = w * detail::horner<batch_type, 0x3fd999999997fa04ll, 0x3fcc71c51d8e78afll, 0x3fc39a09d078c69fll>(w);
1874
+ batch_type t2 = z * detail::horner<batch_type, 0x3fe5555555555593ll, 0x3fd2492494229359ll, 0x3fc7466496cb03dell, 0x3fc2f112df3e5244ll>(w);
1875
+ batch_type R = t2 + t1;
1876
+ batch_type dk = to_float(k);
1877
+ detail::reassociation_barrier(dk, "prevent distributing multiplies through compensated exponent conversion");
1878
+ batch_type r = fma(dk, constants::log_2hi<batch_type>(), fma(s, hfsq + R, dk * constants::log_2lo<batch_type>() + c) - hfsq + f);
1879
+ #ifdef __FAST_MATH__
1880
+ return r;
1881
+ #else
1882
+ batch_type zz = select(isnez, select(self == constants::infinity<batch_type>(), constants::infinity<batch_type>(), r), constants::minusinfinity<batch_type>());
1883
+ return select(!(uf >= batch_type(0.)), constants::nan<batch_type>(), zz);
1884
+ #endif
1885
+ }
1886
+
1887
+ template <class A, class T>
1888
+ XSIMD_INLINE batch<std::complex<T>, A> log1p(batch<std::complex<T>, A> const& self, requires_arch<common>) noexcept
1889
+ {
1890
+ using batch_type = batch<std::complex<T>, A>;
1891
+ using real_batch = typename batch_type::real_batch;
1892
+ batch_type u = 1 + self;
1893
+ batch_type logu = log(u);
1894
+ return select(u == batch_type(1.),
1895
+ self,
1896
+ select(u.real() <= real_batch(0.),
1897
+ logu,
1898
+ logu * self / (u - batch_type(1.))));
1899
+ }
1900
+
1901
+ // mod
1902
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1903
+ XSIMD_INLINE batch<T, A> mod(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
1904
+ {
1905
+ return detail::apply([](T x, T y) noexcept -> T
1906
+ { return x % y; },
1907
+ self, other);
1908
+ }
1909
+
1910
+ // nearbyint
1911
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1912
+ XSIMD_INLINE batch<T, A> nearbyint(batch<T, A> const& self, requires_arch<common>) noexcept
1913
+ {
1914
+ return self;
1915
+ }
1916
+ namespace detail
1917
+ {
1918
+ template <class A, class T>
1919
+ XSIMD_INLINE batch<T, A> nearbyintf(batch<T, A> const& self) noexcept
1920
+ {
1921
+ using batch_type = batch<T, A>;
1922
+ batch_type s = bitofsign(self);
1923
+ batch_type v = self ^ s;
1924
+ batch_type t2n = constants::twotonmb<batch_type>();
1925
+ batch_type d0 = v + t2n;
1926
+ detail::reassociation_barrier(d0, "prevent collapsing (v + 2^n) - 2^n back to v");
1927
+ batch_type d = d0 - t2n;
1928
+ return s ^ select(v < t2n, d, v);
1929
+ }
1930
+ }
1931
+ template <class A>
1932
+ XSIMD_INLINE batch<float, A> nearbyint(batch<float, A> const& self, requires_arch<common>) noexcept
1933
+ {
1934
+ return detail::nearbyintf(self);
1935
+ }
1936
+ template <class A>
1937
+ XSIMD_INLINE batch<double, A> nearbyint(batch<double, A> const& self, requires_arch<common>) noexcept
1938
+ {
1939
+ return detail::nearbyintf(self);
1940
+ }
1941
+
1942
+ // nearbyint_as_int
1943
+ template <class T, class A, class = std::enable_if_t<std::is_integral<T>::value>>
1944
+ XSIMD_INLINE batch<T, A> nearbyint_as_int(batch<T, A> const& self, requires_arch<common>) noexcept
1945
+ {
1946
+ return self;
1947
+ }
1948
+
1949
+ // nearbyint_as_int
1950
+ template <class A>
1951
+ XSIMD_INLINE batch<as_integer_t<float>, A>
1952
+ nearbyint_as_int(batch<float, A> const& self, requires_arch<common>) noexcept
1953
+ {
1954
+ using U = as_integer_t<float>;
1955
+ return kernel::detail::apply_transform<U>([](float x) noexcept -> U
1956
+ { return std::nearbyintf(x); },
1957
+ self);
1958
+ }
1959
+
1960
+ template <class A>
1961
+ XSIMD_INLINE batch<as_integer_t<double>, A>
1962
+ nearbyint_as_int(batch<double, A> const& self, requires_arch<common>) noexcept
1963
+ {
1964
+ using U = as_integer_t<double>;
1965
+ return kernel::detail::apply_transform<U>([](double x) noexcept -> U
1966
+ { return std::nearbyint(x); },
1967
+ self);
1968
+ }
1969
+
1970
+ // nextafter
1971
+ namespace detail
1972
+ {
1973
+ template <class T, class A, bool is_int = std::is_integral<T>::value>
1974
+ struct nextafter_kernel
1975
+ {
1976
+ using batch_type = batch<T, A>;
1977
+
1978
+ static XSIMD_INLINE batch_type next(batch_type const& b) noexcept
1979
+ {
1980
+ return b;
1981
+ }
1982
+
1983
+ static XSIMD_INLINE batch_type prev(batch_type const& b) noexcept
1984
+ {
1985
+ return b;
1986
+ }
1987
+ };
1988
+
1989
+ template <class T, class A>
1990
+ struct bitwise_cast_batch;
1991
+
1992
+ template <class A>
1993
+ struct bitwise_cast_batch<float, A>
1994
+ {
1995
+ using type = batch<int32_t, A>;
1996
+ };
1997
+
1998
+ template <class A>
1999
+ struct bitwise_cast_batch<double, A>
2000
+ {
2001
+ using type = batch<int64_t, A>;
2002
+ };
2003
+
2004
+ template <class T, class A>
2005
+ struct nextafter_kernel<T, A, false>
2006
+ {
2007
+ using batch_type = batch<T, A>;
2008
+ using int_batch = typename bitwise_cast_batch<T, A>::type;
2009
+ using int_type = typename int_batch::value_type;
2010
+
2011
+ static XSIMD_INLINE batch_type next(const batch_type& b) noexcept
2012
+ {
2013
+ batch_type n = ::xsimd::bitwise_cast<T>(::xsimd::bitwise_cast<int_type>(b) + int_type(1));
2014
+ #ifdef __FAST_MATH__
2015
+ return n;
2016
+ #else
2017
+ return select(b == constants::infinity<batch_type>(), b, n);
2018
+ #endif
2019
+ }
2020
+
2021
+ static XSIMD_INLINE batch_type prev(const batch_type& b) noexcept
2022
+ {
2023
+ batch_type p = ::xsimd::bitwise_cast<T>(::xsimd::bitwise_cast<int_type>(b) - int_type(1));
2024
+ #ifdef __FAST_MATH__
2025
+ return p;
2026
+ #else
2027
+ return select(b == constants::minusinfinity<batch_type>(), b, p);
2028
+ #endif
2029
+ }
2030
+ };
2031
+ }
2032
+ template <class A, class T>
2033
+ XSIMD_INLINE batch<T, A> nextafter(batch<T, A> const& from, batch<T, A> const& to, requires_arch<common>) noexcept
2034
+ {
2035
+ using kernel = detail::nextafter_kernel<T, A>;
2036
+ return select(from == to, from,
2037
+ select(to > from, kernel::next(from), kernel::prev(from)));
2038
+ }
2039
+
2040
+ // pow
2041
+ /* origin: boost/simd/arch/common/simd/function/pow.hpp*/
2042
+ /*
2043
+ * ====================================================
2044
+ * copyright 2016 NumScale SAS
2045
+ *
2046
+ * Distributed under the Boost Software License, Version 1.0.
2047
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
2048
+ * ====================================================
2049
+ */
2050
+ template <class A, class T>
2051
+ XSIMD_INLINE batch<T, A> pow(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
2052
+ {
2053
+ using batch_type = batch<T, A>;
2054
+ const auto zero = batch_type(0.);
2055
+ auto negself = self < zero;
2056
+ auto iszeropowpos = self == zero && other >= zero;
2057
+ auto adj_self = select(iszeropowpos, batch_type(1), abs(self));
2058
+ batch_type z = exp(other * log(adj_self));
2059
+ z = select(iszeropowpos, zero, z);
2060
+ z = select(is_odd(other) && negself, -z, z);
2061
+ auto invalid = negself && !(is_flint(other) || isinf(other));
2062
+ return select(invalid, constants::nan<batch_type>(), z);
2063
+ }
2064
+
2065
+ template <class A, class T>
2066
+ XSIMD_INLINE batch<std::complex<T>, A> pow(const batch<std::complex<T>, A>& a, const batch<std::complex<T>, A>& z, requires_arch<common>) noexcept
2067
+ {
2068
+ using cplx_batch = batch<std::complex<T>, A>;
2069
+ using real_batch = typename cplx_batch::real_batch;
2070
+ real_batch absa = abs(a);
2071
+ real_batch arga = arg(a);
2072
+ real_batch x = z.real();
2073
+ real_batch y = z.imag();
2074
+ real_batch r = pow(absa, x);
2075
+ real_batch theta = x * arga;
2076
+ real_batch ze(0);
2077
+ auto cond = (y == ze);
2078
+ r = select(cond, r, r * exp(-y * arga));
2079
+ theta = select(cond, theta, theta + y * log(absa));
2080
+ auto sincosTheta = xsimd::sincos(theta);
2081
+ return select(absa == ze, cplx_batch(ze), cplx_batch(r * sincosTheta.second, r * sincosTheta.first));
2082
+ }
2083
+
2084
+ template <class A, class T>
2085
+ inline batch<std::complex<T>, A> pow(const batch<std::complex<T>, A>& a, const batch<T, A>& z, requires_arch<common>) noexcept
2086
+ {
2087
+ using cplx_batch = batch<std::complex<T>, A>;
2088
+
2089
+ auto absa = abs(a);
2090
+ auto arga = arg(a);
2091
+ auto r = pow(absa, z);
2092
+
2093
+ auto theta = z * arga;
2094
+ auto sincosTheta = xsimd::sincos(theta);
2095
+ return select(absa == 0, cplx_batch(0), cplx_batch(r * sincosTheta.second, r * sincosTheta.first));
2096
+ }
2097
+
2098
+ template <class A, class T>
2099
+ inline batch<std::complex<T>, A> pow(const batch<T, A>& a, const batch<std::complex<T>, A>& z, requires_arch<common>) noexcept
2100
+ {
2101
+ return pow(batch<std::complex<T>, A> { a, batch<T, A> {} }, z);
2102
+ }
2103
+
2104
+ // reciprocal
2105
+ template <class T, class A, class = std::enable_if_t<std::is_floating_point<T>::value>>
2106
+ XSIMD_INLINE batch<T, A> reciprocal(batch<T, A> const& self,
2107
+ requires_arch<common>) noexcept
2108
+ {
2109
+ using batch_type = batch<T, A>;
2110
+ return div(batch_type(1), self);
2111
+ }
2112
+
2113
+ // reduce_add
2114
+ template <class A, class T>
2115
+ XSIMD_INLINE std::complex<T> reduce_add(batch<std::complex<T>, A> const& self, requires_arch<common>) noexcept
2116
+ {
2117
+ return { reduce_add(self.real()), reduce_add(self.imag()) };
2118
+ }
2119
+
2120
+ template <class A, class T, class /*=std::enable_if_t<std::is_scalar<T>::value>*/>
2121
+ XSIMD_INLINE T reduce_add(batch<T, A> const& self, requires_arch<common>) noexcept
2122
+ {
2123
+ alignas(A::alignment()) T buffer[batch<T, A>::size];
2124
+ self.store_aligned(buffer);
2125
+ T res = 0;
2126
+ for (T val : buffer)
2127
+ {
2128
+ res += val;
2129
+ }
2130
+ return res;
2131
+ }
2132
+
2133
+ namespace detail
2134
+ {
2135
+ template <class T, T N>
2136
+ struct split_high
2137
+ {
2138
+ static constexpr T get(T i, T)
2139
+ {
2140
+ return i < N ? (i + N) : ((i % N) + N);
2141
+ }
2142
+ };
2143
+
2144
+ template <class Op, class A, class T>
2145
+ XSIMD_INLINE T reduce(Op, batch<T, A> const& self, std::integral_constant<unsigned, 1>) noexcept
2146
+ {
2147
+ return ::xsimd::kernel::first(self, A {});
2148
+ }
2149
+
2150
+ template <class Op, class A, class T, unsigned Lvl>
2151
+ XSIMD_INLINE T reduce(Op op, batch<T, A> const& self, std::integral_constant<unsigned, Lvl>) noexcept
2152
+ {
2153
+ using index_type = as_unsigned_integer_t<T>;
2154
+ batch<T, A> split = swizzle(self, make_batch_constant<index_type, split_high<index_type, Lvl / 2>, A>());
2155
+ return reduce(op, op(split, self), std::integral_constant<unsigned, Lvl / 2>());
2156
+ }
2157
+ }
2158
+
2159
+ // reduce_max
2160
+ template <class A, class T>
2161
+ XSIMD_INLINE T reduce_max(batch<T, A> const& self, requires_arch<common>) noexcept
2162
+ {
2163
+ return detail::reduce([](batch<T, A> const& x, batch<T, A> const& y)
2164
+ { return max(x, y); },
2165
+ self, std::integral_constant<unsigned, batch<T, A>::size>());
2166
+ }
2167
+
2168
+ // reduce_min
2169
+ template <class A, class T>
2170
+ XSIMD_INLINE T reduce_min(batch<T, A> const& self, requires_arch<common>) noexcept
2171
+ {
2172
+ return detail::reduce([](batch<T, A> const& x, batch<T, A> const& y)
2173
+ { return min(x, y); },
2174
+ self, std::integral_constant<unsigned, batch<T, A>::size>());
2175
+ }
2176
+
2177
+ // reduce_mul
2178
+ template <class A, class T>
2179
+ XSIMD_INLINE std::complex<T> reduce_mul(batch<std::complex<T>, A> const& self, requires_arch<common>) noexcept
2180
+ {
2181
+ // FIXME: could do better
2182
+ alignas(A::alignment()) std::complex<T> buffer[batch<std::complex<T>, A>::size];
2183
+ self.store_aligned(buffer);
2184
+ std::complex<T> res = 1;
2185
+ for (auto val : buffer)
2186
+ {
2187
+ res *= val;
2188
+ }
2189
+ return res;
2190
+ }
2191
+
2192
+ template <class A, class T, class /*=std::enable_if_t<std::is_scalar<T>::value>*/>
2193
+ XSIMD_INLINE T reduce_mul(batch<T, A> const& self, requires_arch<common>) noexcept
2194
+ {
2195
+ alignas(A::alignment()) T buffer[batch<T, A>::size];
2196
+ self.store_aligned(buffer);
2197
+ T res = 1;
2198
+ for (T val : buffer)
2199
+ {
2200
+ res *= val;
2201
+ }
2202
+ return res;
2203
+ }
2204
+
2205
+ // remainder
2206
+ template <class A>
2207
+ XSIMD_INLINE batch<float, A> remainder(batch<float, A> const& self, batch<float, A> const& other, requires_arch<common>) noexcept
2208
+ {
2209
+ batch<float, A> q = nearbyint(self / other);
2210
+ detail::reassociation_barrier(q, "prevent pulling multiply back through rounded quotient");
2211
+ return fnma(q, other, self);
2212
+ }
2213
+ template <class A>
2214
+ XSIMD_INLINE batch<double, A> remainder(batch<double, A> const& self, batch<double, A> const& other, requires_arch<common>) noexcept
2215
+ {
2216
+ batch<double, A> q = nearbyint(self / other);
2217
+ detail::reassociation_barrier(q, "prevent pulling multiply back through rounded quotient");
2218
+ return fnma(q, other, self);
2219
+ }
2220
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
2221
+ XSIMD_INLINE batch<T, A> remainder(batch<T, A> const& self, batch<T, A> const& other, requires_arch<common>) noexcept
2222
+ {
2223
+ auto mod = self % other;
2224
+ return select(mod <= other / 2, mod, mod - other);
2225
+ }
2226
+
2227
+ // select
2228
+ template <class A, class T>
2229
+ XSIMD_INLINE batch<std::complex<T>, A> select(batch_bool<T, A> const& cond, batch<std::complex<T>, A> const& true_br, batch<std::complex<T>, A> const& false_br, requires_arch<common>) noexcept
2230
+ {
2231
+ return { select(cond, true_br.real(), false_br.real()), select(cond, true_br.imag(), false_br.imag()) };
2232
+ }
2233
+
2234
+ // sign
2235
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
2236
+ XSIMD_INLINE batch<T, A> sign(batch<T, A> const& self, requires_arch<common>) noexcept
2237
+ {
2238
+ using batch_type = batch<T, A>;
2239
+ batch_type res = select(self > batch_type(0), batch_type(1), batch_type(0)) - select(self < batch_type(0), batch_type(1), batch_type(0));
2240
+ return res;
2241
+ }
2242
+
2243
+ namespace detail
2244
+ {
2245
+ template <class T, class A>
2246
+ XSIMD_INLINE batch<T, A> signf(batch<T, A> const& self) noexcept
2247
+ {
2248
+ using batch_type = batch<T, A>;
2249
+ batch_type res = select(self > batch_type(0.f), batch_type(1.f), batch_type(0.f)) - select(self < batch_type(0.f), batch_type(1.f), batch_type(0.f));
2250
+ #ifdef XSIMD_NO_NANS
2251
+ return res;
2252
+ #else
2253
+ return select(isnan(self), constants::nan<batch_type>(), res);
2254
+ #endif
2255
+ }
2256
+ }
2257
+
2258
+ template <class A>
2259
+ XSIMD_INLINE batch<float, A> sign(batch<float, A> const& self, requires_arch<common>) noexcept
2260
+ {
2261
+ return detail::signf(self);
2262
+ }
2263
+ template <class A>
2264
+ XSIMD_INLINE batch<double, A> sign(batch<double, A> const& self, requires_arch<common>) noexcept
2265
+ {
2266
+ return detail::signf(self);
2267
+ }
2268
+ template <class A, class T>
2269
+ XSIMD_INLINE batch<std::complex<T>, A> sign(const batch<std::complex<T>, A>& z, requires_arch<common>) noexcept
2270
+ {
2271
+ using batch_type = batch<std::complex<T>, A>;
2272
+ using real_batch = typename batch_type::real_batch;
2273
+ auto rz = z.real();
2274
+ auto iz = z.imag();
2275
+ return select(rz != real_batch(0.),
2276
+ batch_type(sign(rz)),
2277
+ batch_type(sign(iz)));
2278
+ }
2279
+
2280
+ // signnz
2281
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
2282
+ XSIMD_INLINE batch<T, A> signnz(batch<T, A> const& self, requires_arch<common>) noexcept
2283
+ {
2284
+ using batch_type = batch<T, A>;
2285
+ return (self >> (sizeof(T) * 8 - 1)) | batch_type(1.);
2286
+ }
2287
+
2288
+ namespace detail
2289
+ {
2290
+ template <class T, class A>
2291
+ XSIMD_INLINE batch<T, A> signnzf(batch<T, A> const& self) noexcept
2292
+ {
2293
+ using batch_type = batch<T, A>;
2294
+ #ifndef XSIMD_NO_NANS
2295
+ return select(isnan(self), constants::nan<batch_type>(), batch_type(1.) | (constants::signmask<batch_type>() & self));
2296
+ #else
2297
+ return batch_type(1.) | (constants::signmask<batch_type>() & self);
2298
+ #endif
2299
+ }
2300
+ }
2301
+
2302
+ template <class A>
2303
+ XSIMD_INLINE batch<float, A> signnz(batch<float, A> const& self, requires_arch<common>) noexcept
2304
+ {
2305
+ return detail::signnzf(self);
2306
+ }
2307
+ template <class A>
2308
+ XSIMD_INLINE batch<double, A> signnz(batch<double, A> const& self, requires_arch<common>) noexcept
2309
+ {
2310
+ return detail::signnzf(self);
2311
+ }
2312
+
2313
+ // sqrt
2314
+ template <class A, class T>
2315
+ XSIMD_INLINE batch<std::complex<T>, A> sqrt(batch<std::complex<T>, A> const& z, requires_arch<common>) noexcept
2316
+ {
2317
+
2318
+ constexpr T csqrt_scale_factor = std::is_same<T, float>::value ? 6.7108864e7f : 1.8014398509481984e16;
2319
+ constexpr T csqrt_scale = std::is_same<T, float>::value ? 1.220703125e-4f : 7.450580596923828125e-9;
2320
+ using batch_type = batch<std::complex<T>, A>;
2321
+ using real_batch = batch<T, A>;
2322
+ real_batch x = z.real();
2323
+ real_batch y = z.imag();
2324
+ real_batch sqrt_x = sqrt(fabs(x));
2325
+ real_batch sqrt_hy = sqrt(0.5 * fabs(y));
2326
+ auto cond = (fabs(x) > real_batch(4.) || fabs(y) > real_batch(4.));
2327
+ x = select(cond, x * 0.25, x * csqrt_scale_factor);
2328
+ y = select(cond, y * 0.25, y * csqrt_scale_factor);
2329
+ real_batch scale = select(cond, real_batch(2.), real_batch(csqrt_scale));
2330
+ real_batch r = abs(batch_type(x, y));
2331
+
2332
+ auto condxp = x > real_batch(0.);
2333
+ real_batch t0 = select(condxp, xsimd::sqrt(0.5 * (r + x)), xsimd::sqrt(0.5 * (r - x)));
2334
+ real_batch r0 = scale * fabs((0.5 * y) / t0);
2335
+ t0 *= scale;
2336
+ real_batch t = select(condxp, t0, r0);
2337
+ r = select(condxp, r0, t0);
2338
+ batch_type resg = select(y < real_batch(0.), batch_type(t, -r), batch_type(t, r));
2339
+ real_batch ze(0.);
2340
+
2341
+ return select(y == ze,
2342
+ select(x == ze,
2343
+ batch_type(ze, ze),
2344
+ select(x < ze, batch_type(ze, sqrt_x), batch_type(sqrt_x, ze))),
2345
+ select(x == ze,
2346
+ select(y > ze, batch_type(sqrt_hy, sqrt_hy), batch_type(sqrt_hy, -sqrt_hy)),
2347
+ resg));
2348
+ }
2349
+
2350
+ // tgamma
2351
+
2352
+ namespace detail
2353
+ {
2354
+ /* origin: boost/simd/arch/common/detail/common/stirling_kernel.hpp */
2355
+ /*
2356
+ * ====================================================
2357
+ * copyright 2016 NumScale SAS
2358
+ *
2359
+ * Distributed under the Boost Software License, Version 1.0.
2360
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
2361
+ * ====================================================
2362
+ */
2363
+ template <class B>
2364
+ struct stirling_kernel;
2365
+
2366
+ template <class A>
2367
+ struct stirling_kernel<batch<float, A>>
2368
+ {
2369
+ using batch_type = batch<float, A>;
2370
+ static XSIMD_INLINE batch_type compute(const batch_type& x) noexcept
2371
+ {
2372
+ return horner<batch_type,
2373
+ 0x3daaaaab,
2374
+ 0x3b638e39,
2375
+ 0xbb2fb930,
2376
+ 0xb970b359>(x);
2377
+ }
2378
+
2379
+ static XSIMD_INLINE batch_type split_limit() noexcept
2380
+ {
2381
+ return batch_type(bit_cast<float>(uint32_t(0x41d628f6)));
2382
+ }
2383
+
2384
+ static XSIMD_INLINE batch_type large_limit() noexcept
2385
+ {
2386
+ return batch_type(bit_cast<float>(uint32_t(0x420c28f3)));
2387
+ }
2388
+ };
2389
+
2390
+ template <class A>
2391
+ struct stirling_kernel<batch<double, A>>
2392
+ {
2393
+ using batch_type = batch<double, A>;
2394
+ static XSIMD_INLINE batch_type compute(const batch_type& x) noexcept
2395
+ {
2396
+ return horner<batch_type,
2397
+ 0x3fb5555555555986ull, // 8.33333333333482257126E-2
2398
+ 0x3f6c71c71b98c5fdull, // 3.47222221605458667310E-3
2399
+ 0xbf65f72607d44fd7ull, // -2.68132617805781232825E-3
2400
+ 0xbf2e166b27e61d7cull, // -2.29549961613378126380E-4
2401
+ 0x3f49cc72592d7293ull // 7.87311395793093628397E-4
2402
+ >(x);
2403
+ }
2404
+
2405
+ static XSIMD_INLINE batch_type split_limit() noexcept
2406
+ {
2407
+ return batch_type(bit_cast<double>(uint64_t(0x4061e083ba3443d4)));
2408
+ }
2409
+
2410
+ static XSIMD_INLINE batch_type large_limit() noexcept
2411
+ {
2412
+ return batch_type(bit_cast<double>(uint64_t(0x4065800000000000)));
2413
+ }
2414
+ };
2415
+
2416
+ /* origin: boost/simd/arch/common/simd/function/stirling.hpp */
2417
+ /*
2418
+ * ====================================================
2419
+ * copyright 2016 NumScale SAS
2420
+ *
2421
+ * Distributed under the Boost Software License, Version 1.0.
2422
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
2423
+ * ====================================================
2424
+ */
2425
+ template <class T, class A>
2426
+ XSIMD_INLINE batch<T, A> stirling(const batch<T, A>& a) noexcept
2427
+ {
2428
+ using batch_type = batch<T, A>;
2429
+ const batch_type stirlingsplitlim = stirling_kernel<batch_type>::split_limit();
2430
+ const batch_type stirlinglargelim = stirling_kernel<batch_type>::large_limit();
2431
+ batch_type x = select(a >= batch_type(0.), a, constants::nan<batch_type>());
2432
+ batch_type w = batch_type(1.) / x;
2433
+ w = fma(w, stirling_kernel<batch_type>::compute(w), batch_type(1.));
2434
+ batch_type y = exp(-x);
2435
+ auto test = (x < stirlingsplitlim);
2436
+ batch_type z = x - batch_type(0.5);
2437
+ z = select(test, z, batch_type(0.5) * z);
2438
+ batch_type v = exp(z * log(abs(x)));
2439
+ y *= v;
2440
+ y = select(test, y, y * v);
2441
+ y *= constants::sqrt_2pi<batch_type>() * w;
2442
+ #ifdef __FAST_MATH__
2443
+ return y;
2444
+ #else
2445
+ y = select(isinf(x), x, y);
2446
+ return select(x > stirlinglargelim, constants::infinity<batch_type>(), y);
2447
+ #endif
2448
+ }
2449
+
2450
+ /* origin: boost/simd/arch/common/detail/common/gamma_kernel.hpp */
2451
+ /*
2452
+ * ====================================================
2453
+ * copyright 2016 NumScale SAS
2454
+ *
2455
+ * Distributed under the Boost Software License, Version 1.0.
2456
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
2457
+ * ====================================================
2458
+ */
2459
+ template <class B>
2460
+ struct tgamma_kernel;
2461
+
2462
+ template <class A>
2463
+ struct tgamma_kernel<batch<float, A>>
2464
+ {
2465
+ using batch_type = batch<float, A>;
2466
+ static XSIMD_INLINE batch_type compute(const batch_type& x) noexcept
2467
+ {
2468
+ return horner<batch_type,
2469
+ 0x3f800000UL, // 9.999999757445841E-01
2470
+ 0x3ed87799UL, // 4.227874605370421E-01
2471
+ 0x3ed2d411UL, // 4.117741948434743E-01
2472
+ 0x3da82a34UL, // 8.211174403261340E-02
2473
+ 0x3d93ae7cUL, // 7.211014349068177E-02
2474
+ 0x3b91db14UL, // 4.451165155708328E-03
2475
+ 0x3ba90c99UL, // 5.158972571345137E-03
2476
+ 0x3ad28b22UL // 1.606319369134976E-03
2477
+ >(x);
2478
+ }
2479
+ };
2480
+
2481
+ template <class A>
2482
+ struct tgamma_kernel<batch<double, A>>
2483
+ {
2484
+ using batch_type = batch<double, A>;
2485
+ static XSIMD_INLINE batch_type compute(const batch_type& x) noexcept
2486
+ {
2487
+ return horner<batch_type,
2488
+ 0x3ff0000000000000ULL, // 9.99999999999999996796E-1
2489
+ 0x3fdfa1373993e312ULL, // 4.94214826801497100753E-1
2490
+ 0x3fca8da9dcae7d31ULL, // 2.07448227648435975150E-1
2491
+ 0x3fa863d918c423d3ULL, // 4.76367800457137231464E-2
2492
+ 0x3f8557cde9db14b0ULL, // 1.04213797561761569935E-2
2493
+ 0x3f5384e3e686bfabULL, // 1.19135147006586384913E-3
2494
+ 0x3f24fcb839982153ULL // 1.60119522476751861407E-4
2495
+ >(x)
2496
+ / horner<batch_type,
2497
+ 0x3ff0000000000000ULL, // 1.00000000000000000320E00
2498
+ 0x3fb24944c9cd3c51ULL, // 7.14304917030273074085E-2
2499
+ 0xbfce071a9d4287c2ULL, // -2.34591795718243348568E-1
2500
+ 0x3fa25779e33fde67ULL, // 3.58236398605498653373E-2
2501
+ 0x3f8831ed5b1bb117ULL, // 1.18139785222060435552E-2
2502
+ 0xBf7240e4e750b44aULL, // -4.45641913851797240494E-3
2503
+ 0x3f41ae8a29152573ULL, // 5.39605580493303397842E-4
2504
+ 0xbef8487a8400d3aFULL // -2.31581873324120129819E-5
2505
+ >(x);
2506
+ }
2507
+ };
2508
+
2509
+ /* origin: boost/simd/arch/common/simd/function/gamma.hpp */
2510
+ /*
2511
+ * ====================================================
2512
+ * copyright 2016 NumScale SAS
2513
+ *
2514
+ * Distributed under the Boost Software License, Version 1.0.
2515
+ * (See copy at http://boost.org/LICENSE_1_0.txt)
2516
+ * ====================================================
2517
+ */
2518
+ template <class B>
2519
+ XSIMD_INLINE B tgamma_large_negative(const B& a) noexcept
2520
+ {
2521
+ B st = stirling(a);
2522
+ B p = floor(a);
2523
+ B sgngam = select(is_even(p), -B(1.), B(1.));
2524
+ B z = a - p;
2525
+ auto test2 = z < B(0.5);
2526
+ z = select(test2, z - B(1.), z);
2527
+ z = a * sin(z, trigo_pi_tag());
2528
+ z = abs(z);
2529
+ return sgngam * constants::pi<B>() / (z * st);
2530
+ }
2531
+
2532
+ template <class B, class BB>
2533
+ XSIMD_INLINE B tgamma_other(const B& a, const BB& test) noexcept
2534
+ {
2535
+ B x = select(test, B(2.), a);
2536
+ #ifndef XSIMD_NO_INFINITIES
2537
+ auto inf_result = (a == constants::infinity<B>());
2538
+ x = select(inf_result, B(2.), x);
2539
+ #endif
2540
+ B z = B(1.);
2541
+ auto test1 = (x >= B(3.));
2542
+ while (any(test1))
2543
+ {
2544
+ x = select(test1, x - B(1.), x);
2545
+ z = select(test1, z * x, z);
2546
+ test1 = (x >= B(3.));
2547
+ }
2548
+ test1 = (x < B(0.));
2549
+ while (any(test1))
2550
+ {
2551
+ z = select(test1, z / x, z);
2552
+ x = select(test1, x + B(1.), x);
2553
+ test1 = (x < B(0.));
2554
+ }
2555
+ auto test2 = (x < B(2.));
2556
+ while (any(test2))
2557
+ {
2558
+ z = select(test2, z / x, z);
2559
+ x = select(test2, x + B(1.), x);
2560
+ test2 = (x < B(2.));
2561
+ }
2562
+ x = z * tgamma_kernel<B>::compute(x - B(2.));
2563
+ #ifndef XSIMD_NO_INFINITIES
2564
+ return select(inf_result, a, x);
2565
+ #else
2566
+ return x;
2567
+ #endif
2568
+ }
2569
+ }
2570
+
2571
+ template <class A, class T>
2572
+ XSIMD_INLINE batch<T, A> tgamma(batch<T, A> const& self, requires_arch<common>) noexcept
2573
+ {
2574
+ using batch_type = batch<T, A>;
2575
+ auto nan_result = (self < batch_type(0.) && is_flint(self));
2576
+ #ifndef XSIMD_NO_NANS
2577
+ nan_result = isnan(self) || nan_result;
2578
+ #endif
2579
+ batch_type q = abs(self);
2580
+ auto test = (self < batch_type(-33.));
2581
+ batch_type r = constants::nan<batch_type>();
2582
+ if (any(test))
2583
+ {
2584
+ r = detail::tgamma_large_negative(q);
2585
+ if (all(test))
2586
+ return select(nan_result, constants::nan<batch_type>(), r);
2587
+ }
2588
+ batch_type r1 = detail::tgamma_other(self, test);
2589
+ batch_type r2 = select(test, r, r1);
2590
+ #ifdef __FAST_MATH__
2591
+ return r2;
2592
+ #else
2593
+ return select(self == batch_type(0.), copysign(constants::infinity<batch_type>(), self), select(nan_result, constants::nan<batch_type>(), r2));
2594
+ #endif
2595
+ }
2596
+
2597
+ }
2598
+
2599
+ }
2600
+
2601
+ #endif