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 thoughput. 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 5 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_archieve = Str("<html>...</html><html>...</html>")
_, end_tag, next_doc = web_archieve.partition("</html>") # or use `find`
next_doc_offset = next_doc.offset_within(web_archieve)
web_archieve.write_to("next_doc.html") # no GIL, no copies, just a view

PyArrow

A Str is easy to cast to PyArrow buffers.

from pyarrow import foreign_buffer
from stringzilla import Str

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

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

Quick Start: C/C++ 🛠️

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

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

Or using a pure CMake approach:

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

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

Basic Usage with C 99 and Newer

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

#include <stringzilla/stringzilla.h>

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

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

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

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

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

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

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

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

Basic Usage with C++ 11 and Newer

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

#include <stringzilla/stringzilla.hpp>

namespace sz = ashvardanian::stringzilla;

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

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

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

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

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

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

Memory Ownership and Small String Optimization

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

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

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

} sz_string_t;

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

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

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

sz_memory_allocator_t allocator;
sz_string_t string;

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

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

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

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

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

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

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

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

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

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

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

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

using str = std::string;

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

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

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

using str = sz::string;

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

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

Beyond the C++ Standard Library - Learning from Python

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Splits and Ranges

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

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

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

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

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

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

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

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

Concatenating Strings without Allocations

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

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

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

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

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

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

Random Generation

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

sz::string random_string(std::size_t length, char const *alphabet, std::size_t cardinality) {
    sz::string result(length, '\0');
    static std::random_device seed_source; // Too expensive to construct every time
    std::mt19937 generator(seed_source());
    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.

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

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.9.0-cp312-cp312-win_amd64.whl (74.6 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.9.0-cp312-cp312-win32.whl (64.0 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.9.0-cp312-cp312-musllinux_1_2_x86_64.whl (255.0 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.9.0-cp312-cp312-musllinux_1_2_s390x.whl (194.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp312-cp312-musllinux_1_2_ppc64le.whl (216.4 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp312-cp312-musllinux_1_2_i686.whl (199.4 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp312-cp312-musllinux_1_2_aarch64.whl (205.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.4 kB view details)

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

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

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

stringzilla-3.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.1 kB view details)

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

stringzilla-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.6 kB view details)

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

stringzilla-3.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.8 kB view details)

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

stringzilla-3.9.0-cp312-cp312-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.9.0-cp312-cp312-macosx_10_9_x86_64.whl (73.5 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.9.0-cp312-cp312-macosx_10_9_universal2.whl (112.5 kB view details)

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

stringzilla-3.9.0-cp311-cp311-win_arm64.whl (64.5 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.9.0-cp311-cp311-win_amd64.whl (74.5 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.9.0-cp311-cp311-win32.whl (63.9 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.9.0-cp311-cp311-musllinux_1_2_x86_64.whl (254.4 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.9.0-cp311-cp311-musllinux_1_2_s390x.whl (193.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp311-cp311-musllinux_1_2_ppc64le.whl (216.9 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp311-cp311-musllinux_1_2_i686.whl (199.4 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp311-cp311-musllinux_1_2_aarch64.whl (205.5 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (258.8 kB view details)

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

stringzilla-3.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.8 kB view details)

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

stringzilla-3.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.5 kB view details)

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

stringzilla-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.0 kB view details)

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

stringzilla-3.9.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.7 kB view details)

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

stringzilla-3.9.0-cp311-cp311-macosx_11_0_arm64.whl (73.7 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.9.0-cp311-cp311-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.9.0-cp311-cp311-macosx_10_9_universal2.whl (112.3 kB view details)

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

stringzilla-3.9.0-cp310-cp310-win_arm64.whl (63.1 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.9.0-cp310-cp310-win_amd64.whl (73.0 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.9.0-cp310-cp310-win32.whl (63.9 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.9.0-cp310-cp310-musllinux_1_2_x86_64.whl (252.2 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.9.0-cp310-cp310-musllinux_1_2_s390x.whl (191.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp310-cp310-musllinux_1_2_ppc64le.whl (214.5 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp310-cp310-musllinux_1_2_i686.whl (197.3 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp310-cp310-musllinux_1_2_aarch64.whl (203.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (256.8 kB view details)

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

stringzilla-3.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (189.7 kB view details)

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

stringzilla-3.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (218.0 kB view details)

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

stringzilla-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (207.7 kB view details)

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

stringzilla-3.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.6 kB view details)

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

stringzilla-3.9.0-cp310-cp310-macosx_11_0_arm64.whl (73.7 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.9.0-cp310-cp310-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.9.0-cp310-cp310-macosx_10_9_universal2.whl (112.3 kB view details)

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

stringzilla-3.9.0-cp39-cp39-win_arm64.whl (64.5 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.9.0-cp39-cp39-win_amd64.whl (74.7 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.9.0-cp39-cp39-win32.whl (64.0 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.9.0-cp39-cp39-musllinux_1_2_x86_64.whl (251.0 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.9.0-cp39-cp39-musllinux_1_2_s390x.whl (190.1 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp39-cp39-musllinux_1_2_ppc64le.whl (213.1 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp39-cp39-musllinux_1_2_i686.whl (196.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp39-cp39-musllinux_1_2_aarch64.whl (202.2 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.7 kB view details)

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

stringzilla-3.9.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.4 kB view details)

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

stringzilla-3.9.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.5 kB view details)

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

stringzilla-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.6 kB view details)

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

stringzilla-3.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.3 kB view details)

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

stringzilla-3.9.0-cp39-cp39-macosx_11_0_arm64.whl (73.6 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.9.0-cp39-cp39-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.9.0-cp39-cp39-macosx_10_9_universal2.whl (112.2 kB view details)

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

stringzilla-3.9.0-cp38-cp38-win_amd64.whl (73.1 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.9.0-cp38-cp38-win32.whl (64.0 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.9.0-cp38-cp38-musllinux_1_2_x86_64.whl (250.1 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.9.0-cp38-cp38-musllinux_1_2_s390x.whl (188.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp38-cp38-musllinux_1_2_ppc64le.whl (212.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp38-cp38-musllinux_1_2_i686.whl (195.6 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp38-cp38-musllinux_1_2_aarch64.whl (201.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (254.9 kB view details)

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

stringzilla-3.9.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.4 kB view details)

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

stringzilla-3.9.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.6 kB view details)

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

stringzilla-3.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (205.5 kB view details)

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

stringzilla-3.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.3 kB view details)

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

stringzilla-3.9.0-cp38-cp38-macosx_11_0_arm64.whl (73.6 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.9.0-cp38-cp38-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.9.0-cp38-cp38-macosx_10_9_universal2.whl (112.2 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-win_amd64.whl (73.1 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.9.0-cp37-cp37m-win32.whl (64.0 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_x86_64.whl (248.6 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_s390x.whl (187.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_ppc64le.whl (210.4 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_i686.whl (193.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_aarch64.whl (199.1 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.5 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.7 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.6 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (203.2 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.4 kB view details)

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

stringzilla-3.9.0-cp37-cp37m-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.9.0-cp36-cp36m-win_amd64.whl (73.0 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.9.0-cp36-cp36m-win32.whl (63.9 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_x86_64.whl (247.7 kB view details)

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

stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_s390x.whl (186.8 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_ppc64le.whl (209.8 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_i686.whl (193.2 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_aarch64.whl (198.4 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.6 kB view details)

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

stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (184.7 kB view details)

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

stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.2 kB view details)

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

stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.3 kB view details)

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

stringzilla-3.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.8 kB view details)

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

stringzilla-3.9.0-cp36-cp36m-macosx_10_9_x86_64.whl (73.1 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 b7665c03f140cbbe2338bf8bf939b2f2fed60e2a223abfdd6ee8a5f458bb2e6a
MD5 9145316296085ad44f4485c816c82314
BLAKE2b-256 1ab03ba75e910bf107400d38fc2cc942ff0e5d80604da1128af40d3e2436e2d0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 4a694f3c1075022f7d739e18958f4c7ef8203200d3613ea50b418bd883cb818f
MD5 2417c74f8bc394b0e004eb4d4417120a
BLAKE2b-256 d02ce4c8790553ee976ae07336ca4607a53dda11cc5af2275038cc66f5959eda

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 73c55404cfce1eebe8ea1514e46ba22fb7182402b99f6f5cad85e26f27ea2267
MD5 09e25cbf98ffaa520cda407c4a3688e4
BLAKE2b-256 262befba5e48854684345c2d5f4c75a13bffff9cccdf649e024032070d078b07

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 29e0353475b1a38aaa3e00558662c1203ea21efa436f028576655d1eeab34126
MD5 05ddf052dfabd277a82c2b76a6826dfb
BLAKE2b-256 53c48addfc0364fc1d50ac2a76fa7d13becc59937d8e2d28f1de3764eba3330c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 fc0d5f00cb4a52f40ad04b36ce6599e8516c4f0bcc3857387a38eb2e9719472e
MD5 4c6a1bdf1a74737078be3acb74b706ad
BLAKE2b-256 3dab95d9914bfd32bd74caba79a042ad282d009cea7b35c994c83c4e18c18d77

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 77353d70411c69d1cfdbd12d30da479c3a66ae27c7117cb1b17f6c6eb7e93754
MD5 430f349001ec7625b841119d445e2e9a
BLAKE2b-256 1ff9253d043a3aa0714eebd7bce982cc8c801d8ecffea6fe00229549e0745876

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 de0f994b2bd2797ff859e7f8b8d882feca0342f24223f3fd33273265b78bdb4a
MD5 1d0211a4dc38312fa809f5cc4997e329
BLAKE2b-256 1b7c8f67619663622789156a550624112d207098e2445b49284febc23206e0f0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3e01724ab153e1ccb261491d43f1b16f08b7dd7105b6ce16002dad1632dd1b4a
MD5 68d791bca8c8c4ea28f180c1a543e8ba
BLAKE2b-256 5ec28b71a45d69a70684991eb4c2b5fd175d813f79b1f6eb999fb1f0aa4fa218

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f40a155ea20705eb2233cd568b6c51b9e4d394ce0d42751d9124f8e3272d7655
MD5 426b0361f249339b7b6faf0dc593674e
BLAKE2b-256 0122058ceaeca26e57d4ec24fae6d71072ef6e95b9e255ba0ba5b6fba6f62265

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 f948a91e4462e5e415048d2c89fafcf72a26730a9f0ba091abaac1437d1c18fd
MD5 5c77cd5e65d2a80a76cc651ddafb4ae9
BLAKE2b-256 f11d45aceafd12e7e2fd83877202a978a0c7f112bb966c3104a7e252a0b2f656

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 0083b4b39127a086c1097c589029d07981424d9e0cc53f12982d10c87f136589
MD5 eaf8a037780319569b2d1ad53cc26779
BLAKE2b-256 608e97194c783dea549af9655370396edcf9c310bee605459f11b04276113d1a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ca37539add820fbbc3773d1866a7d6bf3b485bc88d8ed39cfabadc5375b1b003
MD5 d23660ad55534672ef075392cd28e818
BLAKE2b-256 844159c9b2125659ee4e88ee7b3ae398eddf3fe35a5cb970014f998f40f79fe1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e220e5b86d83ea7410c17cc002bde226722ff6cc05eb8a492e33b0e726976805
MD5 b743341ecfb36e1bcd1d609e2c3c45df
BLAKE2b-256 45305c14ce9ccd6ed167b03ba2f77e697b840375b5a690d1ec6e64b256300a33

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ea86c89e6e5163d732e2eaae50dbefe847ea81e54191e8cf44b79ac29769fd5b
MD5 0be7366c7e1368f2e85ce417d8493ed6
BLAKE2b-256 3716a44dd05eb933d4bce0adcc6ce8c85fff138d84231d453dfe1f145cadf14e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 06b964d3646dcd2aaba03615cafcdd85ffcb2dde35d35b09bf44c6f408c7597a
MD5 908a7716eb10568a90523e3fbc0bf94b
BLAKE2b-256 6747db34dcb672edc54d4aeb66e709d0c6b4265d687536bfe8c17f01c6851637

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 7a431152ad49eaa0b4133467029c0bd1ef1d1d8fef9f74504256bcc14a331c7c
MD5 924c34e118f0c730df228c1851550f5e
BLAKE2b-256 c57482f2dabce9df3b47c422c537df29a58135d9078c2acbeb768581248313b5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 c08954b77909e5b6382352e54165b8163735f2f25585c0204abd708567afb8bd
MD5 b8b5e2a2a69c425f1e9b314bc1957483
BLAKE2b-256 e054aaa2ef00c989b6f047833de36405512e234ca2c9d3439903d040487002f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 af4c70c5d3f56767dc7fb2ccdb53cb5ace8ce9300c141f3432f66d1cf7cc067e
MD5 0d651f315693c8b63ebde14d8426f891
BLAKE2b-256 e3b1d9316775962e995e6d3f4fa8881091afa6a7b10bdb5309e14ea279c977ba

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 acaca8cb04d77a2d0707ea7cd5ac0820d88b70962c3010b0712247daaa61eeef
MD5 74fd36893c25af1d31a321371af94532
BLAKE2b-256 77fb6099786084072ef824f4832f8cb8ea6e1e71a9ffa0b850be25f05a635902

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 bcc6f6046cd931b43aaf9fdbba7873c5973844f4ff3bc65c57719069f34da9e1
MD5 50fbf54f43272715274da926df3c46ee
BLAKE2b-256 81f0b56deef83dda2d9dbc9fe9e523cdc351b37e3cda11a9fcefde428ee45f0a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 3103f4e26ff5d62c1af0a6103ae92bba61346c55c0dbd324f5ae3e4633ebdcce
MD5 dfcfaa7dd7974ab4dd577c3493633bea
BLAKE2b-256 fd19674a04f1891bfc9eb8e9be6539cf0008472c4f7081698ed870dfa4b17f3b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 34338b22632136fa9c97d0afb4dda5ed69802855dc69445100fde889f672ec36
MD5 e5eff5400870e471991596e54777073b
BLAKE2b-256 c878180128fc4278d53a41d30d351e713db88c6d81ddf4a55ec84a31357a4dab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 13c79773adb4264020066845325a48ea682b543c63a09fe33d6fe819a3d2d9f0
MD5 369072e467150d92113fe65db70c702a
BLAKE2b-256 874b6afded2dd15af342a7d93bfea4f354c39db5563b2451ebde4afd519dc31e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2cde6ae11f2c1ec59b11450a152bf43bc550ab2f0cd4649013c62372b78a26b1
MD5 35161993efd906a804c9a9e940e39c8e
BLAKE2b-256 80f33e9771fc9c0440f848b2e91774c9e3135a0554323233551b2d88684887eb

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f4483656670e1df2dfde30612fe592b396f00d8ef28a56f655e07836f774e300
MD5 fec04e0e4f2023a654c716bd6325000e
BLAKE2b-256 40b159410e25d24b5d68388156a3fe34b3b645b381f0fb622e48c2bb9a8b2d85

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 2616a00ba5b809baf3c0ae9d999c8e36cf93cf1d9c1a7ae227b56eaa262ddc7c
MD5 a22d2fcceb69c046a4143310f13e1d35
BLAKE2b-256 d5bddcfec5ef37d60d9f8256e98ca6e21709100c120452b82abffd6f2879f577

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 204650d5c62eacd247ce01df818ac2d2331e1d58b7ff884a544574f94adc778a
MD5 9ecdf6bc2a0453af43f1f5f39f7a3f0e
BLAKE2b-256 1ebad30e3d319723073efcdefabb052eb363c24c7ee3aab8bc695715f3dbe6d9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e4d172407b17a1eeea484720df98207583ac00d5a229bc0f8113c5b0ebc0177c
MD5 edcef1c6383518a1373470d6df722fea
BLAKE2b-256 92da0f2e70fda9ea2920992744c8e3cacd5f91e8e9caa80f3acfe2e0c39c8650

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e7f39443d3cc75a0a17039ce7ee7370d494eec72576f0536a16a4f776274aa2b
MD5 647e60c602531e9e02b050a778d170bd
BLAKE2b-256 3bcb4b1fb444f9b12b161d7dd394499ef8f8b72105330cb3e42521ad2c6001eb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 75325255e5ada4d73b3f9afd4f107c3fe35a0019ad2b30095dc53a16816eee19
MD5 8f7750a048d414c2d7a6874083d29565
BLAKE2b-256 166d7779dea000911b58359274de28912238f9f248cf20d9679f1356180a99f2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 cb461e6f9e9b284a9c0c510af034037b7bf97f88c4f3cef126476259a35a6b29
MD5 eff2de1a21a9caf33e9e3726ab5d0ffa
BLAKE2b-256 6970b02808cb344a541d49aacd39fa4394dd3adc3835f03f90f81391c4ad6d1f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 427c5090da02e3d01ee698ff8703d4bc95f6b5801d63134755049485ff973c44
MD5 ffe836848fda12851f9dca056dc1138d
BLAKE2b-256 f8e7c718d6562392f1eb352f73dca1b310049cddf45953e0a11222cf9df7fbb0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 7813648c193da31c490710cfbb45b49240db5d19623451510ecb284e617fcbc3
MD5 ca33d674482e2e4af10c17cf6ddc745d
BLAKE2b-256 2fabcdd6bcc81275b2d8d514ea7246a04210c770e452b0214427017d191547c9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 4ebb0680e14c8e54efc6abe31ca2698dd8cb2e7da79864c14da1e15bdf1f6d91
MD5 f8459487dce446b44aaf85ce38e1fe8a
BLAKE2b-256 360240d2965b3a9ccf78a0eec9d66085c28e218a4b676119e855e811e1942db6

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 064511672fec4c3cd2ec34ac22042f4b53e14a8e8381519f7b69d0e94fb2b4ad
MD5 7a2aad40ade6845c5723435af6fe7074
BLAKE2b-256 12cf8ec8e0b402eeed3a78e31e30458042d014ebe2246e4ab009cc332d53da52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 205a2f7069e642f429c29d66325bbd2f3887acff5450df9f95555316aa200331
MD5 7d7fd34041842fe62ade5e851924b3fc
BLAKE2b-256 60916acbc5539e2f5ef6d10f362205db506b604e29d13bd398e837cd08362fc8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 905df35ae8e5ef41d3d9a43d9d9ec517e1a5fd531264653ae48cc6032a86294f
MD5 d2276f60dc2141361ae18f71c9a584e5
BLAKE2b-256 dcbab5c86d67e6b498de8f25b694dcd741abb6f9380f97bff10b424f7c391eb0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 244aa4e1612621035472822989b8fcd6892ec6fca6070503426e83c340e344a6
MD5 fd1175cfcf209d44b44b24b329d093e0
BLAKE2b-256 e0d8d22fe29b767f36ad27c863dde36d205c94fe2a53bcfd7f284c5ada76bb34

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 f3300193dac9752acd03151219d4d63bbe3b3d62c57d9f89ae427e7d54d26b3c
MD5 647b6a2c44c84595513a720d4d6c4895
BLAKE2b-256 50d6edade89dbbda5f29c43a57613fd33627ebf238d2c8754f58966dd8fb79b2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3aa2b8b2c15c3a33ab6f0314c53daaeec969299eb0f8dae54751a38052adbf54
MD5 b496e8c10b4226557b25d3af28d3a3c0
BLAKE2b-256 9dd0a7327e6f658f3752ad6ee497388e49705e2dc088d9fd51bfea887e9a24bc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ab65d27c17fe7ed90acf013e8ca2a07fc12c425d563606bf7523bd207cffb2f2
MD5 38f5d2baa44023edce3549861776609e
BLAKE2b-256 98965a2a5c62afd4c55457b0372f1f36694280eb0902d5133de472bc5898a5f6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 8fb00618950dd9bd4d6f3cae5f98ed10385efa39a34847c2e1ebc12086fba2b2
MD5 44ebe64d2dc98bcbd52b5cc1e241840c
BLAKE2b-256 0f7fbc5bffcf508f9cc02593906e36796134e2e2622cecb3e2c74697e9be5e63

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 e4181d018499445445069321ee01a6261c4df7ae417fab107f841928a40fc9c9
MD5 5717248fbcf3939d3f4c5912d12264d7
BLAKE2b-256 f1adc8a6640803a450017bd24df684b289c0cc8dcb2487df24af2d1cca1913e0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 dbc7e21ac4b7cb5bc1a10102d9600b1c17113e4bf28ba7b671dc374f9e0e5db8
MD5 b971a696621beeafd4e95bb12afd707c
BLAKE2b-256 f14413587c17f39652208f44a30672721bd6783d2cab141ad1fa4d035d0f3fae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a4a83c38bf75bd720487aa07fceb1fd1bdd024f206cae63ac3a35207b209e9ca
MD5 b2db773e89f106fcf8aa8ffd68e7995f
BLAKE2b-256 57f0c48745b3ffa902320acd68ec41bc16689db6ae8f0b7db04f8f4e33d28e1a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 86abf5305b26f7576b811e869af88cfcc83d0c0950b313423d33b233dd656e51
MD5 b0261127d9a54081ac950c09b6c51a54
BLAKE2b-256 e662a7010c0e40d037fcaef2f160a9545580713cb6c586877d20d936a32c5103

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d57195f2f01cdff86df600a960356d33e031c160447e92797a341102369f068f
MD5 a94cab32e86df99210a07ff9c9d66807
BLAKE2b-256 4dcc6264888f66546ec33ffa463e6f836cc34d98ca8c34090605b50d04ab9f5c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 3fc127dbedfb9456ffc77a1425746008342dd66204fd5d17a58c6a484462190a
MD5 b3d9ac6bf71aef4f9b549c1194861794
BLAKE2b-256 8e9f1e0f0077fd3f4dc7f6ae6ebd90751aacc149fc2a9b605ee5bf16cf1c7d47

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 e748277c637105770a8aae782ba0891a0b311225f50a3fdb906df654f03ca61a
MD5 79ba258d4bb4d878ea8ab69267c6b39d
BLAKE2b-256 fafa6a4fc9024c28df2b1170e0a39102bdef9f1b48d3f132d63b93c98a5c3a65

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 72f5803213067277a12d76429910ece9e4eacc8658eb0a56d51e981398c58f5b
MD5 86bdbdaf82876363b00175c1be4fcc45
BLAKE2b-256 f0624e4b800f8c69a30a0489a8cb806e6b6da6127f89348c16d41ae0c98c14ea

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 e31aa63b47f1ba90759fdddeaee6f3392ff5a0df6c8189748def57f35dbeb8c3
MD5 0b6ae1e2a08df07773670c0974945170
BLAKE2b-256 069e268102b222b3f6ddc823bdeb698e69ea90a5882b41362b6aba97d9bb4a63

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 70e96cff9dbb5ddcca6622f314183d6f1a3bd8b657ea44f23fc387ae6d1a8ba7
MD5 ddf6885a15468ee569082c7c768f6597
BLAKE2b-256 720c9566142ec516689438a289b55beedbfca85d0a5e9d3f02a19a88f56e68a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 f0a46fbe3fd621b32b66eec28302654b43e5052bd4a6be9195999e3f8335407d
MD5 bb14ac7a1d2ede33288ee6c632c36a17
BLAKE2b-256 d6ca79907b85fbfa0ca416506ade40daf40e4d2381d1cf97fae81c7f8f9d8848

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 82aa5757ac73d1e4600b2f825b5aec0b210b4c104352ee4726a7e56dc4faa2c9
MD5 4633a522aeea7a3af5340ddfcf069c49
BLAKE2b-256 a30186e9717d9e1217619752b6d8f28efec2cf307ebbd0060c184db02ff88280

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 c10db7f6f71b6681c822ae6792aa4ecd9426475890a67f996d55a52b1afd0b0b
MD5 674dea9e69bc8335013e3c93182c679c
BLAKE2b-256 0b12c5f0319d3ffda69bbb84e3a3184c9001f19442021127b587968085e42744

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 43efe2bd3941fb55e8412ec87e07efe5fa61fbb9ca3067bf3d24112b51c1eaeb
MD5 0003b41504df985fc5c6661ea2b341c9
BLAKE2b-256 d8871129f23f5784ecfafeb3915fa75c2c9dbf38dcc39ba606da9469848bf5e7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d04fdd758ac8df6a18d84e63afbc21ba8a62bf01e880df5eea90d658977228b4
MD5 70bfdccde3622aa9fe4d944fa8f85b15
BLAKE2b-256 4a8a783aca340d1a3121be5a79018b6ab7531493a169faab335b66f5e95cd6db

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 95024da6a10667dcc047970a5306df3df14916737624f07d33854ec630d41af2
MD5 6184bf552d84e8c95956706a47af4b40
BLAKE2b-256 97fc0f9b062d3dd2df93c3be0ef6aec4a5f799238487ca17d8665647296902fb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 44ae5b6074e47747a81a6b18e463187a1e9f5fb773b877dfe4e1be8916e652ba
MD5 e7a8a6b03d26fe37ed5bb576bd2684a2
BLAKE2b-256 fc276f11cd7633d329043a9bbd10508017cbe9dd65a1e8b74f9939c7a9195171

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4f9cb183336787d7d423cd76b4a749e6cc4d85ee893228e3ad9ae04bddc73824
MD5 eea305a2637e1f9e385394ffbdc9bf85
BLAKE2b-256 43d8728e09db8bc3148cc40701266a27e4302a93c35da88917166288361f3058

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a608e398d3317b0555d8a728ef7189561474619a1c41b55feed500d98c9de4af
MD5 3f389507b2e9cb0af86dc039fd91748f
BLAKE2b-256 a179b86e8e3e94643606533c7eef30f28c68cb79f049a8c5ea094d3cc9e4ca56

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6533285a10cd4c0b4d47aa13fd85a027dc38b4715cd5372d5383c2f03765949a
MD5 d0ef676fdb6cae0210ac965c2c95541b
BLAKE2b-256 9b28612ac74682c95d110c0ab902162067addafbb736d7089b6b19df481ec966

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 8f7a0408a560cec9f9fb148680c7e9537ff09522f7e94ca8128befc979ca3394
MD5 610d4876145712ebe220ca9a57feda1b
BLAKE2b-256 bf2a790c81ba520bf15e73d6032e1f2a0574fdb914063e297c5d9fddfa5c0501

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 4aa8e20bf7d8fdce08eb6255e0ddc6f2e2018466f83471dc51832422165116b8
MD5 05ec8be02e6b4a9ab5f0f2462f16a8d3
BLAKE2b-256 9466418bc94a565c6c800b12ecac8c5bd9ba283e29d6d0e8f7435a85657703df

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 1e8261f973c29049a25ac644a6b8b0313bf3a466a471f8b85c7371892176db17
MD5 3762350db9501fd731b150e9dde7f771
BLAKE2b-256 dea177e90a746381e3fef80435d8a55d1c31e9e1614f6efbb0d61287a1096910

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 bfd292241133cf0268184f27e49e6e5d2e09b15dafec758073e1270932658cd6
MD5 c82d311e1e67c29d678b9c5f88b98b70
BLAKE2b-256 902dbbb03aa238f23eb949cfc1f740c38a92a627c6b491fd42f86e9998c292bd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e384304f38c6172a4ef4de2ca37629e9f4923f0eadd9f2e2a45cc8411c3a540d
MD5 f02555136e3c179e5451eedd46459d38
BLAKE2b-256 314dd465c91960f5dcd5fd0971b5b6d3f764f5ffb6d76b5a098d67188d919cc0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 97737a4a2fa9d8d1b407f4a9c9724ac0e11afefa6b0b01fe4205666440858cc8
MD5 c9f5bc5c14aaacf32c2fba4317412c00
BLAKE2b-256 33f0d29d98560c262fb45894872a74d4f8718b4aabc60c504b8e1221ec7990ef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 700e54c2ae3b9754dc50a640b8014d9f316e454a526d8630d08746732e43a2bb
MD5 0fc05169e72cd74ca09aec23ebd0350d
BLAKE2b-256 4cecf5e9b14bc1683be9560ceafccbc948871b4d7d2910dc72ddf42e8d4001b8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 f35654aed447cad16d97bf6f26e0945b1ad55ce93e244a2ae9df872bb830ab66
MD5 ec3b4c0c15674fcf673631883006c8c5
BLAKE2b-256 3ffa0729a7f8009b22724fcbd14e8729a21a5419e6175da9dc7fb88972b3c30d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 c59b0e6cb5629d3c4d8aca3dd9da99b5419347785eafb41cd0f33978e6760848
MD5 ed562be74b8aef3f30a7e945b700b391
BLAKE2b-256 020a214294f73257f0ca29174544a0e3fbdc1fadc6efaac8d3ca4e361e816ccc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 54f18e39a3fc5e6f03fbda43b3010fd4fbee0b83da761d6b6eecfe0a48c999ba
MD5 c37c903e8fae9b3fc8afcc27ca645042
BLAKE2b-256 82d80d5fd910d92bb7c0fd24f7426e06aeefc86a118c297a92f630bc0da5c121

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 372924ba03b93c70c859a23edeba3dd30ef90c49ca18d4bad7dfde1234d4008e
MD5 8df4695771e7b340889cc96e5ffd151a
BLAKE2b-256 0b4eb1ccf460c8b1877d62e689c437f32aae6fe7eb93c13999237f77a83977fc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 a5241ea8a5a48eba2761d18f0713ba5d627b7e57cc9e8ee11a0ce148257f1fc1
MD5 009ee414f10906ecb828efe5863c37d0
BLAKE2b-256 7f205173ad72807a0f1a3598e7ce6efe224d5cc6328c3a71b03def4e69ff00eb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4a5660806eed9d0be54d186d9a534a7312d02bbc3a44d04b83fcf2f6836e7fad
MD5 e9d8c16812ace64dc27efe418d33b4d6
BLAKE2b-256 22cd5d433bc724f8496064eeef96b814e891120390a6b2d161a1fddbea464565

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ed77c08480510defb4e4e9fd0041b73c4cf3f9891bc83e829ba92069c0d93f7d
MD5 d19f79031b93584f3946ee782cb02e0b
BLAKE2b-256 47f84d3ec9daff6fb7b1319d341347c927eeffdbd4dc591cf4c7d1bc49436391

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9bfd3bbd9cec841132e96015a1c8d6422c2e7e7c77763ba0dcb77778e46808b5
MD5 cd50ae8d9c7c65b0a6b9931b5aa2f358
BLAKE2b-256 3e78e31a73504e01e3f4a468ae340f1a465931154cb37c30f6ab4fb3494afa32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 17082f5af2f375399de5049a5290a404bca19955a57c14530cd943dd038ecc6c
MD5 958bc616d693da1ab96527b2ef735109
BLAKE2b-256 46ca5b8509a9f18d37ec81479fdc54999fd6cf6d2220b9b75f1acdfe1e2d6792

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 636da3c78eeea331e2df8927a31ac621e1f9a12266ac04112eec99f1ea2571da
MD5 f97d080425241cd0e79ddffa3706a449
BLAKE2b-256 127bd1fefaa52e7f032003b177b8a7d65c075cd3c3bcb808c6841c45dc38916f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 1df865aef55d9d9e1d3275bdeae1fb3c53354c125e44b59b67105f7c77a4699c
MD5 564b5c817c5055961cf7e2574a279d32
BLAKE2b-256 eb289e7073d4f8f2729ba8b6132674656cb7ca31031cd7d2d18326edc840ccb0

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 99764593b91ad881472003126448121c9b5d5b920c298d50ae0589100118acb2
MD5 48d00ab86a098c9a3d75fd150ad58b00
BLAKE2b-256 be39b80f03f2f1afd4a314d89e42ba8205cdce3056063fc69a6e2a6fa0cad778

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6792ba2518f543259f44f70aeab5a8924289e8b3f5a98eec85ddc0bb4923bac0
MD5 9f378d86a3e795a9fa416f226e1c01e5
BLAKE2b-256 023b4eff1e8553e53f2dfdf4f375650add6f8310fb965ee7754cf423608ec6f5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 4eafc2cb197700c16ed2c54d6274201e5b4a57d2dac1129e75649b2c76ceea33
MD5 4df0d759ea6c4ecfbb7c4e482abc33e6
BLAKE2b-256 735b9145506788031d7cf2c0212ca492c4d9335b86e8ecfc897083c622056be8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 fdfa1c8ef862df22d24a1944887f3d0ef992f8d43b5efc0ef2515c0493970e18
MD5 9b0fea58da6b058fdcc3f330d47bb9db
BLAKE2b-256 706cdf3bfb9d49a33c273f50baebae7695e26b98d56a5fc64d00524c39bf1547

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 90ba4784b5506933343013cc9d5ce105ffa4eabfef205494cd9377150ae63462
MD5 cd396571c705546051dca61ffabbe60c
BLAKE2b-256 8dbc853e355fbb94a5876774d16611d081d2762ab3fd9ad186277f82dfca4d78

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0b3f950a9169d7e19c37ba3f35ca8405ebbdc1f1ecc56c9f147cb2c563323de5
MD5 7509543182c510dcbc8af19918f89fb4
BLAKE2b-256 4cfc9057f2e41927248683f59f2b99fad50b10328a07c98c5a88170546d66fda

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 cceea906cdfaabbbbd6f3d9cf7d5646db6e79416ca0baf32172104b5df294c57
MD5 f8291a585a547917baa360183e4e731e
BLAKE2b-256 a12e5079f9e6a4d71a008057861bbd8f86f8d100686c85b8319d4f579af02d48

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 391bd954841780e4bcbb9b85c918fbbc57722faa3f03d170bee906c50f7ebcce
MD5 e73f22695b2434e2c030b65aea9ba0e6
BLAKE2b-256 836aef5e1959e856903627f4981709287f8eebff2429a04b501d8a2d532c784c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 74dbc5c5e4ca32c89fa4d99d7ecc001f57853d9af02b2a2754cd62e6c350563e
MD5 d3cb41fddbd3789fb1e10d7384f1d9a6
BLAKE2b-256 a873c14263cee348728e25bca11421a46a529ebc053d86e6d1eab8f7367af13f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f0d0e26265b5caa373138793cb577b858b75a490b69019f8c9fbc3d056575fad
MD5 dcbaa0a632c141cd996b7743c6c9cc76
BLAKE2b-256 45c479a39bbd0c16f6650be35f7ba0dfad53871dad8bff7dc1ca939eae386ab7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 982c8ae776fcf22c640cd506359277f45ca9b4ececd314a0e6d37bd9dc8632dc
MD5 039da2508d23f724b3fe1a6c165a1202
BLAKE2b-256 c025b4bf6ae87beeaf1acce2c2624478481b45783ece32f55e35e4abf1fa1753

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 1e2ea4dc6e6d0dc7c723bc79764d4530cae21cca209a22ce70cb7443d937d89a
MD5 52104c0f4902f7ffbf2bd1686aba0aab
BLAKE2b-256 128ae80b37e12f637d6f12b17e91ee4e8c93cae79dde00caea5449cb3320b50e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 b8ff79610c48a457769b0ae77a73cf2eded04597e3dbaac13e9260d70cd703d0
MD5 e38f27e7ffeb2a7a26f9ec6b6ae509be
BLAKE2b-256 7a7c2df4fdc270f3e0ec9d5830d5cccf0d57325bf87e58fc47d3919ba02789ff

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 dc44811d73173d98fb4842bf90e1adc8d953906fc9338be934d9fa09a4e86ca4
MD5 f6917cf509df3b3fbdbdbce2f4c3a9e5
BLAKE2b-256 222f07f348a8b85a004a0c9a44c114b5121883864aeff9ce7066365ea6aa5b11

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 18c3127379e71c2bfbfdb2642c9aaf5125a15f1c6942431a618ef23f437935e1
MD5 64982b7b4baefdc3b0b5e1a3325c32fa
BLAKE2b-256 5a6e8254ffdbb7ff939020ddd5ac138a89a8019a1b446aa19d83e63c41658c7e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 686c18342a440d5d990c9574ab43aab2f192de04f4674b320699480a041a92d8
MD5 23f150efd215f8d483e4e6989bf95a76
BLAKE2b-256 6e2d6e7de3cf4671143c7ade07c02ebfa429e148eff6fd8726e7487ac5a955a5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 d54515ce856d19e646378df8985881e07c44c44398201f4d995c1885e2279996
MD5 ff64ef11d1d30451a3bfbfef141ce742
BLAKE2b-256 fea70b26c48b53bdecc0fbab0d0eb63c8e09af0fe3e745927a9730c2804b4743

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 550dd5b582937bcadb98a635ecb8cb6df55fe4c72a1acd9ef7a2b0f0d1c5bb8a
MD5 c755284a449c8a8dc00309eeb499ef4d
BLAKE2b-256 f4a39442f7f5dba721721ebb3bb473696cae29244768007bbb021e0296dad295

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2f0aa82b4de66c25aa8e9cedaf2bcf70639789691a96efcb5be2eaff242f772b
MD5 99aba774520fa4ede9a42ce0641c085b
BLAKE2b-256 72d5bfb8bc8c4b4a13aa76ff6133df557b6ead404b2460066235db0fd42c6057

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.0-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.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 22c076a55461490d4edfbfe67e13943245c6e52427dec8f5cea6b877484c7ed3
MD5 8e86ee7e22efb70d451f502129a7d54f
BLAKE2b-256 37437b96c41475a20292ef9fad9d0ffcda214eae9ecc89f347272f6ee1a03cad

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 72e1327bbb26061675d783a40e290df0b32ff85298c9a473853434cb7fb2a62d
MD5 dd72a8a1bb7c8ea0932bae3d09eec07e
BLAKE2b-256 ff7e3ca525baae7212fa73366fa17386579091a6e75e28b44fae929fa185ff61

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 ea1699e26fef8410fe6f0ef97da30ab04bb734c430ab797407665627349c1359
MD5 c469707a3d4087c03b8e39aa8864b09b
BLAKE2b-256 11b5c704aced2aedeb725b2c9e164db21b04945a982f53736fe40a9430f202b3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a312efeff01a0b1af6ed5a05192800a50671cc17ec4670a754a3966313cef651
MD5 4823116af17d72531b03b67dc9dbd6ba
BLAKE2b-256 18a166bf3ebeba7ebbabcadfa7875a36e57de999e0a47c432203a3fe0d83b3e0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 83298f1a702892a5dc06fd42128041bb0696ad8bc1fe25fa811d2bfdf5151537
MD5 235bcff16ca9bc74790982c35bcb01eb
BLAKE2b-256 ab71b6f823e5a9ab30b6964b0e3cc602db8aea780a3c6bccfcd21ce0b9c2aa17

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.0-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 b87f408698bf2d0eb169fb707fdde7ddb483edf1b0a73682f3f546335e7c0c8a
MD5 eee36b696ba4849aef3c757647b0b039
BLAKE2b-256 b0a1c9bf1a6ad1bc22cfd9c75b3f608dcf76a45a1fbb2b88cc89f0974c2b9c7d

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