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").front(2) == "2"; // take first 2 characters
str("a:b").back(-1) == "b"; // accepting negative indices
str("a:b").back(-2) == ":b"; // similar to Python's `"a:b"[-2:]`
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.6-cp312-cp312-win_arm64.whl (62.8 kB view details)

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.9.6-cp312-cp312-win_amd64.whl (73.0 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.9.6-cp312-cp312-win32.whl (64.4 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.9.6-cp312-cp312-musllinux_1_2_x86_64.whl (255.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.9.6-cp312-cp312-musllinux_1_2_s390x.whl (194.9 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp312-cp312-musllinux_1_2_ppc64le.whl (217.1 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp312-cp312-musllinux_1_2_i686.whl (200.0 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp312-cp312-musllinux_1_2_aarch64.whl (206.1 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (260.2 kB view details)

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

stringzilla-3.9.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.5 kB view details)

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

stringzilla-3.9.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.7 kB view details)

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

stringzilla-3.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.3 kB view details)

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

stringzilla-3.9.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (198.5 kB view details)

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

stringzilla-3.9.6-cp312-cp312-macosx_11_0_arm64.whl (74.1 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.9.6-cp312-cp312-macosx_10_13_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.12 macOS 10.13+ x86-64

stringzilla-3.9.6-cp312-cp312-macosx_10_13_universal2.whl (113.1 kB view details)

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

stringzilla-3.9.6-cp311-cp311-win_arm64.whl (62.8 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.9.6-cp311-cp311-win_amd64.whl (72.9 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.9.6-cp311-cp311-win32.whl (64.3 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.9.6-cp311-cp311-musllinux_1_2_x86_64.whl (255.1 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.9.6-cp311-cp311-musllinux_1_2_s390x.whl (194.3 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp311-cp311-musllinux_1_2_ppc64le.whl (217.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp311-cp311-musllinux_1_2_i686.whl (200.1 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp311-cp311-musllinux_1_2_aarch64.whl (206.2 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.5 kB view details)

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

stringzilla-3.9.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.6 kB view details)

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

stringzilla-3.9.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (221.2 kB view details)

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

stringzilla-3.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.7 kB view details)

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

stringzilla-3.9.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (198.3 kB view details)

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

stringzilla-3.9.6-cp311-cp311-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.9.6-cp311-cp311-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.9.6-cp311-cp311-macosx_10_9_universal2.whl (112.6 kB view details)

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

stringzilla-3.9.6-cp310-cp310-win_arm64.whl (62.8 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.9.6-cp310-cp310-win_amd64.whl (72.7 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.9.6-cp310-cp310-win32.whl (64.2 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.9.6-cp310-cp310-musllinux_1_2_x86_64.whl (252.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.9.6-cp310-cp310-musllinux_1_2_s390x.whl (191.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp310-cp310-musllinux_1_2_ppc64le.whl (214.9 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp310-cp310-musllinux_1_2_i686.whl (197.8 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp310-cp310-musllinux_1_2_aarch64.whl (203.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (257.2 kB view details)

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

stringzilla-3.9.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (190.1 kB view details)

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

stringzilla-3.9.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (218.3 kB view details)

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

stringzilla-3.9.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (208.3 kB view details)

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

stringzilla-3.9.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.8 kB view details)

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

stringzilla-3.9.6-cp310-cp310-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.9.6-cp310-cp310-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.9.6-cp310-cp310-macosx_10_9_universal2.whl (112.6 kB view details)

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

stringzilla-3.9.6-cp39-cp39-win_arm64.whl (62.9 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.9.6-cp39-cp39-win_amd64.whl (73.1 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.9.6-cp39-cp39-win32.whl (64.3 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.9.6-cp39-cp39-musllinux_1_2_x86_64.whl (251.4 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.9.6-cp39-cp39-musllinux_1_2_s390x.whl (190.5 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp39-cp39-musllinux_1_2_ppc64le.whl (213.7 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp39-cp39-musllinux_1_2_i686.whl (196.7 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp39-cp39-musllinux_1_2_aarch64.whl (202.6 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (256.0 kB view details)

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

stringzilla-3.9.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.7 kB view details)

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

stringzilla-3.9.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.9 kB view details)

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

stringzilla-3.9.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (207.1 kB view details)

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

stringzilla-3.9.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.7 kB view details)

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

stringzilla-3.9.6-cp39-cp39-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.9.6-cp39-cp39-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.9.6-cp39-cp39-macosx_10_9_universal2.whl (112.5 kB view details)

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

stringzilla-3.9.6-cp38-cp38-win_amd64.whl (72.8 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.9.6-cp38-cp38-win32.whl (64.3 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.9.6-cp38-cp38-musllinux_1_2_x86_64.whl (250.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.9.6-cp38-cp38-musllinux_1_2_s390x.whl (189.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp38-cp38-musllinux_1_2_ppc64le.whl (212.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp38-cp38-musllinux_1_2_i686.whl (196.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp38-cp38-musllinux_1_2_aarch64.whl (201.7 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.3 kB view details)

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

stringzilla-3.9.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.8 kB view details)

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

stringzilla-3.9.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.9 kB view details)

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

stringzilla-3.9.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.0 kB view details)

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

stringzilla-3.9.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.7 kB view details)

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

stringzilla-3.9.6-cp38-cp38-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.9.6-cp38-cp38-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.9.6-cp38-cp38-macosx_10_9_universal2.whl (112.5 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-win_amd64.whl (72.8 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.9.6-cp37-cp37m-win32.whl (64.3 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_x86_64.whl (248.9 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_s390x.whl (188.0 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_ppc64le.whl (210.8 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_i686.whl (194.2 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_aarch64.whl (199.4 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.8 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (186.1 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.9 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (203.6 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.8 kB view details)

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

stringzilla-3.9.6-cp37-cp37m-macosx_10_9_x86_64.whl (73.5 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.9.6-cp36-cp36m-win_amd64.whl (72.7 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.9.6-cp36-cp36m-win32.whl (64.2 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_x86_64.whl (248.1 kB view details)

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

stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_s390x.whl (187.3 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_ppc64le.whl (210.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_i686.whl (193.5 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_aarch64.whl (198.7 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.0 kB view details)

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

stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.1 kB view details)

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

stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.5 kB view details)

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

stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.7 kB view details)

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

stringzilla-3.9.6-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.3 kB view details)

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

stringzilla-3.9.6-cp36-cp36m-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 3c65c0fe17c8fe1c7d0c87944f9f47265b182c902d5550bf634a759a9d8c01a8
MD5 49cbf1967cd7681cd3f6293ae53e3099
BLAKE2b-256 26e75e680eca21bba297d79f0f01766ee31e7dcaec752e637b813b85fc1e207a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 5d7b1b6ae6c966005fd5d73ded1881cb7337dd327c3b515f1caed040778f1b28
MD5 9eab506b8dc1487c0a2b1256d9f7b83d
BLAKE2b-256 1b066f4ee6f007c005e58fe4b1780e014090ce285b68e7e7338d17bd25e0b815

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp312-cp312-win32.whl
  • Upload date:
  • Size: 64.4 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 98b93601ebcacb566de8d8d378d0df58d6648813b4acf48e700244992bdfd056
MD5 5f9d735558333a49cebb1a1acc7ff9dc
BLAKE2b-256 6d128c0e5b4b094b7b79abcd7feaa81f94d87b2fd9a51bb8521aec711df4c36e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 4b3aecd19c3b17ca7f84a037dc66f9345801cb8bc80a895f8f836c4d84d57380
MD5 e2bf7e6904810c0c88e526ee3e17311f
BLAKE2b-256 57fe00bd574a3588d0585cded6935c28e4da19163f71f141c91fb36187af82dd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 d2f0c4e9c82eaaaafde13e7e20d42798bdc864845f34c168bf6063f6efb7eb92
MD5 c128742571d56f29453cdd8d5dd343ff
BLAKE2b-256 c99acfc0f3c161b575d5fb4f30ecc75bd63bba5ecf3d6f424edeec687ee855d3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 393ad7eb2abe3546867a1b2997408d35aad64b4be46900e0188bff006a978e59
MD5 edd0c9fcd756d376a8126d411f360b2c
BLAKE2b-256 195734f96fb06f373774b8e9d6b52282743a565bd69c52b3a6fe7af1b32d4038

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 f1285b8d43835da9cf389ac1afe1b2049f0f2c263412651d6304366979619592
MD5 0dc1bcee5dd4f5c476892e7ddd43f713
BLAKE2b-256 636a3344a9e2bbe87f232a7c89fb44ca345469d5d293e99aaa6942e1e18eb0b6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 27806db724e85ca2ceb603a54fee537f90e26a69f783b8b22e11209d0111c687
MD5 472727fe022c2c7fd301d01ff36b1532
BLAKE2b-256 124700db64c32bd70c8134000e535564b5956dfce5ac65e181a1925e4f94b917

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 27b3dbf67d2385c764b5b5878756d6f13d63fc44532bfcd199d05b6081f1c5b0
MD5 b3ca014c0b7bb93497ccc23d952b31c4
BLAKE2b-256 4019972503eddd6a0b0960c46680212ca0094494f9abd4fbc243bad74beb82a6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 7949693733fe0643946bbf2544964abed817f48192cc9982031938c53b11877c
MD5 b4731b95da1001448017e273a672fb0d
BLAKE2b-256 5b171c047745f1fb4c398d7083d5a3b51160ecf636c4aecb5794350ca2fec56a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c7f257dd9bfaf4e5492ceb30e9a15e524cdff0e613fc25cf145e696b3b26a182
MD5 1082694ccc9a6dc440289e46d897bb19
BLAKE2b-256 16216aad84a13afea8c46e186ac1e0a1bb7513cd7c762fc7a6b4c9676825db45

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 901f544a1054d6b8b2c792d4fd8ee65755664a17dca9fa14555faf9eefc979be
MD5 a2794d200e71a88593d2eedc28b36f34
BLAKE2b-256 ebaeb7a75c793916f12700260ed3769af1884c5ca904820b84b18217f5bfa9e8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 d5af5fae9f72028ef724a529208cae5a6592c23f80c99fc230b61fc7d9f74bd9
MD5 c09971f686908f7593164822b9bb74d0
BLAKE2b-256 ccb31b43766d5a598232004afe870a0ffc4799201e8536a1e2b6d47f90caadbd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 46e8c6dbe30d73dd4a355c8cfd1ca94950211e2a2f0418a3cebbf251cdad371f
MD5 8b4175128d84e49974fc18044ec66fc5
BLAKE2b-256 cc57928997405b26c4085769e78ef486aa80d14cb77c189a0bb02100f15e6a02

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 72613521b0fca952a599554cd462a81d0ab312fc58f3cf59120ba41fcf784873
MD5 cf0c5902f6fdda46a64c7e8a84072001
BLAKE2b-256 1d1974c46ae710eb20f9e6702037c1bdca1420d8378f34d10cd949be19867201

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-cp312-cp312-macosx_10_13_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp312-cp312-macosx_10_13_universal2.whl
Algorithm Hash digest
SHA256 90bce97bd589ad0c76060a09f215c9efd16f68917fbaa6214804145ec3425877
MD5 5b23d43c44d3fca3c903b3bd399be70a
BLAKE2b-256 52dba8e3bcda3ab479d99aa27a565aa9caea947bd8c9e50aa4c6a7b8e996dd78

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 fc1e1adf8b5a04852243c9f7367c06a44d637d208b89a945c52cfd07dcc3ba89
MD5 8c728f0b3d949ef0e590417ea68e10f3
BLAKE2b-256 de5036508af026c9b8577cc4d6d95257c7a4febde7ff70d2d88f2cc23f772f50

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 a21e786a165185b8b53927413282ef69abe5fd80381996669b6d6744e0485fe3
MD5 3bc55953964f29eeef25c7049ddbb70c
BLAKE2b-256 b0e4f3f2b6e1f1af8a3f3fbc0b83d331e641100aad7a9317cdb464df215a3f9c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp311-cp311-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 82f7716e7297f409e1c20839337fca2708e8018ee0ce7f22324cff03bb18dac8
MD5 3df23d239ce711d63d712db9065e3bc6
BLAKE2b-256 2e9710490614a273d4e70f36096e943bc13e1f331191c300d25d2c4dee87a6cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 87c1a5137b07704ef452a8b17b1b7d376b1dc8195ee1b643e427708abcecf4c2
MD5 18b52e97665afe7a63ae986c4e4eb98c
BLAKE2b-256 c0fb624595fe87aa039ab7ffb8cd2a0dcb68260e88ad2af616d59d1da9c9d098

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 9bf64241c275fd3fdc796513de35c816daeb8de57676699410a33fecf16c43c5
MD5 b78bb2a512f617c971ec32d56fe13cf0
BLAKE2b-256 6348bd957cc49aba450f41dc03ae71ef85d9171b67c4bdfeb4c98f23c0e08a87

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 c6050585bda01198c92adaeb419d5194b01f86bf4af6eb8a8352859201bd44aa
MD5 bc5227adb44ee902536e22c63ed66996
BLAKE2b-256 7774563ac37ea5265d12501deb9189048fb1a1cb524411942f1637005833bafe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 ba6aaa07012bb516fd1db88ee455adaca22d55814859fd8e31e5cc8db12708d4
MD5 ae6bb0ba976d02bacb6b3a99f153b074
BLAKE2b-256 6c43c7dbaf051d8df50af8bedd96a5e2e37ce85ea1a726c95834a206fe36afde

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a8962272357a0dbf4fe99a1960622a18ed0a56855a7e167c5d026e3048e1e801
MD5 a34fe13600632f2283593fa7d993f25c
BLAKE2b-256 ec82da6e63b93b50c6047311e17fe4098d7a5c540a0d287f658adcffdd2935f8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 90dee2e42e610911467efce84336dfd2e9ac8dea4112b0fa93bb0e5ef3ff8340
MD5 12007528ffb45570e94119b8cd05e6d8
BLAKE2b-256 9a6c089b482b71034500d67bd7486395fa5684ea4da22bf93c1aae53572476c5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 841f7fe5ef06cf192364607fe7399e7ab1b9b53265dad3cb6d41a10946eca5a3
MD5 bdf863080bcf33e21615dc1938f397a8
BLAKE2b-256 7da86da15e4bcbd1a903d1c5169e6cdaebe9a8f3ccbf209ca2748ede9e4f6035

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 0ceb8cb3ada497a1654e75e6d33a6214fd84918e067a04438094901248aea007
MD5 9d0cce088983d6702c1016d407a11753
BLAKE2b-256 49e4bc279da674d5e2a79ae6a524bf226dcf41607b64e6c6ca0bef47f5aee5f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a15df7c3cfc4395100d88abebbdb45541058cf15e52de149876adee78d8b8e14
MD5 e72f49386a6c4a941d8b29d5d2a6ddc5
BLAKE2b-256 0b91621ae2abf90457e6c694c075137e5bcbf1c6c017ff3fdf49af438f475580

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9973d57af0428bf864d4066496d064d07c9a19e8b71e496cc38652a78fbe5578
MD5 1869fb2df4f06fa93681f07d8060f641
BLAKE2b-256 f72358993aec0d63e627776240f99bc9e44d1078d043103ef622a3f37a1d8d9c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a2f7affea6c7f56d738644c075b86a00a2fd96f24758699ad17b4a58ec576cfc
MD5 25b9bc09b843634bc45719b90a0e37c1
BLAKE2b-256 5934bacb74f65068835be79ddcf3ed8f3c9b89035020945a3c0fe61b9f7ce379

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 8f2919d8e92710edbf5274d619a2c0a40677b1f0801d992addf3065730271207
MD5 d7f66b8801f6a76392c1c477896c39b9
BLAKE2b-256 6881229297682cd2d88a6b21190ffeecdac6bd4b9c7d59100a28583944344319

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 e86b0c9200016b8e04ec557982a680c84399af38e340131cb99bb9602ef86112
MD5 8308d0bf839b66fbc419460ee555adbe
BLAKE2b-256 54037f528ed554b6aea30d5c1952703c0726eca5f896e82878662f00ed1df28d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 ef1d65f741056e6320428af3ec330808da0fe41cb3753ce807c8fe0b79aea219
MD5 056c9d82b5da3c9f5edb8feb879b6caf
BLAKE2b-256 daf44a9933de78e2c4490eff943de3218c7fdf57ff7ab77c46c62ff58860dbdb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 5457bfe8d1af4732a317f8fe6b20bbd8cabb29e58f9d7bab3608dab8c97af69b
MD5 624ebd6c15d24a43dd3ce086e55146c8
BLAKE2b-256 c7ed65ce550f8f4984bc1a7c77a4a75818c014ab9d41b04c5b11e6df9e7556fa

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp310-cp310-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 ce2b2302c0006e81607f45d5be4be0f6190344c7ea0a2a66a360121c996a9825
MD5 c23c603d8762ee1d85e3e64013c91cce
BLAKE2b-256 9b6f91733b6d22419f1e1daaf80837f91742a7f8c580f7a45860d8d6799877b3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a420e58dc52b8762afa2013ada5a99dbe7a1c32e9bd97792310d648930e62ca3
MD5 dba0e5dd09fcd4c1dfdb64539f9bcd69
BLAKE2b-256 a11b4621d1f1a385841f767b74d2c053f4c6490e8a31e44c1a315a75aa198eff

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 86070867fe9bd67a0c55b26ef8a513fe95899550b7c70f23cf57af8cdaac15eb
MD5 8787161fdb6d89f717700dee810ba3af
BLAKE2b-256 f20a3675696524af4e65a30bd8b9e3d6585d1e971e859442d1178a76e56bfd07

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 555ee0631752cf6b6f6c3efd1fca6ab5115d570ba5aa69c3e797498eeb121be7
MD5 241ff969c76f34921b8805dcc1d37134
BLAKE2b-256 aa0b893fc6f5fb6773c8fce02ca7efd3b406cb66c62860b9fcd00d875904854e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 a894fa553c1b881338be2b0c8c8ae8f7f11ce4b9d7bc77ed7e762b66d75dbe3e
MD5 c4780db2f400e37f88da500a02361726
BLAKE2b-256 41c228cb8fd32faab2159de7ead54052a6d8ed95ac8d01fb758f985b269b3fd1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 33e6e380bb92a91193db65ab5091ca98667daf42dcd606da563923d9a7933e52
MD5 d31bf6f00c8cbadde610d27463bba421
BLAKE2b-256 8df91b5e444281fa080bae76a8998be80ee239b0a09f6e12fa1d6071abc29020

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c7582d14eea663fb1ffc5761730f4d164d018ce19f9f35454d5a2796c056de62
MD5 474631859eff65faa9c1177103e9261c
BLAKE2b-256 829ef2db663896546fc47799919528ce2882c0de1d5b7c4c03651001dfe01418

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 a7c757bd2c6f7f1e606f6ee04613aa06d084da306514e75dff17dc786c6950ff
MD5 4869b2180ade0ed74a4c1e23bfa4adfe
BLAKE2b-256 a4ddd2eb928e48b6ab734fc9be4ee1583431266f08b5f0962e91ed3d64d557ae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 04a6e86a72ca3e18aade75b865971d85f51adb3d06286b336b7ddc84912f90a6
MD5 fc1d0b48f35a209d0f42756eafd94220
BLAKE2b-256 a78343a0b427b36345d6c7f7aefa96be4a8db46d70fd31d10f56ce55e4f7a354

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 fb0f484097404c67ff1802b38bad3dc8394796ef143df3ff3f8b1e7b9cb9c0dc
MD5 1a0cd34a563d0656e501ceebf92ac383
BLAKE2b-256 da31de12d111e51c2d764d67458994898bfa38375ebfab6a03520d7493849360

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 1739d4285f625d8e66949e745ede630a768ac60ba4ac7ebbea7045a537b0e6dd
MD5 45e2997d317b07b5f30271ec787627b8
BLAKE2b-256 e329ff29de298b1da1ec8f330fa7fa6b08e0f92847c2db88bc90cd3f396c854f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 60dc4d7db358efff95a829c9508ce06fc93147d02b26ddf8bb00a6f0171a4d2b
MD5 effb387bc16423a14719dda4a6db6983
BLAKE2b-256 b3d137c98a885e60485b9168d7d33a8a2074b03876420e04e2ead6e94c602ee4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 e07bf4f2649efbd9ed21cc16aeda25b5ca5d352c5e5a3fcdca8f82cbe77e7c3e
MD5 3c8d99c024968bcacf7c8bb3e6c9be64
BLAKE2b-256 d98200fc9de61d31f94d6c2217c07672e27d6a2dbc8b3ba07ad01c048347897b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 5d9b5e09e9b06053d9df9f2d7ce0f0c914b272866f80c4e703aba52a05eb492a
MD5 79b4ab02ef3960f2d6404f498f42565e
BLAKE2b-256 6aba9195974d4a6449abdb252bfe5a790eb59f4ea005e322e49049671527e624

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 4a93c05a05868c300e3860c89fcd191e45f3fb6141efd792feee42cbcf094d56
MD5 adce6a95b16075712f7b3de4a0b66460
BLAKE2b-256 7a3c620c05b296e7c14681163e50f7cc0f54137407659ec1b575736cf0e42e99

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 89c066c090473505fcb49df8a9764709db85a5d8b524aaab29c7efd46e2ccfd5
MD5 313b531e51152386eb462b6bce7283ad
BLAKE2b-256 87e6ea8a68138cfb42f3e059d91b9a6eb8590ff47d2628e31172c6d755213efd

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp39-cp39-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 46d8d477dad4e122ca842ecc00637f0fc38513a702df1bc0e235591d9a45c1fa
MD5 7ddc6dcb982114287401321841ef5266
BLAKE2b-256 9c797942393d696a46f9dbe3ceffe8bfc4b1756ca8ff48ad221f9bcf2528f183

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5a776d81439119b15902394990bb1e815e9547a815c508d007ce62d98a1de0d0
MD5 ac06f25a78cd47e42d386fdd9c087432
BLAKE2b-256 8aebee8a5d2e7d3163155b5d1a5a425bbdce4813d75cc358c85d07d973833803

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 9cc0dcc0934f2384a6622929ad6afa12291aaaf24691b8db7e86b9c54862069e
MD5 e2ea9b730a9f3a174a3d2a680c3a270a
BLAKE2b-256 a2f7741fc64653e110d4effe5c43a618a987c7e49a3dc456a6b73f15f01928cb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 f04ba098cf468ff899e89f51f47c3f7ae76a32766a45a5302f0891ad1cc3b4d8
MD5 4d67ed96b08072057f7baeb0769958b7
BLAKE2b-256 267110fa6964881ad2ec0676abb0c76a651df69fe108a510b544d563d81e013e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 0eb34a722944b69471e6d92910bd248a11220ee080bfd3e94535627660abdb1a
MD5 6d2ca026f50959afa2c9db99131d2e0f
BLAKE2b-256 22d315ce3024a4011b06bd150644786d0ccc996d9457a2787186acecd3142a86

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5d3b44a50f4abf52c8c4dae6e15db26e75b803e33435cfa4d597a2b8d9f9c743
MD5 a82af338298047dcb3178887787f44d8
BLAKE2b-256 3816e968116f4037467c2eb7c052d05b9a0672db77a9c2342a91d7d84aa350f6

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7926aad2e3ea3e760ec4b8038ea6e5e466e803c3218289474c3e75a4dc0ed536
MD5 392f41e20d74f32ebb0c3c4746179cfc
BLAKE2b-256 5acd3f99ee886f26d8418a436a2e16ba8c81b727a6d96938129d7b5defb387a1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e80015702baaed1bc8165a67cacd8d7ce40097f918077dcfeb20a21ba1458d1a
MD5 023b77376e7812cb603a7db2a3af51f6
BLAKE2b-256 0db9bb20a3d0b10fad0cc5b5ce04b0b11a52ea9ba4475515e72da8942270767e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 56ac25837eeb29825b7297e85b83d4c05b054397e094f8d2455358e1a5f46dba
MD5 222f8f2e2342c0bdf80890bdbb8eace1
BLAKE2b-256 c0094705d2e3ac48367ffc182aa28e6b1091d19da2122533e060f1504e8f90d4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4b5edd9852158e7ae14f544fb135528d62feb7f52a06c4167fff076243805b15
MD5 91255a1e6d2c489543b5c37457d4518b
BLAKE2b-256 49d32dfa33594903f3140fd5b0827e39c5f1e36cd8ec4213273f4c46b7b1a2e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a439214886cd87a1c557b5a265bc0569ee9013cd2fb6f320edfcdee4fe2058d1
MD5 26edced1ac6f0022eebf8ad7b27b29fc
BLAKE2b-256 45fda23be916e99ce008733815422151f021a50fe6b9b5820fa547821abf0ba6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 da944b24901355393e09e66f8188518615c80a754764c25b4aaa4a3921ecf5b3
MD5 b42237b87cc58c7b07d5a180d2198934
BLAKE2b-256 3b7c4ddb7b2c0fcaf0b7360196b84575ab85a16f4daedbb38f920ca5a19a2e11

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 05aa51955bd662300406389df77b2fa6eff87760b94993803b956685f9afc71a
MD5 b643e5b03440e72b3601f39d3251a678
BLAKE2b-256 f146f47f22a0248c2556cb15ce36b1bb4be0a962315fe6d4d2ac2d9dc286117d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 ac932bb64b24784f0c62c0fd806c68e7498e46244ce7e12cdd43ed9f550e3d50
MD5 8dee4ceaab123b04692b4ec51752e5cc
BLAKE2b-256 b62907bf006d27b6cefbad1a9659336dee2390663770b18cdb1aea250e63f2b4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 e4880b588350cc377874505a3d2305d02e7d19e2d5be9c293b12363221142821
MD5 36bbc08ea7da0ec45562b0ed8980d8de
BLAKE2b-256 c4b5834c1ecf87c1e4282ceff4f7d555181d1320b858be61d1915fdc64ab350f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp38-cp38-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 2e0f34a5a36ec2120eedfa09ba040d8b9017512edd34094ffd02e7797b986c28
MD5 431544cba7dbe3a2b781fc620ff74e82
BLAKE2b-256 c9ea4a7487c562912a4f1c69d538b070cd42002aee3255b8130a92f5b6c3a934

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 da7a36b373aeec2e30f849b7692c1f68865693a9c42c03554a06e30d7c22fe15
MD5 10291a4cb63f58b47171d66f56344e5c
BLAKE2b-256 36d66b71b04c47aa0244c9ae61e4708f678ccb17e7d89f68c01cf8f63c5f13a9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 2bec46ffa675d43e498fda3066d80e14ccc5b1cfda808580defde61859b268a3
MD5 cf6b6e8d448e5886cbf1a1c3f0438cf1
BLAKE2b-256 a315463b004fa79261f24b69c14de5b429ee20c49e5b47632c1a94668b5d25ad

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 8eb9440836079870b90bd1120c923b123a7bad2b9d3efccc6ec15f58423f5a78
MD5 2ff5cf9a2f9f01650810e30cdbb14489
BLAKE2b-256 821ab435a5f8ecb9c99acb19158215668585dcaee3b2f9f4108e9b5b7406944b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 2b28e3b97ff468cdf890c3e063c9e6186335b43444f6ba9c4f256dee4e07bd99
MD5 da27069c9c400359fe3c90b94d12d615
BLAKE2b-256 81d8bc48413df9f263879bcbe32ef8e43146fae5c0d9bd6529b49295f1c66eef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 50761b7cd5103bbc311578c83069d813a7b8cae86023437817305f4a2001246c
MD5 94d62c5214856b82df99d991e09ece4f
BLAKE2b-256 2f824e189491a2b603e3de79aeb71effb3dce5279af07b6be40ea6ce7bb52835

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 25f9debeda700631475ddadd89045d9ae32e076435f128f17bbc5a2187b7f7a2
MD5 9ad9d1114d3d41d83c133acb78c3b7c2
BLAKE2b-256 daaa24b7d92c6279e27e4fad608a4c11a1a21e89cd53cd0af64073ff713270aa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 c6db7439208175dc7e17d556d64b927c9324e2ee02496ced2959e79df99130b1
MD5 c1249d21509e9cdda8408bf130f4698c
BLAKE2b-256 5c5551e186cac7b8e6e0351ba5528e90b6a7982e7a7a120df757a41e7693ef77

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 36838e7643b8a3f5cbac3909c9100536203ed788dfb5bdeb094737a03548cfa8
MD5 10459e6daf27c81f5584f0195b6a7470
BLAKE2b-256 71b0cbd3c8021914de2aa325859f1dc5ae7978f70b70f64f23e17c0f44c62518

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3bf5c67992a1041f9780e91f61037d5acf26a3a0f345ce89e17895bed16d0f52
MD5 bb615acfaa70e88c80745e4a5eff51cd
BLAKE2b-256 52916e32f645b50e2fa6406439d93208cb20ec0f72da7c35aa11204ae34bcbd5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 aee8ebeb7f991f6f423c2d43e515f53c8e796eb26c227713476a57c2a79e66e7
MD5 d16d6b08b131f9044404e1f88a6c0b3e
BLAKE2b-256 2d19c53a4595bc82126022c2b6fbb4e6e94a80cc860c8c5d1135e6d4226904c9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d6d1390460f116fff483868096abe314ff3b9f9d4258913c9c42de937609fae9
MD5 3e2eda301021d716000dae4dc6070702
BLAKE2b-256 e9f5e5b8f401beb1b7df7f134cc3ed2b3c70dfe86ce2af72c2511f9a5cf2ebcb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a271720df93716b291e407852f3af28824e4fc02c4d2664faf8bbe7315a67ce1
MD5 be6cc86bf7a5aba2986a13a90fe54ff3
BLAKE2b-256 5bf3a9c99f99ef43c741a8158f6a843655b3bb8f333205fa3d21e54e945dacf1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 51528e9758e42076a68c90e84a97b152c353b2bf8b24f33479bd6f047436b4f1
MD5 29f25b7d0151764e0fc3906aa81c8a4a
BLAKE2b-256 8d76262acc2abbbfbd6a7f9ef9478cfc0781586f8012b1db2977e865c75f7fc3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 7182c92424c810d162ce398d1e0ddc79974de36798ad545e89756a5a4595b098
MD5 64a6a05e3790666f9f7a34ecc9658f9b
BLAKE2b-256 3467f53eb129ec57eac198f2bf7431a7b9fffced5ccdd280894c984c5ee7d5f5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 4d491dbd57fbe288ead6a0b3b4469f49b07ed4520397b4e3f8a4b95c73e02756
MD5 bc844a03e68e1f9056b7fb29d4777497
BLAKE2b-256 2eea0c86dd9e90af519f9b9040a5a5fe12b7011a5f67831a41c11cc16534049b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2ac878b8d7efd42b581e3adb45a164070bb35a13a3daa589bb3a97142045ecd6
MD5 f5b5f0361904b211b609960f7b954899
BLAKE2b-256 c09a4c6ed3da82d0b750c6035723c17d6e688f40b98a9a377ea21b9266cf8a10

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 bd139f89b165ec7b8eb41a77307d1272406bb7831d479c5755cb1c123a7fb1a3
MD5 b289f94c00e12723539bae89732d675c
BLAKE2b-256 4e944fe1d95647820d082c6fb8865a5aea4fb9c6af78f6e9af8e24e14a8c6bc9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 8da19296fdcad40f0a6fe43ff397db90e219eb5805ab1b4731b962dcb3e76c79
MD5 98a3ca0fabbaae4e476c8fcd993826f6
BLAKE2b-256 0b21d3bc1e38ac07f86d39fedbf4a4d6d2a9130193d4f1cc9cdd740ec338de52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 d36e69f6a6b580a94b42f46dab43868bcd2383b6f9ff9dce310cda3210c18020
MD5 5e3c53126d6a442d16ffbd10462c5db5
BLAKE2b-256 fea1006240f586a3dfdeec630b22848dcad78445a3477167232b873f5a869b78

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ba031fe75c7e6de40ce6e5316c9d4ca9149b5da8f8a962ef250178a28a2761ab
MD5 fe8ec72226abaeea9da9a9c72b067409
BLAKE2b-256 69ab6169a601aef39fa8974162aa060d6232621d658307a84f8f1c7bc8e9ce15

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 def9c4419c88ee6cc6bab6fa03198767d6bf40a5b42891c8c9dfd64b18d23f83
MD5 7d982786a75f0bc7afd2077145e3ab43
BLAKE2b-256 ce74a30ef9201ec3bd0ee2f9672a6907eb15a2b0c56cd3faeddd76e1f449c5a6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 abd18d47acf98a92f36dbf51efb13e22e40a164e9fe566d7ccb957cf1b27c940
MD5 6b0477a8b6528567745288307fb8a59f
BLAKE2b-256 7519ad88c49b4b38212b25d0a0a14a21fbd01041ccf48b5c26081b884ec74e73

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 08d3a040e5300ecb210336ac252e767d1bcf541b0d854ad8a1af6c80e20a85f1
MD5 f6923e581f68832433e6900b88b8d9f0
BLAKE2b-256 587ac7caaa60fcdf4fc807d9ae5bbd8a7ac51b592cbb94c0f60b0b8dc6fb4355

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a93e32238fb336fb024a357186adcc42f3e75fd8cf89c736d629a824181d14c3
MD5 67cb8f0ac2a5f1f376d8d01f03d052fa
BLAKE2b-256 33e1d245c69a3d88b837d0ca6ead4664915f0b00d37fec3f036474aec40a528f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c6e6d5f0d2ba9ba82b7f2852fe49afc35b0f336babedc4807b573408f2e56fd7
MD5 6c454ff891bb1ce5ac97694587a1090e
BLAKE2b-256 0b0c09b3484a86a82b5a599a424466b0635764ffab62e9b69cb8aee35fa77ae8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4c6b21914ea484470cc65e6542a3869c0e48b9e89dfaaeb15693c705fb850173
MD5 f8666b726943e07c63f1c2ba988d52d3
BLAKE2b-256 453bf1fdeed2546de1a93644bd60b3128f8f1d161ffae897407e67882195f66d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 0605738e1b37975fdded41bdc1712b4ce809e13614598ed461f56002982f9d0a
MD5 d75f687c866fbe8e65eb2cd94b22f6b1
BLAKE2b-256 4ddf652cd259319972db4f9d1d62f80aaff25accba70dfe187e1822718518e01

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.9.6-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.6m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 8aa3d0e2264e890666b95a8ba2bf2563e96261bd8cce24414423f30527a10df4
MD5 45b6c1782e06f9d768291a2d94a2ad19
BLAKE2b-256 e86c87476ab779594a28d6ca9e33d96f00e23a459beb1236d12330c368b38522

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ff4f681dbf70abacf32e7b27c19d5744de8d89547cb077e6ffe94e0f69f15928
MD5 e12c225517c4be201b522865993c4664
BLAKE2b-256 02049838a3d2ebdb96612f5a5905f2363c25cd7656c8ebfb783d77b802fd1842

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 1433452dad9156435b5163da968642a440964eef20f34246efa69e436531643f
MD5 cb0064ce97d0aeb878c52a397ac554b0
BLAKE2b-256 eb8ca80dff62bc1fa5f98be102d44bf331875a73f2bf610f9613fd10a8ffee40

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 cd53ff8ffaed87fa883e70763ff00b4ef91f051690ace0edb8a591bf4249368f
MD5 cd0d7b25e78d040a6634a75a8b43036b
BLAKE2b-256 21d21a1019d09a96a584b29202cdc883c94c9506e131d22029b7723f15db0412

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 89571e04f257a8ca23ac094d7db7e17ceac9edba735265548ea9461f5ca11c58
MD5 c2b8cea7845a6933a1b8232284831be8
BLAKE2b-256 599bbe7d441edf5f99c1d7991bd1e508a19721bb9f26a4e04feed600cb3f9431

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 9b2a40a751e129c5afddbe36b6500860e936ad371469dab4411ab3d2c70c56fd
MD5 cef5c4404e2b9fbcfd04d34ae62438c9
BLAKE2b-256 d0c7399b95a6eba9f403f81472a818898c86aa2cd2c4c36f3af82494b488df49

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.6-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.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1d16d845493db63889b3fe207fb8444e1c8cb4897e55fdf7f836dc357409f6db
MD5 ef0da19f9d28aa4a1694577a2fa60010
BLAKE2b-256 5cb9732b923bf2e8f8ab51c24bcb041d1ca80bd0119d11acff8c6ea19df3c552

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 181dc4801c7333fa3c744377ad2f7c49dfa139d95d1bb2a42a2e8d51077b6830
MD5 31188be44c47aadc2157353439b36b1d
BLAKE2b-256 40903e4adb13868b8ae37c7c6e3bdfd4dd81f9a6831127cee4f5202ed1bd7c9f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 36ba7e4935e029a0aec85eda5c21955129d46b6fcff04ba7def4143ef62b82db
MD5 1cae5afe731c5df4c65151e1908670df
BLAKE2b-256 5f9858de06c3c8dc8016c1becaae495dfa11d97cb9bc8a6af5b8834ba0bd4116

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9c63ac24a392b50fd414262fd38c81090d0dda00f2bb633eb76c848c326e11b8
MD5 049863c035eb514df0b9b029e1de5973
BLAKE2b-256 a683727d3f703bb862fa104c79e203664f0be9bb47e484c7d010606ea610f578

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 d26fcb95e026de77911c4ee7686bec35caba78b8b5c84f76824719a86e64332f
MD5 656b26118751cb820f4a52ecf3435a01
BLAKE2b-256 14851833c5bda0bea35ddf30c9dbb76b6a501d19c0b172bbb0b955baf3dc2bbe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.6-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 1ed0ae3d90dd873d855da727c97f2ddd375639106e449680409636705f1ecac6
MD5 f6d9f53c31b0e517fba335df8583ed30
BLAKE2b-256 ddab45a58e8e49f41abbec8ee9fdb519ebe793535cb833eca60f1d091b2fd00e

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