Files
2025-06-26 09:17:29 +02:00

300 lines
8.3 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
//
// MolecularDNAHashing.hh
// Geant4
//
// Created by Mathieu Karamitros
//
//
#ifndef MolecularDNAHashing_h
#define MolecularDNAHashing_h
#include <cstdint>
#include <string>
#include <type_traits>
#include <utility>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
namespace G4::hashing
{
namespace crc32
{
//--------------------------------------------------------------------------
// Generate CRC lookup table
//--------------------------------------------------------------------------
template<unsigned long long c, int k = 8>
struct f : f<((c & 1) ? 0xedb88320 : 0) ^ (c >> 1), k - 1>
{};
template<unsigned long long c>
struct f<c, 0>
{
enum
{
value = c
};
};
#define _A_(x) _B_(x) _B_(x + 128llu)
#define _B_(x) _C_(x) _C_(x + 64llu)
#define _C_(x) _D_(x) _D_(x + 32llu)
#define _D_(x) _E_(x) _E_(x + 16llu)
#define _E_(x) _F_(x) _F_(x + 8llu)
#define _F_(x) _G_(x) _G_(x + 4llu)
#define _G_(x) _H_(x) _H_(x + 2llu)
#define _H_(x) _I_(x) _I_(x + 1llu)
#define _I_(x) f<x>::value,
static constexpr unsigned fCrc_table[] = {_A_(0llu)};
//--------------------------------------------------------------------------
// CRC32 ALGO
//--------------------------------------------------------------------------
//--------------------------------
// RUN TIME ALGO
uint32_t Hash(const char* str, size_t len);
//--------------------------------------------------------------------------
// Details for compilation time
namespace detail
{
// CRC32 Table (zlib polynomial)
template<size_t idx>
constexpr uint32_t Combine_crc32(const char* str, uint32_t part)
{
return (part >> 8) ^ fCrc_table[(part ^ str[idx]) & 0x000000FF];
}
// recursion
template<size_t idx>
constexpr uint32_t Crc32(const char* str)
{
return Combine_crc32<idx>(str, Crc32<idx - 1>(str));
}
// stop-recursion
template<>
constexpr uint32_t Crc32<size_t(-1)>(const char* /*str*/)
{
return 0xFFFFFFFF;
}
} // namespace detail
//--------------------------------------------------------------------------
// use COMPILATION TIME CRC32 as a hash function
template<size_t len>
constexpr uint32_t Hash(const char (&str)[len])
{
return (detail::Crc32<len - 2>(str)) ^ 0xFFFFFFFF;
}
//--------------------------------------------------------------------------
// std::string hasher for convenience
uint32_t Hash(const std::string& str);
// in window
// warning C4717: 'G4::hashing::crc32::crc32_hasher<G4String>::operator()':
// recursive on all control paths, function will cause runtime stack overflow
/*
template <typename T>
struct crc32_hasher
{
template <size_t len>
uint32_t constexpr operator()(const char (&str)[len]) const
{
return hash(str);
}
uint32_t operator()(T str) const { return hash(str); }
};
template <typename T>
uint32_t constexpr hash(T&& t)
{
return crc32_hasher<typename std::decay<T>::type>()(std::forward<T>(t));
}
*/
} // namespace crc32
//--------------------------------------------------------------------------
// fnv ALGO
//--------------------------------------------------------------------------
namespace fnv
{
// Fowler / Noll / Vo (fnv) Hash - 1a
// magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/
#define fnv_offset_basis 0xcbf29ce484222325U
#define fnv_prime 0x100000001b3U // 64 bits
// 224 + 28 + 0x93
//------------------------------------------------------------------------
// Run time
size_t Hash(const std::string& str);
//--------------------------------------------------------------------------
// Details for compilation time
namespace detail
{
// recursion
template<int idx>
constexpr size_t Fnv(const char* str, size_t len, size_t hash)
{
return Fnv<idx - 1>(str, len, (hash ^ (str[len - idx])) * fnv_prime);
}
// stop-recursion
template<>
constexpr size_t Fnv<-1>(const char*, size_t, size_t hash)
{
return hash;
}
} // namespace detail
//------------------------------------------------------------------------
// COMPILATION TIME
template<size_t len>
constexpr size_t Hash(const char (&str)[len])
{
return detail::Fnv<len - 2>(str, len - 2, fnv_offset_basis);
}
//------------------------------------------------------------------------
template<class>
struct fnv_hasher;
template<typename T>
struct fnv_hasher
{
template<size_t len>
size_t constexpr operator()(const char (&str)[len]) const
{
return Hash(str);
}
size_t operator()(const T& str) const { return Hash(str); }
};
// template<>
// size_t fnv_hasher<std::string>::operator()(const std::string& str)
// const{
// return hash(str.c_str());
// }
template<typename T>
size_t constexpr Hash(T&& t)
{
return fnv_hasher<typename std::decay<T>::type>()(std::forward<T>(t));
}
} // namespace fnv
//--------------------------------------------------------------------------
// LARSON
//--------------------------------------------------------------------------
namespace larson
{
//------------------------------------------------------------------------
// Details for compilation time
namespace detail
{
// recursion
template<int idx>
constexpr size_t Larson(const char* str, size_t len, size_t hash)
{
return Larson<idx - 1>(str, len + 1, hash * 101 + str[len]);
}
// stop-recursion
template<>
constexpr size_t Larson<-1>(const char*, size_t, size_t hash)
{
return hash;
}
} // namespace detail
//------------------------------------------------------------------------
// COMPILATION TIME
template<size_t len>
constexpr size_t Cthash(const char (&str)[len], unsigned int seed = 0)
{
return detail::Larson<len - 2>(str, 0, seed);
}
//------------------------------------------------------------------------
// RUN TIME
size_t Hash(const char* str, unsigned int seed = 0);
size_t Hash(std::string str, unsigned int seed = 0);
} // namespace larson
//--------------------------------------------------------------------------
// DEFAULT STRING HASHER
//--------------------------------------------------------------------------
template<typename T>
struct hasher
{
std::size_t constexpr operator()(char const* input) const
{
return *input ? static_cast<std::size_t>(*input) + 33 * (*this)(input + 1) : 5381;
}
std::size_t operator()(const std::string& str) const { return (*this)(str.c_str()); }
};
template<typename T>
std::size_t constexpr Hash(T&& t)
{
return hasher<typename std::decay<T>::type>()(std::forward<T>(t));
}
// not necessary
template<>
std::size_t constexpr Hash<const char*>(const char*&& str)
{
return hasher<std::string>()(str);
}
inline namespace literals
{
std::size_t constexpr operator""_hash(const char* s, size_t)
{
return hasher<std::string>()(s);
}
} // namespace literals
} // namespace G4::hashing
using namespace G4::hashing::literals;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif