Skip to main content

SIMD-accelerated string search, sort, hashes, fingerprints, & edit distances

Project description

StringZilla 🦖

StringZilla banner

The world wastes a minimum of $100M annually due to inefficient string operations. A typical codebase processes strings character by character, resulting in too many branches and data-dependencies, neglecting 90% of modern CPU's potential. LibC is different. It attempts to leverage SIMD instructions to boost some operations, and is often used by higher-level languages, runtimes, and databases. But it isn't perfect. 1️⃣ First, even on common hardware, including over a billion 64-bit ARM CPUs, common functions like strstr and memmem only achieve 1/3 of the CPU's throughput. 2️⃣ Second, SIMD coverage is inconsistent: acceleration in forward scans does not guarantee speed in the reverse-order search. 3️⃣ At last, most high-level languages can't always use LibC, as the strings are often not NULL-terminated or may contain the Unicode "Zero" character in the middle of the string. That's why StringZilla was created. To provide predictably high performance, portable to any modern platform, operating system, and programming language.

StringZilla Python installs StringZilla Rust installs GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status StringZilla code size

StringZilla is the GodZilla of string libraries, using SIMD and SWAR to accelerate string operations on modern CPUs. It is up to 10x faster than the default and even other SIMD-accelerated string libraries in C, C++, Python, and other languages, while covering broad functionality. It accelerates exact and fuzzy string matching, edit distance computations, sorting, lazily-evaluated ranges to avoid memory allocations, and even random-string generators.

  • 🐂 C : Upgrade LibC's <string.h> to <stringzilla.h> in C 99
  • 🐉 C++: Upgrade STL's <string> to <stringzilla.hpp> in C++ 11
  • 🐍 Python: Upgrade your str to faster Str
  • 🍎 Swift: Use the String+StringZilla extension
  • 🦀 Rust: Use the StringZilla traits crate
  • 🐚 Shell: Accelerate common CLI tools with sz_ prefix
  • 📚 Researcher? Jump to Algorithms & Design Decisions
  • 💡 Thinking to contribute? Look for "good first issues"
  • 🤝 And check the guide to setup the environment
  • Want more bindings or features? Let me know!

Who is this for?

  • For data-engineers parsing large datasets, like the CommonCrawl, RedPajama, or LAION.
  • For software engineers optimizing strings in their apps and services.
  • For bioinformaticians and search engineers looking for edit-distances for USearch.
  • For DBMS devs, optimizing LIKE, ORDER BY, and GROUP BY operations.
  • For hardware designers, needing a SWAR baseline for strings-processing functionality.
  • For students studying SIMD/SWAR applications to non-data-parallel operations.

Performance

C C++ Python StringZilla
find the first occurrence of a random word from text, ≅ 5 bytes long
strstr 1
x86: 7.4 · arm: 2.0 GB/s
.find
x86: 2.9 · arm: 1.6 GB/s
.find
x86: 1.1 · arm: 0.6 GB/s
sz_find
x86: 10.6 · arm: 7.1 GB/s
find the last occurrence of a random word from text, ≅ 5 bytes long
.rfind
x86: 0.5 · arm: 0.4 GB/s
.rfind
x86: 0.9 · arm: 0.5 GB/s
sz_rfind
x86: 10.8 · arm: 6.7 GB/s
split lines separated by \n or \r 2
strcspn 1
x86: 5.42 · arm: 2.19 GB/s
.find_first_of
x86: 0.59 · arm: 0.46 GB/s
re.finditer
x86: 0.06 · arm: 0.02 GB/s
sz_find_charset
x86: 4.08 · arm: 3.22 GB/s
find the last occurrence of any of 6 whitespaces 2
.find_last_of
x86: 0.25 · arm: 0.25 GB/s
sz_rfind_charset
x86: 0.43 · arm: 0.23 GB/s
Random string from a given alphabet, 20 bytes long 5
rand() % n
x86: 18.0 · arm: 9.4 MB/s
uniform_int_distribution
x86: 47.2 · arm: 20.4 MB/s
join(random.choices(...))
x86: 13.3 · arm: 5.9 MB/s
sz_generate
x86: 56.2 · arm: 25.8 MB/s
Get sorted order, ≅ 8 million English words 6
qsort_r
x86: 3.55 · arm: 5.77 s
std::sort
x86: 2.79 · arm: 4.02 s
numpy.argsort
x86: 7.58 · arm: 13.00 s
sz_sort
x86: 1.91 · arm: 2.37 s
Levenshtein edit distance, ≅ 5 bytes long
via jellyfish 3
x86: 1,550 · arm: 2,220 ns
sz_edit_distance
x86: 99 · arm: 180 ns
Needleman-Wunsch alignment scores, ≅ 10 K aminoacids long
via biopython 4
x86: 257 · arm: 367 ms
sz_alignment_score
x86: 73 · arm: 177 ms

StringZilla has a lot of functionality, most of which is covered by benchmarks across C, C++, Python and other languages. You can find those in the ./scripts directory, with usage notes listed in the CONTRIBUTING.md file. Notably, if the CPU supports misaligned loads, even the 64-bit SWAR backends are faster than either standard library.

Most benchmarks were conducted on a 1 GB English text corpus, with an average word length of 6 characters. The code was compiled with GCC 12, using glibc v2.35. The benchmarks performed on Arm-based Graviton3 AWS c7g instances and r7iz Intel Sapphire Rapids. Most modern Arm-based 64-bit CPUs will have similar relative speedups. Variance withing x86 CPUs will be larger. 1 Unlike other libraries, LibC requires strings to be NULL-terminated. 2 Six whitespaces in the ASCII set are: \t\n\v\f\r. Python's and other standard libraries have specialized functions for those. 3 Most Python libraries for strings are also implemented in C. 4 Unlike the rest of BioPython, the alignment score computation is implemented in C. 5 All modulo operations were conducted with uint8_t to allow compilers more optimization opportunities. The C++ STL and StringZilla benchmarks used a 64-bit Mersenne Twister as the generator. For C, C++, and StringZilla, an in-place update of the string was used. In Python every string had to be allocated as a new object, which makes it less fair. 6 Contrary to the popular opinion, Python's default sorted function works faster than the C and C++ standard libraries. That holds for large lists or tuples of strings, but fails as soon as you need more complex logic, like sorting dictionaries by a string key, or producing the "sorted order" permutation. The latter is very common in database engines and is most similar to numpy.argsort. Current StringZilla solution can be at least 4x faster without loss of generality.

Functionality

StringZilla is compatible with most modern CPUs, and provides a broad range of functionality.

  • works on both Little-Endian and Big-Endian architectures.
  • works on 32-bit and 64-bit hardware architectures.
  • compatible with ASCII and UTF-8 encoding.

Not all features are available across all bindings. Consider contributing, if you need a feature that's not yet implemented.

Maturity C 99 C++ 11 Python Swift Rust
Substring Search 🌳
Character Set Search 🌳
Edit Distances 🧐
Small String Class 🧐
Sorting & Sequence Operations 🚧
Lazy Ranges, Compressed Arrays 🧐
Hashes & Fingerprints 🚧

🌳 parts are used in production. 🧐 parts are in beta. 🚧 parts are under active development, and are likely to break in subsequent releases. ✅ are implemented. ⚪ are considered. ❌ are not intended.

Quick Start: Python 🐍

Python bindings are available on PyPI, and can be installed with pip. You can immediately check the installed version and the used hardware capabilities with following commands:

pip install stringzilla
python -c "import stringzilla; print(stringzilla.__version__)"
python -c "import stringzilla; print(stringzilla.__capabilities__)"

Basic Usage

If you've ever used the Python str, bytes, bytearray, memoryview class, you'll know what to expect. StringZilla's Str class is a hybrid of those two, providing str-like interface to byte-arrays.

from stringzilla import Str, File

text_from_str = Str('some-string') # no copies, just a view
text_from_file = Str(File('some-file.txt')) # memory-mapped file

The File class memory-maps a file from persistent memory without loading its copy into RAM. The contents of that file would remain immutable, and the mapping can be shared by multiple Python processes simultaneously. A standard dataset pre-processing use case would be to map a sizeable textual dataset like Common Crawl into memory, spawn child processes, and split the job between them.

Basic Operations

  • Length: len(text) -> int
  • Indexing: text[42] -> str
  • Slicing: text[42:46] -> Str
  • Substring check: 'substring' in text -> bool
  • Hashing: hash(text) -> int
  • String conversion: str(text) -> str

Advanced Operations

import sys

x: bool = text.contains('substring', start=0, end=sys.maxsize)
x: int = text.find('substring', start=0, end=sys.maxsize)
x: int = text.count('substring', start=0, end=sys.maxsize, allowoverlap=False)
x: str = text.decode(encoding='utf-8', errors='strict')
x: Strs = text.split(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.splitlines(keeplinebreaks=False, maxsplit=sys.maxsize)

It's important to note, that the last function behavior is slightly different from Python's str.splitlines. The native version matches \n, \r, \v or \x0b, \f or \x0c, \x1c, \x1d, \x1e, \x85, \r\n, \u2028, \u2029, including 3x two-bytes-long runes. The StringZilla version matches only \n, \v, \f, \r, \x1c, \x1d, \x1e, \x85, avoiding two-byte-long runes.

Character Set Operations

Python strings don't natively support character set operations. This forces people to use regular expressions, which are slow and hard to read. To avoid the need for re.finditer, StringZilla provides the following interfaces:

x: int = text.find_first_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_of('chars', start=0, end=sys.maxsize)
x: int = text.find_first_not_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_not_of('chars', start=0, end=sys.maxsize)
x: Strs = text.split_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)

Collection-Level Operations

Once split into a Strs object, you can sort, shuffle, and reorganize the slices, with minimum memory footprint. If all the chunks are located in consecutive memory regions, the memory overhead can be as low as 4 bytes per chunk.

lines: Strs = text.split(separator='\n') # 4 bytes per line overhead for under 4 GB of text
batch: Strs = lines.sample(seed=42) # 10x faster than `random.choices`
lines.shuffle(seed=42) # or shuffle all lines in place and shard with slices
# WIP: lines.sort() # explodes to 16 bytes per line overhead for any length text
# WIP: sorted_order: tuple = lines.argsort() # similar to `numpy.argsort`

Working on RedPajama, addressing 20 Billion annotated english documents, one will need only 160 GB of RAM instead of Terabytes. Once loaded, the data will be memory-mapped, and can be reused between multiple Python processes without copies. And of course, you can use slices to navigate the dataset and shard it between multiple workers.

lines[::3] # every third line
lines[1::1] # every odd line
lines[:-100:-1] # last 100 lines in reverse order

Iterators and Memory Efficiency

Python's operations like split() and readlines() immediately materialize a list of copied parts. This can be very memory-inefficient for large datasets. StringZilla saves a lot of memory by viewing existing memory regions as substrings, but even more memory can be saved by using lazily evaluated iterators.

x: SplitIterator[Str] = text.split_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.split_charset_iter(separator='chars', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_charset_iter(separator='chars', keepseparator=False)

StringZilla can easily be 10x more memory efficient than native Python classes for tokenization. With lazy operations, it practically becomes free.

import stringzilla as sz
%load_ext memory_profiler

text = open("enwik9.txt", "r").read() # 1 GB, mean word length 7.73 bytes
%memit text.split() # increment: 8670.12 MiB (152 ms)
%memit sz.split(text) # increment: 530.75 MiB (25 ms)
%memit sum(1 for _ in sz.split_iter(text)) # increment: 0.00 MiB

Low-Level Python API

Aside from calling the methods on the Str and Strs classes, you can also call the global functions directly on str and bytes instances. Assuming StringZilla CPython bindings are implemented without any intermediate tools like SWIG or PyBind, the call latency should be similar to native classes.

import stringzilla as sz

contains: bool = sz.contains("haystack", "needle", start=0, end=sys.maxsize)
offset: int = sz.find("haystack", "needle", start=0, end=sys.maxsize)
count: int = sz.count("haystack", "needle", start=0, end=sys.maxsize, allowoverlap=False)

Edit Distances

assert sz.edit_distance("apple", "aple") == 1 # skip one ASCII character
assert sz.edit_distance("αβγδ", "αγδ") == 2 # skip two bytes forming one rune
assert sz.edit_distance_unicode("αβγδ", "αγδ") == 1 # one unicode rune

Several Python libraries provide edit distance computation. Most of them are implemented in C, but are not always as fast as StringZilla. Taking a 1'000 long proteins around 10'000 characters long, computing just a 100 distances:

Moreover, you can pass custom substitution matrices to compute the Needleman-Wunsch alignment scores. That task is very common in bioinformatics and computational biology. It's natively supported in BioPython, and its BLOSUM matrices can be converted to StringZilla's format. Alternatively, you can construct an arbitrary 256 by 256 cost matrix using NumPy. Depending on arguments, the result may be equal to the negative Levenshtein distance.

import numpy as np
import stringzilla as sz

costs = np.zeros((256, 256), dtype=np.int8)
costs.fill(-1)
np.fill_diagonal(costs, 0)

assert sz.alignment_score("first", "second", substitution_matrix=costs, gap_score=-1) == -sz.edit_distance(a, b)

Using the same proteins as for Levenshtein distance benchmarks:

§ Example converting from BioPython to StringZilla.
import numpy as np
from Bio import Align
from Bio.Align import substitution_matrices

aligner = Align.PairwiseAligner()
aligner.substitution_matrix = substitution_matrices.load("BLOSUM62")
aligner.open_gap_score = 1
aligner.extend_gap_score = 1

# Convert the matrix to NumPy
subs_packed = np.array(aligner.substitution_matrix).astype(np.int8)
subs_reconstructed = np.zeros((256, 256), dtype=np.int8)

# Initialize all banned characters to a the largest possible penalty
subs_reconstructed.fill(127)
for packed_row, packed_row_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
    for packed_column, packed_column_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
        reconstructed_row = ord(packed_row_aminoacid)
        reconstructed_column = ord(packed_column_aminoacid)
        subs_reconstructed[reconstructed_row, reconstructed_column] = subs_packed[packed_row, packed_column]

# Let's pick two examples for of tri-peptides (made of 3 aminoacids)
glutathione = "ECG" # Need to rebuild human tissue?
thyrotropin_releasing_hormone = "QHP" # Or to regulate your metabolism?

assert sz.alignment_score(
    glutathione,
    thyrotropin_releasing_hormone, 
    substitution_matrix=subs_reconstructed, 
    gap_score=1) == aligner.score(glutathione, thyrotropin_releasing_hormone) # Equal to 6

Serialization

Filesystem

Similar to how File can be used to read a large file, other interfaces can be used to dump strings to disk faster. The Str class has write_to to write the string to a file, and offset_within to obtain integer offsets of substring view in larger string for navigation.

web_archive = Str("<html>...</html><html>...</html>")
_, end_tag, next_doc = web_archive.partition("</html>") # or use `find`
next_doc_offset = next_doc.offset_within(web_archive)
web_archive.write_to("next_doc.html") # no GIL, no copies, just a view

PyArrow

A Str is easy to cast to PyArrow buffers.

from pyarrow import foreign_buffer
from stringzilla import Str

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

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

Quick Start: C/C++ 🛠️

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

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

Or using a pure CMake approach:

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

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

Basic Usage with C 99 and Newer

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

#include <stringzilla/stringzilla.h>

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

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

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

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

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

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

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

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

Basic Usage with C++ 11 and Newer

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

#include <stringzilla/stringzilla.hpp>

namespace sz = ashvardanian::stringzilla;

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

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

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

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

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

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

Memory Ownership and Small String Optimization

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

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

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

} sz_string_t;

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

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

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

sz_memory_allocator_t allocator;
sz_string_t string;

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

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

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

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

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

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

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

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

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

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

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

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

using str = std::string;

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

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

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

using str = sz::string;

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

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

Beyond the C++ Standard Library - Learning from Python

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Splits and Ranges

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

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

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

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

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

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

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

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

Concatenating Strings without Allocations

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

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

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

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

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

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

Random Generation

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

sz::string random_string(std::size_t length, char const *alphabet, std::size_t cardinality) {
    sz::string result(length, '\0');
    static std::random_device seed_source; // Expensive to construct - due to system calls
    static std::mt19937 generator(seed_source()); // Also expensive - due to the state size
    std::uniform_int_distribution<std::size_t> distribution(0, cardinality);
    std::generate(result.begin(), result.end(), [&]() { return alphabet[distribution(generator)]; });
    return result;
}

Mouthful and slow. StringZilla provides a C native method - sz_generate and a convenient C++ wrapper - sz::generate. Similar to Python it also defines the commonly used character sets.

auto protein = sz::string::random(300, "ARNDCQEGHILKMFPSTWYV"); // static method
auto dna = sz::basic_string<custom_allocator>::random(3_000_000_000, "ACGT");

dna.randomize("ACGT"); // `noexcept` pre-allocated version
dna.randomize(&std::rand, "ACGT"); // pass any generator, like `std::mt19937`

char uuid[36];
sz::randomize(sz::string_span(uuid, 36), "0123456789abcdef-"); // Overwrite any buffer

Levenshtein Edit Distance and Alignment Scores

Levenshtein and Hamming edit distance are provided for both byte-strings and UTF-8 strings. The latter will output the distance in Unicode code points, not bytes. Needleman-Wunsch alignment scores are only defined for byte-strings.

// Count number of substitutions in same length strings
sz::hamming_distance(first, second[, upper_bound]) -> std::size_t;
sz::hamming_distance_utf8(first, second[, upper_bound]) -> std::size_t;

// Count number of insertions, deletions and substitutions
sz::edit_distance(first, second[, upper_bound[, allocator]]) -> std::size_t;
sz::edit_distance_utf8(first, second[, upper_bound[, allocator]]) -> std::size_t;

// Substitution-parametrized Needleman-Wunsch global alignment score
std::int8_t costs[256][256]; // Substitution costs matrix
sz::alignment_score(first, second, costs[, gap_score[, allocator]) -> std::ptrdiff_t;

Sorting in C and C++

LibC provides qsort and STL provides std::sort. Both have their quarks. The LibC standard has no way to pass a context to the comparison function, that's only possible with platform-specific extensions. Those have different arguments order on every OS.

// Linux: https://linux.die.net/man/3/qsort_r
void qsort_r(void *elements, size_t count, size_t element_width, 
    int (*compare)(void const *left, void const *right, void *context),
    void *context);
// MacOS and FreeBSD: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/qsort_r.3.html
void qsort_r(void *elements, size_t count, size_t element_width, 
    void *context,
    int (*compare)(void *context, void const *left, void const *right));
// Windows conflicts with ISO `qsort_s`: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170
void qsort_s(id *elements, size_t count, size_t element_width, 
    int (*compare)(void *context, void const *left, void const *right),
    void *context);

C++ generic algorithm is not perfect either. There is no guarantee in the standard that std::sort won't allocate any memory. If you are running on embedded, in real-time or on 100+ CPU cores per node, you may want to avoid that. StringZilla doesn't solve the general case, but hopes to improve the performance for strings. Use sz_sort, or the high-level sz::sorted_order, which can be used sort any collection of elements convertible to sz::string_view.

std::vector<std::string> data({"c", "b", "a"});
std::vector<std::size_t> order = sz::sorted_order(data); //< Simple shortcut

// Or, taking care of memory allocation:
sz::sorted_order(data.begin(), data.end(), order.data(), [](auto const &x) -> sz::string_view { return x; });

Standard C++ Containers with String Keys

The C++ Standard Templates Library provides several associative containers, often used with string keys.

std::map<std::string, int, std::less<std::string>> sorted_words;
std::unordered_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>> words;

The performance of those containers is often limited by the performance of the string keys, especially on reads. StringZilla can be used to accelerate containers with std::string keys, by overriding the default comparator and hash functions.

std::map<std::string, int, sz::string_view_less> sorted_words;
std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to> words;

Alternatively, a better approach would be to use the sz::string class as a key. The right hash function and comparator would be automatically selected and the performance gains would be more noticeable if the keys are short.

std::map<sz::string, int> sorted_words;
std::unordered_map<sz::string, int> words;

Compilation Settings and Debugging

SZ_DEBUG:

For maximal performance, the C library does not perform any bounds checking in Release builds. In C++, bounds checking happens only in places where the STL std::string would do it. If you want to enable more aggressive bounds-checking, define SZ_DEBUG before including the header. If not explicitly set, it will be inferred from the build type.

SZ_USE_X86_AVX512, SZ_USE_X86_AVX2, SZ_USE_ARM_NEON:

One can explicitly disable certain families of SIMD instructions for compatibility purposes. Default values are inferred at compile time.

SZ_DYNAMIC_DISPATCH:

By default, StringZilla is a header-only library. But if you are running on different generations of devices, it makes sense to pre-compile the library for all supported generations at once, and dispatch at runtime. This flag does just that and is used to produce the stringzilla.so shared library, as well as the Python bindings.

SZ_USE_MISALIGNED_LOADS:

By default, StringZilla avoids misaligned loads. If supported, it replaces many byte-level operations with word-level ones. Going from char-like types to uint64_t-like ones can significantly accelerate the serial (SWAR) backend. So consider enabling it if you are building for some embedded device.

SZ_AVOID_LIBC and SZ_OVERRIDE_LIBC:

When using the C header-only library one can disable the use of LibC. This may affect the type resolution system on obscure hardware platforms. Moreover, one may let stringzilla override the common symbols like the memcpy and memset with its own implementations. In that case you can use the LD_PRELOAD trick to prioritize it's symbols over the ones from the LibC and accelerate existing string-heavy applications without recompiling them.

SZ_AVOID_STL and SZ_SAFETY_OVER_COMPATIBILITY:

When using the C++ interface one can disable implicit conversions from std::string to sz::string and back. If not needed, the <string> and <string_view> headers will be excluded, reducing compilation time. Moreover, if STL compatibility is a low priority, one can make the API safer by disabling the overloads, which are subjectively error prone.

STRINGZILLA_BUILD_SHARED, STRINGZILLA_BUILD_TEST, STRINGZILLA_BUILD_BENCHMARK, STRINGZILLA_TARGET_ARCH for CMake users:

When compiling the tests and benchmarks, you can explicitly set the target hardware architecture. It's synonymous to GCC's -march flag and is used to enable/disable the appropriate instruction sets. You can also disable the shared library build, if you don't need it.

Quick Start: Rust 🦀

StringZilla is available as a Rust crate, with documentation available on docs.rs/stringzilla. To use the latest crate release in your project, add the following to your Cargo.toml:

[dependencies]
stringzilla = ">=3"

Or if you want to use the latest pre-release version from the repository:

[dependencies]
stringzilla = { git = "https://github.com/ashvardanian/stringzilla", branch = "main-dev" }

Once installed, all of the functionality is available through the stringzilla namespace. Many interfaces will look familiar to the users of the memchr crate.

use stringzilla::sz;

// Identical to `memchr::memmem::find` and `memchr::memmem::rfind` functions
sz::find("Hello, world!", "world") // 7
sz::rfind("Hello, world!", "world") // 7

// Generalizations of `memchr::memrchr[123]`
sz::find_char_from("Hello, world!", "world") // 2
sz::rfind_char_from("Hello, world!", "world") // 11

Unlike memchr, the throughput of stringzilla is high in both normal and reverse-order searches. It also provides no constraints on the size of the character set, while memchr allows only 1, 2, or 3 characters. In addition to global functions, stringzilla provides a StringZilla extension trait:

use stringzilla::StringZilla;

let my_string: String = String::from("Hello, world!");
let my_str = my_string.as_str();
let my_cow_str = Cow::from(&my_string);

// Use the generic function with a String
assert_eq!(my_string.sz_find("world"), Some(7));
assert_eq!(my_string.sz_rfind("world"), Some(7));
assert_eq!(my_string.sz_find_char_from("world"), Some(2));
assert_eq!(my_string.sz_rfind_char_from("world"), Some(11));
assert_eq!(my_string.sz_find_char_not_from("world"), Some(0));
assert_eq!(my_string.sz_rfind_char_not_from("world"), Some(12));

// Same works for &str and Cow<'_, str>
assert_eq!(my_str.sz_find("world"), Some(7));
assert_eq!(my_cow_str.as_ref().sz_find("world"), Some(7));

The library also exposes Levenshtein and Hamming edit-distances for byte-arrays and UTF-8 strings, as well as Needleman-Wunch alignment scores.

use stringzilla::sz;

// Handling arbitrary byte arrays:
sz::edit_distance("Hello, world!", "Hello, world?"); // 1
sz::hamming_distance("Hello, world!", "Hello, world?"); // 1
sz::alignment_score("Hello, world!", "Hello, world?", sz::unary_substitution_costs(), -1); // -1

// Handling UTF-8 strings:
sz::hamming_distance_utf8("αβγδ", "αγγδ") // 1
sz::edit_distance_utf8("façade", "facade") // 1

Quick Start: Swift 🍏

StringZilla can be added as a dependency in the Swift Package Manager. In your Package.swift file, add the following:

dependencies: [
    .package(url: "https://github.com/ashvardanian/stringzilla")
]

The package currently covers only the most basic functionality, but is planned to be extended to cover the full C++ API.

var s = "Hello, world! Welcome to StringZilla. 👋"
s[s.findFirst(substring: "world")!...] // "world! Welcome to StringZilla. 👋")    
s[s.findLast(substring: "o")!...] // "o StringZilla. 👋")
s[s.findFirst(characterFrom: "aeiou")!...] // "ello, world! Welcome to StringZilla. 👋")
s[s.findLast(characterFrom: "aeiou")!...] // "a. 👋")
s[s.findFirst(characterNotFrom: "aeiou")!...] // "Hello, world! Welcome to StringZilla. 👋"
s.editDistance(from: "Hello, world!")! // 29

Algorithms & Design Decisions 📚

StringZilla aims to optimize some of the slowest string operations. Some popular operations, however, like equality comparisons and relative order checking, almost always complete on some of the very first bytes in either string. In such operations vectorization is almost useless, unless huge and very similar strings are considered. StringZilla implements those operations as well, but won't result in substantial speedups.

Exact Substring Search

Substring search algorithms are generally divided into: comparison-based, automaton-based, and bit-parallel. Different families are effective for different alphabet sizes and needle lengths. The more operations are needed per-character - the more effective SIMD would be. The longer the needle - the more effective the skip-tables are. StringZilla uses different exact substring search algorithms for different needle lengths and backends:

  • When no SIMD is available - SWAR (SIMD Within A Register) algorithms are used on 64-bit words.
  • Boyer-Moore-Horspool (BMH) algorithm with Raita heuristic variation for longer needles.
  • SIMD algorithms are randomized to look at different parts of the needle.

On very short needles, especially 1-4 characters long, brute force with SIMD is the fastest solution. On mid-length needles, bit-parallel algorithms are effective, as the character masks fit into 32-bit or 64-bit words. Either way, if the needle is under 64-bytes long, on haystack traversal we will still fetch every CPU cache line. So the only way to improve performance is to reduce the number of comparisons. The snippet below shows how StringZilla accomplishes that for needles of length two.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L1585-L1637

Going beyond that, to long needles, Boyer-Moore (BM) and its variants are often the best choice. It has two tables: the good-suffix shift and the bad-character shift. Common choice is to use the simplified BMH algorithm, which only uses the bad-character shift table, reducing the pre-processing time. We do the same for mid-length needles up to 256 bytes long. That way the stack-allocated shift table remains small.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1774-L1825

In the C++ Standards Library, the std::string::find function uses the BMH algorithm with Raita's heuristic. Before comparing the entire string, it matches the first, last, and the middle character. Very practical, but can be slow for repetitive characters. Both SWAR and SIMD backends of StringZilla have a cheap pre-processing step, where we locate unique characters. This makes the library a lot more practical when dealing with non-English corpora.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1398-L1431

All those, still, have $O(hn)$ worst case complexity. To guarantee $O(h)$ worst case time complexity, the Apostolico-Giancarlo (AG) algorithm adds an additional skip-table. Preprocessing phase is $O(n+sigma)$ in time and space. On traversal, performs from $(h/n)$ to $(3h/2)$ comparisons. It however, isn't practical on modern CPUs. A simpler idea, the Galil-rule might be a more relevant optimizations, if many matches must be found.

Other algorithms previously considered and deprecated:

  • Apostolico-Giancarlo algorithm for longer needles. Control-flow is too complex for efficient vectorization.
  • Shift-Or-based Bitap algorithm for short needles. Slower than SWAR.
  • Horspool-style bad-character check in SIMD backends. Effective only for very long needles, and very uneven character distributions between the needle and the haystack. Faster "character-in-set" check needed to generalize.

§ Reading materials. Exact String Matching Algorithms in Java. SIMD-friendly algorithms for substring searching.

Levenshtein Edit Distance

Levenshtein distance is the best known edit-distance for strings, that checks, how many insertions, deletions, and substitutions are needed to transform one string to another. It's extensively used in approximate string-matching, spell-checking, and bioinformatics.

The computational cost of the Levenshtein distance is $O(n * m)$, where $n$ and $m$ are the lengths of the string arguments. To compute that, the naive approach requires $O(n * m)$ space to store the "Levenshtein matrix", the bottom-right corner of which will contain the Levenshtein distance. The algorithm producing the matrix has been simultaneously studied/discovered by the Soviet mathematicians Vladimir Levenshtein in 1965, Taras Vintsyuk in 1968, and American computer scientists - Robert Wagner, David Sankoff, Michael J. Fischer in the following years. Several optimizations are known:

  1. Space Optimization: The matrix can be computed in $O(min(n,m))$ space, by only storing the last two rows of the matrix.
  2. Divide and Conquer: Hirschberg's algorithm can be applied to decompose the computation into subtasks.
  3. Automata: Levenshtein automata can be effective, if one of the strings doesn't change, and is a subject to many comparisons.
  4. Shift-Or: Bit-parallel algorithms transpose the matrix into a bit-matrix, and perform bitwise operations on it.

The last approach is quite powerful and performant, and is used by the great RapidFuzz library. It's less known, than the others, derived from the Baeza-Yates-Gonnet algorithm, extended to bounded edit-distance search by Manber and Wu in 1990s, and further extended by Gene Myers in 1999 and Heikki Hyyro between 2002 and 2004.

StringZilla introduces a different approach, extensively used in Unum's internal combinatorial optimization libraries. The approach doesn't change the number of trivial operations, but performs them in a different order, removing the data dependency, that occurs when computing the insertion costs. This results in much better vectorization for intra-core parallelism and potentially multi-core evaluation of a single request.

Next design goals:

  • Generalize fast traversals to rectangular matrices.
  • Port x86 AVX-512 solution to Arm NEON.

§ Reading materials. Faster Levenshtein Distances with a SIMD-friendly Traversal Order.

Needleman-Wunsch Alignment Score for Bioinformatics

The field of bioinformatics studies various representations of biological structures. The "primary" representations are generally strings over sparse alphabets:

  • DNA sequences, where the alphabet is {A, C, G, T}, ranging from ~100 characters for short reads to 3 billion for the human genome.
  • RNA sequences, where the alphabet is {A, C, G, U}, ranging from ~50 characters for tRNA to thousands for mRNA.
  • Proteins, where the alphabet is made of 22 amino acids, ranging from 2 characters for dipeptide to 35,000 for Titin, the longest protein.

The shorter the representation, the more often researchers may want to use custom substitution matrices. Meaning that the cost of a substitution between two characters may not be the same for all pairs.

StringZilla adapts the fairly efficient two-row Wagner-Fisher algorithm as a baseline serial implementation of the Needleman-Wunsch score. It supports arbitrary alphabets up to 256 characters, and can be used with either BLOSUM, PAM, or other substitution matrices. It also uses SIMD for hardware acceleration of the substitution lookups. This however, does not yet break the data-dependency for insertion costs, where 80% of the time is wasted. With that solved, the SIMD implementation will become 5x faster than the serial one.

Random Generation

Generating random strings from different alphabets is a very common operation. StringZilla accepts an arbitrary Pseudorandom Number Generator to produce noise, and an array of characters to sample from. Sampling is optimized to avoid integer division, a costly operation on modern CPUs. For that a 768-byte long lookup table is used to perform 2 lookups, 1 multiplication, 2 shifts, and 2 accumulations.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L2490-L2533

Sorting

For lexicographic sorting of strings, StringZilla uses a "hybrid-hybrid" approach with $O(n * log(n))$ and.

  1. Radix sort for first bytes exported into a continuous buffer for locality.
  2. IntroSort on partially ordered chunks to balance efficiency and worst-case performance.
    1. IntroSort begins with a QuickSort.
    2. If the recursion depth exceeds a certain threshold, it switches to a HeapSort.

Next design goals:

  • Generalize to arrays with over 4 billion entries.
  • Algorithmic improvements may yield another 3x performance gain.
  • SIMD-acceleration for the Radix slice.

Hashing

[!WARNING] Hash functions are not cryptographically safe and are currently under active development. They may change in future minor releases.

Choosing the right hashing algorithm for your application can be crucial from both performance and security standpoint. In StringZilla a 64-bit rolling hash function is reused for both string hashes and substring hashes, Rabin-style fingerprints. Rolling hashes take the same amount of time to compute hashes with different window sizes, and are fast to update. Those are not however perfect hashes, and collisions are frequent. StringZilla attempts to use SIMD, but the performance is not yet satisfactory. On Intel Sapphire Rapids, the following numbers can be expected for N-way parallel variants.

  • 4-way AVX2 throughput with 64-bit integer multiplication (no native support): 0.28 GB/s.
  • 4-way AVX2 throughput with 32-bit integer multiplication: 0.54 GB/s.
  • 4-way AVX-512DQ throughput with 64-bit integer multiplication: 0.46 GB/s.
  • 4-way AVX-512 throughput with 32-bit integer multiplication: 0.58 GB/s.
  • 8-way AVX-512 throughput with 32-bit integer multiplication: 0.11 GB/s.

Next design goals:

  • Try gear-hash and other rolling approaches.

Why not CRC32?

Cyclic Redundancy Check 32 is one of the most commonly used hash functions in Computer Science. It has in-hardware support on both x86 and Arm, for both 8-bit, 16-bit, 32-bit, and 64-bit words. The 0x1EDC6F41 polynomial is used in iSCSI, Btrfs, ext4, and the 0x04C11DB7 in SATA, Ethernet, Zlib, PNG. In case of Arm more than one polynomial is supported. It is, however, somewhat limiting for Big Data usecases, which often have to deal with more than 4 Billion strings, making collisions unavoidable. Moreover, the existing SIMD approaches are tricky, combining general purpose computations with specialized instructions, to utilize more silicon in every cycle.

§ Reading materials. Comprehensive derivation of approaches Faster computation for 4 KB buffers on x86 Comparing different lookup tables Great open-source implementations. By Peter Cawley By Stephan Brumme

Other Modern Alternatives

MurmurHash from 2008 by Austin Appleby is one of the best known non-cryptographic hashes. It has a very short implementation and is capable of producing 32-bit and 128-bit hashes. The CityHash from 2011 by Google and the xxHash improve on that, better leveraging the super-scalar nature of modern CPUs and producing 64-bit and 128-bit hashes.

Neither of those functions are cryptographic, unlike MD5, SHA, and BLAKE algorithms. Most of cryptographic hashes are based on the Merkle-Damgård construction, and aren't resistant to the length-extension attacks. Current state of the Art, might be the BLAKE3 algorithm. It's resistant to a broad range of attacks, can process 2 bytes per CPU cycle, and comes with a very optimized official implementation for C and Rust. It has the same 128-bit security level as the BLAKE2, and achieves its performance gains by reducing the number of mixing rounds, and processing data in 1 KiB chunks, which is great for longer strings, but may result in poor performance on short ones.

All mentioned libraries have undergone extensive testing and are considered production-ready. They can definitely accelerate your application, but so may the downstream mixer. For instance, when a hash-table is constructed, the hashes are further shrunk to address table buckets. If the mixer looses entropy, the performance gains from the hash function may be lost. An example would be power-of-two modulo, which is a common mixer, but is known to be weak. One alternative would be the fastrange by Daniel Lemire. Another one is the Fibonacci hash trick using the Golden Ratio, also used in StringZilla.

Unicode, UTF-8, and Wide Characters

Most StringZilla operations are byte-level, so they work well with ASCII and UTF8 content out of the box. In some cases, like edit-distance computation, the result of byte-level evaluation and character-level evaluation may differ. So StringZilla provides following functions to work with Unicode:

  • sz_edit_distance_utf8 - computes the Levenshtein distance between two UTF-8 strings.
  • sz_hamming_distance_utf8 - computes the Hamming distance between two UTF-8 strings.

Java, JavaScript, Python 2, C#, and Objective-C, however, use wide characters (wchar) - two byte long codes, instead of the more reasonable fixed-length UTF32 or variable-length UTF8. This leads to all kinds of offset-counting issues when facing four-byte long Unicode characters. So consider transcoding with simdutf, if you are coming from such environments.

Contributing 👾

Please check out the contributing guide for more details on how to setup the development environment and contribute to this project. If you like this project, you may also enjoy USearch, UCall, UForm, and SimSIMD. 🤗

If you like strings and value efficiency, you may also enjoy the following projects:

  • simdutf - transcoding UTF8, UTF16, and UTF32 LE and BE.
  • hyperscan - regular expressions with SIMD acceleration.
  • pyahocorasick - Aho-Corasick algorithm in Python.
  • rapidfuzz - fast string matching in C++ and Python.

If you are looking for more reading materials on this topic, consider the following:

License 📜

Feel free to use the project under Apache 2.0 or the Three-clause BSD license at your preference.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

stringzilla-3.9.3-cp312-cp312-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.12 Windows ARM64

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

Uploaded CPython 3.12 Windows x86-64

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

Uploaded CPython 3.12 Windows x86

stringzilla-3.9.3-cp312-cp312-musllinux_1_2_x86_64.whl (255.2 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.9.3-cp312-cp312-musllinux_1_2_s390x.whl (194.5 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.9.3-cp312-cp312-musllinux_1_2_ppc64le.whl (216.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.3-cp312-cp312-musllinux_1_2_i686.whl (199.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.6 kB view details)

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

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

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

stringzilla-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.3 kB view details)

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

stringzilla-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (209.8 kB view details)

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

stringzilla-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (198.0 kB view details)

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

stringzilla-3.9.3-cp312-cp312-macosx_11_0_arm64.whl (74.0 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

stringzilla-3.9.3-cp312-cp312-macosx_10_9_universal2.whl (112.7 kB view details)

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

stringzilla-3.9.3-cp311-cp311-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.11 Windows ARM64

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

Uploaded CPython 3.11 Windows x86-64

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

Uploaded CPython 3.11 Windows x86

stringzilla-3.9.3-cp311-cp311-musllinux_1_2_x86_64.whl (254.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.9.3-cp311-cp311-musllinux_1_2_s390x.whl (193.8 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.9.3-cp311-cp311-musllinux_1_2_ppc64le.whl (217.1 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.3-cp311-cp311-musllinux_1_2_i686.whl (199.6 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.9.3-cp311-cp311-musllinux_1_2_aarch64.whl (205.7 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.0 kB view details)

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

stringzilla-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.0 kB view details)

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

stringzilla-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.7 kB view details)

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

stringzilla-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.2 kB view details)

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

stringzilla-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (197.9 kB view details)

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

stringzilla-3.9.3-cp311-cp311-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

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

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.9.3-cp311-cp311-macosx_10_9_universal2.whl (112.4 kB view details)

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

stringzilla-3.9.3-cp310-cp310-win_arm64.whl (63.3 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.9.3-cp310-cp310-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.10 Windows x86-64

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

Uploaded CPython 3.10 Windows x86

stringzilla-3.9.3-cp310-cp310-musllinux_1_2_x86_64.whl (252.4 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.9.3-cp310-cp310-musllinux_1_2_s390x.whl (191.4 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.9.3-cp310-cp310-musllinux_1_2_ppc64le.whl (214.7 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.3-cp310-cp310-musllinux_1_2_i686.whl (197.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

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

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (257.0 kB view details)

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

stringzilla-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (189.9 kB view details)

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

stringzilla-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (218.2 kB view details)

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

stringzilla-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (208.0 kB view details)

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

stringzilla-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.7 kB view details)

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

stringzilla-3.9.3-cp310-cp310-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

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

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.9.3-cp310-cp310-macosx_10_9_universal2.whl (112.4 kB view details)

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

stringzilla-3.9.3-cp39-cp39-win_arm64.whl (64.7 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.9.3-cp39-cp39-win_amd64.whl (74.9 kB view details)

Uploaded CPython 3.9 Windows x86-64

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

Uploaded CPython 3.9 Windows x86

stringzilla-3.9.3-cp39-cp39-musllinux_1_2_x86_64.whl (251.1 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.9.3-cp39-cp39-musllinux_1_2_s390x.whl (190.3 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

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

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.9.3-cp39-cp39-musllinux_1_2_aarch64.whl (202.4 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.9 kB view details)

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

stringzilla-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.6 kB view details)

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

stringzilla-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.7 kB view details)

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

stringzilla-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.7 kB view details)

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

stringzilla-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.4 kB view details)

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

stringzilla-3.9.3-cp39-cp39-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.9.3-cp39-cp39-macosx_10_9_universal2.whl (112.4 kB view details)

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

stringzilla-3.9.3-cp38-cp38-win_amd64.whl (73.3 kB view details)

Uploaded CPython 3.8 Windows x86-64

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

Uploaded CPython 3.8 Windows x86

stringzilla-3.9.3-cp38-cp38-musllinux_1_2_x86_64.whl (250.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.9.3-cp38-cp38-musllinux_1_2_s390x.whl (189.1 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.9.3-cp38-cp38-musllinux_1_2_ppc64le.whl (212.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.3-cp38-cp38-musllinux_1_2_i686.whl (195.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.9.3-cp38-cp38-musllinux_1_2_aarch64.whl (201.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.1 kB view details)

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

stringzilla-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.6 kB view details)

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

stringzilla-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.8 kB view details)

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

stringzilla-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (205.7 kB view details)

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

stringzilla-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.5 kB view details)

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

stringzilla-3.9.3-cp38-cp38-macosx_11_0_arm64.whl (73.8 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.9.3-cp38-cp38-macosx_10_9_universal2.whl (112.4 kB view details)

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

stringzilla-3.9.3-cp37-cp37m-win_amd64.whl (73.3 kB view details)

Uploaded CPython 3.7m Windows x86-64

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

Uploaded CPython 3.7m Windows x86

stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_x86_64.whl (248.7 kB view details)

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

stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_s390x.whl (187.8 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_ppc64le.whl (210.6 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_i686.whl (193.9 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

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

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.7 kB view details)

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

stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.9 kB view details)

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

stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.8 kB view details)

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

stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (203.4 kB view details)

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

stringzilla-3.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.6 kB view details)

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

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

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.9.3-cp36-cp36m-win_amd64.whl (73.2 kB view details)

Uploaded CPython 3.6m Windows x86-64

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

Uploaded CPython 3.6m Windows x86

stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_x86_64.whl (247.9 kB view details)

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

stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_s390x.whl (187.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

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

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_i686.whl (193.4 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

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

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (252.8 kB view details)

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

stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (184.9 kB view details)

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

stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.4 kB view details)

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

stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.5 kB view details)

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

stringzilla-3.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (190.9 kB view details)

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

stringzilla-3.9.3-cp36-cp36m-macosx_10_9_x86_64.whl (73.2 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 aa75072538b2bafc0a740eb51244e21252c36b94ec2ae57717204e5a83d9560f
MD5 a383cd1c923738f9337b12df39fbee43
BLAKE2b-256 ecf930ca1860c1f8d52348920a9d22b95a8161de1ee9e3f85cad1ada8109a10d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 5d530eace5ff9a77b0c6f56db838d3de484df7a1fb69e615c3b1efa0555ba3f2
MD5 3da9ca2e713969ee163eba10999006c7
BLAKE2b-256 fdbc2aaba388ecda037b86f78ab430a6572948f697c3529fbcfdb233997b94a0

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 f8be2443574529b6a604bbe7d36eb867a41f2b81e053da55d4eb01e3ead0e7cb
MD5 6d6753c66457928e7e8f9e7696ae9373
BLAKE2b-256 11c0d057c35262294c4e07ad82c1de9e331ddba2e5a3416e05dec7ead704813d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8d7ff9420b761b0e29089eca15bb92cae45b574431dd4386d2c6965d19789a49
MD5 566dff58cb16b8b88aaec108d2d33348
BLAKE2b-256 a2d48124a510898fbcbf885b0058c72d5efbb39c6f4046dac003bdd063d5e3da

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 517d64d2125108d584626ebb82b7d472f7261f54d6a29f93bee3c9a3f23a47d2
MD5 d10b2dc473b7b066a73b20c694d5fbdc
BLAKE2b-256 cd62f005e706f495f068febb09685cd479b8dbd7856acd9bfa384344cc7d32ec

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 525c746764dd56bb8996feeef53a14466674cfa4fed8aef6d8372888335d220f
MD5 8d2c06f930e9c8f3d7aa462ec5f500e3
BLAKE2b-256 ddb44669429753a397fd07e17c284f9f507624e03ebeaafb54f9daa3116ab814

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 cb15c99ac3d6ec394a189f4d16bb5fca0f92588880f2be95ea4fd1cbb70a0af1
MD5 2e3f7acdf86c6710a662f796a5a60211
BLAKE2b-256 eb78261a20debb6cfd553fe9ed28ff1c0019d7f4f50b85186078858a69202d9f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0ace8366632d7d835404d60ac50def64e6231e28a903d2a3a296df2fde2f29d7
MD5 93e2843b8208c905f8565babeb2ac3fe
BLAKE2b-256 e7ddef505a15488178d613813df3357f1d3e0d1fd70f03a792b170d701b4247d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ed8c4e542659a97758d0a9a78df4bb166370ef8db097f22f38f1a182eafe8c96
MD5 9a6481765fa6368ae3ece622dafeee90
BLAKE2b-256 149dc3359424cab4b0f6a0b32b9714a1340165c40fc2344e76c1a237e7db35f9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e0485f1c359fab7341ebc5ceaca3b95cfc96f77a59be7a4a011cc779c6872c89
MD5 a39762bd16a1c6d05323d9db7dca0566
BLAKE2b-256 77aab3da8bcfcc3385414ecb1ab83ca93e9042abf15ecd05016cb7a4f12979f6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 3fe0dcaf2ce86a1c200a0a91565397849ec5c92a3d2030c84ad86e1d1163d4b1
MD5 02613a50a2ec264e9bc114d616e7621c
BLAKE2b-256 d958295ea0dfa834ee9b0700c87850247abcc0b0f48dd440062dc8be34d24d94

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d9371edc6a17822b333ea17af3c3e6756742576b308676804286b937880455f6
MD5 431b6d8d5ec7f010d03ff23b00227c02
BLAKE2b-256 423e90ae0db9edf4e7e0ef9dd7f2ba18564a3cd9ec4ab3eb9e9869ed5949c479

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 10a7ee52f3e8e5e7ccba4a0e50a6fb59f0aaabc942248e6e1d1f2049fc1c987f
MD5 8cf867239c25a9f198dcf954522b2988
BLAKE2b-256 e7daca2157838e04dfa64f9c0bcf77d69a647a0cf2f97a073a555125fcfb2e88

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b9d3f147641a42488ae07f8a2674ce203b274c1811b5c6e437139c242ccc4547
MD5 3457010775adc8237d336173e8f992d0
BLAKE2b-256 5625dcc84ebc6bf38cda5edbf7fb9f6522384132813dc3f0f27d9fc1bd3c2b00

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7904ad17debd0d5107986d5ebe0637f04676b78c1a7008cb16002e3aef80b440
MD5 a2c1f624ccb6f713b9fa64dd9d853a24
BLAKE2b-256 9694500770e5efc027632d1be52e5d1202dd427cd2fbbafe3f5fc66dbcdc6238

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp312-cp312-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 a24aac562045aaa8d409c21b3e7bcb1b4f4149b6e3e905717a33cb37ac7506e8
MD5 a6192835d43c1568a1883fa3fab9abd3
BLAKE2b-256 d69fad6aef0bc2510d17c4ae88d3326c275aa5b6583ca7a1380b04ba0f7e2dfe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 5ed428c1a118f077fb698ce37e14c5b6dc529a396c8bcbe8a97a8e98482b4217
MD5 209e2d9010cee19a392ea376eeb893c8
BLAKE2b-256 053f952c327e930079d4dd3977fed7d5a0be0ec3abe72486c0b3dbac46c13447

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 d7c3fc11d9b2e72cc18bded87c57c7ac6f106f6af65980d937a581779c5ab76e
MD5 4658284ee4e38dea980659327d07645d
BLAKE2b-256 162a09e4fd89c32c679d8689545bfc87af50d0d7dafb9d4d934285d05a1f735e

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 f6937362d3712fd133a3b4a59cb8a88f2a3a46944ab1926ade99c9c088ec5cd0
MD5 070dd98104e7e4b2b633b66f01981164
BLAKE2b-256 a160e9240e7a935962deaf0b6fcacb2318a556a29f54420731b0cc996b43a4af

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b4f7d36d028e5fc267d69e0143606f6ebe878c1f438996f8d82d6996fbe59a4b
MD5 a8660b9f7e1cb58b6fcd0956d2714d9d
BLAKE2b-256 1391854b483a4581570b661c75cb2e10d054ee0b1fa011452397eec8e039f613

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 6c4a7404a6ba84a39419bf3a67ca83d3cb5d739a9cc443c9cc16044d9ea7f767
MD5 0e10b85a7724891b6305ecd750d739ea
BLAKE2b-256 f1a3ebcb4159c361ae2e54749a037ff2a822a88efc1f0dbd9aff241bdd445258

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 91a0b923df3edb80efd00882c5eb1b231ed80f75033d0b8cc6dd2a47fa1bce0a
MD5 0dab2badd857ea2c39878d94dbcc5834
BLAKE2b-256 f5efc8094ae8334895d286dc0004d1ead30408664f961ed2c8801a935326c8bf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3fcfd51e788d52bdb8b563780fc060230693f05d6c04067a745ecc181e20e2d8
MD5 dfa255c764773007dd3f38a9d2260bf0
BLAKE2b-256 4fa13637ecb434593c5153add3bab5531a78036c70be60f7a3b94509526cc835

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4377f7782f2909dedf316a6e2eb48a6eab410406a59df046657d07c3b2b844d7
MD5 a1caa2a17915c17571470e1fdef7847d
BLAKE2b-256 338d2c79f91ea9ec3517707f8596247ff302bfe94219784bbc90afa488495889

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4e8f76573879c85decabf3ead76a2796d581f4a070a62bdc30de475be40fa7b1
MD5 2efbeb196f35922ef05fd5ab906ae254
BLAKE2b-256 4d5f86ae4c2b75cee2478dce7c653ff2582b002d441cc469e9e9f402eb069b14

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 310427baca6282ea0d4c50c482684f339e834a8dfd3ed3c91c97634344e70c79
MD5 470631830d1fb98b271cd080a70d1c8f
BLAKE2b-256 c78dadd43f6a9d7f6a511ce9f56927be937a2bbeb5471623e86b9811cc14eaca

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 71a914f5101ae79959df6cb86cd8c64ceb53db1ed33537915de0115b5296cf4c
MD5 6e4cd2a4cf9281b7667dac95771f0066
BLAKE2b-256 fb99703ff81c48798523be8aedc9458ee1f25e04541ee6c829db623fbc2c3f91

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6b0fd8139f16f8b02e27103f3a91d0d0804f68049e5a78e6392702fb4edcfdd9
MD5 a87384add4cec7ab18f5f593b22b923a
BLAKE2b-256 97cad80ac245206d9ae3aa7b243ea4732b56b43f0fee3ede57325a37152208bb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 020bd8ae82585fd82f370865488f7856a1f58af077bca955251e935b66c971ed
MD5 7a2ea8ff3b292d01cc25c64be6ebe347
BLAKE2b-256 d0d7412086f9bdfb1b758d1c0a905338671b1343922be7911845dc267136ae2b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 15a7a0243bd744374263682b65df3166d695fce77e4406ed3129e850cf87e5e6
MD5 7c43fae49eb02d6ef15136c1488baaab
BLAKE2b-256 7629af7d024d1cca1b80aa04a832e9dfb7729672c7a064a59ce379b3e7fe4117

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 8e2189bf2c1cddd061dc497be346a82bff41d141f49ba29b91735ef5d3b09841
MD5 8b3925e0c010fdbbe10562883a802ace
BLAKE2b-256 c798b0ef09cefc8cd5ca4e1d58c20875054037b9d292ce813f157e455823f326

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 859f50ccfc27eda0c8745836b54e0953cd95d4387d8f8dfae902ccc5fd888a56
MD5 2cbce305e79e66a6b355416ed68ad6c2
BLAKE2b-256 b6bfedfe4333572ff72d6a9836545541458f29db1734b12d229f9d576659c48a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 d9e6a642ed5e325c428ab545511aaa08f01d298e934fed980df6e0f252e16c3e
MD5 732ecdc383f2b4aa7c6b20de4a58aa65
BLAKE2b-256 1a7adfc060980a101ff33d42be8c5afb8735995ab05fbe0c4e973613d81ebbb8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 cba58d02708a3755f3a32f5b9bca02a6d0d265a7857728763a990e1b4ef7a992
MD5 65e0a1f560bbeaa8e88a077298577e30
BLAKE2b-256 a6b2fd2e576422059778299dc47761edd1367057629dfe4bf8335271a5d9ebca

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 400f5fd6a89a85250a17ac59c04944acdb82248b680e78a798cf4986c3f918ef
MD5 477542718ce4b995a88bcef1a6e7841f
BLAKE2b-256 4d4b352b6308da94a8c6bc06d64281dffce90ad6784557f70dd65e0dbe491a0c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 409552a08277578375cf711f7b1852463b33f54936eb74c234c7e9a6e84e2f95
MD5 7dac5287afc471cc2766c1cee107f0f0
BLAKE2b-256 8951a773fde68aea3703219c00b5327a8bfd7da21a2297fa6410c5a26a23513f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 6ad3196f04deca95007a4f61187510aff05133c90931a6f029319254553bec0f
MD5 12b8d6c1dee9a93d3502a5628bc6818c
BLAKE2b-256 ef2857993c3b63025776ff1485e2c88e5fbcf2cbd6c8a748a1c6f6920a3c6a66

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 18af0a8a25f9e31dc2566e2c67c890f6c6523d37e5e93b4d3a769aa1fd425d94
MD5 3f1e899100e6684945f2cf8bb40da91b
BLAKE2b-256 af68c5b7a751d6170cd6c5e0a9dd1aaa2d7350acc1acf01642f724b38955ba57

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 884175db0261cd3079e56b29fbaf6ecf51a8c24b32d2f646e81c1df609b6de5c
MD5 071cdb4cdf7f3b3842541da9f6d32a1e
BLAKE2b-256 8ba87a9202b83f8444ba1ccaa33574b09db65c2156d9b044c47a56bb5c2cca31

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 122e69b71e9671acbb9a21d5f4e1ead0c8c8c395a5313319e9ef1ad419c99bf3
MD5 7d312586ebf436ad700e70c511375da0
BLAKE2b-256 7566363b9c57c3ed77e97b89d6eb37a561d32812b5de84ba42e401446d25cadc

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 396681125fc68896da2a0261210f3f2b881952bc999f8cd37e4de68020cf5726
MD5 a3c691220fe98d022144f8166567c303
BLAKE2b-256 06a7d8abb8b3b8789c1847ea1b7a20a46b7ae62060afbcf76dee8f766dbb548e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 575bf7e8d513f026d5b46e981b16fc455bccb2d941e8af6ed1e12af2e61f1361
MD5 acd09bb3542bc328a46cdcc67270c618
BLAKE2b-256 678c8c2dd35bfeeb54d43f848edbd7397b737168d38405d348185fbee4ed429d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 daa714743be01f3041137d11f95e3e741192787d2cd978418ed0e449b6989110
MD5 573b6e479178418960975956d4d3eb9d
BLAKE2b-256 1e4e6af44e30e80582afc22692ed0fbcc43e2b13d9213687a3347ab47b0e0c24

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 e4125102d87199f743361d83b398b9d110b72c51c41d6cfabb8a89ac249940bc
MD5 26dca61aa48966aae3f93cad45299681
BLAKE2b-256 d5f8e71a6d934341bf46ab4a9baacdc515008d5f1f44288f65c224e4903599a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ab0a4c78fb6850b03e9b6716d20c2bf422f2eaad211b5f0e6142006515b2b33a
MD5 c0fa1aec45b6b13317c174c699c9e5dd
BLAKE2b-256 bf7b35066191ff2529ab722a8889cb22966d90e27ebf03f9c1db461c3a64f7b7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3d835ee907ada227afa6de74cc2216f9d8afebda84533fc10921b8a0af516d20
MD5 4fae72b433220ef6e842162d7fc5772e
BLAKE2b-256 e10e03e54f1f788fa1a8c2e4a900f82054ed4aff9afb95616bb4ddddd85d875d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 da7d2e0ec3a4ce22ad912fb0d9d6e040035dbb97b686841b1b11aa4cccfeb244
MD5 1a4ffcacf325f56e5e79210277229e5f
BLAKE2b-256 8b54b911bad724c7233c9b20e827aecbfd0a5e21fc5a718e9df6f9ea4c21bbae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 2c68ba89524970aff8e13729d9531944bf4cdf0a28b1f0daed7aa83b6d50257f
MD5 3e33878633a0a4d79c1eeec4eef9f0cf
BLAKE2b-256 c18d937599749fe86a0b58a56872aa7d4170cf9f85c8f8b6d3e702f07b9eb481

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 c63ec274fd48b438bac00cf0b1c50140abbb6efb6f4a9d63d19c9bcf76e14df3
MD5 3002c5044c6ac946e947329466cdf92d
BLAKE2b-256 bff78694ad9be31005b58983e9c4199388535e45b7dbdc72c4579451838f65fa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 3f4c4dc2313c77564aa2da4d314f04f67910b26487cd85b9b8525cc9f15b0b32
MD5 af50fb516562771c8e890dea11b4ce26
BLAKE2b-256 0f0ab50e056a4a88003a39080f3f97d1e3233df5f424d823e360acb2405bf44d

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 6b1d6d4d2f313e99bf747603735f3de5098485b90f8f56b4ea21a4192439fb2a
MD5 b533560c18ffcfcb93c4cdaf337c5f8c
BLAKE2b-256 63789092b906be6dbeae64adbb077703ef92cebc1c95c7c733850215c4256012

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9882c2374605654654b018574dcce87b87a8f526f683557cf0f851eddde4152f
MD5 188157630afc053cf86310ef635a672c
BLAKE2b-256 28134734d68bb9bfa3296b81deae8d94f2bbf507282cdeb25cd90cd7f36028f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 a4c29d871fd4ebde07161b5775dd4f92855f841db3b7351fc9366f12a3e70112
MD5 f81811caa5218498b4a90c5dd683cd2c
BLAKE2b-256 9e91a973190a089dd0152ffecead1189c723fa3789574d67cbbbc3ac3c6cdc00

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 fcc59b7ea2addcc221ddc6fa51cbf0a2aa6ed41cc8fe9dcd12c46a875fa532a4
MD5 4328da4b0844c53c03eaba7d4ac7d9fe
BLAKE2b-256 83cd7bf31d91937662e140c7503f76326bb69fa405f3c379f468eff7cdb55a8b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 ed40d21ea7d1a374d560b366712a5433c482dd8ee40e23976e7aee14b87d94b5
MD5 e88f7d4337374e17e286701b150251e4
BLAKE2b-256 8304de18bbbfaf7f8ac590da600c2252fadbe69dfd5b349505458e9aa7bb22e7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b7dd08664b12a2df5a5a2d9daedaece26582c1ba869c62e635346a4e22785d31
MD5 190dfed6560062f40c77e6b4ef74c178
BLAKE2b-256 de7ec79bfe31984b250ab4bfe82c18353e2f65891f12fae6f8f8d0444d05bc21

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8f4dc2e7128f463200a41939e7394a98c3bf338ffaa01a369204debb0ba94718
MD5 87c697cf7003ccdc75248c930987aca3
BLAKE2b-256 14573085fc99853c4a3aaf51d64d52944e6f2b894d6a79ed77d41d7bd38748a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 a02dc08d2a1a89d12d3c9263bfad5fd6b251997dea66233e281a0dab408be66b
MD5 378a18025022649eb3cf92b94816e171
BLAKE2b-256 08ab93d1e858042a61468b5f8738695ff0c6667c868856ed73f8d030c25e1fe6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 05dcf76d6330afb1153eacc0a19e0eacca6f94f94c249725b29823c24b1735fe
MD5 43e2c182d073a26eea23b10f21292d59
BLAKE2b-256 fdb93803d9a3affb27c93d5c782c5c7fe01cae0a17367a8389c74378d8ad2b0d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 72020bcd6ba474af193f3aba87185aa0e8479fe20a6ae6b17d22e77dd9eb432d
MD5 293a2649bd1b631cd985ef3ded958b75
BLAKE2b-256 b3b1abca13bf1a5a871145eaee379c892d8cf2f2f0b95127a653d3d7efb88f2c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 6ba46a5675f5197193ba7120ff2fdf0652ccd0ef8c2864643b698d2728e493ea
MD5 f782f3058320a97644e48c1bae73bff1
BLAKE2b-256 c0bb7f1fe9738c2f530cc63ddee9fa2cb7f37801e9ba93d7c8c4ac34c64f4f91

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dfd9b1b03169f50db54670d49b4ae40848e9e952d338e1e727d1a3af1b1c788d
MD5 28773833c702bdea18926e6450f29dad
BLAKE2b-256 3224ea7cae7c041d4775a779bb37812faf6344ae17cb9be0bc6993194a757cc7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 ca990b02ca1f760e38d81034a31253f073903f561746cd8478e6fd7f530db989
MD5 0c08a6047551ba96ab28c9682d8ea8e5
BLAKE2b-256 b888e35c971216da52ff6c025c8641e2c5d27f13f73af1740656c3a31566564f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 45bdcdddee67d512a8184729cbf804a0209b9db68647d212af83c67a355a836f
MD5 6fef67a41b13146f0e1db3ee2f5dcd89
BLAKE2b-256 e1b444073b5b09583b0367a931a10aa268bbdfd5032e18e2ae51216319c6cc54

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 20123a436e797690e3935ea8fca67170e8a5135f7e1a47436c1076f6552efb4b
MD5 5478a3a554818a3f1ba2aa77c9e505b4
BLAKE2b-256 e6ad6286982f822b8ad22d526b37284f2dcb53a8f39dc39c94aee13b1cc52b73

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 42f267b271315f375d7e0fac817aa5e11acbf14fecfd9e5142ad0fda1337b307
MD5 bbe0770fc1d169a15dbf61e8cc4d6ffd
BLAKE2b-256 c7710e355f551188df3feeaaa3d3dbbae5baccb1c8763b8c1294a4c914a556fd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 dea7f542d30676e5c2648b95b40cae6a6985ef85183f90f1e0121a3cc1965e77
MD5 4485312798e4bf5f12e8590735158f4f
BLAKE2b-256 20efa8dce60ee54cf22f872e74b5de29c9d7598cf5ff5483841906d4c3a3c8ac

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 64eb970d0eade3f896f97b53de62fe5bfc07169abb43b0b442c287744c1694c5
MD5 cd3455004f41ca4775146e45d7862d3f
BLAKE2b-256 09d5a3dce0e1e231482bfc916100440ff9e1ecc2dae15d537b23d2b448a39f79

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 b7575fa9a9028993f9a1081a2ea072f5375c7d247d3b693734aec09182e944e8
MD5 d3c063bcd99e5bc9f654c14dfdeddacc
BLAKE2b-256 078ec2aa6a29b81113a2b418560cedceba777e02c80ac33b4fab191344ffe6cb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 2000969ae324b0a03d7ec07ad3fe38b7781cf5966f8dd3483528cf40e2c7dcbd
MD5 ac2ea82c3bc33e7c492922a18009c8ce
BLAKE2b-256 0e2187b883a1421f68b1b40d9b18d1bb76a126f77d4131518a0a47d7eb57b2eb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 2bb57080e94302613d5661d1f3d4647a0492c42b6a10b1fb805a863a9c6366e0
MD5 bda7eab503da11a919934bffb482c48f
BLAKE2b-256 1126ca19dda267f7c2879e9bd3a23da66105c14600c5c00cc536b8ddf9695e92

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a1a7b04cecc4d440f16e20c3ba3ee643e092b2a6cb50807c76afb92b778fdaa8
MD5 3038359034218ee1f04b39efeb618d2e
BLAKE2b-256 39fdce991e9e6fc7029d6236a52cb667b3450b09c4caa55d0657f9871fd9504d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 9194a45cc665bbd9b4e0a79a0fcdf66d11638e3e8c4d98d2a69635e5681e69c3
MD5 8210043461b6e27f111d4d22d33c8433
BLAKE2b-256 f2e961f6d93c8a83e2ebe57c875fc19ddda9e15452789671ad43407855a9e3d1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 419249b0fb0199c75686ec78b50f5f65d380a81ab872d248b3fc82e08f03b393
MD5 7419c5022fcd2d2c02fa96f0818f9413
BLAKE2b-256 140a22a486faba5f4d0c0a6e9bbe7d16e1957e1cfd9dfe95b25d8a717729e8fe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6b73dbbba50db82379214889ee9d5940d218ceaf5f906c7fd35ef6ec5288182d
MD5 919be99fb518c2bffeb7135c84b1463f
BLAKE2b-256 e253d5fc3550f9d50248b34610664e9c0bb6d1edb76aa367a7ff5fcf47e0d31b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ec945c47ee5a5797ce7bd5510af6e4e514a942084e7186816088abee276a8ce6
MD5 fe51b35522daffb88399b45ab4ffd55f
BLAKE2b-256 472b116fb801d78e687189eb914e0dd2509ddc674a3798fe349c872d6505fb68

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 26b3c9776b12cfcf1b40bb3bf57e5f583448c97e80208a1cc0968ebd3af88a06
MD5 a0c05a3c2ade587e015615546cd20dcc
BLAKE2b-256 c3030790a9ba2439d8648473e54a9c53d2c25fc3fd354e8645fc487d0fc8ff3c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 23f7eda2e78b1dca5fb53e69d8e2d2aa4725b10429701ce95693521fe961d671
MD5 e425235b52560a0be62faeda2919c8fb
BLAKE2b-256 55474460da43f11fa6e5cec08a2efab915aaa44b8fb464186c5ddcfa765e2e5b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 c1e1a2cd6a1148ef73b6c3ea1ae52f760f4de9f7a92d0ff31b9be9f0c0c394ee
MD5 8b813e1b18040cd9b2c8f807c3a0e653
BLAKE2b-256 d5b5760dcd9935431212cff276d1120fd683e5fa50d09f0aac710bc7904107a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 d54602d781b7dff42e01201e245ea5730177b8be776443797c7ff847c64c029e
MD5 572691bf2a8ddb1ce3867d82ea9bb1eb
BLAKE2b-256 2abe4eedbf33023161c5b7e8e8ced23a49580f831b8aac1ca7bd0726c2aedfab

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 c2528bd34bc60c6485caa0fab54d6b59a80167cb13bdb562935b135bd3e2a437
MD5 2aa94fa9c1b0e76f5049e35b80717bd0
BLAKE2b-256 15a7112fcdd174dfdf1c6e68c196a127957466d364d08c462a4ecb5242c8b142

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 09d55bf7a7a35033bd51bd413bbd351b5deddb794adf20d0d210bf064235abd5
MD5 2a34efc999717fb6644302d8ddb61f48
BLAKE2b-256 bcd43d23085b075bcc412e5a096ea04db2ecdad7bfd9702fec46a1d03ac6260d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 db768780f751c70d78e275d6a002bb9e82c09700f1ebc1d8093f0cfe0bf63907
MD5 8ec5a8d38111ee470dfe44e9197a1e0e
BLAKE2b-256 45aee2468e1df20e59b38f234fbe64a8c177e2d3a6282ce8ea631bc0e3ea4236

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 cabb708b1c82b956564d25d6c01a800bd1860e46938f91a7bf89cad72323f605
MD5 d4c3248784f56f920afded69c0aa29e4
BLAKE2b-256 84737f60b1ce0b3ed9b066faa411928ca858ecd4ba987ec01f88d273a9f02e11

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 f575c5ee3c1b3784f5007051e1866d1fc2421832bb7c02500e04a47c64a5238e
MD5 caba63361ffbede404285ea1c9c2b8d3
BLAKE2b-256 86dfe9d9caf3cb2acf0939fb0ee42bae1954f84249cb47724ad2b7c0b9da604c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 936ab2925086fc48315a6a8a5c1561984a88df465c1a986670aa202f90f01e68
MD5 f4742d584e8e63fb94c3a4472182feb2
BLAKE2b-256 3b25dc48ee2b4a876f8a951d655c8c1b9d7c29876367768fbd20c695f1210d88

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 58b45054453ff82228c3a5229c594c525cb7dcf4c1abcdfb0a8bb4f8089ea619
MD5 cb1583c87233b9e5f7d780c9cd0f105a
BLAKE2b-256 92f38f166426df74021bc45098197389c5dbdadabbfaefce131d56af0e47bbc3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 26e553109939874ebc5009be3cdf7bc378931f7135a293b1699c9ca5dd60056b
MD5 3c87259f49334bb929ba9d4948221696
BLAKE2b-256 6ca5bb25a9bd26c849a440dcd8896fa780b6150f569e7077270a1f91acca3fbb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 9d7cc1cd7317a254a6ffe39fe043142779bd74a812ed031414a297b8e583a31e
MD5 a374710282f29751008c2a9998395478
BLAKE2b-256 a78084f4eb35366fa8a49d270eef7f0cd3ed507ec344276954a65463055ae714

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 46a38099ff827851970cbd477595338091fb8284f51e55743b75fef0ccb34378
MD5 c605eb856fba6230f9317c4109246b27
BLAKE2b-256 12b8fad9e182cc32b018a995730f4fe303eaa5d160ed29f7e1bfea0140b44b47

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 b2140196bb57862d3e472fc5852f40cfc8b192a3cd520d0fe6e818bde7b50cb8
MD5 a8ab5196ec1a1ba5239f01c9fec767fd
BLAKE2b-256 7ba37485b47ceddedb21546ff70e83896c46c66dd67f6b9553c36c098a254725

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3a73d0911c51a67c4051745ee6b0b5e2278e4ce7477a6a3e7601241a17d605fe
MD5 97dcc84404854e6d460359b84a4dcd0e
BLAKE2b-256 3d1c77a35fc1a34f24c3c9b4e7ea78a143de3973b0817c0d7f4e61b053c33191

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 75b9ddf38d71247a7704641d2d28e4a7922c4cf9f05f83080ce61b5e1ade7369
MD5 c6b89b3043dacbad251440cdd41f47ed
BLAKE2b-256 52a952dd808297ad882071bbc7bf844efd3bad4b58188e7601c157e417947f8c

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 443c8f42ad028f761554d1a9d5e288c0f43f03207667d13e691a2b7021e09764
MD5 83d910e01407f62ebe3da6876dccdd17
BLAKE2b-256 3dcfd7976afc0d5a1a2a23e2c6de548e51fee91daafaa6e5a702d95549c71db8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 28694972701e4e13bf5be082b9b95806cf49b2f2e6ab51d9ccd0b1902d743efb
MD5 9189a416411124ce0afb178b82387f65
BLAKE2b-256 d6d2d0d9832579498ec5fc086b3e71d99fd23f45c374f8f2be424b91cf3869e2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 4354f9e793f20db440135f732a2378e807837d11ada5e63f744da0dfc223edd0
MD5 e7b2f4271a332a6d6db8a14e2e12da88
BLAKE2b-256 c2c3bd2825774cd0edea2b2cb95d532244621b01b2b7a0b0f5286d4397149cfe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 5123c90e05f4234756e51a45ca3015877c0fc0759198041ee53da709bb295185
MD5 b8b02308b4d3d293f16638fbe942e018
BLAKE2b-256 3f583dba88638923fa34ab976ce242705357ee46bc9e34862f6a58033d0b55cf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 1cf539fcc0b9e2b9a0e888523e5d2c433fe9b25ceb0e5ae6a6b577592ccb3474
MD5 fa8abebec4809506c58a7ba65eaf4abb
BLAKE2b-256 6bb0c50bf16805e0888e947372d0de34ecaa1f446347bc6e18a140ad99d924e6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 9bcf6521d3b2ad6ab6ee78bd6b0c79b80455dfc5c88527be839f34b7cfe9257b
MD5 72ea88998201948e22391a7fc6297e78
BLAKE2b-256 663243d36343a428273e841297ffcbf0f0dbc50a5589dc85450cdf9abed58621

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.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.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1787e631bf03af4291110b808ecc34eee86c7df73ebdbe4c3c31c2af059a2de0
MD5 27e50e64e9aa7605f7c40f2765d7ce84
BLAKE2b-256 1f0dcdafaa87abed881a96a79e661e4864ca9a4e27f9584647c3e109a670b4f9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 79fa53112e0a32414eedbcba0d06eae7a96dd2c172b28347dca55fd1bb5e818b
MD5 a4ca5b0a96fff908bc936f011fdcabc8
BLAKE2b-256 ab9033ea47366e88ef49771aa5ca774bb9a42fffd005db084cc133ba271cca33

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 6ded46d205948ac42729b7099d72fae8827780b1e865f4cdc6332aa266db581d
MD5 60c67867452879b46477d8ebd938bed2
BLAKE2b-256 9a9955b837df117884227ebfe6ac4c3512da5536010a4d9fe9d298c996e38b12

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d6330e55a4fe5826ea3b29c4c0c158432a489627c3b99df3e651f9776ba6de11
MD5 9d0475121dc7e2f1c4b246bdee4d61ec
BLAKE2b-256 05cc6385a3d2014126c5c592f6fa9f6ec4968ab470b66654817b211bcf18eac0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 10c6bdd7ad96113bb24a20ab20cc3650b42280c78bd9be96f11d378ab767c036
MD5 817c5f8e8305393a027c6fe8a3993d04
BLAKE2b-256 81b7eb06ec5e9ce9a6eb3b0730aeb6db45003ad28905ad1fd11ecdf8822d6314

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for stringzilla-3.9.3-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 bc7aa25ef2aa63bfc56f88cd6f48ba42b79e1c5abc667c7337b72c183277d905
MD5 730d97d191c7ee1f5173482d0719616b
BLAKE2b-256 101349c607ec22269c00ff9988b2ab8c3c0d941f8ef8dcbdc16afa98cb684127

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