react-native-executorch 0.10.5 → 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 (251) hide show
  1. package/README.md +10 -1
  2. package/android/build.gradle.kts +4 -3
  3. package/ios/RnExecutorch.mm +15 -17
  4. package/lib/module/fetcher/fetcher.js +35 -122
  5. package/lib/module/fetcher/fetcher.js.map +1 -1
  6. package/lib/module/fetcher/telemetry.js +1 -1
  7. package/lib/module/index.js +12 -13
  8. package/lib/module/index.js.map +1 -1
  9. package/lib/module/models.js +4 -2
  10. package/lib/module/models.js.map +1 -1
  11. package/lib/typescript/src/fetcher/fetcher.d.ts +3 -7
  12. package/lib/typescript/src/fetcher/fetcher.d.ts.map +1 -1
  13. package/lib/typescript/src/models.d.ts.map +1 -1
  14. package/package.json +9 -7
  15. package/react-native-executorch.podspec +6 -2
  16. package/src/fetcher/fetcher.ts +38 -131
  17. package/src/fetcher/telemetry.ts +1 -1
  18. package/src/models.ts +6 -1
  19. package/third-party/common/phonemis/CMakeLists.txt +70 -14
  20. package/third-party/common/phonemis/README.md +183 -33
  21. package/third-party/common/phonemis/THIRD_PARTY_NOTICES.md +57 -0
  22. package/third-party/common/phonemis/knowledge/code_style.md +642 -0
  23. package/third-party/common/phonemis/licenses/Unicode-3.0.txt +39 -0
  24. package/third-party/common/phonemis/licenses/misaki-Apache-2.0.txt +201 -0
  25. package/third-party/common/phonemis/licenses/nlohmann-json-MIT.txt +21 -0
  26. package/third-party/common/phonemis/licenses/xsimd-BSD-3-Clause.txt +29 -0
  27. package/third-party/common/phonemis/src/phonemis/base/config.h +6 -0
  28. package/third-party/common/phonemis/src/phonemis/base/ipipeline.cpp +75 -0
  29. package/third-party/common/phonemis/src/phonemis/base/ipipeline.h +21 -0
  30. package/third-party/common/phonemis/src/phonemis/base/phonemizer/constants.h +2 -5
  31. package/third-party/common/phonemis/src/phonemis/base/phonemizer/lexicon_phonemizer.cpp +3 -4
  32. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.cpp +17 -8
  33. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.h +4 -0
  34. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.cpp +21 -6
  35. package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.h +13 -4
  36. package/third-party/common/phonemis/src/phonemis/base/pipeline.cpp +8 -0
  37. package/third-party/common/phonemis/src/phonemis/base/pipeline.h +19 -0
  38. package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.cpp +37 -0
  39. package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.h +45 -0
  40. package/third-party/common/phonemis/src/phonemis/base/processor/common/constants.h +10 -0
  41. package/third-party/common/phonemis/src/phonemis/base/processor/common/context.cpp +105 -0
  42. package/third-party/common/phonemis/src/phonemis/base/processor/common/context.h +49 -0
  43. package/third-party/common/phonemis/src/phonemis/base/processor/common/document.cpp +173 -0
  44. package/third-party/common/phonemis/src/phonemis/base/processor/common/document.h +67 -0
  45. package/third-party/common/phonemis/src/phonemis/base/processor/common/text.cpp +75 -0
  46. package/third-party/common/phonemis/src/phonemis/base/processor/common/text.h +60 -0
  47. package/third-party/common/phonemis/src/phonemis/base/processor/common/types.h +18 -0
  48. package/third-party/common/phonemis/src/phonemis/base/processor/config.h +53 -0
  49. package/third-party/common/phonemis/src/phonemis/base/processor/layer.h +9 -7
  50. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/constants.h +20 -0
  51. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.cpp +89 -0
  52. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.h +35 -0
  53. package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/types.h +16 -0
  54. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/kind.h +40 -0
  55. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/layer.h +382 -0
  56. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/notation.h +30 -0
  57. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.cpp +51 -0
  58. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.h +31 -0
  59. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern.h +30 -0
  60. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.cpp +17 -0
  61. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.h +31 -0
  62. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.cpp +811 -0
  63. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.h +285 -0
  64. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.cpp +64 -0
  65. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.h +23 -0
  66. package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/types.h +94 -0
  67. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sanitizer/layer.cpp +19 -0
  68. package/third-party/common/phonemis/src/phonemis/base/processor/{sanitizer_layer.h → layers/sanitizer/layer.h} +8 -8
  69. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.cpp +65 -0
  70. package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.h +29 -0
  71. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.cpp +170 -0
  72. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.h +40 -0
  73. package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/types.h +25 -0
  74. package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.cpp +47 -0
  75. package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.h +19 -0
  76. package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.cpp +60 -0
  77. package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.h +45 -0
  78. package/third-party/common/phonemis/src/phonemis/base/processor/processor.cpp +6 -7
  79. package/third-party/common/phonemis/src/phonemis/base/processor/processor.h +14 -10
  80. package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.cpp +89 -52
  81. package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.h +16 -9
  82. package/third-party/common/phonemis/src/phonemis/base/tokenizer/tokenizer.cpp +13 -12
  83. package/third-party/common/phonemis/src/phonemis/lang/de/constants.h +183 -19
  84. package/third-party/common/phonemis/src/phonemis/lang/de/num2word.cpp +355 -309
  85. package/third-party/common/phonemis/src/phonemis/lang/de/num2word.h +42 -17
  86. package/third-party/common/phonemis/src/phonemis/lang/de/patterns.cpp +56 -0
  87. package/third-party/common/phonemis/src/phonemis/lang/de/patterns.h +15 -0
  88. package/third-party/common/phonemis/src/phonemis/lang/de/pipeline.h +3 -3
  89. package/third-party/common/phonemis/src/phonemis/lang/en/constants.h +181 -30
  90. package/third-party/common/phonemis/src/phonemis/lang/en/hmm_tagger.cpp +5 -7
  91. package/third-party/common/phonemis/src/phonemis/lang/en/num2word.cpp +232 -135
  92. package/third-party/common/phonemis/src/phonemis/lang/en/num2word.h +41 -16
  93. package/third-party/common/phonemis/src/phonemis/lang/en/pipeline.h +3 -10
  94. package/third-party/common/phonemis/src/phonemis/lang/es/constants.h +182 -60
  95. package/third-party/common/phonemis/src/phonemis/lang/es/num2word.cpp +247 -212
  96. package/third-party/common/phonemis/src/phonemis/lang/es/num2word.h +38 -18
  97. package/third-party/common/phonemis/src/phonemis/lang/es/patterns.cpp +50 -0
  98. package/third-party/common/phonemis/src/phonemis/lang/es/patterns.h +15 -0
  99. package/third-party/common/phonemis/src/phonemis/lang/es/pipeline.h +3 -3
  100. package/third-party/common/phonemis/src/phonemis/lang/fr/constants.h +152 -26
  101. package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.cpp +252 -179
  102. package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.h +38 -15
  103. package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.cpp +83 -0
  104. package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.h +15 -0
  105. package/third-party/common/phonemis/src/phonemis/lang/fr/pipeline.h +3 -3
  106. package/third-party/common/phonemis/src/phonemis/lang/hi/constants.h +62 -10
  107. package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.cpp +74 -123
  108. package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.h +27 -16
  109. package/third-party/common/phonemis/src/phonemis/lang/hi/pipeline.h +5 -3
  110. package/third-party/common/phonemis/src/phonemis/lang/it/constants.h +122 -42
  111. package/third-party/common/phonemis/src/phonemis/lang/it/num2word.cpp +200 -207
  112. package/third-party/common/phonemis/src/phonemis/lang/it/num2word.h +30 -18
  113. package/third-party/common/phonemis/src/phonemis/lang/it/patterns.cpp +25 -0
  114. package/third-party/common/phonemis/src/phonemis/lang/it/patterns.h +15 -0
  115. package/third-party/common/phonemis/src/phonemis/lang/it/pipeline.h +3 -3
  116. package/third-party/common/phonemis/src/phonemis/lang/pl/constants.h +346 -77
  117. package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.cpp +631 -246
  118. package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.h +47 -15
  119. package/third-party/common/phonemis/src/phonemis/lang/pl/pipeline.h +6 -6
  120. package/third-party/common/phonemis/src/phonemis/lang/pt/constants.h +201 -0
  121. package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.cpp +365 -0
  122. package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.h +53 -0
  123. package/third-party/common/phonemis/src/phonemis/lang/pt/pipeline.h +4 -2
  124. package/third-party/common/phonemis/src/phonemis/main.cpp +42 -11
  125. package/third-party/common/phonemis/src/phonemis/protophone/meta.h +24 -0
  126. package/third-party/common/phonemis/src/phonemis/protophone/numeric.h +26 -0
  127. package/third-party/common/phonemis/src/phonemis/protophone/protophone.cpp +525 -0
  128. package/third-party/common/phonemis/src/phonemis/protophone/protophone.h +80 -0
  129. package/third-party/common/phonemis/src/phonemis/protophone/tensor.h +76 -0
  130. package/third-party/common/phonemis/src/phonemis/protophone/tensor_utils.h +89 -0
  131. package/third-party/common/phonemis/src/phonemis/protophone/tensor_view.h +125 -0
  132. package/third-party/common/phonemis/src/phonemis/protophone/types.h +43 -0
  133. package/third-party/common/phonemis/src/phonemis/utils/strings.h +20 -14
  134. package/third-party/common/phonemis/src/phonemis/utils/unicode.h +15 -1
  135. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_arithmetic.hpp +267 -0
  136. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_bit.hpp +232 -0
  137. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_cast.hpp +43 -0
  138. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_complex.hpp +112 -0
  139. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_details.hpp +386 -0
  140. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_logical.hpp +240 -0
  141. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_math.hpp +2601 -0
  142. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_memory.hpp +1006 -0
  143. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_rounding.hpp +72 -0
  144. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_swizzle.hpp +260 -0
  145. package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_trigo.hpp +996 -0
  146. package/third-party/common/phonemis/src/third-party/xsimd/arch/utils/shifts.hpp +82 -0
  147. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx.hpp +2111 -0
  148. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2.hpp +1591 -0
  149. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2_128.hpp +170 -0
  150. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512bw.hpp +724 -0
  151. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512cd.hpp +28 -0
  152. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512dq.hpp +270 -0
  153. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512er.hpp +17 -0
  154. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512f.hpp +2919 -0
  155. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512ifma.hpp +17 -0
  156. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512pf.hpp +17 -0
  157. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi.hpp +76 -0
  158. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi2.hpp +130 -0
  159. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512bw.hpp +17 -0
  160. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512vbmi2.hpp +17 -0
  161. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx_128.hpp +164 -0
  162. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avxvnni.hpp +17 -0
  163. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common.hpp +26 -0
  164. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common_fwd.hpp +127 -0
  165. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_constants.hpp +393 -0
  166. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_emulated.hpp +787 -0
  167. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx.hpp +93 -0
  168. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx2.hpp +46 -0
  169. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_sse.hpp +97 -0
  170. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma4.hpp +92 -0
  171. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_i8mm_neon64.hpp +17 -0
  172. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_isa.hpp +148 -0
  173. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon.hpp +3580 -0
  174. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon64.hpp +1614 -0
  175. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_rvv.hpp +1515 -0
  176. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_scalar.hpp +1210 -0
  177. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse2.hpp +2333 -0
  178. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse3.hpp +66 -0
  179. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_1.hpp +510 -0
  180. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_2.hpp +44 -0
  181. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_ssse3.hpp +186 -0
  182. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sve.hpp +1186 -0
  183. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vsx.hpp +947 -0
  184. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vxe.hpp +787 -0
  185. package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_wasm.hpp +1819 -0
  186. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_arch.hpp +242 -0
  187. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_config.hpp +633 -0
  188. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features.hpp +50 -0
  189. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_arm.hpp +132 -0
  190. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_ppc.hpp +54 -0
  191. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_riscv.hpp +95 -0
  192. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_s390x.hpp +56 -0
  193. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_x86.hpp +1121 -0
  194. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpuid.hpp +144 -0
  195. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_getauxval.hpp +159 -0
  196. package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_macros.hpp +78 -0
  197. package/third-party/common/phonemis/src/third-party/xsimd/math/xsimd_rem_pio2.hpp +707 -0
  198. package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_aligned_allocator.hpp +349 -0
  199. package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_alignment.hpp +102 -0
  200. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_all_registers.hpp +57 -0
  201. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_api.hpp +3106 -0
  202. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx2_register.hpp +57 -0
  203. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512bw_register.hpp +51 -0
  204. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512cd_register.hpp +51 -0
  205. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512dq_register.hpp +51 -0
  206. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512er_register.hpp +51 -0
  207. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512f_register.hpp +77 -0
  208. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512ifma_register.hpp +51 -0
  209. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512pf_register.hpp +51 -0
  210. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi2_register.hpp +51 -0
  211. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi_register.hpp +51 -0
  212. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512bw_register.hpp +54 -0
  213. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512vbmi2_register.hpp +53 -0
  214. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx_register.hpp +79 -0
  215. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avxvnni_register.hpp +44 -0
  216. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch.hpp +1666 -0
  217. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_constant.hpp +572 -0
  218. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_fwd.hpp +41 -0
  219. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_common_arch.hpp +49 -0
  220. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_emulated_register.hpp +80 -0
  221. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx2_register.hpp +50 -0
  222. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx_register.hpp +50 -0
  223. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_sse_register.hpp +50 -0
  224. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma4_register.hpp +50 -0
  225. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_i8mm_neon64_register.hpp +55 -0
  226. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon64_register.hpp +55 -0
  227. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon_register.hpp +130 -0
  228. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_register.hpp +96 -0
  229. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_rvv_register.hpp +491 -0
  230. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse2_register.hpp +59 -0
  231. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse3_register.hpp +49 -0
  232. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_1_register.hpp +48 -0
  233. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_2_register.hpp +48 -0
  234. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_ssse3_register.hpp +48 -0
  235. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sve_register.hpp +216 -0
  236. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_traits.hpp +409 -0
  237. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_utils.hpp +462 -0
  238. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vsx_register.hpp +84 -0
  239. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vxe_register.hpp +86 -0
  240. package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_wasm_register.hpp +59 -0
  241. package/third-party/common/phonemis/src/third-party/xsimd/utils/bits.hpp +122 -0
  242. package/third-party/common/phonemis/src/third-party/xsimd/utils/xsimd_type_traits.hpp +145 -0
  243. package/third-party/common/phonemis/src/third-party/xsimd/xsimd.hpp +43 -0
  244. package/third-party/common/phonemis/src/phonemis/base/processor/constants.h +0 -11
  245. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/config.h +0 -16
  246. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.cpp +0 -271
  247. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.h +0 -45
  248. package/third-party/common/phonemis/src/phonemis/base/processor/num2word/types.h +0 -29
  249. package/third-party/common/phonemis/src/phonemis/base/processor/sanitizer_layer.cpp +0 -22
  250. package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.cpp +0 -40
  251. package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.h +0 -22
@@ -0,0 +1,1819 @@
1
+ /***************************************************************************
2
+ * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
3
+ * Martin Renou *
4
+ * Copyright (c) QuantStack *
5
+ * Copyright (c) Serge Guelton *
6
+ * Copyright (c) Anutosh Bhat *
7
+ * *
8
+ * Distributed under the terms of the BSD 3-Clause License. *
9
+ * *
10
+ * The full license is in the file LICENSE, distributed with this software. *
11
+ ****************************************************************************/
12
+
13
+ #ifndef XSIMD_WASM_HPP
14
+ #define XSIMD_WASM_HPP
15
+
16
+ #include <type_traits>
17
+
18
+ #include "../types/xsimd_wasm_register.hpp"
19
+ #include "./common/xsimd_common_cast.hpp"
20
+
21
+ namespace xsimd
22
+ {
23
+ template <typename T, class A, bool... Values>
24
+ struct batch_bool_constant;
25
+
26
+ template <class T_out, class T_in, class A>
27
+ XSIMD_INLINE batch<T_out, A> bitwise_cast(batch<T_in, A> const& x) noexcept;
28
+
29
+ template <typename T, class A, T... Values>
30
+ struct batch_constant;
31
+
32
+ namespace kernel
33
+ {
34
+ using namespace types;
35
+
36
+ // fwd
37
+ template <class A, class T, size_t I>
38
+ XSIMD_INLINE batch<T, A> insert(batch<T, A> const& self, T val, index<I>, requires_arch<common>) noexcept;
39
+ template <class A, typename T, typename ITy, ITy... Indices>
40
+ XSIMD_INLINE batch<T, A> shuffle(batch<T, A> const& x, batch<T, A> const& y, batch_constant<ITy, A, Indices...>, requires_arch<common>) noexcept;
41
+ template <class A, class T>
42
+ XSIMD_INLINE batch<T, A> avg(batch<T, A> const&, batch<T, A> const&, requires_arch<common>) noexcept;
43
+ template <class A, class T>
44
+ XSIMD_INLINE void transpose(batch<T, A>* matrix_begin, batch<T, A>* matrix_end, requires_arch<common>) noexcept;
45
+
46
+ // abs
47
+ template <class A, class T, std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value>>
48
+ XSIMD_INLINE batch<T, A> abs(batch<T, A> const& self, requires_arch<wasm>) noexcept
49
+ {
50
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
51
+ {
52
+ return wasm_i8x16_abs(self);
53
+ }
54
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
55
+ {
56
+ return wasm_i16x8_abs(self);
57
+ }
58
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
59
+ {
60
+ return wasm_i32x4_abs(self);
61
+ }
62
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
63
+ {
64
+ return wasm_i64x2_abs(self);
65
+ }
66
+ else
67
+ {
68
+ assert(false && "unsupported arch/op combination");
69
+ return {};
70
+ }
71
+ }
72
+
73
+ template <class A>
74
+ XSIMD_INLINE batch<float, A> abs(batch<float, A> const& self, requires_arch<wasm>) noexcept
75
+ {
76
+ return wasm_f32x4_abs(self);
77
+ }
78
+
79
+ template <class A>
80
+ XSIMD_INLINE batch<double, A> abs(batch<double, A> const& self, requires_arch<wasm>) noexcept
81
+ {
82
+ return wasm_f64x2_abs(self);
83
+ }
84
+
85
+ // add
86
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
87
+ XSIMD_INLINE batch<T, A> add(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
88
+ {
89
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
90
+ {
91
+ return wasm_i8x16_add(self, other);
92
+ }
93
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
94
+ {
95
+ return wasm_i16x8_add(self, other);
96
+ }
97
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
98
+ {
99
+ return wasm_i32x4_add(self, other);
100
+ }
101
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
102
+ {
103
+ return wasm_i64x2_add(self, other);
104
+ }
105
+ else
106
+ {
107
+ assert(false && "unsupported arch/op combination");
108
+ return {};
109
+ }
110
+ }
111
+
112
+ template <class A>
113
+ XSIMD_INLINE batch<float, A> add(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
114
+ {
115
+ return wasm_f32x4_add(self, other);
116
+ }
117
+
118
+ template <class A>
119
+ XSIMD_INLINE batch<double, A> add(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
120
+ {
121
+ return wasm_f64x2_add(self, other);
122
+ }
123
+
124
+ // avgr
125
+ template <class A, class T, class = std::enable_if_t<std::is_unsigned<T>::value>>
126
+ XSIMD_INLINE batch<T, A> avgr(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
127
+ {
128
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
129
+ {
130
+ return wasm_u8x16_avgr(self, other);
131
+ }
132
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
133
+ {
134
+ return wasm_u16x8_avgr(self, other);
135
+ }
136
+ else
137
+ {
138
+ return avgr(self, other, common {});
139
+ }
140
+ }
141
+
142
+ // avg
143
+ template <class A, class T, class = std::enable_if_t<std::is_unsigned<T>::value>>
144
+ XSIMD_INLINE batch<T, A> avg(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
145
+ {
146
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
147
+ {
148
+ auto adj = ((self ^ other) << 7) >> 7;
149
+ return avgr(self, other, A {}) - adj;
150
+ }
151
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
152
+ {
153
+ auto adj = ((self ^ other) << 15) >> 15;
154
+ return avgr(self, other, A {}) - adj;
155
+ }
156
+ else
157
+ {
158
+ return avg(self, other, common {});
159
+ }
160
+ }
161
+
162
+ // all
163
+ template <class A>
164
+ XSIMD_INLINE bool all(batch_bool<float, A> const& self, requires_arch<wasm>) noexcept
165
+ {
166
+ return wasm_i32x4_bitmask(self) == 0x0F;
167
+ }
168
+ template <class A>
169
+ XSIMD_INLINE bool all(batch_bool<double, A> const& self, requires_arch<wasm>) noexcept
170
+ {
171
+ return wasm_i64x2_bitmask(self) == 0x03;
172
+ }
173
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
174
+ XSIMD_INLINE bool all(batch_bool<T, A> const& self, requires_arch<wasm>) noexcept
175
+ {
176
+ return wasm_i8x16_bitmask(self) == 0xFFFF;
177
+ }
178
+
179
+ // any
180
+ template <class A>
181
+ XSIMD_INLINE bool any(batch_bool<float, A> const& self, requires_arch<wasm>) noexcept
182
+ {
183
+ return wasm_i32x4_bitmask(self) != 0;
184
+ }
185
+ template <class A>
186
+ XSIMD_INLINE bool any(batch_bool<double, A> const& self, requires_arch<wasm>) noexcept
187
+ {
188
+ return wasm_i64x2_bitmask(self) != 0;
189
+ }
190
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
191
+ XSIMD_INLINE bool any(batch_bool<T, A> const& self, requires_arch<wasm>) noexcept
192
+ {
193
+ return wasm_i8x16_bitmask(self) != 0;
194
+ }
195
+
196
+ // batch_bool_cast
197
+ template <class A, class T_out, class T_in>
198
+ XSIMD_INLINE batch_bool<T_out, A> batch_bool_cast(batch_bool<T_in, A> const& self, batch_bool<T_out, A> const&, requires_arch<wasm>) noexcept
199
+ {
200
+ return { bitwise_cast<T_out>(batch<T_in, A>(self.data)).data };
201
+ }
202
+
203
+ // bitwise_and
204
+ template <class A, class T>
205
+ XSIMD_INLINE batch<T, A> bitwise_and(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
206
+ {
207
+ return wasm_v128_and(self, other);
208
+ }
209
+
210
+ template <class A, class T>
211
+ XSIMD_INLINE batch_bool<T, A> bitwise_and(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<wasm>) noexcept
212
+ {
213
+ return wasm_v128_and(self, other);
214
+ }
215
+
216
+ // bitwise_andnot
217
+ template <class A, class T>
218
+ XSIMD_INLINE batch<T, A> bitwise_andnot(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
219
+ {
220
+ return wasm_v128_andnot(self, other);
221
+ }
222
+
223
+ template <class A, class T>
224
+ XSIMD_INLINE batch_bool<T, A> bitwise_andnot(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<wasm>) noexcept
225
+ {
226
+ return wasm_v128_andnot(self, other);
227
+ }
228
+
229
+ // bitwise_cast
230
+ template <class A, class T, class Tp>
231
+ XSIMD_INLINE batch<Tp, A> bitwise_cast(batch<T, A> const& self, batch<Tp, A> const&, requires_arch<wasm>) noexcept
232
+ {
233
+ return batch<Tp, A>(self.data);
234
+ }
235
+
236
+ // bitwise_or
237
+ template <class A, class T>
238
+ XSIMD_INLINE batch<T, A> bitwise_or(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
239
+ {
240
+ return wasm_v128_or(self, other);
241
+ }
242
+
243
+ template <class A, class T>
244
+ XSIMD_INLINE batch_bool<T, A> bitwise_or(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<wasm>) noexcept
245
+ {
246
+ return wasm_v128_or(self, other);
247
+ }
248
+
249
+ // bitwise_lshift
250
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
251
+ XSIMD_INLINE batch<T, A> bitwise_lshift(batch<T, A> const& self, int32_t other, requires_arch<wasm>) noexcept
252
+ {
253
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
254
+ {
255
+ return wasm_i8x16_shl(self, other);
256
+ }
257
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
258
+ {
259
+ return wasm_i16x8_shl(self, other);
260
+ }
261
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
262
+ {
263
+ return wasm_i32x4_shl(self, other);
264
+ }
265
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
266
+ {
267
+ return wasm_i64x2_shl(self, other);
268
+ }
269
+ else
270
+ {
271
+ assert(false && "unsupported arch/op combination");
272
+ return {};
273
+ }
274
+ }
275
+
276
+ // bitwise_rshift
277
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
278
+ XSIMD_INLINE batch<T, A> bitwise_rshift(batch<T, A> const& self, int32_t other, requires_arch<wasm>) noexcept
279
+ {
280
+ if (std::is_signed<T>::value)
281
+ {
282
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
283
+ {
284
+ return wasm_i8x16_shr(self, other);
285
+ }
286
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
287
+ {
288
+ return wasm_i16x8_shr(self, other);
289
+ }
290
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
291
+ {
292
+ return wasm_i32x4_shr(self, other);
293
+ }
294
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
295
+ {
296
+ return wasm_i64x2_shr(self, other);
297
+ }
298
+ else
299
+ {
300
+ assert(false && "unsupported arch/op combination");
301
+ return {};
302
+ }
303
+ }
304
+ else
305
+ {
306
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
307
+ {
308
+ return wasm_u8x16_shr(self, other);
309
+ }
310
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
311
+ {
312
+ return wasm_u16x8_shr(self, other);
313
+ }
314
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
315
+ {
316
+ return wasm_u32x4_shr(self, other);
317
+ }
318
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
319
+ {
320
+ return wasm_u64x2_shr(self, other);
321
+ }
322
+ else
323
+ {
324
+ assert(false && "unsupported arch/op combination");
325
+ return {};
326
+ }
327
+ }
328
+ }
329
+
330
+ // bitwise_not
331
+ template <class A, class T>
332
+ XSIMD_INLINE batch<T, A> bitwise_not(batch<T, A> const& self, requires_arch<wasm>) noexcept
333
+ {
334
+ return wasm_v128_not(self);
335
+ }
336
+
337
+ template <class A, class T>
338
+ XSIMD_INLINE batch_bool<T, A> bitwise_not(batch_bool<T, A> const& self, requires_arch<wasm>) noexcept
339
+ {
340
+ return wasm_v128_not(self);
341
+ }
342
+
343
+ // bitwise_xor
344
+ template <class A, class T>
345
+ XSIMD_INLINE batch<T, A> bitwise_xor(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
346
+ {
347
+ return wasm_v128_xor(self, other);
348
+ }
349
+
350
+ template <class A, class T>
351
+ XSIMD_INLINE batch_bool<T, A> bitwise_xor(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<wasm>) noexcept
352
+ {
353
+ return wasm_v128_xor(self, other);
354
+ }
355
+
356
+ // broadcast
357
+ template <class A>
358
+ batch<float, A> XSIMD_INLINE broadcast(float val, requires_arch<wasm>) noexcept
359
+ {
360
+ return wasm_f32x4_splat(val);
361
+ }
362
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
363
+ XSIMD_INLINE batch<T, A> broadcast(T val, requires_arch<wasm>) noexcept
364
+ {
365
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
366
+ {
367
+ return wasm_i8x16_splat(val);
368
+ }
369
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
370
+ {
371
+ return wasm_i16x8_splat(val);
372
+ }
373
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
374
+ {
375
+ return wasm_i32x4_splat(val);
376
+ }
377
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
378
+ {
379
+ return wasm_i64x2_splat(val);
380
+ }
381
+ else
382
+ {
383
+ assert(false && "unsupported arch/op combination");
384
+ return {};
385
+ }
386
+ }
387
+ template <class A>
388
+ XSIMD_INLINE batch<double, A> broadcast(double val, requires_arch<wasm>) noexcept
389
+ {
390
+ return wasm_f64x2_splat(val);
391
+ }
392
+
393
+ // ceil
394
+ template <class A>
395
+ XSIMD_INLINE batch<float, A> ceil(batch<float, A> const& self, requires_arch<wasm>) noexcept
396
+ {
397
+ return wasm_f32x4_ceil(self);
398
+ }
399
+ template <class A>
400
+ XSIMD_INLINE batch<double, A> ceil(batch<double, A> const& self, requires_arch<wasm>) noexcept
401
+ {
402
+ return wasm_f64x2_ceil(self);
403
+ }
404
+
405
+ // div
406
+ template <class A>
407
+ XSIMD_INLINE batch<float, A> div(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
408
+ {
409
+ return wasm_f32x4_div(self, other);
410
+ }
411
+ template <class A>
412
+ XSIMD_INLINE batch<double, A> div(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
413
+ {
414
+ return wasm_f64x2_div(self, other);
415
+ }
416
+
417
+ // eq
418
+ template <class A>
419
+ XSIMD_INLINE batch_bool<float, A> eq(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
420
+ {
421
+ return wasm_f32x4_eq(self, other);
422
+ }
423
+ template <class A>
424
+ XSIMD_INLINE batch_bool<float, A> eq(batch_bool<float, A> const& self, batch_bool<float, A> const& other, requires_arch<wasm>) noexcept
425
+ {
426
+ return wasm_i32x4_eq(self, other);
427
+ }
428
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
429
+ XSIMD_INLINE batch_bool<T, A> eq(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
430
+ {
431
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
432
+ {
433
+ return wasm_i8x16_eq(self, other);
434
+ }
435
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
436
+ {
437
+ return wasm_i16x8_eq(self, other);
438
+ }
439
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
440
+ {
441
+ return wasm_i32x4_eq(self, other);
442
+ }
443
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
444
+ {
445
+ return wasm_i64x2_eq(self, other);
446
+ }
447
+ else
448
+ {
449
+ assert(false && "unsupported arch/op combination");
450
+ return {};
451
+ }
452
+ }
453
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
454
+ XSIMD_INLINE batch_bool<T, A> eq(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<wasm>) noexcept
455
+ {
456
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
457
+ {
458
+ return wasm_i8x16_eq(self, other);
459
+ }
460
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
461
+ {
462
+ return wasm_i16x8_eq(self, other);
463
+ }
464
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
465
+ {
466
+ return wasm_i32x4_eq(self, other);
467
+ }
468
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
469
+ {
470
+ return wasm_i64x2_eq(self, other);
471
+ }
472
+ else
473
+ {
474
+ assert(false && "unsupported arch/op combination");
475
+ return {};
476
+ }
477
+ }
478
+ template <class A>
479
+ XSIMD_INLINE batch_bool<double, A> eq(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
480
+ {
481
+ return wasm_f64x2_eq(self, other);
482
+ }
483
+ template <class A>
484
+ XSIMD_INLINE batch_bool<double, A> eq(batch_bool<double, A> const& self, batch_bool<double, A> const& other, requires_arch<wasm>) noexcept
485
+ {
486
+ return wasm_i64x2_eq(self, other);
487
+ }
488
+
489
+ // fast_cast
490
+ namespace detail
491
+ {
492
+ template <class A>
493
+ XSIMD_INLINE batch<float, A> fast_cast(batch<int32_t, A> const& self, batch<float, A> const&, requires_arch<wasm>) noexcept
494
+ {
495
+ return wasm_f32x4_convert_i32x4(self);
496
+ }
497
+
498
+ template <class A>
499
+ XSIMD_INLINE batch<double, A> fast_cast(batch<uint64_t, A> const& x, batch<double, A> const&, requires_arch<wasm>) noexcept
500
+ {
501
+ // from https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx
502
+ // adapted to wasm
503
+ v128_t xH = wasm_u64x2_shr(x, 32);
504
+ xH = wasm_v128_or(xH, wasm_f64x2_splat(19342813113834066795298816.)); // 2^84
505
+ v128_t mask = wasm_i16x8_make(0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000);
506
+ v128_t xL = wasm_v128_or(wasm_v128_and(mask, x), wasm_v128_andnot(wasm_f64x2_splat(0x0010000000000000), mask)); // 2^52
507
+ v128_t f = wasm_f64x2_sub(xH, wasm_f64x2_splat(19342813118337666422669312.)); // 2^84 + 2^52
508
+ return wasm_f64x2_add(f, xL);
509
+ }
510
+
511
+ template <class A>
512
+ XSIMD_INLINE batch<double, A> fast_cast(batch<int64_t, A> const& x, batch<double, A> const&, requires_arch<wasm>) noexcept
513
+ {
514
+ // from https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx
515
+ // adapted to wasm
516
+ v128_t xH = wasm_i32x4_shr(x, 16);
517
+ xH = wasm_v128_and(xH, wasm_i16x8_make(0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF));
518
+ xH = wasm_i64x2_add(xH, wasm_f64x2_splat(442721857769029238784.)); // 3*2^67
519
+ v128_t mask = wasm_i16x8_make(0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000);
520
+ v128_t xL = wasm_v128_or(wasm_v128_and(mask, x), wasm_v128_andnot(wasm_f64x2_splat(0x0010000000000000), mask)); // 2^52
521
+ v128_t f = wasm_f64x2_sub(xH, wasm_f64x2_splat(442726361368656609280.)); // 3*2^67 + 2^52
522
+ return wasm_f64x2_add(f, xL);
523
+ }
524
+
525
+ template <class A>
526
+ XSIMD_INLINE batch<int32_t, A> fast_cast(batch<float, A> const& self, batch<int32_t, A> const&, requires_arch<wasm>) noexcept
527
+ {
528
+ return wasm_i32x4_make(
529
+ static_cast<int32_t>(wasm_f32x4_extract_lane(self, 0)),
530
+ static_cast<int32_t>(wasm_f32x4_extract_lane(self, 1)),
531
+ static_cast<int32_t>(wasm_f32x4_extract_lane(self, 2)),
532
+ static_cast<int32_t>(wasm_f32x4_extract_lane(self, 3)));
533
+ }
534
+ }
535
+ // first
536
+ template <class A>
537
+ XSIMD_INLINE float first(batch<float, A> const& self, requires_arch<wasm>) noexcept
538
+ {
539
+ return wasm_f32x4_extract_lane(self, 0);
540
+ }
541
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
542
+ XSIMD_INLINE T first(batch<T, A> const& self, requires_arch<wasm>) noexcept
543
+ {
544
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
545
+ {
546
+ return wasm_i8x16_extract_lane(self, 0);
547
+ }
548
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
549
+ {
550
+ return wasm_i16x8_extract_lane(self, 0);
551
+ }
552
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
553
+ {
554
+ return wasm_i32x4_extract_lane(self, 0);
555
+ }
556
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
557
+ {
558
+ return wasm_i64x2_extract_lane(self, 0);
559
+ }
560
+ else
561
+ {
562
+ assert(false && "unsupported arch/op combination");
563
+ return {};
564
+ }
565
+ }
566
+ template <class A>
567
+ XSIMD_INLINE double first(batch<double, A> const& self, requires_arch<wasm>) noexcept
568
+ {
569
+ return wasm_f64x2_extract_lane(self, 0);
570
+ }
571
+
572
+ // floor
573
+ template <class A>
574
+ XSIMD_INLINE batch<float, A> floor(batch<float, A> const& self, requires_arch<wasm>) noexcept
575
+ {
576
+ return wasm_f32x4_floor(self);
577
+ }
578
+
579
+ template <class A>
580
+ XSIMD_INLINE batch<double, A> floor(batch<double, A> const& self, requires_arch<wasm>) noexcept
581
+ {
582
+ return wasm_f64x2_floor(self);
583
+ }
584
+
585
+ // from_mask
586
+ template <class A>
587
+ XSIMD_INLINE batch_bool<float, A> from_mask(batch_bool<float, A> const&, uint64_t mask, requires_arch<wasm>) noexcept
588
+ {
589
+ alignas(A::alignment()) static const uint32_t lut[][4] = {
590
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
591
+ { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 },
592
+ { 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
593
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 },
594
+ { 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 },
595
+ { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 },
596
+ { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
597
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
598
+ { 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF },
599
+ { 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF },
600
+ { 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF },
601
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF },
602
+ { 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF },
603
+ { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF },
604
+ { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
605
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
606
+ };
607
+ assert(!(mask & ~0xFul) && "inbound mask");
608
+ return wasm_v128_load((const v128_t*)lut[mask]);
609
+ }
610
+ template <class A>
611
+ XSIMD_INLINE batch_bool<double, A> from_mask(batch_bool<double, A> const&, uint64_t mask, requires_arch<wasm>) noexcept
612
+ {
613
+ alignas(A::alignment()) static const uint64_t lut[][4] = {
614
+ { 0x0000000000000000ul, 0x0000000000000000ul },
615
+ { 0xFFFFFFFFFFFFFFFFul, 0x0000000000000000ul },
616
+ { 0x0000000000000000ul, 0xFFFFFFFFFFFFFFFFul },
617
+ { 0xFFFFFFFFFFFFFFFFul, 0xFFFFFFFFFFFFFFFFul },
618
+ };
619
+ assert(!(mask & ~0x3ul) && "inbound mask");
620
+ return wasm_v128_load((const v128_t*)lut[mask]);
621
+ }
622
+ template <class T, class A, class = std::enable_if_t<std::is_integral<T>::value>>
623
+ XSIMD_INLINE batch_bool<T, A> from_mask(batch_bool<T, A> const&, uint64_t mask, requires_arch<wasm>) noexcept
624
+ {
625
+ alignas(A::alignment()) static const uint64_t lut64[] = {
626
+ 0x0000000000000000,
627
+ 0x000000000000FFFF,
628
+ 0x00000000FFFF0000,
629
+ 0x00000000FFFFFFFF,
630
+ 0x0000FFFF00000000,
631
+ 0x0000FFFF0000FFFF,
632
+ 0x0000FFFFFFFF0000,
633
+ 0x0000FFFFFFFFFFFF,
634
+ 0xFFFF000000000000,
635
+ 0xFFFF00000000FFFF,
636
+ 0xFFFF0000FFFF0000,
637
+ 0xFFFF0000FFFFFFFF,
638
+ 0xFFFFFFFF00000000,
639
+ 0xFFFFFFFF0000FFFF,
640
+ 0xFFFFFFFFFFFF0000,
641
+ 0xFFFFFFFFFFFFFFFF,
642
+ };
643
+ alignas(A::alignment()) static const uint32_t lut32[] = {
644
+ 0x00000000,
645
+ 0x000000FF,
646
+ 0x0000FF00,
647
+ 0x0000FFFF,
648
+ 0x00FF0000,
649
+ 0x00FF00FF,
650
+ 0x00FFFF00,
651
+ 0x00FFFFFF,
652
+ 0xFF000000,
653
+ 0xFF0000FF,
654
+ 0xFF00FF00,
655
+ 0xFF00FFFF,
656
+ 0xFFFF0000,
657
+ 0xFFFF00FF,
658
+ 0xFFFFFF00,
659
+ 0xFFFFFFFF,
660
+ };
661
+ alignas(A::alignment()) static const uint32_t lut16[][4] = {
662
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
663
+ { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 },
664
+ { 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
665
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 },
666
+ { 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 },
667
+ { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 },
668
+ { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
669
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 },
670
+ { 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF },
671
+ { 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF },
672
+ { 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF },
673
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF },
674
+ { 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF },
675
+ { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF },
676
+ { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
677
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF },
678
+ };
679
+ alignas(A::alignment()) static const uint64_t lut8[][4] = {
680
+ { 0x0000000000000000ul, 0x0000000000000000ul },
681
+ { 0xFFFFFFFFFFFFFFFFul, 0x0000000000000000ul },
682
+ { 0x0000000000000000ul, 0xFFFFFFFFFFFFFFFFul },
683
+ { 0xFFFFFFFFFFFFFFFFul, 0xFFFFFFFFFFFFFFFFul },
684
+ };
685
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
686
+ {
687
+ assert(!(mask & ~0xFFFF) && "inbound mask");
688
+ return wasm_i32x4_make(lut32[mask & 0xF], lut32[(mask >> 4) & 0xF], lut32[(mask >> 8) & 0xF], lut32[mask >> 12]);
689
+ }
690
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
691
+ {
692
+ assert(!(mask & ~0xFF) && "inbound mask");
693
+ return wasm_i64x2_make(lut64[mask & 0xF], lut64[mask >> 4]);
694
+ }
695
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
696
+ {
697
+ assert(!(mask & ~0xFul) && "inbound mask");
698
+ return wasm_v128_load((const v128_t*)lut16[mask]);
699
+ }
700
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
701
+ {
702
+ assert(!(mask & ~0x3ul) && "inbound mask");
703
+ return wasm_v128_load((const v128_t*)lut8[mask]);
704
+ }
705
+ }
706
+
707
+ // ge
708
+ template <class A>
709
+ XSIMD_INLINE batch_bool<float, A> ge(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
710
+ {
711
+ return wasm_f32x4_ge(self, other);
712
+ }
713
+ template <class A>
714
+ XSIMD_INLINE batch_bool<double, A> ge(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
715
+ {
716
+ return wasm_f64x2_ge(self, other);
717
+ }
718
+
719
+ // gt
720
+ template <class A>
721
+ XSIMD_INLINE batch_bool<float, A> gt(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
722
+ {
723
+ return wasm_f32x4_gt(self, other);
724
+ }
725
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
726
+ XSIMD_INLINE batch_bool<T, A> gt(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
727
+ {
728
+ if (std::is_signed<T>::value)
729
+ {
730
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
731
+ {
732
+ return wasm_i8x16_gt(self, other);
733
+ }
734
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
735
+ {
736
+ return wasm_i16x8_gt(self, other);
737
+ }
738
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
739
+ {
740
+ return wasm_i32x4_gt(self, other);
741
+ }
742
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
743
+ {
744
+ return wasm_i64x2_gt(self, other);
745
+ }
746
+ else
747
+ {
748
+ assert(false && "unsupported arch/op combination");
749
+ return {};
750
+ }
751
+ }
752
+ else
753
+ {
754
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
755
+ {
756
+ return wasm_u8x16_gt(self, other);
757
+ }
758
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
759
+ {
760
+ return wasm_u16x8_gt(self, other);
761
+ }
762
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
763
+ {
764
+ return wasm_u32x4_gt(self, other);
765
+ }
766
+ else
767
+ {
768
+ return gt(self, other, common {});
769
+ }
770
+ }
771
+ }
772
+
773
+ template <class A>
774
+ XSIMD_INLINE batch_bool<double, A> gt(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
775
+ {
776
+ return wasm_f64x2_gt(self, other);
777
+ }
778
+
779
+ // haddp
780
+ template <class A>
781
+ XSIMD_INLINE batch<float, A> haddp(batch<float, A> const* row, requires_arch<wasm>) noexcept
782
+ {
783
+ v128_t tmp0 = wasm_i32x4_shuffle(row[0], row[1], 0, 4, 1, 5);
784
+ v128_t tmp1 = wasm_i32x4_shuffle(row[0], row[1], 2, 6, 3, 7);
785
+ v128_t tmp2 = wasm_i32x4_shuffle(row[2], row[3], 2, 6, 3, 7);
786
+ tmp0 = wasm_f32x4_add(tmp0, tmp1);
787
+ tmp1 = wasm_i32x4_shuffle(row[2], row[3], 0, 4, 1, 5);
788
+ tmp1 = wasm_f32x4_add(tmp1, tmp2);
789
+ tmp2 = wasm_i32x4_shuffle(tmp1, tmp0, 6, 7, 2, 3);
790
+ tmp0 = wasm_i32x4_shuffle(tmp0, tmp1, 0, 1, 4, 5);
791
+ return wasm_f32x4_add(tmp0, tmp2);
792
+ }
793
+ template <class A>
794
+ XSIMD_INLINE batch<double, A> haddp(batch<double, A> const* row, requires_arch<wasm>) noexcept
795
+ {
796
+ return wasm_f64x2_add(wasm_i64x2_shuffle(row[0], row[1], 0, 2),
797
+ wasm_i64x2_shuffle(row[0], row[1], 1, 3));
798
+ }
799
+
800
+ // insert
801
+ template <class A, size_t I>
802
+ XSIMD_INLINE batch<float, A> insert(batch<float, A> const& self, float val, index<I> pos, requires_arch<wasm>) noexcept
803
+ {
804
+ return wasm_f32x4_replace_lane(self, pos, val);
805
+ }
806
+ template <class A, class T, size_t I, class = std::enable_if_t<std::is_integral<T>::value>>
807
+ XSIMD_INLINE batch<T, A> insert(batch<T, A> const& self, T val, index<I> pos, requires_arch<wasm>) noexcept
808
+ {
809
+ if (std::is_signed<T>::value)
810
+ {
811
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
812
+ {
813
+ return wasm_i8x16_replace_lane(self, pos, val);
814
+ }
815
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
816
+ {
817
+ return wasm_i16x8_replace_lane(self, pos, val);
818
+ }
819
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
820
+ {
821
+ return wasm_i32x4_replace_lane(self, pos, val);
822
+ }
823
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
824
+ {
825
+ return wasm_i64x2_replace_lane(self, pos, val);
826
+ }
827
+ else
828
+ {
829
+ assert(false && "unsupported arch/op combination");
830
+ return {};
831
+ }
832
+ }
833
+ else
834
+ {
835
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
836
+ {
837
+ return wasm_u8x16_replace_lane(self, pos, val);
838
+ }
839
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
840
+ {
841
+ return wasm_u16x8_replace_lane(self, pos, val);
842
+ }
843
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
844
+ {
845
+ return wasm_u32x4_replace_lane(self, pos, val);
846
+ }
847
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
848
+ {
849
+ return wasm_u64x2_replace_lane(self, pos, val);
850
+ }
851
+ else
852
+ {
853
+ assert(false && "unsupported arch/op combination");
854
+ return {};
855
+ }
856
+ }
857
+ }
858
+
859
+ template <class A, size_t I>
860
+ XSIMD_INLINE batch<double, A> insert(batch<double, A> const& self, double val, index<I> pos, requires_arch<wasm>) noexcept
861
+ {
862
+ return wasm_f64x2_replace_lane(self, pos, val);
863
+ }
864
+
865
+ // isnan
866
+ template <class A>
867
+ XSIMD_INLINE batch_bool<float, A> isnan(batch<float, A> const& self, requires_arch<wasm>) noexcept
868
+ {
869
+ return wasm_v128_or(wasm_f32x4_ne(self, self), wasm_f32x4_ne(self, self));
870
+ }
871
+ template <class A>
872
+ XSIMD_INLINE batch_bool<double, A> isnan(batch<double, A> const& self, requires_arch<wasm>) noexcept
873
+ {
874
+ return wasm_v128_or(wasm_f64x2_ne(self, self), wasm_f64x2_ne(self, self));
875
+ }
876
+
877
+ // le
878
+ template <class A>
879
+ XSIMD_INLINE batch_bool<float, A> le(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
880
+ {
881
+ return wasm_f32x4_le(self, other);
882
+ }
883
+ template <class A>
884
+ XSIMD_INLINE batch_bool<double, A> le(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
885
+ {
886
+ return wasm_f64x2_le(self, other);
887
+ }
888
+
889
+ // load_aligned
890
+ template <class A>
891
+ XSIMD_INLINE batch<float, A> load_aligned(float const* mem, convert<float>, requires_arch<wasm>) noexcept
892
+ {
893
+ return wasm_v128_load(mem);
894
+ }
895
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
896
+ XSIMD_INLINE batch<T, A> load_aligned(T const* mem, convert<T>, requires_arch<wasm>) noexcept
897
+ {
898
+ return wasm_v128_load((v128_t const*)mem);
899
+ }
900
+ template <class A>
901
+ XSIMD_INLINE batch<double, A> load_aligned(double const* mem, convert<double>, requires_arch<wasm>) noexcept
902
+ {
903
+ return wasm_v128_load(mem);
904
+ }
905
+
906
+ // load_complex
907
+ namespace detail
908
+ {
909
+ template <class A>
910
+ XSIMD_INLINE batch<std::complex<float>, A> load_complex(batch<float, A> const& hi, batch<float, A> const& lo, requires_arch<wasm>) noexcept
911
+ {
912
+ return { wasm_i32x4_shuffle(hi, lo, 0, 2, 4, 6), wasm_i32x4_shuffle(hi, lo, 1, 3, 5, 7) };
913
+ }
914
+ template <class A>
915
+ XSIMD_INLINE batch<std::complex<double>, A> load_complex(batch<double, A> const& hi, batch<double, A> const& lo, requires_arch<wasm>) noexcept
916
+ {
917
+ return { wasm_i64x2_shuffle(hi, lo, 0, 2), wasm_i64x2_shuffle(hi, lo, 1, 3) };
918
+ }
919
+ }
920
+
921
+ // load_unaligned
922
+ template <class A>
923
+ XSIMD_INLINE batch<float, A> load_unaligned(float const* mem, convert<float>, requires_arch<wasm>) noexcept
924
+ {
925
+ return wasm_v128_load(mem);
926
+ }
927
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
928
+ XSIMD_INLINE batch<T, A> load_unaligned(T const* mem, convert<T>, requires_arch<wasm>) noexcept
929
+ {
930
+ return wasm_v128_load((v128_t const*)mem);
931
+ }
932
+ template <class A>
933
+ XSIMD_INLINE batch<double, A> load_unaligned(double const* mem, convert<double>, requires_arch<wasm>) noexcept
934
+ {
935
+ return wasm_v128_load(mem);
936
+ }
937
+
938
+ // lt
939
+ template <class A>
940
+ XSIMD_INLINE batch_bool<float, A> lt(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
941
+ {
942
+ return wasm_f32x4_lt(self, other);
943
+ }
944
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
945
+ XSIMD_INLINE batch_bool<T, A> lt(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
946
+ {
947
+ if (std::is_signed<T>::value)
948
+ {
949
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
950
+ {
951
+ return wasm_i8x16_lt(self, other);
952
+ }
953
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
954
+ {
955
+ return wasm_i16x8_lt(self, other);
956
+ }
957
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
958
+ {
959
+ return wasm_i32x4_lt(self, other);
960
+ }
961
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
962
+ {
963
+ return wasm_i64x2_lt(self, other);
964
+ }
965
+ else
966
+ {
967
+ assert(false && "unsupported arch/op combination");
968
+ return {};
969
+ }
970
+ }
971
+ else
972
+ {
973
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
974
+ {
975
+ return wasm_u8x16_lt(self, other);
976
+ }
977
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
978
+ {
979
+ return wasm_u16x8_lt(self, other);
980
+ }
981
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
982
+ {
983
+ return wasm_u32x4_lt(self, other);
984
+ }
985
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
986
+ {
987
+ auto xself = wasm_v128_xor(self, wasm_i64x2_splat(std::numeric_limits<int64_t>::lowest()));
988
+ auto xother = wasm_v128_xor(other, wasm_i64x2_splat(std::numeric_limits<int64_t>::lowest()));
989
+ v128_t tmp1 = wasm_i64x2_sub(xself, xother);
990
+ v128_t tmp2 = wasm_v128_xor(xself, xother);
991
+ v128_t tmp3 = wasm_v128_andnot(xself, xother);
992
+ v128_t tmp4 = wasm_v128_andnot(tmp1, tmp2);
993
+ v128_t tmp5 = wasm_v128_or(tmp3, tmp4);
994
+ v128_t tmp6 = wasm_i32x4_shr(tmp5, 31);
995
+ return wasm_i32x4_shuffle(tmp6, wasm_i32x4_splat(0), 1, 1, 3, 3);
996
+ }
997
+ else
998
+ {
999
+ assert(false && "unsupported arch/op combination");
1000
+ return {};
1001
+ }
1002
+ }
1003
+ }
1004
+
1005
+ template <class A>
1006
+ XSIMD_INLINE batch_bool<double, A> lt(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1007
+ {
1008
+ return wasm_f64x2_lt(self, other);
1009
+ }
1010
+
1011
+ // mask
1012
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1013
+ XSIMD_INLINE uint64_t mask(batch_bool<T, A> const& self, requires_arch<wasm>) noexcept
1014
+ {
1015
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1016
+ {
1017
+ return wasm_i8x16_bitmask(self);
1018
+ }
1019
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1020
+ {
1021
+ return wasm_i16x8_bitmask(self);
1022
+ }
1023
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1024
+ {
1025
+ return wasm_i32x4_bitmask(self);
1026
+ }
1027
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1028
+ {
1029
+ return wasm_i64x2_bitmask(self);
1030
+ }
1031
+ else
1032
+ {
1033
+ assert(false && "unsupported arch/op combination");
1034
+ return {};
1035
+ }
1036
+ }
1037
+ template <class A>
1038
+ XSIMD_INLINE uint64_t mask(batch_bool<float, A> const& self, requires_arch<wasm>) noexcept
1039
+ {
1040
+ return wasm_i32x4_bitmask(self);
1041
+ }
1042
+
1043
+ template <class A>
1044
+ XSIMD_INLINE uint64_t mask(batch_bool<double, A> const& self, requires_arch<wasm>) noexcept
1045
+ {
1046
+ return wasm_i64x2_bitmask(self);
1047
+ }
1048
+
1049
+ // max
1050
+ template <class A>
1051
+ XSIMD_INLINE batch<float, A> max(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1052
+ {
1053
+ return wasm_f32x4_pmax(self, other);
1054
+ }
1055
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1056
+ XSIMD_INLINE batch<T, A> max(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1057
+ {
1058
+ return select(self > other, self, other);
1059
+ }
1060
+ template <class A>
1061
+ XSIMD_INLINE batch<double, A> max(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1062
+ {
1063
+ return wasm_f64x2_pmax(self, other);
1064
+ }
1065
+
1066
+ // min
1067
+ template <class A>
1068
+ XSIMD_INLINE batch<float, A> min(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1069
+ {
1070
+ return wasm_f32x4_pmin(self, other);
1071
+ }
1072
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1073
+ XSIMD_INLINE batch<T, A> min(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1074
+ {
1075
+ return select(self <= other, self, other);
1076
+ }
1077
+ template <class A>
1078
+ XSIMD_INLINE batch<double, A> min(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1079
+ {
1080
+ return wasm_f64x2_pmin(self, other);
1081
+ }
1082
+
1083
+ // mul
1084
+ template <class A>
1085
+ XSIMD_INLINE batch<float, A> mul(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1086
+ {
1087
+ return wasm_f32x4_mul(self, other);
1088
+ }
1089
+ template <class A>
1090
+ XSIMD_INLINE batch<double, A> mul(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1091
+ {
1092
+ return wasm_f64x2_mul(self, other);
1093
+ }
1094
+
1095
+ // neg
1096
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1097
+ XSIMD_INLINE batch<T, A> neg(batch<T, A> const& self, requires_arch<wasm>) noexcept
1098
+ {
1099
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1100
+ {
1101
+ return wasm_i8x16_neg(self);
1102
+ }
1103
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1104
+ {
1105
+ return wasm_i16x8_neg(self);
1106
+ }
1107
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1108
+ {
1109
+ return wasm_i32x4_neg(self);
1110
+ }
1111
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1112
+ {
1113
+ return wasm_i64x2_neg(self);
1114
+ }
1115
+ else
1116
+ {
1117
+ assert(false && "unsupported arch/op combination");
1118
+ return {};
1119
+ }
1120
+ }
1121
+
1122
+ template <class A>
1123
+ XSIMD_INLINE batch<float, A> neg(batch<float, A> const& self, requires_arch<wasm>) noexcept
1124
+ {
1125
+ return wasm_f32x4_neg(self);
1126
+ }
1127
+
1128
+ template <class A>
1129
+ XSIMD_INLINE batch<double, A> neg(batch<double, A> const& self, requires_arch<wasm>) noexcept
1130
+ {
1131
+ return wasm_f64x2_neg(self);
1132
+ }
1133
+
1134
+ // neq
1135
+ template <class A>
1136
+ XSIMD_INLINE batch_bool<float, A> neq(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1137
+ {
1138
+ return wasm_f32x4_ne(self, other);
1139
+ }
1140
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1141
+ XSIMD_INLINE batch_bool<T, A> neq(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1142
+ {
1143
+ return ~(self == other);
1144
+ }
1145
+ template <class A>
1146
+ XSIMD_INLINE batch_bool<float, A> neq(batch_bool<float, A> const& self, batch_bool<float, A> const& other, requires_arch<wasm>) noexcept
1147
+ {
1148
+ return wasm_v128_xor(self, other);
1149
+ }
1150
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1151
+ XSIMD_INLINE batch_bool<T, A> neq(batch_bool<T, A> const& self, batch_bool<T, A> const& other, requires_arch<wasm>) noexcept
1152
+ {
1153
+ return ~(self == other);
1154
+ }
1155
+
1156
+ template <class A>
1157
+ XSIMD_INLINE batch_bool<double, A> neq(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1158
+ {
1159
+ return wasm_f64x2_ne(self, other);
1160
+ }
1161
+ template <class A>
1162
+ XSIMD_INLINE batch_bool<double, A> neq(batch_bool<double, A> const& self, batch_bool<double, A> const& other, requires_arch<wasm>) noexcept
1163
+ {
1164
+ return wasm_v128_xor(self, other);
1165
+ }
1166
+
1167
+ // reciprocal
1168
+ template <class A>
1169
+ XSIMD_INLINE batch<float, A> reciprocal(batch<float, A> const& self, requires_arch<wasm>) noexcept
1170
+ {
1171
+ v128_t one = wasm_f32x4_splat(1.0f);
1172
+ return wasm_f32x4_div(one, self);
1173
+ }
1174
+ template <class A>
1175
+ XSIMD_INLINE batch<double, A> reciprocal(batch<double, A> const& self, requires_arch<wasm>) noexcept
1176
+ {
1177
+ v128_t one = wasm_f64x2_splat(1.0);
1178
+ return wasm_f64x2_div(one, self);
1179
+ }
1180
+
1181
+ // reduce_add
1182
+ template <class A>
1183
+ XSIMD_INLINE float reduce_add(batch<float, A> const& self, requires_arch<wasm>) noexcept
1184
+ {
1185
+ v128_t tmp0 = wasm_f32x4_add(self, wasm_i32x4_shuffle(self, self, 6, 7, 2, 3));
1186
+ v128_t tmp1 = wasm_i32x4_shuffle(tmp0, tmp0, 1, 0, 4, 4);
1187
+ v128_t tmp2 = wasm_f32x4_add(tmp0, tmp1);
1188
+ v128_t tmp3 = wasm_i32x4_shuffle(tmp0, tmp2, 4, 1, 2, 3);
1189
+ return wasm_f32x4_extract_lane(tmp3, 0);
1190
+ }
1191
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1192
+ XSIMD_INLINE T reduce_add(batch<T, A> const& self, requires_arch<wasm>) noexcept
1193
+ {
1194
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1195
+ {
1196
+ v128_t tmp0 = wasm_i32x4_shuffle(self, wasm_i32x4_splat(0), 2, 3, 0, 0);
1197
+ v128_t tmp1 = wasm_i32x4_add(self, tmp0);
1198
+ v128_t tmp2 = wasm_i32x4_shuffle(tmp1, wasm_i32x4_splat(0), 1, 0, 0, 0);
1199
+ v128_t tmp3 = wasm_i32x4_add(tmp1, tmp2);
1200
+ return wasm_i32x4_extract_lane(tmp3, 0);
1201
+ }
1202
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1203
+ {
1204
+ v128_t tmp0 = wasm_i32x4_shuffle(self, wasm_i32x4_splat(0), 2, 3, 0, 0);
1205
+ v128_t tmp1 = wasm_i64x2_add(self, tmp0);
1206
+ return wasm_i64x2_extract_lane(tmp1, 0);
1207
+ }
1208
+ else
1209
+ {
1210
+ return reduce_add(self, common {});
1211
+ }
1212
+ }
1213
+ template <class A>
1214
+ XSIMD_INLINE double reduce_add(batch<double, A> const& self, requires_arch<wasm>) noexcept
1215
+ {
1216
+ v128_t tmp0 = wasm_i64x2_shuffle(self, self, 1, 3);
1217
+ v128_t tmp1 = wasm_f64x2_add(self, tmp0);
1218
+ v128_t tmp2 = wasm_i64x2_shuffle(tmp0, tmp1, 2, 1);
1219
+ return wasm_f64x2_extract_lane(tmp2, 0);
1220
+ }
1221
+
1222
+ // reduce_mul
1223
+ template <class A>
1224
+ XSIMD_INLINE float reduce_mul(batch<float, A> const& self, requires_arch<wasm>) noexcept
1225
+ {
1226
+ v128_t tmp0 = wasm_f32x4_mul(self, wasm_i32x4_shuffle(self, self, 6, 7, 2, 3));
1227
+ v128_t tmp1 = wasm_i32x4_shuffle(tmp0, tmp0, 1, 0, 4, 4);
1228
+ v128_t tmp2 = wasm_f32x4_mul(tmp0, tmp1);
1229
+ v128_t tmp3 = wasm_i32x4_shuffle(tmp0, tmp2, 4, 1, 2, 3);
1230
+ return wasm_f32x4_extract_lane(tmp3, 0);
1231
+ }
1232
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1233
+ XSIMD_INLINE T reduce_mul(batch<T, A> const& self, requires_arch<wasm>) noexcept
1234
+ {
1235
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1236
+ {
1237
+ v128_t tmp0 = wasm_i32x4_shuffle(self, wasm_i32x4_splat(0), 2, 3, 0, 0);
1238
+ v128_t tmp1 = wasm_i32x4_mul(self, tmp0);
1239
+ v128_t tmp2 = wasm_i32x4_shuffle(tmp1, wasm_i32x4_splat(0), 1, 0, 0, 0);
1240
+ v128_t tmp3 = wasm_i32x4_mul(tmp1, tmp2);
1241
+ return wasm_i32x4_extract_lane(tmp3, 0);
1242
+ }
1243
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1244
+ {
1245
+ v128_t tmp0 = wasm_i32x4_shuffle(self, wasm_i32x4_splat(0), 2, 3, 0, 0);
1246
+ v128_t tmp1 = wasm_i64x2_mul(self, tmp0);
1247
+ return wasm_i64x2_extract_lane(tmp1, 0);
1248
+ }
1249
+ else
1250
+ {
1251
+ return reduce_mul(self, common {});
1252
+ }
1253
+ }
1254
+ template <class A>
1255
+ XSIMD_INLINE double reduce_mul(batch<double, A> const& self, requires_arch<wasm>) noexcept
1256
+ {
1257
+ v128_t tmp0 = wasm_i64x2_shuffle(self, self, 1, 3);
1258
+ v128_t tmp1 = wasm_f64x2_mul(self, tmp0);
1259
+ v128_t tmp2 = wasm_i64x2_shuffle(tmp0, tmp1, 2, 1);
1260
+ return wasm_f64x2_extract_lane(tmp2, 0);
1261
+ }
1262
+
1263
+ // rsqrt
1264
+ template <class A>
1265
+ XSIMD_INLINE batch<float, A> rsqrt(batch<float, A> const& self, requires_arch<wasm>) noexcept
1266
+ {
1267
+ v128_t one = wasm_f32x4_splat(1.0f);
1268
+ return wasm_f32x4_div(one, wasm_f32x4_sqrt(self));
1269
+ }
1270
+ template <class A>
1271
+ XSIMD_INLINE batch<double, A> rsqrt(batch<double, A> const& self, requires_arch<wasm>) noexcept
1272
+ {
1273
+ v128_t one = wasm_f64x2_splat(1.0);
1274
+ return wasm_f64x2_div(one, wasm_f64x2_sqrt(self));
1275
+ }
1276
+
1277
+ // slide_left
1278
+ template <size_t N, class A, class T>
1279
+ XSIMD_INLINE batch<T, A> slide_left(batch<T, A> const& x, requires_arch<wasm>) noexcept
1280
+ {
1281
+ return wasm_i8x16_shuffle(
1282
+ wasm_i64x2_const(0, 0), x, ((N) & 0xF0) ? 0 : 16 - ((N) & 0xF),
1283
+ ((N) & 0xF0) ? 0 : 17 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 18 - ((N) & 0xF),
1284
+ ((N) & 0xF0) ? 0 : 19 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 20 - ((N) & 0xF),
1285
+ ((N) & 0xF0) ? 0 : 21 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 22 - ((N) & 0xF),
1286
+ ((N) & 0xF0) ? 0 : 23 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 24 - ((N) & 0xF),
1287
+ ((N) & 0xF0) ? 0 : 25 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 26 - ((N) & 0xF),
1288
+ ((N) & 0xF0) ? 0 : 27 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 28 - ((N) & 0xF),
1289
+ ((N) & 0xF0) ? 0 : 29 - ((N) & 0xF), ((N) & 0xF0) ? 0 : 30 - ((N) & 0xF),
1290
+ ((N) & 0xF0) ? 0 : 31 - ((N) & 0xF));
1291
+ }
1292
+
1293
+ // slide_right
1294
+ template <size_t N, class A, class T>
1295
+ XSIMD_INLINE batch<T, A> slide_right(batch<T, A> const& x, requires_arch<wasm>) noexcept
1296
+ {
1297
+ return wasm_i8x16_shuffle(
1298
+ x, wasm_i64x2_const(0, 0), ((N) & 0xF0) ? 16 : ((N) & 0xF) + 0,
1299
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 1, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 2,
1300
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 3, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 4,
1301
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 5, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 6,
1302
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 7, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 8,
1303
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 9, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 10,
1304
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 11, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 12,
1305
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 13, ((N) & 0xF0) ? 16 : ((N) & 0xF) + 14,
1306
+ ((N) & 0xF0) ? 16 : ((N) & 0xF) + 15);
1307
+ }
1308
+
1309
+ // sadd
1310
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1311
+ XSIMD_INLINE batch<T, A> sadd(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1312
+ {
1313
+ if (std::is_signed<T>::value)
1314
+ {
1315
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1316
+ {
1317
+ return wasm_i8x16_add_sat(self, other);
1318
+ }
1319
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1320
+ {
1321
+ return wasm_i16x8_add_sat(self, other);
1322
+ }
1323
+ else
1324
+ {
1325
+ return sadd(self, other, common {});
1326
+ }
1327
+ }
1328
+ else
1329
+ {
1330
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1331
+ {
1332
+ return wasm_u8x16_add_sat(self, other);
1333
+ }
1334
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1335
+ {
1336
+ return wasm_u16x8_add_sat(self, other);
1337
+ }
1338
+ else
1339
+ {
1340
+ return sadd(self, other, common {});
1341
+ }
1342
+ }
1343
+ }
1344
+
1345
+ // select
1346
+ template <class A>
1347
+ XSIMD_INLINE batch<float, A> select(batch_bool<float, A> const& cond, batch<float, A> const& true_br, batch<float, A> const& false_br, requires_arch<wasm>) noexcept
1348
+ {
1349
+ return wasm_v128_or(wasm_v128_and(cond, true_br), wasm_v128_andnot(false_br, cond));
1350
+ }
1351
+
1352
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1353
+ XSIMD_INLINE batch<T, A> select(batch_bool<T, A> const& cond, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<wasm>) noexcept
1354
+ {
1355
+ return wasm_v128_or(wasm_v128_and(cond, true_br), wasm_v128_andnot(false_br, cond));
1356
+ }
1357
+ template <class A, class T, bool... Values, class = std::enable_if_t<std::is_integral<T>::value>>
1358
+ XSIMD_INLINE batch<T, A> select(batch_bool_constant<T, A, Values...> const&, batch<T, A> const& true_br, batch<T, A> const& false_br, requires_arch<wasm>) noexcept
1359
+ {
1360
+ return select(batch_bool<T, A> { Values... }, true_br, false_br, wasm {});
1361
+ }
1362
+ template <class A>
1363
+ XSIMD_INLINE batch<double, A> select(batch_bool<double, A> const& cond, batch<double, A> const& true_br, batch<double, A> const& false_br, requires_arch<wasm>) noexcept
1364
+ {
1365
+ return wasm_v128_or(wasm_v128_and(cond, true_br), wasm_v128_andnot(false_br, cond));
1366
+ }
1367
+
1368
+ // shuffle
1369
+ template <class A, class ITy, ITy I0, ITy I1, ITy I2, ITy I3>
1370
+ XSIMD_INLINE batch<float, A> shuffle(batch<float, A> const& x, batch<float, A> const& y, batch_constant<ITy, A, I0, I1, I2, I3>, requires_arch<wasm>) noexcept
1371
+ {
1372
+ return wasm_i32x4_shuffle(x, y, I0, I1, I2, I3);
1373
+ }
1374
+
1375
+ template <class A, class ITy, ITy I0, ITy I1>
1376
+ XSIMD_INLINE batch<double, A> shuffle(batch<double, A> const& x, batch<double, A> const& y, batch_constant<ITy, A, I0, I1>, requires_arch<wasm>) noexcept
1377
+ {
1378
+ return wasm_i64x2_shuffle(x, y, I0, I1);
1379
+ }
1380
+
1381
+ // set
1382
+ template <class A, class... Values>
1383
+ XSIMD_INLINE batch<float, A> set(batch<float, A> const&, requires_arch<wasm>, Values... values) noexcept
1384
+ {
1385
+ static_assert(sizeof...(Values) == batch<float, A>::size, "consistent init");
1386
+ return wasm_f32x4_make(values...);
1387
+ }
1388
+
1389
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1390
+ XSIMD_INLINE batch<T, A> set(batch<T, A> const&, requires_arch<wasm>, T v0, T v1) noexcept
1391
+ {
1392
+ return wasm_i64x2_make(v0, v1);
1393
+ }
1394
+
1395
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1396
+ XSIMD_INLINE batch<T, A> set(batch<T, A> const&, requires_arch<wasm>, T v0, T v1, T v2, T v3) noexcept
1397
+ {
1398
+ return wasm_i32x4_make(v0, v1, v2, v3);
1399
+ }
1400
+
1401
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1402
+ XSIMD_INLINE batch<T, A> set(batch<T, A> const&, requires_arch<wasm>, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7) noexcept
1403
+ {
1404
+ return wasm_i16x8_make(v0, v1, v2, v3, v4, v5, v6, v7);
1405
+ }
1406
+
1407
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1408
+ XSIMD_INLINE batch<T, A> set(batch<T, A> const&, requires_arch<wasm>, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14, T v15) noexcept
1409
+ {
1410
+ return wasm_i8x16_make(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15);
1411
+ }
1412
+
1413
+ template <class A, class... Values>
1414
+ XSIMD_INLINE batch<double, A> set(batch<double, A> const&, requires_arch<wasm>, Values... values) noexcept
1415
+ {
1416
+ static_assert(sizeof...(Values) == batch<double, A>::size, "consistent init");
1417
+ return wasm_f64x2_make(values...);
1418
+ }
1419
+
1420
+ template <class A, class T, class... Values, class = std::enable_if_t<std::is_integral<T>::value>>
1421
+ XSIMD_INLINE batch_bool<T, A> set(batch_bool<T, A> const&, requires_arch<wasm>, Values... values) noexcept
1422
+ {
1423
+ return set(batch<T, A>(), A {}, static_cast<T>(values ? -1LL : 0LL)...).data;
1424
+ }
1425
+
1426
+ template <class A, class... Values>
1427
+ XSIMD_INLINE batch_bool<float, A> set(batch_bool<float, A> const&, requires_arch<wasm>, Values... values) noexcept
1428
+ {
1429
+ static_assert(sizeof...(Values) == batch_bool<float, A>::size, "consistent init");
1430
+ return set(batch<int32_t, A>(), A {}, static_cast<int32_t>(values ? -1LL : 0LL)...).data;
1431
+ }
1432
+
1433
+ template <class A, class... Values>
1434
+ XSIMD_INLINE batch_bool<double, A> set(batch_bool<double, A> const&, requires_arch<wasm>, Values... values) noexcept
1435
+ {
1436
+ static_assert(sizeof...(Values) == batch_bool<double, A>::size, "consistent init");
1437
+ return set(batch<int64_t, A>(), A {}, static_cast<int64_t>(values ? -1LL : 0LL)...).data;
1438
+ }
1439
+
1440
+ // ssub
1441
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1442
+ XSIMD_INLINE batch<T, A> ssub(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1443
+ {
1444
+ if (std::is_signed<T>::value)
1445
+ {
1446
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1447
+ {
1448
+ return wasm_i8x16_sub_sat(self, other);
1449
+ }
1450
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1451
+ {
1452
+ return wasm_i16x8_sub_sat(self, other);
1453
+ }
1454
+ else
1455
+ {
1456
+ return ssub(self, other, common {});
1457
+ }
1458
+ }
1459
+ else
1460
+ {
1461
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1462
+ {
1463
+ return wasm_u8x16_sub_sat(self, other);
1464
+ }
1465
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1466
+ {
1467
+ return wasm_u16x8_sub_sat(self, other);
1468
+ }
1469
+ else
1470
+ {
1471
+ return ssub(self, other, common {});
1472
+ }
1473
+ }
1474
+ }
1475
+
1476
+ // store_aligned
1477
+ template <class A>
1478
+ XSIMD_INLINE void store_aligned(float* mem, batch<float, A> const& self, requires_arch<wasm>) noexcept
1479
+ {
1480
+ return wasm_v128_store(mem, self);
1481
+ }
1482
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1483
+ XSIMD_INLINE void store_aligned(T* mem, batch<T, A> const& self, requires_arch<wasm>) noexcept
1484
+ {
1485
+ return wasm_v128_store((v128_t*)mem, self);
1486
+ }
1487
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1488
+ XSIMD_INLINE void store_aligned(T* mem, batch_bool<T, A> const& self, requires_arch<wasm>) noexcept
1489
+ {
1490
+ return wasm_v128_store((v128_t*)mem, self);
1491
+ }
1492
+ template <class A>
1493
+ XSIMD_INLINE void store_aligned(double* mem, batch<double, A> const& self, requires_arch<wasm>) noexcept
1494
+ {
1495
+ return wasm_v128_store(mem, self);
1496
+ }
1497
+
1498
+ // store_complex
1499
+ namespace detail
1500
+ {
1501
+ // complex_low
1502
+ template <class A>
1503
+ XSIMD_INLINE batch<float, A> complex_low(batch<std::complex<float>, A> const& self, requires_arch<wasm>) noexcept
1504
+ {
1505
+ return wasm_i32x4_shuffle(self.real(), self.imag(), 0, 4, 1, 5);
1506
+ }
1507
+ // complex_high
1508
+ template <class A>
1509
+ XSIMD_INLINE batch<float, A> complex_high(batch<std::complex<float>, A> const& self, requires_arch<wasm>) noexcept
1510
+ {
1511
+ return wasm_i32x4_shuffle(self.real(), self.imag(), 2, 6, 3, 7);
1512
+ }
1513
+ template <class A>
1514
+ XSIMD_INLINE batch<double, A> complex_low(batch<std::complex<double>, A> const& self, requires_arch<wasm>) noexcept
1515
+ {
1516
+ return wasm_i64x2_shuffle(self.real(), self.imag(), 0, 2);
1517
+ }
1518
+ template <class A>
1519
+ XSIMD_INLINE batch<double, A> complex_high(batch<std::complex<double>, A> const& self, requires_arch<wasm>) noexcept
1520
+ {
1521
+ return wasm_i64x2_shuffle(self.real(), self.imag(), 1, 3);
1522
+ }
1523
+ }
1524
+
1525
+ // store_unaligned
1526
+ template <class A>
1527
+ XSIMD_INLINE void store_unaligned(float* mem, batch<float, A> const& self, requires_arch<wasm>) noexcept
1528
+ {
1529
+ return wasm_v128_store(mem, self);
1530
+ }
1531
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1532
+ XSIMD_INLINE void store_unaligned(T* mem, batch<T, A> const& self, requires_arch<wasm>) noexcept
1533
+ {
1534
+ return wasm_v128_store((v128_t*)mem, self);
1535
+ }
1536
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1537
+ XSIMD_INLINE void store_unaligned(T* mem, batch_bool<T, A> const& self, requires_arch<wasm>) noexcept
1538
+ {
1539
+ return wasm_v128_store((v128_t*)mem, self);
1540
+ }
1541
+ template <class A>
1542
+ XSIMD_INLINE void store_unaligned(double* mem, batch<double, A> const& self, requires_arch<wasm>) noexcept
1543
+ {
1544
+ return wasm_v128_store(mem, self);
1545
+ }
1546
+
1547
+ // sub
1548
+ template <class A>
1549
+ XSIMD_INLINE batch<float, A> sub(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1550
+ {
1551
+ return wasm_f32x4_sub(self, other);
1552
+ }
1553
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1554
+ XSIMD_INLINE batch<T, A> sub(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1555
+ {
1556
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1557
+ {
1558
+ return wasm_i8x16_sub(self, other);
1559
+ }
1560
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1561
+ {
1562
+ return wasm_i16x8_sub(self, other);
1563
+ }
1564
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1565
+ {
1566
+ return wasm_i32x4_sub(self, other);
1567
+ }
1568
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1569
+ {
1570
+ return wasm_i64x2_sub(self, other);
1571
+ }
1572
+ else
1573
+ {
1574
+ assert(false && "unsupported arch/op combination");
1575
+ return {};
1576
+ }
1577
+ }
1578
+ template <class A>
1579
+ XSIMD_INLINE batch<double, A> sub(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1580
+ {
1581
+ return wasm_f64x2_sub(self, other);
1582
+ }
1583
+
1584
+ // sqrt
1585
+ template <class A>
1586
+ XSIMD_INLINE batch<float, A> sqrt(batch<float, A> const& val, requires_arch<wasm>) noexcept
1587
+ {
1588
+ return wasm_f32x4_sqrt(val);
1589
+ }
1590
+ template <class A>
1591
+ XSIMD_INLINE batch<double, A> sqrt(batch<double, A> const& val, requires_arch<wasm>) noexcept
1592
+ {
1593
+ return wasm_f64x2_sqrt(val);
1594
+ }
1595
+
1596
+ // swizzle
1597
+ template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
1598
+ XSIMD_INLINE batch<float, A> swizzle(batch<float, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<wasm>) noexcept
1599
+ {
1600
+ return wasm_i32x4_shuffle(self, self, V0, V1, V2, V3);
1601
+ }
1602
+
1603
+ template <class A, uint64_t V0, uint64_t V1>
1604
+ XSIMD_INLINE batch<double, A> swizzle(batch<double, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<wasm>) noexcept
1605
+ {
1606
+ return wasm_i64x2_shuffle(self, self, V0, V1);
1607
+ }
1608
+
1609
+ template <class A, uint64_t V0, uint64_t V1>
1610
+ XSIMD_INLINE batch<uint64_t, A> swizzle(batch<uint64_t, A> const& self, batch_constant<uint64_t, A, V0, V1>, requires_arch<wasm>) noexcept
1611
+ {
1612
+ return wasm_i64x2_shuffle(self, self, V0, V1);
1613
+ }
1614
+
1615
+ template <class A, uint64_t V0, uint64_t V1>
1616
+ XSIMD_INLINE batch<int64_t, A> swizzle(batch<int64_t, A> const& self, batch_constant<uint64_t, A, V0, V1> mask, requires_arch<wasm>) noexcept
1617
+ {
1618
+ return bitwise_cast<int64_t>(swizzle(bitwise_cast<uint64_t>(self), mask, wasm {}));
1619
+ }
1620
+
1621
+ template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
1622
+ XSIMD_INLINE batch<uint32_t, A> swizzle(batch<uint32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3>, requires_arch<wasm>) noexcept
1623
+ {
1624
+ return wasm_i32x4_shuffle(self, self, V0, V1, V2, V3);
1625
+ }
1626
+
1627
+ template <class A, uint32_t V0, uint32_t V1, uint32_t V2, uint32_t V3>
1628
+ XSIMD_INLINE batch<int32_t, A> swizzle(batch<int32_t, A> const& self, batch_constant<uint32_t, A, V0, V1, V2, V3> mask, requires_arch<wasm>) noexcept
1629
+ {
1630
+ return bitwise_cast<int32_t>(swizzle(bitwise_cast<uint32_t>(self), mask, wasm {}));
1631
+ }
1632
+
1633
+ template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
1634
+ XSIMD_INLINE batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<wasm>) noexcept
1635
+ {
1636
+ return wasm_i16x8_shuffle(self, self, V0, V1, V2, V3, V4, V5, V6, V7);
1637
+ }
1638
+
1639
+ template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
1640
+ XSIMD_INLINE batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<uint16_t, A, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<wasm>) noexcept
1641
+ {
1642
+ return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), mask, wasm {}));
1643
+ }
1644
+
1645
+ template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
1646
+ uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
1647
+ XSIMD_INLINE batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15>, requires_arch<wasm>) noexcept
1648
+ {
1649
+ return wasm_i8x16_shuffle(self, self, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15);
1650
+ }
1651
+
1652
+ template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
1653
+ uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
1654
+ XSIMD_INLINE batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<uint8_t, A, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<wasm>) noexcept
1655
+ {
1656
+ return bitwise_cast<int8_t>(swizzle(bitwise_cast<uint8_t>(self), mask, wasm {}));
1657
+ }
1658
+
1659
+ // transpose
1660
+ template <class A, class T>
1661
+ XSIMD_INLINE void transpose(batch<T, A>* matrix_begin, batch<T, A>* matrix_end, requires_arch<wasm>) noexcept
1662
+ {
1663
+ assert((matrix_end - matrix_begin == batch<T, A>::size) && "correctly sized matrix");
1664
+ (void)matrix_end;
1665
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1666
+ {
1667
+ auto r0 = matrix_begin[0], r1 = matrix_begin[1], r2 = matrix_begin[2], r3 = matrix_begin[3];
1668
+
1669
+ auto t0 = wasm_i32x4_shuffle(r0, r1, 0, 4, 1, 5); // r0[0] r1[0] r0[1] r1[1]
1670
+ auto t1 = wasm_i32x4_shuffle(r0, r1, 2, 6, 3, 7); // r0[2] r1[2] r0[3] r1[3]
1671
+
1672
+ auto t2 = wasm_i32x4_shuffle(r2, r3, 0, 4, 1, 5); // r2[0] r3[0] r2[1] r3[1]
1673
+ auto t3 = wasm_i32x4_shuffle(r2, r3, 2, 6, 3, 7); // r2[2] r3[2] r2[3] r3[3]
1674
+
1675
+ matrix_begin[0] = wasm_i32x4_shuffle(t0, t2, 0, 1, 4, 5); // r0[0] r1[0] r2[0] r3[0]
1676
+ matrix_begin[1] = wasm_i32x4_shuffle(t0, t2, 2, 3, 6, 7); // r0[1] r1[1] r2[1] r3[1]
1677
+ matrix_begin[2] = wasm_i32x4_shuffle(t1, t3, 0, 1, 4, 5); // r0[2] r1[2] r2[2] r3[2]
1678
+ matrix_begin[3] = wasm_i32x4_shuffle(t1, t3, 2, 3, 6, 7); // r0[3] r1[3] r2[3] r3[3]
1679
+ }
1680
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1681
+ {
1682
+ auto r0 = matrix_begin[0], r1 = matrix_begin[1];
1683
+
1684
+ matrix_begin[0] = wasm_i64x2_shuffle(r0, r1, 0, 2);
1685
+ matrix_begin[1] = wasm_i64x2_shuffle(r0, r1, 1, 3);
1686
+ }
1687
+ else
1688
+ {
1689
+ transpose(matrix_begin, matrix_end, common {});
1690
+ }
1691
+ }
1692
+
1693
+ // trunc
1694
+ template <class A>
1695
+ XSIMD_INLINE batch<float, A> trunc(batch<float, A> const& self, requires_arch<wasm>) noexcept
1696
+ {
1697
+ return wasm_f32x4_trunc(self);
1698
+ }
1699
+ template <class A>
1700
+ XSIMD_INLINE batch<double, A> trunc(batch<double, A> const& self, requires_arch<wasm>) noexcept
1701
+ {
1702
+ return wasm_f64x2_trunc(self);
1703
+ }
1704
+
1705
+ // widen
1706
+ template <class A>
1707
+ XSIMD_INLINE std::array<batch<double, A>, 2> widen(batch<float, A> const& x, requires_arch<wasm>) noexcept
1708
+ {
1709
+ return { batch<double, A>(wasm_f64x2_promote_low_f32x4(x)),
1710
+ batch<double, A>(wasm_f64x2_promote_low_f32x4(wasm_i32x4_shuffle(x, x, 2, 3, 0, 1))) };
1711
+ }
1712
+ template <class A>
1713
+ XSIMD_INLINE std::array<batch<widen_t<uint8_t>, A>, 2> widen(batch<uint8_t, A> const& x, requires_arch<wasm>) noexcept
1714
+ {
1715
+ return { batch<widen_t<uint8_t>, A>(wasm_u16x8_extend_low_u8x16(x)), batch<widen_t<uint8_t>, A>(wasm_u16x8_extend_high_u8x16(x)) };
1716
+ }
1717
+ template <class A>
1718
+ XSIMD_INLINE std::array<batch<widen_t<int8_t>, A>, 2> widen(batch<int8_t, A> const& x, requires_arch<wasm>) noexcept
1719
+ {
1720
+ return { batch<widen_t<int8_t>, A>(wasm_i16x8_extend_low_i8x16(x)), batch<widen_t<int8_t>, A>(wasm_i16x8_extend_high_i8x16(x)) };
1721
+ }
1722
+ template <class A>
1723
+ XSIMD_INLINE std::array<batch<widen_t<uint16_t>, A>, 2> widen(batch<uint16_t, A> const& x, requires_arch<wasm>) noexcept
1724
+ {
1725
+ return { batch<widen_t<uint16_t>, A>(wasm_u32x4_extend_low_u16x8(x)), batch<widen_t<uint16_t>, A>(wasm_u32x4_extend_high_u16x8(x)) };
1726
+ }
1727
+ template <class A>
1728
+ XSIMD_INLINE std::array<batch<widen_t<int16_t>, A>, 2> widen(batch<int16_t, A> const& x, requires_arch<wasm>) noexcept
1729
+ {
1730
+ return { batch<widen_t<int16_t>, A>(wasm_i32x4_extend_low_i16x8(x)), batch<widen_t<int16_t>, A>(wasm_i32x4_extend_high_i16x8(x)) };
1731
+ }
1732
+ template <class A>
1733
+ XSIMD_INLINE std::array<batch<widen_t<uint32_t>, A>, 2> widen(batch<uint32_t, A> const& x, requires_arch<wasm>) noexcept
1734
+ {
1735
+ return { batch<widen_t<uint32_t>, A>(wasm_u64x2_extend_low_u32x4(x)), batch<widen_t<uint32_t>, A>(wasm_u64x2_extend_high_u32x4(x)) };
1736
+ }
1737
+ template <class A>
1738
+ XSIMD_INLINE std::array<batch<widen_t<int32_t>, A>, 2> widen(batch<int32_t, A> const& x, requires_arch<wasm>) noexcept
1739
+ {
1740
+ return { batch<widen_t<int32_t>, A>(wasm_i64x2_extend_low_i32x4(x)), batch<widen_t<int32_t>, A>(wasm_i64x2_extend_high_i32x4(x)) };
1741
+ }
1742
+
1743
+ // zip_hi
1744
+ template <class A>
1745
+ XSIMD_INLINE batch<float, A> zip_hi(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1746
+ {
1747
+ return wasm_i32x4_shuffle(self, other, 2, 6, 3, 7);
1748
+ }
1749
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1750
+ XSIMD_INLINE batch<T, A> zip_hi(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1751
+ {
1752
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1753
+ {
1754
+ return wasm_i8x16_shuffle(self, other, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31);
1755
+ }
1756
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1757
+ {
1758
+ return wasm_i16x8_shuffle(self, other, 4, 12, 5, 13, 6, 14, 7, 15);
1759
+ }
1760
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1761
+ {
1762
+ return wasm_i32x4_shuffle(self, other, 2, 6, 3, 7);
1763
+ }
1764
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1765
+ {
1766
+ return wasm_i64x2_shuffle(self, other, 1, 3);
1767
+ }
1768
+ else
1769
+ {
1770
+ assert(false && "unsupported arch/op combination");
1771
+ return {};
1772
+ }
1773
+ }
1774
+ template <class A>
1775
+ XSIMD_INLINE batch<double, A> zip_hi(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1776
+ {
1777
+ return wasm_i64x2_shuffle(self, other, 1, 3);
1778
+ }
1779
+
1780
+ // zip_lo
1781
+ template <class A>
1782
+ XSIMD_INLINE batch<float, A> zip_lo(batch<float, A> const& self, batch<float, A> const& other, requires_arch<wasm>) noexcept
1783
+ {
1784
+ return wasm_i32x4_shuffle(self, other, 0, 4, 1, 5);
1785
+ }
1786
+ template <class A, class T, class = std::enable_if_t<std::is_integral<T>::value>>
1787
+ XSIMD_INLINE batch<T, A> zip_lo(batch<T, A> const& self, batch<T, A> const& other, requires_arch<wasm>) noexcept
1788
+ {
1789
+ XSIMD_IF_CONSTEXPR(sizeof(T) == 1)
1790
+ {
1791
+ return wasm_i8x16_shuffle(self, other, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23);
1792
+ }
1793
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 2)
1794
+ {
1795
+ return wasm_i16x8_shuffle(self, other, 0, 8, 1, 9, 2, 10, 3, 11);
1796
+ }
1797
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 4)
1798
+ {
1799
+ return wasm_i32x4_shuffle(self, other, 0, 4, 1, 5);
1800
+ }
1801
+ else XSIMD_IF_CONSTEXPR(sizeof(T) == 8)
1802
+ {
1803
+ return wasm_i64x2_shuffle(self, other, 0, 2);
1804
+ }
1805
+ else
1806
+ {
1807
+ assert(false && "unsupported arch/op combination");
1808
+ return {};
1809
+ }
1810
+ }
1811
+ template <class A>
1812
+ XSIMD_INLINE batch<double, A> zip_lo(batch<double, A> const& self, batch<double, A> const& other, requires_arch<wasm>) noexcept
1813
+ {
1814
+ return wasm_i64x2_shuffle(self, other, 0, 2);
1815
+ }
1816
+ }
1817
+ }
1818
+
1819
+ #endif