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

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.8.2-cp312-cp312-win_amd64.whl (69.1 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.8.2-cp312-cp312-win32.whl (63.5 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.8.2-cp312-cp312-musllinux_1_2_x86_64.whl (254.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.8.2-cp312-cp312-musllinux_1_2_s390x.whl (180.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp312-cp312-musllinux_1_2_ppc64le.whl (215.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp312-cp312-musllinux_1_2_i686.whl (196.3 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp312-cp312-musllinux_1_2_aarch64.whl (190.7 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.1 kB view details)

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

stringzilla-3.8.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.7 kB view details)

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

stringzilla-3.8.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (219.6 kB view details)

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

stringzilla-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (193.7 kB view details)

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

stringzilla-3.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.5 kB view details)

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

stringzilla-3.8.2-cp312-cp312-macosx_11_0_arm64.whl (71.6 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.8.2-cp312-cp312-macosx_10_9_x86_64.whl (74.4 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.8.2-cp312-cp312-macosx_10_9_universal2.whl (113.2 kB view details)

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

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

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.8.2-cp311-cp311-win_amd64.whl (69.0 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.8.2-cp311-cp311-win32.whl (63.4 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.8.2-cp311-cp311-musllinux_1_2_x86_64.whl (254.2 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.8.2-cp311-cp311-musllinux_1_2_s390x.whl (180.4 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp311-cp311-musllinux_1_2_ppc64le.whl (216.2 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp311-cp311-musllinux_1_2_i686.whl (196.3 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp311-cp311-musllinux_1_2_aarch64.whl (191.2 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (258.5 kB view details)

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

stringzilla-3.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (191.6 kB view details)

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

stringzilla-3.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.1 kB view details)

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

stringzilla-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (194.2 kB view details)

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

stringzilla-3.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.5 kB view details)

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

stringzilla-3.8.2-cp311-cp311-macosx_11_0_arm64.whl (71.5 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.8.2-cp311-cp311-macosx_10_9_x86_64.whl (74.3 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.8.2-cp311-cp311-macosx_10_9_universal2.whl (113.0 kB view details)

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

stringzilla-3.8.2-cp310-cp310-win_arm64.whl (61.7 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.8.2-cp310-cp310-win_amd64.whl (67.2 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.8.2-cp310-cp310-win32.whl (63.4 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.8.2-cp310-cp310-musllinux_1_2_x86_64.whl (252.0 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.8.2-cp310-cp310-musllinux_1_2_s390x.whl (177.9 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp310-cp310-musllinux_1_2_ppc64le.whl (213.7 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp310-cp310-musllinux_1_2_i686.whl (194.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp310-cp310-musllinux_1_2_aarch64.whl (189.0 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (256.5 kB view details)

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

stringzilla-3.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (189.4 kB view details)

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

stringzilla-3.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (217.5 kB view details)

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

stringzilla-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (192.1 kB view details)

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

stringzilla-3.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.3 kB view details)

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

stringzilla-3.8.2-cp310-cp310-macosx_11_0_arm64.whl (71.5 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.8.2-cp310-cp310-macosx_10_9_x86_64.whl (74.3 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.8.2-cp310-cp310-macosx_10_9_universal2.whl (113.0 kB view details)

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

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

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.8.2-cp39-cp39-win_amd64.whl (69.1 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.8.2-cp39-cp39-win32.whl (63.5 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.8.2-cp39-cp39-musllinux_1_2_x86_64.whl (250.7 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.8.2-cp39-cp39-musllinux_1_2_s390x.whl (177.1 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp39-cp39-musllinux_1_2_ppc64le.whl (212.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp39-cp39-musllinux_1_2_i686.whl (192.9 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp39-cp39-musllinux_1_2_aarch64.whl (187.8 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.4 kB view details)

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

stringzilla-3.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.1 kB view details)

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

stringzilla-3.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.0 kB view details)

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

stringzilla-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (191.0 kB view details)

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

stringzilla-3.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.0 kB view details)

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

stringzilla-3.8.2-cp39-cp39-macosx_11_0_arm64.whl (71.4 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.8.2-cp39-cp39-macosx_10_9_x86_64.whl (74.2 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.8.2-cp39-cp39-macosx_10_9_universal2.whl (112.9 kB view details)

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

stringzilla-3.8.2-cp38-cp38-win_amd64.whl (67.3 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.8.2-cp38-cp38-win32.whl (63.5 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.8.2-cp38-cp38-musllinux_1_2_x86_64.whl (250.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.8.2-cp38-cp38-musllinux_1_2_s390x.whl (176.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp38-cp38-musllinux_1_2_ppc64le.whl (211.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp38-cp38-musllinux_1_2_i686.whl (192.2 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp38-cp38-musllinux_1_2_aarch64.whl (186.9 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (254.6 kB view details)

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

stringzilla-3.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.2 kB view details)

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

stringzilla-3.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.0 kB view details)

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

stringzilla-3.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (190.0 kB view details)

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

stringzilla-3.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.1 kB view details)

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

stringzilla-3.8.2-cp38-cp38-macosx_11_0_arm64.whl (71.4 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.8.2-cp38-cp38-macosx_10_9_x86_64.whl (74.2 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.8.2-cp38-cp38-macosx_10_9_universal2.whl (112.9 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-win_amd64.whl (67.3 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.8.2-cp37-cp37m-win32.whl (63.4 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_x86_64.whl (248.3 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_s390x.whl (174.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_ppc64le.whl (209.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_i686.whl (190.7 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_aarch64.whl (184.8 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.2 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.4 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.2 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (187.8 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.1 kB view details)

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

stringzilla-3.8.2-cp37-cp37m-macosx_10_9_x86_64.whl (74.2 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.8.2-cp36-cp36m-win_amd64.whl (67.3 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.8.2-cp36-cp36m-win32.whl (63.4 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_x86_64.whl (247.6 kB view details)

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

stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_s390x.whl (173.6 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_ppc64le.whl (209.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_i686.whl (190.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_aarch64.whl (184.3 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.3 kB view details)

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

stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (184.5 kB view details)

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

stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (212.7 kB view details)

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

stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (187.1 kB view details)

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

stringzilla-3.8.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.5 kB view details)

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

stringzilla-3.8.2-cp36-cp36m-macosx_10_9_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 453ed1ebd61a1cd542ee46d0194643bd7dc74c8226a803d38e00b979ceffdccb
MD5 70c9a5da40380168f4aa4164c0c872c2
BLAKE2b-256 1c6ded279f63636c099e1a6e18edb16698134c3861e22fe18da9b7a494c38a56

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0af2a77b4c34f43c9839ddadb6f808c06a08693ed4ed0481e57fcf6b50276d50
MD5 d35184a5e907c65ecbf0c1eda9be6349
BLAKE2b-256 0b36cefebea9f2d1a9e3825ac1df2250309f41b416ea31df53f6526817a7b53c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp312-cp312-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 ec1c0808f8c4dade54c8fa2bd92bc672edf87fdbb69f119ebf04923539729526
MD5 cba638e5f5e417a3967e1457c5e98042
BLAKE2b-256 b55f603d42c4cee3d22ebe69fe4db1613041e8b975570f18c79154cef596dd6e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 04da2d7faf6efc0996d508706d5759a80adf0e312026b84563564fd714d697f3
MD5 651773237c33488c17d80af90be31738
BLAKE2b-256 7ea800f2d7c3ce043befdc3c53d5e2e2b684e150a52ef4060d03bd07721a45bb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 93d260fbaca11d0e974fabe422610ce926ea2c9f32d7725034c879d205aa2125
MD5 bd3d8aac1890fb82d53fd6f7b35df904
BLAKE2b-256 37abceaa66a49493178ee732a3516aadf0532d3bad6e603207fc5e51ceba5ea7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 129691384b58d452ccfcb50da687c9a6c8ce0651506b7658324a6c42ad70fb2c
MD5 b1121003fa6e5433d050342363de30b3
BLAKE2b-256 0e27ba4acb1463efb4185176a00ba04b069c52b9e05ce782557d95ff75f99fe2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 60f413342b663125c93574da0232e9b2154188d33d76d42f540c4c02e58907ba
MD5 6b067c066d07ef640ec8e430cb1b2aee
BLAKE2b-256 bad6909765ff81e9be50f35c0f5761fe54de2afb03e79ad22461876141b2b498

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b363779db7f1737e702b3ee45f74e6eb4ea77911866ba53b76abaf34ba29dd85
MD5 687bcaa6533c3b2f128a5384642dfbbe
BLAKE2b-256 fd38445fe41c3b53abd82f1fbb481944f425ecc10167bdcfd642174003f96ed5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e6c3e5698c11eef41a6ba31b0aa0c5a6d2d7869fbeb6c7ec9787e51740dc530e
MD5 34861e1f7e73b776f4e834d6cd1552dc
BLAKE2b-256 e1b259bb8c65dac8b6e44e3ebc35892afed89f49a05bd08851b174bcf6314bbc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 9ba2203d700530c32b8d37ce3d8f9ba8ac69c4760502c4f8449f22b32a4d24c7
MD5 2d7311cf26b710e7149839fea143e82e
BLAKE2b-256 f79e50c9d514f9f4848f206c3a24bb7d7c1b7de2d04ac6dc5c5cb1f20259ca59

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 5b965494d8f6876e9e7ebd55457bc8bb9b41a6bce89041176649e6736a4af128
MD5 4ebe08a6c35b47c8949c717d2bc1b2a8
BLAKE2b-256 1c60306d8e578b3e4425cc18889ea12885eed4dca5e1dfc87804834765bc2df2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 16df7bc6951fc29d75ba1725dadb96fcd3865d041c3341c567b66e5e9f216cea
MD5 867745a938e1c164be811e911dd47ea2
BLAKE2b-256 d1188796704c2e2cb6cfb6926dd370775a8fd7ff250cc49306a96dc2a7f35055

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a42c2133324d4b348b640ba82703b5c6d663b9fa4a54d226c84e600f37f527d8
MD5 8c48164d809e2e9a7ef1e010aae0fe1f
BLAKE2b-256 456d26155b9fcdd9453b2b93b32850393c22429f0118bbf3b8f7e7c71d742990

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9978d6df4ae3d679d9b131adefe6d0df8247f5f3693977865aed40dc9ae4376b
MD5 248c3d860eec8234bae32a3fdc44118a
BLAKE2b-256 11dd2da8ee98dd84073af7f80c6c16445e3db198890c6559706d30d71a77920e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 74563cc15819c27b25a415e236a6612da1400a3c995241f53e459da3f5757967
MD5 f599dedc4efdb8ef4f73071e551d7118
BLAKE2b-256 8601725ecbedd47aa618b0fbfe2c574ab4a7dbf62457787971e077f2d4629ea9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 907227820f73dae84db7d818811fd6399339964cbdd820e910eaed18e418393d
MD5 dea66bd35c6461cef011a1e5031a3958
BLAKE2b-256 2a46d3dd24a8b512c9456a5ed5a48d58901b4e03d6d0a86acfcc1999f780889c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 08d98d5b3541605c3cf75822b24e48ba8ffec6afbc74a56ede4500525ed421b6
MD5 dde4ed1c8add205a8994406f1120c2de
BLAKE2b-256 cbac4e35653668f5a79845793f71495a0ac129b9ef556120c317efd4e8671e38

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 7ea80286384da5e3d9f1eb314798b878710789442eb58418eb99695bda119f6b
MD5 ff531a2a8176c8f7033e0028fcbe19b3
BLAKE2b-256 f98f431582299fe3382aeddc868eee617d07c07011146a94057c846422c6f7fa

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp311-cp311-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 2fb79318106f463be58f853f8a1a9b6c810b226670ae39c7ba7a2b9f4d2b1880
MD5 de133f56dc4c124b300793476c6252d3
BLAKE2b-256 71d84b67f3fe38a4b37496decc4b378d0ab6775e06f11c5651e9436a55168290

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7ee310171c9c7244f04b07ece0b98e2b99fd08f704041dfce30e2b908e56dc71
MD5 2b8facfa2ea46395730c22cb35805426
BLAKE2b-256 d9dee341c7c69816e0df9bbef662ac8075a4b7188de168a98d1df6b7d2c9f2f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 4a60682bbff7fb366313a67f79e44a5df39c7922e4564b8fed0a614dc4b37d99
MD5 41c3c1e3b6fb791432c528c717594c93
BLAKE2b-256 5f80883e03e5278bf066abdd3771c2b77c7dfacad21846fead47d72c97c0f6a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 8ab4c5a30c574a9089dc0e2d74e1f6ec5f4baa6998524a304d7db459efd7c4b4
MD5 3d1cdf8c81b54419a80a86ab6345295e
BLAKE2b-256 713b2021ed228f0b1b532967e996ae422fe2a687c1809f21a6d60e5457592fcd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 089d9982af86a86a6c0d58c5004afc0854cfb24874bb85f857da0a76b6534951
MD5 b239467f1089416dfe6c4977181e676e
BLAKE2b-256 d2d907a507a3d276c6631bf40bb3f1df9754c3f24dad2b3f68182d1bd9881ade

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a3b57eac63764c79ed4c1e00eff211021e7c5189ff111138825f95f7d8267560
MD5 16bc3fc2743f1ed6bfda1769ad8e7237
BLAKE2b-256 f6e24b9fcb473b9efbf384982923c8df12626296159261e28ec594c8184507b4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a5f7e7d3e2633996ab9573adb738d7d01ed93b3aa0a32795e89980c77b62caef
MD5 7830735fd3abe28d26c0577dddd1f418
BLAKE2b-256 525c6af73bf8f67e8ae8b0756d367abdb162e9caf8af4b6572e843683ba7273f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 23e9444d08be149c17b586c9006407300de31e64b30e33ea57dabd6882fc7c65
MD5 0d223264e3fb13ee49a1c049135ef0e1
BLAKE2b-256 e603702afde18c53b5d4238551dac262b6bdaba46ca704d3108cdaf91b76c37c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 65be5b8bcb8abb74d982558ce11c699c1576c99d576270cf10218316301e5962
MD5 a1c90f4ecc5bf69cd418d894ea8a3fd6
BLAKE2b-256 ba7f7cfc7e5a3cd98a86c76cc55a3f1913ab6ee3a988bb5d89342111e2a12dcd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 12b450a2c84c10b5adf95beb8d406041d3cc6f633742c4738ceffb4580543549
MD5 b419abb946984bc05a474ef792f652c6
BLAKE2b-256 4ddd13dd1874ec20573c55a0fa19cf18afd0ef3f8aceb004744cc702c609c928

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a877e219b1c9db919e5669cba1a45908e5b908b702108d3bc8e5e8e4309682d1
MD5 3b869d63340ba9e3fe5d1cf8c9d2052b
BLAKE2b-256 5be99aa63830a241a6ec135f62bf6253be9039498c6d65b52b7264c12a862747

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e10d3e07fd7b2f8f6b10528937b41777569fcd5d0213636ac3d17f964cf20fd2
MD5 adf73b9b8ef0ca333fea483ccb7a18d2
BLAKE2b-256 3c4f0390b189087e7f488fcdffc3f3f8388ce1a559cadacc3fbc17a099f978e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 ad5d28acf82a6c75a414e34d2d08be5fc01ff752561976bed9d45de3be8d88ab
MD5 c3f23a7bd148120d0109940c218a1782
BLAKE2b-256 7e8a5c3563debf4d9bb3f1685efd987c10be7ffe4ea514051428b2915d0bb585

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 c0c7ab94c7f176cd98f1356649b939c957422d3452882c22f10a5ff1cb4ed252
MD5 d01918359351ccd6154c194f81a8b94d
BLAKE2b-256 1e9e3ee915c31330e1dbbf78c5d14f8bb7cab58a01a2e6602c5720890b5c1d94

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 5fdb9fc24ed0eb4b8318ed0351735f3ef01a469c2789077cc380e223107fc7f4
MD5 53b5ad86596414c1473d8443d5fe700a
BLAKE2b-256 37794b7e350ea6146a981927b4ce5085a61b4495d2ad806d6c3efa166175732a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 ea859f7d23d39bd0652e445766bbc24d41c18af58900e03697fdf5e00223f82c
MD5 9110d31708c192a20977416a39170723
BLAKE2b-256 20b4a07cbd98703a2b18b8d29f3231f73d5175255a77f0dcf5b6b855e873f8b3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp310-cp310-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 a5096828095b145df70b21372e417cbc8651f7b5e1bc51b9039057b26c7c19bd
MD5 a45cc4d8b919b892b227f3517ad1a2e5
BLAKE2b-256 ec31ab9da65c453822169644a2f9723668520d4c55cbff1476ec9c64adc754d7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 180bc977c24b5edd9e87848af9328d665a016e100322789c5a57491642bc80d2
MD5 f041e61bb4a43653b58dcbcf1be81757
BLAKE2b-256 b896dc09bffaa153290d0dcfff6cd255f38fc9cab7811e3638f4a200f58a368d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 fc2a4cd524fe5fa9c6ceb3a568062c1b3beee81ca61a9357583bdf7ea00aede8
MD5 14f717c0732c7fbce5d8490f125bbea0
BLAKE2b-256 9b9e2dbdbd20ce1a2ff8c853f76c8cdeb12249726c0bcc4d492fd531fe0f0651

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 f5566c2d835723a939cf07ae1a7d362b06362c3669da4d8f247c482da64b5c69
MD5 df175026eff1a4f20092db8a6c914acd
BLAKE2b-256 ef4a53cf2b9cc9cd0c1b48e38afa1be224bde172e3aa29a810a30e3784f8e8e3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 a03793227000147674bdd8913d5c2fd644120a484314f8ba56fb7cadcbff6483
MD5 e02da34a0b649feb8380e838ec09a770
BLAKE2b-256 720242c46f24af2d194b3a18bc7139c79c5fc4ace420561b88edf60e04911656

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3608cb06e27ba49bc4472989dbc5e198254ba19cbd57221c74a895e7691953e5
MD5 fa423a46af3f91aa0b24eb6322e932f9
BLAKE2b-256 db53ba144cf461844ca2f4e36e6883e907f051444425c1f71a623b99998f56d9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b94df818dc88299d8743e936711ec6c11b664c563e9ca3f84c91fd41212b7ea9
MD5 a375b3ad36936b243e7cde6eefcbaedd
BLAKE2b-256 dbdb6f505a224b78411d18a26a7cd31b014cf616bf81a65790cd582fb026b327

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 990de241ba3b7ffc810018f4b7c381aeee8db94783d796b861230fa819169970
MD5 69f95e70eb30276cf7789a264213bd29
BLAKE2b-256 60f00caf8205141cf63d87fb26bb09b788e18d27670c564ac0b902233a8efb38

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 472b6d74e28735b33dbff4926ca3e2cdf12016299bbc4c823d3210f81f97afc1
MD5 f73ea95121617c2e862ccb27a305f4a4
BLAKE2b-256 b4ecd13521e53575fb8e558822c9f9a91ca9cacdaa6b39276eb7ff03c9e65ca4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ace1bf3db2bcd3370ca7e951b88b15f58ad649bb79e8da3e18ddc505565ad0f3
MD5 c4e7cf0f74bcdfa0330d3445d7d28173
BLAKE2b-256 b75aa3bbd4a21fc852f4fca0d9901967eafe6c76583a4b09083083867d038e2b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ae4d364ff733007d4c63bd509eda1fb7c68f1c4d1074539318c506d521333e9b
MD5 6dba8ac5af3fa495aab0a6159fc2fcfd
BLAKE2b-256 b9c9ad47f8c9906a16c22ef906f2d99fa3ec252d47b982fad414f587a7a0acb3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b6c2cbe0d153b6b0609df66e46ca08e7fcd232f8a7b92291d9b83b3c45ced632
MD5 7ecbfc4a55662896d0c233fe1c9e9ca9
BLAKE2b-256 ef12a5e9aa31e93efd2f2eb6690fb11a4b09a38d6053321126f261ece3d08717

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 9c5b1f28df440f8a6ef62a6a1d7c325d7caa94fc30e6639be41e50d1c2376eed
MD5 b25095785e8c1b4abb382d00957b63fb
BLAKE2b-256 28f054d8efd785fe797c2aed91ad0417bdf34ac3e02dcd5e43f93d79faa84412

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 2b699c348ceae636165a8e38ea2d218dab0fc617f40622d24e4bd79a887df0ae
MD5 b1e2ce44767e40129efefc459a234a7c
BLAKE2b-256 bc9a2ad842f6b2167919b1fa7a728d0529371a29cc4e8e126682adbe97cc7659

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 2aa319f7fa3dd3991ae0e38b6eb2c8f9feb7451219a03658df287cfb6568db4b
MD5 f1620510748755079427927fb6b62e29
BLAKE2b-256 243bf8c757bed5d8ffdb49c9996770d5b84700b6ca91a7871673d499af8b4df3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 7d1b997334425284f9ee6f38c5640ec057bc3224e4f7a305c07dd2256819715f
MD5 0ca9a1889845190e75f69fcf1020d054
BLAKE2b-256 5b00afc1aae4aa3119b597b7a6e648452c96f5f72824c8fe55891ec9f8918f0a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp39-cp39-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 1548e545d2a5a9e7c84056f481147cd9a9372b5d30fcf71b5429c4e682b3a1c1
MD5 f6a4b6bd3f6256058befe317d2515927
BLAKE2b-256 fd0d7d00b0161e9bed60091aacb4129cdf58cc3d786ac15c9acba07b7228581f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e943c2a8a7a50423fdb7d58fe31a82c5221a57125a6f5c2c5b55564bf801d2ad
MD5 f7c06c3323f14b2c44fcde69a55d7b63
BLAKE2b-256 1937590eb1f60e423c781717509581a80d12e0c9d220d1a137e58a98d4ab68f5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 ead337f830c449bf2512bcbf2066d226b006a65271aa12eaa3b69f95a4f1ea49
MD5 786579396cd2267621e8927749311b69
BLAKE2b-256 2c6cc4b376eca0364722ddf2b43ac6f07a1acf99b781f3a9ca1dd2c58ee72b43

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 8b6cc411552b4e8f336d34db1c17551ff6fc6f8662e32feea74dae3c3dac4194
MD5 fa5212020f07e0c0ec5177f5dcb71976
BLAKE2b-256 3b7c3753c5872f0de4d1fc746ff39ed8b2af8f9c428d285d55e385bfda776522

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 29c33755da9ecad0c66c16519afb70c937fa812cdb7d9c5907c10f941bb68b00
MD5 ae092efb6aeaacbed95bdd5588424894
BLAKE2b-256 4823aebaccf587241445383ea811361a8fa188d4694f0b1e939d0626d77f7658

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 7ddbcd0745218c14c37b03986e31730a1fffde696f3ee0eb974a764d9d0cb7e4
MD5 39b15e4900b0a3f1591ff4b05c7d0356
BLAKE2b-256 1c7c3b6298cda7346257e21a709446f5d468fb14c4305630f52d34bac4a765f0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 77bf26f4c6da9b8f1475b58504760be0e056fc10a14560a366dee2903a0c868d
MD5 5d5fc781edc4bbdc0bc1e82826c013e4
BLAKE2b-256 a992f6ab75d7b1b6e52f4e574110d41e814662c064ce247eca1e51eaf1ee052f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 36ee6bfb338cfdf19077fd7883d5694e6e14d1864b6bedb412b7f89c8b471fd3
MD5 bc15f451054c0ba2e49e4bdab8cc1a31
BLAKE2b-256 1880e4ed91aef963ab60b4ac924b316d7792f0e739c45c7f17764c20a373be4f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 0e404b40e1e189860563eaaded9f5eed42220982c812b528f97ae479b3bd0cc7
MD5 cfcb624f984811e339a07d257ce6ca8a
BLAKE2b-256 100385cd87febb8ef24131484bfd806d08fe266004bdf57946f1a71432b19779

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ac121314ee1420a6cce52c0f27fa499aacf941c2d1836a08e8563ae89ec11d69
MD5 727d78da5edddf75aac32d596454574f
BLAKE2b-256 0dd37ee32bc2de2f25ed7f9d67a0b4c6b23a78bb07afa9898cc5618bfb690a52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 5572cabc4bcc50ed169ce1d5961e4ad56a4ee9c45a231ed6058af46c9395d3a4
MD5 50ca9de151ebaa2b96ae678e5ed426ae
BLAKE2b-256 7fa353db99bd8eb11d3b6672228285c36e1f683bf2a3cde4ccdb7b775a78bdb6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 491be28e028727265054f485a90f04a6b59fd4cd7b138d967e923d1e23543763
MD5 a1672996d864c5ec05023542ee30b795
BLAKE2b-256 40f1a0ae4570ff1a7947f814bb893a33669ba00b32d92a01f139150f7f0c0c8b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 33c077f1341b671d335a01bc220777337e0b8a5bcc67f7ca5413b35e4916db1f
MD5 6048455c4504df0ba00a58815e22385b
BLAKE2b-256 3466892468e88d2d4af6ba247f1862e130b9f7dace840b3ee232d8c9fad098c1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 370af0ce02804e0b97d139130d23d5db4dbb85b4d75e9ae31c4294bf164f22b9
MD5 cf18d6ca20a2dba4bcdf04f933b74c58
BLAKE2b-256 0399b1aca2fbd87837e5a78967c04aea4e5263013db752f9dd1a27ab19f0c358

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 3fba17b91f29ab5eeaa1fcf23656c18bcfcee3af8adb1b83adf63ef2a4b8f0f5
MD5 cb18cc2f336db1a2fa0433102eadb086
BLAKE2b-256 8f55a8861cbe92339d589665f9b7fabb0687ceea9fccbb37dc3a96a9307a3616

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp38-cp38-win32.whl
  • Upload date:
  • Size: 63.5 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 16a44e59d45cb4495cf73f3f03963aa4b92865e3966047033914b0f0e106aa84
MD5 f5bb54347985fad8c7fd6fd33ccac1a8
BLAKE2b-256 82b24705b23a2d6715e864deedc25dca57758d312f79d8b0e56f31995ed3c880

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b52787e64536239541dd377fbb367c493601d9426f8d9ba8cfa0e1b62ce7d6a2
MD5 a721d265026a7f68a15639e605a7e6c3
BLAKE2b-256 80307a01361a9334361ed9de612c377b564da3af36b48c32c91fcbc7484a7a26

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 c4e2f7a535d00fbac4ed5e7d1c8fb3a582a71c21f388b716dd650162db4e87b0
MD5 2d0d6788928a6cb4f4d0c080de782a40
BLAKE2b-256 410c9fcaae5f484ea22d0fdb92b57c0c379f3296470b01cdd6f6626241eed571

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 3f0753e2d1f2cdbfe590562bccad0298f1ce4f6da41d71549425322bf5f584a4
MD5 605e142b4bc109d81235912ec6a6760d
BLAKE2b-256 fd0ff91e0419e6ec14373be1421c411d71da460306f2c837c529d05a5e96453e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 0c49df8776234744439a158bbe5cbc16e07ea5dbae3a804364efd5a428aed177
MD5 daf586e2b1ef2debdde556f419999898
BLAKE2b-256 e21ef737f3093833bc54660be6c00bc799b346f6616a38ee3be0d3953d3c7198

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4cbefa4a73717977b9d2d9c988325169c57083af8a2fdfde5b47066a1c09d542
MD5 e0ce3e12ffe71f39ec188d57d7d5312b
BLAKE2b-256 5bda36dbc754ded44609dce7801cdccaaf2097fad15bbdc7439b334a6e423d32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ef73bd8c7b9d6d59471b0d09444e9cb2771cb0d92ac017927ea98b2b036145b1
MD5 d4841d231f26e5df718fbefdde273f16
BLAKE2b-256 271e942ef3afb1a16351970bf65e737ebd30abf79b007f76ff54231b1f68b72c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 dd2f44171ec92375b6abde87fd128bf451cbda16dee52c9fffa01ef5fd2072ae
MD5 535802e35afe4d1f1a8f2e09ac895ec0
BLAKE2b-256 9c7372eacb63ce7125ca91363cddd2da6fff0606f08f60ebb77a24b59983e5d2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c070025ada460c3ecd5705807461c7117e0f01295163ef5ec498d80a372ee224
MD5 2baff938e4d5ffc26340235bdd8e052e
BLAKE2b-256 2ee3ddeab3c42b24bf9fbaa414bd56ea6ae0a25c59723c997cd6318a624af51e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 31b3380ab61298058093b7b6868e5dbffba866b51cc9cb8eaea338aebcd79c67
MD5 b643885c612b59ae81b3d3dae2c7f442
BLAKE2b-256 62294d87beb0db72b91f05f56cf7fde89fde81604ec0f1db72bd3c16d90bb712

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9d42e78fd3f2130fb28153ac9ef1e61754f6f7ccc9c4c82e352da57c68fd47b1
MD5 87f5b71956947c070ca5415ab8636292
BLAKE2b-256 c29e092ba3485f85d9504dd8cd55c59c7d640453c675c3347010568d9d3cba34

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 62b0069a1222c2f2153b44e0a99e8bed4ee3674303eacfc8e3d82a96073f78f8
MD5 6cc0529c4d51319cf9eaacc373021b35
BLAKE2b-256 e4a764f8131290107ffbd76046b8ab006ba50978ee67a7f0f2cca401bc474abe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 e961d7ed5b9ec31c176d1531b09a04301f4a4d4a8b4c65f1ea7cc6808031ee91
MD5 5d250b511f0f91abba4685d900d854b8
BLAKE2b-256 b4938a9518707aba60c69761051279e63e9963ff6bf0aac0f80d0476e7f83f3b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 a483e00817033fb460fca998c647ba99c0693ee6acb826056dc0cf0fc15b540a
MD5 e754f3f20dc3d051b0d2118b2adf8f20
BLAKE2b-256 661387923c3ccee7823c15e75eea96fda5ffedbe6620afe7f20e968764410411

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 3460883ccc2abd6a83361ecdabd949d20833fe58d9d4264046adbf0471f788cf
MD5 de532d0b9ec5b45a74135e77fa271db1
BLAKE2b-256 abcb70bf643ba9f680dfb032cb743047b8743185c54dc7d5cb611c58b8251826

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 3df39a71cc588a76f4dcba3ff064877c97c2646bfab50145ff54069cc6cf1b95
MD5 99c3bc83ce43dddeabf2e98a1d70bd95
BLAKE2b-256 a4da97c229d550142d07839ca38cf406d18d36385ecd93d07ef3866e31f2f16b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 49deac8c1b60bfee32920c0f8f3372d1faad3019cfb90ac87334a6a4bcbf5765
MD5 e2eee79968c20462a367d6d3c8f691dd
BLAKE2b-256 f1a7e9122aa7e9d817ac98e6f433606577b965875439cf2943bad138757ef22d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 7fb127ef55d725233fedca85a5138686a79cf1d1b966dd15f3d33471b6f299f7
MD5 e6f5a4fc8715c1f3679c0e06339a8f39
BLAKE2b-256 456a352fdd1d3ff0bc0e8233d0a268da50746c568874f6ada91d31d6b1e6f587

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 3f389af1630e17338076bff51ccd4eea2212d50374b13ed3c276c24fec4e5122
MD5 02896525a205e1fba311a587068ea47f
BLAKE2b-256 ab643f134f28cd063d726f1a6664bf0b72fedb173018eb2198d4238dcb3568e2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 498d17ce724d9f10c318fa1081459d3d35782d21ed084775aeccabd13b59c9c9
MD5 92f16d82982bfa67e16216eb4b798696
BLAKE2b-256 b96235468841cb79b2ec6dd8eb62024711b79dded0869820df5da9d432a5ee01

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f2f16ae1b3ddecd5a7539be2c4fe7806a21197bf7c57d0f8332d03aeb21220ad
MD5 39497ac7d1a7e8e4e9c4bbc4c188bece
BLAKE2b-256 52a8e03518122dd8c7c716807dc15e1675b60e5ed06fc3e1ea3045e9eb86bbf7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 6fe01421724a2e617e4f8100212bc06c62473e103055b4a864178266fdae5c8c
MD5 e1fc3901e818ebb992a12735f95ed177
BLAKE2b-256 ba3f9f763d6c2c2f8a3a34bb3c83644a485edb0360060f5900c439f0a5d93a0d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 14dd98efbdcd2ba509422f9e134afe83b8afd233be08d715b9b076638961680d
MD5 5131c8eeb52fe3707ab1207f9eb4a494
BLAKE2b-256 c7ef3db1209bd57dca6c0d6afd7ab0ca26227ba6c40c2670396228cd5954a77e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 61270ec1a3f1999cf34cf783041a2c7d9cc01f94886773f821fff6753b0d362d
MD5 4b438c95b263d026fcd536c3f0d71329
BLAKE2b-256 b42dad0973b554bf439a3cd9090068f51de4f7ed5cf84b55d4f2991476b0d29e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 acc851487280c430b1b7a76aeaeae7b001734adaa4a319a13a0d3231a4c92df9
MD5 f77f8646c73c3b41f8edb81ab6f23d5e
BLAKE2b-256 4a7028fe9d63efd1a49d3bff0c68adc72d83cb08139b4057b2e2868463d3d79e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ca5635854107c35a2d3a19fcf85d7059400fd8c994e4b1ba15d3d7800b84a116
MD5 9ebe6ed43afc13c6bc8223eb4d638e96
BLAKE2b-256 854384bdc6bc69cb7d86737248eebed474b6183be24a2438237c8e4c5251b743

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4b521aa04ec60511e71aef82ba259ef9699e627bada5c2e238e0cdc919f7a46b
MD5 beea8330fb766b9f35cac56b7c39514c
BLAKE2b-256 188ac19181863cafefaa5c729cc37a7151c9bae8481fd6232fc6cfff2e24a4dd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 686051f0ebf89623fb390033ab89e0017b9530318f77181813fa1f83eaf68beb
MD5 76599deb09e94d3e3a4043ba1b40582a
BLAKE2b-256 1a7d6505febd0335544a6c434b79c0b4def42e25c3f3342f351cd14b16fc49fd

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.2-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 63.4 kB
  • Tags: CPython 3.6m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 64449e9bc81be1c2619b12cea7414ee6904c06d6a1f05c58e246ebbf4ebb3d35
MD5 1ce567c36f03356b31fe6fa6c3cd6efd
BLAKE2b-256 f9653f276c188eb650352990a776e0ef2af7e6ca26199654d5782eff43e5d4bd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9577ad5d869d0dfc8e8348f1e40b8889191f11586ae2e17527cf9ae724d4f6d8
MD5 0453851950024695fa42dd26368341b1
BLAKE2b-256 88c494a6b9a9e4aaad61f0a7abdf3a4b130447a40ca77faa346fd73df0a8664e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 8f9e57d31f4bb3d2ae994ef44334d574281232e6c932a578ea7ec51e8c5025f8
MD5 04b0a3fd7a60f08a61984485ba407395
BLAKE2b-256 9c5246685f6dced617d267e4d51b4c46974cc271426402c13f975bcd77256426

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 48353181c483fed8dc510660d9338f93db4e0432581c226b65dc2054381c2a51
MD5 4b1c801ff0ea39b8b84cdbcc8312f066
BLAKE2b-256 56a4485f753d395a7cad6edc19f264064258344a2f8aa9650191a9f14a5547e6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 22278e2b169e08069cfb0cbdb13979f697155916187cb569af2b103f962bc8ac
MD5 b96687624c1fb5618cf6f90f4d145686
BLAKE2b-256 adfd7047fac72f05fe7701def8b58e3dc2425b5466434c049573df09b2e83127

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 67397061c93e5c3e7e17d8667b6546a240a59de7954dab2085866c8e173ba3e2
MD5 abbdd02c531d7afd88c9432868644c1a
BLAKE2b-256 ff4667acc5bb0bd9e92e7584533a0305ed73e71ecfd66334f574b52434f07dfe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 2807bc18a734b9f1dc737e8fb122f2d6c05f333207373db28634bba8f513738b
MD5 2df982ca537a44275b11fcea8c59a8f8
BLAKE2b-256 991f70ba677ab55581deaa431d9aec5bc6332f45a22f70206deeda4463ab3726

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 3a4c59be4218894ef3ae24c0b4b5688aedd6c2235f38068bf7bc9558e73eb613
MD5 442371b9d9a2dadfe3f23c2ebbad5877
BLAKE2b-256 be661323f961e68a14626377d303bd1f621409f2a6485fa7cac8b3f0f7bef950

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 21aab278ae6e7e873997882e72c31ac735512fd5cd4fcff68ec13ad9f79556a8
MD5 068f17d5776f20d4b3bcc16cb81aa506
BLAKE2b-256 882a04dd30e19f98dc5f384384bc4292c7d5993b35babb3723292991f6cd32bb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 1a05b09c4d42107089704e3c312bc2ce0823256332cffea34c6804991ea4599a
MD5 cd59e89b0897578b0f25c9df9ab05dd8
BLAKE2b-256 9735989148fae558281495601eb8b499a5ebfab79a9ae9e71991ec72031272a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 31a06004eca914c8fcd9aee8444b87601d19621f204f869fda337696ed41a596
MD5 8cf0c286c66d8044eeb9ee69d83631b4
BLAKE2b-256 f3f9601d2fe677692850969a5282043c6a8c0aeed289b1bf01361cffc57e50d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.2-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 105dbfc31c5bf1f0d350b8ff79bf39e473b9b00e3af146a5eed0043dc0ae3ffc
MD5 dc302d40b0f437632263e11d9d2e8fa4
BLAKE2b-256 bdce437460ec9d0c880f6c2179b199decf2860f74bed9a7ec14bbc7650c873f8

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