stride-align for Ruby

stride-align brings the complete public R binding surface to Ruby: Unicode string distances and similarities, local and global alignment, batch search, substitution matrices, keyboard-confusion matrices, phonetics, and Dynamic Time Warping. The implementation is backed by the same header-only C++20 core.

Install

Build and install the gem from the repository root:

bindings/ruby/build-package.sh
gem install dist/ruby/stride-align-0.6.0.gem

Building requires Ruby development headers and a C++20 compiler. The resulting gem contains its C++ headers, BMPM rules, BLOSUM/PAM catalog, and keyboard data; it does not depend on Python, R, NumPy, or a binding-framework gem at runtime.

Import dispatch

Requiring the gem first imports the portable _generic extension, asks it for the CPU-compatible backends packaged by the build, and then imports the best one. Each backend is a separate Ruby extension, matching Python's import-based dispatch model—unsupported instructions are never linked into the module that performs CPU detection.

Source gems can build generic plus SSE4.1, AVX2, AVX-512 BW/VL, NEON, SVE, SVE2, LSX, LASX, VSX, or RVV extensions when the host compiler supports them. Pin a backend before require when benchmarking:

STRIDE_ALIGN_RUBY_BACKEND=generic ruby benchmark.rb
STRIDE_ALIGN_RUBY_BACKEND=avx2 ruby benchmark.rb

An unavailable or CPU-incompatible override raises LoadError. Inspect the active dispatch with StrideAlign.stride_backend and StrideAlign.stride_available_backends.

Use

require "stride_align"

StrideAlign.levenshtein_score("kitten", "sitting")
# => 3

StrideAlign.jaro_winkler_similarities(
  "Martha", ["Martha", "Marhta", "Arthur", nil]
)

StrideAlign.cdist(
  ["Martha", "Arthur"],
  ["Martha", "Marhta", "Arthur"],
  scorer: StrideAlign::Scorer::JARO_WINKLER
)

path = StrideAlign.smith_waterman_path("ACCGT", "CCG")
path.cigar          # => "3="
path.aligned_query  # => "CCG"

StrideAlign.smith_waterman_scores(
  "HE", ["HE", "HH"], matrix: StrideAlign.blosum62
)
# => [13, 8]

Pair functions accept either scalar strings or arrays. Equal-length arrays are processed elementwise; a length-one side is broadcast. nil represents a missing string and produces a missing score. Batch selection returns arrays of hashes, cdist returns an array of rows, and source indices are zero-based.

The Ruby API covers every export in the R package:

  • Levenshtein, OSA/Damerau, true Damerau-Levenshtein, Indel, Hamming, Jaro, and Jaro-Winkler pair and batch forms
  • Smith-Waterman and Needleman-Wunsch scores, normalized scores, linear and affine gaps, traceback objects, CIGAR output, and prepared score facades
  • top-k, best, extract, dense cdist, threshold filtering, global top-k, and per-query top-k across all sixteen scorer IDs
  • LCS, n-gram similarities, Ratcliff-Obershelp, token/partial ratios, WRatio, and Monge-Elkan
  • custom and NCBI-text substitution matrices, the complete BLOSUM/PAM catalog, nucleotide/ASCII matrices, and keyboard-confusion helpers
  • Soundex, Metaphone, NYSIIS, Match Rating, Caverphone, Cologne, Daitch-Mokotoff, Double Metaphone, and Beider-Morse
  • scalar and one-to-many Dynamic Time Warping

Ruby classes and hashes replace R's S3 objects and data frames. The Python compatibility packages (rapidfuzz, parasail, jellyfish, and thefuzz) remain Python-only.

Test

The test suite includes a live audit against the R NAMESPACE, so a newly exported R API cannot silently be omitted from Ruby:

bindings/ruby/build-package.sh /tmp/stride-align-ruby-dist
GEM_HOME=/tmp/stride-align-ruby-gems \
  gem install --local --no-document \
  /tmp/stride-align-ruby-dist/stride-align-0.6.0.gem
GEM_HOME=/tmp/stride-align-ruby-gems \
  ruby bindings/ruby/test/test_stride_align.rb