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.1-cp312-cp312-win_arm64.whl (64.6 kB view details)

Uploaded CPython 3.12 Windows ARM64

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

Uploaded CPython 3.12 Windows x86-64

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

Uploaded CPython 3.12 Windows x86

stringzilla-3.9.1-cp312-cp312-musllinux_1_2_x86_64.whl (255.1 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.9.1-cp312-cp312-musllinux_1_2_s390x.whl (194.4 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-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.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.1 kB view details)

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

stringzilla-3.9.1-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.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.7 kB view details)

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

stringzilla-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.9 kB view details)

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

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

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.9.1-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.1-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.1-cp311-cp311-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.11 Windows ARM64

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

Uploaded CPython 3.11 Windows x86-64

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

Uploaded CPython 3.11 Windows x86

stringzilla-3.9.1-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.1-cp311-cp311-musllinux_1_2_s390x.whl (193.7 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (258.9 kB view details)

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

stringzilla-3.9.1-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.1-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.1-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.1-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.1-cp311-cp311-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.9.1-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.1-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.1-cp310-cp310-win_arm64.whl (63.3 kB view details)

Uploaded CPython 3.10 Windows ARM64

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

Uploaded CPython 3.10 Windows x86-64

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

Uploaded CPython 3.10 Windows x86

stringzilla-3.9.1-cp310-cp310-musllinux_1_2_x86_64.whl (252.3 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.9.1-cp310-cp310-musllinux_1_2_s390x.whl (191.2 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-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.1-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.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (218.1 kB view details)

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

stringzilla-3.9.1-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.1-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.1-cp310-cp310-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.9.1-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.1-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.1-cp39-cp39-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.9 Windows ARM64

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

Uploaded CPython 3.9 Windows x86-64

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

Uploaded CPython 3.9 Windows x86

stringzilla-3.9.1-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.1-cp39-cp39-musllinux_1_2_s390x.whl (190.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.9.1-cp39-cp39-musllinux_1_2_aarch64.whl (202.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-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.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.5 kB view details)

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

stringzilla-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.6 kB view details)

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

stringzilla-3.9.1-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.1-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.1-cp39-cp39-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.9.1-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.1-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.1-cp38-cp38-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.8 Windows x86-64

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

Uploaded CPython 3.8 Windows x86

stringzilla-3.9.1-cp38-cp38-musllinux_1_2_x86_64.whl (250.2 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

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

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.9.1-cp38-cp38-musllinux_1_2_ppc64le.whl (212.4 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.1-cp38-cp38-musllinux_1_2_i686.whl (195.7 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.9.1-cp38-cp38-musllinux_1_2_aarch64.whl (201.4 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-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.1-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.1-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.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (205.7 kB view details)

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

stringzilla-3.9.1-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.1-cp38-cp38-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.9.1-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.1-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.1-cp37-cp37m-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.7m Windows x86-64

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

Uploaded CPython 3.7m Windows x86

stringzilla-3.9.1-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.1-cp37-cp37m-musllinux_1_2_s390x.whl (187.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_ppc64le.whl (210.5 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_i686.whl (193.8 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

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

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-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.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.8 kB view details)

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

stringzilla-3.9.1-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.1-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.1-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.1-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.1-cp36-cp36m-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.6m Windows x86-64

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

Uploaded CPython 3.6m Windows x86

stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_x86_64.whl (247.8 kB view details)

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

stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_s390x.whl (187.0 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_i686.whl (193.3 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

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

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.9.1-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.1-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.1-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.1-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.1-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.1-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.1-cp312-cp312-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 104d542400ebff7889e7ea81519ea6c82d486b2244793f30d83ce23e412d2fca
MD5 0bbd1d44fafbd95cba1097961b40e8cd
BLAKE2b-256 a14dfdb0599d80b69337864b655ea0cc8e982b28f10a868d26c9417a1dc333a9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 409645c4f4998ae01f22e75b712b7995c925dc7a41a0bde059f0edd03ee5e9fb
MD5 2e1a29e3b23699cc54dc04ad536daba1
BLAKE2b-256 72748b421183731e5b9277f3f0b621170b0d0c47e38e7a0dc15d591d7f2ce209

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 515093c78e35c2c524867a9eaa9137baecccb168b056b168944b99ad549bbd4a
MD5 7ec03d796115abbe14f4396d1287cb6f
BLAKE2b-256 4534e6c833cc53b1a50ce899203cad31db64a5625e6b854da0d72acc4ccaf201

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b1d577d783b79b08cbebc5051b54d84719a62e33a647840043c3719b579246ee
MD5 ead26e1d1705f4e68aaacaea0c5a63ab
BLAKE2b-256 a77df3886c1a423f5dfc266bf9c57ad463d878adc4270b4a861ca6f694d4638c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 8698b7ddcecfdcd2be4da7a1a5e0ed7e4ee95c4fb0c60b6ebf3486f8c289a162
MD5 a9b6a235866f4816cdf7a59c2fdde6fd
BLAKE2b-256 3798c19ed2cf88febd227a56e0e0f106b98fdd64f35a68c6a959693e0b722885

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 a121783681617af3b336edc5ab8996af05d51cc357bfd122bcdf63f4b4897c78
MD5 9798804b16437dc7ecfebdc9fc62a086
BLAKE2b-256 7109cc5971beb8b6dc9ac68638f0ec68eb71d1b631c8604ad619c05f3a39eeed

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 056478ae1df1fc030246484b2b4e4b47c3bd9407922130a2c17f0cecd52e028d
MD5 83559181e949649b09a7ce775d374851
BLAKE2b-256 84c817ce9704692ced413ac1c82b95b2494d2fca75606f1be7590acfab63c1bd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2a529894f7678db3a7496e8dccc74f69bfae4b961b2c2c2c31660ca8ded144c4
MD5 d2ee50e4c26b873fe45c56e6bbcfa8c2
BLAKE2b-256 f74f0a4ec448c0ac6e05050492abb02eb438ab96a2eca0ba830332b283d259f7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ef643e038988c05f1bdac07e9fa951542fdec39811faf94efaf4b439a036283d
MD5 631be47911311b93129c260c0f507103
BLAKE2b-256 55dff4eaccd407df2ea4cf072d362966a328d3dab65c248e3b1e27d30491cb77

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 ebf427182b1d739db57f1d2ae7261e509f06fea61b8ec8bb33ca5f81c20f62ba
MD5 ba4234d16e4c7c0acb1b25d5c675669f
BLAKE2b-256 aac5f916de545194d89ea769ba866222ddb81cd761237ab4e2d434812902768e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 ab7f09c28ea01eb894b0f104ccd48c04a41c78270057eba1bd85616e7b8ff236
MD5 084264edb67906af233dcc52232c7521
BLAKE2b-256 33c7d918c3d6874067d346d3df6523af42401078a419019fa8431d529b922667

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2c0c3b2708944b35789a585e169629a1f0804564428859ae0cf430fa72cc4355
MD5 b3fee17c86cce6353bfe44597a5d65cf
BLAKE2b-256 14c0a511f257fd9b38d17dcfbbac8fb9f404de7d5887d89db81b7684f4a2876f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 11f82f8c65e9365ceaf3305ef00597088eeeba7a3119696454d0ffa257d09c87
MD5 203d26e878e6383ca241b80c72693787
BLAKE2b-256 a2f8a7908fb5ed0e0ee602f9ce8015d73e04ff670c40cdbcfe1271d6367b6f5c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0d444a199d46601100bd4f0b9e32848e2c56e00bab75d502afa404b6252ef831
MD5 55cff9def735c3459db9c57d821f18ce
BLAKE2b-256 345c8c411c87e8be7cb9dc6f2ad4da8ac63d85d1fe4f3bb72d77b92163fffb9d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 76ed4283b3416f19f678c62161b85f429de5669b4e1b278fb4217d61c36998b4
MD5 bbc7ede1f567181f39e57b9e893fe0bd
BLAKE2b-256 879fbe71bb97ba4766f421832533804c8e7e75330c792f535a5341e9686d488d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 b49999788bcc2766f6acc84424e46eec20ef8df58ec72203e0d45c3d23426f17
MD5 0a72cd35b602b583bd6d0dc9ef750906
BLAKE2b-256 9b82bd153b176f91b82c1adc3a146cc6a433d1529a0c8c0181e5f6c0295454f0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 2347ed335e1244581936c6d5d825947da3099355ed79e1d1658676ab649dbbd1
MD5 2bc996f89059e976bb5f611ce743e40a
BLAKE2b-256 7cff27a5f4b6f4adf791e8e69410475c59127780273a40547fc5d91005c05aa4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 18eb0f5bf88725edbd70e42813e6083f000d6eb772f03ee16d6e4514bc8cfc23
MD5 62743d3f4b833136e11f880b83ffc3ae
BLAKE2b-256 3d5fdc2601486ba5daf72b5de421b4f10eb0299f61405a5bf57f2dffac48754b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 1bea699261dc6e1015f4fa3b69987a719bf13e25fe8ac5671d69216cf1e8cb7c
MD5 0786b1a7ac816283222c4336bb140ee8
BLAKE2b-256 bf34f3409e81c357f31f6bfdd55f5a972ebafda9f64295bc6ef9eb50267fdeae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a53b4f307be9ae37cbc868cf7b65d0bccf5951317bf4d57fe110f67141728143
MD5 4398ded23cae55d232be0ec865557db8
BLAKE2b-256 45e5d7b3f2261c9d00679a6bb19da4193f7c4b6ce389f7a9981b95d287339685

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 143c4d6e2df138de5b844754885b36c6d9cccd3cca95839170e32edec94ceeba
MD5 2942e3e76ac5ee20671113c7478023e2
BLAKE2b-256 fbb54387350957c30ca114543a7ec101bd72ee585b7f9479b388e49bfc1adf80

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 25031df5ec9d5858d791ec348267b1210d6ae98e25231ac83c2480cd01a9831c
MD5 00530ee81950eb22e05e9102495e71e4
BLAKE2b-256 eefd38013549b351c4724cacd86e10a66006d4f44a60f4a1bb33a0a2cd6a6110

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 7767e160e45802b02ca15ee603314a15c3cfc2686ffb11471a7ff5084beeb681
MD5 c3ba3b63089a0104312113513ca5aac3
BLAKE2b-256 3bdbfb7267bd9a7f7672ac922313108a4f4a6a6a608fa7ee9ece98444b968bc4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1d87c5701378764fbf9ab1b71f1282e1e1caae91cf19148a416f7719fb39f6fe
MD5 d1a2f7b440cfaffdf9507cad1deadcce
BLAKE2b-256 b517ec096f3d6921c3c1625dcd31f95274ed805be7e54868e73af21014e37ca3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0e3eec688fb75fdf722ee7ee6744a7e98229b7d0fb947659fb44206c7605cbca
MD5 f10ae3e76f6407a60646f1dfe096c1d0
BLAKE2b-256 fcf005538fc27573f012ed96566c193de3adfdf4cb966bd8a59d1f23964726b6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 f9d559a7190bbc98a8fe6df9be4fb217b86a94581909e6446c78ef2c4d74b117
MD5 ea738afc7643fc20835df1dab8c80760
BLAKE2b-256 a4231459ab846e1c0c2639ff2cd11670d0b098743bbadcf82d026a3a7a79768f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 12ae9c9df8817e004e30735fce7f32d8d8b47e9d73d44932049017c8384db012
MD5 3e9bdc559b4fbf3f5a04e1e35168c936
BLAKE2b-256 7c1c5b7fde791a14d2dcc9fed2b73cc7024488d07852967054ff0e9acb6458bc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 292d11c9fe5a35cc0f5b394c22b4d2e09f9e7e89d4e7057a0b29f836e9559b27
MD5 b0a5cffb15606868418d15b210f9e80a
BLAKE2b-256 5aebc01ec77d8dbe50c16a88dca52f965a58dbcfa12b6322870da299295622f0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 66460fff4ff0e7cdf5e44a1e51126d1e0f92d490df161215ee97750b49991177
MD5 02e1efbd1a0d58b8ac153953b47528b3
BLAKE2b-256 37da89657f01e0483ce95412b4da887478d310ae2f897410cf1bd08ab61990bf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6828255dfbf25fe367488e85d71d1f10b98cf3062f7c02ac9cb6c51a597bd6e7
MD5 6850fbbab43f050d4e5f08d0c40406c4
BLAKE2b-256 ac38b71b978c9f7f41586bcc2a6ad189364a6635e2c8b16a7f4bca13ccbdc829

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 b55e9ecad12660d7252d9be928b1d22d504f3859cf2685f8bcec15e856a3f6b0
MD5 9ada6384c354ee850b68d7affe7e90c0
BLAKE2b-256 e66c266376bd28870ded30455e4162bed6e9d27cbae2ee0a8af0580b748ecb90

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 05b47a091fe730b44529934df51ff22e844b0c8b1654077d99c8171b7a2c5f51
MD5 47e0a612cae73ea2488982d07770d979
BLAKE2b-256 01f2a112911d20ccdc7f5f3a3b9411dad07b6a113bb5a0dd0dba73be8b6d50e3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 ffc4029c51077b19a7a3c4fc63d6635946ba8f91fbc876c4fea2a12d9f63ad7e
MD5 ef50ac6e821184fc611f0e0f61011122
BLAKE2b-256 8b5b8a7f003ba41d07dbb8253ee7bef90eb01dd078562a8e2b3f421d1c996888

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 f52ef4cfbbe34f901d4fd716386ae0e8c4b06cebd892c045e761d4e6dfdef66b
MD5 faa8b3b51eb8863f201e4a1939df3df1
BLAKE2b-256 9a7a2cc8586771d270b25aee73dee6c8e15cbbc20cfa9083e1237d6a248a9b0e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 42bdbed9e0f71df19f0293eb1f8d23b59f1ad518a4b14b939af66a0600c731f5
MD5 df7cda4f4bc3e7712b9843c2e86577d2
BLAKE2b-256 d8d2f8edcea1ed9af5268afa2498ca3c26cdbb9ff56f435568f3cdd3e7f02d28

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 84924d61433d14524f9a888f63001c55e91c8cd3582fc7e730338526890f3cd1
MD5 94c52a80403f1d9830d3d27adf8caf64
BLAKE2b-256 631036f3d417b9c4aac177b5e2c3193923ef75ca412743e452685c1e122eb01b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 30e14c4d1482e274af8838da0189817b1e89288458528ed250971e0c4e944731
MD5 415164369ff72f7ef2034ac36f99f407
BLAKE2b-256 2e81ca00f91c828251dde2f4dce344892a0ec1c50f98ab5c5d02d13d59be48b5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 6396a93e511e32ff3ec4dcf8bd5391a3c767cefefd471a503e2febb84a0a7eb3
MD5 97e6526e90237a6a9438897d492d01d7
BLAKE2b-256 799d3745d6b3d55dfcd45e8700c2daf15c436f0ba8076bd9cb8b7bbf09865e45

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 1a9dd3adf9f1752649b9b259a04b4e059bbbd7a3687ee9c951ea2155c6b92b53
MD5 44dd5646c472ab96ca5bee3642e39aba
BLAKE2b-256 deacabe945ae2247aff6da432fa4e14717f6905320d99a4b869506b8e85f0dd7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c00387c8e472097cf0d3ccb77df0abe9e00d528840515b2086fd12dfcf73dc1d
MD5 3a684ddde495821eaa4049cd0d447fb0
BLAKE2b-256 c462f5021f76441b05f5a74fabeb930a879cab87c848d4f5386ec57f39f58f2e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3a980d3d73fdec110d7b7b4a57154d7a1988ba7a00c2917c866aebdb30bce43f
MD5 bc8e2a5a7931ab0ea983f15477181634
BLAKE2b-256 26bb52f9165a3533a26bc427f34bfbc7f99b1cfbbd28e546a706321bcf2e8e31

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 ef2463e6084ef4f96405450d7e64ab997bdb3c61e39784c5b48cb137ba8ff43d
MD5 4c1ce19ee0eacb4bcc35065ce17d4827
BLAKE2b-256 a2c4b950b55935078033c58d6a898aa85d977d9cf475a27f59abf0ba1b46c6a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 f6b9ba5a14464f1ae02d453dc197feb5d750e474658a6b322831a5a48d386d72
MD5 35344ab70bdb8e56942a71970abee194
BLAKE2b-256 56cb83f9f42f50ca0fa2c3b4b85cd8e67bcdb9dd8a56a48372d8a2d697f9199e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 324383504d6b52296a8382eb87c08c6e99d1e2055b714cc8c95e1e0b2f50f28c
MD5 95fd728df5a7a8ba97420e078f7ee385
BLAKE2b-256 951a9e32d5e751f50a0f017e8ac16f1e0adc5fb425d0817d83b8c8b3edefafed

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 0e7de0612ca87940b44b17baedfbe4bfbcb42e939241c261619fef0480b38dd3
MD5 91230faffc9e08d92604e7deef9f2a82
BLAKE2b-256 aa096a13ac5f8e2b63fc899264ce449ba0e85818b64d0f8ca37140187e773905

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4a93f23c9207208125c0d025dafb160624692007966ed7cdcdb3b5f92cde044f
MD5 0e89dcf2158ff6d00dd3c6eb99d3ebad
BLAKE2b-256 99e4e38d66b89d784422ba6ad89ac6cf8d2ec501d229b48cd266d34e800792b4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 612509fc1310e621e9fe30f0169a37d495c041a87c871bda74d0ea0883b16427
MD5 7929b07862b5bddfe7644569d42a971b
BLAKE2b-256 62763439aab12ce9a9fa3a830e3e315c80ec36ea59dc5ad8d69cc846d17e8fd6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 1e4c09717362dc7afc027aa322f682e666007bf0f90c5ebb5a0975d9a182126c
MD5 1c89c0304ade4fe48331e2ef88fb1de2
BLAKE2b-256 e2b6f23d8fca90d99e001b321e206cf3ecf391cb450f35d3d90685b423cf7bc7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 ca547b88265b1700345c3adcb04a361c5cc185c83c42ba28dd6b6771734a2ed3
MD5 1a733a55a8c4f1ba85951fdb85fcd18f
BLAKE2b-256 a50590139516de44cd0ec71a0979533a2eb6811b4aef1c9d0c036f4e9dcfe0e9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 5404e530a84881e6ab68ba81c36c6ae8e3f6d5b7d5b791483b6da8432c73bab3
MD5 d724cef116a6e67592bba1d7397829df
BLAKE2b-256 1f466a310a3f3d9983d9404ea2208325236c36036415a924c890e21cd4186edf

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 8b18ce394bdf759896f4bfb892be03a2440dc90f10789196d913f9fdd1e7f474
MD5 f52db2292670e3f03aae8650686c531c
BLAKE2b-256 e475cbce0e25b69f0d946971a4f355f09a9e179627ac1fbb7f0bf7ecca6da902

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7baa2e179753e2431813a8dafddd70e7ec7ebadc3df33fbfa25ad90de3c98d80
MD5 d24148fb234a4a4e970dd16d19607465
BLAKE2b-256 3ae3260675ed310bce075f313a9b07d9e0e5e097c31e27bd48163666eed1e57b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 17a4fcae777b48195a768f85e641d2ae00be0f80b105df932c7b297a9f1dea39
MD5 c45dbf1a0d232a0d8a4c9a9518177a0a
BLAKE2b-256 a21a32f4eca2bbea81485a79cb1fb26b6c13146098cbc2befba7c4913d9ff37d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 67e62ffc3a8e0b791d597cecd93610c13e11664d108f1fe48a921b8b9e27a442
MD5 0c9441256efb83fd76a5e7f3603f12ee
BLAKE2b-256 308153b5a82d72af0a3c251b22966b3b51f420a8f2f971a46c06f01d558a2d0b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 4710351c5c2983914aa3baf44ec4bc7e5cc4f500227d93395f2bf449c62ef6e2
MD5 0f5c8aff1983a314a2d1bb1b010ed5cb
BLAKE2b-256 39ba2dfbf2f57b6c29d6f7d9546b30ef28a483b48addd589e65371c7bf2a7809

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 486d5b1e8d6bf428555bec205d0a2e63afdbb94f0a3846d359cdd413a1812033
MD5 de41e459b8fe4010ba4ffd2c30f3f775
BLAKE2b-256 2e7a04bc9272850f5aee1382d9857fee2986293e827405367f33de52cf2e0e84

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 28041cd027cc1655aacf881823c9839a50e5639b5e2a1c8477d8f5d67efbe3dd
MD5 f0a941149a28bb94a8238152fd0459ff
BLAKE2b-256 74735bc5c440f584a170b1a369c6c375ab8210892e3deefe9f1f262a738b401a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 f598ac16f851183879f4e2f205bf40ab14560f73de38d889c5667711d812403a
MD5 8ed38d2f521dfcfd6120025e53df10de
BLAKE2b-256 625a1bb657a80b3df6dec3b17c1c349682efbb4400e80c289d92d206e2df80c3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 b1ae943e50e6ceaf0fd674457e15f9041db932d077a4450a0d7b1b5e23c960d2
MD5 bd15758a4ec5d4e451a883254962446a
BLAKE2b-256 3c6098230d052c9f5bba7b8f621ad0733e28870edd122f6df960ce4b0a260951

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 48550e82159f4b54b6e659b6e724ca11f63aa5dae5ad58fb5ab56c28d0aa735c
MD5 71ec7a27c77560ff7bf7f8cc90073717
BLAKE2b-256 df0c1e1218d1bce62d630909226588976fbc059d05e35d87a525dd2b95563a37

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f9538259627938ba6f9e02b37fbd7cd7ab36284ed1a0f144220f3646e127b369
MD5 c199bb556db04384231b102202428ef7
BLAKE2b-256 847b5ef0f2afd77a8c273a3d5175559bfe0e7b5de0b84d53951035188fcc71d5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d8adfeaff1a366e6e343b3fb029c22c1d804e08f6ee631f0f972d9cfee9d62bd
MD5 d84a5bdc9d6a93933051b15be1e80fba
BLAKE2b-256 b4f0f43587bc0cc7bdd904ee375617b59698d274c72bfde4931e2c275ba9c3d5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 be026f50df686790ce08346c475f20c56cb28b632f11b654843c3fdea26e7048
MD5 bb8995128274d0b036f87e979ac72c31
BLAKE2b-256 40b1d14d71ff6658f916db410ca39ab7b771909c5275e82684f013ad687f2008

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 23427890643175dc60b553261071bd915a8c8dfa1eda9b7eae13e232db2b2d53
MD5 4b13183f6595cdc90b752518cbaf3637
BLAKE2b-256 6914bd7598e88ca8381ea2f29d8c72fef61d4107217279822963219339bc9834

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 a3e4ea4efbe041b32f477b870b8e14d6e9e92c4c68bc7c8d80f5f3d46827ff56
MD5 1805cb46d4055b422c0668cb3b0900e8
BLAKE2b-256 7abdb441f4066d020efe172b23afe32d8cc537739826388659bc8baf7ba6f25d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 6585af9af209e3f14fb891013280e532518087246a58107886ed346b50478b0c
MD5 47a7c04a909784dd2d24b2f3b8c42a89
BLAKE2b-256 a6462f24de44983d3829ef65a71d560b64fd51d742eb8bf549aa9f8fbd937f63

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1e28269a71a44383d7be7f030482c3c46280c9e8c2f7473551d3c61699c319c5
MD5 e20e1f412f1ad6f8698793d9280f69b2
BLAKE2b-256 ab0c0f4be4f78a807c18a55f3b7254a23b171e1251af58ad49cd68af658789a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 4fc6a43d19e42cd806420e3a4064bac2f2e1335f282edf6b4d311a9a4b58f7a0
MD5 1c19e067aa4ed2ce3caf7274f5c78050
BLAKE2b-256 197568cca0f8c653eaba0e8e3d21d2cfc7824638f9e7852dac92b0726f6a1b32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 5129e5d6a37d1ca734ee4552b444ec5eb6957b3e78f92ea565cf451708b0d9d2
MD5 e3703e5f530eca320ce0f174978db98a
BLAKE2b-256 c000a6cc4dec9f3272bd99a127f4a97176dcf38e6c01f5c0ae28a5ccd4071530

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 6ab419a43adf3373e463b2c81ee946f9c16fdec6c5ca48c9db38754f1d1322f4
MD5 3401d1a1a0574facc1cea0699264e5fe
BLAKE2b-256 9da7eb943ca5e6ed6c5ec9ea5dfcea0ada6189e8b3a1c8cf28aac9edf458ad02

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 64bc740a6055017253d1393d4425cde62d01ca960dc53ccf8215978e2877645f
MD5 3dc3536fbac753bd46d0a44123b1076d
BLAKE2b-256 9ed1b5fb971e50b04cfc5463ea8a80d83ebe5447eb885ee9baca13b1f7448c7c

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e30e0a355edf6f67cb4f380e510deddaf394207f0ec25d911425d4baf539425d
MD5 c1c5dd0fd6d644f37d562ff7be5734bd
BLAKE2b-256 b2353d7818ca01593e51c78fa5b3d592afc721937771768d884364b12b34ea7e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 533bba4140d79c63415a5a94450f4502ef4ff2cef92b43b92739b37fc9f427c0
MD5 c27295b2e33d6994c99e063a010843c6
BLAKE2b-256 36483ca6fd051de3c64ffef7b3790344a5c668d15466a8f13f51558f06670920

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 ca87c12da85360c44aa257a61285eb04067872c058002ddfee8eb3c6afb91361
MD5 73c403737f0cb0681b48daa333e8dd17
BLAKE2b-256 7906972a5eab63710becffe2ad1de24e887c7e95a166c07a3eff2cf417db7a73

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a24092dd69418928b8eacb523c7afafcab9572e00ade389a88ad6dfda99885a0
MD5 9016416b7945c71c6473d37405481c7a
BLAKE2b-256 1a76ab9382cf8d9027f644991696bb84a88fceb7623ac62b0bc135e6c8480939

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9ba0c506901e348a828f7d133c638d9e3435114b24b9ac254e8cd153e7521c9a
MD5 30f5673784fe3c9b599af3ad423bbbd3
BLAKE2b-256 f19c559925633907b655f5ea0630d1f1f1a5e6d01b617de8be5b9a19e5a61a5a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5f9a716908abac1886765f03119ea7a52a5eb68f79382c1c078e37559828eb6a
MD5 79286f157dd5e6387c0da166506e4678
BLAKE2b-256 9456da48a6c6d36c9fc808cf5f2b2bfb1a60770eb943cef972cc19909ae47151

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 773b87b87d524fdf1d808fda1d849edefb58ba05b373b7debf7af503121c3f1a
MD5 31e1c81dedceeccfbc58ff5d1b4918b3
BLAKE2b-256 0395ef7831f9440249988a7c069b5e0ae9ca17d1eaf8602cfce01233fe3964f6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 314f2284a9a0f979f279ab155fb2bed155f4bc188232832c5c1aae1d0862083f
MD5 10a613ae54155d4107d58d9b360ae0bc
BLAKE2b-256 dea3ba2eb3abd1d48cd84f0507665d80a6a929198f6cbe201d19a598ecbe9358

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 db7c1d8201e41d3253ea16e0b4c27938487ababb0c1a117dfe9f3a889274e983
MD5 3b370d9e25ae9a6a96e53a8e7462848c
BLAKE2b-256 77dc5451976e8b0a24e77bceb5f04bba904cbb39cf754545b01f9e1e320de01d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 d15904614d3624b0115da2274869fc2e5ae2cb9edd1bfe5268edee23f7a376a2
MD5 46fa6a7821b0c3a898dcebafd36d4105
BLAKE2b-256 13bbd3feb354a8df75d8b15325e73068679c4615698d3872f29ce402b73a70f4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 04e6049fd96dbcbbee9ae014d41ff5014f17f54fd90b644e6fb400c8f6f50973
MD5 dd97a1a5c19f48e6b2e79ae19c4cb45a
BLAKE2b-256 69fbbe24c8dd320ee359b8220d3ab8ad48396b95f9668d7dfdeba1706a722895

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 f2764f12a09fe39631125ec1bc28895a6ab5552ca7bba702135760f6f6bea881
MD5 f0d987817125174919eda4103893a519
BLAKE2b-256 23038f9413b80abae4d8c48bf8ceb1fd177e146360b0ba3df5716b4982f6a516

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 e466efea655167789fe23db1b49f34f70d32df71b33d48efa681201cee60dfa5
MD5 5c01fd5f6f78c6e70c969471c646fdc7
BLAKE2b-256 d829b1dfb84dbd2ef7cdaf635e64e4f05f75ae0b8fbf910d18e90c0d93fe4856

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 ba7baa6fdcd1928a71f76587fb7b9865e30d9718108e651abec1b6a4573c5714
MD5 d561b494beeef64ce76e3aca1045541b
BLAKE2b-256 18272ca26c77cd09e055f21a8e8fb70ef0ccb663c3fa5aa341f47296945018e3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 9e93541413ce77f270dac3d1f889af7e42cc88b21535c61c01a62aab77027412
MD5 79c33cdab445ea39b16867a5e51f3578
BLAKE2b-256 a20e226b9d65c41686064be0e608520059723d639efae4cc7c962bae639e0354

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 02b14ba4f016ff32bee48faaed1722961882e19c08f7e828d2ea2dfeb062a512
MD5 a092c7f726d3423456b31df64c3f8f28
BLAKE2b-256 c2c52d4c42a10382a20a1309581c2282800ed2d8174915690f478172724cc925

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 4889ff2057770d2728bdfce470748a47beb04130ec530b229392e0c89b081ef9
MD5 5f7a258dbe255aaabd16181e15fac494
BLAKE2b-256 dc7911f38aae148a07167fa4442427a9bd970add8e90ac487a3eb8c800e48a68

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 8c6101166afe941b15a797efb410d9e9b3660a630282aab694bc727a4902cccc
MD5 9d10468af1b534b3713d64281557efff
BLAKE2b-256 c53d2071f8ec25ca2c8264749dbcac8277364163c0bad6c37d21a35c41247d02

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a0a8b2e14304847de457137de9946c49de3e538d0b8c1cc9a8bbc40019bbfd1f
MD5 085153769428e00275bb71d968cbf196
BLAKE2b-256 11b7e691f7b6b95a3029367345d6413f1534ee59993079db0bb0854cf79a1a71

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 04f209e549c85893c710319b3b15d790e12855bf326287c53b991af5c1d79af0
MD5 cc4e254a4bd03885cd53122c83033536
BLAKE2b-256 75bd22983ab3f5794ff2e2920e95bcab37da4039c1beccfc3576420d51bb7950

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3d0c632a1e198ee056d1b52c8a0e4bb2465c83bf10ae5c1050a1688ffef7b91c
MD5 902ab5a46870d8d7371931a6abb39be9
BLAKE2b-256 c62e9a8c46d6a720a6638cb090879fefffd5b59801b165958fae83847bd1b6d9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 ee7ae81d330f507a300e22165f2ea1a49a7d3271e0a5ac914caf01038c38837c
MD5 57c211e95bb9597aec00dc5e049c5065
BLAKE2b-256 d55f593df9fd23e43179d1895a37c06d70502a2d5bd33c54997cf227b35b2c38

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.1-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.1-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 3ce051492c7628c6f5be0fc7a58d8ef14af03397a6b781ead2d415b13ecc5ffe
MD5 98db24ab0cc19bcfc70a7e0678a60a45
BLAKE2b-256 ef1cd7988e766cb9051817fe11afe02c1e7d673af16ff3dc8bf0415a4dfe58ab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 20b33a7c375131900a3d83d980fda85fd10c8ea570beb3a8f3eb08030b5dc86f
MD5 1aef3b6247a7f7e81dd50c840b327dc6
BLAKE2b-256 2cd798a586fb08d0df83cc788f31f0a826c0e63969ee3772e9d71a3351478284

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 a6606e4ee27d16ab3fb1289c06d8976c6fe351e1359a9483de9f1e71e5081c3b
MD5 175da05ab545c1eef2081f365cb2de78
BLAKE2b-256 039c82f0e1fa6fc868f57cbc1adc457c772a5d9fe83b27591fc21a8f4d9ce52d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 ca75ff64945b6278a892cb61705f674a7ecbfee940d7506325bddbfc71a15ec3
MD5 5c64d744c9790f44957936d83e04ac03
BLAKE2b-256 181ec48241a3f232817d01e87e6d00434f5f4244059dc02a9aca255f9729f61b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 b2c6716f8d55159963c27f7df30aa62290d34df1dd7e9ff30c26f7fc81cff418
MD5 a8f8b9c84a44315a1ff6f2ff0bd12a58
BLAKE2b-256 0196a1db5dd7e609bf4e2a48d46634e0be401afe9727cc9846709d20a53f220a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 6bc926ae75e2bd0b6459e11a4ecb135b92a555f72bfd52da9bfff6bfee871e38
MD5 5c96d79a715b2b60e963d0f7d9078d01
BLAKE2b-256 b3bff21c4ba6a6232dff2a6e25580b13c2101be0983748013935994fb8a845d4

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.1-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.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3a418457fda4a1305c46781b98aa0dce9c272d139c77b3e8d6ad27604bc0fd03
MD5 7a48d8b6988b88a0447de2cbb22a95ba
BLAKE2b-256 396b8ec82a6b3f024b776ee04fc79897b6469bf85ce9295c436e16d4baf0bb8d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e6ec7a1bd96bee2651e7a9ea14a1c8164ed13249ff530a78eb91b8d9189d0092
MD5 1628265e470502124cd270f23ad4afd7
BLAKE2b-256 8fab66a6dffbe568c53e83464a206f2606539628304a89ea617c1a38a2f31634

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 afe097b2a0f098ae16d44b494e97d82ecbbe7eeebe90ece3a14e442ca35e4470
MD5 39e6beb358acf60238bd6f6214ff93f7
BLAKE2b-256 af8bdee056b69206d6251365a5be8d728f4b70d7847393d769d0161c89dbd611

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f6d52699c14fc6be650cf7aded7489e2490e3220c824c5c732bf499f6f824e78
MD5 4928a4c7ee5bfad969d5b6bd82b8ff2e
BLAKE2b-256 92d9d5e40c2b99c53bf381943b176819797177c83d9ca5053e1bb517d34d2c0a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ef549863d40429d6fcedc44f921c54312efdcdda1febb1adb2a17ec5038ae5f4
MD5 28e5866722f498013f034d0e16ed3dde
BLAKE2b-256 9a1f5979580bd96d44f62d8ca0ac2898209af7f7b95bb13f087b42960b2bdcb5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.1-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 5520b9b3848a42d82f0099ff313b11a34ea7305649fb760927837eafd0bea2a1
MD5 70ef23a16ae7869595fb43973ce8c627
BLAKE2b-256 8b058b5b47ea7756dd1c0e4fc771d761792618e71c604be17039503165a9f765

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