diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..9bee0e54
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,102 @@
+cmake_minimum_required(VERSION 3.23 FATAL_ERROR)
+
+# Project
+
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+project(
+ pyci
+ VERSION ${SKBUILD_PROJECT_VERSION}
+ LANGUAGES CXX)
+
+execute_process(
+ COMMAND sh -c "${CMAKE_CXX_COMPILER} --version | head -n 1"
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE PYCI_COMPILER_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+execute_process(
+ COMMAND git rev-parse --abbrev-ref HEAD
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE PYCI_GIT_BRANCH
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+execute_process(
+ COMMAND date -u +%F\ %T
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ OUTPUT_VARIABLE PYCI_BUILD_TIME
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+# Dependencies
+
+set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries")
+set(BUILD_TESTING OFF CACHE BOOL "Build testing")
+
+set(BUILD_SHARED_LIBS_ORIGINAL ${BUILD_SHARED_LIBS})
+set(BUILD_TESTING_ORIGINAL ${BUILD_TESTING})
+
+set(BUILD_SHARED_LIBS OFF)
+set(BUILD_TESTING OFF)
+
+include(FetchContent)
+
+find_package(Eigen3 REQUIRED NO_MODULE)
+
+FetchContent_Populate(spectra
+ URL https://github.com/yixuan/spectra/archive/refs/tags/v1.0.1.tar.gz
+ URL_HASH MD5=4c5364e377f733c3b2574d39a718bc3b
+ SOURCE_DIR spectra)
+
+FetchContent_Populate(parallel_hashmap
+ URL https://github.com/greg7mdp/parallel-hashmap/archive/refs/tags/v1.4.0.tar.gz
+ URL_HASH MD5=264fc23f81d17d30a0ebf34cdec8f4a6
+ SOURCE_DIR parallel_hashmap)
+
+FetchContent_Populate(rapidhash
+ URL https://github.com/Nicoshev/rapidhash/archive/refs/tags/rapidhash_v1.0.tar.gz
+ URL_HASH MD5=eff40e2b9b66e4608ba37709995b5255
+ SOURCE_DIR rapidhash)
+
+set(PYBIND11_FINDPYTHON ON)
+find_package(Python REQUIRED COMPONENTS Interpreter Development.Module NumPy)
+find_package(pybind11 CONFIG REQUIRED)
+
+set(BUILD_SHARED_LIBS_ORIGINAL ${BUILD_SHARED_LIBS})
+set(BUILD_TESTING_ORIGINAL ${BUILD_TESTING})
+
+# Build
+
+file(GLOB_RECURSE PYCI_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.cpp")
+
+pybind11_add_module(${PROJECT_NAME} MODULE ${PYCI_SOURCE_FILES})
+
+set_target_properties(${PROJECT_NAME}
+ PROPERTIES
+ OUTPUT_NAME _${PROJECT_NAME}
+ ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_NAME})
+
+target_include_directories(${PROJECT_NAME}
+ PRIVATE
+ ${PROJECT_SOURCE_DIR}/include
+ ${PROJECT_BINARY_DIR}/spectra/include
+ ${PROJECT_BINARY_DIR}/parallel_hashmap
+ ${PROJECT_BINARY_DIR}/rapidhash)
+
+target_link_libraries(${PROJECT_NAME} PRIVATE Eigen3::Eigen)
+
+target_compile_definitions(${PROJECT_NAME}
+ PRIVATE
+ _PYCI_VERSION="${PROJECT_VERSION}"
+ _GIT_BRANCH="${PYCI_GIT_BRANCH}"
+ _BUILD_TIME="${PYCI_BUILD_TIME}"
+ _COMPILER_VERSION="${PYCI_COMPILER_VERSION}")
+
+# Install
+
+install(TARGETS ${PROJECT_NAME} DESTINATION ${PROJECT_NAME})
+
+install(
+ DIRECTORY ${PROJECT_SOURCE_DIR}/include
+ DESTINATION ${SKBUILD_PLATLIB_DIR}/pyci/include)
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 6c500e7b..00000000
--- a/Makefile
+++ /dev/null
@@ -1,116 +0,0 @@
-# This file is part of PyCI.
-#
-# PyCI is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# PyCI is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with PyCI. If not, see .
-
-
-# Setup
-# -----
-
-# Set C compiler executable
-CC ?= cc
-export CC
-
-# Set C++ compiler executable
-CXX ?= c++
-export CXX
-
-# Set Python executable
-PYTHON ?= python3
-
-# Set C++ compile flags
-CFLAGS := -std=c++14 -Wall -Wextra -pipe -O3
-CFLAGS += -fPIC -flto=auto -fvisibility=hidden
-CFLAGS += -pthread
-CFLAGS += -Ipyci/include
-
-ifneq ($(MAKE_NATIVE),)
-CFLAGS += -mavx -mavx2 -msse4.2 -march=native -mtune=native
-endif
-
-# Set Python include directories
-CFLAGS += $(shell $(PYTHON) tools/python_include_dirs.py)
-
-# Set external projects and their include directories
-DEPS := $(addprefix deps/,eigen spectra parallel-hashmap pybind11)
-CFLAGS += $(addprefix -Ideps/,eigen spectra/include parallel-hashmap pybind11/include)
-
-# This C++ compile flag is needed in order for Macs to find system libraries
-ifeq ($(shell uname -s),Darwin)
-CFLAGS += -undefined dynamic_lookup
-endif
-
-# Set PyCI version number
-VERSION_MAJOR := 0
-VERSION_MINOR := 6
-VERSION_PATCH := 1
-PYCI_VERSION := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
-
-# Set preprocessor directives
-DEFS := -D_PYCI_VERSION='$(PYCI_VERSION)'
-DEFS += -D_GIT_BRANCH='$(shell git rev-parse --abbrev-ref HEAD)'
-DEFS += -D_BUILD_TIME='$(shell date -u +%F\ %T)'
-DEFS += -D_COMPILER_VERSION='$(shell $(CXX) --version | head -n 1)'
-
-# Set objects
-OBJECTS := $(patsubst %.cpp,%.o,$(wildcard pyci/src/*.cpp))
-
-
-# Make commands
-# -------------
-
-.PHONY: all
-all: pyci/_pyci.so.$(PYCI_VERSION) pyci/_pyci.so.$(VERSION_MAJOR) pyci/_pyci.so
-
-.PHONY: test
-test:
- $(PYTHON) -m pytest -sv ./pyci
-
-.PHONY: clean
-clean:
- rm -rf pyci/src/*.o pyci/_pyci.so*
-
-.PHONY: cleandeps
-cleandeps:
- rm -rf deps
-
-
-# Make targets
-# ------------
-
-compile_flags.txt:
- echo "$(CFLAGS)" | tr ' ' '\n' > $(@)
-
-pyci/src/%.o: pyci/src/%.cpp pyci/include/pyci.h $(DEPS)
- $(CXX) $(CFLAGS) $(DEFS) -c $(<) -o $(@)
-
-pyci/_pyci.so.$(PYCI_VERSION): $(OBJECTS)
- $(CXX) $(CFLAGS) $(DEFS) -shared $(^) -o $(@)
-
-pyci/_pyci.so.$(VERSION_MAJOR): pyci/_pyci.so.$(PYCI_VERSION)
- ln -sf $(notdir $(<)) $(@)
-
-pyci/_pyci.so: pyci/_pyci.so.$(PYCI_VERSION)
- ln -sf $(notdir $(<)) $(@)
-
-deps/eigen:
- @git clone https://gitlab.com/libeigen/eigen.git $(@)
-
-deps/spectra:
- @git clone https://github.com/yixuan/spectra.git $(@)
-
-deps/parallel-hashmap:
- @git clone https://github.com/greg7mdp/parallel-hashmap.git $(@)
-
-deps/pybind11:
- @git clone https://github.com/pybind/pybind11.git $(@)
diff --git a/pyci/include/pyci.h b/include/pyci.h
similarity index 98%
rename from pyci/include/pyci.h
rename to include/pyci.h
index 881c2bb4..017cde4c 100644
--- a/pyci/include/pyci.h
+++ b/include/pyci.h
@@ -41,7 +41,7 @@
#include
-#include
+#include
#include
@@ -118,13 +118,11 @@ inline int Ctz(const unsigned long long t) {
/* Hash function. */
-typedef std::pair Hash;
+typedef std::uint64_t Hash;
template
-Hash spookyhash(T length, const U *data) {
- Hash h(0x23a23cf5033c3c81UL, 0xb3816f6a2c68e530UL);
- SpookyHash::Hash128(reinterpret_cast(data), length * sizeof(U), &h.first, &h.second);
- return h;
+Hash compute_hash(T length, const U *data) {
+ return rapidhash(reinterpret_cast(data), length * sizeof(U));
}
/* Vector template types. */
diff --git a/pyci/include/sort_with_arg.h b/include/sort_with_arg.h
similarity index 100%
rename from pyci/include/sort_with_arg.h
rename to include/sort_with_arg.h
diff --git a/pyci/include/SpookyV2.h b/pyci/include/SpookyV2.h
deleted file mode 100644
index 4ccc0d52..00000000
--- a/pyci/include/SpookyV2.h
+++ /dev/null
@@ -1,299 +0,0 @@
-//
-// SpookyHash: a 128-bit noncryptographic hash function
-// By Bob Jenkins, public domain
-// Oct 31 2010: alpha, framework + SpookyHash::Mix appears right
-// Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right
-// Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas
-// Feb 2 2012: production, same bits as beta
-// Feb 5 2012: adjusted definitions of uint* to be more portable
-// Mar 30 2012: 3 bytes/cycle, not 4. Alpha was 4 but wasn't thorough enough.
-// August 5 2012: SpookyV2 (different results)
-//
-// Up to 3 bytes/cycle for long messages. Reasonably fast for short messages.
-// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit.
-//
-// This was developed for and tested on 64-bit x86-compatible processors.
-// It assumes the processor is little-endian. There is a macro
-// controlling whether unaligned reads are allowed (by default they are).
-// This should be an equally good hash on big-endian machines, but it will
-// compute different results on them than on little-endian machines.
-//
-// Google's CityHash has similar specs to SpookyHash, and CityHash is faster
-// on new Intel boxes. MD4 and MD5 also have similar specs, but they are orders
-// of magnitude slower. CRCs are two or more times slower, but unlike
-// SpookyHash, they have nice math for combining the CRCs of pieces to form
-// the CRCs of wholes. There are also cryptographic hashes, but those are even
-// slower than MD5.
-//
-
-#include
-
-#ifdef _MSC_VER
-# define INLINE __forceinline
- typedef unsigned __int64 uint64;
- typedef unsigned __int32 uint32;
- typedef unsigned __int16 uint16;
- typedef unsigned __int8 uint8;
-#else
-# include
-# define INLINE inline
- typedef uint64_t uint64;
- typedef uint32_t uint32;
- typedef uint16_t uint16;
- typedef uint8_t uint8;
-#endif
-
-
-class SpookyHash
-{
-public:
- //
- // SpookyHash: hash a single message in one call, produce 128-bit output
- //
- static void Hash128(
- const void *message, // message to hash
- size_t length, // length of message in bytes
- uint64 *hash1, // in/out: in seed 1, out hash value 1
- uint64 *hash2); // in/out: in seed 2, out hash value 2
-
- //
- // Hash64: hash a single message in one call, return 64-bit output
- //
- static uint64 Hash64(
- const void *message, // message to hash
- size_t length, // length of message in bytes
- uint64 seed) // seed
- {
- uint64 hash1 = seed;
- Hash128(message, length, &hash1, &seed);
- return hash1;
- }
-
- //
- // Hash32: hash a single message in one call, produce 32-bit output
- //
- static uint32 Hash32(
- const void *message, // message to hash
- size_t length, // length of message in bytes
- uint32 seed) // seed
- {
- uint64 hash1 = seed, hash2 = seed;
- Hash128(message, length, &hash1, &hash2);
- return (uint32)hash1;
- }
-
- //
- // Init: initialize the context of a SpookyHash
- //
- void Init(
- uint64 seed1, // any 64-bit value will do, including 0
- uint64 seed2); // different seeds produce independent hashes
-
- //
- // Update: add a piece of a message to a SpookyHash state
- //
- void Update(
- const void *message, // message fragment
- size_t length); // length of message fragment in bytes
-
-
- //
- // Final: compute the hash for the current SpookyHash state
- //
- // This does not modify the state; you can keep updating it afterward
- //
- // The result is the same as if SpookyHash() had been called with
- // all the pieces concatenated into one message.
- //
- void Final(
- uint64 *hash1, // out only: first 64 bits of hash value.
- uint64 *hash2); // out only: second 64 bits of hash value.
-
- //
- // left rotate a 64-bit value by k bytes
- //
- static INLINE uint64 Rot64(uint64 x, int k)
- {
- return (x << k) | (x >> (64 - k));
- }
-
- //
- // This is used if the input is 96 bytes long or longer.
- //
- // The internal state is fully overwritten every 96 bytes.
- // Every input bit appears to cause at least 128 bits of entropy
- // before 96 other bytes are combined, when run forward or backward
- // For every input bit,
- // Two inputs differing in just that input bit
- // Where "differ" means xor or subtraction
- // And the base value is random
- // When run forward or backwards one Mix
- // I tried 3 pairs of each; they all differed by at least 212 bits.
- //
- static INLINE void Mix(
- const uint64 *data,
- uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3,
- uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7,
- uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11)
- {
- s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = Rot64(s0,11); s11 += s1;
- s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = Rot64(s1,32); s0 += s2;
- s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = Rot64(s2,43); s1 += s3;
- s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = Rot64(s3,31); s2 += s4;
- s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = Rot64(s4,17); s3 += s5;
- s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = Rot64(s5,28); s4 += s6;
- s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = Rot64(s6,39); s5 += s7;
- s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = Rot64(s7,57); s6 += s8;
- s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = Rot64(s8,55); s7 += s9;
- s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = Rot64(s9,54); s8 += s10;
- s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = Rot64(s10,22); s9 += s11;
- s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = Rot64(s11,46); s10 += s0;
- }
-
- //
- // Mix all 12 inputs together so that h0, h1 are a hash of them all.
- //
- // For two inputs differing in just the input bits
- // Where "differ" means xor or subtraction
- // And the base value is random, or a counting value starting at that bit
- // The final result will have each bit of h0, h1 flip
- // For every input bit,
- // with probability 50 +- .3%
- // For every pair of input bits,
- // with probability 50 +- 3%
- //
- // This does not rely on the last Mix() call having already mixed some.
- // Two iterations was almost good enough for a 64-bit result, but a
- // 128-bit result is reported, so End() does three iterations.
- //
- static INLINE void EndPartial(
- uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3,
- uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7,
- uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11)
- {
- h11+= h1; h2 ^= h11; h1 = Rot64(h1,44);
- h0 += h2; h3 ^= h0; h2 = Rot64(h2,15);
- h1 += h3; h4 ^= h1; h3 = Rot64(h3,34);
- h2 += h4; h5 ^= h2; h4 = Rot64(h4,21);
- h3 += h5; h6 ^= h3; h5 = Rot64(h5,38);
- h4 += h6; h7 ^= h4; h6 = Rot64(h6,33);
- h5 += h7; h8 ^= h5; h7 = Rot64(h7,10);
- h6 += h8; h9 ^= h6; h8 = Rot64(h8,13);
- h7 += h9; h10^= h7; h9 = Rot64(h9,38);
- h8 += h10; h11^= h8; h10= Rot64(h10,53);
- h9 += h11; h0 ^= h9; h11= Rot64(h11,42);
- h10+= h0; h1 ^= h10; h0 = Rot64(h0,54);
- }
-
- static INLINE void End(
- const uint64 *data,
- uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3,
- uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7,
- uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11)
- {
- h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3];
- h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7];
- h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11];
- EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- }
-
- //
- // The goal is for each bit of the input to expand into 128 bits of
- // apparent entropy before it is fully overwritten.
- // n trials both set and cleared at least m bits of h0 h1 h2 h3
- // n: 2 m: 29
- // n: 3 m: 46
- // n: 4 m: 57
- // n: 5 m: 107
- // n: 6 m: 146
- // n: 7 m: 152
- // when run forwards or backwards
- // for all 1-bit and 2-bit diffs
- // with diffs defined by either xor or subtraction
- // with a base of all zeros plus a counter, or plus another bit, or random
- //
- static INLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3)
- {
- h2 = Rot64(h2,50); h2 += h3; h0 ^= h2;
- h3 = Rot64(h3,52); h3 += h0; h1 ^= h3;
- h0 = Rot64(h0,30); h0 += h1; h2 ^= h0;
- h1 = Rot64(h1,41); h1 += h2; h3 ^= h1;
- h2 = Rot64(h2,54); h2 += h3; h0 ^= h2;
- h3 = Rot64(h3,48); h3 += h0; h1 ^= h3;
- h0 = Rot64(h0,38); h0 += h1; h2 ^= h0;
- h1 = Rot64(h1,37); h1 += h2; h3 ^= h1;
- h2 = Rot64(h2,62); h2 += h3; h0 ^= h2;
- h3 = Rot64(h3,34); h3 += h0; h1 ^= h3;
- h0 = Rot64(h0,5); h0 += h1; h2 ^= h0;
- h1 = Rot64(h1,36); h1 += h2; h3 ^= h1;
- }
-
- //
- // Mix all 4 inputs together so that h0, h1 are a hash of them all.
- //
- // For two inputs differing in just the input bits
- // Where "differ" means xor or subtraction
- // And the base value is random, or a counting value starting at that bit
- // The final result will have each bit of h0, h1 flip
- // For every input bit,
- // with probability 50 +- .3% (it is probably better than that)
- // For every pair of input bits,
- // with probability 50 +- .75% (the worst case is approximately that)
- //
- static INLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3)
- {
- h3 ^= h2; h2 = Rot64(h2,15); h3 += h2;
- h0 ^= h3; h3 = Rot64(h3,52); h0 += h3;
- h1 ^= h0; h0 = Rot64(h0,26); h1 += h0;
- h2 ^= h1; h1 = Rot64(h1,51); h2 += h1;
- h3 ^= h2; h2 = Rot64(h2,28); h3 += h2;
- h0 ^= h3; h3 = Rot64(h3,9); h0 += h3;
- h1 ^= h0; h0 = Rot64(h0,47); h1 += h0;
- h2 ^= h1; h1 = Rot64(h1,54); h2 += h1;
- h3 ^= h2; h2 = Rot64(h2,32); h3 += h2;
- h0 ^= h3; h3 = Rot64(h3,25); h0 += h3;
- h1 ^= h0; h0 = Rot64(h0,63); h1 += h0;
- }
-
-private:
-
- //
- // Short is used for messages under 192 bytes in length
- // Short has a low startup cost, the normal mode is good for long
- // keys, the cost crossover is at about 192 bytes. The two modes were
- // held to the same quality bar.
- //
- static void Short(
- const void *message, // message (array of bytes, not necessarily aligned)
- size_t length, // length of message (in bytes)
- uint64 *hash1, // in/out: in the seed, out the hash value
- uint64 *hash2); // in/out: in the seed, out the hash value
-
- // number of uint64's in internal state
- static const size_t sc_numVars = 12;
-
- // size of the internal state
- static const size_t sc_blockSize = sc_numVars*8;
-
- // size of buffer of unhashed data, in bytes
- static const size_t sc_bufSize = 2*sc_blockSize;
-
- //
- // sc_const: a constant which:
- // * is not zero
- // * is odd
- // * is a not-very-regular mix of 1's and 0's
- // * does not need any other special mathematical properties
- //
- static const uint64 sc_const = 0xdeadbeefdeadbeefLL;
-
- uint64 m_data[2*sc_numVars]; // unhashed data, for partial messages
- uint64 m_state[sc_numVars]; // internal state of the hash
- size_t m_length; // total length of the input so far
- uint8 m_remainder; // length of unhashed data stashed in m_data
-};
-
-
-
diff --git a/pyci/src/SpookyV2.cpp b/pyci/src/SpookyV2.cpp
deleted file mode 100644
index 735bd562..00000000
--- a/pyci/src/SpookyV2.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-// Spooky Hash
-// A 128-bit noncryptographic hash, for checksums and table lookup
-// By Bob Jenkins. Public domain.
-// Oct 31 2010: published framework, disclaimer ShortHash isn't right
-// Nov 7 2010: disabled ShortHash
-// Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
-// April 10 2012: buffer overflow on platforms without unaligned reads
-// July 12 2012: was passing out variables in final to in/out in short
-// July 30 2012: I reintroduced the buffer overflow
-// August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
-
-#include
-#include "SpookyV2.h"
-
-#define ALLOW_UNALIGNED_READS 1
-
-//
-// short hash ... it could be used on any message,
-// but it's used by Spooky just for short messages.
-//
-void SpookyHash::Short(
- const void *message,
- size_t length,
- uint64 *hash1,
- uint64 *hash2)
-{
- uint64 buf[2*sc_numVars];
- union
- {
- const uint8 *p8;
- uint32 *p32;
- uint64 *p64;
- size_t i;
- } u;
-
- u.p8 = (const uint8 *)message;
-
- if (!ALLOW_UNALIGNED_READS && (u.i & 0x7))
- {
- memcpy(buf, message, length);
- u.p64 = buf;
- }
-
- size_t remainder = length%32;
- uint64 a=*hash1;
- uint64 b=*hash2;
- uint64 c=sc_const;
- uint64 d=sc_const;
-
- if (length > 15)
- {
- const uint64 *end = u.p64 + (length/32)*4;
-
- // handle all complete sets of 32 bytes
- for (; u.p64 < end; u.p64 += 4)
- {
- c += u.p64[0];
- d += u.p64[1];
- ShortMix(a,b,c,d);
- a += u.p64[2];
- b += u.p64[3];
- }
-
- //Handle the case of 16+ remaining bytes.
- if (remainder >= 16)
- {
- c += u.p64[0];
- d += u.p64[1];
- ShortMix(a,b,c,d);
- u.p64 += 2;
- remainder -= 16;
- }
- }
-
- // Handle the last 0..15 bytes, and its length
- d += ((uint64)length) << 56;
- switch (remainder)
- {
- case 15:
- d += ((uint64)u.p8[14]) << 48;
- case 14:
- d += ((uint64)u.p8[13]) << 40;
- case 13:
- d += ((uint64)u.p8[12]) << 32;
- case 12:
- d += u.p32[2];
- c += u.p64[0];
- break;
- case 11:
- d += ((uint64)u.p8[10]) << 16;
- case 10:
- d += ((uint64)u.p8[9]) << 8;
- case 9:
- d += (uint64)u.p8[8];
- case 8:
- c += u.p64[0];
- break;
- case 7:
- c += ((uint64)u.p8[6]) << 48;
- case 6:
- c += ((uint64)u.p8[5]) << 40;
- case 5:
- c += ((uint64)u.p8[4]) << 32;
- case 4:
- c += u.p32[0];
- break;
- case 3:
- c += ((uint64)u.p8[2]) << 16;
- case 2:
- c += ((uint64)u.p8[1]) << 8;
- case 1:
- c += (uint64)u.p8[0];
- break;
- case 0:
- c += sc_const;
- d += sc_const;
- }
- ShortEnd(a,b,c,d);
- *hash1 = a;
- *hash2 = b;
-}
-
-
-
-
-// do the whole hash in one call
-void SpookyHash::Hash128(
- const void *message,
- size_t length,
- uint64 *hash1,
- uint64 *hash2)
-{
- if (length < sc_bufSize)
- {
- Short(message, length, hash1, hash2);
- return;
- }
-
- uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
- uint64 buf[sc_numVars];
- uint64 *end;
- union
- {
- const uint8 *p8;
- uint64 *p64;
- size_t i;
- } u;
- size_t remainder;
-
- h0=h3=h6=h9 = *hash1;
- h1=h4=h7=h10 = *hash2;
- h2=h5=h8=h11 = sc_const;
-
- u.p8 = (const uint8 *)message;
- end = u.p64 + (length/sc_blockSize)*sc_numVars;
-
- // handle all whole sc_blockSize blocks of bytes
- if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0))
- {
- while (u.p64 < end)
- {
- Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- u.p64 += sc_numVars;
- }
- }
- else
- {
- while (u.p64 < end)
- {
- memcpy(buf, u.p64, sc_blockSize);
- Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- u.p64 += sc_numVars;
- }
- }
-
- // handle the last partial block of sc_blockSize bytes
- remainder = (length - ((const uint8 *)end-(const uint8 *)message));
- memcpy(buf, end, remainder);
- memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder);
- ((uint8 *)buf)[sc_blockSize-1] = remainder;
-
- // do some final mixing
- End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- *hash1 = h0;
- *hash2 = h1;
-}
-
-
-
-// init spooky state
-void SpookyHash::Init(uint64 seed1, uint64 seed2)
-{
- m_length = 0;
- m_remainder = 0;
- m_state[0] = seed1;
- m_state[1] = seed2;
-}
-
-
-// add a message fragment to the state
-void SpookyHash::Update(const void *message, size_t length)
-{
- uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
- size_t newLength = length + m_remainder;
- uint8 remainder;
- union
- {
- const uint8 *p8;
- uint64 *p64;
- size_t i;
- } u;
- const uint64 *end;
-
- // Is this message fragment too short? If it is, stuff it away.
- if (newLength < sc_bufSize)
- {
- memcpy(&((uint8 *)m_data)[m_remainder], message, length);
- m_length = length + m_length;
- m_remainder = (uint8)newLength;
- return;
- }
-
- // init the variables
- if (m_length < sc_bufSize)
- {
- h0=h3=h6=h9 = m_state[0];
- h1=h4=h7=h10 = m_state[1];
- h2=h5=h8=h11 = sc_const;
- }
- else
- {
- h0 = m_state[0];
- h1 = m_state[1];
- h2 = m_state[2];
- h3 = m_state[3];
- h4 = m_state[4];
- h5 = m_state[5];
- h6 = m_state[6];
- h7 = m_state[7];
- h8 = m_state[8];
- h9 = m_state[9];
- h10 = m_state[10];
- h11 = m_state[11];
- }
- m_length = length + m_length;
-
- // if we've got anything stuffed away, use it now
- if (m_remainder)
- {
- uint8 prefix = sc_bufSize-m_remainder;
- memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix);
- u.p64 = m_data;
- Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- u.p8 = ((const uint8 *)message) + prefix;
- length -= prefix;
- }
- else
- {
- u.p8 = (const uint8 *)message;
- }
-
- // handle all whole blocks of sc_blockSize bytes
- end = u.p64 + (length/sc_blockSize)*sc_numVars;
- remainder = (uint8)(length-((const uint8 *)end-u.p8));
- if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0)
- {
- while (u.p64 < end)
- {
- Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- u.p64 += sc_numVars;
- }
- }
- else
- {
- while (u.p64 < end)
- {
- memcpy(m_data, u.p8, sc_blockSize);
- Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- u.p64 += sc_numVars;
- }
- }
-
- // stuff away the last few bytes
- m_remainder = remainder;
- memcpy(m_data, end, remainder);
-
- // stuff away the variables
- m_state[0] = h0;
- m_state[1] = h1;
- m_state[2] = h2;
- m_state[3] = h3;
- m_state[4] = h4;
- m_state[5] = h5;
- m_state[6] = h6;
- m_state[7] = h7;
- m_state[8] = h8;
- m_state[9] = h9;
- m_state[10] = h10;
- m_state[11] = h11;
-}
-
-
-// report the hash for the concatenation of all message fragments so far
-void SpookyHash::Final(uint64 *hash1, uint64 *hash2)
-{
- // init the variables
- if (m_length < sc_bufSize)
- {
- *hash1 = m_state[0];
- *hash2 = m_state[1];
- Short( m_data, m_length, hash1, hash2);
- return;
- }
-
- const uint64 *data = (const uint64 *)m_data;
- uint8 remainder = m_remainder;
-
- uint64 h0 = m_state[0];
- uint64 h1 = m_state[1];
- uint64 h2 = m_state[2];
- uint64 h3 = m_state[3];
- uint64 h4 = m_state[4];
- uint64 h5 = m_state[5];
- uint64 h6 = m_state[6];
- uint64 h7 = m_state[7];
- uint64 h8 = m_state[8];
- uint64 h9 = m_state[9];
- uint64 h10 = m_state[10];
- uint64 h11 = m_state[11];
-
- if (remainder >= sc_blockSize)
- {
- // m_data can contain two blocks; handle any whole first block
- Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
- data += sc_numVars;
- remainder -= sc_blockSize;
- }
-
- // mix in the last partial block, and the length mod sc_blockSize
- memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder));
-
- ((uint8 *)data)[sc_blockSize-1] = remainder;
-
- // do some final mixing
- End(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
-
- *hash1 = h0;
- *hash2 = h1;
-}
-
diff --git a/pyproject.toml b/pyproject.toml
index 342bd775..6490e3b9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -80,6 +80,7 @@ packages = [
]
[tool.setuptools.package-data]
+where = ["pyci"]
# Non-Python files to include in the package
"pyci" = [
"_pyci.so", # Compiled C++ extension
@@ -92,14 +93,14 @@ packages = [
"data/*.npz" # Compressed NumPy data files
]
-# Build configuration
-[tool.scikit-build]
-sdist.exclude = [
- ".github",
- "tests/data/*.fchk",
- "examples/*.fchk"
-]
-metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
+# # Build configuration
+# [tool.scikit-build]
+# sdist.exclude = [
+# ".github",
+# "tests/data/*.fchk",
+# "examples/*.fchk"
+# ]
+# metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
# Version management configuration
[tool.setuptools_scm]
diff --git a/pyci/src/ap1rog.cpp b/src/ap1rog.cpp
similarity index 100%
rename from pyci/src/ap1rog.cpp
rename to src/ap1rog.cpp
diff --git a/pyci/src/apig.cpp b/src/apig.cpp
similarity index 100%
rename from pyci/src/apig.cpp
rename to src/apig.cpp
diff --git a/pyci/src/binding.cpp b/src/binding.cpp
similarity index 100%
rename from pyci/src/binding.cpp
rename to src/binding.cpp
diff --git a/pyci/src/common.cpp b/src/common.cpp
similarity index 100%
rename from pyci/src/common.cpp
rename to src/common.cpp
diff --git a/pyci/src/dociwfn.cpp b/src/dociwfn.cpp
similarity index 100%
rename from pyci/src/dociwfn.cpp
rename to src/dociwfn.cpp
diff --git a/pyci/src/enpt2.cpp b/src/enpt2.cpp
similarity index 100%
rename from pyci/src/enpt2.cpp
rename to src/enpt2.cpp
diff --git a/pyci/src/fanci.cpp b/src/fanci.cpp
similarity index 100%
rename from pyci/src/fanci.cpp
rename to src/fanci.cpp
diff --git a/pyci/src/fullciwfn.cpp b/src/fullciwfn.cpp
similarity index 100%
rename from pyci/src/fullciwfn.cpp
rename to src/fullciwfn.cpp
diff --git a/pyci/src/genciwfn.cpp b/src/genciwfn.cpp
similarity index 100%
rename from pyci/src/genciwfn.cpp
rename to src/genciwfn.cpp
diff --git a/pyci/src/hci.cpp b/src/hci.cpp
similarity index 100%
rename from pyci/src/hci.cpp
rename to src/hci.cpp
diff --git a/pyci/src/onespinwfn.cpp b/src/onespinwfn.cpp
similarity index 99%
rename from pyci/src/onespinwfn.cpp
rename to src/onespinwfn.cpp
index 4cba6438..b720bbca 100644
--- a/pyci/src/onespinwfn.cpp
+++ b/src/onespinwfn.cpp
@@ -135,7 +135,7 @@ void OneSpinWfn::copy_det(const long i, ulong *det) const {
}
Hash OneSpinWfn::rank_det(const ulong *det) const {
- return spookyhash(nword, det);
+ return compute_hash(nword, det);
}
long OneSpinWfn::add_det(const ulong *det) {
diff --git a/pyci/src/overlap.cpp b/src/overlap.cpp
similarity index 100%
rename from pyci/src/overlap.cpp
rename to src/overlap.cpp
diff --git a/pyci/src/rdm.cpp b/src/rdm.cpp
similarity index 100%
rename from pyci/src/rdm.cpp
rename to src/rdm.cpp
diff --git a/pyci/src/sparseop.cpp b/src/sparseop.cpp
similarity index 100%
rename from pyci/src/sparseop.cpp
rename to src/sparseop.cpp
diff --git a/pyci/src/squantop.cpp b/src/squantop.cpp
similarity index 100%
rename from pyci/src/squantop.cpp
rename to src/squantop.cpp
diff --git a/pyci/src/twospinwfn.cpp b/src/twospinwfn.cpp
similarity index 99%
rename from pyci/src/twospinwfn.cpp
rename to src/twospinwfn.cpp
index def18ef6..492c8580 100644
--- a/pyci/src/twospinwfn.cpp
+++ b/src/twospinwfn.cpp
@@ -141,7 +141,7 @@ void TwoSpinWfn::copy_det(const long i, ulong *det) const {
}
Hash TwoSpinWfn::rank_det(const ulong *det) const {
- return spookyhash(nword2, det);
+ return compute_hash(nword2, det);
}
long TwoSpinWfn::add_det(const ulong *det) {
diff --git a/pyci/src/wfn.cpp b/src/wfn.cpp
similarity index 100%
rename from pyci/src/wfn.cpp
rename to src/wfn.cpp