forked from celeritas-project/celeritas
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add deduplicating transform inserter (celeritas-project#1112)
* Add equality operators to transforms * Add to-do * Add missing include * Maked signed permutation accessible * Add transofrm hasher * Add transform inserter * Fix missing symbols in release mode * Fix documentation * Apply review feedback
- Loading branch information
Showing
15 changed files
with
432 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers. | ||
// See the top-level COPYRIGHT file for details. | ||
// SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
//---------------------------------------------------------------------------// | ||
//! \file orange/orangeinp/detail/TransformInserter.cc | ||
//---------------------------------------------------------------------------// | ||
#include "TransformInserter.hh" | ||
|
||
#include "orange/transform/TransformHasher.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace orangeinp | ||
{ | ||
namespace detail | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct with a pointer to the transform vector. | ||
*/ | ||
TransformInserter::TransformInserter(VecTransform* transforms) | ||
: transform_{transforms} | ||
, cache_{0, HashTransform{transforms}, EqualTransform{transforms}} | ||
{ | ||
CELER_EXPECT(transform_); | ||
CELER_EXPECT(transform_->empty()); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a transform with deduplication. | ||
*/ | ||
TransformId TransformInserter::operator()(VariantTransform&& vt) | ||
{ | ||
CELER_ASSUME(!vt.valueless_by_exception()); | ||
TransformId result = this->size_id(); | ||
transform_->push_back(std::move(vt)); | ||
auto [iter, inserted] = cache_.insert(result); | ||
if (!inserted) | ||
{ | ||
// Roll back the change by erasing the last element | ||
transform_->pop_back(); | ||
// Return the existing ID | ||
return *iter; | ||
} | ||
return result; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Calculate the hash of a transform. | ||
*/ | ||
std::size_t TransformInserter::HashTransform::operator()(TransformId id) const | ||
{ | ||
CELER_EXPECT(storage && id < storage->size()); | ||
return visit(TransformHasher{}, (*storage)[id.unchecked_get()]); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Compare two transform IDs for equality in a common container. | ||
*/ | ||
bool TransformInserter::EqualTransform::operator()(TransformId a, | ||
TransformId b) const | ||
{ | ||
CELER_EXPECT(storage && a < storage->size() && b < storage->size()); | ||
return (*storage)[a.unchecked_get()] == (*storage)[b.unchecked_get()]; | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace detail | ||
} // namespace orangeinp | ||
} // namespace celeritas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers. | ||
// See the top-level COPYRIGHT file for details. | ||
// SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
//---------------------------------------------------------------------------// | ||
//! \file orange/orangeinp/detail/TransformInserter.hh | ||
//---------------------------------------------------------------------------// | ||
#pragma once | ||
|
||
#include <unordered_set> | ||
#include <vector> | ||
|
||
#include "orange/transform/VariantTransform.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace orangeinp | ||
{ | ||
namespace detail | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Deduplicate transforms as they're being built. | ||
* | ||
* This currently only works for *exact* transforms rather than *almost exact* | ||
* transforms. We may eventually want to add a "transform simplifier" and | ||
* "transform soft equal". | ||
*/ | ||
class TransformInserter | ||
{ | ||
public: | ||
//!@{ | ||
//! \name Type aliases | ||
using VecTransform = std::vector<VariantTransform>; | ||
//!@} | ||
|
||
public: | ||
// Construct with a pointer to the transform vector | ||
explicit TransformInserter(VecTransform* transforms); | ||
|
||
// Construct a transform with deduplication | ||
TransformId operator()(VariantTransform&& vt); | ||
|
||
private: | ||
//// TYPES //// | ||
|
||
struct HashTransform | ||
{ | ||
VecTransform* storage{nullptr}; | ||
std::size_t operator()(TransformId) const; | ||
}; | ||
struct EqualTransform | ||
{ | ||
VecTransform* storage{nullptr}; | ||
bool operator()(TransformId, TransformId) const; | ||
}; | ||
|
||
//// DATA //// | ||
|
||
VecTransform* transform_; | ||
std::unordered_set<TransformId, HashTransform, EqualTransform> cache_; | ||
|
||
//// HELPER FUNCTIONS //// | ||
|
||
//! Get the ID of the next transform to be inserted | ||
TransformId size_id() const { return TransformId(transform_->size()); } | ||
}; | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace detail | ||
} // namespace orangeinp | ||
} // namespace celeritas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers. | ||
// See the top-level COPYRIGHT file for details. | ||
// SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
//---------------------------------------------------------------------------// | ||
//! \file orange/transform/TransformHasher.cc | ||
//---------------------------------------------------------------------------// | ||
#include "TransformHasher.hh" | ||
|
||
#include <functional> | ||
|
||
#include "corecel/Assert.hh" | ||
#include "corecel/math/HashUtils.hh" | ||
|
||
namespace celeritas | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* By default, calculate a hash based on the stored data. | ||
*/ | ||
template<class T> | ||
auto TransformHasher::operator()(T const& t) const -> result_type | ||
{ | ||
return hash_as_bytes(t.data()); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Special hash for "no transformation". | ||
*/ | ||
auto TransformHasher::operator()(NoTransformation const&) const -> result_type | ||
{ | ||
return std::hash<result_type>{}(0); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Special hash for "signed permutation". | ||
*/ | ||
auto TransformHasher::operator()(SignedPermutation const& t) const | ||
-> result_type | ||
{ | ||
auto v = t.value(); | ||
return std::hash<decltype(v)>{}(v); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
// FREE FUNCTIONS | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Calculate a hash for a variant transform. | ||
*/ | ||
TransformHasher::result_type | ||
visit(TransformHasher const& th, VariantTransform const& transform) | ||
{ | ||
CELER_ASSUME(!transform.valueless_by_exception()); | ||
return std::visit(th, transform); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
// EXPLICIT INSTANTIATION | ||
//---------------------------------------------------------------------------// | ||
//! \cond | ||
|
||
template std::size_t TransformHasher::operator()(Translation const&) const; | ||
template std::size_t TransformHasher::operator()(Transformation const&) const; | ||
|
||
//! \endcond | ||
//---------------------------------------------------------------------------// | ||
} // namespace celeritas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
//----------------------------------*-C++-*----------------------------------// | ||
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers. | ||
// See the top-level COPYRIGHT file for details. | ||
// SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
//---------------------------------------------------------------------------// | ||
//! \file orange/transform/TransformHasher.hh | ||
//---------------------------------------------------------------------------// | ||
#pragma once | ||
|
||
#include <cstdlib> | ||
|
||
#include "VariantTransform.hh" | ||
|
||
namespace celeritas | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Calculate a hash value of a transform for deduplication. | ||
*/ | ||
class TransformHasher | ||
{ | ||
public: | ||
//!@{ | ||
//! \name Type aliases | ||
using result_type = std::size_t; | ||
//!@} | ||
|
||
public: | ||
// By default, calculate a hash based on the stored data | ||
template<class T> | ||
result_type operator()(T const&) const; | ||
|
||
// Special hash for "no transformation" | ||
result_type operator()(NoTransformation const&) const; | ||
|
||
// Special hash for "signed permutation" | ||
result_type operator()(SignedPermutation const&) const; | ||
}; | ||
|
||
//---------------------------------------------------------------------------// | ||
// FREE FUNCTIONS | ||
//---------------------------------------------------------------------------// | ||
// Calculate a hash for a variant transform | ||
TransformHasher::result_type | ||
visit(TransformHasher const&, VariantTransform const& transform); | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace celeritas |
Oops, something went wrong.