Skip to content

Commit f0d236a

Browse files
committed
Merge branch 'feature/DeBoostify'
2 parents 16f54ea + dce3e8f commit f0d236a

32 files changed

+3199
-1921
lines changed

.github/workflows/ci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- feature/DeBoostify
7+
pull_request:
8+
branches:
9+
- feature/DeBoostify
10+
11+
jobs:
12+
build-and-test:
13+
name: Build and Test on ${{ matrix.os }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
matrix:
17+
os: [ubuntu-latest, macos-latest, windows-latest]
18+
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v2
22+
23+
- name: Set up CMake
24+
uses: jwlawson/[email protected]
25+
with:
26+
cmake-version: '3.25'
27+
28+
- name: Set up dependencies
29+
if: runner.os == 'Linux'
30+
run: sudo apt-get update && sudo apt-get install -y build-essential
31+
32+
- name: Set up dependencies
33+
if: runner.os == 'macOS'
34+
#run: brew install cmake
35+
36+
#- name: Set up dependencies
37+
#if: runner.os == 'Windows'
38+
#run: choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
39+
40+
- name: Create build directory
41+
run: mkdir build
42+
43+
- name: Configure CMake
44+
run: cmake -S $GITHUB_WORKSPACE -B build -DSpecUtils_BUILD_UNIT_TESTS=ON -DSpecUtils_BUILD_REGRESSION_TEST=ON -DSpecUtils_ENABLE_EQUALITY_CHECKS=ON -DPERFORM_DEVELOPER_CHECKS=OFF -DSpecUtils_ENABLE_D3_CHART=ON -DSpecUtils_D3_SUPPORT_FILE_STATIC=ON -DSpecUtils_ENABLE_URI_SPECTRA=OFF
45+
46+
- name: Build
47+
run: cmake --build build --config Release
48+
49+
- name: Run tests
50+
run: ctest --test-dir build -C Release
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Boost Software License - Version 1.0 - August 17th, 2003
2+
3+
Permission is hereby granted, free of charge, to any person or organization
4+
obtaining a copy of the software and accompanying documentation covered by
5+
this license (the "Software") to use, reproduce, display, distribute,
6+
execute, and transmit the Software, and to prepare derivative works of the
7+
Software, and to permit third-parties to whom the Software is furnished to
8+
do so, all subject to the following:
9+
10+
The copyright notices in the Software and this entire statement, including
11+
the above license grant, this restriction and the following disclaimer,
12+
must be included in all copies of the Software, in whole or in part, and
13+
all derivative works of the Software, unless such copies or derivative
14+
works are solely in the form of machine-executable object code generated by
15+
a source language processor.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20+
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21+
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23+
DEALINGS IN THE SOFTWARE.
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/**
2+
* This file contains code extracted from boost 1.78, by wcjohns 20240809.
3+
*
4+
* It is the minimal amount of the boost hash implementation that we need to
5+
* hash a SpecFile to generate a UUID based on spectrum file contents.
6+
* We use `boost::hash` because `std::hash` is not guaranteed to be stable
7+
* across executions of the same executable.
8+
*
9+
* Installing boost, particularly on Windows, for just this functionality
10+
* has proven to be a burden for developers, so this code was extracted
11+
* to be stand-alone.
12+
*
13+
* Some function signatures have been changed to support this extraction
14+
* of a small amount of the code - this is not the complete implementation
15+
* of `boost::hash`, just what we use in SpecUtils. The actual computation
16+
* code is left unchanged, and it was checked for a number of spectrum
17+
* files that this code produced the same answer as boost proper.
18+
*/
19+
20+
// wcjohns: original notice from the top of `boost/container_hash/hash.hpp`:
21+
//
22+
// Copyright 2005-2014 Daniel James.
23+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
24+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
25+
26+
// Based on Peter Dimov's proposal
27+
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
28+
// issue 6.18.
29+
//
30+
// This also contains public domain code from MurmurHash. From the
31+
// MurmurHash header:
32+
33+
// MurmurHash3 was written by Austin Appleby, and is placed in the public
34+
// domain. The author hereby disclaims copyright to this source code.
35+
36+
37+
#if !defined(SpecUtils_boost_hash_hpp)
38+
#define SpecUtils_boost_hash_hpp
39+
40+
#include <string>
41+
#include <vector>
42+
#include <cstdint>
43+
#include <climits>
44+
#include <type_traits>
45+
46+
namespace boost_hash
47+
{
48+
// Forward declaration
49+
template <class T>
50+
void hash_combine( std::size_t& seed, T const& v );
51+
52+
namespace hash_detail
53+
{
54+
template <typename T>
55+
typename std::enable_if<sizeof(T) == 8, std::size_t>::type
56+
hash_mix( T x )
57+
{
58+
std::uint64_t const m = (std::uint64_t(0xe9846af) << 32) + 0x9b1a615d;
59+
60+
x ^= x >> 32;
61+
x *= m;
62+
x ^= x >> 32;
63+
x *= m;
64+
x ^= x >> 28;
65+
66+
return x;
67+
}
68+
69+
template <typename T>
70+
typename std::enable_if<sizeof(T) == 4, std::size_t>::type
71+
hash_mix( T x )
72+
{
73+
std::uint32_t const m1 = 0x21f0aaad;
74+
std::uint32_t const m2 = 0x735a2d97;
75+
76+
x ^= x >> 16;
77+
x *= m1;
78+
x ^= x >> 15;
79+
x *= m2;
80+
x ^= x >> 15;
81+
82+
return x;
83+
}
84+
85+
template<class T,
86+
bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)),
87+
bool is_unsigned = std::is_unsigned<T>::value,
88+
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT,
89+
std::size_t type_bits = sizeof(T) * CHAR_BIT>
90+
struct hash_integral_impl;
91+
92+
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, false, is_unsigned, size_t_bits, type_bits>
93+
{
94+
static std::size_t fn( T v )
95+
{
96+
return static_cast<std::size_t>( v );
97+
}
98+
};
99+
100+
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, true, false, size_t_bits, type_bits>
101+
{
102+
static std::size_t fn( T v )
103+
{
104+
typedef typename std::make_unsigned<T>::type U;
105+
106+
if( v >= 0 )
107+
{
108+
return hash_integral_impl<U>::fn( static_cast<U>( v ) );
109+
}
110+
else
111+
{
112+
return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
113+
}
114+
}
115+
};
116+
117+
template<class T> struct hash_integral_impl<T, true, true, 32, 64>
118+
{
119+
static std::size_t fn( T v )
120+
{
121+
std::size_t seed = 0;
122+
123+
seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
124+
seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
125+
126+
return seed;
127+
}
128+
};
129+
130+
131+
// float
132+
template <typename T>
133+
typename std::enable_if<sizeof(T) == 4, std::size_t>::type
134+
hash_float_impl( T v )
135+
{
136+
std::uint32_t w;
137+
std::memcpy( &w, &v, sizeof( v ) );
138+
139+
return w;
140+
}
141+
142+
// double
143+
template <typename T>
144+
typename std::enable_if<sizeof(T) == 8, std::size_t>::type
145+
hash_float_impl( T v )
146+
{
147+
std::uint64_t w;
148+
std::memcpy( &w, &v, sizeof( v ) );
149+
150+
//return boost_hash::hash_value( w );
151+
return hash_detail::hash_integral_impl<std::uint64_t>::fn( w );
152+
}
153+
154+
155+
std::size_t hash_range( std::size_t seed, const char *first, const char *last )
156+
{
157+
std::size_t n = static_cast<std::size_t>( last - first );
158+
159+
for( ; n >= 4; first += 4, n -= 4 )
160+
{
161+
std::uint32_t w =
162+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
163+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
164+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
165+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[3] ) ) << 24;
166+
167+
hash_combine( seed, w );
168+
}
169+
170+
{
171+
std::uint32_t w = 0x01u;
172+
173+
switch( n )
174+
{
175+
case 1:
176+
177+
w =
178+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
179+
0x0100u;
180+
181+
break;
182+
183+
case 2:
184+
185+
w =
186+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
187+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
188+
0x010000u;
189+
190+
break;
191+
192+
case 3:
193+
194+
w =
195+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
196+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
197+
static_cast<std::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
198+
0x01000000u;
199+
200+
break;
201+
}
202+
203+
hash_combine( seed, w );
204+
}
205+
206+
return seed;
207+
}
208+
}//namespace hash_detail
209+
210+
// Hash floating point types (e.g., `float` and `double`)
211+
template <typename T>
212+
typename std::enable_if<std::is_floating_point<T>::value, std::size_t>::type
213+
hash_value( T v )
214+
{
215+
return boost_hash::hash_detail::hash_float_impl( v );
216+
}
217+
218+
// Hash integral types (e.g., `int` and `uint64_t`, etc)
219+
template <typename T>
220+
typename std::enable_if<std::is_integral<T>::value, std::size_t>::type
221+
hash_value( T v )
222+
{
223+
return hash_detail::hash_integral_impl<T>::fn( v );
224+
}
225+
226+
std::size_t hash_value( const std::string &v )
227+
{
228+
return boost_hash::hash_detail::hash_range( 0, v.data(), v.data() + v.size() );
229+
}
230+
231+
template <class T>
232+
std::size_t hash_value( const std::vector<T> &v )
233+
{
234+
std::size_t seed = 0;
235+
for( const T &val : v )
236+
hash_combine<T>(seed, val );
237+
238+
return seed;
239+
}
240+
241+
242+
template <class T>
243+
void hash_combine( std::size_t& seed, T const& v )
244+
{
245+
seed = boost_hash::hash_detail::hash_mix( seed + 0x9e3779b9 + boost_hash::hash_value( v ) );
246+
}
247+
}//namespace boost_hash
248+
249+
#endif //SpecUtils_boost_hash_hpp

0 commit comments

Comments
 (0)