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

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.8.3-cp312-cp312-win_amd64.whl (74.2 kB view details)

Uploaded CPython 3.12 Windows x86-64

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

Uploaded CPython 3.12 Windows x86

stringzilla-3.8.3-cp312-cp312-musllinux_1_2_x86_64.whl (254.4 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

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

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.8.3-cp312-cp312-musllinux_1_2_aarch64.whl (205.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.2 kB view details)

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

stringzilla-3.8.3-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.3-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.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.3 kB view details)

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

stringzilla-3.8.3-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.3-cp312-cp312-macosx_11_0_arm64.whl (73.6 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.8.3-cp312-cp312-macosx_10_9_x86_64.whl (73.4 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

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

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

stringzilla-3.8.3-cp311-cp311-win_arm64.whl (64.1 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.8.3-cp311-cp311-win_amd64.whl (74.1 kB view details)

Uploaded CPython 3.11 Windows x86-64

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

Uploaded CPython 3.11 Windows x86

stringzilla-3.8.3-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.3-cp311-cp311-musllinux_1_2_s390x.whl (180.4 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.8.3-cp311-cp311-musllinux_1_2_aarch64.whl (206.0 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-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.3-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.3-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.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.7 kB view details)

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

stringzilla-3.8.3-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.3-cp311-cp311-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.8.3-cp311-cp311-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

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

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

stringzilla-3.8.3-cp310-cp310-win_arm64.whl (62.9 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.8.3-cp310-cp310-win_amd64.whl (72.4 kB view details)

Uploaded CPython 3.10 Windows x86-64

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

Uploaded CPython 3.10 Windows x86

stringzilla-3.8.3-cp310-cp310-musllinux_1_2_x86_64.whl (252.1 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

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

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.8.3-cp310-cp310-musllinux_1_2_aarch64.whl (203.5 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-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.3-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.3-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.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (207.4 kB view details)

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

stringzilla-3.8.3-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.3-cp310-cp310-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.8.3-cp310-cp310-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

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

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

stringzilla-3.8.3-cp39-cp39-win_arm64.whl (64.2 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.8.3-cp39-cp39-win_amd64.whl (74.2 kB view details)

Uploaded CPython 3.9 Windows x86-64

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

Uploaded CPython 3.9 Windows x86

stringzilla-3.8.3-cp39-cp39-musllinux_1_2_x86_64.whl (250.8 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

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

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-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.3-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.3-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.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.3 kB view details)

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

stringzilla-3.8.3-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.3-cp39-cp39-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.8.3-cp39-cp39-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.8.3-cp39-cp39-macosx_10_9_universal2.whl (112.3 kB view details)

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

stringzilla-3.8.3-cp38-cp38-win_amd64.whl (72.5 kB view details)

Uploaded CPython 3.8 Windows x86-64

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

Uploaded CPython 3.8 Windows x86

stringzilla-3.8.3-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.3-cp38-cp38-musllinux_1_2_s390x.whl (176.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (254.7 kB view details)

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

stringzilla-3.8.3-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.3-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.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (205.2 kB view details)

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

stringzilla-3.8.3-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.3-cp38-cp38-macosx_11_0_arm64.whl (73.4 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

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

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.8.3-cp38-cp38-macosx_10_9_universal2.whl (112.3 kB view details)

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

stringzilla-3.8.3-cp37-cp37m-win_amd64.whl (72.5 kB view details)

Uploaded CPython 3.7m Windows x86-64

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

Uploaded CPython 3.7m Windows x86

stringzilla-3.8.3-cp37-cp37m-musllinux_1_2_x86_64.whl (248.4 kB view details)

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

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

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

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

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-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.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.5 kB view details)

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

stringzilla-3.8.3-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.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.9 kB view details)

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

stringzilla-3.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.2 kB view details)

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

stringzilla-3.8.3-cp37-cp37m-macosx_10_9_x86_64.whl (73.2 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.8.3-cp36-cp36m-win_amd64.whl (72.4 kB view details)

Uploaded CPython 3.6m Windows x86-64

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

Uploaded CPython 3.6m Windows x86

stringzilla-3.8.3-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.3-cp36-cp36m-musllinux_1_2_s390x.whl (173.6 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_i686.whl (190.2 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_aarch64.whl (198.6 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.8.3-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.3-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.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (212.8 kB view details)

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

stringzilla-3.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.0 kB view details)

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

stringzilla-3.8.3-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.3-cp36-cp36m-macosx_10_9_x86_64.whl (73.0 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 4bffd96c4349b832b7cc701cf327b3b49c745a650b71104749258619438432fb
MD5 0c2548c7ff1941f3ed0ea1328ef31cdd
BLAKE2b-256 64f1da4ce95e91b155f0a71e5198711cf61faf049f2d9013ad64a846d48768a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 68d4151bcd7c53ad7aa983222e678fc6822ef570383167267844804f1d063b2c
MD5 cbe87973241df8e392edb7ff977931f1
BLAKE2b-256 40052d68623b437e7602809fd39efa71e9fa14e14df3eb37ee4bfe72bcca7375

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 a51679e4bf6b6bb735d66d3811f2261df80849bb5a99ebb2f5034322d1bc8963
MD5 8b471487d795fabc8c6a5c86266dde1b
BLAKE2b-256 39685f9c9f8b8582d78332f0a91967fc0887df7f99afbcdf9f4f7953711b8420

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 48c0acf5680b3ac954cdc987625f88ff8892d35209cacf80a3aee1382a973435
MD5 16a2d0922cb435bb99509b55223a9b48
BLAKE2b-256 66d2fb5e81775c60278e0190724a6195cd692e96353c482068bc9c4661ee53fc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 9c3541cced6acf6b64823850d8674bc636f24bdfc83481821d7fe48b6aafaa3b
MD5 ba32316f21164b908f4254843b7932e5
BLAKE2b-256 ccd47d6f142ea6ce01a11d071e434aecbae17284c5b3668e61b960218166ea8e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 51978988176956071c72df6cc8a6705bc0048319133a297d7ff0235db790a742
MD5 e03f9e75f506c63dc7231832165d27f9
BLAKE2b-256 48d39dcf73f15ae260c86b464ce765a81343b1ae0e60fe7f8e2c37363904486c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 6a1f8b3fcaa256e85db01b0a430d3fe58e647a843b3c230439eba8ca3108213d
MD5 bfadd3213a9c64a3e35024ba575c8c1b
BLAKE2b-256 b4ec5c43aec39fc6eb41dc26da0ee5120ab5a07ef3a7af8e815412a8bdaec069

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5b0f0a4c2a556be1ff4de2c8cd9968f27947e6395ef8f039ba8eb9533922fac0
MD5 272cada278e02971083eaeb87624aed6
BLAKE2b-256 ab8e0654b7c51512e8c582b2d68d52a6f3ec700beff3a5001986ac253a293237

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 aa7288dd4c338fa5d5699f3ffdcff1b629a41850c1c1e3046096385fab9d81ce
MD5 17f98f00df739154aef11385fa0244e4
BLAKE2b-256 393fb50781626d554fefd4ab730de1637fb2d4163c7bd6ad0062aceaf87fd944

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 78ed87ce9e05a9d430d37f82faa0e4e601c650ee4b6af9a35ce27a1946fb4f11
MD5 02d51cebe52cd73cdbee497fe21262db
BLAKE2b-256 5f383434c5b82b5a2ab8436a6691807f34d48725612ed67e682f406ad7d5df83

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 16c7a6815a27da794e9b8fa3cde92b641bcecca92f1246dbf293e2045b71ea3a
MD5 aa27b431fbb6b7590f4b3156823ba270
BLAKE2b-256 5f7f16cfa64275e3a2a723016491f46e009aa066aaea5698f4d04a1c61dad837

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0b054b14d6719a143ea8babd54f4737fbea1c59bef46b637129dc2593d7fa3d9
MD5 ebcc9785c72ea1e3349fdde48c36fb52
BLAKE2b-256 ee0d3e608e391180568ef901d407597f970f69ee2cd1db98d54f93413d33aa80

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 0268faac34a0f70a81a364e719ec7ad209a14c3a1da337fe540aa2e29c9e1805
MD5 d327e44f814b421b60a67dc42b985ede
BLAKE2b-256 ef77f97cfe185e53bb793926e1a4927f0f3284d4ec254367f398185eae4b3977

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c29e39cfa83c83b61c3b42b103e153ab3146014efa31540db9b068896146a06f
MD5 6b065bdd3e3895bd233a16656d4bf928
BLAKE2b-256 3036ddbc2e2a828d7b1d880b90d34c1754116c87e468bef9eb07deab6e8f1f57

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 93916dec5836367408b4785eab236226a2d7ba364ae2da6cab465e635d03d226
MD5 ba0ed46c91115379cdae5e53350cd6f4
BLAKE2b-256 ac78ddcb87e043bf9a54fb189869d8295c3e0ac11a6715dd36b634794f82bb82

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 c60ff1105f2cccf19462743262983b02dcdcc0038e0ae84e9f0c84b725c27f78
MD5 f977ae07edd3af4df7fcee8849a270db
BLAKE2b-256 1ba76e3459dab963e2956d33bf13885bc55995ed2d89686189e15be8f2bb04c7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 2f2016fa2c5de87a09424b8758ed637647eaa0d2c64658102a738d0c3e7a0bfb
MD5 1dcc7376dd4a86fa90ded1f4115a95c8
BLAKE2b-256 390fbca2cfe3eef4e2689b819a2de50637cdd45634f741f8436d564dffcb4328

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 2e0d2f3e42a57889fd228a8e3e6821347f15d8d468e38bbdb54916b77cca3691
MD5 6f280137928504f39cacabaed66fb4dc
BLAKE2b-256 2d3ebb7d19df76d13ae637149d1209ee346a3c350bf3469f5fdabc1ea7dd8cfe

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 1dd5c376fa201f88ffa7366e1d28e6c98a1b60fd9e1d1b59f47bb6cbe884e559
MD5 a97a6cbc7ee81c25595a8acbfdf9af6e
BLAKE2b-256 648e3482b7639be884b5bf63f2a3b019b6470af7a29c1a39e5fb8c43f1fadeb6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3b7903e3c04cfb3bfb6f8efc798bc81f6656e61acdcdd4ee171f97dd79b7b459
MD5 b7d34f6c557557f0bd81b24d3b1f670c
BLAKE2b-256 68091f92a3b515eb290b9947384bb078d12228b34e1f5f76238b620ee0962b2b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 1e92f0deb1637cfe0826c9d9a113848ceb1e4ee793008bac6bc2dfdc55357b09
MD5 72ac0f211c18613b8d608be26b22604f
BLAKE2b-256 051a944412c288af02d36af8a4ec0380a71a6a9c3860bb5092e5c14960905f23

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 252738e42bc21466855f0be2c22057a872ce3d3a215551c5764aef8dbfd41254
MD5 dc7c39cc9112dbaa79c7c165986fb1ef
BLAKE2b-256 77ea08fbf62917e73e7f238e96d67939a1bbc530dbf64d1a21f8e2fc7f2b0a72

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 b9ec5a669a4f6b5a6223ab88e9f20385baf35153f0b80e5ef40fd8588652b871
MD5 33ac825dda2285ec63bb41b300dd0533
BLAKE2b-256 8dda300b8c01d8a9f324bfb876c6416a6e1d04d932ae942bafccadebe8c984d7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f55ec840756097b0a7709feac049be00b6de814f4321b7e24fb87aa0adca1257
MD5 3fcb295f33fbaf156b20c5e9bea2072d
BLAKE2b-256 16e2d59c4f368da3e275df9e87a9a8bc64b83575fa325553da5c7aeddeaa34b8

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e60f07b4bcc9ba1ff804ca764fd5319d3e9f7a4fb56599619262e4f93f2c499a
MD5 03726d45a6cd3e893e820680c77e3c7b
BLAKE2b-256 6181b7f7da50f91211239ae5ebd15188b47bd276046f61b252b81b8fb349632e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 ecae75783babbbeff6404a8bb227055d98efa570db72b5efcdcb76ab2c0b7c94
MD5 c5e02b7004f07069a7f3aa38033b07b1
BLAKE2b-256 e4585bd42190ecd14baff943fcaa14643d370333d33b23a38a352fd7a77b0dc6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 eff82f22cbe45a56bf754d2ed5519f8ee11a6f35411370a27ba405bf2b1393ad
MD5 29d6c84bb198895d3eab122de6005173
BLAKE2b-256 6ad33d4e50572a158b6b5a14f358de35495e76ddee85380af5ad0250d0e95f80

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 44bdae2f71afcd1d181810db03415f73b9a1d4eb8a33ff4febbdd9dc879a1667
MD5 f443b14243fb0e4b9bb8fc9aa61113da
BLAKE2b-256 be7b33e4a169b3e594ef6aade0aec9fa18cca552e53ca00d5bb28c41115a9ce6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 bf50424afb3f629f37e81fb1915c33dd469c8f2b0685ddabbde53fb3c1d40c30
MD5 469f5d854ac8105710035cade8285b3f
BLAKE2b-256 8d462057d09600b72b6ac39ab2c91d906aa89b1d9a600fd2d24f5789558af96d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 75940fd1fa5a50f3fccc562bda13908d7246dfa9234e1310c41b42b9a76dcc64
MD5 f433ee06469a6b8da4870d3bcd21b3a0
BLAKE2b-256 8e6ef035364610174e587f36d328e65df0cda513564af6cca6015e88eab47ade

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 de0ab18f6e702bbc1e06b3f06ecb3499ac427dd08aac07e7889967c84b6da8b5
MD5 a709bf4147a15c6b6eacdb063ed51309
BLAKE2b-256 33651b6dda02194fda38ab4de42e482476066201663f4f820b0f8c1866939903

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 850a81571b39e76119e7639cd369fdd930c57ea43cd471e6226f6f5b735d7b3f
MD5 a05d32a12aba62162e68226bec63991d
BLAKE2b-256 c33d6b3201f2cd39b44988d0f67ac8f65a9fbb1fe8a89f0ffdf8bc849ea13b4e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 d6384df5fc8e436773e17d33d0498de0ae968312e29d7c5c1d218608dc423d87
MD5 61f6fb688e7d60b392a66782fbaae080
BLAKE2b-256 66266c4de78201638b9f6fe99532dcd5e03613c5c100115d4a0fb89af0a1f55d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 9bcebaf86f09fafcca714ebbfaa9dba6a5a307c7e91c5661b7fd9b9269673a3e
MD5 5a78c4906751373d2e23c1a3e897602e
BLAKE2b-256 d9c9143c803d4b94db5997b5dc918ecbd019b3ba7c0f0d4de3b8ea9bc492f9b2

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 36ac5b3a9a9c229d59eac38c615afc9b4727418d048f19b2cd26e4fbe635e1be
MD5 480444460f57636389530a1a57c4b8c7
BLAKE2b-256 26396dee30ffbfb0bb4d773e15473594557e1420ecc7787bdca701df59b50ca9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3f38bae63bb7d7aa8af7b901508c19b2ea773494a24f17c50c5a1a5125bdf77b
MD5 f4901b7b2f424414af13e6647092ea19
BLAKE2b-256 747ac7b2b1b6d83a82b04112998a2111015595a85e0b8df56c9ecb8278afb60b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 4ae65549b6325d67ff87f980fdd0e39446888c0af2927de745bfb5d9ea38441a
MD5 82de20ad09e4eff37899fa4a2811d1c9
BLAKE2b-256 71816c1649b810e85933490c6d19553592e882555983db2acc88de0e768d6765

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 d76f09cf2ad8c33f0221593ca8a462e0f00e46f9a2b844202a7faf4223194f9e
MD5 557353e90322aa9c6225b0f0bc6f64a4
BLAKE2b-256 cc555b49454818d1ac1e35d75f9772a22371c1413243117af6258ee0fb664edb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 c24c9977338842ac58463a30310fc3115d915ee319218307b9ecad2b50a85c9e
MD5 23ab84b54943e35b4bd6e1d6c252645e
BLAKE2b-256 7ce4414c390d95a2feadc2e5c875cb6035da9214fe2722ae5df491d176e5cc55

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 05b936d7dd38faf373689ff113e6c6b6c2eecc76bb956a9785da7dbf3e68968d
MD5 aaf286989b15fbc42104f13ed0333c21
BLAKE2b-256 a5c5b18f0105385f6560b373f8331df034ccbacbfb81d97d7981a63ee9418214

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 38d76bae7d797f456fd29d970d5a69dd126908a22ec30cb15e54555ce310cd4e
MD5 56f0ebb4326a6931915a2803767657ab
BLAKE2b-256 29f1ae575c535b372ed1f20ca39f6e901e773ce4a2fca1b0400203510ed6b656

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 2d3f42db4ad01f82ffe5cbd5f4822b2945a460b9b92a8302067ee545f92847f1
MD5 eb0deaed39d2ee714cfeaae64dc3bfed
BLAKE2b-256 6fcee28fedf7bb2b41107db0247a72d370c08a1d70e816eb78ea41c53a0dd9a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 9e539f793eb7767b03afa4dc1d13494230c78ba9ccde27a8dd190437fd7bb004
MD5 652ce46a15d8dc50fbda670104ede4da
BLAKE2b-256 b67ff8f324278027b244834680e384398279a5dcc6cc4a4b61e7d7f4abf52db2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 abb6ce93b9494309a6dc0a6909817cfd36bfcb5df2dce281eb756c3c6b0a0cca
MD5 d63185a5141dba7d419900b2413fc4eb
BLAKE2b-256 991258b2341e9d457e7a4a46b97867787e12c4b6e18cc91ca17b68b5c2c32355

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 37a50e23220fd3c161000064c13b3f7d4650a7e9e1ac4989285c84ce6462ddbb
MD5 bd5deb89f56d18b170890a8514daa909
BLAKE2b-256 add796250d333b44f64b47f269aa63ac401dc870bc38fa331f5dbddad7c08aa9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 efe44039af6c710ec3d9b723fa1823c0d6aa5058d6b0e0577d5422432a6186aa
MD5 97023b2266273a4673f401f8a9d6e03a
BLAKE2b-256 d3f57c889aff51144d0db792d759936e8ac42aef17f78d230439ca19bcec9a37

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 28ab96ab8bd4b2f62c94547d4f0d7457b7a6496feac48fe630daaca0bae5a00b
MD5 d9ecb54c65ca29a36c56a9dde6f497f8
BLAKE2b-256 166425ed1883887527a0c40999f751f64ec32a47d0805c781d22a7d8a8d4c027

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 978d23444c46fb6607e916094fabab8fa7899db6357df6345030dd464664fd1a
MD5 835312e9cc52f6316d6e6e6897283168
BLAKE2b-256 b994000bf8ef6292e40f8a6e56ca80049a2a8693f11cd0a7456550e122b61cbb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 da64bf8e4250df4a035afbc6f864a2ba47d8447dc0efebc320637ff8e9825a35
MD5 7d1395ee5f22349fb2de8747fcf881bd
BLAKE2b-256 a0b308c009ef1e3df67dcc8e5e9c30d7eb527524e37da6b9c053dca3edaec326

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 97d0572f3f148ebba39dcd676a7f37a493ca1cd019b484645797754b63ec06c5
MD5 5c0b83fe4ac73d1438acc1be1ae6d54e
BLAKE2b-256 24f088403446cb228ca2be2c21563ad41f335468601cdb9b36a323708fdd58ce

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 cab3402578c8d9ad7fc23c2f55d5cd67cc510ad1d070dfeb2afe392622a433ef
MD5 6f47a3019cb37fec41490fcb45a2a3c6
BLAKE2b-256 69189c4267976914caa7ca14702ab184efc1f51ca2cac76b93f97de72eaa8d3a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a1e102315fd9e79e27f4c39a36635ce7af44978f25d81817eea9706f1ae2bd09
MD5 ee73e22ae258c6c2c6660efdc395e276
BLAKE2b-256 1e6ee9cdecccbee9801adfdeebd43c9a1b193cf911117013881e6339f26342d5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 e5c6d11eeccf0a231ca2e52b69b5d599d61e2429811996333b8cb23214c21b6d
MD5 3434504bd6ee34bbc919a81ce827d79c
BLAKE2b-256 c7aed398e34f0bc2067d68d060d75675ad7437d02fd7e20e99a3267f065209d2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 513b565368dec4b0b607b553f2db8eed50f34469fe48b352f99672ccbd254fed
MD5 f174ecb1f01cebd1890e905295863d3c
BLAKE2b-256 aaeb9dc389db2dbcf836680d96ae9c68bd6281dcc3fb91c7cf71d6f0ddac4d61

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 c98a4f893e3c1a1a24ecd69d1c67d22ce99ed4552959028bc04f7b89854c6365
MD5 e7415da140a867e43179cf282787c124
BLAKE2b-256 c69050f4ab20195515ccd62fa326b77ac990824575dde4ad857ebec40613892d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1fe2b9262a084b6a8919de00a3d74029c138edefe41fc75913a63a2560df0d59
MD5 047db3be32ba5c9a3c9838bdbab84657
BLAKE2b-256 8a7cf0005bc38834b2e4931eef661137bbb9d24604cb253d28e9ec573ae088f7

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 86cfa670bcfb947e9b3c7a748efd0954be3456e90a0d4ceff0a8fe827148d61a
MD5 44a723815098ec204caa9ddc094d6acc
BLAKE2b-256 e03f1b84a8c40ecf483a629297430051d17aa51919536e4f5f66db0868ceefd4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 250777d351a679b5ea60b509cb8fc05d31d66e4ff00afe790256b1edfcd33b3a
MD5 85a4b5930d29ffe59cf6aa2b5a380565
BLAKE2b-256 f4128d01080998d7ece873b5bf5aedbbbf61e3e7de4228d1981e49bdb11da3a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 bb3ff972d57d9c6bef4ec8f2c59f11ae98949fa672e84c915046d98a854de14c
MD5 19abe55d3c5b41cc266a2dc51dffc783
BLAKE2b-256 7aee02f569bde8c5b9d8ee810111f7f0fae1eca0510b3bb7dfb11f8e70d039d9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2b009e844bead97119bc4c70a11f12213dcf43f1ccdb468ddaa5c841c46427a2
MD5 938af5dfde64faa9d6d20e993150d916
BLAKE2b-256 3fab756185a6414bb9c7b13e6730a1beee552e71d4d85e03aa80dc6e6e9bda79

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c00255fe16cd3b5d158946f09ea2065c2716eb38ead88e9ae0246f9d8a9b4dac
MD5 c21945c47fe1d7d17544ef9869ddf097
BLAKE2b-256 fe6e18648f67e18e83c78df7b5ca91cf44042eae1e2a99b9bfa8952dc3dcbfbb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d8beabc8b03f7032fdd6f8681825bdeb4b6385f58e5515d567319059d439187c
MD5 2f4fe312c3f9e0737e10d6c735b87eab
BLAKE2b-256 0dde45b8f620817e66c653823ace82dda7cfd4d19be54bac6625a2460ac98594

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 ac66f8c0d4be31b3da7bfc69bcb46d4c62e097889136b53945ee0982ffa69aef
MD5 be45aebf97e2837588786f0382cac164
BLAKE2b-256 499ec230cc5ae9f8e527510d9faeef416110d543aea9026cdacf6f42c6126355

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 0faf7b3841377e18999ee7173d816f7a2936bf95da5742ff538b180afbcb47f4
MD5 25d097b39fa5d87fcc7886558d41cb69
BLAKE2b-256 056080df8080e79da56ed915490482acbc53bee44661339bdea7f9a0a203a278

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 752de7d7f30d6455e0a3a73e1384218fc3f8f7948f3dcb5ca2a4f0898ee526ab
MD5 a17872bed50681c57afedcd6de4c702d
BLAKE2b-256 b8845e95ca21b6a96a49400a82af38b9a746bef5c1e23f3a3141b7d6f5e588f8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 ee452ccc9cc2bf07429ef9d4d8edc0c562691c11a1c8f9ccda8b04010ee91470
MD5 4daa0289e71c7a514af2eb0e3414b02b
BLAKE2b-256 81d1a5360b8235b387ddd7a19bb29b9820b1f97c3d28124dfc5a6f516483d5b8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 191c3f01d4e68ef0d635095666e5085f4f219c91b4fe9f01b4898e9664d651a5
MD5 2efe5fa51eceb69389d16cba1de3ace5
BLAKE2b-256 576ce746f5ea8cb04955bb196749abf4b50be3c2a8c45480f760c5e1977ea64c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 b9052a2b6a7bfa30b2909a40e9998c096c0f8f7e709fbed8cc33b2333e45f065
MD5 4e102dbe363a6a55b2d25749ed74c3f3
BLAKE2b-256 6fe9206f9439ab09d448028cdc0ef5f0c3ec2206769185416502f00ad14f60dd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 0ac66c11058a367663e1ab4a427f5b7d50cd78e82d38250ee074d3e60259489a
MD5 df8dc2dbe0514a2e64ca249bab245189
BLAKE2b-256 a04f039b8e3f54c04df626d12919fb5126a000358e21afa4c1a500d40aa83cc7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 99ef1dbe249f6275b2e374621f0b2d2a0053c0fbdadc950247a38d99cd35af43
MD5 06e07dfffb492bbec5d5ebce3a3721ae
BLAKE2b-256 72f3046b44635277135d496b0da12cc03c586fbb1ee6c72064e266faf752d536

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f8f378a9a2ed9a4bb884f1aa91bf68e79097a0c6115b639c205067aeb1019880
MD5 172034df3b7aab68c45613c0ce536d6b
BLAKE2b-256 2b2443bd61aec06fd1ba01a656279a5e9f99dd0e05c7b0d2c52d681725e30eac

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7737dca185e276fceae2c7d1b5c42b7cd9b2777a76b1b497dc23ce1363608b85
MD5 5976f244fbde8145fecbf7c40eb38935
BLAKE2b-256 13ca486dcc5bac41f0a1e45ebc23c0614baf92f879977c1572940aee9bd5a16d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e357583a2a6417e6239d7022f237a73eac012a355bcd55701103263e49003031
MD5 e5f7a9386cfbaff0735d09dbe74cb091
BLAKE2b-256 3ed812a2d7d9e9e7ab38707145674b42dd0deff6bf5d2628d0d105587736e46d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 b0d5f5c23a2ade3f6192ed1757e13ed741d481552f0db681a42fff6d35e65b01
MD5 aa442125f12681daba9e79964d836569
BLAKE2b-256 e459d786844c153b799ca9c2c81f96788bc85bba1e90b764adfb90041fc3b89d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 56dbfdf0bd61823823ba8f9d9927aaaee057b66ff5a4022092547cd273eb52e2
MD5 eadb5236a0aab3dead437110be40bce6
BLAKE2b-256 092c962fb6a3aa04c310c3e1e7234fb719e9f66d8e5b1e32c2ebabd5214b85a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ead49bfbae31695a3a2a7ad046b83b8f54166a87d36859075d1ecaccd0f2307f
MD5 bf3c8168940ba021cb03ed7086adaec3
BLAKE2b-256 0326a1579c015260e5ee5b955600be413fcec58c18264000d715cdbbe537f624

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ce3b7f4ad1f0568c324a9a2e608d47a2c741cd8cd5b0ada62ea04fe1ed94988c
MD5 38fc7dbe77f7e278a107a1e31eebff49
BLAKE2b-256 fb148f36dad0efbdd7af8eaa2d39191ef85afd814c6f92a583efe670d1a19283

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 aca1d096cd958a69c8d185d3a803f05f5ae264984be89b455fb130e03e56ea88
MD5 4451fd3434499de96549689348470c05
BLAKE2b-256 454ee255c5c732c6cbe2a131e4eb01c878b5c71cf54157132fc99aff3845f05e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 1ec94d9a6b7710464713a21748a800aa831b0660811b18a4cf71a927f80d388f
MD5 ed008fbd65602dfc75acdc0aefd24ff2
BLAKE2b-256 403fb062bbe13909bfcb45f754239876a245eed84a2fe885b7bffa9e9fdec9f1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 9e0daba19cfc397ed556a5fd1e689d9356d316283aa4c871aea94f0fd3f1b942
MD5 4aa2e03a9bd2fc1a330b86b518fa1661
BLAKE2b-256 684b643ca066383775679c01ecd90bfdeb3c9b6b8025f74bbd7cc6b3b3410397

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 3382f499d1d16effe652a402583f0943b0e05895be3dc4cb67de0e615561540f
MD5 b3adc7bb65a1bb9bbaedb3c71b9184d9
BLAKE2b-256 f0f06849c086803f9d7a488570befb66927357630e7e79abcfddcb6f8cca8cf9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b34ba8571f41b28c0fde735886923941bd88171c7c01895e3ca455e48199aed1
MD5 e3142d8cccd17a66c771c3809cc828f9
BLAKE2b-256 be9b3fa56fd78fa27c3ea0c6582a545e65ac69ff789d8d55cace6cf818eaa26b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 ffd46b6264d414c21aac51efd71aea0f7539291a82879657abd03b19315b82cc
MD5 93f617cf67d08b0bc41a2c26e6804045
BLAKE2b-256 55fc27ed00510c45aec1817a008b9370b813198bd8d5ae30014cb97b73efcee4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 da7cba6f329581d3f3613e16d6bf66e71266fe40b90e2621cea26c1534b5308c
MD5 0fd7640eba7a4aa1811c98bbfa059346
BLAKE2b-256 39683e3df37bbc5c6a936893186998255d0bd28aef32423f0a11e00c5a1c871e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 19c18f20e480fb2dd58afb5693f8bdd78a8718637e17d2812ca5856a23030c55
MD5 8fa21fd98cc2fc103af944745e268964
BLAKE2b-256 ad729d8916fd4b718d1ae2ef7a793af4ca4a3df4d7a63f67a5d3d250ba608f5d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 75795e113fd1cb469802468251d77bc639fa0800f034132162f4bbf9dbb42802
MD5 79cd48312ba1fb627eed62ce84636013
BLAKE2b-256 79aa9078d28df839e1c44574574341ae07494592bab76118230859f82952c315

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 06f1e2c79a2bb464cc79a0f74a2aa33161995017f91ee077779a1cd5f808da0b
MD5 c26d73af4796f7ae38e677c3cd3b9c44
BLAKE2b-256 78c19f9309a00579cd1d0611c8e5551fab00dc9be58b9b79373c6ea247f4090e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 ddfd649d8e37406069d865d59952b0a90b3475fbd9a6b259d2f0a30ad594ee32
MD5 a6302724eb9b3b6c3c397497076fd47a
BLAKE2b-256 a4bb9fd97dac2ce4cca8bc9c1e9d453955902a0ace93636abd4a5b300e534bd2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 21bb1449bc693d1e8916a153f31821594e295aaa0342c1db8fb22a286b59ae09
MD5 2a38ecf1967366520a49a98acf7b46f1
BLAKE2b-256 547a701a127993b75c1e03a516874892828ed646ebf90fa79ac26a0f43a2ca52

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 cfe0f601b6e0e1b17fb75787bee68dee1da42983c34c21bf77adbb13301bc4cf
MD5 db62e87343fcac35b5f145cd2305ecf8
BLAKE2b-256 df537c5fbc0a0876fdea4e45bd3c6cbaaf423e7134ef3d07a79348b44ec4b28b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9e18209c29729606d0b054dbc6cfcf18a845428e103128365235e77537710731
MD5 652802e216442bcd00dfb8cbadadcacb
BLAKE2b-256 d99e8733536f286afcfe33ce331de61bda69e8b19947020dde5e44a6ba5cd03a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 17a12ebbde7a62da1ebad3e113969a53c76a075cb1de8a15f41bb63e92755747
MD5 1ccac80060e4ea94a607ff99eabddfa9
BLAKE2b-256 aca36a91d03ac6a6fa480e8fa5db678870d871badf61ddbdabd08586d68a5378

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 dde715c99df0b0a92b7bcaf0f0afd429fa5bce8c02e3120701aaac129361df94
MD5 ad460b3e0f00b90ae1647e22da9cdf33
BLAKE2b-256 4a117fb60ac36fe362bc20605f4b0411c477f1c04089daae1e86f92384a450c4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: stringzilla-3.8.3-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.3-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 2296b2906a04976b4f872124ca41a7beb4dbfec4e9e97e85afb34f7c8e667053
MD5 4f0d33c3ed01ed3bf9382a085c6317c0
BLAKE2b-256 9c830286fe4e1dab29fd7732a57fb6c682edbf7ddf30e9314a60c5549c22b371

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6e6f6878e03fc7de2c8cbba13a0c940541853e6a84c3115c8736474eb1b28561
MD5 9c2d9d0929a596f9fd15059a20b9bcea
BLAKE2b-256 66802a57f9ad8266f326f25839b79827165f44094c182a836e18de8751e940ef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 0a21585c24224dce08c5a47fa26b811a62eb481bd9cafdd5f19ec664128cde80
MD5 f752c7fb6597181ba7cb8e9bfffd984f
BLAKE2b-256 3390942d4ebd93962290827eccbbc81d0585faec3180d552fd252c9d8a26e013

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 2c9048c5a49c97271425e415615a1c677d45375a81bb6883acf72423e1285b15
MD5 62a3594e8bcd6b0d6cafef136ea8cb50
BLAKE2b-256 7603eb407ff8d2a290c76332726b6671c2e9953aab17842c24cf90f886c41b0f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 8d374c20cad7c078cd9c16b51f6bb54de2017dc053aced52c4e448247b5bac58
MD5 4e1d60ca6606d8dc2e9e7f44d48f209a
BLAKE2b-256 ea650ae590d0b9af8381dd0401968bdddaf87e77e1c9d65c3355d5c9d0397313

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 5228f8c5e88353f1d2414345632f62e8a179a9246d5848fd46b264b6bd54ce79
MD5 c58a0ab0abb10f37c97be7861963407d
BLAKE2b-256 6acee986335b66a8ec010534bd34617efae45dc437fdf75b5f4375cd3df46c99

See more details on using hashes here.

File details

Details for the file stringzilla-3.8.3-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.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 506373e5ff2715e0698948d79caff67467cab94e0493b074310ab3fc04ab4b3d
MD5 ebdd795e0f1658a8d48e4293f5b87053
BLAKE2b-256 eb5ee7c53c4d983f48257dd8e095a3c0136b585908cd939a494aca651f6dd90f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 971507127311617162323d5561de9660bb9800db23b3edc2caf161740a42a97e
MD5 f32b24157499b6ec7d77162e75b6cbb8
BLAKE2b-256 31fa1036f891a848470e6b424fae3507b98d4fb0bec94b7e909ad533edeb70c5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 6074ea9265165c99fad671f4e58f4a9d4f4a015978f106f3e63e9aa7171cbb8d
MD5 f3c35766bc5570e355bea3f3292ebf6c
BLAKE2b-256 9eaf5d2022edacbc3e5f981bafc1494aeeb6747f5bdb8ab59b6ecc6ee3c2e04c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 065dffb205db7f44903cb74f4b7028108860310ea9a618af699606614b7dc101
MD5 0f928f425d6b0aefd244bce967a9d4dc
BLAKE2b-256 d7b9fb102d33498536bbe69d2927cf59b06cfb8189e60dde357cbe263516eedd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 4934fc14e79aad4ba76b69387048cd56655baa2e1fabc544523b8192a2434ef3
MD5 3c6e11cf707ffe4b4f882d66023a90f5
BLAKE2b-256 8b491dda9adc6e26ccefbc156dd255692aab29c103293c58b17e083d5d3fe45a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.8.3-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 86eca7e6164381f8b12d91cfd65a645b4ba7d0c252cda364d99db99e5499c459
MD5 3809d7c3b5f6637e88535b9e9fbe6fd3
BLAKE2b-256 fcaf14ef2ddc709d7064b627f247b2f899c0a63b81218bbae1fac344df09eef0

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