Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Development
openfoam
Commits
55a89e9d
Commit
55a89e9d
authored
Oct 30, 2009
by
Mark Olesen
Browse files
added HashTbl as development replacement for HashTable
- rename to HashTable later when it is considered stable
parent
83cee1cb
Changes
9
Hide whitespace changes
Inline
Side-by-side
applications/test/HashTable3/Make/files
0 → 100644
View file @
55a89e9d
hashTableTest3.C
EXE = $(FOAM_USER_APPBIN)/hashTableTest3
applications/test/HashTable3/Make/options
0 → 100644
View file @
55a89e9d
/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */
/* EXE_LIBS = -lfiniteVolume */
applications/test/HashTable3/hashTableTest3.C
0 → 100644
View file @
55a89e9d
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
Test speeds for some HashTable operations
\*---------------------------------------------------------------------------*/
#include
"argList.H"
#include
"HashTable.H"
#include
"HashPtrTable.H"
#include
"Map.H"
#include
"StaticHashTable.H"
#include
"HashTbl.H"
#include
"cpuTime.H"
using
namespace
Foam
;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int
main
(
int
argc
,
char
*
argv
[])
{
const
label
nLoops
=
30
;
const
label
nBase
=
100000
;
const
label
nSize
=
nLoops
*
nBase
;
cpuTime
timer
;
// ie, a
// Map<label> map(2 * nSize);
// HashTable<label, label, Hash<label> > map(2 * nSize);
// StaticHashTable<label, label, Hash<label> > map(2 * nSize);
HashTbl
<
label
,
label
,
Hash
<
label
>
>
map
(
2
*
nSize
);
Info
<<
"Constructed map of size: "
<<
nSize
<<
" "
<<
timer
.
cpuTimeIncrement
()
<<
" s
\n\n
"
;
for
(
label
i
=
0
;
i
<
nSize
;
i
++
)
{
map
.
insert
(
i
,
i
);
}
Info
<<
"Inserted "
<<
nSize
<<
" elements: "
<<
timer
.
cpuTimeIncrement
()
<<
" s
\n\n
"
;
label
elemI
=
0
;
for
(
label
iLoop
=
0
;
iLoop
<
nLoops
;
iLoop
++
)
{
for
(
label
i
=
0
;
i
<
nBase
;
i
++
)
{
map
.
erase
(
elemI
++
);
}
Info
<<
"loop "
<<
iLoop
<<
" - Erased "
<<
nBase
<<
" elements: "
<<
" "
<<
timer
.
cpuTimeIncrement
()
<<
" s
\n
"
;
}
return
0
;
}
// ************************************************************************* //
src/OpenFOAM/Make/files
View file @
55a89e9d
...
...
@@ -61,6 +61,7 @@ $(sha1)/SHA1Digest.C
primitives/random/Random.C
containers/HashTables/HashTbl/HashTblName.C
containers/HashTables/HashTable/HashTableName.C
containers/HashTables/StaticHashTable/StaticHashTableName.C
containers/Lists/SortableList/ParSortableListName.C
...
...
src/OpenFOAM/containers/HashTables/HashTbl/HashTbl.C
0 → 100644
View file @
55a89e9d
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#ifndef HashTbl_C
#define HashTbl_C
#include
"HashTbl.H"
#include
"List.H"
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
label
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
canonicalSize
(
const
label
size
)
{
if
(
size
<
1
)
{
return
0
;
}
// enforce power of two
unsigned
int
goodSize
=
size
;
if
(
goodSize
&
(
goodSize
-
1
))
{
// brute-force is fast enough
goodSize
=
1
;
while
(
goodSize
<
unsigned
(
size
))
{
goodSize
<<=
1
;
}
}
return
goodSize
;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
HashTbl
(
const
label
size
)
:
HashTblName
(),
nElmts_
(
0
),
tableSize_
(
canonicalSize
(
size
)),
table_
(
NULL
),
endIter_
(
*
this
,
NULL
,
0
),
endConstIter_
(
*
this
,
NULL
,
0
)
{
if
(
tableSize_
)
{
table_
=
new
hashedEntry
*
[
tableSize_
];
for
(
label
hashIdx
=
0
;
hashIdx
<
tableSize_
;
hashIdx
++
)
{
table_
[
hashIdx
]
=
0
;
}
}
}
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
HashTbl
(
const
HashTbl
<
T
,
Key
,
Hash
>&
ht
)
:
HashTblName
(),
nElmts_
(
0
),
tableSize_
(
ht
.
tableSize_
),
table_
(
NULL
),
endIter_
(
*
this
,
NULL
,
0
),
endConstIter_
(
*
this
,
NULL
,
0
)
{
if
(
tableSize_
)
{
table_
=
new
hashedEntry
*
[
tableSize_
];
for
(
label
hashIdx
=
0
;
hashIdx
<
tableSize_
;
hashIdx
++
)
{
table_
[
hashIdx
]
=
0
;
}
for
(
const_iterator
iter
=
ht
.
cbegin
();
iter
!=
ht
.
cend
();
++
iter
)
{
insert
(
iter
.
key
(),
*
iter
);
}
}
}
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
HashTbl
(
const
Xfer
<
HashTbl
<
T
,
Key
,
Hash
>
>&
ht
)
:
HashTblName
(),
nElmts_
(
0
),
tableSize_
(
0
),
table_
(
NULL
),
endIter_
(
*
this
,
NULL
,
0
),
endConstIter_
(
*
this
,
NULL
,
0
)
{
transfer
(
ht
());
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::~
HashTbl
()
{
if
(
table_
)
{
clear
();
delete
[]
table_
;
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template
<
class
T
,
class
Key
,
class
Hash
>
bool
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
found
(
const
Key
&
key
)
const
{
if
(
nElmts_
)
{
const
label
hashIdx
=
hashKeyIndex
(
key
);
for
(
hashedEntry
*
ep
=
table_
[
hashIdx
];
ep
;
ep
=
ep
->
next_
)
{
if
(
key
==
ep
->
key_
)
{
return
true
;
}
}
}
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::found(const Key& key) : "
<<
"Entry "
<<
key
<<
" not found in hash table
\n
"
;
}
# endif
return
false
;
}
template
<
class
T
,
class
Key
,
class
Hash
>
typename
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
iterator
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
find
(
const
Key
&
key
)
{
if
(
nElmts_
)
{
const
label
hashIdx
=
hashKeyIndex
(
key
);
for
(
hashedEntry
*
ep
=
table_
[
hashIdx
];
ep
;
ep
=
ep
->
next_
)
{
if
(
key
==
ep
->
key_
)
{
return
iterator
(
*
this
,
ep
,
hashIdx
);
}
}
}
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::find(const Key& key) : "
<<
"Entry "
<<
key
<<
" not found in hash table
\n
"
;
}
# endif
return
end
();
}
template
<
class
T
,
class
Key
,
class
Hash
>
typename
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
const_iterator
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
find
(
const
Key
&
key
)
const
{
if
(
nElmts_
)
{
const
label
hashIdx
=
hashKeyIndex
(
key
);
for
(
hashedEntry
*
ep
=
table_
[
hashIdx
];
ep
;
ep
=
ep
->
next_
)
{
if
(
key
==
ep
->
key_
)
{
return
const_iterator
(
*
this
,
ep
,
hashIdx
);
}
}
}
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::find(const Key& key) const : "
<<
"Entry "
<<
key
<<
" not found in hash table
\n
"
;
}
# endif
return
cend
();
}
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
List
<
Key
>
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
toc
()
const
{
List
<
Key
>
tofc
(
nElmts_
);
label
i
=
0
;
for
(
const_iterator
iter
=
cbegin
();
iter
!=
cend
();
++
iter
)
{
tofc
[
i
++
]
=
iter
.
key
();
}
return
tofc
;
}
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
List
<
Key
>
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
sortedToc
()
const
{
List
<
Key
>
sortedList
=
this
->
toc
();
sort
(
sortedList
);
return
sortedList
;
}
template
<
class
T
,
class
Key
,
class
Hash
>
bool
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
set
(
const
Key
&
key
,
const
T
&
newEntry
,
const
bool
protect
)
{
if
(
!
tableSize_
)
{
resize
(
2
);
}
const
label
hashIdx
=
hashKeyIndex
(
key
);
hashedEntry
*
existing
=
0
;
hashedEntry
*
prev
=
0
;
for
(
hashedEntry
*
ep
=
table_
[
hashIdx
];
ep
;
ep
=
ep
->
next_
)
{
if
(
key
==
ep
->
key_
)
{
existing
=
ep
;
break
;
}
prev
=
ep
;
}
// not found, insert it at the head
if
(
!
existing
)
{
table_
[
hashIdx
]
=
new
hashedEntry
(
key
,
table_
[
hashIdx
],
newEntry
);
nElmts_
++
;
if
(
double
(
nElmts_
)
/
tableSize_
>
0
.
8
)
{
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::set"
"(const Key& key, T newEntry) : "
"Doubling table size
\n
"
;
}
# endif
resize
(
2
*
tableSize_
);
}
}
else
if
(
protect
)
{
// found - but protected from overwriting
// this corresponds to the STL 'insert' convention
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::set"
"(const Key& key, T newEntry, true) : "
"Cannot insert "
<<
key
<<
" already in hash table
\n
"
;
}
# endif
return
false
;
}
else
{
// found - overwrite existing entry
// this corresponds to the Perl convention
hashedEntry
*
ep
=
new
hashedEntry
(
key
,
existing
->
next_
,
newEntry
);
// replace existing element - within list or insert at the head
if
(
prev
)
{
prev
->
next_
=
ep
;
}
else
{
table_
[
hashIdx
]
=
ep
;
}
delete
existing
;
}
return
true
;
}
template
<
class
T
,
class
Key
,
class
Hash
>
bool
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
erase
(
const
iterator
&
cit
)
{
if
(
cit
.
elmtPtr_
)
// note: endIter_ also has 0 elmtPtr_
{
iterator
&
it
=
const_cast
<
iterator
&>
(
cit
);
// Search element before elmtPtr_
hashedEntry
*
prev
=
0
;
for
(
hashedEntry
*
ep
=
table_
[
it
.
hashIndex_
];
ep
;
ep
=
ep
->
next_
)
{
if
(
ep
==
it
.
elmtPtr_
)
{
break
;
}
prev
=
ep
;
}
if
(
prev
)
{
// Have element before elmtPtr
prev
->
next_
=
it
.
elmtPtr_
->
next_
;
delete
it
.
elmtPtr_
;
it
.
elmtPtr_
=
prev
;
}
else
{
// elmtPtr is first element on SLList
table_
[
it
.
hashIndex_
]
=
it
.
elmtPtr_
->
next_
;
delete
it
.
elmtPtr_
;
// Search back for previous non-zero table entry
while
(
--
it
.
hashIndex_
>=
0
&&
!
table_
[
it
.
hashIndex_
])
{}
if
(
it
.
hashIndex_
>=
0
)
{
// In table entry search for last element
it
.
elmtPtr_
=
table_
[
it
.
hashIndex_
];
while
(
it
.
elmtPtr_
&&
it
.
elmtPtr_
->
next_
)
{
it
.
elmtPtr_
=
it
.
elmtPtr_
->
next_
;
}
}
else
{
// No previous found. Mark with special value which is
// - not end()/cend()
// - handled by operator++
it
.
elmtPtr_
=
reinterpret_cast
<
hashedEntry
*>
(
this
);
it
.
hashIndex_
=
-
1
;
}
}
nElmts_
--
;
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::erase(iterator&) : "
<<
"hashedEntry "
<<
it
.
elmtPtr_
->
key_
<<
" removed.
\n
"
;
}
# endif
return
true
;
}
else
{
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::erase(iterator&) : "
<<
"cannot remove hashedEntry from hash table
\n
"
;
}
# endif
return
false
;
}
}
template
<
class
T
,
class
Key
,
class
Hash
>
bool
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
erase
(
const
Key
&
key
)
{
iterator
fnd
=
find
(
key
);
if
(
fnd
!=
end
())
{
return
erase
(
fnd
);
}
else
{
return
false
;
}
}
template
<
class
T
,
class
Key
,
class
Hash
>
Foam
::
label
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
erase
(
const
UList
<
Key
>&
keys
)
{
label
count
=
0
;
// Remove listed keys from this table
if
(
this
->
size
())
{
forAll
(
keys
,
keyI
)
{
if
(
erase
(
keys
[
keyI
]))
{
count
++
;
}
}
}
return
count
;
}
template
<
class
T
,
class
Key
,
class
Hash
>
template
<
class
AnyType
>
Foam
::
label
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
erase
(
const
HashTbl
<
AnyType
,
Key
,
Hash
>&
rhs
)
{
label
count
=
0
;
// Remove rhs elements from this table
if
(
this
->
size
())
{
// NOTE: could further optimize depending on which hash is smaller
for
(
iterator
iter
=
begin
();
iter
!=
end
();
++
iter
)
{
if
(
rhs
.
found
(
iter
.
key
())
&&
erase
(
iter
))
{
count
++
;
}
}
}
return
count
;
}
template
<
class
T
,
class
Key
,
class
Hash
>
void
Foam
::
HashTbl
<
T
,
Key
,
Hash
>::
resize
(
const
label
sz
)
{
label
newSize
=
canonicalSize
(
sz
);
if
(
newSize
==
tableSize_
)
{
# ifdef FULLDEBUG
if
(
debug
)
{
Info
<<
"HashTbl<T, Key, Hash>::resize(const label) : "
<<
"new table size == old table size
\n
"
;
}
# endif
return
;
}
HashTbl
<
T
,
Key
,
Hash
>*
newTable
=
new
HashTbl
<
T
,
Key
,
Hash
>
(
newSize
);