stride-align 0.6.0

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 (190) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/NOTICE +255 -0
  4. data/README.md +107 -0
  5. data/data/bmpm_data/gen_approx_any.txt +131 -0
  6. data/data/bmpm_data/gen_approx_arabic.txt +26 -0
  7. data/data/bmpm_data/gen_approx_common.txt +233 -0
  8. data/data/bmpm_data/gen_approx_cyrillic.txt +18 -0
  9. data/data/bmpm_data/gen_approx_czech.txt +18 -0
  10. data/data/bmpm_data/gen_approx_dutch.txt +18 -0
  11. data/data/bmpm_data/gen_approx_english.txt +47 -0
  12. data/data/bmpm_data/gen_approx_french.txt +25 -0
  13. data/data/bmpm_data/gen_approx_german.txt +73 -0
  14. data/data/bmpm_data/gen_approx_greek.txt +18 -0
  15. data/data/bmpm_data/gen_approx_greeklatin.txt +20 -0
  16. data/data/bmpm_data/gen_approx_hebrew.txt +18 -0
  17. data/data/bmpm_data/gen_approx_hungarian.txt +18 -0
  18. data/data/bmpm_data/gen_approx_italian.txt +18 -0
  19. data/data/bmpm_data/gen_approx_polish.txt +84 -0
  20. data/data/bmpm_data/gen_approx_portuguese.txt +18 -0
  21. data/data/bmpm_data/gen_approx_romanian.txt +18 -0
  22. data/data/bmpm_data/gen_approx_russian.txt +48 -0
  23. data/data/bmpm_data/gen_approx_spanish.txt +21 -0
  24. data/data/bmpm_data/gen_approx_turkish.txt +18 -0
  25. data/data/bmpm_data/gen_exact_any.txt +40 -0
  26. data/data/bmpm_data/gen_exact_approx_common.txt +79 -0
  27. data/data/bmpm_data/gen_exact_arabic.txt +18 -0
  28. data/data/bmpm_data/gen_exact_common.txt +32 -0
  29. data/data/bmpm_data/gen_exact_cyrillic.txt +18 -0
  30. data/data/bmpm_data/gen_exact_czech.txt +18 -0
  31. data/data/bmpm_data/gen_exact_dutch.txt +18 -0
  32. data/data/bmpm_data/gen_exact_english.txt +18 -0
  33. data/data/bmpm_data/gen_exact_french.txt +18 -0
  34. data/data/bmpm_data/gen_exact_german.txt +18 -0
  35. data/data/bmpm_data/gen_exact_greek.txt +18 -0
  36. data/data/bmpm_data/gen_exact_greeklatin.txt +18 -0
  37. data/data/bmpm_data/gen_exact_hebrew.txt +18 -0
  38. data/data/bmpm_data/gen_exact_hungarian.txt +18 -0
  39. data/data/bmpm_data/gen_exact_italian.txt +18 -0
  40. data/data/bmpm_data/gen_exact_polish.txt +23 -0
  41. data/data/bmpm_data/gen_exact_portuguese.txt +18 -0
  42. data/data/bmpm_data/gen_exact_romanian.txt +18 -0
  43. data/data/bmpm_data/gen_exact_russian.txt +19 -0
  44. data/data/bmpm_data/gen_exact_spanish.txt +19 -0
  45. data/data/bmpm_data/gen_exact_turkish.txt +18 -0
  46. data/data/bmpm_data/gen_hebrew_common.txt +113 -0
  47. data/data/bmpm_data/gen_lang.txt +295 -0
  48. data/data/bmpm_data/gen_languages.txt +36 -0
  49. data/data/bmpm_data/gen_rules_any.txt +367 -0
  50. data/data/bmpm_data/gen_rules_arabic.txt +76 -0
  51. data/data/bmpm_data/gen_rules_cyrillic.txt +99 -0
  52. data/data/bmpm_data/gen_rules_czech.txt +67 -0
  53. data/data/bmpm_data/gen_rules_dutch.txt +78 -0
  54. data/data/bmpm_data/gen_rules_english.txt +113 -0
  55. data/data/bmpm_data/gen_rules_french.txt +114 -0
  56. data/data/bmpm_data/gen_rules_german.txt +129 -0
  57. data/data/bmpm_data/gen_rules_greek.txt +97 -0
  58. data/data/bmpm_data/gen_rules_greeklatin.txt +118 -0
  59. data/data/bmpm_data/gen_rules_hebrew.txt +62 -0
  60. data/data/bmpm_data/gen_rules_hungarian.txt +83 -0
  61. data/data/bmpm_data/gen_rules_italian.txt +77 -0
  62. data/data/bmpm_data/gen_rules_polish.txt +185 -0
  63. data/data/bmpm_data/gen_rules_portuguese.txt +105 -0
  64. data/data/bmpm_data/gen_rules_romanian.txt +64 -0
  65. data/data/bmpm_data/gen_rules_russian.txt +142 -0
  66. data/data/bmpm_data/gen_rules_spanish.txt +85 -0
  67. data/data/bmpm_data/gen_rules_turkish.txt +50 -0
  68. data/data/keyboard_data/qwerty.npy +0 -0
  69. data/data/matrix_data/BLOSUM100 +31 -0
  70. data/data/matrix_data/BLOSUM30 +31 -0
  71. data/data/matrix_data/BLOSUM35 +31 -0
  72. data/data/matrix_data/BLOSUM40 +31 -0
  73. data/data/matrix_data/BLOSUM45 +25 -0
  74. data/data/matrix_data/BLOSUM50 +25 -0
  75. data/data/matrix_data/BLOSUM55 +31 -0
  76. data/data/matrix_data/BLOSUM60 +31 -0
  77. data/data/matrix_data/BLOSUM62 +25 -0
  78. data/data/matrix_data/BLOSUM65 +31 -0
  79. data/data/matrix_data/BLOSUM70 +31 -0
  80. data/data/matrix_data/BLOSUM75 +31 -0
  81. data/data/matrix_data/BLOSUM80 +25 -0
  82. data/data/matrix_data/BLOSUM85 +31 -0
  83. data/data/matrix_data/BLOSUM90 +25 -0
  84. data/data/matrix_data/NUC.4.4 +25 -0
  85. data/data/matrix_data/PAM10 +34 -0
  86. data/data/matrix_data/PAM100 +34 -0
  87. data/data/matrix_data/PAM110 +34 -0
  88. data/data/matrix_data/PAM120 +34 -0
  89. data/data/matrix_data/PAM130 +34 -0
  90. data/data/matrix_data/PAM140 +34 -0
  91. data/data/matrix_data/PAM150 +34 -0
  92. data/data/matrix_data/PAM160 +34 -0
  93. data/data/matrix_data/PAM170 +34 -0
  94. data/data/matrix_data/PAM180 +34 -0
  95. data/data/matrix_data/PAM190 +34 -0
  96. data/data/matrix_data/PAM20 +34 -0
  97. data/data/matrix_data/PAM200 +34 -0
  98. data/data/matrix_data/PAM210 +34 -0
  99. data/data/matrix_data/PAM220 +34 -0
  100. data/data/matrix_data/PAM230 +34 -0
  101. data/data/matrix_data/PAM240 +34 -0
  102. data/data/matrix_data/PAM250 +25 -0
  103. data/data/matrix_data/PAM260 +34 -0
  104. data/data/matrix_data/PAM270 +34 -0
  105. data/data/matrix_data/PAM280 +34 -0
  106. data/data/matrix_data/PAM290 +34 -0
  107. data/data/matrix_data/PAM30 +25 -0
  108. data/data/matrix_data/PAM300 +34 -0
  109. data/data/matrix_data/PAM310 +34 -0
  110. data/data/matrix_data/PAM320 +34 -0
  111. data/data/matrix_data/PAM330 +34 -0
  112. data/data/matrix_data/PAM340 +34 -0
  113. data/data/matrix_data/PAM350 +34 -0
  114. data/data/matrix_data/PAM360 +34 -0
  115. data/data/matrix_data/PAM370 +34 -0
  116. data/data/matrix_data/PAM380 +34 -0
  117. data/data/matrix_data/PAM390 +34 -0
  118. data/data/matrix_data/PAM40 +34 -0
  119. data/data/matrix_data/PAM400 +34 -0
  120. data/data/matrix_data/PAM410 +34 -0
  121. data/data/matrix_data/PAM420 +34 -0
  122. data/data/matrix_data/PAM430 +34 -0
  123. data/data/matrix_data/PAM440 +34 -0
  124. data/data/matrix_data/PAM450 +34 -0
  125. data/data/matrix_data/PAM460 +34 -0
  126. data/data/matrix_data/PAM470 +34 -0
  127. data/data/matrix_data/PAM480 +34 -0
  128. data/data/matrix_data/PAM490 +34 -0
  129. data/data/matrix_data/PAM50 +34 -0
  130. data/data/matrix_data/PAM500 +34 -0
  131. data/data/matrix_data/PAM60 +34 -0
  132. data/data/matrix_data/PAM70 +25 -0
  133. data/data/matrix_data/PAM80 +34 -0
  134. data/data/matrix_data/PAM90 +34 -0
  135. data/ext/stride_align/backend_avx2.cpp +2 -0
  136. data/ext/stride_align/backend_avx512bwvl.cpp +2 -0
  137. data/ext/stride_align/backend_generic.cpp +3 -0
  138. data/ext/stride_align/backend_impl.hpp +983 -0
  139. data/ext/stride_align/backend_lasx.cpp +2 -0
  140. data/ext/stride_align/backend_lsx.cpp +2 -0
  141. data/ext/stride_align/backend_neon.cpp +2 -0
  142. data/ext/stride_align/backend_rvv.cpp +2 -0
  143. data/ext/stride_align/backend_sse41.cpp +2 -0
  144. data/ext/stride_align/backend_sve.cpp +2 -0
  145. data/ext/stride_align/backend_sve2.cpp +2 -0
  146. data/ext/stride_align/backend_vsx.cpp +2 -0
  147. data/ext/stride_align/beider_morse_impl.cpp +5 -0
  148. data/ext/stride_align/cpu_detect.cpp +172 -0
  149. data/ext/stride_align/cpu_detect.hpp +6 -0
  150. data/ext/stride_align/extconf.rb +114 -0
  151. data/ext/stride_align/target_profile.hpp +82 -0
  152. data/ext/stride_align/vendor/beider_morse_impl.cpp +1467 -0
  153. data/ext/stride_align/vendor/stride_align/alignment.hpp +199 -0
  154. data/ext/stride_align/vendor/stride_align/batch.hpp +812 -0
  155. data/ext/stride_align/vendor/stride_align/beider_morse.hpp +121 -0
  156. data/ext/stride_align/vendor/stride_align/caverphone.hpp +222 -0
  157. data/ext/stride_align/vendor/stride_align/cologne_phonetic.hpp +202 -0
  158. data/ext/stride_align/vendor/stride_align/core.hpp +731 -0
  159. data/ext/stride_align/vendor/stride_align/daitch_mokotoff.hpp +631 -0
  160. data/ext/stride_align/vendor/stride_align/double_metaphone.hpp +796 -0
  161. data/ext/stride_align/vendor/stride_align/dtw.hpp +300 -0
  162. data/ext/stride_align/vendor/stride_align/encoded.hpp +235 -0
  163. data/ext/stride_align/vendor/stride_align/hamming.hpp +55 -0
  164. data/ext/stride_align/vendor/stride_align/indel.hpp +1200 -0
  165. data/ext/stride_align/vendor/stride_align/jaro.hpp +517 -0
  166. data/ext/stride_align/vendor/stride_align/lcs.hpp +159 -0
  167. data/ext/stride_align/vendor/stride_align/levenshtein.hpp +1247 -0
  168. data/ext/stride_align/vendor/stride_align/levenshtein_prepared.hpp +193 -0
  169. data/ext/stride_align/vendor/stride_align/match_rating.hpp +168 -0
  170. data/ext/stride_align/vendor/stride_align/metaphone.hpp +291 -0
  171. data/ext/stride_align/vendor/stride_align/ngram.hpp +176 -0
  172. data/ext/stride_align/vendor/stride_align/nysiis.hpp +199 -0
  173. data/ext/stride_align/vendor/stride_align/pairwise_alignment.hpp +465 -0
  174. data/ext/stride_align/vendor/stride_align/partial_ratio.hpp +486 -0
  175. data/ext/stride_align/vendor/stride_align/ratcliff_obershelp.hpp +101 -0
  176. data/ext/stride_align/vendor/stride_align/soundex.hpp +108 -0
  177. data/ext/stride_align/vendor/stride_align/token_ratios.hpp +445 -0
  178. data/ext/stride_align/vendor/stride_align/types.hpp +16 -0
  179. data/ext/stride_align/vendor/stride_align/utf8.hpp +512 -0
  180. data/ext/stride_align/vendor/stride_align/wratio.hpp +363 -0
  181. data/lib/stride_align/algorithms.rb +296 -0
  182. data/lib/stride_align/alignment_path.rb +217 -0
  183. data/lib/stride_align/backend.rb +47 -0
  184. data/lib/stride_align/batch.rb +705 -0
  185. data/lib/stride_align/core.rb +180 -0
  186. data/lib/stride_align/keyboard.rb +200 -0
  187. data/lib/stride_align/matrices.rb +403 -0
  188. data/lib/stride_align/version.rb +5 -0
  189. data/lib/stride_align.rb +87 -0
  190. metadata +231 -0
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_LASX 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_LSX 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_NEON 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_RVV 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_SSE41 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_SVE 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_SVE2 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,2 @@
1
+ #define STRIDE_ALIGN_RUBY_TARGET_VSX 1
2
+ #include "backend_impl.hpp"
@@ -0,0 +1,5 @@
1
+ #if __has_include("vendor/beider_morse_impl.cpp")
2
+ #include "vendor/beider_morse_impl.cpp"
3
+ #else
4
+ #include "../../../../src/cpp/beider_morse_impl.cpp"
5
+ #endif
@@ -0,0 +1,172 @@
1
+ #include "cpu_detect.hpp"
2
+
3
+ #include <string>
4
+ #include <vector>
5
+
6
+ #if defined(__linux__) && \
7
+ (defined(__aarch64__) || defined(__loongarch__) || \
8
+ defined(__powerpc64__) || defined(__ppc64__) || defined(__riscv))
9
+ #include <sys/auxv.h>
10
+ #endif
11
+
12
+ #if defined(__linux__) && defined(__aarch64__)
13
+ #include <asm/hwcap.h>
14
+ #include <sys/prctl.h>
15
+ #endif
16
+
17
+ #if defined(__linux__) && defined(__loongarch__)
18
+ #include <asm/hwcap.h>
19
+ #endif
20
+
21
+ #if defined(__linux__) && \
22
+ (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
23
+ #include <asm/cputable.h>
24
+ #endif
25
+
26
+ #if defined(__linux__) && defined(__riscv)
27
+ #include <asm/hwcap.h>
28
+ #endif
29
+
30
+ namespace {
31
+
32
+ [[maybe_unused]] bool supports_sse41() noexcept {
33
+ #if (defined(__x86_64__) || defined(__i386__)) && \
34
+ (defined(__GNUC__) || defined(__clang__))
35
+ __builtin_cpu_init();
36
+ return __builtin_cpu_supports("sse4.1") != 0;
37
+ #else
38
+ return false;
39
+ #endif
40
+ }
41
+
42
+ [[maybe_unused]] bool supports_x86_64_v3() noexcept {
43
+ #if (defined(__x86_64__) || defined(__i386__)) && \
44
+ (defined(__GNUC__) || defined(__clang__))
45
+ __builtin_cpu_init();
46
+ return __builtin_cpu_supports("avx2") != 0 &&
47
+ __builtin_cpu_supports("bmi") != 0 &&
48
+ __builtin_cpu_supports("bmi2") != 0 &&
49
+ __builtin_cpu_supports("f16c") != 0 &&
50
+ __builtin_cpu_supports("fma") != 0 &&
51
+ __builtin_cpu_supports("lzcnt") != 0 &&
52
+ __builtin_cpu_supports("movbe") != 0;
53
+ #else
54
+ return false;
55
+ #endif
56
+ }
57
+
58
+ [[maybe_unused]] bool supports_avx512bwvl() noexcept {
59
+ #if (defined(__x86_64__) || defined(__i386__)) && \
60
+ (defined(__GNUC__) || defined(__clang__))
61
+ __builtin_cpu_init();
62
+ return supports_x86_64_v3() &&
63
+ __builtin_cpu_supports("avx512f") != 0 &&
64
+ __builtin_cpu_supports("avx512bw") != 0 &&
65
+ __builtin_cpu_supports("avx512cd") != 0 &&
66
+ __builtin_cpu_supports("avx512vl") != 0 &&
67
+ __builtin_cpu_supports("avx512dq") != 0;
68
+ #else
69
+ return false;
70
+ #endif
71
+ }
72
+
73
+ [[maybe_unused]] bool supports_neon() noexcept {
74
+ #if defined(__APPLE__) && defined(__aarch64__)
75
+ return true;
76
+ #elif defined(__linux__) && defined(__aarch64__)
77
+ return (getauxval(AT_HWCAP) & HWCAP_ASIMD) != 0;
78
+ #else
79
+ return false;
80
+ #endif
81
+ }
82
+
83
+ [[maybe_unused]] bool supports_sve() noexcept {
84
+ #if defined(__linux__) && defined(__aarch64__) && defined(HWCAP_SVE) && \
85
+ defined(PR_SVE_GET_VL) && defined(PR_SVE_VL_LEN_MASK)
86
+ if ((getauxval(AT_HWCAP) & HWCAP_SVE) == 0) return false;
87
+ const int vector_length = prctl(PR_SVE_GET_VL);
88
+ return vector_length >= 0 &&
89
+ (vector_length & PR_SVE_VL_LEN_MASK) == 16;
90
+ #else
91
+ return false;
92
+ #endif
93
+ }
94
+
95
+ [[maybe_unused]] bool supports_sve2() noexcept {
96
+ #if defined(__linux__) && defined(__aarch64__) && defined(HWCAP2_SVE2)
97
+ return supports_sve() && (getauxval(AT_HWCAP2) & HWCAP2_SVE2) != 0;
98
+ #else
99
+ return false;
100
+ #endif
101
+ }
102
+
103
+ [[maybe_unused]] bool supports_lsx() noexcept {
104
+ #if defined(__linux__) && defined(__loongarch__)
105
+ return (getauxval(AT_HWCAP) & HWCAP_LOONGARCH_LSX) != 0;
106
+ #else
107
+ return false;
108
+ #endif
109
+ }
110
+
111
+ [[maybe_unused]] bool supports_lasx() noexcept {
112
+ #if defined(__linux__) && defined(__loongarch__)
113
+ return (getauxval(AT_HWCAP) & HWCAP_LOONGARCH_LASX) != 0;
114
+ #else
115
+ return false;
116
+ #endif
117
+ }
118
+
119
+ [[maybe_unused]] bool supports_vsx() noexcept {
120
+ #if defined(__linux__) && \
121
+ (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__))
122
+ return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_VSX) != 0;
123
+ #else
124
+ return false;
125
+ #endif
126
+ }
127
+
128
+ [[maybe_unused]] bool supports_rvv() noexcept {
129
+ #if defined(__linux__) && defined(__riscv) && defined(COMPAT_HWCAP_ISA_V)
130
+ return (getauxval(AT_HWCAP) & COMPAT_HWCAP_ISA_V) != 0;
131
+ #else
132
+ return false;
133
+ #endif
134
+ }
135
+
136
+ } // namespace
137
+
138
+ std::vector<std::string> stride_align_ruby_backend_candidates() {
139
+ std::vector<std::string> names;
140
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_AVX512BWVL)
141
+ if (supports_avx512bwvl()) names.emplace_back("avx512bwvl");
142
+ #endif
143
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_AVX2)
144
+ if (supports_x86_64_v3()) names.emplace_back("avx2");
145
+ #endif
146
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_SSE41)
147
+ if (supports_sse41()) names.emplace_back("sse41");
148
+ #endif
149
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_SVE2)
150
+ if (supports_sve2()) names.emplace_back("sve2");
151
+ #endif
152
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_SVE)
153
+ if (supports_sve()) names.emplace_back("sve");
154
+ #endif
155
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_NEON)
156
+ if (supports_neon()) names.emplace_back("neon");
157
+ #endif
158
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_LASX)
159
+ if (supports_lasx()) names.emplace_back("lasx");
160
+ #endif
161
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_LSX)
162
+ if (supports_lsx()) names.emplace_back("lsx");
163
+ #endif
164
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_VSX)
165
+ if (supports_vsx()) names.emplace_back("vsx");
166
+ #endif
167
+ #if defined(STRIDE_ALIGN_RUBY_HAVE_RVV)
168
+ if (supports_rvv()) names.emplace_back("rvv");
169
+ #endif
170
+ names.emplace_back("generic");
171
+ return names;
172
+ }
@@ -0,0 +1,6 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <vector>
5
+
6
+ std::vector<std::string> stride_align_ruby_backend_candidates();
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+ require "rbconfig"
5
+ require "shellwords"
6
+
7
+ extension_root = File.expand_path(__dir__)
8
+ repository_root = File.expand_path("../../../../", extension_root)
9
+ vendored_include = File.join(extension_root, "vendor")
10
+ include_root = if File.directory?(File.join(vendored_include, "stride_align"))
11
+ vendored_include
12
+ else
13
+ File.join(repository_root, "include")
14
+ end
15
+
16
+ abort "stride-align C++ headers were not found" unless File.file?(
17
+ File.join(include_root, "stride_align", "core.hpp")
18
+ )
19
+
20
+ $INCFLAGS = "-I#{Shellwords.escape(include_root)} #{$INCFLAGS}"
21
+ $CXXFLAGS = "#{$CXXFLAGS} -std=c++20 -O3 -Wall -Wextra -Wpedantic -Wno-register"
22
+
23
+ host_cpu = RbConfig::CONFIG.fetch("host_cpu", "").downcase
24
+ host_os = RbConfig::CONFIG.fetch("host_os", "").downcase
25
+
26
+ def supports_flags?(flags)
27
+ try_compile("int main() { return 0; }", flags)
28
+ end
29
+
30
+ base_flags = ""
31
+ profiles = {}
32
+
33
+ case host_cpu
34
+ when /x86_64|amd64/
35
+ base_flags = "-march=x86-64 -mtune=generic -msse2 -mno-avx -mno-avx2 -mno-avx512f"
36
+ candidates = {
37
+ "sse41" => "-march=x86-64 -mtune=generic -msse4.1 -mno-avx -mno-avx2 -mno-avx512f",
38
+ # The generic flags are part of CXXFLAGS and explicitly disable AVX. GCC
39
+ # preserves those -mno-* choices across a later -march, so re-enable the
40
+ # profile features here instead of relying on -march alone.
41
+ "avx2" => "-march=x86-64-v3 -mtune=generic -mavx -mavx2",
42
+ "avx512bwvl" => "-march=x86-64-v4 -mtune=generic -mavx -mavx2 -mavx512f -mavx512bw -mavx512cd -mavx512vl -mavx512dq"
43
+ }
44
+ candidates.each { |name, flags| profiles[name] = flags if supports_flags?(flags) }
45
+ when /aarch64|arm64/
46
+ neon_flags = host_os.include?("darwin") ? "-mcpu=apple-m1" : "-march=armv8-a+simd -mtune=generic"
47
+ profiles["neon"] = neon_flags if supports_flags?(neon_flags)
48
+ if host_os.include?("linux")
49
+ sve_flags = "-march=armv8.2-a+sve -msve-vector-bits=128 -mtune=generic"
50
+ sve2_flags = "-march=armv9-a+sve2 -msve-vector-bits=128 -mtune=generic"
51
+ profiles["sve"] = sve_flags if supports_flags?(sve_flags)
52
+ profiles["sve2"] = sve2_flags if supports_flags?(sve2_flags)
53
+ end
54
+ when /loongarch64/
55
+ base_flags = "-march=loongarch64 -mtune=generic -mno-lsx -mno-lasx"
56
+ $LDFLAGS = "#{$LDFLAGS} -static-libstdc++ -static-libgcc" if host_os.include?("linux")
57
+ candidates = {
58
+ "lsx" => "-march=la464 -mtune=la464 -mlsx -mno-lasx",
59
+ "lasx" => "-march=la464 -mtune=la464 -mlsx -mlasx"
60
+ }
61
+ candidates.each { |name, flags| profiles[name] = flags if supports_flags?(flags) }
62
+ when /ppc64|powerpc64/
63
+ $LDFLAGS = "#{$LDFLAGS} -static-libstdc++ -static-libgcc" if host_os.include?("linux")
64
+ flags = "-mcpu=power8 -mtune=power8 -mvsx"
65
+ profiles["vsx"] = flags if supports_flags?(flags)
66
+ when /riscv64/
67
+ base_flags = "-march=rv64gc -mabi=lp64d"
68
+ flags = "-march=rv64gcv -mabi=lp64d"
69
+ profiles["rvv"] = flags if supports_flags?(flags)
70
+ end
71
+
72
+ have_defines = profiles.keys.map do |name|
73
+ "-DSTRIDE_ALIGN_RUBY_HAVE_#{name.upcase}=1"
74
+ end
75
+
76
+ $CPPFLAGS = "#{$CPPFLAGS} #{have_defines.join(' ')}"
77
+ $CXXFLAGS = "#{$CXXFLAGS} #{base_flags}" unless base_flags.empty?
78
+ $srcs = %w[backend_generic.cpp cpu_detect.cpp beider_morse_impl.cpp]
79
+ $objs = $srcs.map { |source| source.sub(/\.cpp\z/, ".o") }
80
+
81
+ create_makefile("stride_align/_generic")
82
+
83
+ dlext = RbConfig::CONFIG.fetch("DLEXT")
84
+ backend_targets = profiles.keys.map { |name| "_#{name}.#{dlext}" }
85
+
86
+ File.open("Makefile", "a") do |makefile|
87
+ makefile.puts
88
+ makefile.puts "STRIDE_ALIGN_RUBY_BACKENDS = #{profiles.keys.join(' ')}"
89
+ makefile.puts "STRIDE_ALIGN_RUBY_BACKEND_TARGETS = #{backend_targets.join(' ')}"
90
+ makefile.puts "CLEANOBJS += $(STRIDE_ALIGN_RUBY_BACKEND_TARGETS)"
91
+ makefile.puts "all: $(STRIDE_ALIGN_RUBY_BACKEND_TARGETS)"
92
+ makefile.puts
93
+
94
+ profiles.each do |name, flags|
95
+ object = "backend_#{name}.o"
96
+ target = "_#{name}.#{dlext}"
97
+ makefile.puts "#{object}: backend_#{name}.cpp backend_impl.hpp target_profile.hpp"
98
+ makefile.puts "\t$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) #{flags} -c $< -o $@"
99
+ makefile.puts
100
+ makefile.puts "#{target}: #{object}"
101
+ makefile.puts "\t$(LDSHAREDXX) $(DLDFLAGS) $(ARCH_FLAG) $(LDFLAGS) -o $@ $^ $(LOCAL_LIBS) $(LIBS)"
102
+ makefile.puts
103
+ end
104
+
105
+ makefile.puts "install-so: install-stride-align-backends"
106
+ makefile.puts "install-stride-align-backends: $(STRIDE_ALIGN_RUBY_BACKEND_TARGETS)"
107
+ makefile.puts "\t$(MAKEDIRS) $(DESTDIR)$(sitearchdir)/stride_align"
108
+ unless backend_targets.empty?
109
+ makefile.puts "\t$(INSTALL_PROG) $(STRIDE_ALIGN_RUBY_BACKEND_TARGETS) $(DESTDIR)$(sitearchdir)/stride_align"
110
+ end
111
+ makefile.puts ".PHONY: install-stride-align-backends"
112
+ end
113
+
114
+ puts "stride-align Ruby backends: #{profiles.empty? ? 'generic only' : profiles.keys.join(', ')}"
@@ -0,0 +1,82 @@
1
+ #pragma once
2
+
3
+ // Every Ruby native backend is a separate importable extension compiled for
4
+ // exactly one ISA. Keep the selected profile and compiler feature macros in
5
+ // lock-step so a mislabeled binary fails while the gem is being built rather
6
+ // than crashing on a user's machine.
7
+
8
+ #if (defined(STRIDE_ALIGN_RUBY_TARGET_GENERIC) + \
9
+ defined(STRIDE_ALIGN_RUBY_TARGET_SSE41) + \
10
+ defined(STRIDE_ALIGN_RUBY_TARGET_AVX2) + \
11
+ defined(STRIDE_ALIGN_RUBY_TARGET_AVX512BWVL) + \
12
+ defined(STRIDE_ALIGN_RUBY_TARGET_NEON) + \
13
+ defined(STRIDE_ALIGN_RUBY_TARGET_SVE) + \
14
+ defined(STRIDE_ALIGN_RUBY_TARGET_SVE2) + \
15
+ defined(STRIDE_ALIGN_RUBY_TARGET_LSX) + \
16
+ defined(STRIDE_ALIGN_RUBY_TARGET_LASX) + \
17
+ defined(STRIDE_ALIGN_RUBY_TARGET_VSX) + \
18
+ defined(STRIDE_ALIGN_RUBY_TARGET_RVV)) != 1
19
+ #error "Exactly one Ruby backend target must be selected"
20
+ #endif
21
+
22
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_GENERIC) && \
23
+ (defined(__x86_64__) || defined(__i386__)) && \
24
+ (defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__))
25
+ #error "The generic x86 Ruby backend unexpectedly enables AVX"
26
+ #endif
27
+
28
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_GENERIC) && defined(__loongarch__) && \
29
+ (defined(__loongarch_sx) || defined(__loongarch_asx))
30
+ #error "The generic LoongArch Ruby backend unexpectedly enables LSX or LASX"
31
+ #endif
32
+
33
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_SSE41) && \
34
+ (!defined(__SSE4_1__) || defined(__AVX__))
35
+ #error "The SSE4.1 Ruby backend must select SSE4.1 without AVX"
36
+ #endif
37
+
38
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_AVX2) && \
39
+ (!defined(__AVX2__) || !defined(__BMI__) || !defined(__BMI2__) || \
40
+ !defined(__F16C__) || !defined(__FMA__) || !defined(__LZCNT__) || \
41
+ !defined(__MOVBE__) || defined(__AVX512F__))
42
+ #error "The AVX2 Ruby backend must select the x86-64-v3 feature set"
43
+ #endif
44
+
45
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_AVX512BWVL) && \
46
+ (!defined(__AVX512F__) || !defined(__AVX512BW__) || \
47
+ !defined(__AVX512CD__) || !defined(__AVX512VL__) || \
48
+ !defined(__AVX512DQ__))
49
+ #error "The AVX-512 Ruby backend requires the x86-64-v4 feature set"
50
+ #endif
51
+
52
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_NEON) && \
53
+ !defined(__ARM_NEON) && !defined(__ARM_NEON__)
54
+ #error "The NEON Ruby backend did not select NEON"
55
+ #endif
56
+
57
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_SVE) && \
58
+ (!defined(__ARM_FEATURE_SVE) || defined(__ARM_FEATURE_SVE2))
59
+ #error "The SVE Ruby backend must select SVE without SVE2"
60
+ #endif
61
+
62
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_SVE2) && !defined(__ARM_FEATURE_SVE2)
63
+ #error "The SVE2 Ruby backend did not select SVE2"
64
+ #endif
65
+
66
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_LSX) && \
67
+ (!defined(__loongarch_sx) || defined(__loongarch_asx))
68
+ #error "The LSX Ruby backend must select LSX without LASX"
69
+ #endif
70
+
71
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_LASX) && \
72
+ (!defined(__loongarch_sx) || !defined(__loongarch_asx))
73
+ #error "The LASX Ruby backend did not select LASX"
74
+ #endif
75
+
76
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_VSX) && !defined(__VSX__)
77
+ #error "The VSX Ruby backend did not select VSX"
78
+ #endif
79
+
80
+ #if defined(STRIDE_ALIGN_RUBY_TARGET_RVV) && !defined(__riscv_vector)
81
+ #error "The RVV Ruby backend did not select the vector extension"
82
+ #endif