From 3a48029fc2bb1d230d04a8caf6f1e31bac1d5c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Fri, 12 Dec 2025 22:27:27 +0100 Subject: [PATCH] manifold: Update to 3.3.2 --- thirdparty/README.md | 2 +- thirdparty/manifold/include/manifold/common.h | 111 +-------- thirdparty/manifold/include/manifold/linalg.h | 40 ++++ thirdparty/manifold/src/boolean_result.cpp | 4 - thirdparty/manifold/src/csg_tree.cpp | 63 ++--- thirdparty/manifold/src/edge_op.cpp | 1 + thirdparty/manifold/src/impl.cpp | 9 +- thirdparty/manifold/src/impl.h | 10 + thirdparty/manifold/src/manifold.cpp | 74 ++++++ thirdparty/manifold/src/properties.cpp | 9 +- thirdparty/manifold/src/quickhull.cpp | 2 + thirdparty/manifold/src/smoothing.cpp | 2 + thirdparty/manifold/src/sparse.h | 225 ------------------ thirdparty/manifold/src/subdivision.cpp | 2 + thirdparty/manifold/src/vec.h | 4 + 15 files changed, 189 insertions(+), 369 deletions(-) delete mode 100644 thirdparty/manifold/src/sparse.h diff --git a/thirdparty/README.md b/thirdparty/README.md index 62fe3e0f573..411dd0b06fc 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -658,7 +658,7 @@ See `linuxbsd_headers/README.md`. ## manifold - Upstream: https://github.com/elalish/manifold -- Version: git (76208dc02b069d2be50ed2d8a9279ee5622fa5fd, 2025) +- Version: 3.3.2 (798d83c8d7fabcddd23c1617097b95ba40f2597c, 2025) - License: Apache 2.0 File extracted from upstream source: diff --git a/thirdparty/manifold/include/manifold/common.h b/thirdparty/manifold/include/manifold/common.h index 6975cc3de58..d48cf4d2ebc 100644 --- a/thirdparty/manifold/include/manifold/common.h +++ b/thirdparty/manifold/include/manifold/common.h @@ -488,80 +488,12 @@ constexpr double DEFAULT_LENGTH = 1.0; */ class Quality { private: - inline static int circularSegments_ = DEFAULT_SEGMENTS; - inline static double circularAngle_ = DEFAULT_ANGLE; - inline static double circularEdgeLength_ = DEFAULT_LENGTH; - public: - /** - * Sets an angle constraint the default number of circular segments for the - * CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and - * Manifold::Revolve() constructors. The number of segments will be rounded up - * to the nearest factor of four. - * - * @param angle The minimum angle in degrees between consecutive segments. The - * angle will increase if the the segments hit the minimum edge length. - * Default is 10 degrees. - */ - static void SetMinCircularAngle(double angle) { - if (angle <= 0) return; - circularAngle_ = angle; - } - - /** - * Sets a length constraint the default number of circular segments for the - * CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and - * Manifold::Revolve() constructors. The number of segments will be rounded up - * to the nearest factor of four. - * - * @param length The minimum length of segments. The length will - * increase if the the segments hit the minimum angle. Default is 1.0. - */ - static void SetMinCircularEdgeLength(double length) { - if (length <= 0) return; - circularEdgeLength_ = length; - } - - /** - * Sets the default number of circular segments for the - * CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and - * Manifold::Revolve() constructors. Overrides the edge length and angle - * constraints and sets the number of segments to exactly this value. - * - * @param number Number of circular segments. Default is 0, meaning no - * constraint is applied. - */ - static void SetCircularSegments(int number) { - if (number < 3 && number != 0) return; - circularSegments_ = number; - } - - /** - * Determine the result of the SetMinCircularAngle(), - * SetMinCircularEdgeLength(), and SetCircularSegments() defaults. - * - * @param radius For a given radius of circle, determine how many default - * segments there will be. - */ - static int GetCircularSegments(double radius) { - if (circularSegments_ > 0) return circularSegments_; - int nSegA = 360.0 / circularAngle_; - int nSegL = 2.0 * radius * kPi / circularEdgeLength_; - int nSeg = fmin(nSegA, nSegL) + 3; - nSeg -= nSeg % 4; - return std::max(nSeg, 4); - } - - /** - * Resets the circular construction parameters to their defaults if - * SetMinCircularAngle, SetMinCircularEdgeLength, or SetCircularSegments have - * been called. - */ - static void ResetToDefaults() { - circularSegments_ = DEFAULT_SEGMENTS; - circularAngle_ = DEFAULT_ANGLE; - circularEdgeLength_ = DEFAULT_LENGTH; - } + static void SetMinCircularAngle(double angle); + static void SetMinCircularEdgeLength(double length); + static void SetCircularSegments(int number); + static int GetCircularSegments(double radius); + static void ResetToDefaults(); }; /** @} */ @@ -600,39 +532,6 @@ struct ExecutionParams { /** @} */ #ifdef MANIFOLD_DEBUG -template -std::ostream& operator<<(std::ostream& out, const la::vec& v) { - return out << '{' << v[0] << '}'; -} -template -std::ostream& operator<<(std::ostream& out, const la::vec& v) { - return out << '{' << v[0] << ',' << v[1] << '}'; -} -template -std::ostream& operator<<(std::ostream& out, const la::vec& v) { - return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}'; -} -template -std::ostream& operator<<(std::ostream& out, const la::vec& v) { - return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}'; -} - -template -std::ostream& operator<<(std::ostream& out, const la::mat& m) { - return out << '{' << m[0] << '}'; -} -template -std::ostream& operator<<(std::ostream& out, const la::mat& m) { - return out << '{' << m[0] << ',' << m[1] << '}'; -} -template -std::ostream& operator<<(std::ostream& out, const la::mat& m) { - return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}'; -} -template -std::ostream& operator<<(std::ostream& out, const la::mat& m) { - return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}'; -} inline std::ostream& operator<<(std::ostream& stream, const Box& box) { return stream << "min: " << box.min << ", " diff --git a/thirdparty/manifold/include/manifold/linalg.h b/thirdparty/manifold/include/manifold/linalg.h index 12f484fa1c3..2b82421abc7 100644 --- a/thirdparty/manifold/include/manifold/linalg.h +++ b/thirdparty/manifold/include/manifold/linalg.h @@ -2360,6 +2360,46 @@ struct converter, vec> { /** @} */ } // namespace linalg +#ifdef MANIFOLD_DEBUG +#include + +namespace linalg { +template +std::ostream& operator<<(std::ostream& out, const vec& v) { + return out << '{' << v[0] << '}'; +} +template +std::ostream& operator<<(std::ostream& out, const vec& v) { + return out << '{' << v[0] << ',' << v[1] << '}'; +} +template +std::ostream& operator<<(std::ostream& out, const vec& v) { + return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << '}'; +} +template +std::ostream& operator<<(std::ostream& out, const vec& v) { + return out << '{' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << '}'; +} + +template +std::ostream& operator<<(std::ostream& out, const mat& m) { + return out << '{' << m[0] << '}'; +} +template +std::ostream& operator<<(std::ostream& out, const mat& m) { + return out << '{' << m[0] << ',' << m[1] << '}'; +} +template +std::ostream& operator<<(std::ostream& out, const mat& m) { + return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << '}'; +} +template +std::ostream& operator<<(std::ostream& out, const mat& m) { + return out << '{' << m[0] << ',' << m[1] << ',' << m[2] << ',' << m[3] << '}'; +} +} // namespace linalg +#endif + namespace std { /** @addtogroup hash * @ingroup LinAlg diff --git a/thirdparty/manifold/src/boolean_result.cpp b/thirdparty/manifold/src/boolean_result.cpp index 803aeb4924e..7eacf3c4de0 100644 --- a/thirdparty/manifold/src/boolean_result.cpp +++ b/thirdparty/manifold/src/boolean_result.cpp @@ -878,10 +878,6 @@ Manifold::Impl Boolean3::Result(OpType op) const { #endif // Level 6 - - if (ManifoldParams().intermediateChecks) - DEBUG_ASSERT(outR.IsManifold(), logicErr, "polygon mesh is not manifold!"); - outR.Face2Tri(faceEdge, halfedgeRef); halfedgeRef.clear(); faceEdge.clear(); diff --git a/thirdparty/manifold/src/csg_tree.cpp b/thirdparty/manifold/src/csg_tree.cpp index c41cb8f0c5f..35585a6103f 100644 --- a/thirdparty/manifold/src/csg_tree.cpp +++ b/thirdparty/manifold/src/csg_tree.cpp @@ -342,7 +342,9 @@ std::shared_ptr BatchBoolean( std::vector> tmp; #if MANIFOLD_PAR == 1 tbb::task_group group; - std::mutex mutex; + // make sure the order of result is deterministic + std::vector> parallelTmp; + for (int i = 0; i < 4; i++) parallelTmp.push_back(nullptr); #endif while (results.size() > 1) { for (size_t i = 0; i < 4 && results.size() > 1; i++) { @@ -353,11 +355,8 @@ std::shared_ptr BatchBoolean( auto b = std::move(results.back()); results.pop_back(); #if MANIFOLD_PAR == 1 - group.run([&, a, b]() { - auto result = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation); - mutex.lock(); - tmp.push_back(result); - mutex.unlock(); + group.run([&, i, a, b]() { + parallelTmp[i] = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation); }); #else auto result = SimpleBoolean(*a->GetImpl(), *b->GetImpl(), operation); @@ -366,6 +365,8 @@ std::shared_ptr BatchBoolean( } #if MANIFOLD_PAR == 1 group.wait(); + for (int i = 0; i < 4 && parallelTmp[i]; i++) + tmp.emplace_back(std::move(parallelTmp[i])); #endif for (auto result : tmp) { results.push_back(result); @@ -617,33 +618,35 @@ std::shared_ptr CsgOpNode::ToLeafNode() const { std::shared_ptr frame = stack.back(); auto impl = frame->op_node->impl_.GetGuard(); if (frame->finalize) { - switch (frame->op_node->op_) { - case OpType::Add: - *impl = {BatchUnion(frame->positive_children)}; - break; - case OpType::Intersect: { - *impl = {BatchBoolean(OpType::Intersect, frame->positive_children)}; - break; - }; - case OpType::Subtract: - if (frame->positive_children.empty()) { - // nothing to subtract from, so the result is empty. - *impl = {std::make_shared()}; - } else { - auto positive = BatchUnion(frame->positive_children); - if (frame->negative_children.empty()) { - // nothing to subtract, result equal to the LHS. - *impl = {frame->positive_children[0]}; + if (!frame->op_node->cache_) { + switch (frame->op_node->op_) { + case OpType::Add: + *impl = {BatchUnion(frame->positive_children)}; + break; + case OpType::Intersect: { + *impl = {BatchBoolean(OpType::Intersect, frame->positive_children)}; + break; + }; + case OpType::Subtract: + if (frame->positive_children.empty()) { + // nothing to subtract from, so the result is empty. + *impl = {std::make_shared()}; } else { - auto negative = BatchUnion(frame->negative_children); - *impl = {SimpleBoolean(*positive->GetImpl(), *negative->GetImpl(), - OpType::Subtract)}; + auto positive = BatchUnion(frame->positive_children); + if (frame->negative_children.empty()) { + // nothing to subtract, result equal to the LHS. + *impl = {frame->positive_children[0]}; + } else { + auto negative = BatchUnion(frame->negative_children); + *impl = {SimpleBoolean(*positive->GetImpl(), + *negative->GetImpl(), OpType::Subtract)}; + } } - } - break; + break; + } + frame->op_node->cache_ = std::static_pointer_cast( + (*impl)[0]->Transform(frame->op_node->transform_)); } - frame->op_node->cache_ = std::static_pointer_cast( - (*impl)[0]->Transform(frame->op_node->transform_)); if (frame->positive_dest != nullptr) frame->positive_dest->push_back(std::static_pointer_cast( frame->op_node->cache_->Transform(frame->transform))); diff --git a/thirdparty/manifold/src/edge_op.cpp b/thirdparty/manifold/src/edge_op.cpp index 81567ffeba5..ae038896349 100644 --- a/thirdparty/manifold/src/edge_op.cpp +++ b/thirdparty/manifold/src/edge_op.cpp @@ -202,6 +202,7 @@ namespace manifold { */ void Manifold::Impl::CleanupTopology() { if (!halfedge_.size()) return; + DEBUG_ASSERT(IsManifold(), logicErr, "polygon mesh is not manifold!"); // In the case of a very bad triangulation, it is possible to create pinched // verts. They must be removed before edge collapse. diff --git a/thirdparty/manifold/src/impl.cpp b/thirdparty/manifold/src/impl.cpp index 10a3a85991a..d4b3a0c3e25 100644 --- a/thirdparty/manifold/src/impl.cpp +++ b/thirdparty/manifold/src/impl.cpp @@ -149,8 +149,12 @@ int GetLabels(std::vector& components, namespace manifold { #if (MANIFOLD_PAR == 1) +#if (TBB_VERSION_MAJOR < 2021) +tbb::task_arena gc_arena(1, 1); +#else tbb::task_arena gc_arena(1, 1, tbb::task_arena::priority::low); #endif +#endif std::atomic Manifold::Impl::meshIDCounter_(1); @@ -484,8 +488,9 @@ void Manifold::Impl::CreateHalfedges(const Vec& triProp, const int pair1 = ids[k]; Halfedge& h1 = halfedge_[pair1]; if (h0.startVert != h1.endVert || h0.endVert != h1.startVert) break; - if (halfedge_[NextHalfedge(pair0)].endVert == - halfedge_[NextHalfedge(pair1)].endVert) { + if (h1.pairedHalfedge != kRemovedHalfedge && + halfedge_[NextHalfedge(pair0)].endVert == + halfedge_[NextHalfedge(pair1)].endVert) { h0.pairedHalfedge = h1.pairedHalfedge = kRemovedHalfedge; // Reorder so that remaining edges pair up if (k != i + numEdge) std::swap(ids[i + numEdge], ids[k]); diff --git a/thirdparty/manifold/src/impl.h b/thirdparty/manifold/src/impl.h index 9e935de12a3..62e368012df 100644 --- a/thirdparty/manifold/src/impl.h +++ b/thirdparty/manifold/src/impl.h @@ -68,6 +68,16 @@ struct Manifold::Impl { const uint32_t numVert = meshGL.NumVert(); const uint32_t numTri = meshGL.NumTri(); + if (numVert == 0 && numTri == 0) { + MakeEmpty(Error::NoError); + return; + } + + if (numVert < 4 || numTri < 4) { + MakeEmpty(Error::NotManifold); + return; + } + if (meshGL.numProp < 3) { MakeEmpty(Error::MissingPositionProperties); return; diff --git a/thirdparty/manifold/src/manifold.cpp b/thirdparty/manifold/src/manifold.cpp index 627ef5ea385..05082def869 100644 --- a/thirdparty/manifold/src/manifold.cpp +++ b/thirdparty/manifold/src/manifold.cpp @@ -200,6 +200,80 @@ MeshGLP GetMeshGLImpl(const manifold::Manifold::Impl& impl, namespace manifold { +static int circularSegments_ = DEFAULT_SEGMENTS; +static double circularAngle_ = DEFAULT_ANGLE; +static double circularEdgeLength_ = DEFAULT_LENGTH; + +/** + * Sets an angle constraint the default number of circular segments for the + * CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and + * Manifold::Revolve() constructors. The number of segments will be rounded up + * to the nearest factor of four. + * + * @param angle The minimum angle in degrees between consecutive segments. The + * angle will increase if the the segments hit the minimum edge length. + * Default is 10 degrees. + */ +void Quality::SetMinCircularAngle(double angle) { + if (angle <= 0) return; + circularAngle_ = angle; +} + +/** + * Sets a length constraint the default number of circular segments for the + * CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and + * Manifold::Revolve() constructors. The number of segments will be rounded up + * to the nearest factor of four. + * + * @param length The minimum length of segments. The length will + * increase if the the segments hit the minimum angle. Default is 1.0. + */ +void Quality::SetMinCircularEdgeLength(double length) { + if (length <= 0) return; + circularEdgeLength_ = length; +} + +/** + * Sets the default number of circular segments for the + * CrossSection::Circle(), Manifold::Cylinder(), Manifold::Sphere(), and + * Manifold::Revolve() constructors. Overrides the edge length and angle + * constraints and sets the number of segments to exactly this value. + * + * @param number Number of circular segments. Default is 0, meaning no + * constraint is applied. + */ +void Quality::SetCircularSegments(int number) { + if (number < 3 && number != 0) return; + circularSegments_ = number; +} + +/** + * Determine the result of the SetMinCircularAngle(), + * SetMinCircularEdgeLength(), and SetCircularSegments() defaults. + * + * @param radius For a given radius of circle, determine how many default + * segments there will be. + */ +int Quality::GetCircularSegments(double radius) { + if (circularSegments_ > 0) return circularSegments_; + int nSegA = 360.0 / circularAngle_; + int nSegL = 2.0 * radius * kPi / circularEdgeLength_; + int nSeg = fmin(nSegA, nSegL) + 3; + nSeg -= nSeg % 4; + return std::max(nSeg, 4); +} + +/** + * Resets the circular construction parameters to their defaults if + * SetMinCircularAngle, SetMinCircularEdgeLength, or SetCircularSegments have + * been called. + */ +void Quality::ResetToDefaults() { + circularSegments_ = DEFAULT_SEGMENTS; + circularAngle_ = DEFAULT_ANGLE; + circularEdgeLength_ = DEFAULT_LENGTH; +} + /** * Construct an empty Manifold. * diff --git a/thirdparty/manifold/src/properties.cpp b/thirdparty/manifold/src/properties.cpp index d66b05595db..b80d5af1a37 100644 --- a/thirdparty/manifold/src/properties.cpp +++ b/thirdparty/manifold/src/properties.cpp @@ -73,7 +73,13 @@ struct CheckHalfedges { bool operator()(size_t edge) const { const Halfedge halfedge = halfedges[edge]; - if (halfedge.startVert == -1 || halfedge.endVert == -1) return true; + if (halfedge.startVert == -1 && halfedge.endVert == -1 && + halfedge.pairedHalfedge == -1) + return true; + if (halfedges[NextHalfedge(edge)].startVert == -1 || + halfedges[NextHalfedge(NextHalfedge(edge))].startVert == -1) { + return false; + } if (halfedge.pairedHalfedge == -1) return false; const Halfedge paired = halfedges[halfedge.pairedHalfedge]; @@ -114,6 +120,7 @@ namespace manifold { */ bool Manifold::Impl::IsManifold() const { if (halfedge_.size() == 0) return true; + if (halfedge_.size() % 3 != 0) return false; return all_of(countAt(0_uz), countAt(halfedge_.size()), CheckHalfedges({halfedge_})); } diff --git a/thirdparty/manifold/src/quickhull.cpp b/thirdparty/manifold/src/quickhull.cpp index 54733d6807c..5860f4a0440 100644 --- a/thirdparty/manifold/src/quickhull.cpp +++ b/thirdparty/manifold/src/quickhull.cpp @@ -18,7 +18,9 @@ #include "quickhull.h" #include +#include #include +#include #include "impl.h" diff --git a/thirdparty/manifold/src/smoothing.cpp b/thirdparty/manifold/src/smoothing.cpp index bf8903dfb3b..3d275eba1b9 100644 --- a/thirdparty/manifold/src/smoothing.cpp +++ b/thirdparty/manifold/src/smoothing.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "impl.h" #include "parallel.h" diff --git a/thirdparty/manifold/src/sparse.h b/thirdparty/manifold/src/sparse.h deleted file mode 100644 index a25ea611412..00000000000 --- a/thirdparty/manifold/src/sparse.h +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright 2021 The Manifold Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once -#include "./parallel.h" -#include "./utils.h" -#include "./vec.h" -#include "manifold/common.h" -#include "manifold/optional_assert.h" - -namespace { -template -inline bool FirstFinite(T v) { - return std::isfinite(v[0]); -} - -template <> -inline bool FirstFinite(double v) { - return std::isfinite(v); -} -} // namespace - -namespace manifold { - -/** @ingroup Private */ -class SparseIndices { - // sparse indices where {p1: q1, p2: q2, ...} are laid out as - // p1 q1 p2 q2 or q1 p1 q2 p2, depending on endianness - // such that the indices are sorted by (p << 32) | q - public: -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ - defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || \ - defined(__AARCH64EB__) || defined(_MIBSEB) || defined(__MIBSEB) || \ - defined(__MIBSEB__) - static constexpr size_t pOffset = 0; -#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ - defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \ - defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \ - defined(__MIPSEL) || defined(__MIPSEL__) || defined(__EMSCRIPTEN__) || \ - defined(_WIN32) - static constexpr size_t pOffset = 1; -#else -#error "unknown architecture" -#endif - static constexpr int64_t EncodePQ(int p, int q) { - return (int64_t(p) << 32) | q; - } - - SparseIndices() = default; - SparseIndices(size_t size) { data_ = Vec(size * sizeof(int64_t)); } - - void Clear() { data_.clear(false); } - - void FromIndices(const std::vector& indices) { - std::vector sizes; - size_t total_size = 0; - for (const auto& ind : indices) { - sizes.push_back(total_size); - total_size += ind.data_.size(); - } - data_ = Vec(total_size); - for_each_n(ExecutionPolicy::Par, countAt(0), indices.size(), [&](size_t i) { - std::copy(indices[i].data_.begin(), indices[i].data_.end(), - data_.begin() + sizes[i]); - }); - } - - size_t size() const { return data_.size() / sizeof(int64_t); } - - Vec Copy(bool use_q) const { - Vec out(size()); - size_t offset = pOffset; - if (use_q) offset = 1 - offset; - const int* p = ptr(); - for_each(autoPolicy(out.size()), countAt(0_uz), countAt(out.size()), - [&](size_t i) { out[i] = p[i * 2 + offset]; }); - return out; - } - - void Sort() { - VecView view = AsVec64(); - stable_sort(view.begin(), view.end()); - } - - void Resize(size_t size) { data_.resize(size * sizeof(int64_t), -1); } - - inline int& Get(size_t i, bool use_q) { - if (use_q) - return ptr()[2 * i + 1 - pOffset]; - else - return ptr()[2 * i + pOffset]; - } - - inline int Get(size_t i, bool use_q) const { - if (use_q) - return ptr()[2 * i + 1 - pOffset]; - else - return ptr()[2 * i + pOffset]; - } - - inline int64_t GetPQ(size_t i) const { - VecView view = AsVec64(); - return view[i]; - } - - inline void Set(size_t i, int p, int q) { - VecView view = AsVec64(); - view[i] = EncodePQ(p, q); - } - - inline void SetPQ(size_t i, int64_t pq) { - VecView view = AsVec64(); - view[i] = pq; - } - - VecView AsVec64() { - return VecView(reinterpret_cast(data_.data()), - data_.size() / sizeof(int64_t)); - } - - VecView AsVec64() const { - return VecView( - reinterpret_cast(data_.data()), - data_.size() / sizeof(int64_t)); - } - - VecView AsVec32() { - return VecView(reinterpret_cast(data_.data()), - data_.size() / sizeof(int32_t)); - } - - VecView AsVec32() const { - return VecView( - reinterpret_cast(data_.data()), - data_.size() / sizeof(int32_t)); - } - - inline void Add(int p, int q, bool seq = false) { - data_.extend(sizeof(int64_t), seq); - Set(size() - 1, p, q); - } - - void Unique() { - Sort(); - VecView view = AsVec64(); - size_t newSize = unique(view.begin(), view.end()) - view.begin(); - Resize(newSize); - } - - size_t RemoveZeros(Vec& S) { - DEBUG_ASSERT(S.size() == size(), userErr, - "Different number of values than indicies!"); - - Vec new2Old(S.size()); - sequence(new2Old.begin(), new2Old.end()); - - size_t size = copy_if(countAt(0_uz), countAt(S.size()), new2Old.begin(), - [&S](const size_t i) { return S[i] != 0; }) - - new2Old.begin(); - new2Old.resize(size); - - Permute(S, new2Old); - Vec tmp(std::move(data_)); - Resize(size); - gather(new2Old.begin(), new2Old.end(), - reinterpret_cast(tmp.data()), - reinterpret_cast(data_.data())); - - return size; - } - - template - size_t KeepFinite(Vec& v, Vec& x) { - DEBUG_ASSERT(x.size() == size(), userErr, - "Different number of values than indicies!"); - - Vec new2Old(v.size()); - size_t size = copy_if(countAt(0_uz), countAt(v.size()), new2Old.begin(), - [&v](size_t i) { return FirstFinite(v[i]); }) - - new2Old.begin(); - new2Old.resize(size); - - Permute(v, new2Old); - Permute(x, new2Old); - Vec tmp(std::move(data_)); - Resize(size); - gather(new2Old.begin(), new2Old.end(), - reinterpret_cast(tmp.data()), - reinterpret_cast(data_.data())); - - return size; - } - -#ifdef MANIFOLD_DEBUG - void Dump() const { - std::cout << "SparseIndices = " << std::endl; - const int* p = ptr(); - for (size_t i = 0; i < size(); ++i) { - std::cout << i << ", p = " << Get(i, false) << ", q = " << Get(i, true) - << std::endl; - } - std::cout << std::endl; - } -#endif - - private: - Vec data_; - inline int* ptr() { return reinterpret_cast(data_.data()); } - inline const int* ptr() const { - return reinterpret_cast(data_.data()); - } -}; - -} // namespace manifold diff --git a/thirdparty/manifold/src/subdivision.cpp b/thirdparty/manifold/src/subdivision.cpp index 71fbd36338e..6aa855f6fdd 100644 --- a/thirdparty/manifold/src/subdivision.cpp +++ b/thirdparty/manifold/src/subdivision.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "impl.h" #include "parallel.h" diff --git a/thirdparty/manifold/src/vec.h b/thirdparty/manifold/src/vec.h index 282e559b8e8..fcb1e4f93cc 100644 --- a/thirdparty/manifold/src/vec.h +++ b/thirdparty/manifold/src/vec.h @@ -228,10 +228,14 @@ class Vec : public VecView { // Currently it is set to 64 pages (4kB page). constexpr size_t ASYNC_FREE_THRESHOLD = 1 << 18; TracyFreeS(ptr, 3); +#if defined(__has_feature) +#if !__has_feature(address_sanitizer) #if (MANIFOLD_PAR == 1) if (size * sizeof(T) > ASYNC_FREE_THRESHOLD) gc_arena.enqueue([ptr]() { free(ptr); }); else +#endif +#endif #endif free(ptr); }