Skip to main content

SIMD-accelerated string search, sort, hashes, fingerprints, & edit distances

Project description

StringZilla 🦖

StringZilla banner

The world wastes a minimum of $100M annually due to inefficient string operations. A typical codebase processes strings character by character, resulting in too many branches and data-dependencies, neglecting 90% of modern CPU's potential. LibC is different. It attempts to leverage SIMD instructions to boost some operations, and is often used by higher-level languages, runtimes, and databases. But it isn't perfect. 1️⃣ First, even on common hardware, including over a billion 64-bit ARM CPUs, common functions like strstr and memmem only achieve 1/3 of the CPU's throughput. 2️⃣ Second, SIMD coverage is inconsistent: acceleration in forward scans does not guarantee speed in the reverse-order search. 3️⃣ At last, most high-level languages can't always use LibC, as the strings are often not NULL-terminated or may contain the Unicode "Zero" character in the middle of the string. That's why StringZilla was created. To provide predictably high performance, portable to any modern platform, operating system, and programming language.

StringZilla Python installs StringZilla Rust installs GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status StringZilla code size

StringZilla is the GodZilla of string libraries, using SIMD and SWAR to accelerate string operations on modern CPUs. It is up to 10x faster than the default and even other SIMD-accelerated string libraries in C, C++, Python, and other languages, while covering broad functionality. It accelerates exact and fuzzy string matching, edit distance computations, sorting, lazily-evaluated ranges to avoid memory allocations, and even random-string generators.

  • 🐂 C : Upgrade LibC's <string.h> to <stringzilla.h> in C 99
  • 🐉 C++: Upgrade STL's <string> to <stringzilla.hpp> in C++ 11
  • 🐍 Python: Upgrade your str to faster Str
  • 🍎 Swift: Use the String+StringZilla extension
  • 🦀 Rust: Use the StringZilla traits crate
  • 🐚 Shell: Accelerate common CLI tools with sz_ prefix
  • 📚 Researcher? Jump to Algorithms & Design Decisions
  • 💡 Thinking to contribute? Look for "good first issues"
  • 🤝 And check the guide to setup the environment
  • Want more bindings or features? Let me know!

Who is this for?

  • For data-engineers parsing large datasets, like the CommonCrawl, RedPajama, or LAION.
  • For software engineers optimizing strings in their apps and services.
  • For bioinformaticians and search engineers looking for edit-distances for USearch.
  • For DBMS devs, optimizing LIKE, ORDER BY, and GROUP BY operations.
  • For hardware designers, needing a SWAR baseline for strings-processing functionality.
  • For students studying SIMD/SWAR applications to non-data-parallel operations.

Performance

C C++ Python StringZilla
find the first occurrence of a random word from text, ≅ 5 bytes long
strstr 1
x86: 7.4 · arm: 2.0 GB/s
.find
x86: 2.9 · arm: 1.6 GB/s
.find
x86: 1.1 · arm: 0.6 GB/s
sz_find
x86: 10.6 · arm: 7.1 GB/s
find the last occurrence of a random word from text, ≅ 5 bytes long
.rfind
x86: 0.5 · arm: 0.4 GB/s
.rfind
x86: 0.9 · arm: 0.5 GB/s
sz_rfind
x86: 10.8 · arm: 6.7 GB/s
split lines separated by \n or \r 2
strcspn 1
x86: 5.42 · arm: 2.19 GB/s
.find_first_of
x86: 0.59 · arm: 0.46 GB/s
re.finditer
x86: 0.06 · arm: 0.02 GB/s
sz_find_charset
x86: 4.08 · arm: 3.22 GB/s
find the last occurrence of any of 6 whitespaces 2
.find_last_of
x86: 0.25 · arm: 0.25 GB/s
sz_rfind_charset
x86: 0.43 · arm: 0.23 GB/s
Random string from a given alphabet, 20 bytes long 5
rand() % n
x86: 18.0 · arm: 9.4 MB/s
uniform_int_distribution
x86: 47.2 · arm: 20.4 MB/s
join(random.choices(...))
x86: 13.3 · arm: 5.9 MB/s
sz_generate
x86: 56.2 · arm: 25.8 MB/s
Get sorted order, ≅ 8 million English words 6
qsort_r
x86: 3.55 · arm: 5.77 s
std::sort
x86: 2.79 · arm: 4.02 s
numpy.argsort
x86: 7.58 · arm: 13.00 s
sz_sort
x86: 1.91 · arm: 2.37 s
Levenshtein edit distance, ≅ 5 bytes long
via jellyfish 3
x86: 1,550 · arm: 2,220 ns
sz_edit_distance
x86: 99 · arm: 180 ns
Needleman-Wunsch alignment scores, ≅ 10 K aminoacids long
via biopython 4
x86: 257 · arm: 367 ms
sz_alignment_score
x86: 73 · arm: 177 ms

StringZilla has a lot of functionality, most of which is covered by benchmarks across C, C++, Python and other languages. You can find those in the ./scripts directory, with usage notes listed in the CONTRIBUTING.md file. Notably, if the CPU supports misaligned loads, even the 64-bit SWAR backends are faster than either standard library.

Most benchmarks were conducted on a 1 GB English text corpus, with an average word length of 6 characters. The code was compiled with GCC 12, using glibc v2.35. The benchmarks performed on Arm-based Graviton3 AWS c7g instances and r7iz Intel Sapphire Rapids. Most modern Arm-based 64-bit CPUs will have similar relative speedups. Variance withing x86 CPUs will be larger. 1 Unlike other libraries, LibC requires strings to be NULL-terminated. 2 Six whitespaces in the ASCII set are: \t\n\v\f\r. Python's and other standard libraries have specialized functions for those. 3 Most Python libraries for strings are also implemented in C. 4 Unlike the rest of BioPython, the alignment score computation is implemented in C. 5 All modulo operations were conducted with uint8_t to allow compilers more optimization opportunities. The C++ STL and StringZilla benchmarks used a 64-bit Mersenne Twister as the generator. For C, C++, and StringZilla, an in-place update of the string was used. In Python every string had to be allocated as a new object, which makes it less fair. 6 Contrary to the popular opinion, Python's default sorted function works faster than the C and C++ standard libraries. That holds for large lists or tuples of strings, but fails as soon as you need more complex logic, like sorting dictionaries by a string key, or producing the "sorted order" permutation. The latter is very common in database engines and is most similar to numpy.argsort. Current StringZilla solution can be at least 4x faster without loss of generality.

Functionality

StringZilla is compatible with most modern CPUs, and provides a broad range of functionality.

  • works on both Little-Endian and Big-Endian architectures.
  • works on 32-bit and 64-bit hardware architectures.
  • compatible with ASCII and UTF-8 encoding.

Not all features are available across all bindings. Consider contributing, if you need a feature that's not yet implemented.

Maturity C 99 C++ 11 Python Swift Rust
Substring Search 🌳
Character Set Search 🌳
Edit Distances 🧐
Small String Class 🧐
Sorting & Sequence Operations 🚧
Lazy Ranges, Compressed Arrays 🧐
Hashes & Fingerprints 🚧

🌳 parts are used in production. 🧐 parts are in beta. 🚧 parts are under active development, and are likely to break in subsequent releases. ✅ are implemented. ⚪ are considered. ❌ are not intended.

Quick Start: Python 🐍

Python bindings are available on PyPI, and can be installed with pip. You can immediately check the installed version and the used hardware capabilities with following commands:

pip install stringzilla
python -c "import stringzilla; print(stringzilla.__version__)"
python -c "import stringzilla; print(stringzilla.__capabilities__)"

Basic Usage

If you've ever used the Python str, bytes, bytearray, memoryview class, you'll know what to expect. StringZilla's Str class is a hybrid of those two, providing str-like interface to byte-arrays.

from stringzilla import Str, File

text_from_str = Str('some-string') # no copies, just a view
text_from_file = Str(File('some-file.txt')) # memory-mapped file

The File class memory-maps a file from persistent memory without loading its copy into RAM. The contents of that file would remain immutable, and the mapping can be shared by multiple Python processes simultaneously. A standard dataset pre-processing use case would be to map a sizeable textual dataset like Common Crawl into memory, spawn child processes, and split the job between them.

Basic Operations

  • Length: len(text) -> int
  • Indexing: text[42] -> str
  • Slicing: text[42:46] -> Str
  • Substring check: 'substring' in text -> bool
  • Hashing: hash(text) -> int
  • String conversion: str(text) -> str

Advanced Operations

import sys

x: bool = text.contains('substring', start=0, end=sys.maxsize)
x: int = text.find('substring', start=0, end=sys.maxsize)
x: int = text.count('substring', start=0, end=sys.maxsize, allowoverlap=False)
x: str = text.decode(encoding='utf-8', errors='strict')
x: Strs = text.split(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.splitlines(keeplinebreaks=False, maxsplit=sys.maxsize)

It's important to note, that the last function behavior is slightly different from Python's str.splitlines. The native version matches \n, \r, \v or \x0b, \f or \x0c, \x1c, \x1d, \x1e, \x85, \r\n, \u2028, \u2029, including 3x two-bytes-long runes. The StringZilla version matches only \n, \v, \f, \r, \x1c, \x1d, \x1e, \x85, avoiding two-byte-long runes.

Character Set Operations

Python strings don't natively support character set operations. This forces people to use regular expressions, which are slow and hard to read. To avoid the need for re.finditer, StringZilla provides the following interfaces:

x: int = text.find_first_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_of('chars', start=0, end=sys.maxsize)
x: int = text.find_first_not_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_not_of('chars', start=0, end=sys.maxsize)
x: Strs = text.split_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)

Collection-Level Operations

Once split into a Strs object, you can sort, shuffle, and reorganize the slices, with minimum memory footprint. If all the chunks are located in consecutive memory regions, the memory overhead can be as low as 4 bytes per chunk.

lines: Strs = text.split(separator='\n') # 4 bytes per line overhead for under 4 GB of text
batch: Strs = lines.sample(seed=42) # 10x faster than `random.choices`
lines.shuffle(seed=42) # or shuffle all lines in place and shard with slices
# WIP: lines.sort() # explodes to 16 bytes per line overhead for any length text
# WIP: sorted_order: tuple = lines.argsort() # similar to `numpy.argsort`

Working on RedPajama, addressing 20 Billion annotated english documents, one will need only 160 GB of RAM instead of Terabytes. Once loaded, the data will be memory-mapped, and can be reused between multiple Python processes without copies. And of course, you can use slices to navigate the dataset and shard it between multiple workers.

lines[::3] # every third line
lines[1::1] # every odd line
lines[:-100:-1] # last 100 lines in reverse order

Iterators and Memory Efficiency

Python's operations like split() and readlines() immediately materialize a list of copied parts. This can be very memory-inefficient for large datasets. StringZilla saves a lot of memory by viewing existing memory regions as substrings, but even more memory can be saved by using lazily evaluated iterators.

x: SplitIterator[Str] = text.split_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.split_charset_iter(separator='chars', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_charset_iter(separator='chars', keepseparator=False)

StringZilla can easily be 10x more memory efficient than native Python classes for tokenization. With lazy operations, it practically becomes free.

import stringzilla as sz
%load_ext memory_profiler

text = open("enwik9.txt", "r").read() # 1 GB, mean word length 7.73 bytes
%memit text.split() # increment: 8670.12 MiB (152 ms)
%memit sz.split(text) # increment: 530.75 MiB (25 ms)
%memit sum(1 for _ in sz.split_iter(text)) # increment: 0.00 MiB

Low-Level Python API

Aside from calling the methods on the Str and Strs classes, you can also call the global functions directly on str and bytes instances. Assuming StringZilla CPython bindings are implemented without any intermediate tools like SWIG or PyBind, the call latency should be similar to native classes.

import stringzilla as sz

contains: bool = sz.contains("haystack", "needle", start=0, end=sys.maxsize)
offset: int = sz.find("haystack", "needle", start=0, end=sys.maxsize)
count: int = sz.count("haystack", "needle", start=0, end=sys.maxsize, allowoverlap=False)

Edit Distances

assert sz.edit_distance("apple", "aple") == 1 # skip one ASCII character
assert sz.edit_distance("αβγδ", "αγδ") == 2 # skip two bytes forming one rune
assert sz.edit_distance_unicode("αβγδ", "αγδ") == 1 # one unicode rune

Several Python libraries provide edit distance computation. Most of them are implemented in C, but are not always as fast as StringZilla. Taking a 1'000 long proteins around 10'000 characters long, computing just a 100 distances:

Moreover, you can pass custom substitution matrices to compute the Needleman-Wunsch alignment scores. That task is very common in bioinformatics and computational biology. It's natively supported in BioPython, and its BLOSUM matrices can be converted to StringZilla's format. Alternatively, you can construct an arbitrary 256 by 256 cost matrix using NumPy. Depending on arguments, the result may be equal to the negative Levenshtein distance.

import numpy as np
import stringzilla as sz

costs = np.zeros((256, 256), dtype=np.int8)
costs.fill(-1)
np.fill_diagonal(costs, 0)

assert sz.alignment_score("first", "second", substitution_matrix=costs, gap_score=-1) == -sz.edit_distance(a, b)

Using the same proteins as for Levenshtein distance benchmarks:

§ Example converting from BioPython to StringZilla.
import numpy as np
from Bio import Align
from Bio.Align import substitution_matrices

aligner = Align.PairwiseAligner()
aligner.substitution_matrix = substitution_matrices.load("BLOSUM62")
aligner.open_gap_score = 1
aligner.extend_gap_score = 1

# Convert the matrix to NumPy
subs_packed = np.array(aligner.substitution_matrix).astype(np.int8)
subs_reconstructed = np.zeros((256, 256), dtype=np.int8)

# Initialize all banned characters to a the largest possible penalty
subs_reconstructed.fill(127)
for packed_row, packed_row_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
    for packed_column, packed_column_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
        reconstructed_row = ord(packed_row_aminoacid)
        reconstructed_column = ord(packed_column_aminoacid)
        subs_reconstructed[reconstructed_row, reconstructed_column] = subs_packed[packed_row, packed_column]

# Let's pick two examples for of tri-peptides (made of 3 aminoacids)
glutathione = "ECG" # Need to rebuild human tissue?
thyrotropin_releasing_hormone = "QHP" # Or to regulate your metabolism?

assert sz.alignment_score(
    glutathione,
    thyrotropin_releasing_hormone, 
    substitution_matrix=subs_reconstructed, 
    gap_score=1) == aligner.score(glutathione, thyrotropin_releasing_hormone) # Equal to 6

Serialization

Filesystem

Similar to how File can be used to read a large file, other interfaces can be used to dump strings to disk faster. The Str class has write_to to write the string to a file, and offset_within to obtain integer offsets of substring view in larger string for navigation.

web_archive = Str("<html>...</html><html>...</html>")
_, end_tag, next_doc = web_archive.partition("</html>") # or use `find`
next_doc_offset = next_doc.offset_within(web_archive)
web_archive.write_to("next_doc.html") # no GIL, no copies, just a view

PyArrow

A Str is easy to cast to PyArrow buffers.

from pyarrow import foreign_buffer
from stringzilla import Str

original = "hello"
view = Str(native)
arrow = foreign_buffer(view.address, view.nbytes, view)

That means you can convert Str to pyarrow.Buffer and Strs to pyarrow.Array without extra copies.

Quick Start: C/C++ 🛠️

The C library is header-only, so you can just copy the stringzilla.h header into your project. Same applies to C++, where you would copy the stringzilla.hpp header. Alternatively, add it as a submodule, and include it in your build system.

git submodule add https://github.com/ashvardanian/stringzilla.git

Or using a pure CMake approach:

FetchContent_Declare(stringzilla GIT_REPOSITORY https://github.com/ashvardanian/stringzilla.git)
FetchContent_MakeAvailable(stringzilla)

Last, but not the least, you can also install it as a library, and link against it. This approach is worse for inlining, but brings dynamic runtime dispatch for the most advanced CPU features.

Basic Usage with C 99 and Newer

There is a stable C 99 interface, where all function names are prefixed with sz_. Most interfaces are well documented, and come with self-explanatory names and examples. In some cases, hardware specific overloads are available, like sz_find_avx512 or sz_find_neon. Both are companions of the sz_find, first for x86 CPUs with AVX-512 support, and second for Arm NEON-capable CPUs.

#include <stringzilla/stringzilla.h>

// Initialize your haystack and needle
sz_string_view_t haystack = {your_text, your_text_length};
sz_string_view_t needle = {your_subtext, your_subtext_length};

// Perform string-level operations
sz_size_t substring_position = sz_find(haystack.start, haystack.length, needle.start, needle.length);
sz_size_t substring_position = sz_find_avx512(haystack.start, haystack.length, needle.start, needle.length);
sz_size_t substring_position = sz_find_neon(haystack.start, haystack.length, needle.start, needle.length);

// Hash strings
sz_u64_t hash = sz_hash(haystack.start, haystack.length);

// Perform collection level operations
sz_sequence_t array = {your_order, your_count, your_get_start, your_get_length, your_handle};
sz_sort(&array, &your_config);
§ Mapping from LibC to StringZilla.

By design, StringZilla has a couple of notable differences from LibC:

  1. all strings are expected to have a length, and are not necessarily null-terminated.
  2. every operations has a reverse order counterpart.

That way sz_find and sz_rfind are similar to strstr and strrstr in LibC. Similarly, sz_find_byte and sz_rfind_byte replace memchr and memrchr. The sz_find_charset maps to strspn and strcspn, while sz_rfind_charset has no sibling in LibC.

LibC Functionality StringZilla Equivalents
memchr(haystack, needle, haystack_length), strchr sz_find_byte(haystack, haystack_length, needle)
memrchr(haystack, needle, haystack_length) sz_rfind_byte(haystack, haystack_length, needle)
memcmp, strcmp sz_order, sz_equal
strlen(haystack) sz_find_byte(haystack, haystack_length, needle)
strcspn(haystack, needles) sz_rfind_charset(haystack, haystack_length, needles_bitset)
strspn(haystack, needles) sz_find_charset(haystack, haystack_length, needles_bitset)
memmem(haystack, haystack_length, needle, needle_length), strstr sz_find(haystack, haystack_length, needle, needle_length)
memcpy(destination, source, destination_length) sz_copy(destination, source, destination_length)
memmove(destination, source, destination_length) sz_move(destination, source, destination_length)
memset(destination, value, destination_length) sz_fill(destination, destination_length, value)

Basic Usage with C++ 11 and Newer

There is a stable C++ 11 interface available in the ashvardanian::stringzilla namespace. It comes with two STL-like classes: string_view and string. The first is a non-owning view of a string, and the second is a mutable string with a Small String Optimization.

#include <stringzilla/stringzilla.hpp>

namespace sz = ashvardanian::stringzilla;

sz::string haystack = "some string";
sz::string_view needle = sz::string_view(haystack).substr(0, 4);

auto substring_position = haystack.find(needle); // Or `rfind`
auto hash = std::hash<sz::string_view>(haystack); // Compatible with STL's `std::hash`

haystack.end() - haystack.begin() == haystack.size(); // Or `rbegin`, `rend`
haystack.find_first_of(" \w\t") == 4; // Or `find_last_of`, `find_first_not_of`, `find_last_not_of`
haystack.starts_with(needle) == true; // Or `ends_with`
haystack.remove_prefix(needle.size()); // Why is this operation in-place?!
haystack.contains(needle) == true; // STL has this only from C++ 23 onwards
haystack.compare(needle) == 1; // Or `haystack <=> needle` in C++ 20 and beyond

StringZilla also provides string literals for automatic type resolution, similar to STL:

using sz::literals::operator""_sz;
using std::literals::operator""sv;

auto a = "some string"; // char const *
auto b = "some string"sv; // std::string_view
auto b = "some string"_sz; // sz::string_view

Memory Ownership and Small String Optimization

Most operations in StringZilla don't assume any memory ownership. But in addition to the read-only search-like operations StringZilla provides a minimalistic C and C++ implementations for a memory owning string "class". Like other efficient string implementations, it uses the Small String Optimization (SSO) to avoid heap allocations for short strings.

typedef union sz_string_t {
    struct internal {
        sz_ptr_t start;
        sz_u8_t length;
        char chars[SZ_STRING_INTERNAL_SPACE]; /// Ends with a null-terminator.
    } internal;

    struct external {
        sz_ptr_t start;
        sz_size_t length;        
        sz_size_t space; /// The length of the heap-allocated buffer.
        sz_size_t padding;
    } external;

} sz_string_t;

As one can see, a short string can be kept on the stack, if it fits within internal.chars array. Before 2015 GCC string implementation was just 8 bytes, and could only fit 7 characters. Different STL implementations today have different thresholds for the Small String Optimization. Similar to GCC, StringZilla is 32 bytes in size, and similar to Clang it can fit 22 characters on stack. Our layout might be preferential, if you want to avoid branches. If you use a different compiler, you may want to check it's SSO buffer size with a simple Gist.

libstdc++ in GCC 13 libc++ in Clang 17 StringZilla
sizeof(std::string) 32 24 32
Small String Capacity 15 22 22

This design has been since ported to many high-level programming languages. Swift, for example, can store 15 bytes in the String instance itself. StringZilla implements SSO at the C level, providing the sz_string_t union and a simple API for primary operations.

sz_memory_allocator_t allocator;
sz_string_t string;

// Init and make sure we are on stack
sz_string_init(&string);
sz_string_is_on_stack(&string); // == sz_true_k

// Optionally pre-allocate space on the heap for future insertions.
sz_string_grow(&string, 100, &allocator); // == sz_true_k

// Append, erase, insert into the string.
sz_string_expand(&string, 0, "_Hello_", 7, &allocator); // == sz_true_k
sz_string_expand(&string, SZ_SIZE_MAX, "world", 5, &allocator); // == sz_true_k
sz_string_erase(&string, 0, 1);

// Unpacking & introspection.
sz_ptr_t string_start;
sz_size_t string_length;
sz_size_t string_space;
sz_bool_t string_is_external;
sz_string_unpack(string, &string_start, &string_length, &string_space, &string_is_external);
sz_equal(string_start, "Hello_world", 11); // == sz_true_k

// Reclaim some memory.
sz_string_shrink_to_fit(&string, &allocator); // == sz_true_k
sz_string_free(&string, &allocator);

Unlike the conventional C strings, the sz_string_t is allowed to contain null characters. To safely print those, pass the string_length to printf as well.

printf("%.*s\n", (int)string_length, string_start);

What's Wrong with the C++ Standard Library?

C++ Code Evaluation Result Invoked Signature
"Loose"s.replace(2, 2, "vath"s, 1) "Loathe" 🤢 (pos1, count1, str2, pos2)
"Loose"s.replace(2, 2, "vath", 1) "Love" 🥰 (pos1, count1, str2, count2)

StringZilla is designed to be a drop-in replacement for the C++ Standard Templates Library. That said, some of the design decisions of STL strings are highly controversial, error-prone, and expensive. Most notably:

  1. Argument order for replace, insert, erase and similar functions is impossible to guess.
  2. Bounds-checking exceptions for substr-like functions are only thrown for one side of the range.
  3. Returning string copies in substr-like functions results in absurd volume of allocations.
  4. Incremental construction via push_back-like functions goes through too many branches.
  5. Inconsistency between string and string_view methods, like the lack of remove_prefix and remove_suffix.

Check the following set of asserts validating the std::string specification. It's not realistic to expect the average developer to remember the 14 overloads of std::string::replace.

using str = std::string;

assert(str("hello world").substr(6) == "world");
assert(str("hello world").substr(6, 100) == "world"); // 106 is beyond the length of the string, but its OK
assert_throws(str("hello world").substr(100), std::out_of_range);   // 100 is beyond the length of the string
assert_throws(str("hello world").substr(20, 5), std::out_of_range); // 20 is beyond the length of the string
assert_throws(str("hello world").substr(-1, 5), std::out_of_range); // -1 casts to unsigned without any warnings...
assert(str("hello world").substr(0, -1) == "hello world");          // -1 casts to unsigned without any warnings...

assert(str("hello").replace(1, 2, "123") == "h123lo");
assert(str("hello").replace(1, 2, str("123"), 1) == "h23lo");
assert(str("hello").replace(1, 2, "123", 1) == "h1lo");
assert(str("hello").replace(1, 2, "123", 1, 1) == "h2lo");
assert(str("hello").replace(1, 2, str("123"), 1, 1) == "h2lo");
assert(str("hello").replace(1, 2, 3, 'a') == "haaalo");
assert(str("hello").replace(1, 2, {'a', 'b'}) == "hablo");

To avoid those issues, StringZilla provides an alternative consistent interface. It supports signed arguments, and doesn't have more than 3 arguments per function or The standard API and our alternative can be conditionally disabled with SZ_SAFETY_OVER_COMPATIBILITY=1. When it's enabled, the subjectively risky overloads from the Standard will be disabled.

using str = sz::string;

str("a:b").front(1) == "a"; // no checks, unlike `substr`
str("a:b").back(-1) == "b"; // accepting negative indices
str("a:b").sub(1, -1) == ":"; // similar to Python's `"a:b"[1:-1]`
str("a:b").sub(-2, -1) == ":"; // similar to Python's `"a:b"[-2:-1]`
str("a:b").sub(-2, 1) == ""; // similar to Python's `"a:b"[-2:1]`
"a:b"_sz[{-2, -1}] == ":"; // works on views and overloads `operator[]`

Assuming StringZilla is a header-only library you can use the full API in some translation units and gradually transition to safer restricted API in others. Bonus - all the bound checking is branchless, so it has a constant cost and won't hurt your branch predictor.

Beyond the C++ Standard Library - Learning from Python

Python is arguably the most popular programming language for data science. In part, that's due to the simplicity of its standard interfaces. StringZilla brings some of that functionality to C++.

  • Content checks: isalnum, isalpha, isascii, isdigit, islower, isspace, isupper.
  • Trimming character sets: lstrip, rstrip, strip.
  • Trimming string matches: remove_prefix, remove_suffix.
  • Ranges of search results: splitlines, split, rsplit.
  • Number of non-overlapping substring matches: count.
  • Partitioning: partition, rpartition.

For example, when parsing documents, it is often useful to split it into substrings. Most often, after that, you would compute the length of the skipped part, the offset and the length of the remaining part. This results in a lot of pointer arithmetic and is error-prone. StringZilla provides a convenient partition function, which returns a tuple of three string views, making the code cleaner.

auto parts = haystack.partition(':'); // Matching a character
auto [before, match, after] = haystack.partition(':'); // Structure unpacking
auto [before, match, after] = haystack.partition(char_set(":;")); // Character-set argument
auto [before, match, after] = haystack.partition(" : "); // String argument
auto [before, match, after] = haystack.rpartition(sz::whitespaces); // Split around the last whitespace

Combining those with the split function, one can easily parse a CSV file or HTTP headers.

for (auto line : haystack.split("\r\n")) {
    auto [key, _, value] = line.partition(':');
    headers[key.strip()] = value.strip();
}

Some other extensions are not present in the Python standard library either. Let's go through the C++ functionality category by category.

Some of the StringZilla interfaces are not available even Python's native str class. Here is a sneak peek of the most useful ones.

text.hash(); // -> 64 bit unsigned integer 
text.ssize(); // -> 64 bit signed length to avoid `static_cast<std::ssize_t>(text.size())`
text.contains_only(" \w\t"); // == text.find_first_not_of(char_set(" \w\t")) == npos;
text.contains(sz::whitespaces); // == text.find(char_set(sz::whitespaces)) != npos;

// Simpler slicing than `substr`
text.front(10); // -> sz::string_view
text.back(10); // -> sz::string_view

// Safe variants, which clamp the range into the string bounds
using sz::string::cap;
text.front(10, cap) == text.front(std::min(10, text.size()));
text.back(10, cap) == text.back(std::min(10, text.size()));

// Character set filtering
text.lstrip(sz::whitespaces).rstrip(sz::newlines); // like Python
text.front(sz::whitespaces); // all leading whitespaces
text.back(sz::digits); // all numerical symbols forming the suffix

// Incremental construction
using sz::string::unchecked;
text.push_back('x'); // no surprises here
text.push_back('x', unchecked); // no bounds checking, Rust style
text.try_push_back('x'); // returns `false` if the string is full and the allocation failed

sz::concatenate(text, "@", domain, ".", tld); // No allocations

Splits and Ranges

One of the most common use cases is to split a string into a collection of substrings. Which would often result in StackOverflow lookups and snippets like the one below.

std::vector<std::string> lines = split(haystack, "\r\n"); // string delimiter
std::vector<std::string> words = split(lines, ' '); // character delimiter

Those allocate memory for each string and the temporary vectors. Each allocation can be orders of magnitude more expensive, than even serial for-loop over characters. To avoid those, StringZilla provides lazily-evaluated ranges, compatible with the Range-v3 library.

for (auto line : haystack.split("\r\n"))
    for (auto word : line.split(char_set(" \w\t.,;:!?")))
        std::cout << word << std::endl;

Each of those is available in reverse order as well. It also allows interleaving matches, if you want both inclusions of xx in xxx. Debugging pointer offsets is not a pleasant exercise, so keep the following functions in mind.

  • haystack.[r]find_all(needle, interleaving)
  • haystack.[r]find_all(char_set(""))
  • haystack.[r]split(needle)
  • haystack.[r]split(char_set(""))

For $N$ matches the split functions will report $N+1$ matches, potentially including empty strings. Ranges have a few convenience methods as well:

range.size(); // -> std::size_t
range.empty(); // -> bool
range.template to<std::set<std::sting>>(); 
range.template to<std::vector<std::sting_view>>(); 

Concatenating Strings without Allocations

Another common string operation is concatenation. The STL provides std::string::operator+ and std::string::append, but those are not very efficient, if multiple invocations are performed.

std::string name, domain, tld;
auto email = name + "@" + domain + "." + tld; // 4 allocations

The efficient approach would be to pre-allocate the memory and copy the strings into it.

std::string email;
email.reserve(name.size() + domain.size() + tld.size() + 2);
email.append(name), email.append("@"), email.append(domain), email.append("."), email.append(tld);

That's mouthful and error-prone. StringZilla provides a more convenient concatenate function, which takes a variadic number of arguments. It also overrides the operator| to concatenate strings lazily, without any allocations.

auto email = sz::concatenate(name, "@", domain, ".", tld);   // 0 allocations
auto email = name | "@" | domain | "." | tld;                // 0 allocations
sz::string email = name | "@" | domain | "." | tld;          // 1 allocations

Random Generation

Software developers often need to generate random strings for testing purposes. The STL provides std::generate and std::random_device, that can be used with StringZilla.

sz::string random_string(std::size_t length, char const *alphabet, std::size_t cardinality) {
    sz::string result(length, '\0');
    static std::random_device seed_source; // Expensive to construct - due to system calls
    static std::mt19937 generator(seed_source()); // Also expensive - due to the state size
    std::uniform_int_distribution<std::size_t> distribution(0, cardinality);
    std::generate(result.begin(), result.end(), [&]() { return alphabet[distribution(generator)]; });
    return result;
}

Mouthful and slow. StringZilla provides a C native method - sz_generate and a convenient C++ wrapper - sz::generate. Similar to Python it also defines the commonly used character sets.

auto protein = sz::string::random(300, "ARNDCQEGHILKMFPSTWYV"); // static method
auto dna = sz::basic_string<custom_allocator>::random(3_000_000_000, "ACGT");

dna.randomize("ACGT"); // `noexcept` pre-allocated version
dna.randomize(&std::rand, "ACGT"); // pass any generator, like `std::mt19937`

char uuid[36];
sz::randomize(sz::string_span(uuid, 36), "0123456789abcdef-"); // Overwrite any buffer

Levenshtein Edit Distance and Alignment Scores

Levenshtein and Hamming edit distance are provided for both byte-strings and UTF-8 strings. The latter will output the distance in Unicode code points, not bytes. Needleman-Wunsch alignment scores are only defined for byte-strings.

// Count number of substitutions in same length strings
sz::hamming_distance(first, second[, upper_bound]) -> std::size_t;
sz::hamming_distance_utf8(first, second[, upper_bound]) -> std::size_t;

// Count number of insertions, deletions and substitutions
sz::edit_distance(first, second[, upper_bound[, allocator]]) -> std::size_t;
sz::edit_distance_utf8(first, second[, upper_bound[, allocator]]) -> std::size_t;

// Substitution-parametrized Needleman-Wunsch global alignment score
std::int8_t costs[256][256]; // Substitution costs matrix
sz::alignment_score(first, second, costs[, gap_score[, allocator]) -> std::ptrdiff_t;

Sorting in C and C++

LibC provides qsort and STL provides std::sort. Both have their quarks. The LibC standard has no way to pass a context to the comparison function, that's only possible with platform-specific extensions. Those have different arguments order on every OS.

// Linux: https://linux.die.net/man/3/qsort_r
void qsort_r(void *elements, size_t count, size_t element_width, 
    int (*compare)(void const *left, void const *right, void *context),
    void *context);
// MacOS and FreeBSD: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/qsort_r.3.html
void qsort_r(void *elements, size_t count, size_t element_width, 
    void *context,
    int (*compare)(void *context, void const *left, void const *right));
// Windows conflicts with ISO `qsort_s`: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170
void qsort_s(id *elements, size_t count, size_t element_width, 
    int (*compare)(void *context, void const *left, void const *right),
    void *context);

C++ generic algorithm is not perfect either. There is no guarantee in the standard that std::sort won't allocate any memory. If you are running on embedded, in real-time or on 100+ CPU cores per node, you may want to avoid that. StringZilla doesn't solve the general case, but hopes to improve the performance for strings. Use sz_sort, or the high-level sz::sorted_order, which can be used sort any collection of elements convertible to sz::string_view.

std::vector<std::string> data({"c", "b", "a"});
std::vector<std::size_t> order = sz::sorted_order(data); //< Simple shortcut

// Or, taking care of memory allocation:
sz::sorted_order(data.begin(), data.end(), order.data(), [](auto const &x) -> sz::string_view { return x; });

Standard C++ Containers with String Keys

The C++ Standard Templates Library provides several associative containers, often used with string keys.

std::map<std::string, int, std::less<std::string>> sorted_words;
std::unordered_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>> words;

The performance of those containers is often limited by the performance of the string keys, especially on reads. StringZilla can be used to accelerate containers with std::string keys, by overriding the default comparator and hash functions.

std::map<std::string, int, sz::string_view_less> sorted_words;
std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to> words;

Alternatively, a better approach would be to use the sz::string class as a key. The right hash function and comparator would be automatically selected and the performance gains would be more noticeable if the keys are short.

std::map<sz::string, int> sorted_words;
std::unordered_map<sz::string, int> words;

Compilation Settings and Debugging

SZ_DEBUG:

For maximal performance, the C library does not perform any bounds checking in Release builds. In C++, bounds checking happens only in places where the STL std::string would do it. If you want to enable more aggressive bounds-checking, define SZ_DEBUG before including the header. If not explicitly set, it will be inferred from the build type.

SZ_USE_X86_AVX512, SZ_USE_X86_AVX2, SZ_USE_ARM_NEON:

One can explicitly disable certain families of SIMD instructions for compatibility purposes. Default values are inferred at compile time.

SZ_DYNAMIC_DISPATCH:

By default, StringZilla is a header-only library. But if you are running on different generations of devices, it makes sense to pre-compile the library for all supported generations at once, and dispatch at runtime. This flag does just that and is used to produce the stringzilla.so shared library, as well as the Python bindings.

SZ_USE_MISALIGNED_LOADS:

By default, StringZilla avoids misaligned loads. If supported, it replaces many byte-level operations with word-level ones. Going from char-like types to uint64_t-like ones can significantly accelerate the serial (SWAR) backend. So consider enabling it if you are building for some embedded device.

SZ_AVOID_LIBC and SZ_OVERRIDE_LIBC:

When using the C header-only library one can disable the use of LibC. This may affect the type resolution system on obscure hardware platforms. Moreover, one may let stringzilla override the common symbols like the memcpy and memset with its own implementations. In that case you can use the LD_PRELOAD trick to prioritize it's symbols over the ones from the LibC and accelerate existing string-heavy applications without recompiling them.

SZ_AVOID_STL and SZ_SAFETY_OVER_COMPATIBILITY:

When using the C++ interface one can disable implicit conversions from std::string to sz::string and back. If not needed, the <string> and <string_view> headers will be excluded, reducing compilation time. Moreover, if STL compatibility is a low priority, one can make the API safer by disabling the overloads, which are subjectively error prone.

STRINGZILLA_BUILD_SHARED, STRINGZILLA_BUILD_TEST, STRINGZILLA_BUILD_BENCHMARK, STRINGZILLA_TARGET_ARCH for CMake users:

When compiling the tests and benchmarks, you can explicitly set the target hardware architecture. It's synonymous to GCC's -march flag and is used to enable/disable the appropriate instruction sets. You can also disable the shared library build, if you don't need it.

Quick Start: Rust 🦀

StringZilla is available as a Rust crate, with documentation available on docs.rs/stringzilla. To use the latest crate release in your project, add the following to your Cargo.toml:

[dependencies]
stringzilla = ">=3"

Or if you want to use the latest pre-release version from the repository:

[dependencies]
stringzilla = { git = "https://github.com/ashvardanian/stringzilla", branch = "main-dev" }

Once installed, all of the functionality is available through the stringzilla namespace. Many interfaces will look familiar to the users of the memchr crate.

use stringzilla::sz;

// Identical to `memchr::memmem::find` and `memchr::memmem::rfind` functions
sz::find("Hello, world!", "world") // 7
sz::rfind("Hello, world!", "world") // 7

// Generalizations of `memchr::memrchr[123]`
sz::find_char_from("Hello, world!", "world") // 2
sz::rfind_char_from("Hello, world!", "world") // 11

Unlike memchr, the throughput of stringzilla is high in both normal and reverse-order searches. It also provides no constraints on the size of the character set, while memchr allows only 1, 2, or 3 characters. In addition to global functions, stringzilla provides a StringZilla extension trait:

use stringzilla::StringZilla;

let my_string: String = String::from("Hello, world!");
let my_str = my_string.as_str();
let my_cow_str = Cow::from(&my_string);

// Use the generic function with a String
assert_eq!(my_string.sz_find("world"), Some(7));
assert_eq!(my_string.sz_rfind("world"), Some(7));
assert_eq!(my_string.sz_find_char_from("world"), Some(2));
assert_eq!(my_string.sz_rfind_char_from("world"), Some(11));
assert_eq!(my_string.sz_find_char_not_from("world"), Some(0));
assert_eq!(my_string.sz_rfind_char_not_from("world"), Some(12));

// Same works for &str and Cow<'_, str>
assert_eq!(my_str.sz_find("world"), Some(7));
assert_eq!(my_cow_str.as_ref().sz_find("world"), Some(7));

The library also exposes Levenshtein and Hamming edit-distances for byte-arrays and UTF-8 strings, as well as Needleman-Wunch alignment scores.

use stringzilla::sz;

// Handling arbitrary byte arrays:
sz::edit_distance("Hello, world!", "Hello, world?"); // 1
sz::hamming_distance("Hello, world!", "Hello, world?"); // 1
sz::alignment_score("Hello, world!", "Hello, world?", sz::unary_substitution_costs(), -1); // -1

// Handling UTF-8 strings:
sz::hamming_distance_utf8("αβγδ", "αγγδ") // 1
sz::edit_distance_utf8("façade", "facade") // 1

Quick Start: Swift 🍏

StringZilla can be added as a dependency in the Swift Package Manager. In your Package.swift file, add the following:

dependencies: [
    .package(url: "https://github.com/ashvardanian/stringzilla")
]

The package currently covers only the most basic functionality, but is planned to be extended to cover the full C++ API.

var s = "Hello, world! Welcome to StringZilla. 👋"
s[s.findFirst(substring: "world")!...] // "world! Welcome to StringZilla. 👋")    
s[s.findLast(substring: "o")!...] // "o StringZilla. 👋")
s[s.findFirst(characterFrom: "aeiou")!...] // "ello, world! Welcome to StringZilla. 👋")
s[s.findLast(characterFrom: "aeiou")!...] // "a. 👋")
s[s.findFirst(characterNotFrom: "aeiou")!...] // "Hello, world! Welcome to StringZilla. 👋"
s.editDistance(from: "Hello, world!")! // 29

Algorithms & Design Decisions 📚

StringZilla aims to optimize some of the slowest string operations. Some popular operations, however, like equality comparisons and relative order checking, almost always complete on some of the very first bytes in either string. In such operations vectorization is almost useless, unless huge and very similar strings are considered. StringZilla implements those operations as well, but won't result in substantial speedups.

Exact Substring Search

Substring search algorithms are generally divided into: comparison-based, automaton-based, and bit-parallel. Different families are effective for different alphabet sizes and needle lengths. The more operations are needed per-character - the more effective SIMD would be. The longer the needle - the more effective the skip-tables are. StringZilla uses different exact substring search algorithms for different needle lengths and backends:

  • When no SIMD is available - SWAR (SIMD Within A Register) algorithms are used on 64-bit words.
  • Boyer-Moore-Horspool (BMH) algorithm with Raita heuristic variation for longer needles.
  • SIMD algorithms are randomized to look at different parts of the needle.

On very short needles, especially 1-4 characters long, brute force with SIMD is the fastest solution. On mid-length needles, bit-parallel algorithms are effective, as the character masks fit into 32-bit or 64-bit words. Either way, if the needle is under 64-bytes long, on haystack traversal we will still fetch every CPU cache line. So the only way to improve performance is to reduce the number of comparisons. The snippet below shows how StringZilla accomplishes that for needles of length two.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L1585-L1637

Going beyond that, to long needles, Boyer-Moore (BM) and its variants are often the best choice. It has two tables: the good-suffix shift and the bad-character shift. Common choice is to use the simplified BMH algorithm, which only uses the bad-character shift table, reducing the pre-processing time. We do the same for mid-length needles up to 256 bytes long. That way the stack-allocated shift table remains small.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1774-L1825

In the C++ Standards Library, the std::string::find function uses the BMH algorithm with Raita's heuristic. Before comparing the entire string, it matches the first, last, and the middle character. Very practical, but can be slow for repetitive characters. Both SWAR and SIMD backends of StringZilla have a cheap pre-processing step, where we locate unique characters. This makes the library a lot more practical when dealing with non-English corpora.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1398-L1431

All those, still, have $O(hn)$ worst case complexity. To guarantee $O(h)$ worst case time complexity, the Apostolico-Giancarlo (AG) algorithm adds an additional skip-table. Preprocessing phase is $O(n+sigma)$ in time and space. On traversal, performs from $(h/n)$ to $(3h/2)$ comparisons. It however, isn't practical on modern CPUs. A simpler idea, the Galil-rule might be a more relevant optimizations, if many matches must be found.

Other algorithms previously considered and deprecated:

  • Apostolico-Giancarlo algorithm for longer needles. Control-flow is too complex for efficient vectorization.
  • Shift-Or-based Bitap algorithm for short needles. Slower than SWAR.
  • Horspool-style bad-character check in SIMD backends. Effective only for very long needles, and very uneven character distributions between the needle and the haystack. Faster "character-in-set" check needed to generalize.

§ Reading materials. Exact String Matching Algorithms in Java. SIMD-friendly algorithms for substring searching.

Levenshtein Edit Distance

Levenshtein distance is the best known edit-distance for strings, that checks, how many insertions, deletions, and substitutions are needed to transform one string to another. It's extensively used in approximate string-matching, spell-checking, and bioinformatics.

The computational cost of the Levenshtein distance is $O(n * m)$, where $n$ and $m$ are the lengths of the string arguments. To compute that, the naive approach requires $O(n * m)$ space to store the "Levenshtein matrix", the bottom-right corner of which will contain the Levenshtein distance. The algorithm producing the matrix has been simultaneously studied/discovered by the Soviet mathematicians Vladimir Levenshtein in 1965, Taras Vintsyuk in 1968, and American computer scientists - Robert Wagner, David Sankoff, Michael J. Fischer in the following years. Several optimizations are known:

  1. Space Optimization: The matrix can be computed in $O(min(n,m))$ space, by only storing the last two rows of the matrix.
  2. Divide and Conquer: Hirschberg's algorithm can be applied to decompose the computation into subtasks.
  3. Automata: Levenshtein automata can be effective, if one of the strings doesn't change, and is a subject to many comparisons.
  4. Shift-Or: Bit-parallel algorithms transpose the matrix into a bit-matrix, and perform bitwise operations on it.

The last approach is quite powerful and performant, and is used by the great RapidFuzz library. It's less known, than the others, derived from the Baeza-Yates-Gonnet algorithm, extended to bounded edit-distance search by Manber and Wu in 1990s, and further extended by Gene Myers in 1999 and Heikki Hyyro between 2002 and 2004.

StringZilla introduces a different approach, extensively used in Unum's internal combinatorial optimization libraries. The approach doesn't change the number of trivial operations, but performs them in a different order, removing the data dependency, that occurs when computing the insertion costs. This results in much better vectorization for intra-core parallelism and potentially multi-core evaluation of a single request.

Next design goals:

  • Generalize fast traversals to rectangular matrices.
  • Port x86 AVX-512 solution to Arm NEON.

§ Reading materials. Faster Levenshtein Distances with a SIMD-friendly Traversal Order.

Needleman-Wunsch Alignment Score for Bioinformatics

The field of bioinformatics studies various representations of biological structures. The "primary" representations are generally strings over sparse alphabets:

  • DNA sequences, where the alphabet is {A, C, G, T}, ranging from ~100 characters for short reads to 3 billion for the human genome.
  • RNA sequences, where the alphabet is {A, C, G, U}, ranging from ~50 characters for tRNA to thousands for mRNA.
  • Proteins, where the alphabet is made of 22 amino acids, ranging from 2 characters for dipeptide to 35,000 for Titin, the longest protein.

The shorter the representation, the more often researchers may want to use custom substitution matrices. Meaning that the cost of a substitution between two characters may not be the same for all pairs.

StringZilla adapts the fairly efficient two-row Wagner-Fisher algorithm as a baseline serial implementation of the Needleman-Wunsch score. It supports arbitrary alphabets up to 256 characters, and can be used with either BLOSUM, PAM, or other substitution matrices. It also uses SIMD for hardware acceleration of the substitution lookups. This however, does not yet break the data-dependency for insertion costs, where 80% of the time is wasted. With that solved, the SIMD implementation will become 5x faster than the serial one.

Random Generation

Generating random strings from different alphabets is a very common operation. StringZilla accepts an arbitrary Pseudorandom Number Generator to produce noise, and an array of characters to sample from. Sampling is optimized to avoid integer division, a costly operation on modern CPUs. For that a 768-byte long lookup table is used to perform 2 lookups, 1 multiplication, 2 shifts, and 2 accumulations.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L2490-L2533

Sorting

For lexicographic sorting of strings, StringZilla uses a "hybrid-hybrid" approach with $O(n * log(n))$ and.

  1. Radix sort for first bytes exported into a continuous buffer for locality.
  2. IntroSort on partially ordered chunks to balance efficiency and worst-case performance.
    1. IntroSort begins with a QuickSort.
    2. If the recursion depth exceeds a certain threshold, it switches to a HeapSort.

Next design goals:

  • Generalize to arrays with over 4 billion entries.
  • Algorithmic improvements may yield another 3x performance gain.
  • SIMD-acceleration for the Radix slice.

Hashing

[!WARNING] Hash functions are not cryptographically safe and are currently under active development. They may change in future minor releases.

Choosing the right hashing algorithm for your application can be crucial from both performance and security standpoint. In StringZilla a 64-bit rolling hash function is reused for both string hashes and substring hashes, Rabin-style fingerprints. Rolling hashes take the same amount of time to compute hashes with different window sizes, and are fast to update. Those are not however perfect hashes, and collisions are frequent. StringZilla attempts to use SIMD, but the performance is not yet satisfactory. On Intel Sapphire Rapids, the following numbers can be expected for N-way parallel variants.

  • 4-way AVX2 throughput with 64-bit integer multiplication (no native support): 0.28 GB/s.
  • 4-way AVX2 throughput with 32-bit integer multiplication: 0.54 GB/s.
  • 4-way AVX-512DQ throughput with 64-bit integer multiplication: 0.46 GB/s.
  • 4-way AVX-512 throughput with 32-bit integer multiplication: 0.58 GB/s.
  • 8-way AVX-512 throughput with 32-bit integer multiplication: 0.11 GB/s.

Next design goals:

  • Try gear-hash and other rolling approaches.

Why not CRC32?

Cyclic Redundancy Check 32 is one of the most commonly used hash functions in Computer Science. It has in-hardware support on both x86 and Arm, for both 8-bit, 16-bit, 32-bit, and 64-bit words. The 0x1EDC6F41 polynomial is used in iSCSI, Btrfs, ext4, and the 0x04C11DB7 in SATA, Ethernet, Zlib, PNG. In case of Arm more than one polynomial is supported. It is, however, somewhat limiting for Big Data usecases, which often have to deal with more than 4 Billion strings, making collisions unavoidable. Moreover, the existing SIMD approaches are tricky, combining general purpose computations with specialized instructions, to utilize more silicon in every cycle.

§ Reading materials. Comprehensive derivation of approaches Faster computation for 4 KB buffers on x86 Comparing different lookup tables Great open-source implementations. By Peter Cawley By Stephan Brumme

Other Modern Alternatives

MurmurHash from 2008 by Austin Appleby is one of the best known non-cryptographic hashes. It has a very short implementation and is capable of producing 32-bit and 128-bit hashes. The CityHash from 2011 by Google and the xxHash improve on that, better leveraging the super-scalar nature of modern CPUs and producing 64-bit and 128-bit hashes.

Neither of those functions are cryptographic, unlike MD5, SHA, and BLAKE algorithms. Most of cryptographic hashes are based on the Merkle-Damgård construction, and aren't resistant to the length-extension attacks. Current state of the Art, might be the BLAKE3 algorithm. It's resistant to a broad range of attacks, can process 2 bytes per CPU cycle, and comes with a very optimized official implementation for C and Rust. It has the same 128-bit security level as the BLAKE2, and achieves its performance gains by reducing the number of mixing rounds, and processing data in 1 KiB chunks, which is great for longer strings, but may result in poor performance on short ones.

All mentioned libraries have undergone extensive testing and are considered production-ready. They can definitely accelerate your application, but so may the downstream mixer. For instance, when a hash-table is constructed, the hashes are further shrunk to address table buckets. If the mixer looses entropy, the performance gains from the hash function may be lost. An example would be power-of-two modulo, which is a common mixer, but is known to be weak. One alternative would be the fastrange by Daniel Lemire. Another one is the Fibonacci hash trick using the Golden Ratio, also used in StringZilla.

Unicode, UTF-8, and Wide Characters

Most StringZilla operations are byte-level, so they work well with ASCII and UTF8 content out of the box. In some cases, like edit-distance computation, the result of byte-level evaluation and character-level evaluation may differ. So StringZilla provides following functions to work with Unicode:

  • sz_edit_distance_utf8 - computes the Levenshtein distance between two UTF-8 strings.
  • sz_hamming_distance_utf8 - computes the Hamming distance between two UTF-8 strings.

Java, JavaScript, Python 2, C#, and Objective-C, however, use wide characters (wchar) - two byte long codes, instead of the more reasonable fixed-length UTF32 or variable-length UTF8. This leads to all kinds of offset-counting issues when facing four-byte long Unicode characters. So consider transcoding with simdutf, if you are coming from such environments.

Contributing 👾

Please check out the contributing guide for more details on how to setup the development environment and contribute to this project. If you like this project, you may also enjoy USearch, UCall, UForm, and SimSIMD. 🤗

If you like strings and value efficiency, you may also enjoy the following projects:

  • simdutf - transcoding UTF8, UTF16, and UTF32 LE and BE.
  • hyperscan - regular expressions with SIMD acceleration.
  • pyahocorasick - Aho-Corasick algorithm in Python.
  • rapidfuzz - fast string matching in C++ and Python.

If you are looking for more reading materials on this topic, consider the following:

License 📜

Feel free to use the project under Apache 2.0 or the Three-clause BSD license at your preference.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

stringzilla-3.9.2-cp312-cp312-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.9.2-cp312-cp312-win_amd64.whl (74.8 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.9.2-cp312-cp312-win32.whl (64.2 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl (255.2 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp312-cp312-musllinux_1_2_s390x.whl (194.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp312-cp312-musllinux_1_2_ppc64le.whl (216.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp312-cp312-musllinux_1_2_i686.whl (199.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp312-cp312-musllinux_1_2_aarch64.whl (205.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.5 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.0 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.2 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.8 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (198.0 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp312-cp312-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.9.2-cp312-cp312-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.9.2-cp312-cp312-macosx_10_9_universal2.whl (112.7 kB view details)

Uploaded CPython 3.12 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.2-cp311-cp311-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.9.2-cp311-cp311-win_amd64.whl (74.7 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.9.2-cp311-cp311-win32.whl (64.1 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl (254.5 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp311-cp311-musllinux_1_2_s390x.whl (193.7 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp311-cp311-musllinux_1_2_ppc64le.whl (217.0 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp311-cp311-musllinux_1_2_i686.whl (199.5 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp311-cp311-musllinux_1_2_aarch64.whl (205.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.0 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.0 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.7 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.1 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.9 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp311-cp311-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.9.2-cp311-cp311-macosx_10_9_x86_64.whl (73.5 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.9.2-cp311-cp311-macosx_10_9_universal2.whl (112.4 kB view details)

Uploaded CPython 3.11 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.2-cp310-cp310-win_arm64.whl (63.3 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.9.2-cp310-cp310-win_amd64.whl (73.1 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.9.2-cp310-cp310-win32.whl (64.1 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl (252.4 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp310-cp310-musllinux_1_2_s390x.whl (191.4 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp310-cp310-musllinux_1_2_ppc64le.whl (214.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp310-cp310-musllinux_1_2_i686.whl (197.5 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp310-cp310-musllinux_1_2_aarch64.whl (203.3 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (257.0 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (189.8 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (218.2 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (207.9 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.7 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp310-cp310-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.9.2-cp310-cp310-macosx_10_9_x86_64.whl (73.5 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.9.2-cp310-cp310-macosx_10_9_universal2.whl (112.4 kB view details)

Uploaded CPython 3.10 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.2-cp39-cp39-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.9.2-cp39-cp39-win_amd64.whl (74.8 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.9.2-cp39-cp39-win32.whl (64.2 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.9.2-cp39-cp39-musllinux_1_2_x86_64.whl (251.1 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp39-cp39-musllinux_1_2_s390x.whl (190.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp39-cp39-musllinux_1_2_ppc64le.whl (213.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp39-cp39-musllinux_1_2_i686.whl (196.5 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp39-cp39-musllinux_1_2_aarch64.whl (202.4 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.8 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.6 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.7 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.7 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.4 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp39-cp39-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.9.2-cp39-cp39-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.9.2-cp39-cp39-macosx_10_9_universal2.whl (112.4 kB view details)

Uploaded CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.2-cp38-cp38-win_amd64.whl (73.3 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.9.2-cp38-cp38-win32.whl (64.2 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.9.2-cp38-cp38-musllinux_1_2_x86_64.whl (250.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp38-cp38-musllinux_1_2_s390x.whl (189.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp38-cp38-musllinux_1_2_ppc64le.whl (212.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp38-cp38-musllinux_1_2_i686.whl (195.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp38-cp38-musllinux_1_2_aarch64.whl (201.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.1 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.6 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.7 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (205.6 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.4 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp38-cp38-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.9.2-cp38-cp38-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.9.2-cp38-cp38-macosx_10_9_universal2.whl (112.4 kB view details)

Uploaded CPython 3.8 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.2-cp37-cp37m-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.9.2-cp37-cp37m-win32.whl (64.1 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_x86_64.whl (248.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_s390x.whl (187.8 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_ppc64le.whl (210.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_i686.whl (193.9 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_aarch64.whl (199.2 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.6 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.9 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.8 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (203.4 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.6 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp37-cp37m-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.9.2-cp36-cp36m-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.9.2-cp36-cp36m-win32.whl (64.1 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_x86_64.whl (247.9 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ x86-64

stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_s390x.whl (187.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_ppc64le.whl (209.9 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_i686.whl (193.4 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_aarch64.whl (198.5 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.7 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (184.9 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.4 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.5 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.9 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.2-cp36-cp36m-macosx_10_9_x86_64.whl (73.2 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

Details for the file stringzilla-3.9.2-cp312-cp312-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 5ec860da0b1dafe9528bdb88cd41b314f84bb1f6f6fe8a5a42dce18b391f645f
MD5 d8a2ae120e66b8d43e80d892ec4e7f27
BLAKE2b-256 54e566f23fa1c0910aedd7df5a59c7be09332e37476619e60311ff69c0142e4d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 bf0d07ef87b00071b3a4ffc33ed386a81ced823ef64d354ec111a0f69e038544
MD5 d714d7c89502e3a1c6ddd137fc053327
BLAKE2b-256 1ebc2e01f97550aad0aa6551c89ff1d7c2caad872d7269829265829eb2654b09

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp312-cp312-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 a958c3d2e2ac2ca2a1c87839e728969c557775c2aaf98580f8a8b254ad290900
MD5 4de10295ad687fa7a4c13f7553ee499c
BLAKE2b-256 92c57467c59313b1958d923ddb6da827d3c12f9f8b5c5471c66ded252de88b06

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 16e296c14594804b598289d6adb5843b0d701f470e5bb269d51271f9f3c828fa
MD5 bc03937b2d86fd4e158a9f95e8d49f2e
BLAKE2b-256 c035b4c04f0c59f0d0ac0c7375153dc866220d622a729f55f7bd5d644de82d9b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 3bdb9c84b0ad9ec851e23dd81563103f0434214da0094fa3e86dc41eff5f21f8
MD5 f4aa62c37dbe09652deefc2240bf4f76
BLAKE2b-256 a3f824ae77ca338274ea49324722baeedbb63837beaf7eacb815e5968d7045bd

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 364b0d1ac6a1cd437e68d0e87f9a6a80024735d94ff9af7b3a2d9cbebab97411
MD5 af236e8ac0a957461a04266c8962454e
BLAKE2b-256 4580ddf2ef152052d1b41705b8e2c0b1b39369ae5dd959f9b82e5227c2605d27

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 f821cc7c172a04b47856141c409d91179274a0a3237810efef471497884f2afb
MD5 669fff279a1f003efcd61f816ce5d55c
BLAKE2b-256 a91d093ab6c44a37f7c367901553588eec52fd2aa5cd5896700be5dd917db5cc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 7f0b03c500e8eeaaeee743bf412e52911ddd4e14375ab533a38d2aa242dff5d5
MD5 747dd1c5b2b5cfe99107022aab2e3486
BLAKE2b-256 e46c136643275f930cc95006cbfab1ea6b07a630a4b3f54d44783d4906f9500b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5d6d50621ec22d7e4e2471720404a998d6fc48864c270ffed2784493b779d309
MD5 7bbc72e828d7b7c12b8cd33aa00020e8
BLAKE2b-256 d4481f93f678683fd5eb7e2667224f9c25947bc76564c7e03fbf47b051d35eb8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 5d6ef7d19240177f963bc11240822d1904ca20f24034675b2e7d4b7c129df5d2
MD5 68960abc5f74b0e270472f4c04cb95ad
BLAKE2b-256 664c17a88655c15b73fd2e2b23e168ad29045cfd0f00c788ce7668e7581f90f7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 7f05f280f2a769a7799ff90ef7440c80fcb41c65b4792d49d8fef2ed77a8569e
MD5 b784209740c1f270a500f2532dda2c1f
BLAKE2b-256 4d2b7b95f619e4cd56072234f06ebbeced2a6e9a61a0efb2b344a1ac6310a45a

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7a4f3e2773d5af67f52c5afa6b92df7d3018868a898db3bb98688ead7be670c8
MD5 148f18d625f2a63e7a7ce3e888c5027f
BLAKE2b-256 a74d60ac3ee523403c1901ded6351c8eeadabbd559b2e7b16fbcfef00bf97e01

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e123a9eb8ec8961b823faaa9924bbc0f60c1f04e9e4ed4f144f51bbaeeedcf18
MD5 97ca54cd0c67d562916603c812ca8f19
BLAKE2b-256 d49eaba26ba9901985f8a98b6b388567684c97c908480c517a48e00a506b713a

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 08d43c9d7ea7db98c275024a85089d5a6e9f1e6682a80407b67542ee3bdbc990
MD5 5604f9351d7d28b22fd17cc5771556ef
BLAKE2b-256 44164cb62bfc50c7e59c5f3b19a407725f856638553f73915e0af90a42f9a6de

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 652cc081e05abbecb07795a1f7126d3cbf83dfe2b9f0089532ab823a67d3a27a
MD5 66ad5bb65352e02d6fcadbc2e99853e4
BLAKE2b-256 dcb80a4c985ca29b09138f9f4a9175c3fefa09f744030228be3079aec534b9ac

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp312-cp312-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 340041c6b9ea78f1c88983a2eae62780df25f43c94c1e08d3de683d0f641d850
MD5 e99941f839fce207037296c3b38e7290
BLAKE2b-256 eef8f176361647b6cd654912157ca8fbf8f3fe41f0ab545b58606c162fa935e0

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 5563019df3a2c7f8ab127e969398c47171427d2bf98e690cc38e9c5cca9eec0f
MD5 33c8407891036800e1e5eefde06564bd
BLAKE2b-256 24b71c78bf5595e89f45dfb511cd764a54d511e829f9fab73ff1a9927772fdb9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 363db919fdcaf714a3ed3b8d07d4c89d501910e803316f17bff8b2030598b9b8
MD5 ed202ac5fc5158a275f670bdf91d6200
BLAKE2b-256 6177ae7a3fb889120be8532578ab8eb6b8667258d1030345eb92964cd172a86f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp311-cp311-win32.whl
  • Upload date:
  • Size: 64.1 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 e125e2025fc1d7c6f87f2c23196c7d61157fb0113726b9fdd5ead0e32be3268b
MD5 f93770474dca3c217d551121ad2d9d8a
BLAKE2b-256 b719b0b59d4c98ae2ff6245b1d7a05ee2e21f5fd049d287d68f6367e3a429c36

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 31aaa15eb0e6ed7f5e9ba0c1c7fcc61938f23bbe94e4500abc3e55b5febfd6b2
MD5 fb65cb41ff8312ac4d741a78e915d898
BLAKE2b-256 d1b0a2ca825007f5d7ba168c9d7eaa6271a2bcee9c6e7dfdb39abf4bb62b1555

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 ecef93027dbeda9e8c7395c3bc014e09a667597bdab866f349a53a00e8779371
MD5 4c09766092e835a484a396d3dbe92f7e
BLAKE2b-256 8513d3f12c03cde298be5f03246b2454ee54e8cacc6849dec26dc8b07d335e05

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 7deaeebb67ba8b65124015a296944539afbed41d6232d0dad019c4f609cc2d94
MD5 b329cbb7d3e494315860b019b552296b
BLAKE2b-256 d406f1d307b90d88e5b4c3d64a4138d7cc73bf238798ff5d80d3bfbe95c6dfb5

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 7ae55588178b0a4991333c16a04bb7efaeed6b301578c0e250ed8a61f5245021
MD5 6e52a83fd0985406af235c1b49ed8b12
BLAKE2b-256 162c217e63331a9e6a0d63e3b63d0f9b75c5e7a4221d661b404f1638d58e5871

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 e4866cdca88dbf7cdffe793ce14932e860383592d0a81c4b89c3b9584d333997
MD5 9046e60064269e6e6ec8201e91e60c00
BLAKE2b-256 3c6712dc90d659df7b9172f4808aa12a2fc9a073f254c655f1baea8d4f3bba91

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 6b657161c83c404bef4fc7dd19a15609843ee253b8341acec79e3d312e624e05
MD5 5cc68165e6466e5d7562fc78c31076b5
BLAKE2b-256 9a027eaebd8b1f9fcca5dc22813beaa296d9ff68ad122d527d2eb0bdc4e5db8d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 99162b3e13ecf80e8dcdbb415342c4911082ffb0012ecff67e091ca1981066df
MD5 dd8320b4a6d10e7b7351150e1ccc1566
BLAKE2b-256 ba2ed9f0cb9aa2495216df87e9361cf48369a6bda2a4583c2f376f678c0fdd99

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 f4958ea9564a2194ad87527e51bb11d3e55819d1d3aceb08a8fce868b06df0e1
MD5 58d1fac37b039ea92d985ac672ea5509
BLAKE2b-256 fb99a83722c3c033b6bf045ef36f38f7dfef7e1d076befaea31d9a03bffdfacf

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 102e38157d42c88f0fa3982a43e7f5b11850b05eafd6e95b47ef5a7258582c37
MD5 ae3096e04635d2d42fb109100f8c3a28
BLAKE2b-256 2f38c0eea86ef84bd53ea6e3ae721b72c385413a17b53ca7a39b1ef2f0901697

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 cee25bf6499edcba242d78a3481b13defbc199d2d15d3dd31ad505049bce24d2
MD5 76c73c5f64df54b50689e7763bcc3e80
BLAKE2b-256 71892186fe6617b16a92140efaf168cff563287cc01c9746b0abf8126bbbbbf9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0ace830588b35f23a1060887916ad22bcdc3efe8a56954378035754025717534
MD5 6c9e345023ed599ef5dc9cca2375b73a
BLAKE2b-256 80ebffd487ad656479cd520d422a552bb6e8b4bd19587443e261f507071be6ba

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 f9613d0153bd861feb060026d95e8444182f8bf34e8c7206c8b19203e4c4162b
MD5 b85728b3459573ef44d8c9adf4093f97
BLAKE2b-256 e36cea3958623daa1992ab04a5781be5527a3ba664200aa1da3094a8fcd48a1a

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp311-cp311-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 859e8146f551550e29bc0417936a848cd9f773f352991ab1298d144d0660b2c6
MD5 1504e06d5674ae288fe33ae519706d2c
BLAKE2b-256 892fc51ef62c226c5686c2a2fdb1a157b4bda5ad80dd43552e1c029a96276771

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 cf388ab0d7c83479c70ef00332f04d06396f6f966ec1dda44ab88d35888e21b6
MD5 4fea9956be5b066c30f497e0de6dfe79
BLAKE2b-256 8e8315339040e0501a69641ba7ce9e5c4449b4a7a93e660590e4f9bbea25f1a6

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 7ecf100ffbb0c69a6fc4c5de524d27b707a31f36ea017ad22490b825be558970
MD5 635d3d40d8f26ec11e6624690f871c5d
BLAKE2b-256 0f5e57382212f16a15da6202c830682579e53a7254cd64498b55d596e9086c6f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp310-cp310-win32.whl
  • Upload date:
  • Size: 64.1 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 ec9ebdc63b013c17de879dfd78801532a9f0eeb7cb9e4a31b8f50cd9d88a2c88
MD5 25c9ce722865a90e4fe802a9c27c08e5
BLAKE2b-256 22976cdbf4d7be62519f1e58f8c1176342294ee0f2fa02b03b69c392d138f650

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 4b9b33edfdc3a65546dc18f1bb1062c394bea2189d6a06fe61b3bfc8c2f91d5f
MD5 105038c939f9b57c4d4a8b3e3f697cd3
BLAKE2b-256 2f7ec1b4e99bd7f3de86cb268c9a906d34092030b15d26bc9e37e292d6f475c2

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 881fe33e6727edf287b0f49a07dd23b211e4fe2b3aad90933209adeedbce2b20
MD5 e5f2cffdbeafbef9090de51954ea1092
BLAKE2b-256 138b149875dcf1199461764c1e239f3060142ee0cda6b1cea786cd90631e29ae

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 c28732a43efb11aefe560586e479498748a6be103056fa1302e0c81ae7b809db
MD5 4cf8d19f57c74d31d3d21603429f60a1
BLAKE2b-256 691aafb4830327a713e093154553cfe25fce0ff263b9507a261cdc2ac4902b98

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 0ee8ff9f3c84709822d678088705dfeb60f588c36f5068c34da7672e5db18238
MD5 29492f292fd01ad54f85cc74cbe67353
BLAKE2b-256 dfce2af653d0723d236e385521fbb46c52c98abbaf38881c2aaade7c8a4442c8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2b3efc0f9740dbb4b1d07b3a5dc0342f2527e38a859d30c2458d3261c008007b
MD5 c3a754478b0ea94959da8e9634a34a67
BLAKE2b-256 4715ead034fd25b23aad3ec2d84231dde944e8e21c897705e0de2d3550ab89c9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 947188402131b246f967f8abb110151f519eeee4c71cfce8d81a7be357b29f41
MD5 631c21b44e288160a0f40f6d42f6eae2
BLAKE2b-256 6cc0d9690033ddaaaeb79e6d652ff8374afb6131dc311255d05e554859113928

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e567e2302a8a2099cb21bd51ca85a35f05dfcbb670d388e0521d18e35a64a51c
MD5 538fdc5a73c5fcd863b93380ddb0e8ac
BLAKE2b-256 2d2f7146da3babf3eb32931852dfe0ea39125636e971f50899ab0e08b31129f1

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 48143892ca3d58b5f447c76692ff6d87754612ff660dad573faa7f9d4e899b82
MD5 9a3a63c22fa35a71a27541c02279638c
BLAKE2b-256 d39517afc2d7f00f69a9a83d220486a4d6de9cbc7cdf5163d90d6661f5c00316

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4c37a6f641a1bfe80efcfab7d1435b141002f7b73439d54932175356d7eefa07
MD5 94295db1cb9035653e80173f87027454
BLAKE2b-256 b449ef6f2ec66a6dd00c9743429ff06e4b3ffaaa968526734837b6839cee5687

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 05b7209e18f03ffc68feb42f285fee4d006bf108052490649e8529a1fb086262
MD5 5fa7044c55abb7ea373a6181460b15b1
BLAKE2b-256 385d961f9e99747cca5c1f169b82eccaeca17272cb790cbc97adfcadc9810e35

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 39adf233e6f2497a77d494093df448de1e486a72574c878adbcbd10469a6662e
MD5 74c82a114815e4a198276d7158384612
BLAKE2b-256 9c5a37c040bf7e577455f2e5ba1d98615aa13726675530fe9f6d8925d8ad4dd3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 b0d15435907a891af1dee48ad98842c92113ff788ab6929e33cdd273fe2083ee
MD5 129086f3f5688cb5da23b3a45bea48dc
BLAKE2b-256 e067484e9b2423f4ddcea1f9755e6c9f629042187d6f3faf5e0a18f7956a05e8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp310-cp310-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 3625161032677411f893f50399d225600aaffd934877599e6d652455fe5f46d8
MD5 b3989c476502b8b9682a4c59539715e2
BLAKE2b-256 4217b5ff2bba1675ee0368ba62c782700a511fe8eec33aae22a2b30c8609047b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 d24f2d7073f720e9abb9ecbf6ed7429b05078ae4b090c0333bdee0fe01033bbd
MD5 131862458c6d30a52280a706f05704c0
BLAKE2b-256 ab8329ccf006dfae2cb2718cda23082292a825419c966b62139177fc3842a3e0

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 e425af3156682febf571bc173fb151de780b6ecd8171d6c4137aae6edce9095f
MD5 ff365ccf999a6249ee947c040bb7022e
BLAKE2b-256 854856336b17d6018e6aff7fb35785b1dac34808c9c7a9d1f11c6c3cc690fd39

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp39-cp39-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 da41b576c42abc3b8f1496caaf98802e47eb29355c94574a439df0498c8896a3
MD5 312753db89befc33b78d66c5efe3a215
BLAKE2b-256 b8b97ec96cee3d19036f2a120facdea2cf9983a4e45204ce50f34995dc90eb39

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5caecaeb618058eac5d60840f8dbb5f97219728c590f39ebfbcdb5f272e4ffe4
MD5 06231c0df6e842f63e5c46307fb8fc56
BLAKE2b-256 8d6274e66d7870018988698fdbe489dad931fb80c34ebce7abc1e40281f1ab0a

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 e6f4a063eb5ed59339d70b161adb5e9432321f31fa08818b485555e433e5f7ec
MD5 07834c3100119fc12bf3b7eb2eee9bd5
BLAKE2b-256 b1986bc0eced76b601bfecfa836d1e9f44e28f405360c29527da00bc974f2b6e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 6da100d755f5e5005bf4b6b8ad59407cc8014f289c201150aeac2b246762f88a
MD5 3179c63d840761c42b0bec0061439586
BLAKE2b-256 a12075671bbf2230e454cea6482d448181e608b9e64d9efa190fa9c87902a48d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 935ead6bb6a39e241874754485aefc887b7d87114659ba01485c3cd7d6e4aa23
MD5 9ffc87c083336f46c6faf9a2906b3b5e
BLAKE2b-256 023bf6c33f6aab75c479dd0ce8aa1bf36f64146043fb8cb1104069c066fd8caf

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 df2b4cb80d960767c7542a0995b1c6f133d97ef8a6ad994978e1ff2219eced37
MD5 2237200126a2321d0c72de343c0517e6
BLAKE2b-256 14b402df203f7c48ebf9567cded132fcb5fb86c4e6e585af2fbaf4245e434973

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 54a27972b5075b501fe89feee9ed1589ae3a14d8d32d8972dffe66f0d9b6a21f
MD5 a83ecfe93a8d12e6e146944ee940ff63
BLAKE2b-256 66259a860f66969e0b8dd8def501e6e2222558c58e13c02125085ee754ac3a9d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 eccce0d724741923125cea089fa7a4e5e6dc8a58780941b3b78ea3dd67137bd4
MD5 9d4971c143a8bdb643a64282d8a10b22
BLAKE2b-256 00c48da01f282b8a15d4719297908bac010c15fd5e63c36e116b17b4cc7c89e3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 482c57a020419a6ac0b6039de4ff02f99bffcef2ac3604849bc00a8ebdfc131d
MD5 78d351ce555e62396f67f5264b63e836
BLAKE2b-256 c1a5fd91c9a54c2fd4ac4139ad21887823052597878d3e20e94717db2ef8fe3f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a739c8c52019f73bad1b5d25a152dbf2b0e77cbd143c3a34005e3506667878fa
MD5 1a8edd15ee9e97f137a9bb1c92f2706d
BLAKE2b-256 ec9cd61e7c85c378530af89276305f0e82b4a0361135f17f5a2b1dbabcdb27a2

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 275d70702a096d42c5c10bb2fe9068a733abdb740275b13f4be5d550dc3f7f57
MD5 0adb87e1d7afc49d8fc5e759b341c20a
BLAKE2b-256 6f6e71445169b2696f7ef57085731901e6661f29811ee27081c5ea476f1a303e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0bce0c2f548dde8c5387d806df130056003c0aad23de7c3a77a3055defa48f0a
MD5 1605965466f3b6d6bc6672972bab5fb8
BLAKE2b-256 711f2607f36b99d55997937ce5e5fbd61ea01da942658ca5409f363293e591f4

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 c18c67285aef7c3a15422f759d6d12f62d6c73a102097438210183ae6477640a
MD5 d814b60c7a33d1f910689366972d802d
BLAKE2b-256 1b2ebcc27b26965aa8b3729c355898be0f0535cba6ec001c06b68637ecf49e33

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 57b064ad076ef70aaf8e7d89b033e451a2dd1e64e2ac294d2f74beb59cd04af4
MD5 4f34e24c1d9c7cbd820385bacfc36a72
BLAKE2b-256 1f3aceebbb86fc3219272eda5c4d2a53b05a57d233eb718e5840069b5bfb1580

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 1803786dec65654dd1a77c1112f1fbf66a44b4a1b69b6b2051f45f3cccb50fe8
MD5 894bcc891e056f8bd775f9cca58e9ae5
BLAKE2b-256 9fc306d692b5d00ee6c6e075a522df1926763f9984f02a776275609031191b31

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp38-cp38-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 c644433f8fec569c2709b1242601a1c02892e29d51fc07838385a05e0f876a5f
MD5 300bce980d5367ceb2195b09e04b2d55
BLAKE2b-256 25e6504dd253904286594c9de55146a570853d2e8b776769cc16e1b3483709db

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 eaec56e2e8f6d03bdda6668df3808ffc93811ffe44e690f69a94a875a5b74679
MD5 24f94f911c23ea06cb51c1a160207141
BLAKE2b-256 f9e75f94b8f95e2cf352742894cf86c6a4a161e612872132b81a2844677b26ed

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 9e3eb61a4e49945e82d329ac9dcef29639824b0417b63dbc9231805e3f0a2e2b
MD5 7b53df3c8b237203b5cdf21023751083
BLAKE2b-256 88696d3170c592c4bc80660a9c8a7b0303f8b116650d424fe2747712c3e8faf7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 4d077cdb5a6527a7b92e855ec46a1a455dd9a82beadb6f033516b5f6fc149354
MD5 56986e7705297b3da49f1533258f7a23
BLAKE2b-256 f44df85a4a7187505a470a5494f0df13488eb20b54f1951c84d7ba02fded0b61

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 82260f895bfa9438bc0b852770283b20b663e897952bd9ea316097373f45c333
MD5 b32f0109af4c8bc96c4db190c7a04e46
BLAKE2b-256 18812544ef9a69c83c690f8c66d5c53b1307771e1de187ec6104c8a710810bef

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 887282c5618ff4692954ec68f6828b75647852d38f09d8f651549999206953c0
MD5 6360ee08db90dcdf1085d6faf7d94c9a
BLAKE2b-256 80ecb97a030b42268ce5552d876405d5f348c3d6298ec56dea9837263c119ca1

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 febff9ba3bf496aea8ad181b363aed1b9e0ffe8c404f76737394da0898df9663
MD5 ccc9040badac494f4f5188ebba35ba9c
BLAKE2b-256 2fab654e3e4fa14d3a956641f176fe5c8966b8e6cb092909c98cb9fc0f0fd667

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 11355ffd91b7c17594198af20cdaae9c8d133edda984a35aa59d766f2b4b7c63
MD5 4be3f42e8c8d21444e7c20e960f2c13a
BLAKE2b-256 8ca06dd6a32b7d6a4cad2dfabe71365616b6e6d5816d6b1e79e4ff488379493e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 9497afa004af0c75ee8d8abcaf92570703881f6d8bafafd52995881e525a8ec0
MD5 6e769a4edb8de7f90df7c2625161a6b4
BLAKE2b-256 d298d375cc8e9c55460dbcfdc1176f57d9422919b4b312f14a2e49ba01a87aa5

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d8c7e34fcf16c9fcd63a675d293a2587b4de96fd3f8b4f08b2116794c5ca7e36
MD5 9b636ac305467d9b255c18bfb86f1d54
BLAKE2b-256 d8dea4bd137693b2e35190b515a03ca39be8c8033cab31ad54f70c4a5475155f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 fafe82b3269f3f4a82a9e567db80b3491d86b630ff42d851367016977bc10fd6
MD5 575092033dc1af837250bb37997a649c
BLAKE2b-256 a720b0661191fbc854735c5426e6c80ab722a39f242e96808addeb9af1ee17e7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7f719c2445263517ff8def968802738cd4e0d35e09a2a625de182f92f74d1201
MD5 a69158f5cb95ca10d7a378a88badb025
BLAKE2b-256 a200666906556bbbc3360e08598f6d0a14d038b13fa64f7fe582f88527fdec49

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7fb8b7a659dd570f6cf258cce47cc625af105709143a5794a498945b5aec45e8
MD5 263caa35ce6b2ad142122f5a3c8f481f
BLAKE2b-256 fec2711518950f004b4d5fc50509c3f9fb4a245293c8948c12c418e0710b8856

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp38-cp38-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 1fd5acbbb65b3811ae487df33b6d2a4e004ff40185dbaf8eef7875fb2863de48
MD5 751a0b95918d280107e3b69b1ec4cd14
BLAKE2b-256 98295624e3d8700f6fd02d7c5e0e68c77468a77271c2079a999d4fff5204cfbc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 6601b8ec2b0310596c60655a84313f2dd8bc43b6a8561fe79c7e82d9238e113d
MD5 4f9f4da9d0eb0060a546171d465e1b2d
BLAKE2b-256 d8a22efa05530bad68edcda48eda868d314c2a3dfae45cfcb1f0cfcf8894246d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 64.1 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 18625a85f6cd34c1556777640f7a6a933dcd67036a2bd71e7ed77e1c7e198e77
MD5 022f0f9ffcaee0313e13fc014161800f
BLAKE2b-256 f2216dff2edf8ee2c33871c50b5cd4eb5273f6db0205e355d51923d83ef5b15d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 dd6c75059d224c62179ac39103d3f79965ef80489bcbbbfb269c0da153ac9bb3
MD5 5a3f5b02c97a25592365c402cf2b1354
BLAKE2b-256 b08a7dd13e9ecc71c8f39724525bf6df1cb7aa594450981f5c9f09a85827c5d7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 d180cc515094c0f387157dd8eb4ccca1e9e80160b5c27493ef356ec3f4f2ffb4
MD5 172f18207a8387337d45a4c02c464a38
BLAKE2b-256 2e649da3e818bde22d74c831c7c28bcd3fbed80027f9984a9cd028b736fd3441

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 b4e8d98cb3465a82d74f973be52e204330f132a01dbbdb0b14b7e2170dc6828e
MD5 000b75906891f9767e34ec39f180a427
BLAKE2b-256 39ead13878089e280fc33ae542c2001b823d7577bb9febc4fee3801a14b3a352

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 8010163a4be0c14dae1f927af8425a05dc95570026d275af8b12e434914c94e1
MD5 ccd0fb6458c0bc20ad3258c9cc17834b
BLAKE2b-256 7cc13cfcc816b3ef5080315a3a17bfccea36e9e2159b07aaf9a9ed6ed350005e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c5a6ef3faf79d967c974da881742fbd64e4f575d950c71e9ae84fc9d312441b4
MD5 6af5c096be83b431363233dc92a8fcff
BLAKE2b-256 9832439bd2f0fa032053f9eeb71ab6692c3c4a8e440c75cc6ab14d3a1a5c27d5

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bf5d6ed779915757317f47e60ab01ecc876ff359045bcab9b76324a545ecc86e
MD5 8e31f677a2566448731d39c395ec64e3
BLAKE2b-256 2309cab1cf2c75dd67d9e59b4b86114a676561d370782005d06abb66a924b2af

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 5eaef97276e6faf4deb67a71ca5e8e4c6f6157fa51603a53d66db5889c04b6f5
MD5 9ec9eb35d8fd559a64d0d7dfe1321b6d
BLAKE2b-256 8fbd55fe50db96f6a5a9df23b88ebd5386fe1837e6ae9a34a1c3e735ea2f1381

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 6ed2310a6bd1049646bab3e268cba2e642161fab2de58758679abb90989c2e28
MD5 6fbfc8e6f153bc6916e932bfcb1731d4
BLAKE2b-256 9eceb6911a3a0e7ffaa0b61042ad6c41e3aebf5e61e8b8c713f7f8709a7cc886

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 29981d65c9230e7339223edd3908907cc50962b1001cd7dc3eca352555c0025a
MD5 ea2c1a71d83f97689c4fa41a27d90e85
BLAKE2b-256 7296af711989cfc565c97380c2e85883008b7d2c4c92d3bf5acaa0a96556bc33

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e1ef7a62e060bc9ac5e3291a2b45b9f9f287677e4245c387146d0a152d3f21a0
MD5 de8d727c8df5ac7b7f1d549dd7cbe576
BLAKE2b-256 d07df9981ee108b7dc48abdef4c90e4f949f220f05c55b263cfa61402b473542

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 815eb0deb3a5a29edc58ad1742e17b7412ed01496ed1b72ca83601a467c9e61d
MD5 813967d256ea2c2ad53fad1098feac40
BLAKE2b-256 00e22fd55015146e96ac77482c2e4ce6f39629bd888afb7237f15da3da9459e5

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 82c110c3ad05e4d685dc252bb7e7ec1da59f75192df1439d86c5deb9c4964c0b
MD5 d1637eea8377a6e6f245144f8c4c8582
BLAKE2b-256 af8e873a8536b2fca0ad78518e8c217583e81c4ff043fa6fc4862028f9be58dc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.2-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 64.1 kB
  • Tags: CPython 3.6m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 7714a009034d28405af776ddfccbdd6bb2ac657eede5314ddeeebf73f1b003cf
MD5 e9baf04614953c4ba8abb3189368ec01
BLAKE2b-256 8e68af6458a692b924b5aa4a48a4c8c16f7c9fba47ee69a9a1f3cdda62c6539f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 eeb96a6d166444a8cac4a9d62198cb891366cc3b6404c8b5dad43f0796d3fe28
MD5 7abb372bcd671593107377ace82a205a
BLAKE2b-256 0422b7d582056e8b0bae43ca9c5ddeb098a47d87526369783618eb59d9dad466

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 d3ba708e8550b30629bdfc4dd625d37a2404c3fe7e0adb673d6846ae97f0d875
MD5 36a0ce78130d7ec720f9b203cc16ac5f
BLAKE2b-256 fa533b2982be9b1df5b69a81cb79e6c3ffc13d8641fad2c501d6e2020cd2b40d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 6a6453906d62b337d007974f7611708585609986b7a32e08d08a0bdac595f36d
MD5 49c3d8250819c92f06a0d4166a2403a6
BLAKE2b-256 10f10f941db90c2879034a849af7adc1341355780c202a92071f005edb8f3ea6

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 e3a696682c5c560114d9da1787f3ad1caf285e8c1576600e629206b6b54bdcab
MD5 4be852c7684ccc0e6232514f97e06d50
BLAKE2b-256 e4116d32b7f316688e5271b2146424588cbc623d7bba8131800db9b1e60b7ae7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ae7e526bc49cb9cca0779a6cdf24a0077792fd51bf0c4e2b9c7793f16d9b1ee4
MD5 f4363b66530f675816d00859ba1b20dd
BLAKE2b-256 dbc89f2b7d55a02380753e20891c4c0c7d6e45e3f04f08ec3943c510fde519d3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d4c52b5336b81018a12f9544d06b1d9408bfe7ea6705488cafce959521fdba43
MD5 b0ca243f56195a0a987032dcbf434e60
BLAKE2b-256 ce02fc1f3756f2890917d6c6007ed5765399f89059b64a07b0266b64b3f91127

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 623037452814cd76abe088275bd1354a6bec2d650bb8b192fe31e2ca5de014e2
MD5 a1cb863906bdaf8ba00239e85972abdf
BLAKE2b-256 a238ea9f15e80cdcb69049e516ea55319de422e70f7abee29b36c6388b0515f2

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 f11031487578cbfa6fbdce4e0d7cbc491b37c1d3658cb35875e599accd05f92c
MD5 f3fa20ad2dc87a9281985422f1bf8f7c
BLAKE2b-256 a400c37d0f664d9aa0c7e818c85e8ce233f7fad8b03ae9ddf0dca6d29fb9b1cc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3fbd91f82cbfdb0e5f06178449701a0ee27c1ba45aa0c2dd390e7178c648388c
MD5 de781fc550285b89d89633c618a7898c
BLAKE2b-256 453009a91d94a72f7b713f4fcc72afb3901aadd8d761a0001ba0c3b5457ff928

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 dd35c8cdbf4cdcea75c445c254ee68e548ca8873a201501efbb283212eaf7c6b
MD5 7900f767fc6c9f71fd247e7ddf338340
BLAKE2b-256 3bc93f22a828f26d7b200f67fe394391ff08d52187cd1d6b62b17ed18044fe19

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.2-cp36-cp36m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.2-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 90be38bb7fd71fa1362eed4a2e7924ef2ab48fd2f1e37bad4f0dd3c14cc9306b
MD5 1b9afa0fe3cacfc40f5186f27e3f1a66
BLAKE2b-256 a7afb9512e0c924e47f2fba10cce37170edce2d252ee68c0611abd8ac0aa586c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page