Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
HPCAPPs
OpenFOAM-GPU-v2.0
Commits
55e5a777
Commit
55e5a777
authored
Oct 17, 2024
by
shunbo
Browse files
initial commit
parents
Changes
677
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2532 additions
and
0 deletions
+2532
-0
OpenFOAM-v2112/applications/test/HashTable4/Make/files
OpenFOAM-v2112/applications/test/HashTable4/Make/files
+3
-0
OpenFOAM-v2112/applications/test/HashTable4/Make/options
OpenFOAM-v2112/applications/test/HashTable4/Make/options
+2
-0
OpenFOAM-v2112/applications/test/HashTable4/Test-HashTable4.C
...FOAM-v2112/applications/test/HashTable4/Test-HashTable4.C
+314
-0
OpenFOAM-v2112/applications/test/Hashing1/HashFunction.H
OpenFOAM-v2112/applications/test/Hashing1/HashFunction.H
+224
-0
OpenFOAM-v2112/applications/test/Hashing1/Make/files
OpenFOAM-v2112/applications/test/Hashing1/Make/files
+3
-0
OpenFOAM-v2112/applications/test/Hashing1/Make/options
OpenFOAM-v2112/applications/test/Hashing1/Make/options
+3
-0
OpenFOAM-v2112/applications/test/Hashing1/Test-Hashing1.C
OpenFOAM-v2112/applications/test/Hashing1/Test-Hashing1.C
+163
-0
OpenFOAM-v2112/applications/test/Hashing2/Make/files
OpenFOAM-v2112/applications/test/Hashing2/Make/files
+3
-0
OpenFOAM-v2112/applications/test/Hashing2/Make/options
OpenFOAM-v2112/applications/test/Hashing2/Make/options
+3
-0
OpenFOAM-v2112/applications/test/Hashing2/Test-Hashing2.C
OpenFOAM-v2112/applications/test/Hashing2/Test-Hashing2.C
+343
-0
OpenFOAM-v2112/applications/test/Hashing2/hashingTests
OpenFOAM-v2112/applications/test/Hashing2/hashingTests
+101
-0
OpenFOAM-v2112/applications/test/HashingSpeed/Make/files
OpenFOAM-v2112/applications/test/HashingSpeed/Make/files
+3
-0
OpenFOAM-v2112/applications/test/HashingSpeed/Make/options
OpenFOAM-v2112/applications/test/HashingSpeed/Make/options
+3
-0
OpenFOAM-v2112/applications/test/HashingSpeed/Test-HashingSpeed.C
...-v2112/applications/test/HashingSpeed/Test-HashingSpeed.C
+1079
-0
OpenFOAM-v2112/applications/test/IFstream/Make/files
OpenFOAM-v2112/applications/test/IFstream/Make/files
+3
-0
OpenFOAM-v2112/applications/test/IFstream/Make/options
OpenFOAM-v2112/applications/test/IFstream/Make/options
+2
-0
OpenFOAM-v2112/applications/test/IFstream/Test-IFstream.C
OpenFOAM-v2112/applications/test/IFstream/Test-IFstream.C
+105
-0
OpenFOAM-v2112/applications/test/IListStream/Make/files
OpenFOAM-v2112/applications/test/IListStream/Make/files
+3
-0
OpenFOAM-v2112/applications/test/IListStream/Make/options
OpenFOAM-v2112/applications/test/IListStream/Make/options
+2
-0
OpenFOAM-v2112/applications/test/IListStream/Test-IListStream.C
...AM-v2112/applications/test/IListStream/Test-IListStream.C
+170
-0
No files found.
Too many changes to show.
To preserve performance only
677 of 677+
files are displayed.
Plain diff
Email patch
OpenFOAM-v2112/applications/test/HashTable4/Make/files
0 → 100644
View file @
55e5a777
Test-HashTable4.C
EXE = $(FOAM_USER_APPBIN)/Test-HashTable4
OpenFOAM-v2112/applications/test/HashTable4/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude */
/* EXE_LIBS = -lfiniteVolume */
OpenFOAM-v2112/applications/test/HashTable4/Test-HashTable4.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Test HashTable resizing
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "HashSet.H"
#include "HashTable.H"
#include "Map.H"
#include "cpuTime.H"
#include "memInfo.H"
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
// #undef ORDERED
// #define ORDERED
using
namespace
Foam
;
template
<
class
T
>
Ostream
&
printInfo
(
Ostream
&
os
,
const
HashTable
<
T
,
T
,
Hash
<
T
>>&
ht
)
{
os
<<
" (size "
<<
ht
.
size
()
<<
" capacity "
<<
ht
.
capacity
()
<<
") "
;
return
os
;
}
template
<
class
K
,
class
V
>
inline
void
insertElem
(
#ifdef ORDERED
std
::
set
<
K
>&
container
,
#else
std
::
unordered_set
<
K
,
Hash
<
K
>>&
container
,
#endif
K
k
,
V
v
)
{
container
.
insert
(
k
);
}
template
<
class
K
,
class
V
>
inline
void
insertElem
(
#ifdef ORDERED
std
::
map
<
K
,
V
>&
container
,
#else
std
::
unordered_map
<
K
,
V
,
Hash
<
K
>>&
container
,
#endif
K
k
,
V
v
)
{
container
.
insert
(
std
::
make_pair
(
k
,
v
));
}
template
<
class
K
,
class
V
>
inline
void
insertElem
(
HashSet
<
K
,
Hash
<
K
>>&
container
,
K
k
,
V
v
)
{
container
.
insert
(
k
);
}
template
<
class
K
,
class
V
>
inline
void
insertElem
(
HashTable
<
K
,
V
,
Hash
<
K
>>&
container
,
K
k
,
V
v
)
{
container
.
insert
(
k
,
v
);
}
template
<
class
Container
>
inline
void
loopInsert
(
Container
&
container
,
const
label
n
)
{
for
(
label
i
=
0
;
i
<
n
;
i
++
)
{
insertElem
(
container
,
i
,
i
);
}
}
template
<
class
Container
>
inline
unsigned
long
loopFind
(
const
Container
&
container
,
const
label
n
)
{
const
auto
endIter
=
container
.
end
();
unsigned
long
sum
=
0
;
for
(
label
i
=
0
;
i
<
n
;
i
++
)
{
if
(
container
.
find
(
i
)
!=
endIter
)
{
++
sum
;
}
}
return
sum
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
const
label
nLoops
=
200
;
const
label
nFind
=
10
;
const
label
nElem
=
1000000
;
argList
::
noBanner
();
argList
::
addBoolOption
(
"find"
,
"test find"
);
argList
::
addBoolOption
(
"set"
,
"test HashSet"
);
argList
::
addBoolOption
(
"std"
,
"std::unordered_map or std::unordered_set"
);
argList
args
(
argc
,
argv
);
const
bool
optFnd
=
args
.
found
(
"find"
);
const
bool
optSet
=
args
.
found
(
"set"
);
const
bool
optStd
=
args
.
found
(
"std"
);
cpuTime
timer
;
memInfo
mem
;
Info
<<
"insert "
<<
nElem
<<
" (int) elements"
;
if
(
optFnd
)
{
Info
<<
", then find "
<<
(
nFind
*
nLoops
)
<<
" times
\n
"
;
}
else
{
Info
<<
" repeated "
<<
nLoops
<<
" times "
<<
endl
;
}
if
(
false
)
{
// Verify that resizing around (0) doesn't fail
HashTable
<
label
,
label
,
Hash
<
label
>>
map
(
32
);
printInfo
(
Info
,
map
)
<<
endl
;
map
.
insert
(
10
,
1000
);
map
.
resize
(
0
);
printInfo
(
Info
,
map
)
<<
endl
;
map
.
resize
(
10
);
printInfo
(
Info
,
map
)
<<
endl
;
map
.
clear
();
printInfo
(
Info
,
map
)
<<
endl
;
map
.
resize
(
0
);
printInfo
(
Info
,
map
)
<<
endl
;
return
0
;
}
if
(
optStd
)
{
if
(
optFnd
)
{
#ifdef ORDERED
Info
<<
"using stl::set"
<<
endl
;
std
::
set
<
label
>
map
;
#else
Info
<<
"using stl::unordered_set"
<<
endl
;
std
::
unordered_set
<
label
,
Hash
<
label
>>
map
(
32
);
#endif
loopInsert
(
map
,
nElem
);
(
void
)
timer
.
cpuTimeIncrement
();
unsigned
long
sum
=
0
;
for
(
label
loopi
=
0
;
loopi
<
nFind
*
nLoops
;
++
loopi
)
{
sum
+=
loopFind
(
map
,
nElem
);
}
// check result (suppress compiler optimizations?)
if
(
sum
==
0
)
{
Info
<<
"sum=0
\n
"
;
}
}
else
if
(
optSet
)
{
#ifdef ORDERED
Info
<<
"using stl::set"
<<
endl
;
#else
Info
<<
"using stl::unordered_set"
<<
endl
;
#endif
for
(
label
loopi
=
0
;
loopi
<
nLoops
;
++
loopi
)
{
#ifdef ORDERED
std
::
set
<
label
>
map
;
#else
std
::
unordered_set
<
label
,
Hash
<
label
>>
map
(
32
);
#endif
loopInsert
(
map
,
nElem
);
}
}
else
{
#ifdef ORDERED
Info
<<
"using stl::map"
<<
endl
;
#else
Info
<<
"using stl::unordered_map"
<<
endl
;
#endif
for
(
label
loopi
=
0
;
loopi
<
nLoops
;
++
loopi
)
{
#ifdef ORDERED
std
::
map
<
label
,
label
>
map
;
#else
std
::
unordered_map
<
label
,
label
,
Hash
<
label
>>
map
(
32
);
#endif
loopInsert
(
map
,
nElem
);
}
}
}
else
{
if
(
optFnd
)
{
Info
<<
"using HashSet"
<<
endl
;
HashSet
<
label
,
Hash
<
label
>>
map
(
32
);
loopInsert
(
map
,
nElem
);
(
void
)
timer
.
cpuTimeIncrement
();
unsigned
long
sum
=
0
;
for
(
label
loopi
=
0
;
loopi
<
nFind
*
nLoops
;
++
loopi
)
{
sum
+=
loopFind
(
map
,
nElem
);
}
// check result (suppress compiler optimizations?)
if
(
sum
==
0
)
{
Info
<<
"sum=0
\n
"
;
}
}
else
if
(
optSet
)
{
Info
<<
"using HashSet"
<<
endl
;
for
(
label
loopi
=
0
;
loopi
<
nLoops
;
++
loopi
)
{
HashSet
<
label
,
Hash
<
label
>>
map
(
32
);
loopInsert
(
map
,
nElem
);
}
}
else
{
Info
<<
"using HashTable"
<<
endl
;
for
(
label
loopi
=
0
;
loopi
<
nLoops
;
++
loopi
)
{
HashTable
<
label
,
label
,
Hash
<
label
>>
map
(
32
);
loopInsert
(
map
,
nElem
);
}
}
}
Info
<<
timer
.
cpuTimeIncrement
()
<<
" s
\n
"
;
Info
<<
"mem info: "
<<
mem
.
update
()
<<
endl
;
return
0
;
}
// ************************************************************************* //
OpenFOAM-v2112/applications/test/Hashing1/HashFunction.H
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::HashFunction
Description
Hash function class.
Verify that template overloads are properly resolved
Note
The second template parameter (bool) is used for SFINAE overloading,
\*---------------------------------------------------------------------------*/
#ifndef HashFunction_H
#define HashFunction_H
#include "Hash.H"
#ifdef FULLDEBUG
#define HashTypeInfo(Args) void info() { std::cerr<< "" Args << "\n"; }
#else
#define HashTypeInfo(Args) void info() {}
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace
Foam
{
/*---------------------------------------------------------------------------*\
Class Hash Declaration
\*---------------------------------------------------------------------------*/
template
<
class
T
,
class
SFINAEType
=
bool
>
struct
HashFun
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"default"
;
}
#endif
HashTypeInfo
(
"plain hash"
)
unsigned
operator
()(
const
T
&
obj
,
unsigned
seed
=
0
)
const
{
return
Foam
::
Hasher
(
&
obj
,
sizeof
(
obj
),
seed
);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Hashing for label
template
<
>
struct
HashFun
<
Foam
::
label
>
:
Hash
<
label
>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"label"
;
}
#endif
HashTypeInfo
(
"hash label"
)
};
//- Hashing for pointers, interpret pointer as a integer type
template
<
>
struct
HashFun
<
void
*>
:
Hash
<
void
*>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"pointer"
;
}
#endif
HashTypeInfo
(
"hash ptr"
)
};
//- Hashing for string types
template
<
class
StringType
>
struct
HashFun
<
StringType
,
typename
std
::
enable_if
<
std
::
is_base_of
<
std
::
string
,
StringType
>::
value
,
bool
>::
type
>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"string"
;
}
#endif
HashTypeInfo
(
"hash string"
)
unsigned
operator
()(
const
std
::
string
&
obj
,
unsigned
seed
=
0
)
const
{
return
Foam
::
Hasher
(
obj
.
data
(),
obj
.
size
(),
seed
);
}
};
}
// End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Various
#include "edge.H"
#include "face.H"
#include "triFace.H"
#include "Pair.H"
#include "Tuple2.H"
#include "DynamicList.H"
#include "FixedList.H"
namespace
Foam
{
template
<
>
struct
HashFun
<
edge
>
:
Hash
<
edge
>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"edge"
;
}
#endif
HashTypeInfo
(
"hash edge"
)
};
template
<
>
struct
HashFun
<
face
>
:
Hash
<
face
>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"face"
;
}
#endif
HashTypeInfo
(
"hash face"
)
};
template
<
>
struct
HashFun
<
triFace
>
:
Hash
<
triFace
>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"triFace"
;
}
#endif
HashTypeInfo
(
"hash triFace"
)
};
template
<
class
T
>
struct
HashFun
<
Pair
<
T
>>
:
Hash
<
Pair
<
T
>>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"Pair"
;
}
#endif
HashTypeInfo
(
"hash Pair"
)
};
template
<
class
T1
,
class
T2
>
struct
HashFun
<
Tuple2
<
T1
,
T2
>>
:
Hash
<
Tuple2
<
T1
,
T2
>>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"Tuple2"
;
}
#endif
HashTypeInfo
(
"hash Tuple2"
)
};
template
<
class
T
>
struct
HashFun
<
List
<
T
>>
:
Hash
<
List
<
T
>>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"List"
;
}
#endif
HashTypeInfo
(
"hash List"
)
};
template
<
class
T
>
struct
HashFun
<
UList
<
T
>>
:
Hash
<
UList
<
T
>>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"UList"
;
}
#endif
HashTypeInfo
(
"hash UList"
)
};
template
<
class
T
,
int
SizeMin
>
struct
HashFun
<
DynamicList
<
T
,
SizeMin
>>
:
Hash
<
DynamicList
<
T
,
SizeMin
>>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"DynamicList"
;
}
#endif
HashTypeInfo
(
"hash DynamicList"
)
};
template
<
class
T
,
unsigned
N
>
struct
HashFun
<
FixedList
<
T
,
N
>>
:
Hash
<
FixedList
<
T
,
N
>>
{
#ifdef FULLDEBUG
static
constexpr
const
char
*
name
()
noexcept
{
return
"FixedList"
;
}
#endif
HashTypeInfo
(
"hash FixedList"
)
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
}
// End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
OpenFOAM-v2112/applications/test/Hashing1/Make/files
0 → 100644
View file @
55e5a777
Test-Hashing1.C
EXE = $(FOAM_USER_APPBIN)/Test-Hashing1
OpenFOAM-v2112/applications/test/Hashing1/Make/options
0 → 100644
View file @
55e5a777
EXE_INC = ${c++LESSWARN}
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/Hashing1/Test-Hashing1.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-Hashing1
Description
Test/verify overloads of Hash function
\*---------------------------------------------------------------------------*/
#include "IOstreams.H"
#include "IOobject.H"
#include "IFstream.H"
#include "stringList.H"
#include "labelList.H"
#include "labelPair.H"
#include "wordPair.H"
#include "edgeList.H"
#include "faceList.H"
#include "triFaceList.H"
#define FULLDEBUG
#include "HashFunction.H"
using
namespace
Foam
;
template
<
class
T
>
unsigned
rawHasher
(
const
T
&
obj
)
{
return
Foam
::
Hasher
(
&
obj
,
sizeof
(
T
),
0u
);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
{
typedef
unsigned
Type
;
Type
value
=
100
;
Info
<<
"hash "
<<
typeid
(
value
).
name
()
<<
" of "
<<
value
<<
nl
;
Info
<<
" Hasher: "
<<
rawHasher
(
value
)
<<
nl
;
Info
<<
" Hash<>: "
<<
Hash
<
Type
>
()(
value
)
<<
nl
;
}
{
typedef
int32_t
Type
;
Type
value
=
100
;
Info
<<
"hash "
<<
typeid
(
value
).
name
()
<<
" of "
<<
value
<<
nl
;
Info
<<
" Hasher: "
<<
rawHasher
(
value
)
<<
nl
;
Info
<<
" Hash<>: "
<<
Hash
<
Type
>
()(
value
)
<<
nl
;
}
{
typedef
int64_t
Type
;
Type
value
=
100
;
Info
<<
"hash "
<<
typeid
(
value
).
name
()
<<
" of "
<<
value
<<
nl
;
Info
<<
" Hasher: "
<<
rawHasher
(
value
)
<<
nl
;
Info
<<
" Hash<>: "
<<
Hash
<
Type
>
()(
value
)
<<
nl
;
}
HashFun
<
std
::
string
>
().
info
();
HashFun
<
string
>
().
info
();
HashFun
<
Foam
::
word
>
().
info
();
HashFun
<
Foam
::
keyType
>
().
info
();
HashFun
<
int
>
().
info
();
HashFun
<
label
>
().
info
();
HashFun
<
float
>
().
info
();
HashFun
<
double
>
().
info
();
{
float
value
=
15
.
f
;
Info
<<
"hash of "
<<
Foam
::
name
(
&
value
)
<<
" = "
<<
HashFun
<
void
*>
()(
&
value
)
<<
nl
;
}
HashFun
<
labelList
>
().
info
();
HashFun
<
wordUList
>
().
info
();
HashFun
<
edge
>
().
info
();
HashFun
<
Pair
<
label
>>
().
info
();
HashFun
<
labelPair
>
().
info
();
HashFun
<
labelPairPair
>
().
info
();
HashFun
<
Tuple2
<
label
,
word
>>
().
info
();
{
typedef
Tuple2
<
label
,
word
>
Type
;
Type
obj
(
10
,
"test"
);
Info
<<
obj
<<
" hash="
<<
Hash
<
Type
>
()(
obj
)
<<
nl
;
}
{
typedef
Tuple2
<
label
,
label
>
Type
;
Type
obj
(
10
,
12
);
Info
<<
obj
<<
" hash="
<<
Hash
<
Type
>
()(
obj
)
<<
nl
;
}
{
typedef
Pair
<
label
>
Type
;
Type
obj
(
10
,
12
);
Info
<<
obj
<<
" hash="
<<
Hash
<
Type
>
()(
obj
)
<<
nl
;
}
{
typedef
std
::
pair
<
label
,
label
>
Type
;
Type
obj
(
10
,
12
);
Info
<<
obj
<<
" hash="
<<
Hash
<
Type
>
()(
obj
)
<<
nl
;
HashSet
<
Type
>
hs
;
hs
.
insert
(
obj
);
hs
.
erase
(
obj
);
}
{
Pair
<
label
>::
hasher
op
;
Info
<<
"hasher: "
<<
op
(
Pair
<
label
>
(
10
,
12
))
<<
nl
;
}
// Not supported
#if 0
{
Tuple2<label, label>::hasher op;
Info<< "hasher: " << op(Tuple2<label>(10, 12)) << nl;
}
#endif
Info
<<
"
\n
End
\n
"
<<
nl
;
return
0
;
}
// ************************************************************************* //
OpenFOAM-v2112/applications/test/Hashing2/Make/files
0 → 100644
View file @
55e5a777
Test-Hashing2.C
EXE = $(FOAM_USER_APPBIN)/Test-Hashing2
OpenFOAM-v2112/applications/test/Hashing2/Make/options
0 → 100644
View file @
55e5a777
EXE_INC = ${c++LESSWARN}
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/Hashing2/Test-Hashing2.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-Hashing2
Description
\*---------------------------------------------------------------------------*/
#include "IOstreams.H"
#include "IOobject.H"
#include "IFstream.H"
#include "stringList.H"
#include "labelList.H"
#include "labelPair.H"
#include "wordPair.H"
#include "edgeList.H"
#include "faceList.H"
#include "triFaceList.H"
#include "Hash.H"
#include "HashSet.H"
using
namespace
Foam
;
void
infoHashString
(
unsigned
modulus
,
std
::
initializer_list
<
std
::
string
>
lst
)
{
if
(
modulus
)
{
Info
<<
"basic string hashing (mod "
<<
label
(
modulus
)
<<
")"
<<
nl
;
for
(
const
auto
&
str
:
lst
)
{
Info
<<
"hash("
<<
str
.
c_str
()
<<
")="
<<
(
Hash
<
string
>
()(
str
)
%
modulus
)
<<
nl
;
}
}
else
{
Info
<<
"basic string hashing"
<<
nl
;
for
(
const
auto
&
str
:
lst
)
{
Info
<<
"hash("
<<
str
.
c_str
()
<<
")="
<<
Hash
<
string
>
()(
str
)
<<
nl
;
}
}
}
void
reportHashList
(
const
UList
<
string
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
string
>::
value
<<
nl
<<
nl
;
for
(
const
string
&
val
:
list
)
{
unsigned
hash1
=
string
::
hasher
()(
val
);
Info
<<
hex
<<
hash1
<<
": "
<<
val
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
label
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
label
>::
value
<<
nl
<<
nl
;
for
(
const
label
val
:
list
)
{
// Direct value
unsigned
hash1
=
Hash
<
label
>
()(
val
);
// Hashed byte-wise
unsigned
hash2
=
Hash
<
label
>
()(
val
,
0
);
Info
<<
hex
<<
hash1
<<
" (seeded: "
<<
hash2
<<
")"
<<
": "
<<
dec
<<
val
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
face
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
label
>::
value
<<
nl
<<
nl
;
for
(
const
face
&
f
:
list
)
{
// Direct value
unsigned
hash1
=
face
::
hasher
()(
f
);
unsigned
hash2
=
Hash
<
face
>
()(
f
);
Info
<<
hex
<<
"face hash "
<<
hash1
<<
" Hash<face> "
<<
hash2
<<
": "
<<
dec
<<
flatOutput
(
f
)
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
labelList
>&
list
)
{
for
(
const
labelList
&
val
:
list
)
{
unsigned
hash1
=
Foam
::
Hasher
(
val
.
cdata
(),
val
.
size_bytes
());
unsigned
hash2
=
Hash
<
labelList
>
()(
val
);
unsigned
hash2b
=
labelList
::
hasher
()(
val
);
Info
<<
hex
<<
hash1
<<
" or "
<<
hash2
<<
"("
<<
hash2b
<<
") "
<<
": "
<<
dec
<<
val
<<
nl
;
}
unsigned
hash2
=
Hash
<
labelListList
>
()(
list
);
unsigned
hash2bad
=
Foam
::
Hasher
(
&
list
,
sizeof
(
list
));
Info
<<
hex
<<
hash2
<<
" : "
<<
dec
<<
flatOutput
(
list
)
<<
nl
<<
hex
<<
hash2bad
<<
" as direct hash would be wrong"
<<
dec
<<
nl
;
}
void
reportHashList
(
const
UList
<
wordPair
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
wordPair
>::
value
<<
nl
<<
nl
;
for
(
const
wordPair
&
pr
:
list
)
{
unsigned
hash1
=
Hash
<
wordPair
>
()(
pr
);
// as FixedList
unsigned
hash2
=
wordPair
::
hasher
()(
pr
);
// as FixedList
unsigned
hash2sym
=
wordPair
::
symmHasher
()(
pr
);
// as FixedList
unsigned
hash3
=
Hash
<
FixedList
<
word
,
2
>>
()(
pr
);
Info
<<
hex
<<
hash1
<<
" (as FixedList: "
<<
hash2
<<
") or "
<<
hash3
<<
" symm-hash:"
<<
hash2sym
<<
" : "
<<
dec
<<
flatOutput
(
pr
)
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
labelPair
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
labelPair
>::
value
<<
nl
<<
nl
;
for
(
const
labelPair
&
pr
:
list
)
{
unsigned
hash1
=
Hash
<
labelPair
>
()(
pr
);
// as FixedList
unsigned
hash2
=
labelPair
::
hasher
()(
pr
);
// as FixedList
unsigned
hash3
=
Hash
<
labelPair
>
()(
pr
);
Info
<<
hex
<<
hash1
<<
" (as FixedList: "
<<
hash2
<<
") or "
<<
hash3
<<
" : "
<<
dec
<<
pr
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
labelPairPair
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
labelPairPair
>::
value
<<
nl
<<
nl
;
for
(
const
labelPairPair
&
pr
:
list
)
{
unsigned
hash1
=
Hash
<
labelPairPair
>
()(
pr
);
// as FixedList
unsigned
hash2
=
labelPairPair
::
hasher
()(
pr
);
// as FixedList
unsigned
hash3
=
Hash
<
labelPairPair
>
()(
pr
);
Info
<<
hex
<<
hash1
<<
" (as FixedList: "
<<
hash2
<<
") or "
<<
hash3
<<
" : "
<<
dec
<<
pr
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
edge
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
edge
>::
value
<<
nl
<<
nl
;
for
(
const
edge
&
e
:
list
)
{
unsigned
hash1
=
Hash
<
edge
>
()(
e
);
// as FixedList
unsigned
hash2
=
labelPair
::
hasher
()(
e
);
// as FixedList
unsigned
hash3
=
Hash
<
labelPair
>
()(
e
);
Info
<<
hex
<<
hash1
<<
" (as FixedList: "
<<
hash2
<<
") or "
<<
hash3
<<
" : "
<<
dec
<<
e
<<
nl
;
}
}
void
reportHashList
(
const
UList
<
triFace
>&
list
)
{
Info
<<
"contiguous = "
<<
is_contiguous
<
triFace
>::
value
<<
nl
<<
nl
;
for
(
const
triFace
&
f
:
list
)
{
// direct value
unsigned
hash1
=
Hash
<
triFace
>
()(
f
);
unsigned
hash2
=
FixedList
<
label
,
3
>::
hasher
()(
f
);
Info
<<
hex
<<
hash1
<<
" (as FixedList: "
<<
hash2
<<
"): "
<<
dec
<<
f
<<
nl
;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
infoHashString
(
8
,
{
"asdathis1"
,
"adsxf"
,
"hij"
,
"klmpq"
});
IFstream
is
(
"hashingTests"
);
if
(
is
.
good
())
{
Info
<<
nl
<<
"Process "
<<
is
.
name
()
<<
" file ..."
<<
nl
;
}
else
{
Info
<<
nl
<<
"No "
<<
is
.
name
()
<<
" file found ..."
<<
nl
;
}
token
tok
;
while
(
is
.
good
()
&&
is
.
read
(
tok
)
&&
tok
.
good
())
{
const
word
listType
(
tok
.
wordToken
());
Info
<<
nl
;
IOobject
::
writeDivider
(
Info
)
<<
listType
<<
nl
;
if
(
listType
==
"stringList"
)
{
stringList
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"labelList"
)
{
labelList
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"faceList"
)
{
faceList
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"labelListList"
)
{
List
<
labelList
>
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"wordPairList"
)
{
List
<
wordPair
>
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"labelPairList"
)
{
labelPairList
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"labelPairPairList"
)
{
List
<
labelPairPair
>
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"edgeList"
)
{
edgeList
list
(
is
);
reportHashList
(
list
);
}
else
if
(
listType
==
"triFaceList"
)
{
triFaceList
list
(
is
);
reportHashList
(
list
);
}
else
{
Info
<<
"unknown type: "
<<
listType
<<
nl
;
}
}
Info
<<
"
\n
End
\n
"
<<
nl
;
return
0
;
}
// ************************************************************************* //
OpenFOAM-v2112/applications/test/Hashing2/hashingTests
0 → 100644
View file @
55e5a777
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2112 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
stringList
(
"The quick brown fox jumps over the lazy dog"
"The best hash is the one you don't write yourself!"
)
labelList
(
0
1
100
1000
-1
-10
-100
100
)
labelListList
(
(0)
(0 0)
(0 0 0)
(0 1)
(100 1000)
(0 1 100 1000)
(100 1000)
)
faceList
(
(0 1 2 3 4 5)
(5 4 3 1 2 0)
(0 1 2 3 4 5)
(100 0 15)
(15 0 100)
)
// edges are hashed commutatively
edgeList
(
(0 1)
(1 0)
(45 100)
(100 45)
(128 1000)
(1000 128)
(100 45)
)
// triFaces are also hashed commutatively (via multiply/add)
triFaceList
(
(10 20 30)
(30 20 10)
(20 10 30)
)
labelPairList
(
(0 1)
(1 0)
(45 100)
(100 45)
(128 1000)
(1000 128)
(100 45)
)
labelPairPairList
(
((0 1) (1 0))
((45 100) (100 45))
((128 1000) (1000 128))
((45 100) (100 45))
)
wordPairList
(
("Yes" "No")
("True" "False")
("No" "Yes")
("False" "True")
)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
OpenFOAM-v2112/applications/test/HashingSpeed/Make/files
0 → 100644
View file @
55e5a777
Test-HashingSpeed.C
EXE = $(FOAM_USER_APPBIN)/Test-HashingSpeed
OpenFOAM-v2112/applications/test/HashingSpeed/Make/options
0 → 100644
View file @
55e5a777
EXE_INC = ${c++LESSWARN}
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/HashingSpeed/Test-HashingSpeed.C
0 → 100644
View file @
55e5a777
// code taken more-or-less from Paul Hsieh's tests
#include "Hasher.H"
#include "int.H"
#include <cstdio>
#include <ctime>
#ifndef CLOCKS_PER_SEC
#ifdef CLK_TCK
#define CLOCKS_PER_SEC (CLK_TCK)
#endif
#endif
#undef mix
#undef rot
/*
-------------------------------------------------------------------------------
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
These are functions for producing 32-bit hashes for hash table lookup.
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
are externally useful functions. Routines to test the hash are included
if SELF_TEST is defined. You can use this free for any purpose. It's in
the public domain. It has no warranty.
You probably want to use hashlittle(). hashlittle() and hashbig()
hash byte arrays. hashlittle() is is faster than hashbig() on
little-endian machines. Intel and AMD are little-endian machines.
On second thought, you probably want hashlittle2(), which is identical to
hashlittle() except it returns two 32-bit hashes for the price of one.
You could implement hashbig2() if you wanted but I haven't bothered here.
If you want to find a hash of, say, exactly 7 integers, do
a = i1; b = i2; c = i3;
mix(a,b,c);
a += i4; b += i5; c += i6;
mix(a,b,c);
a += i7;
final(a,b,c);
then use c as the hash value. If you have a variable length array of
4-byte integers to hash, use hashword(). If you have a byte array (like
a character string), use hashlittle(). If you have several byte arrays, or
a mix of things, see the comments above hashlittle().
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
then mix those integers. This is fast (you can do a lot more thorough
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
-------------------------------------------------------------------------------
*/
#include <stdio.h>
/* defines printf for tests */
#include <time.h>
/* defines time_t for timings in the test */
#include <sys/param.h>
/* attempt to define endianness */
#ifdef linux
#include <endian.h>
/* attempt to define endianness */
#endif
/*
* My best guess at if you are big-endian or little-endian. This may
* need adjustment.
*/
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
#define HASH_LITTLE_ENDIAN 1
#define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
#define HASH_LITTLE_ENDIAN 0
#define HASH_BIG_ENDIAN 1
#else
#define HASH_LITTLE_ENDIAN 0
#define HASH_BIG_ENDIAN 0
#endif
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
/*
-------------------------------------------------------------------------------
mix -- mix 3 32-bit values reversibly.
This is reversible, so any information in (a,b,c) before mix() is
still in (a,b,c) after mix().
If four pairs of (a,b,c) inputs are run through mix(), or through
mix() in reverse, there are at least 32 bits of the output that
are sometimes the same for one pair and different for another pair.
This was tested for:
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
satisfy this are
4 6 8 16 19 4
9 15 3 18 27 15
14 9 3 7 17 3
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
for "differ" defined as + with a one-bit base and a two-bit delta. I
used http://burtleburtle.net/bob/hash/avalanche.html to choose
the operations, constants, and arrangements of the variables.
This does not achieve avalanche. There are input bits of (a,b,c)
that fail to affect some output bits of (a,b,c), especially of a. The
most thoroughly mixed value is c, but it doesn't really even achieve
avalanche in c.
This allows some parallelism. Read-after-writes are good at doubling
the number of bits affected, so the goal of mixing pulls in the opposite
direction as the goal of parallelism. I did what I could. Rotates
seem to cost as much as shifts on every machine I could lay my hands
on, and rotates are much kinder to the top and bottom bits, so I used
rotates.
-------------------------------------------------------------------------------
*/
#define mix(a,b,c) \
{ \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}
/*
-------------------------------------------------------------------------------
final -- final mixing of 3 32-bit values (a,b,c) into c
Pairs of (a,b,c) values differing in only a few bits will usually
produce values of c that look totally different. This was tested for
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
These constants passed:
14 11 25 16 4 14 24
12 14 25 16 4 14 24
and these came close:
4 8 15 26 3 22 24
10 8 15 26 3 22 24
11 8 15 26 3 22 24
-------------------------------------------------------------------------------
*/
#define final(a,b,c) \
{ \
c ^= b; c -= rot(b, 14); \
a ^= c; a -= rot(c, 11); \
b ^= a; b -= rot(a, 25); \
c ^= b; c -= rot(b, 16); \
a ^= c; a -= rot(c, 4); \
b ^= a; b -= rot(a, 14); \
c ^= b; c -= rot(b, 24); \
}
/*
--------------------------------------------------------------------
This works on all machines. To be useful, it requires
-- that the key be an array of uint32_t's, and
-- that the length be the number of uint32_t's in the key
The function hashword() is identical to hashlittle() on little-endian
machines, and identical to hashbig() on big-endian machines,
except that the length has to be measured in uint32_ts rather than in
bytes. hashlittle() is more complicated than hashword() only because
hashlittle() has to dance around fitting the key bytes into registers.
--------------------------------------------------------------------
*/
uint32_t
hashword
(
const
uint32_t
*
k
,
/* the key, an array of uint32_t values */
size_t
length
,
/* the length of the key, in uint32_ts */
uint32_t
initval
)
/* the previous hash, or an arbitrary value */
{
uint32_t
a
,
b
,
c
;
/* Set up the internal state */
a
=
b
=
c
=
0xdeadbeef
+
(((
uint32_t
)
length
)
<<
2
)
+
initval
;
/*------------------------------------------------- handle most of the key */
while
(
length
>
3
)
{
a
+=
k
[
0
];
b
+=
k
[
1
];
c
+=
k
[
2
];
mix
(
a
,
b
,
c
);
length
-=
3
;
k
+=
3
;
}
/*------------------------------------------- handle the last 3 uint32_t's */
switch
(
length
)
/* all the case statements fall through */
{
case
3
:
c
+=
k
[
2
];
case
2
:
b
+=
k
[
1
];
case
1
:
a
+=
k
[
0
];
final
(
a
,
b
,
c
);
case
0
:
/* case 0: nothing left to add */
break
;
}
/*------------------------------------------------------ report the result */
return
c
;
}
/*
--------------------------------------------------------------------
hashword2() -- same as hashword(), but take two seeds and return two
32-bit values. pc and pb must both be nonnull, and *pc and *pb must
both be initialized with seeds. If you pass in (*pb)==0, the output
(*pc) will be the same as the return value from hashword().
--------------------------------------------------------------------
*/
void
hashword2
(
const
uint32_t
*
k
,
/* the key, an array of uint32_t values */
size_t
length
,
/* the length of the key, in uint32_ts */
uint32_t
*
pc
,
/* IN: seed OUT: primary hash value */
uint32_t
*
pb
)
/* IN: more seed OUT: secondary hash value */
{
uint32_t
a
,
b
,
c
;
/* Set up the internal state */
a
=
b
=
c
=
0xdeadbeef
+
((
uint32_t
)(
length
<<
2
))
+
*
pc
;
c
+=
*
pb
;
/*------------------------------------------------- handle most of the key */
while
(
length
>
3
)
{
a
+=
k
[
0
];
b
+=
k
[
1
];
c
+=
k
[
2
];
mix
(
a
,
b
,
c
);
length
-=
3
;
k
+=
3
;
}
/*------------------------------------------- handle the last 3 uint32_t's */
switch
(
length
)
/* all the case statements fall through */
{
case
3
:
c
+=
k
[
2
];
case
2
:
b
+=
k
[
1
];
case
1
:
a
+=
k
[
0
];
final
(
a
,
b
,
c
);
case
0
:
/* case 0: nothing left to add */
break
;
}
/*------------------------------------------------------ report the result */
*
pc
=
c
;
*
pb
=
b
;
}
/*
-------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value
k : the key (the unaligned variable-length array of bytes)
length : the length of the key, counting by bytes
initval : can be any 4-byte value
Returns a 32-bit value. Every bit of the key affects every bit of
the return value. Two keys differing by one or two bits will have
totally different hash values.
The best hash table sizes are powers of 2. There is no need to do
mod a prime (mod is sooo slow!). If you need less than 32 bits,
use a bitmask. For example, if you need only 10 bits, do
h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.
If you are hashing n strings (uint8_t **)k, do it like this:
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
code any way you wish, private, educational, or commercial. It's free.
Use for hash table lookup, or anything where one collision in 2^^32 is
acceptable. Do NOT use for cryptographic purposes.
-------------------------------------------------------------------------------
*/
uint32_t
hashlittle
(
const
void
*
key
,
size_t
length
,
uint32_t
initval
)
{
uint32_t
a
,
b
,
c
;
/* internal state */
union
{
const
void
*
ptr
;
size_t
i
;
}
u
;
/* needed for Mac Powerbook G4 */
/* Set up the internal state */
a
=
b
=
c
=
0xdeadbeef
+
((
uint32_t
)
length
)
+
initval
;
u
.
ptr
=
key
;
if
(
HASH_LITTLE_ENDIAN
&&
((
u
.
i
&
0x3
)
==
0
))
{
const
uint32_t
*
k
=
(
const
uint32_t
*
)
key
;
/* read 32-bit chunks */
const
uint8_t
*
k8
;
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while
(
length
>
12
)
{
a
+=
k
[
0
];
b
+=
k
[
1
];
c
+=
k
[
2
];
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
3
;
}
/*----------------------------- handle the last (probably partial) block */
k8
=
(
const
uint8_t
*
)
k
;
switch
(
length
)
{
case
12
:
c
+=
k
[
2
];
b
+=
k
[
1
];
a
+=
k
[
0
];
break
;
case
11
:
c
+=
((
uint32_t
)
k8
[
10
])
<<
16
;
/* fall through */
case
10
:
c
+=
((
uint32_t
)
k8
[
9
])
<<
8
;
/* fall through */
case
9
:
c
+=
k8
[
8
];
/* fall through */
case
8
:
b
+=
k
[
1
];
a
+=
k
[
0
];
break
;
case
7
:
b
+=
((
uint32_t
)
k8
[
6
])
<<
16
;
/* fall through */
case
6
:
b
+=
((
uint32_t
)
k8
[
5
])
<<
8
;
/* fall through */
case
5
:
b
+=
k8
[
4
];
/* fall through */
case
4
:
a
+=
k
[
0
];
break
;
case
3
:
a
+=
((
uint32_t
)
k8
[
2
])
<<
16
;
/* fall through */
case
2
:
a
+=
((
uint32_t
)
k8
[
1
])
<<
8
;
/* fall through */
case
1
:
a
+=
k8
[
0
];
break
;
case
0
:
return
c
;
}
}
else
if
(
HASH_LITTLE_ENDIAN
&&
((
u
.
i
&
0x1
)
==
0
))
{
const
uint16_t
*
k
=
(
const
uint16_t
*
)
key
;
/* read 16-bit chunks */
const
uint8_t
*
k8
;
/*--------------- all but last block: aligned reads and different mixing */
while
(
length
>
12
)
{
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
c
+=
k
[
4
]
+
(((
uint32_t
)
k
[
5
])
<<
16
);
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
6
;
}
/*----------------------------- handle the last (probably partial) block */
k8
=
(
const
uint8_t
*
)
k
;
switch
(
length
)
{
case
12
:
c
+=
k
[
4
]
+
(((
uint32_t
)
k
[
5
])
<<
16
);
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
11
:
c
+=
((
uint32_t
)
k8
[
10
])
<<
16
;
/* fall through */
case
10
:
c
+=
k
[
4
];
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
9
:
c
+=
k8
[
8
];
/* fall through */
case
8
:
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
7
:
b
+=
((
uint32_t
)
k8
[
6
])
<<
16
;
/* fall through */
case
6
:
b
+=
k
[
2
];
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
5
:
b
+=
k8
[
4
];
/* fall through */
case
4
:
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
3
:
a
+=
((
uint32_t
)
k8
[
2
])
<<
16
;
/* fall through */
case
2
:
a
+=
k
[
0
];
break
;
case
1
:
a
+=
k8
[
0
];
break
;
case
0
:
return
c
;
/* zero length requires no mixing */
}
}
else
{
/* need to read the key one byte at a time */
const
uint8_t
*
k
=
(
const
uint8_t
*
)
key
;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
while
(
length
>
12
)
{
a
+=
k
[
0
];
a
+=
((
uint32_t
)
k
[
1
])
<<
8
;
a
+=
((
uint32_t
)
k
[
2
])
<<
16
;
a
+=
((
uint32_t
)
k
[
3
])
<<
24
;
b
+=
k
[
4
];
b
+=
((
uint32_t
)
k
[
5
])
<<
8
;
b
+=
((
uint32_t
)
k
[
6
])
<<
16
;
b
+=
((
uint32_t
)
k
[
7
])
<<
24
;
c
+=
k
[
8
];
c
+=
((
uint32_t
)
k
[
9
])
<<
8
;
c
+=
((
uint32_t
)
k
[
10
])
<<
16
;
c
+=
((
uint32_t
)
k
[
11
])
<<
24
;
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
12
;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
switch
(
length
)
/* all the case statements fall through */
{
case
12
:
c
+=
((
uint32_t
)
k
[
11
])
<<
24
;
case
11
:
c
+=
((
uint32_t
)
k
[
10
])
<<
16
;
case
10
:
c
+=
((
uint32_t
)
k
[
9
])
<<
8
;
case
9
:
c
+=
k
[
8
];
case
8
:
b
+=
((
uint32_t
)
k
[
7
])
<<
24
;
case
7
:
b
+=
((
uint32_t
)
k
[
6
])
<<
16
;
case
6
:
b
+=
((
uint32_t
)
k
[
5
])
<<
8
;
case
5
:
b
+=
k
[
4
];
case
4
:
a
+=
((
uint32_t
)
k
[
3
])
<<
24
;
case
3
:
a
+=
((
uint32_t
)
k
[
2
])
<<
16
;
case
2
:
a
+=
((
uint32_t
)
k
[
1
])
<<
8
;
case
1
:
a
+=
k
[
0
];
break
;
case
0
:
return
c
;
}
}
final
(
a
,
b
,
c
);
return
c
;
}
/*
* hashlittle2: return 2 32-bit hash values
*
* This is identical to hashlittle(), except it returns two 32-bit hash
* values instead of just one. This is good enough for hash table
* lookup with 2^^64 buckets, or if you want a second hash if you're not
* happy with the first, or if you want a probably-unique 64-bit ID for
* the key. *pc is better mixed than *pb, so use *pc first. If you want
* a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
*/
void
hashlittle2
(
const
void
*
key
,
/* the key to hash */
size_t
length
,
/* length of the key */
uint32_t
*
pc
,
/* IN: primary initval, OUT: primary hash */
uint32_t
*
pb
)
/* IN: secondary initval, OUT: secondary hash */
{
uint32_t
a
,
b
,
c
;
/* internal state */
union
{
const
void
*
ptr
;
size_t
i
;
}
u
;
/* needed for Mac Powerbook G4 */
/* Set up the internal state */
a
=
b
=
c
=
0xdeadbeef
+
((
uint32_t
)
length
)
+
*
pc
;
c
+=
*
pb
;
u
.
ptr
=
key
;
if
(
HASH_LITTLE_ENDIAN
&&
((
u
.
i
&
0x3
)
==
0
))
{
const
uint32_t
*
k
=
(
const
uint32_t
*
)
key
;
/* read 32-bit chunks */
const
uint8_t
*
k8
;
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while
(
length
>
12
)
{
a
+=
k
[
0
];
b
+=
k
[
1
];
c
+=
k
[
2
];
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
3
;
}
/*----------------------------- handle the last (probably partial) block */
k8
=
(
const
uint8_t
*
)
k
;
switch
(
length
)
{
case
12
:
c
+=
k
[
2
];
b
+=
k
[
1
];
a
+=
k
[
0
];
break
;
case
11
:
c
+=
((
uint32_t
)
k8
[
10
])
<<
16
;
/* fall through */
case
10
:
c
+=
((
uint32_t
)
k8
[
9
])
<<
8
;
/* fall through */
case
9
:
c
+=
k8
[
8
];
/* fall through */
case
8
:
b
+=
k
[
1
];
a
+=
k
[
0
];
break
;
case
7
:
b
+=
((
uint32_t
)
k8
[
6
])
<<
16
;
/* fall through */
case
6
:
b
+=
((
uint32_t
)
k8
[
5
])
<<
8
;
/* fall through */
case
5
:
b
+=
k8
[
4
];
/* fall through */
case
4
:
a
+=
k
[
0
];
break
;
case
3
:
a
+=
((
uint32_t
)
k8
[
2
])
<<
16
;
/* fall through */
case
2
:
a
+=
((
uint32_t
)
k8
[
1
])
<<
8
;
/* fall through */
case
1
:
a
+=
k8
[
0
];
break
;
case
0
:
*
pc
=
c
;
*
pb
=
b
;
return
;
/* zero length strings require no mixing */
}
}
else
if
(
HASH_LITTLE_ENDIAN
&&
((
u
.
i
&
0x1
)
==
0
))
{
const
uint16_t
*
k
=
(
const
uint16_t
*
)
key
;
/* read 16-bit chunks */
const
uint8_t
*
k8
;
/*--------------- all but last block: aligned reads and different mixing */
while
(
length
>
12
)
{
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
c
+=
k
[
4
]
+
(((
uint32_t
)
k
[
5
])
<<
16
);
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
6
;
}
/*----------------------------- handle the last (probably partial) block */
k8
=
(
const
uint8_t
*
)
k
;
switch
(
length
)
{
case
12
:
c
+=
k
[
4
]
+
(((
uint32_t
)
k
[
5
])
<<
16
);
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
11
:
c
+=
((
uint32_t
)
k8
[
10
])
<<
16
;
/* fall through */
case
10
:
c
+=
k
[
4
];
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
9
:
c
+=
k8
[
8
];
/* fall through */
case
8
:
b
+=
k
[
2
]
+
(((
uint32_t
)
k
[
3
])
<<
16
);
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
7
:
b
+=
((
uint32_t
)
k8
[
6
])
<<
16
;
/* fall through */
case
6
:
b
+=
k
[
2
];
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
5
:
b
+=
k8
[
4
];
/* fall through */
case
4
:
a
+=
k
[
0
]
+
(((
uint32_t
)
k
[
1
])
<<
16
);
break
;
case
3
:
a
+=
((
uint32_t
)
k8
[
2
])
<<
16
;
/* fall through */
case
2
:
a
+=
k
[
0
];
break
;
case
1
:
a
+=
k8
[
0
];
break
;
case
0
:
*
pc
=
c
;
*
pb
=
b
;
return
;
/* zero length strings require no mixing */
}
}
else
{
/* need to read the key one byte at a time */
const
uint8_t
*
k
=
(
const
uint8_t
*
)
key
;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
while
(
length
>
12
)
{
a
+=
k
[
0
];
a
+=
((
uint32_t
)
k
[
1
])
<<
8
;
a
+=
((
uint32_t
)
k
[
2
])
<<
16
;
a
+=
((
uint32_t
)
k
[
3
])
<<
24
;
b
+=
k
[
4
];
b
+=
((
uint32_t
)
k
[
5
])
<<
8
;
b
+=
((
uint32_t
)
k
[
6
])
<<
16
;
b
+=
((
uint32_t
)
k
[
7
])
<<
24
;
c
+=
k
[
8
];
c
+=
((
uint32_t
)
k
[
9
])
<<
8
;
c
+=
((
uint32_t
)
k
[
10
])
<<
16
;
c
+=
((
uint32_t
)
k
[
11
])
<<
24
;
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
12
;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
switch
(
length
)
/* all the case statements fall through */
{
case
12
:
c
+=
((
uint32_t
)
k
[
11
])
<<
24
;
case
11
:
c
+=
((
uint32_t
)
k
[
10
])
<<
16
;
case
10
:
c
+=
((
uint32_t
)
k
[
9
])
<<
8
;
case
9
:
c
+=
k
[
8
];
case
8
:
b
+=
((
uint32_t
)
k
[
7
])
<<
24
;
case
7
:
b
+=
((
uint32_t
)
k
[
6
])
<<
16
;
case
6
:
b
+=
((
uint32_t
)
k
[
5
])
<<
8
;
case
5
:
b
+=
k
[
4
];
case
4
:
a
+=
((
uint32_t
)
k
[
3
])
<<
24
;
case
3
:
a
+=
((
uint32_t
)
k
[
2
])
<<
16
;
case
2
:
a
+=
((
uint32_t
)
k
[
1
])
<<
8
;
case
1
:
a
+=
k
[
0
];
break
;
case
0
:
*
pc
=
c
;
*
pb
=
b
;
return
;
/* zero length strings require no mixing */
}
}
final
(
a
,
b
,
c
);
*
pc
=
c
;
*
pb
=
b
;
}
/*
* hashbig():
* This is the same as hashword() on big-endian machines. It is different
* from hashlittle() on all machines. hashbig() takes advantage of
* big-endian byte ordering.
*/
uint32_t
hashbig
(
const
void
*
key
,
size_t
length
,
uint32_t
initval
)
{
uint32_t
a
,
b
,
c
;
union
{
const
void
*
ptr
;
size_t
i
;
}
u
;
/* to cast key to (size_t) happily */
/* Set up the internal state */
a
=
b
=
c
=
0xdeadbeef
+
((
uint32_t
)
length
)
+
initval
;
u
.
ptr
=
key
;
if
(
HASH_BIG_ENDIAN
&&
((
u
.
i
&
0x3
)
==
0
))
{
const
uint32_t
*
k
=
(
const
uint32_t
*
)
key
;
/* read 32-bit chunks */
const
uint8_t
*
k8
;
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while
(
length
>
12
)
{
a
+=
k
[
0
];
b
+=
k
[
1
];
c
+=
k
[
2
];
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
3
;
}
/*----------------------------- handle the last (probably partial) block */
k8
=
(
const
uint8_t
*
)
k
;
switch
(
length
)
/* all the case statements fall through */
{
case
12
:
c
+=
k
[
2
];
b
+=
k
[
1
];
a
+=
k
[
0
];
break
;
case
11
:
c
+=
((
uint32_t
)
k8
[
10
])
<<
8
;
/* fall through */
case
10
:
c
+=
((
uint32_t
)
k8
[
9
])
<<
16
;
/* fall through */
case
9
:
c
+=
((
uint32_t
)
k8
[
8
])
<<
24
;
/* fall through */
case
8
:
b
+=
k
[
1
];
a
+=
k
[
0
];
break
;
case
7
:
b
+=
((
uint32_t
)
k8
[
6
])
<<
8
;
/* fall through */
case
6
:
b
+=
((
uint32_t
)
k8
[
5
])
<<
16
;
/* fall through */
case
5
:
b
+=
((
uint32_t
)
k8
[
4
])
<<
24
;
/* fall through */
case
4
:
a
+=
k
[
0
];
break
;
case
3
:
a
+=
((
uint32_t
)
k8
[
2
])
<<
8
;
/* fall through */
case
2
:
a
+=
((
uint32_t
)
k8
[
1
])
<<
16
;
/* fall through */
case
1
:
a
+=
((
uint32_t
)
k8
[
0
])
<<
24
;
break
;
case
0
:
return
c
;
}
}
else
{
/* need to read the key one byte at a time */
const
uint8_t
*
k
=
(
const
uint8_t
*
)
key
;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
while
(
length
>
12
)
{
a
+=
((
uint32_t
)
k
[
0
])
<<
24
;
a
+=
((
uint32_t
)
k
[
1
])
<<
16
;
a
+=
((
uint32_t
)
k
[
2
])
<<
8
;
a
+=
((
uint32_t
)
k
[
3
]);
b
+=
((
uint32_t
)
k
[
4
])
<<
24
;
b
+=
((
uint32_t
)
k
[
5
])
<<
16
;
b
+=
((
uint32_t
)
k
[
6
])
<<
8
;
b
+=
((
uint32_t
)
k
[
7
]);
c
+=
((
uint32_t
)
k
[
8
])
<<
24
;
c
+=
((
uint32_t
)
k
[
9
])
<<
16
;
c
+=
((
uint32_t
)
k
[
10
])
<<
8
;
c
+=
((
uint32_t
)
k
[
11
]);
mix
(
a
,
b
,
c
);
length
-=
12
;
k
+=
12
;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
switch
(
length
)
/* all the case statements fall through */
{
case
12
:
c
+=
k
[
11
];
case
11
:
c
+=
((
uint32_t
)
k
[
10
])
<<
8
;
case
10
:
c
+=
((
uint32_t
)
k
[
9
])
<<
16
;
case
9
:
c
+=
((
uint32_t
)
k
[
8
])
<<
24
;
case
8
:
b
+=
k
[
7
];
case
7
:
b
+=
((
uint32_t
)
k
[
6
])
<<
8
;
case
6
:
b
+=
((
uint32_t
)
k
[
5
])
<<
16
;
case
5
:
b
+=
((
uint32_t
)
k
[
4
])
<<
24
;
case
4
:
a
+=
k
[
3
];
case
3
:
a
+=
((
uint32_t
)
k
[
2
])
<<
8
;
case
2
:
a
+=
((
uint32_t
)
k
[
1
])
<<
16
;
case
1
:
a
+=
((
uint32_t
)
k
[
0
])
<<
24
;
break
;
case
0
:
return
c
;
}
}
final
(
a
,
b
,
c
);
return
c
;
}
uint32_t
hashLookup3Orig
(
const
char
*
k
,
int
length
)
{
return
hashlittle
(
k
,
length
,
0
);
}
uint32_t
hashLookup3
(
const
char
*
k
,
int
length
)
{
return
Foam
::
Hasher
(
k
,
length
,
0
);
}
/* ======================================================================== */
static
uint32_t
crc_16_table
[
16
]
=
{
0x0000
,
0xCC01
,
0xD801
,
0x1400
,
0xF001
,
0x3C00
,
0x2800
,
0xE401
,
0xA001
,
0x6C00
,
0x7800
,
0xB401
,
0x5000
,
0x9C01
,
0x8801
,
0x4400
};
/*
* This code was found at: http://wannabe.guru.org/alg/node191.html
* and still exists here: http://www.fearme.com/misc/alg/node191.html
*
* this source code is based on Rex and Binstock which, in turn,
* acknowledges William James Hunt.
*
* According to the site this CRC uses the polynomial x^16+x^5+x^2+1.
* Unfortunately, DOCSIS uses x^16+x^12+x^5+1. D'oh!
*/
static
uint32_t
GetCRC16Update
(
uint32_t
start_crc
,
const
char
*
data_stream
,
int
length
)
{
uint32_t
crc
=
start_crc
;
uint32_t
r
;
/* while there is more data to process */
while
(
length
--
>
0
)
{
/* compute checksum of lower four bits of *data_stream */
r
=
crc_16_table
[
crc
&
0xF
];
crc
=
(
crc
>>
4
)
&
0x0FFF
;
crc
^=
r
^
crc_16_table
[
*
data_stream
&
0xF
];
/* now compute checksum of upper four bits of *data_stream */
r
=
crc_16_table
[
crc
&
0xF
];
crc
=
(
crc
>>
4
)
&
0x0FFF
;
crc
^=
r
^
crc_16_table
[(
*
data_stream
>>
4
)
&
0xF
];
/* next... */
data_stream
++
;
}
return
crc
;
}
uint32_t
GetCRC16
(
const
char
*
data_stream
,
int
length
)
{
return
GetCRC16Update
(
0
,
data_stream
,
length
);
}
/* ======================================================================== */
static
uint32_t
crc_table
[
256
];
/* This code was found at:
* http://cell.onecall.net/cell-relay/publications/software/CRC/32bitCRC.c.html
*/
/* */
/* crc32h.c -- package to compute 32-bit CRC one byte at a time using */
/* the high-bit first (Big-Endian) bit ordering convention */
/* */
/* Synopsis: */
/* gen_crc_table() -- generates a 256-word table containing all CRC */
/* remainders for every possible 8-bit byte. It */
/* must be executed (once) before any CRC updates. */
/* */
/* unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size) */
/* unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
/* Returns the updated value of the CRC accumulator after */
/* processing each byte in the addressed block of data. */
/* */
/* It is assumed that an unsigned long is at least 32 bits wide and */
/* that the predefined type char occupies one 8-bit byte of storage. */
/* */
/* The generator polynomial used for this version of the package is */
/* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */
/* as specified in the Autodin/Ethernet/ADCCP protocol standards. */
/* Other degree 32 polynomials may be substituted by re-defining the */
/* symbol POLYNOMIAL below. Lower degree polynomials must first be */
/* multiplied by an appropriate power of x. The representation used */
/* is that the coefficient of x^0 is stored in the LSB of the 32-bit */
/* word and the coefficient of x^31 is stored in the most significant */
/* bit. The CRC is to be appended to the data most significant byte */
/* first. For those protocols in which bytes are transmitted MSB */
/* first and in the same order as they are encountered in the block */
/* this convention results in the CRC remainder being transmitted with */
/* the coefficient of x^31 first and with that of x^0 last (just as */
/* would be done by a hardware shift register mechanization). */
/* */
/* The table lookup technique was adapted from the algorithm described */
/* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
/* generate the table of CRC remainders for all possible bytes */
#define CRC32POLYNOMIAL 0x04c11db7L
static
void
GenerateCRC32Table
(
void
)
{
int
i
,
j
;
uint32_t
crc_accum
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
crc_accum
=
(
(
unsigned
long
)
i
<<
24
);
for
(
j
=
0
;
j
<
8
;
j
++
)
{
if
(
crc_accum
&
0x80000000L
)
{
crc_accum
=
(
crc_accum
<<
1
)
^
CRC32POLYNOMIAL
;
}
else
{
crc_accum
=
(
crc_accum
<<
1
);
}
}
crc_table
[
i
]
=
crc_accum
;
}
return
;
}
/* update the CRC on the data block one byte at a time */
static
uint32_t
UpdateCRC32
(
uint32_t
crc_accum
,
const
char
*
data_blk_ptr
,
int
data_blk_size
)
{
int
j
;
uint8_t
i
;
for
(
j
=
0
;
j
<
data_blk_size
;
j
++
)
{
i
=
(
crc_accum
>>
24
)
^
*
data_blk_ptr
++
;
crc_accum
=
(
crc_accum
<<
8
)
^
crc_table
[
i
];
}
return
crc_accum
;
}
uint32_t
GetCRC32
(
const
char
*
data_stream
,
int
length
)
{
return
UpdateCRC32
(
0
,
data_stream
,
length
);
}
/* ======================================================================== */
/* Performs two parallel CRC-32 on even and odd bytes of the input, then
combines the two in a further CRC-32 calculation */
uint32_t
GetCRC32PH
(
const
char
*
data_blk_ptr
,
int
data_blk_size
)
{
int
j
;
uint8_t
i0
,
i1
;
uint32_t
crc_accum0
=
0
,
crc_accum1
=
0x23456789u
;
if
(
data_blk_size
&
1
)
crc_accum0
^=
*
data_blk_ptr
++
;
for
(
j
=
1
;
j
<
data_blk_size
;
j
+=
2
)
{
i0
=
((
crc_accum0
>>
24
)
^
*
data_blk_ptr
++
);
i1
=
((
crc_accum1
>>
24
)
^
*
data_blk_ptr
++
);
crc_accum0
=
(
crc_accum0
<<
8
)
^
crc_table
[
i0
];
crc_accum1
=
(
crc_accum1
<<
8
)
^
crc_table
[
i1
];
}
return
crc_accum0
+
crc_accum1
;
}
/* ======================================================================== */
/* Fowler / Noll / Vo (FNV) Hash
http://www.isthe.com/chongo/tech/comp/fnv/ */
uint32_t
FNVHash
(
const
char
*
data
,
int
len
)
{
int
i
;
uint32_t
hash
;
hash
=
2166136261u
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
hash
=
(
16777619u
*
hash
)
^
data
[
i
];
}
return
hash
;
}
/* ======================================================================== */
/*
* http://burtleburtle.net/bob/hash/doobs.html
*/
uint32_t
oneAtATimeHash
(
const
char
*
s
,
int
len
)
{
int32_t
hash
;
int
i
;
for
(
hash
=
0
,
i
=
0
;
i
<
len
;
i
++
)
{
hash
+=
s
[
i
];
hash
+=
(
hash
<<
10
);
hash
^=
(
hash
>>
6
);
/* Non-portable due to ANSI C */
}
hash
+=
(
hash
<<
3
);
hash
^=
(
hash
>>
11
);
/* Non-portable due to ANSI C */
hash
+=
(
hash
<<
15
);
return
(
uint32_t
)
hash
;
}
/* ======================================================================== */
uint32_t
oneAtATimeHashPH
(
const
char
*
s
,
int
len
)
{
int32_t
hash0
=
0
,
hash1
=
0x23456789
;
int
i
;
if
(
len
&
1
)
hash1
^=
*
s
++
;
for
(
i
=
1
;
i
<
len
;
i
+=
2
)
{
hash0
+=
*
s
++
;
hash1
+=
*
s
++
;
hash0
+=
(
hash0
<<
10
);
hash1
+=
(
hash1
<<
10
);
hash0
^=
(
hash0
>>
6
);
/* Non-portable due to ANSI C */
hash1
^=
(
hash1
>>
6
);
/* Non-portable due to ANSI C */
}
hash0
+=
hash1
;
hash0
+=
(
hash0
<<
3
);
hash0
^=
(
hash0
>>
11
);
/* Non-portable due to ANSI C */
hash0
+=
(
hash0
<<
15
);
return
(
uint32_t
)
hash0
;
}
/* ======================================================================== */
/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh derivative
license. See:
http://www.azillionmonkeys.com/qed/weblicense.html for license details.
http://www.azillionmonkeys.com/qed/hash.html */
#undef get16bits
#if 0
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
uint32_t
SuperFastHash
(
const
char
*
data
,
int
len
)
{
uint32_t
hash
=
0
;
if
(
len
<=
0
||
data
==
nullptr
)
return
0
;
unsigned
rem
=
len
&
3
;
len
>>=
2
;
/* Main loop */
for
(;
len
>
0
;
len
--
)
{
hash
+=
get16bits
(
data
);
hash
=
(
hash
<<
16
)
^
((
get16bits
(
data
+
2
)
<<
11
)
^
hash
);
hash
+=
hash
>>
11
;
data
+=
2
*
sizeof
(
uint16_t
);
}
/* Handle end cases */
switch
(
rem
)
{
case
3
:
hash
+=
get16bits
(
data
);
hash
^=
hash
<<
16
;
hash
^=
data
[
sizeof
(
uint16_t
)]
<<
18
;
hash
+=
hash
>>
11
;
break
;
case
2
:
hash
+=
get16bits
(
data
);
hash
^=
hash
<<
11
;
hash
+=
hash
>>
17
;
break
;
case
1
:
hash
+=
*
data
;
hash
^=
hash
<<
10
;
hash
+=
hash
>>
1
;
}
/* Force "avalanching" of final 127 bits */
hash
^=
hash
<<
3
;
hash
+=
hash
>>
5
;
hash
^=
hash
<<
4
;
hash
+=
hash
>>
17
;
hash
^=
hash
<<
25
;
hash
+=
hash
>>
6
;
return
hash
;
}
/* ======================================================================== */
/* A hashing function that I believe was created by either Chris Torek or
Dan Bernstein */
uint32_t
alphaNumHash
(
const
char
*
s
,
int
len
)
{
uint32_t
h
;
int
i
;
for
(
h
=
0
,
i
=
0
;
i
<
len
;
i
++
)
{
h
=
(
h
<<
5
)
+
(
h
*
5
)
+
(
unsigned
char
)
s
[
i
];
}
return
h
;
}
uint32_t
bernstein
(
const
char
*
s
,
int
len
)
{
uint32_t
h
;
int
i
;
for
(
h
=
0
,
i
=
0
;
i
<
len
;
i
++
)
{
h
=
(
h
<<
5
)
+
h
+
(
unsigned
char
)
s
[
i
];
}
return
h
;
}
// found somewhere in the 2nd addition
uint32_t
stroustrup
(
const
char
*
s
,
int
len
)
{
uint32_t
h
;
for
(
int
i
=
0
;
i
<
len
;
++
s
,
++
i
)
{
h
=
(
h
<<
1
)
^
(
unsigned
char
)
s
[
i
];
}
return
h
;
}
/* ======================================================================== */
typedef
uint32_t
(
*
hashFn
)
(
const
char
*
s
,
int
len
);
#define BUFF_SZ (128*2)
#define NTESTS 5000000
double
test
(
hashFn
hash
)
{
static
char
buff
[
BUFF_SZ
];
clock_t
c0
,
c1
;
int32_t
i
;
for
(
buff
[
0
]
=
0
,
i
=
1
;
i
<
BUFF_SZ
;
i
++
)
buff
[
i
]
=
(
char
)
(
i
+
buff
[
i
-
1
]);
c0
=
clock
();
for
(
i
=
0
;
i
<
NTESTS
;
i
++
)
hash
(
buff
,
BUFF_SZ
);
c1
=
clock
();
return
(
c1
-
c0
)
*
(
1
.
0
/
(
double
)
CLOCKS_PER_SEC
);
}
struct
tagtest
{
double
res
;
const
char
*
name
;
hashFn
hash
;
}
tests
[]
=
{
// { 0.0, "CRC32\t\t", GetCRC32 },
// { 0.0, "oneAtATimeHash\t", oneAtATimeHash },
// { 0.0, "alphaNumHash\t", alphaNumHash },
{
0
.
0
,
"FNVHash
\t\t
"
,
FNVHash
},
{
0
.
0
,
"bernstein
\t
"
,
bernstein
},
{
0
.
0
,
"stroustrup
\t
"
,
stroustrup
},
{
0
.
0
,
"hashLookup3
\t
"
,
hashLookup3
},
{
0
.
0
,
"hashLookup3Orig
\t
"
,
hashLookup3Orig
},
{
0
.
0
,
"SuperFastHash
\t
"
,
SuperFastHash
},
{
0
.
0
,
nullptr
,
nullptr
}
};
int
main
()
{
int
i
,
j
;
GenerateCRC32Table
();
for
(
j
=
0
;
tests
[
j
].
name
!=
nullptr
;
j
++
)
{
for
(
i
=
0
;
i
<
3
;
i
++
)
{
double
res
=
test
(
tests
[
j
].
hash
);
if
(
tests
[
j
].
res
==
0
.
0
||
tests
[
j
].
res
>
res
)
tests
[
j
].
res
=
res
;
}
printf
(
"%s:%8.4fs
\n
"
,
tests
[
j
].
name
,
tests
[
j
].
res
);
}
return
0
;
}
OpenFOAM-v2112/applications/test/IFstream/Make/files
0 → 100644
View file @
55e5a777
Test-IFstream.C
EXE = $(FOAM_USER_APPBIN)/Test-IFstream
OpenFOAM-v2112/applications/test/IFstream/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/IFstream/Test-IFstream.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-IFstream
Description
Tests on low-level reading
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Fstream.H"
#include "etcFiles.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
argList
::
noBanner
();
argList
::
noParallel
();
#include "setRootCase.H"
// Test with etc/controlDict (mandatory, from distribution)
{
const
fileName
inputFile
(
findEtcFile
(
"controlDict"
,
true
,
0007
)
);
Info
<<
nl
<<
"Test getLine"
<<
nl
<<
inputFile
<<
nl
;
IFstream
is
(
inputFile
);
string
buf
;
// Test that buffer resizing works as expected
Info
<<
"buf: "
<<
buf
.
size
()
<<
'/'
<<
buf
.
capacity
()
<<
nl
;
bool
skipDoc
=
true
;
while
(
is
.
good
())
{
if
(
skipDoc
||
is
.
lineNumber
()
%
2
)
{
is
.
getLine
(
buf
);
Info
<<
is
.
lineNumber
()
<<
": "
<<
buf
.
size
()
<<
'/'
<<
buf
.
capacity
()
<<
' '
<<
buf
<<
nl
;
if
(
buf
.
starts_with
(
"Documentation"
))
{
skipDoc
=
false
;
Info
<<
"Found Documentation: skip until closing '}'"
<<
" line number will now be incorrect"
<<
nl
;
auto
n
=
is
.
getLine
(
nullptr
,
'}'
);
Info
<<
is
.
lineNumber
()
<<
": ["
<<
label
(
n
)
<<
"]"
<<
nl
;
}
}
else
{
auto
n
=
is
.
getLine
(
nullptr
);
Info
<<
is
.
lineNumber
()
<<
": ["
<<
label
(
n
)
<<
"]"
<<
nl
;
}
}
}
Info
<<
"
\n
End
\n
"
<<
endl
;
return
0
;
}
// ************************************************************************* //
OpenFOAM-v2112/applications/test/IListStream/Make/files
0 → 100644
View file @
55e5a777
Test-IListStream.C
EXE = $(FOAM_USER_APPBIN)/Test-IListStream
OpenFOAM-v2112/applications/test/IListStream/Make/options
0 → 100644
View file @
55e5a777
/* EXE_INC = */
/* EXE_LIBS = */
OpenFOAM-v2112/applications/test/IListStream/Test-IListStream.C
0 → 100644
View file @
55e5a777
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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.
OpenFOAM 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 OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
\*---------------------------------------------------------------------------*/
#include "ListStream.H"
#include "UListStream.H"
#include "wordList.H"
#include "IOstreams.H"
#include "argList.H"
using
namespace
Foam
;
Ostream
&
toString
(
Ostream
&
os
,
const
UList
<
char
>&
list
)
{
os
<<
'"'
;
for
(
const
char
c
:
list
)
{
os
<<
c
;
}
os
<<
'"'
;
return
os
;
}
template
<
class
BufType
>
void
printInfo
(
const
BufType
&
buf
)
{
Info
<<
nl
<<
"========================="
<<
endl
;
buf
.
print
(
Info
);
toString
(
Info
,
buf
.
list
());
Info
<<
nl
<<
"========================="
<<
endl
;
}
template
<>
void
printInfo
(
const
List
<
char
>&
buf
)
{
Info
<<
nl
<<
"========================="
<<
endl
;
toString
(
Info
,
buf
);
Info
<<
nl
<<
"========================="
<<
endl
;
}
void
printTokens
(
Istream
&
is
)
{
label
count
=
0
;
token
t
;
while
(
is
.
good
())
{
is
>>
t
;
if
(
t
.
good
())
{
++
count
;
Info
<<
"token: "
<<
t
<<
endl
;
}
}
Info
<<
count
<<
" tokens"
<<
endl
;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
// Buffer storage
DynamicList
<
char
>
storage
(
16
);
OListStream
obuf
(
std
::
move
(
storage
));
obuf
<<
1002
<<
" "
<<
"abcd"
<<
" "
<<
"def"
<<
" "
<<
3
.
14159
<<
";
\n
"
;
// Move contents to output buffer
printInfo
(
obuf
);
Info
<<
nl
<<
"as string: "
;
toString
(
Info
,
obuf
.
list
())
<<
endl
;
Info
<<
"transfer contents to a List"
<<
endl
;
IListStream
ibuf
;
// Reclaim data storage from OListStream -> IListStream
{
List
<
char
>
data
;
obuf
.
swap
(
data
);
ibuf
.
swap
(
data
);
}
Info
<<
nl
;
Info
<<
nl
<<
"input string:"
;
printInfo
(
ibuf
);
Info
<<
nl
<<
"orig output:"
;
printInfo
(
obuf
);
printTokens
(
ibuf
);
Info
<<
nl
<<
"after:"
;
printInfo
(
ibuf
);
// This should also work
ibuf
.
list
()
=
'X'
;
Info
<<
nl
<<
"overwritten with const value:"
;
printInfo
(
ibuf
);
// Can also change content like this:
{
const
int
n
=
min
(
26
,
ibuf
.
size
());
for
(
int
i
=
0
;
i
<
n
;
++
i
)
{
ibuf
.
list
()[
i
]
=
'A'
+
i
;
}
}
Info
<<
nl
<<
"directly written:"
;
printInfo
(
ibuf
);
// Swap in/out an entirely new list storage:
List
<
char
>
newvalues
(
52
);
{
for
(
int
i
=
0
;
i
<
26
;
++
i
)
{
newvalues
[
2
*
i
+
0
]
=
char
(
'a'
+
i
);
newvalues
[
2
*
i
+
1
]
=
char
(
'A'
+
i
);
}
}
ibuf
.
swap
(
newvalues
);
Info
<<
nl
<<
"after swap:"
;
printInfo
(
ibuf
);
Info
<<
nl
<<
"swapped out:"
;
printInfo
(
newvalues
);
Info
<<
"
\n
End
\n
"
<<
endl
;
return
0
;
}
// ************************************************************************* //
Prev
1
…
6
7
8
9
10
11
12
13
14
…
34
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment