diff options
author | Lukas Stockner <lukas.stockner@freenet.de> | 2022-10-30 00:41:21 +0300 |
---|---|---|
committer | Lukas Stockner <lukas.stockner@freenet.de> | 2022-10-30 01:14:59 +0300 |
commit | bc37e8d8399eef686b71341aa90eced9bc117786 (patch) | |
tree | 92e4af388150209df9bc44e2cba6f2f303aa7baf /source/blender/blenlib | |
parent | 552abb838c76d44a0d7d1226b59a1ab381e88386 (diff) | |
parent | d1d2f002c7caaf4ab457ec27bbc44666d7aac624 (diff) |
Merge remote-tracking branch 'origin/master' into principled-v2
Diffstat (limited to 'source/blender/blenlib')
166 files changed, 4292 insertions, 1805 deletions
diff --git a/source/blender/blenlib/BLI_allocator.hh b/source/blender/blenlib/BLI_allocator.hh index f19292fffd8..db3caf2eeb7 100644 --- a/source/blender/blenlib/BLI_allocator.hh +++ b/source/blender/blenlib/BLI_allocator.hh @@ -63,15 +63,14 @@ class RawAllocator { }; public: - void *allocate(size_t size, size_t alignment, const char *UNUSED(name)) + void *allocate(size_t size, size_t alignment, const char * /*name*/) { - BLI_assert(is_power_of_2_i(static_cast<int>(alignment))); + BLI_assert(is_power_of_2_i(int(alignment))); void *ptr = malloc(size + alignment + sizeof(MemHead)); void *used_ptr = reinterpret_cast<void *>( - reinterpret_cast<uintptr_t>(POINTER_OFFSET(ptr, alignment + sizeof(MemHead))) & - ~(static_cast<uintptr_t>(alignment) - 1)); - int offset = static_cast<int>((intptr_t)used_ptr - (intptr_t)ptr); - BLI_assert(offset >= static_cast<int>(sizeof(MemHead))); + uintptr_t(POINTER_OFFSET(ptr, alignment + sizeof(MemHead))) & ~(uintptr_t(alignment) - 1)); + int offset = int(intptr_t(used_ptr) - intptr_t(ptr)); + BLI_assert(offset >= int(sizeof(MemHead))); (static_cast<MemHead *>(used_ptr) - 1)->offset = offset; return used_ptr; } diff --git a/source/blender/blenlib/BLI_any.hh b/source/blender/blenlib/BLI_any.hh index a20239f214f..df67a090e92 100644 --- a/source/blender/blenlib/BLI_any.hh +++ b/source/blender/blenlib/BLI_any.hh @@ -39,15 +39,16 @@ template<typename ExtraInfo> struct AnyTypeInfo { * Used when #T is stored directly in the inline buffer of the #Any. */ template<typename ExtraInfo, typename T> -static constexpr AnyTypeInfo<ExtraInfo> info_for_inline = { +inline constexpr AnyTypeInfo<ExtraInfo> info_for_inline = { is_trivially_copy_constructible_extended_v<T> ? nullptr : - +[](void *dst, const void *src) { new (dst) T(*(const T *)src); }, + +[](void *dst, const void *src) { new (dst) T(*static_cast<const T *>(src)); }, is_trivially_move_constructible_extended_v<T> ? nullptr : - +[](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); }, - is_trivially_destructible_extended_v<T> ? nullptr : - +[](void *src) { std::destroy_at(((T *)src)); }, + +[](void *dst, void *src) { new (dst) T(std::move(*static_cast<T *>(src))); }, + is_trivially_destructible_extended_v<T> ? + nullptr : + +[](void *src) { std::destroy_at((static_cast<T *>(src))); }, nullptr, ExtraInfo::template get<T>()}; @@ -57,7 +58,7 @@ static constexpr AnyTypeInfo<ExtraInfo> info_for_inline = { */ template<typename T> using Ptr = std::unique_ptr<T>; template<typename ExtraInfo, typename T> -static constexpr AnyTypeInfo<ExtraInfo> info_for_unique_ptr = { +inline constexpr AnyTypeInfo<ExtraInfo> info_for_unique_ptr = { [](void *dst, const void *src) { new (dst) Ptr<T>(new T(**(const Ptr<T> *)src)); }, [](void *dst, void *src) { new (dst) Ptr<T>(new T(std::move(**(Ptr<T> *)src))); }, [](void *src) { std::destroy_at((Ptr<T> *)src); }, diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh index 813277d9968..200381048c9 100644 --- a/source/blender/blenlib/BLI_array.hh +++ b/source/blender/blenlib/BLI_array.hh @@ -424,8 +424,7 @@ class Array { T *allocate(int64_t size) { - return static_cast<T *>( - allocator_.allocate(static_cast<size_t>(size) * sizeof(T), alignof(T), AT)); + return static_cast<T *>(allocator_.allocate(size_t(size) * sizeof(T), alignof(T), AT)); } void deallocate_if_not_inline(T *ptr) diff --git a/source/blender/blenlib/BLI_array_store.h b/source/blender/blenlib/BLI_array_store.h index 8a91825da6f..c04c392627d 100644 --- a/source/blender/blenlib/BLI_array_store.h +++ b/source/blender/blenlib/BLI_array_store.h @@ -57,7 +57,6 @@ size_t BLI_array_store_calc_size_expanded_get(const BArrayStore *bs); size_t BLI_array_store_calc_size_compacted_get(const BArrayStore *bs); /** - * * \param data: Data used to create * \param state_reference: The state to use as a reference when adding the new state, * typically this is the previous state, diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh new file mode 100644 index 00000000000..264ac00e034 --- /dev/null +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BLI_generic_span.hh" +#include "BLI_generic_virtual_array.hh" +#include "BLI_index_mask.hh" +#include "BLI_task.hh" +#include "BLI_virtual_array.hh" + +namespace blender::array_utils { + +/** + * Fill the destination span by copying masked values from the `src` array. Threaded based on + * grain-size. + */ +void copy(const GVArray &src, IndexMask selection, GMutableSpan dst, int64_t grain_size = 4096); + +/** + * Fill the destination span by copying values from the `src` array. Threaded based on + * grain-size. + */ +template<typename T> +inline void copy(const Span<T> src, + const IndexMask selection, + MutableSpan<T> dst, + const int64_t grain_size = 4096) +{ + BLI_assert(src.size() == dst.size()); + threading::parallel_for(selection.index_range(), grain_size, [&](const IndexRange range) { + for (const int64_t index : selection.slice(range)) { + dst[index] = src[index]; + } + }); +} + +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +void gather(const GVArray &src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096); + +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +void gather(GSpan src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096); + +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +template<typename T> +inline void gather(const VArray<T> &src, + const IndexMask indices, + MutableSpan<T> dst, + const int64_t grain_size = 4096) +{ + BLI_assert(indices.size() == dst.size()); + threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) { + src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data()); + }); +} + +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +template<typename T, typename IndexT> +inline void gather(const Span<T> src, + const IndexMask indices, + MutableSpan<T> dst, + const int64_t grain_size = 4096) +{ + BLI_assert(indices.size() == dst.size()); + threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) { + for (const int64_t i : range) { + dst[i] = src[indices[i]]; + } + }); +} + +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +template<typename T, typename IndexT> +inline void gather(const Span<T> src, + const Span<IndexT> indices, + MutableSpan<T> dst, + const int64_t grain_size = 4096) +{ + BLI_assert(indices.size() == dst.size()); + threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) { + for (const int64_t i : range) { + dst[i] = src[indices[i]]; + } + }); +} + +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +template<typename T, typename IndexT> +inline void gather(const VArray<T> &src, + const Span<IndexT> indices, + MutableSpan<T> dst, + const int64_t grain_size = 4096) +{ + BLI_assert(indices.size() == dst.size()); + devirtualize_varray(src, [&](const auto &src) { + threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) { + for (const int64_t i : range) { + dst[i] = src[indices[i]]; + } + }); + }); +} + +} // namespace blender::array_utils diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h index 4a7fae6e98c..4292620e462 100644 --- a/source/blender/blenlib/BLI_assert.h +++ b/source/blender/blenlib/BLI_assert.h @@ -67,7 +67,7 @@ void _BLI_assert_unreachable_print(const char *file, int line, const char *funct # define BLI_STATIC_ASSERT(a, msg) static_assert(a, msg); #elif defined(_MSC_VER) /* Visual Studio */ -# if (_MSC_VER > 1910) && !defined(__clang__) +# if !defined(__clang__) # define BLI_STATIC_ASSERT(a, msg) static_assert(a, msg); # else # define BLI_STATIC_ASSERT(a, msg) _STATIC_ASSERT(a); diff --git a/source/blender/blenlib/BLI_bit_vector.hh b/source/blender/blenlib/BLI_bit_vector.hh new file mode 100644 index 00000000000..ca6c6b2cd2a --- /dev/null +++ b/source/blender/blenlib/BLI_bit_vector.hh @@ -0,0 +1,529 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * A `blender::BitVector` is a dynamically growing contiguous arrays of bits. Its main purpose is + * to provide a compact way to map indices to bools. It requires 8 times less memory compared to a + * `blender::Vector<bool>`. + * + * Advantages of using a bit- instead of byte-vector are: + * - Uses less memory. + * - Allows checking the state of many elements at the same time (8 times more bits than bytes fit + * into a CPU register). This can improve performance. + * + * The compact nature of storing bools in individual bits has some downsides that have to be kept + * in mind: + * - Writing to separate bits in the same byte is not thread-safe. Therefore, an existing vector of + * bool can't easily be replaced with a bit vector, if it is written to from multiple threads. + * Read-only access from multiple threads is fine though. + * - Writing individual elements is more expensive when the array is in cache already. That is + * because changing a bit is always a read-modify-write operation on the byte the bit resides in. + * - Reading individual elements is more expensive when the array is in cache already. That is + * because additional bit-wise operations have to be applied after the corresponding byte is + * read. + * + * Comparison to `std::vector<bool>`: + * - `blender::BitVector` has an interface that is more optimized for dealing with bits. + * - `blender::BitVector` has an inline buffer that is used to avoid allocations when the vector is + * small. + * + * Comparison to `BLI_bitmap`: + * - `blender::BitVector` offers a more C++ friendly interface. + * - `BLI_bitmap` should only be used in C code that can not use `blender::BitVector`. + */ + +#include <cstring> + +#include "BLI_allocator.hh" +#include "BLI_index_range.hh" +#include "BLI_memory_utils.hh" +#include "BLI_span.hh" + +namespace blender { + +/** + * This is a read-only pointer to a specific bit. The value of the bit can be retrieved, but not + * changed. + */ +class BitRef { + private: + /** Points to the exact byte that the bit is in. */ + const uint8_t *byte_ptr_; + /** All zeros except for a single one at the bit that is referenced. */ + uint8_t mask_; + + friend class MutableBitRef; + + public: + BitRef() = default; + + /** + * Reference a specific bit in a byte array. Note that #byte_ptr does *not* have to point to the + * exact byte the bit is in. + */ + BitRef(const uint8_t *byte_ptr, const int64_t bit_index) + { + byte_ptr_ = byte_ptr + (bit_index >> 3); + mask_ = 1 << (bit_index & 7); + } + + /** + * Return true when the bit is currently 1 and false otherwise. + */ + bool test() const + { + const uint8_t byte = *byte_ptr_; + const uint8_t masked_byte = byte & mask_; + return masked_byte != 0; + } + + operator bool() const + { + return this->test(); + } +}; + +/** + * Similar to #BitRef, but also allows changing the referenced bit. + */ +class MutableBitRef { + private: + /** Points to the exact byte that the bit is in. */ + uint8_t *byte_ptr_; + /** All zeros except for a single one at the bit that is referenced. */ + uint8_t mask_; + + public: + MutableBitRef() = default; + + /** + * Reference a specific bit in a byte array. Note that #byte_ptr does *not* have to point to the + * exact byte the bit is in. + */ + MutableBitRef(uint8_t *byte_ptr, const int64_t bit_index) + { + byte_ptr_ = byte_ptr + (bit_index >> 3); + mask_ = 1 << uint8_t(bit_index & 7); + } + + /** + * Support implicitly casting to a read-only #BitRef. + */ + operator BitRef() const + { + BitRef bit_ref; + bit_ref.byte_ptr_ = byte_ptr_; + bit_ref.mask_ = mask_; + return bit_ref; + } + + /** + * Return true when the bit is currently 1 and false otherwise. + */ + bool test() const + { + const uint8_t byte = *byte_ptr_; + const uint8_t masked_byte = byte & mask_; + return masked_byte != 0; + } + + operator bool() const + { + return this->test(); + } + + /** + * Change the bit to a 1. + */ + void set() + { + *byte_ptr_ |= mask_; + } + + /** + * Change the bit to a 0. + */ + void reset() + { + *byte_ptr_ &= ~mask_; + } + + /** + * Change the bit to a 1 if #value is true and 0 otherwise. + */ + void set(const bool value) + { + if (value) { + this->set(); + } + else { + this->reset(); + } + } +}; + +template< + /** + * Number of bits that can be stored in the vector without doing an allocation. + */ + int64_t InlineBufferCapacity = 32, + /** + * The allocator used by this vector. Should rarely be changed, except when you don't want that + * MEM_* is used internally. + */ + typename Allocator = GuardedAllocator> +class BitVector { + private: + static constexpr int64_t required_bytes_for_bits(const int64_t number_of_bits) + { + return (number_of_bits + BitsPerByte - 1) / BitsPerByte; + } + + static constexpr int64_t BitsPerByte = 8; + static constexpr int64_t BytesInInlineBuffer = required_bytes_for_bits(InlineBufferCapacity); + static constexpr int64_t BitsInInlineBuffer = BytesInInlineBuffer * BitsPerByte; + static constexpr int64_t AllocationAlignment = 8; + + /** + * Points to the first byte used by the vector. It might point to the memory in the inline + * buffer. + */ + uint8_t *data_; + + /** Current size of the vector in bits. */ + int64_t size_in_bits_; + + /** Number of bits that fit into the vector until a reallocation has to occur. */ + int64_t capacity_in_bits_; + + /** Used for allocations when the inline buffer is too small. */ + Allocator allocator_; + + /** Contains the bits as long as the vector is small enough. */ + TypedBuffer<uint8_t, BytesInInlineBuffer> inline_buffer_; + + public: + BitVector(Allocator allocator = {}) noexcept : allocator_(allocator) + { + data_ = inline_buffer_; + size_in_bits_ = 0; + capacity_in_bits_ = BitsInInlineBuffer; + uninitialized_fill_n(data_, BytesInInlineBuffer, uint8_t(0)); + } + + BitVector(NoExceptConstructor, Allocator allocator = {}) noexcept : BitVector(allocator) + { + } + + BitVector(const BitVector &other) : BitVector(NoExceptConstructor(), other.allocator_) + { + const int64_t bytes_to_copy = other.used_bytes_amount(); + if (other.size_in_bits_ <= BitsInInlineBuffer) { + /* The data is copied into the owned inline buffer. */ + data_ = inline_buffer_; + capacity_in_bits_ = BitsInInlineBuffer; + } + else { + /* Allocate a new byte array because the inline buffer is too small. */ + data_ = static_cast<uint8_t *>( + allocator_.allocate(bytes_to_copy, AllocationAlignment, __func__)); + capacity_in_bits_ = bytes_to_copy * BitsPerByte; + } + size_in_bits_ = other.size_in_bits_; + uninitialized_copy_n(other.data_, bytes_to_copy, data_); + } + + BitVector(BitVector &&other) noexcept : BitVector(NoExceptConstructor(), other.allocator_) + { + if (other.is_inline()) { + /* Copy the data into the inline buffer. */ + const int64_t bytes_to_copy = other.used_bytes_amount(); + data_ = inline_buffer_; + uninitialized_copy_n(other.data_, bytes_to_copy, data_); + } + else { + /* Steal the pointer. */ + data_ = other.data_; + } + size_in_bits_ = other.size_in_bits_; + capacity_in_bits_ = other.capacity_in_bits_; + + /* Clear the other vector because it has been moved from. */ + other.data_ = other.inline_buffer_; + other.size_in_bits_ = 0; + other.capacity_in_bits_ = BitsInInlineBuffer; + } + + /** + * Create a new vector with the given size and fill it with #value. + */ + BitVector(const int64_t size_in_bits, const bool value = false, Allocator allocator = {}) + : BitVector(NoExceptConstructor(), allocator) + { + this->resize(size_in_bits, value); + } + + /** + * Create a bit vector based on an array of bools. Each byte of the input array maps to one bit. + */ + explicit BitVector(const Span<bool> values, Allocator allocator = {}) + : BitVector(NoExceptConstructor(), allocator) + { + this->resize(values.size()); + for (const int64_t i : this->index_range()) { + (*this)[i].set(values[i]); + } + } + + ~BitVector() + { + if (!this->is_inline()) { + allocator_.deallocate(data_); + } + } + + BitVector &operator=(const BitVector &other) + { + return copy_assign_container(*this, other); + } + + BitVector &operator=(BitVector &&other) + { + return move_assign_container(*this, std::move(other)); + } + + /** + * Number of bits in the bit vector. + */ + int64_t size() const + { + return size_in_bits_; + } + + /** + * Get a read-only reference to a specific bit. + */ + BitRef operator[](const int64_t index) const + { + BLI_assert(index >= 0); + BLI_assert(index < size_in_bits_); + return {data_, index}; + } + + /** + * Get a mutable reference to a specific bit. + */ + MutableBitRef operator[](const int64_t index) + { + BLI_assert(index >= 0); + BLI_assert(index < size_in_bits_); + return {data_, index}; + } + + IndexRange index_range() const + { + return {0, size_in_bits_}; + } + + /** + * Add a new bit to the end of the vector. + */ + void append(const bool value) + { + this->ensure_space_for_one(); + MutableBitRef bit{data_, size_in_bits_}; + bit.set(value); + size_in_bits_++; + } + + class Iterator { + private: + const BitVector *vector_; + int64_t index_; + + public: + Iterator(const BitVector &vector, const int64_t index) : vector_(&vector), index_(index) + { + } + + Iterator &operator++() + { + index_++; + return *this; + } + + friend bool operator!=(const Iterator &a, const Iterator &b) + { + BLI_assert(a.vector_ == b.vector_); + return a.index_ != b.index_; + } + + BitRef operator*() const + { + return (*vector_)[index_]; + } + }; + + class MutableIterator { + private: + BitVector *vector_; + int64_t index_; + + public: + MutableIterator(BitVector &vector, const int64_t index) : vector_(&vector), index_(index) + { + } + + MutableIterator &operator++() + { + index_++; + return *this; + } + + friend bool operator!=(const MutableIterator &a, const MutableIterator &b) + { + BLI_assert(a.vector_ == b.vector_); + return a.index_ != b.index_; + } + + MutableBitRef operator*() const + { + return (*vector_)[index_]; + } + }; + + Iterator begin() const + { + return {*this, 0}; + } + + Iterator end() const + { + return {*this, size_in_bits_}; + } + + MutableIterator begin() + { + return {*this, 0}; + } + + MutableIterator end() + { + return {*this, size_in_bits_}; + } + + /** + * Change the size of the vector. If the new vector is larger than the old one, the new elements + * are filled with #value. + */ + void resize(const int64_t new_size_in_bits, const bool value = false) + { + BLI_assert(new_size_in_bits >= 0); + const int64_t old_size_in_bits = size_in_bits_; + if (new_size_in_bits > old_size_in_bits) { + this->reserve(new_size_in_bits); + } + size_in_bits_ = new_size_in_bits; + if (old_size_in_bits < new_size_in_bits) { + this->fill_range(IndexRange(old_size_in_bits, new_size_in_bits - old_size_in_bits), value); + } + } + + /** + * Set #value for every element in #range. + */ + void fill_range(const IndexRange range, const bool value) + { + const AlignedIndexRanges aligned_ranges = split_index_range_by_alignment(range, BitsPerByte); + + /* Fill first few bits. */ + for (const int64_t i : aligned_ranges.prefix) { + (*this)[i].set(value); + } + + /* Fill entire bytes at once. */ + const int64_t start_fill_byte_index = aligned_ranges.aligned.start() / BitsPerByte; + const int64_t bytes_to_fill = aligned_ranges.aligned.size() / BitsPerByte; + const uint8_t fill_value = value ? uint8_t(0xff) : uint8_t(0x00); + initialized_fill_n(data_ + start_fill_byte_index, bytes_to_fill, fill_value); + + /* Fill bits in the end that don't cover a full byte. */ + for (const int64_t i : aligned_ranges.suffix) { + (*this)[i].set(value); + } + } + + /** + * Set #value on every element. + */ + void fill(const bool value) + { + this->fill_range(IndexRange(0, size_in_bits_), value); + } + + /** + * Make sure that the capacity of the vector is large enough to hold the given amount of bits. + * The actual size is not changed. + */ + void reserve(const int new_capacity_in_bits) + { + this->realloc_to_at_least(new_capacity_in_bits); + } + + private: + void ensure_space_for_one() + { + if (UNLIKELY(size_in_bits_ >= capacity_in_bits_)) { + this->realloc_to_at_least(size_in_bits_ + 1); + } + } + + BLI_NOINLINE void realloc_to_at_least(const int64_t min_capacity_in_bits, + const uint8_t initial_value_for_new_bytes = 0x00) + { + if (capacity_in_bits_ >= min_capacity_in_bits) { + return; + } + + const int64_t min_capacity_in_bytes = this->required_bytes_for_bits(min_capacity_in_bits); + + /* At least double the size of the previous allocation. */ + const int64_t min_new_capacity_in_bytes = capacity_in_bits_ * 2; + + const int64_t new_capacity_in_bytes = std::max(min_capacity_in_bytes, + min_new_capacity_in_bytes); + const int64_t bytes_to_copy = this->used_bytes_amount(); + + uint8_t *new_data = static_cast<uint8_t *>( + allocator_.allocate(new_capacity_in_bytes, AllocationAlignment, __func__)); + uninitialized_copy_n(data_, bytes_to_copy, new_data); + /* Always initialize new capacity even if it isn't used yet. That's necessary to avoid warnings + * caused by using uninitialized memory. This happens when e.g. setting a clearing a bit in an + * uninitialized byte. */ + uninitialized_fill_n(new_data + bytes_to_copy, + new_capacity_in_bytes - bytes_to_copy, + uint8_t(initial_value_for_new_bytes)); + + if (!this->is_inline()) { + allocator_.deallocate(data_); + } + + data_ = new_data; + capacity_in_bits_ = new_capacity_in_bytes * BitsPerByte; + } + + bool is_inline() const + { + return data_ == inline_buffer_; + } + + int64_t used_bytes_amount() const + { + return this->required_bytes_for_bits(size_in_bits_); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_compiler_attrs.h b/source/blender/blenlib/BLI_compiler_attrs.h index 99f0aa9f049..f0566e0b3e2 100644 --- a/source/blender/blenlib/BLI_compiler_attrs.h +++ b/source/blender/blenlib/BLI_compiler_attrs.h @@ -25,7 +25,7 @@ #endif /* never returns NULL */ -#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 /* gcc4.9+ only */ +#ifdef __GNUC__ # define ATTR_RETURNS_NONNULL __attribute__((returns_nonnull)) #else # define ATTR_RETURNS_NONNULL @@ -39,14 +39,14 @@ #endif /* hint to treat any non-null function return value cannot alias any other pointer */ -#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) +#ifdef __GNUC__ # define ATTR_MALLOC __attribute__((malloc)) #else # define ATTR_MALLOC #endif /* the function return value points to memory (2 args for 'size * tot') */ -#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) +#if defined(__GNUC__) && !defined(__clang__) # define ATTR_ALLOC_SIZE(args...) __attribute__((alloc_size(args))) #else # define ATTR_ALLOC_SIZE(...) @@ -69,7 +69,7 @@ /* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */ #ifndef ATTR_FALLTHROUGH -# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */ +# ifdef __GNUC__ # define ATTR_FALLTHROUGH __attribute__((fallthrough)) # else # define ATTR_FALLTHROUGH ((void)0) diff --git a/source/blender/blenlib/BLI_compute_context.hh b/source/blender/blenlib/BLI_compute_context.hh new file mode 100644 index 00000000000..e3e5b6f9e85 --- /dev/null +++ b/source/blender/blenlib/BLI_compute_context.hh @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * When logging computed values, we generally want to know where the value was computed. For + * example, geometry nodes logs socket values so that they can be displayed in the ui. For that we + * can combine the logged value with a `ComputeContext`, which identifies the place where the value + * was computed. + * + * This is not a trivial problem because e.g. just storing a pointer to the socket a value + * belongs to is not enough. That's because the same socket may correspond to many different values + * when the socket is used in a node group that is used multiple times. In this case, not only does + * the socket have to be stored but also the entire nested node group path that led to the + * evaluation of the socket. + * + * Storing the entire "context path" for every logged value is not feasible, because that path can + * become quite long. So that would need much more memory, more compute overhead and makes it + * complicated to compare if two contexts are the same. If the identifier for a compute context + * would have a variable size, it would also be much harder to create a map from context to values. + * + * The solution implemented below uses the following key ideas: + * - Every compute context can be hashed to a unique fixed size value (`ComputeContextHash`). While + * technically there could be hash collisions, the hashing algorithm has to be chosen to make + * that practically impossible. This way an entire context path, possibly consisting of many + * nested contexts, is represented by a single value that can be stored easily. + * - A nested compute context is build as singly linked list, where every compute context has a + * pointer to the parent compute context. Note that a link in the other direction is not possible + * because the same parent compute context may be used by many different children which possibly + * run on different threads. + */ + +#include "BLI_array.hh" +#include "BLI_linear_allocator.hh" +#include "BLI_stack.hh" +#include "BLI_string_ref.hh" + +namespace blender { + +/** + * A hash that uniquely identifies a specific (non-fixed-size) compute context. The hash has to + * have enough bits to make collisions practically impossible. + */ +struct ComputeContextHash { + static constexpr int64_t HashSizeInBytes = 16; + uint64_t v1 = 0; + uint64_t v2 = 0; + + uint64_t hash() const + { + return v1; + } + + friend bool operator==(const ComputeContextHash &a, const ComputeContextHash &b) + { + return a.v1 == b.v1 && a.v2 == b.v2; + } + + void mix_in(const void *data, int64_t len); + + friend std::ostream &operator<<(std::ostream &stream, const ComputeContextHash &hash); +}; + +static_assert(sizeof(ComputeContextHash) == ComputeContextHash::HashSizeInBytes); + +/** + * Identifies the context in which a computation happens. This context can be used to identify + * values logged during the computation. For more details, see the comment at the top of the file. + * + * This class should be subclassed to implement specific contexts. + */ +class ComputeContext { + private: + /** + * Only used for debugging currently. + */ + const char *static_type_; + /** + * Pointer to the context that this context is child of. That allows nesting compute contexts. + */ + const ComputeContext *parent_ = nullptr; + + protected: + /** + * The hash that uniquely identifies this context. It's a combined hash of this context as well + * as all the parent contexts. + */ + ComputeContextHash hash_; + + public: + ComputeContext(const char *static_type, const ComputeContext *parent) + : static_type_(static_type), parent_(parent) + { + if (parent != nullptr) { + hash_ = parent_->hash_; + } + } + virtual ~ComputeContext() = default; + + const ComputeContextHash &hash() const + { + return hash_; + } + + const char *static_type() const + { + return static_type_; + } + + const ComputeContext *parent() const + { + return parent_; + } + + /** + * Print the entire nested context stack. + */ + void print_stack(std::ostream &stream, StringRef name) const; + + /** + * Print information about this specific context. This has to be implemented by each subclass. + */ + virtual void print_current_in_line(std::ostream &stream) const = 0; + + friend std::ostream &operator<<(std::ostream &stream, const ComputeContext &compute_context); +}; + +/** + * Utility class to build a context stack in one place. This is typically used to get the hash that + * corresponds to a specific nested compute context, in order to look up corresponding logged + * values. + */ +class ComputeContextBuilder { + private: + LinearAllocator<> allocator_; + Stack<destruct_ptr<ComputeContext>> contexts_; + + public: + bool is_empty() const + { + return contexts_.is_empty(); + } + + const ComputeContext *current() const + { + if (contexts_.is_empty()) { + return nullptr; + } + return contexts_.peek().get(); + } + + const ComputeContextHash hash() const + { + BLI_assert(!contexts_.is_empty()); + return this->current()->hash(); + } + + template<typename T, typename... Args> void push(Args &&...args) + { + const ComputeContext *current = this->current(); + destruct_ptr<T> context = allocator_.construct<T>(current, std::forward<Args>(args)...); + contexts_.push(std::move(context)); + } + + void pop() + { + contexts_.pop(); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_convexhull_2d.h b/source/blender/blenlib/BLI_convexhull_2d.h index 0b4c3d486fb..044c1da6925 100644 --- a/source/blender/blenlib/BLI_convexhull_2d.h +++ b/source/blender/blenlib/BLI_convexhull_2d.h @@ -11,43 +11,26 @@ extern "C" { #endif /** - * A.M. Andrew's monotone chain 2D convex hull algorithm. - * - * \param points: An array of 2D points presorted by increasing x and y-coords. - * \param n: The number of points in points. - * \param r_points: An array of the convex hull vertex indices (max is n). - * \returns the number of points in r_points. - */ -int BLI_convexhull_2d_sorted(const float (*points)[2], int n, int r_points[]); -/** - * A.M. Andrew's monotone chain 2D convex hull algorithm. + * Extract 2D convex hull. * * \param points: An array of 2D points. * \param n: The number of points in points. * \param r_points: An array of the convex hull vertex indices (max is n). - * _must_ be allocated as `n * 2` because of how its used internally, - * even though the final result will be no more than \a n in size. - * \returns the number of points in r_points. - */ -int BLI_convexhull_2d(const float (*points)[2], int n, int r_points[]); - -/** - * \return The best angle for fitting the convex hull to an axis aligned bounding box. - * - * Intended to be used with #BLI_convexhull_2d + * \return The number of indices in r_points. * - * \param points_hull: Ordered hull points - * (result of #BLI_convexhull_2d mapped to a contiguous array). + * \note Performance is `O(n.log(n))`, same as `qsort`. * - * \note we could return the index of the best edge too if its needed. */ -float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n); +int BLI_convexhull_2d(const float (*points)[2], int n, int r_points[/* n */]); + /** - * Wrap #BLI_convexhull_aabb_fit_hull_2d and do the convex hull calculation. + * \return The best angle for fitting the points to an axis aligned bounding box. + * + * \note We could return the index of the best edge too if its needed. * - * \param points: arbitrary 2d points. + * \param points: Arbitrary 2d points. */ -float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n); +float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], int n); #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_cpp_type.hh b/source/blender/blenlib/BLI_cpp_type.hh index cc48b456da7..568ccbb5a64 100644 --- a/source/blender/blenlib/BLI_cpp_type.hh +++ b/source/blender/blenlib/BLI_cpp_type.hh @@ -20,7 +20,7 @@ * cost of longer compile time, a larger binary and the complexity that comes from using * templates). * - If the code is not performance sensitive, it usually makes sense to use #CPPType instead. - * - Sometimes a combination can make sense. Optimized code can be be generated at compile-time for + * - Sometimes a combination can make sense. Optimized code can be generated at compile-time for * some types, while there is a fallback code path using #CPPType for all other types. * #CPPType::to_static_type allows dispatching between both versions based on the type. * @@ -297,7 +297,7 @@ class CPPType : NonCopyable, NonMovable { */ bool pointer_has_valid_alignment(const void *ptr) const { - return ((uintptr_t)ptr & alignment_mask_) == 0; + return (uintptr_t(ptr) & alignment_mask_) == 0; } bool pointer_can_point_to_instance(const void *ptr) const diff --git a/source/blender/blenlib/BLI_cpp_type_make.hh b/source/blender/blenlib/BLI_cpp_type_make.hh index b0dbbff7ca8..1f494624821 100644 --- a/source/blender/blenlib/BLI_cpp_type_make.hh +++ b/source/blender/blenlib/BLI_cpp_type_make.hh @@ -211,8 +211,8 @@ CPPType::CPPType(CPPTypeParam<T, Flags> /* unused */, StringRef debug_name) using namespace cpp_type_util; debug_name_ = debug_name; - size_ = (int64_t)sizeof(T); - alignment_ = (int64_t)alignof(T); + size_ = int64_t(sizeof(T)); + alignment_ = int64_t(alignof(T)); is_trivial_ = std::is_trivial_v<T>; is_trivially_destructible_ = std::is_trivially_destructible_v<T>; if constexpr (std::is_default_constructible_v<T>) { @@ -221,7 +221,7 @@ CPPType::CPPType(CPPTypeParam<T, Flags> /* unused */, StringRef debug_name) value_initialize_ = value_initialize_cb<T>; value_initialize_indices_ = value_initialize_indices_cb<T>; static T default_value; - default_value_ = (void *)&default_value; + default_value_ = &default_value; } if constexpr (std::is_destructible_v<T>) { destruct_ = destruct_cb<T>; @@ -271,7 +271,7 @@ CPPType::CPPType(CPPTypeParam<T, Flags> /* unused */, StringRef debug_name) is_equal_ = is_equal_cb<T>; } - alignment_mask_ = (uintptr_t)alignment_ - (uintptr_t)1; + alignment_mask_ = uintptr_t(alignment_) - uintptr_t(1); has_special_member_functions_ = (default_construct_ && copy_construct_ && copy_assign_ && move_construct_ && move_assign_ && destruct_); } diff --git a/source/blender/blenlib/BLI_dot_export.hh b/source/blender/blenlib/BLI_dot_export.hh index b6decca0720..454f3c8412c 100644 --- a/source/blender/blenlib/BLI_dot_export.hh +++ b/source/blender/blenlib/BLI_dot_export.hh @@ -98,7 +98,7 @@ class Cluster { std::string name() const { - return "cluster_" + std::to_string((uintptr_t)this); + return "cluster_" + std::to_string(uintptr_t(this)); } void set_parent_cluster(Cluster *new_parent); diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h index ce44348d4dd..32cb0f234f2 100644 --- a/source/blender/blenlib/BLI_endian_switch_inline.h +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -26,7 +26,7 @@ BLI_INLINE void BLI_endian_switch_int16(short *val) } BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) { -#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 408)) /* gcc4.8+ only */ +#ifdef __GNUC__ *val = __builtin_bswap16(*val); #else unsigned short tval = *val; diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 063e60ecf03..0ff75ca16e5 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -101,6 +101,7 @@ typedef enum eFileAttributes { FILE_ATTR_MOUNT_POINT = 1 << 14, /* Volume mounted as a folder. */ FILE_ATTR_HARDLINK = 1 << 15, /* Duplicated directory entry. */ } eFileAttributes; +ENUM_OPERATORS(eFileAttributes, FILE_ATTR_HARDLINK); #define FILE_ATTR_ANY_LINK \ (FILE_ATTR_ALIAS | FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYMLINK | FILE_ATTR_JUNCTION_POINT | \ diff --git a/source/blender/blenlib/BLI_float3x3.hh b/source/blender/blenlib/BLI_float3x3.hh index 6a9e7dd04f0..178973c155d 100644 --- a/source/blender/blenlib/BLI_float3x3.hh +++ b/source/blender/blenlib/BLI_float3x3.hh @@ -63,6 +63,15 @@ struct float3x3 { return result; } + static float3x3 from_scale(const float2 scale) + { + float3x3 result = zero(); + result.values[0][0] = scale.x; + result.values[1][1] = scale.y; + result.values[2][2] = 1.0f; + return result; + } + static float3x3 from_translation_rotation_scale(const float2 translation, float rotation, const float2 scale) @@ -190,6 +199,13 @@ struct float3x3 { return result; } + float2 scale_2d() const + { + float2 scale; + mat3_to_size_2d(scale, values); + return scale; + } + friend bool operator==(const float3x3 &a, const float3x3 &b) { return equals_m3m3(a.values, b.values); diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh index 64e6e68432f..ca0d9ea0028 100644 --- a/source/blender/blenlib/BLI_float4x4.hh +++ b/source/blender/blenlib/BLI_float4x4.hh @@ -266,7 +266,7 @@ struct float4x4 { for (int j = 0; j < 4; j++) { snprintf(fchar, sizeof(fchar), "%11.6f", mat[j][i]); stream << fchar; - if (i != 3) { + if (j != 3) { stream << ", "; } } diff --git a/source/blender/blenlib/BLI_function_ref.hh b/source/blender/blenlib/BLI_function_ref.hh index 5f18e994991..bc386322c5d 100644 --- a/source/blender/blenlib/BLI_function_ref.hh +++ b/source/blender/blenlib/BLI_function_ref.hh @@ -63,7 +63,6 @@ * * void some_function(FunctionRef<int()> f); * some_function([]() { return 0; }); - * */ #include "BLI_memory_utils.hh" @@ -117,7 +116,7 @@ template<typename Ret, typename... Params> class FunctionRef<Ret(Params...)> { !std::is_same_v<std::remove_cv_t<std::remove_reference_t<Callable>>, FunctionRef>))> FunctionRef(Callable &&callable) : callback_(callback_fn<typename std::remove_reference_t<Callable>>), - callable_(reinterpret_cast<intptr_t>(&callable)) + callable_(intptr_t(&callable)) { } diff --git a/source/blender/blenlib/BLI_generic_array.hh b/source/blender/blenlib/BLI_generic_array.hh index 4b917434264..03dc8814309 100644 --- a/source/blender/blenlib/BLI_generic_array.hh +++ b/source/blender/blenlib/BLI_generic_array.hh @@ -231,7 +231,9 @@ class GArray { this->deallocate(new_data); throw; } - this->deallocate(data_); + if (this->data_) { + this->deallocate(data_); + } data_ = new_data; } @@ -243,7 +245,7 @@ class GArray { { const int64_t item_size = type_->size(); const int64_t alignment = type_->alignment(); - return allocator_.allocate(static_cast<size_t>(size) * item_size, alignment, AT); + return allocator_.allocate(size_t(size) * item_size, alignment, AT); } void deallocate(void *ptr) diff --git a/source/blender/blenlib/BLI_generic_span.hh b/source/blender/blenlib/BLI_generic_span.hh index 143ab235d2e..e7a08988c46 100644 --- a/source/blender/blenlib/BLI_generic_span.hh +++ b/source/blender/blenlib/BLI_generic_span.hh @@ -100,6 +100,34 @@ class GSpan { { return this->slice(range.start(), range.size()); } + + GSpan drop_front(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::max<int64_t>(0, size_ - n); + return GSpan(*type_, POINTER_OFFSET(data_, type_->size() * n), new_size); + } + + GSpan drop_back(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::max<int64_t>(0, size_ - n); + return GSpan(*type_, data_, new_size); + } + + GSpan take_front(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::min<int64_t>(size_, n); + return GSpan(*type_, data_, new_size); + } + + GSpan take_back(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::min<int64_t>(size_, n); + return GSpan(*type_, POINTER_OFFSET(data_, type_->size() * (size_ - new_size)), new_size); + } }; /** @@ -199,6 +227,35 @@ class GMutableSpan { return this->slice(range.start(), range.size()); } + GMutableSpan drop_front(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::max<int64_t>(0, size_ - n); + return GMutableSpan(*type_, POINTER_OFFSET(data_, type_->size() * n), new_size); + } + + GMutableSpan drop_back(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::max<int64_t>(0, size_ - n); + return GMutableSpan(*type_, data_, new_size); + } + + GMutableSpan take_front(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::min<int64_t>(size_, n); + return GMutableSpan(*type_, data_, new_size); + } + + GMutableSpan take_back(const int64_t n) const + { + BLI_assert(n >= 0); + const int64_t new_size = std::min<int64_t>(size_, n); + return GMutableSpan( + *type_, POINTER_OFFSET(data_, type_->size() * (size_ - new_size)), new_size); + } + /** * Copy all values from another span into this span. This invokes undefined behavior when the * destination contains uninitialized data and T is not trivially copy constructible. diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh index 43ca16a894f..e8a27cea6d8 100644 --- a/source/blender/blenlib/BLI_generic_virtual_array.hh +++ b/source/blender/blenlib/BLI_generic_virtual_array.hh @@ -78,7 +78,7 @@ class GVMutableArrayImpl : public GVArrayImpl { namespace detail { struct GVArrayAnyExtraInfo { const GVArrayImpl *(*get_varray)(const void *buffer) = - [](const void *UNUSED(buffer)) -> const GVArrayImpl * { return nullptr; }; + [](const void * /*buffer*/) -> const GVArrayImpl * { return nullptr; }; template<typename StorageT> static constexpr GVArrayAnyExtraInfo get(); }; @@ -315,7 +315,7 @@ template<typename T> class GVArrayImpl_For_VArray : public GVArrayImpl { protected: void get(const int64_t index, void *r_value) const override { - *(T *)r_value = varray_[index]; + *static_cast<T *>(r_value) = varray_[index]; } void get_to_uninitialized(const int64_t index, void *r_value) const override @@ -325,22 +325,24 @@ template<typename T> class GVArrayImpl_For_VArray : public GVArrayImpl { void materialize(const IndexMask mask, void *dst) const override { - varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize(mask, MutableSpan(static_cast<T *>(dst), mask.min_array_size())); } void materialize_to_uninitialized(const IndexMask mask, void *dst) const override { - varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize_to_uninitialized( + mask, MutableSpan(static_cast<T *>(dst), mask.min_array_size())); } void materialize_compressed(const IndexMask mask, void *dst) const override { - varray_.materialize_compressed(mask, MutableSpan((T *)dst, mask.size())); + varray_.materialize_compressed(mask, MutableSpan(static_cast<T *>(dst), mask.size())); } void materialize_compressed_to_uninitialized(const IndexMask mask, void *dst) const override { - varray_.materialize_compressed_to_uninitialized(mask, MutableSpan((T *)dst, mask.size())); + varray_.materialize_compressed_to_uninitialized( + mask, MutableSpan(static_cast<T *>(dst), mask.size())); } bool try_assign_VArray(void *varray) const override @@ -422,7 +424,7 @@ template<typename T> class GVMutableArrayImpl_For_VMutableArray : public GVMutab protected: void get(const int64_t index, void *r_value) const override { - *(T *)r_value = varray_[index]; + *static_cast<T *>(r_value) = varray_[index]; } void get_to_uninitialized(const int64_t index, void *r_value) const override @@ -443,40 +445,42 @@ template<typename T> class GVMutableArrayImpl_For_VMutableArray : public GVMutab void set_by_relocate(const int64_t index, void *value) override { - T &value_ = *(T *)value; + T &value_ = *static_cast<T *>(value); varray_.set(index, std::move(value_)); value_.~T(); } void set_by_move(const int64_t index, void *value) override { - T &value_ = *(T *)value; + T &value_ = *static_cast<T *>(value); varray_.set(index, std::move(value_)); } void set_all(const void *src) override { - varray_.set_all(Span((T *)src, size_)); + varray_.set_all(Span(static_cast<const T *>(src), size_)); } void materialize(const IndexMask mask, void *dst) const override { - varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize(mask, MutableSpan(static_cast<T *>(dst), mask.min_array_size())); } void materialize_to_uninitialized(const IndexMask mask, void *dst) const override { - varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize_to_uninitialized( + mask, MutableSpan(static_cast<T *>(dst), mask.min_array_size())); } void materialize_compressed(const IndexMask mask, void *dst) const override { - varray_.materialize_compressed(mask, MutableSpan((T *)dst, mask.size())); + varray_.materialize_compressed(mask, MutableSpan(static_cast<T *>(dst), mask.size())); } void materialize_compressed_to_uninitialized(const IndexMask mask, void *dst) const override { - varray_.materialize_compressed_to_uninitialized(mask, MutableSpan((T *)dst, mask.size())); + varray_.materialize_compressed_to_uninitialized( + mask, MutableSpan(static_cast<T *>(dst), mask.size())); } bool try_assign_VArray(void *varray) const override @@ -709,7 +713,7 @@ inline bool GVMutableArray::try_assign_VMutableArray(VMutableArray<T> &varray) c inline GVMutableArrayImpl *GVMutableArray::get_impl() const { - return (GVMutableArrayImpl *)impl_; + return const_cast<GVMutableArrayImpl *>(static_cast<const GVMutableArrayImpl *>(impl_)); } /** \} */ @@ -860,6 +864,7 @@ template<typename T> inline GVArray::GVArray(const VArray<T> &varray) * #this is destructed. */ if (info.type == CommonVArrayInfo::Type::Span && !info.may_have_ownership) { *this = GVArray::ForSpan(GSpan(CPPType::get<T>(), info.data, varray.size())); + return; } if (varray.try_assign_GVArray(*this)) { return; diff --git a/source/blender/blenlib/BLI_generic_virtual_vector_array.hh b/source/blender/blenlib/BLI_generic_virtual_vector_array.hh index 364b1ab33c7..373d010d926 100644 --- a/source/blender/blenlib/BLI_generic_virtual_vector_array.hh +++ b/source/blender/blenlib/BLI_generic_virtual_vector_array.hh @@ -133,8 +133,8 @@ class GVVectorArray_For_SingleGSpan : public GVVectorArray { } protected: - int64_t get_vector_size_impl(int64_t UNUSED(index)) const override; - void get_vector_element_impl(int64_t UNUSED(index), + int64_t get_vector_size_impl(int64_t /*index*/) const override; + void get_vector_element_impl(int64_t /*index*/, int64_t index_in_vector, void *r_value) const override; diff --git a/source/blender/blenlib/BLI_hash.hh b/source/blender/blenlib/BLI_hash.hh index 25d7cd6aaf8..693d4a8a71c 100644 --- a/source/blender/blenlib/BLI_hash.hh +++ b/source/blender/blenlib/BLI_hash.hh @@ -85,7 +85,7 @@ template<typename T> struct DefaultHash { { if constexpr (std::is_enum_v<T>) { /* For enums use the value as hash directly. */ - return (uint64_t)value; + return uint64_t(value); } else { /* Try to call the `hash()` function on the value. */ @@ -119,7 +119,7 @@ template<typename T> struct DefaultHash<const T> { template<> struct DefaultHash<TYPE> { \ uint64_t operator()(TYPE value) const \ { \ - return static_cast<uint64_t>(value); \ + return uint64_t(value); \ } \ } @@ -158,7 +158,7 @@ template<> struct DefaultHash<double> { template<> struct DefaultHash<bool> { uint64_t operator()(bool value) const { - return static_cast<uint64_t>((value != false) * 1298191); + return uint64_t((value != false) * 1298191); } }; @@ -209,8 +209,8 @@ template<> struct DefaultHash<std::string_view> { template<typename T> struct DefaultHash<T *> { uint64_t operator()(const T *value) const { - uintptr_t ptr = reinterpret_cast<uintptr_t>(value); - uint64_t hash = static_cast<uint64_t>(ptr >> 4); + uintptr_t ptr = uintptr_t(value); + uint64_t hash = uint64_t(ptr >> 4); return hash; } }; diff --git a/source/blender/blenlib/BLI_hash_tables.hh b/source/blender/blenlib/BLI_hash_tables.hh index 156fe481828..de65c58d4db 100644 --- a/source/blender/blenlib/BLI_hash_tables.hh +++ b/source/blender/blenlib/BLI_hash_tables.hh @@ -43,8 +43,7 @@ inline constexpr int64_t log2_floor_constexpr(const int64_t x) inline constexpr int64_t log2_ceil_constexpr(const int64_t x) { BLI_assert(x >= 0); - return (is_power_of_2_constexpr(static_cast<int>(x))) ? log2_floor_constexpr(x) : - log2_floor_constexpr(x) + 1; + return (is_power_of_2_constexpr(int(x))) ? log2_floor_constexpr(x) : log2_floor_constexpr(x) + 1; } inline constexpr int64_t power_of_2_max_constexpr(const int64_t x) @@ -71,17 +70,14 @@ inline constexpr int64_t ceil_division_by_fraction(const int64_t x, const int64_t numerator, const int64_t denominator) { - return static_cast<int64_t>( - ceil_division(static_cast<uint64_t>(x) * static_cast<uint64_t>(denominator), - static_cast<uint64_t>(numerator))); + return int64_t(ceil_division(uint64_t(x) * uint64_t(denominator), uint64_t(numerator))); } inline constexpr int64_t floor_multiplication_with_fraction(const int64_t x, const int64_t numerator, const int64_t denominator) { - return static_cast<int64_t>((static_cast<uint64_t>(x) * static_cast<uint64_t>(numerator) / - static_cast<uint64_t>(denominator))); + return int64_t((uint64_t(x) * uint64_t(numerator) / uint64_t(denominator))); } inline constexpr int64_t total_slot_amount_for_usable_slots( @@ -121,7 +117,7 @@ class LoadFactor { int64_t *r_total_slots, int64_t *r_usable_slots) const { - BLI_assert(is_power_of_2_i(static_cast<int>(min_total_slots))); + BLI_assert(is_power_of_2_i(int(min_total_slots))); int64_t total_slots = this->compute_total_slots(min_usable_slots, numerator_, denominator_); total_slots = std::max(total_slots, min_total_slots); @@ -229,17 +225,17 @@ template<typename Pointer> struct PointerKeyInfo { static bool is_empty(Pointer pointer) { - return (uintptr_t)pointer == UINTPTR_MAX; + return uintptr_t(pointer) == UINTPTR_MAX; } static bool is_removed(Pointer pointer) { - return (uintptr_t)pointer == UINTPTR_MAX - 1; + return uintptr_t(pointer) == UINTPTR_MAX - 1; } static bool is_not_empty_or_removed(Pointer pointer) { - return (uintptr_t)pointer < UINTPTR_MAX - 1; + return uintptr_t(pointer) < UINTPTR_MAX - 1; } }; diff --git a/source/blender/blenlib/BLI_index_range.hh b/source/blender/blenlib/BLI_index_range.hh index 6fcc560d856..c259282ca64 100644 --- a/source/blender/blenlib/BLI_index_range.hh +++ b/source/blender/blenlib/BLI_index_range.hh @@ -90,10 +90,10 @@ class IndexRange { return *this; } - constexpr Iterator operator++(int) const + constexpr Iterator operator++(int) { Iterator copied_iterator = *this; - ++copied_iterator; + ++(*this); return copied_iterator; } @@ -140,6 +140,10 @@ class IndexRange { { return (a.size_ == b.size_) && (a.start_ == b.start_ || a.size_ == 0); } + constexpr friend bool operator!=(IndexRange a, IndexRange b) + { + return !(a == b); + } /** * Get the amount of numbers in the range. @@ -248,6 +252,19 @@ class IndexRange { } /** + * Returns a new IndexRange that contains the intersection of the current one with the given + * range. Returns empty range if there are no overlapping indices. The returned range is always + * a valid slice of this range. + */ + constexpr IndexRange intersect(IndexRange other) const + { + const int64_t old_end = start_ + size_; + const int64_t new_start = std::min(old_end, std::max(start_, other.start_)); + const int64_t new_end = std::max(new_start, std::min(old_end, other.start_ + other.size_)); + return IndexRange(new_start, new_end - new_start); + } + + /** * Returns a new IndexRange with n elements removed from the beginning of the range. * This invokes undefined behavior when n is negative. */ @@ -318,4 +335,19 @@ class IndexRange { Span<int64_t> as_span_internal() const; }; +struct AlignedIndexRanges { + IndexRange prefix; + IndexRange aligned; + IndexRange suffix; +}; + +/** + * Split a range into three parts so that the boundaries of the middle part are aligned to some + * power of two. + * + * This can be used when an algorithm can be optimized on aligned indices/memory. The algorithm + * then needs a slow path for the beginning and end, and a fast path for the aligned elements. + */ +AlignedIndexRanges split_index_range_by_alignment(const IndexRange range, const int64_t alignment); + } // namespace blender diff --git a/source/blender/blenlib/BLI_lazy_threading.hh b/source/blender/blenlib/BLI_lazy_threading.hh new file mode 100644 index 00000000000..b5a15919c89 --- /dev/null +++ b/source/blender/blenlib/BLI_lazy_threading.hh @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * The goal of "lazy threading" is to avoid using threads unless one can reasonably assume that it + * is worth distributing work over multiple threads. Using threads can lead to worse overall + * performance by introducing inter-thread communication overhead. Keeping all work on a single + * thread reduces this overhead to zero and also makes better use of the CPU cache. + * + * Functions like #parallel_for also solve this to some degree by using a "grain size". When the + * number of individual tasks is too small, no multi-threading is used. This works very well when + * there are many homogeneous tasks that can be expected to take approximately the same time. + * + * The situation becomes more difficult when: + * - The individual tasks are not homogeneous, i.e. they take different amounts of time to compute. + * - It is practically impossible to guess how long each task will take in advance. + * + * Given those constraints, a single grain size cannot be determined. One could just schedule all + * tasks individually but that would create a lot of overhead when the tasks happen to be very + * small. While TBB will keep all tasks on a single thread if the other threads are busy, if they + * are idle they will start stealing the work even if that's not beneficial for overall + * performance. + * + * This file provides a simple API that allows a task scheduler to properly handle tasks whose size + * is not known in advance. The key idea is this: + * + * > By default, all work stays on a single thread. If an individual task notices that it is about + * > start a computation that will take a while, it notifies the task scheduler further up on the + * > stack. The scheduler then allows other threads to take over other tasks that were originally + * > meant for the current thread. + * + * This way, when all tasks are small, no threading overhead has to be paid for. Whenever there is + * a task that keeps the current thread busy for a while, the other tasks are moved to a separate + * thread so that they can be executed without waiting for the long computation to finish. + * + * Consequently, the earlier a task knows during it execution that it will take a while, the + * better. That's because if it is blocking anyway, it's more efficient to move the other tasks to + * another thread earlier. + * + * To make this work, three things have to be solved: + * 1. The task scheduler has to be able to start single-threaded and become multi-threaded after + * tasks have started executing. This has to be solved in the specific task scheduler. + * 2. There has to be a way for the currently running task to tell the task scheduler that it is + * about to perform a computation that will take a while and that it would be reasonable to move + * other tasks to other threads. This part is implemented in the API provided by this file. + * 3. Individual tasks have to decide when a computation is long enough to justify talking to the + * scheduler. This is always based on heuristics that have to be fine tuned over time. One could + * assume that this means adding new work-size checks to many parts in Blender, but that's + * actually not necessary, because these checks exist already in the form of grain sizes passed + * to e.g. #parallel_for. The assumption here is that when the task thinks the current work load + * is big enough to justify using threads, it's also big enough to justify using another thread + * for waiting tasks on the current thread. + */ + +#include "BLI_function_ref.hh" + +namespace blender::lazy_threading { + +/** + * Tell task schedulers on the current thread that it is about to start a long computation + * and that other waiting tasks should better be moved to another thread if possible. + */ +void send_hint(); + +/** + * Used by the task scheduler to receive hints from current tasks that they will take a while. + * This should only be allocated on the stack. + */ +class HintReceiver { + public: + /** + * The passed in function is called when a task signals that it will take a while. + * \note The function has to stay alive after the call to the constructor. So one must not pass a + * lambda directly into this constructor but store it in a separate variable on the stack first. + */ + HintReceiver(FunctionRef<void()> fn); + ~HintReceiver(); +}; + +} // namespace blender::lazy_threading diff --git a/source/blender/blenlib/BLI_linear_allocator.hh b/source/blender/blenlib/BLI_linear_allocator.hh index deb6ea3b5fd..a897845db45 100644 --- a/source/blender/blenlib/BLI_linear_allocator.hh +++ b/source/blender/blenlib/BLI_linear_allocator.hh @@ -161,7 +161,7 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya void *pointer_buffer = this->allocate(element_amount * sizeof(void *), alignof(void *)); void *elements_buffer = this->allocate(element_amount * element_size, element_alignment); - MutableSpan<void *> pointers((void **)pointer_buffer, element_amount); + MutableSpan<void *> pointers(static_cast<void **>(pointer_buffer), element_amount); void *next_element_buffer = elements_buffer; for (int64_t i : IndexRange(element_amount)) { pointers[i] = next_element_buffer; @@ -207,8 +207,8 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya Span<char> buffer = unused_borrowed_buffers_[i]; if (buffer.size() >= min_allocation_size) { unused_borrowed_buffers_.remove_and_reorder(i); - current_begin_ = (uintptr_t)buffer.begin(); - current_end_ = (uintptr_t)buffer.end(); + current_begin_ = uintptr_t(buffer.begin()); + current_end_ = uintptr_t(buffer.end()); return; } } @@ -226,7 +226,7 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya void *buffer = allocator_.allocate(size_in_bytes, min_alignment, __func__); owned_buffers_.append(buffer); - current_begin_ = (uintptr_t)buffer; + current_begin_ = uintptr_t(buffer); current_end_ = current_begin_ + size_in_bytes; } diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index 237fcdae8b9..6a41fce27b3 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -301,32 +301,33 @@ struct LinkData *BLI_genericNodeN(void *data); * * \code{.c} * - * LISTBASE_CIRCULAR_FORWARD_BEGIN(listbase, item, item_init) + * LISTBASE_CIRCULAR_FORWARD_BEGIN(type, listbase, item, item_init) * { * ...operate on marker... * } - * LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init); + * LISTBASE_CIRCULAR_FORWARD_END (type, listbase, item, item_init); * * \endcode */ -#define LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \ - if ((lb)->first && (lb_init || (lb_init = (lb)->first))) { \ - lb_iter = lb_init; \ +#define LISTBASE_CIRCULAR_FORWARD_BEGIN(type, lb, lb_iter, lb_init) \ + if ((lb)->first && (lb_init || (lb_init = (type)(lb)->first))) { \ + lb_iter = (type)(lb_init); \ do { -#define LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \ +#define LISTBASE_CIRCULAR_FORWARD_END(type, lb, lb_iter, lb_init) \ } \ - while ((lb_iter = (lb_iter)->next ? (lb_iter)->next : (lb)->first), (lb_iter != lb_init)) \ + while ((lb_iter = (lb_iter)->next ? (type)(lb_iter)->next : (type)(lb)->first), \ + (lb_iter != lb_init)) \ ; \ } \ ((void)0) -#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \ - if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \ +#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(type, lb, lb_iter, lb_init) \ + if ((lb)->last && (lb_init || (lb_init = (type)(lb)->last))) { \ lb_iter = lb_init; \ do { -#define LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \ +#define LISTBASE_CIRCULAR_BACKWARD_END(type, lb, lb_iter, lb_init) \ } \ - while ((lb_iter = (lb_iter)->prev ? (lb_iter)->prev : (lb)->last), (lb_iter != lb_init)) \ + while ((lb_iter = (lb_iter)->prev ? (lb_iter)->prev : (type)(lb)->last), (lb_iter != lb_init)) \ ; \ } \ ((void)0) diff --git a/source/blender/blenlib/BLI_listbase_wrapper.hh b/source/blender/blenlib/BLI_listbase_wrapper.hh index 25e029a5616..a32243bc411 100644 --- a/source/blender/blenlib/BLI_listbase_wrapper.hh +++ b/source/blender/blenlib/BLI_listbase_wrapper.hh @@ -42,7 +42,7 @@ template<typename T> class ListBaseWrapper { Iterator &operator++() { - /* Some types store next/prev using `void *`, so cast is necessary. */ + /* Some types store `next/prev` using `void *`, so cast is necessary. */ current_ = static_cast<T *>(current_->next); return *this; } @@ -50,7 +50,7 @@ template<typename T> class ListBaseWrapper { Iterator operator++(int) { Iterator iterator = *this; - ++*this; + ++(*this); return iterator; } diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh index 55233676ed8..6d281420c47 100644 --- a/source/blender/blenlib/BLI_map.hh +++ b/source/blender/blenlib/BLI_map.hh @@ -669,10 +669,10 @@ class Map { return *this; } - BaseIterator operator++(int) const + BaseIterator operator++(int) { BaseIterator copied_iterator = *this; - ++copied_iterator; + ++(*this); return copied_iterator; } @@ -887,6 +887,25 @@ class Map { } /** + * Remove all key-value-pairs for that the given predicate is true. + * + * This is similar to std::erase_if. + */ + template<typename Predicate> void remove_if(Predicate &&predicate) + { + for (Slot &slot : slots_) { + if (slot.is_occupied()) { + const Key &key = *slot.key(); + Value &value = *slot.value(); + if (predicate(MutableItem{key, value})) { + slot.remove(); + removed_slots_++; + } + } + } + } + + /** * Print common statistics like size and collision count. This is useful for debugging purposes. */ void print_stats(StringRef name = "") const @@ -943,7 +962,7 @@ class Map { */ int64_t size_in_bytes() const { - return static_cast<int64_t>(sizeof(Slot) * slots_.size()); + return int64_t(sizeof(Slot) * slots_.size()); } /** @@ -987,7 +1006,7 @@ class Map { max_load_factor_.compute_total_and_usable_slots( SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots); BLI_assert(total_slots >= 1); - const uint64_t new_slot_mask = static_cast<uint64_t>(total_slots) - 1; + const uint64_t new_slot_mask = uint64_t(total_slots) - 1; /** * Optimize the case when the map was empty beforehand. We can avoid some copies here. @@ -1261,7 +1280,7 @@ template<typename Key, typename Value> class StdUnorderedMapWrapper { public: int64_t size() const { - return static_cast<int64_t>(map_.size()); + return int64_t(map_.size()); } bool is_empty() const @@ -1295,7 +1314,7 @@ template<typename Key, typename Value> class StdUnorderedMapWrapper { bool remove(const Key &key) { - return (bool)map_.erase(key); + return bool(map_.erase(key)); } Value &lookup(const Key &key) @@ -1313,7 +1332,7 @@ template<typename Key, typename Value> class StdUnorderedMapWrapper { map_.clear(); } - void print_stats(StringRef UNUSED(name) = "") const + void print_stats(StringRef /*name*/ = "") const { } }; diff --git a/source/blender/blenlib/BLI_map_slots.hh b/source/blender/blenlib/BLI_map_slots.hh index 6426216913f..eb2c1a7f5cf 100644 --- a/source/blender/blenlib/BLI_map_slots.hh +++ b/source/blender/blenlib/BLI_map_slots.hh @@ -169,7 +169,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * key. The hash can be used by other slot implementations to determine inequality faster. */ template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t /*hash*/) const { if (state_ == Occupied) { return is_equal(key, *key_buffer_); @@ -194,7 +194,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * Change the state of this slot from empty/removed to occupied. The value is assumed to be * constructed already. */ - template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash)) + template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t /*hash*/) { BLI_assert(!this->is_occupied()); try { @@ -295,7 +295,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot } template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t /*hash*/) const { BLI_assert(KeyInfo::is_not_empty_or_removed(key)); return is_equal(key, key_); @@ -310,7 +310,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot this->occupy_no_value(std::forward<ForwardKey>(key), hash); } - template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash)) + template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t /*hash*/) { BLI_assert(!this->is_occupied()); BLI_assert(KeyInfo::is_not_empty_or_removed(key)); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 6386a7f76f8..3aa2e35476d 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -164,7 +164,9 @@ void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4]); MINLINE float rgb_to_grayscale(const float rgb[3]); MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3]); -MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3], int limit); +MINLINE int compare_rgb_uchar(const unsigned char col_a[3], + const unsigned char col_b[3], + int limit); /** * Return triangle noise in [-0.5..1.5] range. diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 93b413ab755..d056c42e019 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -1270,8 +1270,8 @@ MINLINE void mul_sh_fl(float r[9], float f); MINLINE void add_sh_shsh(float r[9], const float a[9], const float b[9]); MINLINE float dot_shsh(const float a[9], const float b[9]); -MINLINE float eval_shv3(float r[9], const float v[3]); -MINLINE float diffuse_shv3(const float r[9], const float v[3]); +MINLINE float eval_shv3(float sh[9], const float v[3]); +MINLINE float diffuse_shv3(const float sh[9], const float v[3]); MINLINE void vec_fac_to_sh(float r[9], const float v[3], float f); MINLINE void madd_sh_shfl(float r[9], const float sh[9], float f); diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h index bf91c9108a9..b190b022a88 100644 --- a/source/blender/blenlib/BLI_math_inline.h +++ b/source/blender/blenlib/BLI_math_inline.h @@ -28,8 +28,8 @@ extern "C" { # define MALWAYS_INLINE #endif -/* gcc 4.6 (supports push/pop) */ -#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) +/* Check for GCC push/pop pragma support. */ +#ifdef __GNUC__ # define BLI_MATH_GCC_WARN_PRAGMA 1 #endif diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index c2dafbe3a1a..7e1b7c2ba56 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -98,110 +98,110 @@ void mul_m4_m4_post(float R[4][4], const float B[4][4]); /* Implement #mul_m3_series macro. */ -void _va_mul_m3_series_3(float R[3][3], const float M1[3][3], const float M2[3][3]) ATTR_NONNULL(); -void _va_mul_m3_series_4(float R[3][3], - const float M1[3][3], - const float M2[3][3], - const float M3[3][3]) ATTR_NONNULL(); -void _va_mul_m3_series_5(float R[3][3], - const float M1[3][3], - const float M2[3][3], - const float M3[3][3], - const float M4[3][3]) ATTR_NONNULL(); -void _va_mul_m3_series_6(float R[3][3], - const float M1[3][3], - const float M2[3][3], - const float M3[3][3], - const float M4[3][3], - const float M5[3][3]) ATTR_NONNULL(); -void _va_mul_m3_series_7(float R[3][3], - const float M1[3][3], - const float M2[3][3], - const float M3[3][3], - const float M4[3][3], - const float M5[3][3], - const float M6[3][3]) ATTR_NONNULL(); -void _va_mul_m3_series_8(float R[3][3], - const float M1[3][3], - const float M2[3][3], - const float M3[3][3], - const float M4[3][3], - const float M5[3][3], - const float M6[3][3], - const float M7[3][3]) ATTR_NONNULL(); -void _va_mul_m3_series_9(float R[3][3], - const float M1[3][3], - const float M2[3][3], - const float M3[3][3], - const float M4[3][3], - const float M5[3][3], - const float M6[3][3], - const float M7[3][3], - const float M8[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_3(float r[3][3], const float m1[3][3], const float m2[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_4(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_5(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_6(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_7(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3], + const float m6[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_8(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3], + const float m6[3][3], + const float m7[3][3]) ATTR_NONNULL(); +void _va_mul_m3_series_9(float r[3][3], + const float m1[3][3], + const float m2[3][3], + const float m3[3][3], + const float m4[3][3], + const float m5[3][3], + const float m6[3][3], + const float m7[3][3], + const float m8[3][3]) ATTR_NONNULL(); /* Implement #mul_m4_series macro. */ -void _va_mul_m4_series_3(float R[4][4], const float M1[4][4], const float M2[4][4]) ATTR_NONNULL(); -void _va_mul_m4_series_4(float R[4][4], - const float M1[4][4], - const float M2[4][4], - const float M3[4][4]) ATTR_NONNULL(); -void _va_mul_m4_series_5(float R[4][4], - const float M1[4][4], - const float M2[4][4], - const float M3[4][4], - const float M4[4][4]) ATTR_NONNULL(); -void _va_mul_m4_series_6(float R[4][4], - const float M1[4][4], - const float M2[4][4], - const float M3[4][4], - const float M4[4][4], - const float M5[4][4]) ATTR_NONNULL(); -void _va_mul_m4_series_7(float R[4][4], - const float M1[4][4], - const float M2[4][4], - const float M3[4][4], - const float M4[4][4], - const float M5[4][4], - const float M6[4][4]) ATTR_NONNULL(); -void _va_mul_m4_series_8(float R[4][4], - const float M1[4][4], - const float M2[4][4], - const float M3[4][4], - const float M4[4][4], - const float M5[4][4], - const float M6[4][4], - const float M7[4][4]) ATTR_NONNULL(); -void _va_mul_m4_series_9(float R[4][4], - const float M1[4][4], - const float M2[4][4], - const float M3[4][4], - const float M4[4][4], - const float M5[4][4], - const float M6[4][4], - const float M7[4][4], - const float M8[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_3(float r[4][4], const float m1[4][4], const float m2[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_4(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_5(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_6(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_7(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4], + const float m6[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_8(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4], + const float m6[4][4], + const float m7[4][4]) ATTR_NONNULL(); +void _va_mul_m4_series_9(float r[4][4], + const float m1[4][4], + const float m2[4][4], + const float m3[4][4], + const float m4[4][4], + const float m5[4][4], + const float m6[4][4], + const float m7[4][4], + const float m8[4][4]) ATTR_NONNULL(); #define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__) #define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__) void mul_m4_v3(const float M[4][4], float r[3]); -void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3]); +void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3]); void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]); void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3]); -void mul_v2_m4v3(float r[2], const float M[4][4], const float v[3]); -void mul_v2_m2v2(float r[2], const float M[2][2], const float v[2]); -void mul_m2_v2(const float M[2][2], float v[2]); +void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3]); +void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2]); +void mul_m2_v2(const float mat[2][2], float vec[2]); /** Same as #mul_m4_v3() but doesn't apply translation component. */ -void mul_mat3_m4_v3(const float M[4][4], float r[3]); -void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3]); -void mul_v3_mat3_m4v3_db(double r[3], const double M[4][4], const double v[3]); -void mul_m4_v4(const float M[4][4], float r[4]); -void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4]); +void mul_mat3_m4_v3(const float mat[4][4], float r[3]); +void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3]); +void mul_v3_mat3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]); +void mul_m4_v4(const float mat[4][4], float r[4]); +void mul_v4_m4v4(float r[4], const float mat[4][4], const float v[4]); void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */ -void mul_project_m4_v3(const float M[4][4], float vec[3]); +void mul_project_m4_v3(const float mat[4][4], float vec[3]); void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3]); -void mul_v2_project_m4_v3(float r[2], const float M[4][4], const float vec[3]); +void mul_v2_project_m4_v3(float r[2], const float mat[4][4], const float vec[3]); void mul_m3_v2(const float m[3][3], float r[2]); void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2]); @@ -234,14 +234,14 @@ void negate_m3(float R[3][3]); void negate_mat3_m4(float R[4][4]); void negate_m4(float R[4][4]); -bool invert_m3_ex(float m[3][3], float epsilon); -bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], float epsilon); +bool invert_m3_ex(float mat[3][3], float epsilon); +bool invert_m3_m3_ex(float inverse[3][3], const float mat[3][3], float epsilon); -bool invert_m3(float R[3][3]); -bool invert_m2_m2(float R[2][2], const float A[2][2]); -bool invert_m3_m3(float R[3][3], const float A[3][3]); -bool invert_m4(float R[4][4]); -bool invert_m4_m4(float R[4][4], const float A[4][4]); +bool invert_m3(float mat[3][3]); +bool invert_m2_m2(float inverse[2][2], const float mat[2][2]); +bool invert_m3_m3(float inverse[3][3], const float mat[3][3]); +bool invert_m4(float mat[4][4]); +bool invert_m4_m4(float inverse[4][4], const float mat[4][4]); /** * Computes the inverse of mat and puts it in inverse. * Uses Gaussian Elimination with partial (maximal column) pivoting. @@ -252,12 +252,12 @@ bool invert_m4_m4(float R[4][4], const float A[4][4]); * for non-invertible scale matrices, finding a partial solution can * be useful to have a valid local transform center, see T57767. */ -bool invert_m4_m4_fallback(float R[4][4], const float A[4][4]); +bool invert_m4_m4_fallback(float inverse[4][4], const float mat[4][4]); /* Double arithmetic (mixed float/double). */ -void mul_m4_v4d(const float M[4][4], double r[4]); -void mul_v4d_m4v4d(double r[4], const float M[4][4], const double v[4]); +void mul_m4_v4d(const float mat[4][4], double r[4]); +void mul_v4d_m4v4d(double r[4], const float mat[4][4], const double v[4]); /* Double matrix functions (no mixing types). */ @@ -291,8 +291,8 @@ void normalize_m3_m3_ex(float R[3][3], const float M[3][3], float r_scale[3]) AT void normalize_m3_m3(float R[3][3], const float M[3][3]) ATTR_NONNULL(); void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL(); void normalize_m4(float R[4][4]) ATTR_NONNULL(); -void normalize_m4_m4_ex(float R[4][4], const float M[4][4], float r_scale[3]) ATTR_NONNULL(); -void normalize_m4_m4(float R[4][4], const float M[4][4]) ATTR_NONNULL(); +void normalize_m4_m4_ex(float rmat[4][4], const float mat[4][4], float r_scale[3]) ATTR_NONNULL(); +void normalize_m4_m4(float rmat[4][4], const float mat[4][4]) ATTR_NONNULL(); /** * Make an orthonormal matrix around the selected axis of the given matrix. @@ -326,15 +326,15 @@ void orthogonalize_m3_stable(float R[3][3], int axis, bool normalize); */ void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize); -bool orthogonalize_m3_zero_axes(float R[3][3], float unit_length); -bool orthogonalize_m4_zero_axes(float R[4][4], float unit_length); +bool orthogonalize_m3_zero_axes(float m[3][3], float unit_length); +bool orthogonalize_m4_zero_axes(float m[4][4], float unit_length); -bool is_orthogonal_m3(const float mat[3][3]); -bool is_orthogonal_m4(const float mat[4][4]); -bool is_orthonormal_m3(const float mat[3][3]); -bool is_orthonormal_m4(const float mat[4][4]); +bool is_orthogonal_m3(const float m[3][3]); +bool is_orthogonal_m4(const float m[4][4]); +bool is_orthonormal_m3(const float m[3][3]); +bool is_orthonormal_m4(const float m[4][4]); -bool is_uniform_scaled_m3(const float mat[3][3]); +bool is_uniform_scaled_m3(const float m[3][3]); bool is_uniform_scaled_m4(const float m[4][4]); /* NOTE: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix! @@ -362,22 +362,24 @@ float determinant_m4(const float m[4][4]); * From this decomposition it is trivial to compute the (pseudo-inverse) * of `A` as `Ainv = V.Winv.transpose(U)`. */ -void svd_m4(float U[4][4], float s[4], float V[4][4], float A[4][4]); -void pseudoinverse_m4_m4(float Ainv[4][4], const float A[4][4], float epsilon); -void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon); +void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]); +void pseudoinverse_m4_m4(float inverse[4][4], const float mat[4][4], float epsilon); +void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon); bool has_zero_axis_m4(const float matrix[4][4]); +/** Fix any zero scale axis adding a small bias orthogonal to the other valid axis. */ +void zero_axis_bias_m4(float mat[4][4]); -void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]); +void invert_m4_m4_safe(float inverse[4][4], const float mat[4][4]); -void invert_m3_m3_safe_ortho(float Ainv[3][3], const float A[3][3]); +void invert_m3_m3_safe_ortho(float inverse[3][3], const float mat[3][3]); /** * A safe version of invert that uses valid axes, calculating the zero'd axis * based on the non-zero ones. * * This works well for transformation matrices, when a single axis is zeroed. */ -void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4]); +void invert_m4_m4_safe_ortho(float inverse[4][4], const float mat[4][4]); /** \} */ @@ -394,22 +396,24 @@ void scale_m4_v2(float R[4][4], const float scale[2]); * For an orthogonal matrix, it is the product of all three scale values. * Returns a negative value if the transform is flipped by negative scale. */ -float mat3_to_volume_scale(const float M[3][3]); -float mat4_to_volume_scale(const float M[4][4]); +float mat3_to_volume_scale(const float mat[3][3]); +float mat4_to_volume_scale(const float mat[4][4]); /** * This gets the average scale of a matrix, only use when your scaling * data that has no idea of scale axis, examples are bone-envelope-radius * and curve radius. */ -float mat3_to_scale(const float M[3][3]); -float mat4_to_scale(const float M[4][4]); +float mat3_to_scale(const float mat[3][3]); +float mat4_to_scale(const float mat[4][4]); /** Return 2D scale (in XY plane) of given mat4. */ -float mat4_to_xy_scale(const float M[4][4]); +float mat4_to_xy_scale(const float mat[4][4]); void size_to_mat3(float R[3][3], const float size[3]); void size_to_mat4(float R[4][4], const float size[3]); +/** Return 2D size assuming the given matrix is a 2D affine matrix. */ +void mat3_to_size_2d(float size[2], const float M[3][3]); void mat3_to_size(float size[3], const float M[3][3]); void mat4_to_size(float size[3], const float M[4][4]); @@ -433,7 +437,7 @@ float mat4_to_size_max_axis(const float M[4][4]); */ void mat4_to_size_fix_shear(float size[3], const float M[4][4]); -void translate_m4(float mat[4][4], float tx, float ty, float tz); +void translate_m4(float mat[4][4], float Tx, float Ty, float Tz); /** * Rotate a matrix in-place. * @@ -454,8 +458,20 @@ void rescale_m4(float mat[4][4], const float scale[3]); */ void transform_pivot_set_m4(float mat[4][4], const float pivot[3]); +/** + * \param rot: A 3x3 rotation matrix, normalized never negative. + */ void mat4_to_rot(float rot[3][3], const float wmat[4][4]); + +/** + * \param rot: A 3x3 rotation matrix, normalized never negative. + * \param size: The scale, negative if `mat3` is negative. + */ void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]); +/** + * \param rot: A 3x3 rotation matrix, normalized never negative. + * \param size: The scale, negative if `mat3` is negative. + */ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4]); void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]); void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4]); @@ -528,7 +544,18 @@ void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], flo */ void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], float t); +/** + * Return true when the matrices determinant is less than zero. + * + * \note This is often used to check if a matrix flips content in 3D space, + * where transforming geometry (for example) would flip the direction of polygon normals + * from pointing outside a closed volume, to pointing inside (or the reverse). + * + * When the matrix is constructed from location, rotation & scale + * as matrix will be negative when it has an odd number of negative scales. + */ bool is_negative_m3(const float mat[3][3]); +/** A version of #is_negative_m3 that takes a 4x4 matrix. */ bool is_negative_m4(const float mat[4][4]); bool is_zero_m3(const float mat[3][3]); @@ -605,8 +632,8 @@ void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float /** \name Other * \{ */ -void print_m3(const char *str, const float M[3][3]); -void print_m4(const char *str, const float M[4][4]); +void print_m3(const char *str, const float m[3][3]); +void print_m4(const char *str, const float m[4][4]); #define print_m3_id(M) print_m3(STRINGIFY(M), M) #define print_m4_id(M) print_m4(STRINGIFY(M), M) diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index fef51fa780e..7fb7085360b 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -71,7 +71,7 @@ void mul_qt_fl(float q[4], float f); /** * Raise a unit quaternion to the specified power. */ -void pow_qt_fl_normalized(float q[4], float f); +void pow_qt_fl_normalized(float q[4], float fac); void sub_qt_qtqt(float q[4], const float a[4], const float b[4]); @@ -109,8 +109,8 @@ void add_qt_qtqt(float q[4], const float a[4], const float b[4], float t); /* Conversion. */ -void quat_to_mat3(float mat[3][3], const float q[4]); -void quat_to_mat4(float mat[4][4], const float q[4]); +void quat_to_mat3(float m[3][3], const float q[4]); +void quat_to_mat4(float m[4][4], const float q[4]); /** * Apply the rotation of \a a to \a q keeping the values compatible with \a old. @@ -118,6 +118,11 @@ void quat_to_mat4(float mat[4][4], const float q[4]); */ void quat_to_compatible_quat(float q[4], const float a[4], const float old[4]); +/** + * A version of #mat3_normalized_to_quat that skips error checking. + */ +void mat3_normalized_to_quat_fast(float q[4], const float mat[3][3]); + void mat3_normalized_to_quat(float q[4], const float mat[3][3]); void mat4_normalized_to_quat(float q[4], const float mat[4][4]); void mat3_to_quat(float q[4], const float mat[3][3]); @@ -157,7 +162,10 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q * \param r_twist: if not NULL, receives the twist quaternion. * \returns twist angle. */ -float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4]); +float quat_split_swing_and_twist(const float q_in[4], + int axis, + float r_swing[4], + float r_twist[4]); float angle_normalized_qt(const float q[4]); float angle_normalized_qtqt(const float q1[4], const float q2[4]); @@ -170,17 +178,17 @@ float angle_signed_qt(const float q[4]); float angle_signed_qtqt(const float q1[4], const float q2[4]); /** - * TODO: don't what this is, but it's not the same as #mat3_to_quat. + * Legacy matrix to quaternion conversion, keep to prevent changes to existing + * boids & particle-system behavior. Use #mat3_to_quat for new code. */ -void mat3_to_quat_is_ok(float q[4], const float mat[3][3]); +void mat3_to_quat_legacy(float q[4], const float wmat[3][3]); /* Other. */ /** - * Utility function that performs `sinf` & `cosf` where the quadrants of the circle - * will have exactly matching values when their sign is flipped. - * This works as long as the denominator can be divided by 2 or 4, - * otherwise `sinf` & `cosf` are used without any additional logic. + * Utility that performs `sinf` & `cosf` intended for plotting a 2D circle, + * where the values of the coordinates with are exactly symmetrical although this + * favors even numbers as odd numbers can only be symmetrical on a single axis. * * Besides adjustments to precision, this function is the equivalent of: * \code {.c} @@ -190,11 +198,11 @@ void mat3_to_quat_is_ok(float q[4], const float mat[3][3]); * \endcode * * \param numerator: An integer factor in [0..denominator] (inclusive). - * \param denominator: The faction denominator (typically the number of segments of the circle). + * \param denominator: The fraction denominator (typically the number of segments of the circle). * \param r_sin: The resulting sine. * \param r_cos: The resulting cosine. */ -void sin_cos_from_fraction(const int numerator, const int denominator, float *r_sin, float *r_cos); +void sin_cos_from_fraction(int numerator, int denominator, float *r_sin, float *r_cos); void print_qt(const char *str, const float q[4]); @@ -236,16 +244,16 @@ void axis_angle_to_mat4(float R[4][4], const float axis[3], float angle); /** * 3x3 matrix to axis angle. */ -void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float M[3][3]); +void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float mat[3][3]); /** * 4x4 matrix to axis angle. */ -void mat4_normalized_to_axis_angle(float axis[3], float *angle, const float M[4][4]); -void mat3_to_axis_angle(float axis[3], float *angle, const float M[3][3]); +void mat4_normalized_to_axis_angle(float axis[3], float *angle, const float mat[4][4]); +void mat3_to_axis_angle(float axis[3], float *angle, const float mat[3][3]); /** * 4x4 matrix to axis angle. */ -void mat4_to_axis_angle(float axis[3], float *angle, const float M[4][4]); +void mat4_to_axis_angle(float axis[3], float *angle, const float mat[4][4]); /** * Quaternions to Axis Angle. */ @@ -284,19 +292,19 @@ void eul_to_mat3(float mat[3][3], const float eul[3]); void eul_to_mat4(float mat[4][4], const float eul[3]); void mat3_normalized_to_eul(float eul[3], const float mat[3][3]); -void mat4_normalized_to_eul(float eul[3], const float mat[4][4]); +void mat4_normalized_to_eul(float eul[3], const float m[4][4]); void mat3_to_eul(float eul[3], const float mat[3][3]); void mat4_to_eul(float eul[3], const float mat[4][4]); void quat_to_eul(float eul[3], const float quat[4]); -void mat3_normalized_to_compatible_eul(float eul[3], const float old[3], float mat[3][3]); -void mat3_to_compatible_eul(float eul[3], const float old[3], float mat[3][3]); +void mat3_normalized_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3]); +void mat3_to_compatible_eul(float eul[3], const float oldrot[3], float mat[3][3]); void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float quat[4]); -void rotate_eul(float eul[3], char axis, float angle); +void rotate_eul(float beul[3], char axis, float angle); /* Order independent. */ -void compatible_eul(float eul[3], const float old[3]); +void compatible_eul(float eul[3], const float oldrot[3]); void add_eul_euleul(float r_eul[3], float a[3], float b[3], short order); void sub_eul_euleul(float r_eul[3], float a[3], float b[3], short order); @@ -324,15 +332,15 @@ typedef enum eEulerRotationOrders { /** * Construct quaternion from Euler angles (in radians). */ -void eulO_to_quat(float quat[4], const float eul[3], short order); +void eulO_to_quat(float q[4], const float e[3], short order); /** * Construct 3x3 matrix from Euler angles (in radians). */ -void eulO_to_mat3(float mat[3][3], const float eul[3], short order); +void eulO_to_mat3(float M[3][3], const float e[3], short order); /** * Construct 4x4 matrix from Euler angles (in radians). */ -void eulO_to_mat4(float mat[4][4], const float eul[3], short order); +void eulO_to_mat4(float mat[4][4], const float e[3], short order); /** * Euler Rotation to Axis Angle. */ @@ -345,17 +353,17 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], short order); /** * Convert 3x3 matrix to Euler angles (in radians). */ -void mat3_normalized_to_eulO(float eul[3], short order, const float mat[3][3]); +void mat3_normalized_to_eulO(float eul[3], short order, const float m[3][3]); /** * Convert 4x4 matrix to Euler angles (in radians). */ -void mat4_normalized_to_eulO(float eul[3], short order, const float mat[4][4]); -void mat3_to_eulO(float eul[3], short order, const float mat[3][3]); -void mat4_to_eulO(float eul[3], short order, const float mat[4][4]); +void mat4_normalized_to_eulO(float eul[3], short order, const float m[4][4]); +void mat3_to_eulO(float eul[3], short order, const float m[3][3]); +void mat4_to_eulO(float eul[3], short order, const float m[4][4]); /** * Convert quaternion to Euler angles (in radians). */ -void quat_to_eulO(float eul[3], short order, const float quat[4]); +void quat_to_eulO(float e[3], short order, const float q[4]); /** * Axis Angle to Euler Rotation. */ @@ -364,18 +372,27 @@ void axis_angle_to_eulO(float eul[3], short order, const float axis[3], float an /* Uses 2 methods to retrieve eulers, and picks the closest. */ void mat3_normalized_to_compatible_eulO(float eul[3], - const float old[3], + const float oldrot[3], short order, const float mat[3][3]); void mat4_normalized_to_compatible_eulO(float eul[3], - const float old[3], + const float oldrot[3], short order, const float mat[4][4]); -void mat3_to_compatible_eulO(float eul[3], const float old[3], short order, const float mat[3][3]); -void mat4_to_compatible_eulO(float eul[3], const float old[3], short order, const float mat[4][4]); -void quat_to_compatible_eulO(float eul[3], const float old[3], short order, const float quat[4]); - -void rotate_eulO(float eul[3], short order, char axis, float angle); +void mat3_to_compatible_eulO(float eul[3], + const float oldrot[3], + short order, + const float mat[3][3]); +void mat4_to_compatible_eulO(float eul[3], + const float oldrot[3], + short order, + const float mat[4][4]); +void quat_to_compatible_eulO(float eul[3], + const float oldrot[3], + short order, + const float quat[4]); + +void rotate_eulO(float beul[3], short order, char axis, float angle); /** \} */ @@ -384,7 +401,7 @@ void rotate_eulO(float eul[3], short order, char axis, float angle); * \{ */ void copy_dq_dq(DualQuat *r, const DualQuat *dq); -void normalize_dq(DualQuat *dq, float totw); +void normalize_dq(DualQuat *dq, float totweight); void add_weighted_dq_dq(DualQuat *dq_sum, const DualQuat *dq, float weight); void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq); @@ -401,7 +418,7 @@ void vec_apply_track(float vec[3], short axis); * Lens/angle conversion (radians). */ float focallength_to_fov(float focal_length, float sensor); -float fov_to_focallength(float fov, float sensor); +float fov_to_focallength(float hfov, float sensor); float angle_wrap_rad(float angle); float angle_wrap_deg(float angle); diff --git a/source/blender/blenlib/BLI_math_vec_types.hh b/source/blender/blenlib/BLI_math_vec_types.hh index 7f20881dfa3..0387d0b0440 100644 --- a/source/blender/blenlib/BLI_math_vec_types.hh +++ b/source/blender/blenlib/BLI_math_vec_types.hh @@ -40,6 +40,21 @@ template<typename T> struct vec_struct_base<T, 4> { T x, y, z, w; }; +template<class Fn, size_t... I> void unroll_impl(Fn fn, std::index_sequence<I...> /*indices*/) +{ + (fn(I), ...); +} + +/** + * Variadic templates are used to unroll loops manually. This helps GCC avoid branching during math + * operations and makes the code generation more explicit and predictable. Unrolling should always + * be worth it because the vector size is expected to be small. + */ +template<int N, class Fn> void unroll(Fn fn) +{ + unroll_impl(fn, std::make_index_sequence<N>()); +} + namespace math { template<typename T> uint64_t vector_hash(const T &vec) @@ -74,28 +89,28 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> explicit vec_base(uint value) { for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); + (*this)[i] = T(value); } } explicit vec_base(int value) { for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); + (*this)[i] = T(value); } } explicit vec_base(float value) { for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); + (*this)[i] = T(value); } } explicit vec_base(double value) { for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(value); + (*this)[i] = T(value); } } @@ -126,53 +141,42 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> /** Mixed scalar-vector constructors. */ template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)> - constexpr vec_base(const vec_base<U, 2> &xy, T z) - : vec_base(static_cast<T>(xy.x), static_cast<T>(xy.y), z) + constexpr vec_base(const vec_base<U, 2> &xy, T z) : vec_base(T(xy.x), T(xy.y), z) { } template<typename U, BLI_ENABLE_IF_VEC(Size, == 3)> - constexpr vec_base(T x, const vec_base<U, 2> &yz) - : vec_base(x, static_cast<T>(yz.x), static_cast<T>(yz.y)) + constexpr vec_base(T x, const vec_base<U, 2> &yz) : vec_base(x, T(yz.x), T(yz.y)) { } template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)> - vec_base(vec_base<U, 3> xyz, T w) - : vec_base( - static_cast<T>(xyz.x), static_cast<T>(xyz.y), static_cast<T>(xyz.z), static_cast<T>(w)) + vec_base(vec_base<U, 3> xyz, T w) : vec_base(T(xyz.x), T(xyz.y), T(xyz.z), T(w)) { } template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)> - vec_base(T x, vec_base<U, 3> yzw) - : vec_base( - static_cast<T>(x), static_cast<T>(yzw.x), static_cast<T>(yzw.y), static_cast<T>(yzw.z)) + vec_base(T x, vec_base<U, 3> yzw) : vec_base(T(x), T(yzw.x), T(yzw.y), T(yzw.z)) { } template<typename U, typename V, BLI_ENABLE_IF_VEC(Size, == 4)> - vec_base(vec_base<U, 2> xy, vec_base<V, 2> zw) - : vec_base( - static_cast<T>(xy.x), static_cast<T>(xy.y), static_cast<T>(zw.x), static_cast<T>(zw.y)) + vec_base(vec_base<U, 2> xy, vec_base<V, 2> zw) : vec_base(T(xy.x), T(xy.y), T(zw.x), T(zw.y)) { } template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)> - vec_base(vec_base<U, 2> xy, T z, T w) - : vec_base(static_cast<T>(xy.x), static_cast<T>(xy.y), static_cast<T>(z), static_cast<T>(w)) + vec_base(vec_base<U, 2> xy, T z, T w) : vec_base(T(xy.x), T(xy.y), T(z), T(w)) { } template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)> - vec_base(T x, vec_base<U, 2> yz, T w) - : vec_base(static_cast<T>(x), static_cast<T>(yz.x), static_cast<T>(yz.y), static_cast<T>(w)) + vec_base(T x, vec_base<U, 2> yz, T w) : vec_base(T(x), T(yz.x), T(yz.y), T(w)) { } template<typename U, BLI_ENABLE_IF_VEC(Size, == 4)> - vec_base(T x, T y, vec_base<U, 2> zw) - : vec_base(static_cast<T>(x), static_cast<T>(y), static_cast<T>(zw.x), static_cast<T>(zw.y)) + vec_base(T x, T y, vec_base<U, 2> zw) : vec_base(T(x), T(y), T(zw.x), T(zw.y)) { } @@ -182,7 +186,7 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> explicit vec_base(const vec_base<U, OtherSize> &other) { for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(other[i]); + (*this)[i] = T(other[i]); } } @@ -192,17 +196,13 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> vec_base(const T *ptr) { - for (int i = 0; i < Size; i++) { - (*this)[i] = ptr[i]; - } + unroll<Size>([&](auto i) { (*this)[i] = ptr[i]; }); } template<typename U, BLI_ENABLE_IF((std::is_convertible_v<U, T>))> explicit vec_base(const U *ptr) { - for (int i = 0; i < Size; i++) { - (*this)[i] = ptr[i]; - } + unroll<Size>([&](auto i) { (*this)[i] = ptr[i]; }); } vec_base(const T (*ptr)[Size]) : vec_base(static_cast<const T *>(ptr[0])) @@ -213,9 +213,7 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> template<typename U> explicit vec_base(const vec_base<U, Size> &vec) { - for (int i = 0; i < Size; i++) { - (*this)[i] = static_cast<T>(vec[i]); - } + unroll<Size>([&](auto i) { (*this)[i] = T(vec[i]); }); } /** C-style pointer dereference. */ @@ -250,29 +248,20 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> #define BLI_INT_OP(_T) template<typename U = _T, BLI_ENABLE_IF((std::is_integral_v<U>))> -#define BLI_VEC_OP_IMPL(_result, _i, _op) \ - vec_base _result; \ - for (int _i = 0; _i < Size; _i++) { \ - _op; \ - } \ - return _result; - -#define BLI_VEC_OP_IMPL_SELF(_i, _op) \ - for (int _i = 0; _i < Size; _i++) { \ - _op; \ - } \ - return *this; - /** Arithmetic operators. */ friend vec_base operator+(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] + b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] + b[i]; }); + return result; } friend vec_base operator+(const vec_base &a, const T &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] + b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] + b; }); + return result; } friend vec_base operator+(const T &a, const vec_base &b) @@ -282,52 +271,69 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> vec_base &operator+=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] += b[i]); + unroll<Size>([&](auto i) { (*this)[i] += b[i]; }); + return *this; } vec_base &operator+=(const T &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] += b); + vec_base result; + unroll<Size>([&](auto i) { (*this)[i] += b; }); + return result; } friend vec_base operator-(const vec_base &a) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = -a[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = -a[i]; }); + return result; } friend vec_base operator-(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] - b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] - b[i]; }); + return result; } friend vec_base operator-(const vec_base &a, const T &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] - b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] - b; }); + return result; } friend vec_base operator-(const T &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a - b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a - b[i]; }); + return result; } vec_base &operator-=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] -= b[i]); + unroll<Size>([&](auto i) { (*this)[i] -= b[i]; }); + return *this; } vec_base &operator-=(const T &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] -= b); + unroll<Size>([&](auto i) { (*this)[i] -= b; }); + return *this; } friend vec_base operator*(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] * b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] * b[i]; }); + return result; } template<typename FactorT> friend vec_base operator*(const vec_base &a, FactorT b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] * b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] * b; }); + return result; } friend vec_base operator*(T a, const vec_base &b) @@ -337,12 +343,14 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> vec_base &operator*=(T b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] *= b); + unroll<Size>([&](auto i) { (*this)[i] *= b; }); + return *this; } vec_base &operator*=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] *= b[i]); + unroll<Size>([&](auto i) { (*this)[i] *= b[i]; }); + return *this; } friend vec_base operator/(const vec_base &a, const vec_base &b) @@ -350,13 +358,17 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> for (int i = 0; i < Size; i++) { BLI_assert(b[i] != T(0)); } - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] / b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] / b[i]; }); + return result; } friend vec_base operator/(const vec_base &a, T b) { BLI_assert(b != T(0)); - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] / b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] / b; }); + return result; } friend vec_base operator/(T a, const vec_base &b) @@ -364,31 +376,39 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> for (int i = 0; i < Size; i++) { BLI_assert(b[i] != T(0)); } - BLI_VEC_OP_IMPL(ret, i, ret[i] = a / b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a / b[i]; }); + return result; } vec_base &operator/=(T b) { BLI_assert(b != T(0)); - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] /= b); + unroll<Size>([&](auto i) { (*this)[i] /= b; }); + return *this; } vec_base &operator/=(const vec_base &b) { BLI_assert(b != T(0)); - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] /= b[i]); + unroll<Size>([&](auto i) { (*this)[i] /= b[i]; }); + return *this; } /** Binary operators. */ BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] & b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] & b[i]; }); + return result; } BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, T b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] & b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] & b; }); + return result; } BLI_INT_OP(T) friend vec_base operator&(T a, const vec_base &b) @@ -398,22 +418,28 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> BLI_INT_OP(T) vec_base &operator&=(T b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] &= b); + unroll<Size>([&](auto i) { (*this)[i] &= b; }); + return *this; } BLI_INT_OP(T) vec_base &operator&=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] &= b[i]); + unroll<Size>([&](auto i) { (*this)[i] &= b[i]; }); + return *this; } BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] | b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] | b[i]; }); + return result; } BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, T b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] | b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] | b; }); + return result; } BLI_INT_OP(T) friend vec_base operator|(T a, const vec_base &b) @@ -423,22 +449,28 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> BLI_INT_OP(T) vec_base &operator|=(T b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] |= b); + unroll<Size>([&](auto i) { (*this)[i] |= b; }); + return *this; } BLI_INT_OP(T) vec_base &operator|=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] |= b[i]); + unroll<Size>([&](auto i) { (*this)[i] |= b[i]; }); + return *this; } BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] ^ b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] ^ b[i]; }); + return result; } BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, T b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] ^ b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] ^ b; }); + return result; } BLI_INT_OP(T) friend vec_base operator^(T a, const vec_base &b) @@ -448,59 +480,75 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> BLI_INT_OP(T) vec_base &operator^=(T b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] ^= b); + unroll<Size>([&](auto i) { (*this)[i] ^= b; }); + return *this; } BLI_INT_OP(T) vec_base &operator^=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] ^= b[i]); + unroll<Size>([&](auto i) { (*this)[i] ^= b[i]; }); + return *this; } BLI_INT_OP(T) friend vec_base operator~(const vec_base &a) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = ~a[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = ~a[i]; }); + return result; } /** Bit-shift operators. */ BLI_INT_OP(T) friend vec_base operator<<(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] << b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] << b[i]; }); + return result; } BLI_INT_OP(T) friend vec_base operator<<(const vec_base &a, T b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] << b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] << b; }); + return result; } BLI_INT_OP(T) vec_base &operator<<=(T b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] <<= b); + unroll<Size>([&](auto i) { (*this)[i] <<= b; }); + return *this; } BLI_INT_OP(T) vec_base &operator<<=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] <<= b[i]); + unroll<Size>([&](auto i) { (*this)[i] <<= b[i]; }); + return *this; } BLI_INT_OP(T) friend vec_base operator>>(const vec_base &a, const vec_base &b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] >> b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] >> b[i]; }); + return result; } BLI_INT_OP(T) friend vec_base operator>>(const vec_base &a, T b) { - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] >> b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] >> b; }); + return result; } BLI_INT_OP(T) vec_base &operator>>=(T b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] >>= b); + unroll<Size>([&](auto i) { (*this)[i] >>= b; }); + return *this; } BLI_INT_OP(T) vec_base &operator>>=(const vec_base &b) { - BLI_VEC_OP_IMPL_SELF(i, (*this)[i] >>= b[i]); + unroll<Size>([&](auto i) { (*this)[i] >>= b[i]; }); + return *this; } /** Modulo operators. */ @@ -510,24 +558,28 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> for (int i = 0; i < Size; i++) { BLI_assert(b[i] != T(0)); } - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] % b[i]; }); + return result; } BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, T b) { BLI_assert(b != 0); - BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a[i] % b; }); + return result; } BLI_INT_OP(T) friend vec_base operator%(T a, const vec_base &b) { BLI_assert(b != T(0)); - BLI_VEC_OP_IMPL(ret, i, ret[i] = a % b[i]); + vec_base result; + unroll<Size>([&](auto i) { result[i] = a % b[i]; }); + return result; } #undef BLI_INT_OP -#undef BLI_VEC_OP_IMPL -#undef BLI_VEC_OP_IMPL_SELF /** Compare. */ @@ -567,6 +619,11 @@ template<typename T, int Size> struct vec_base : public vec_struct_base<T, Size> } }; +using char3 = blender::vec_base<int8_t, 3>; + +using uchar3 = blender::vec_base<uint8_t, 3>; +using uchar4 = blender::vec_base<uint8_t, 4>; + using int2 = vec_base<int32_t, 2>; using int3 = vec_base<int32_t, 3>; using int4 = vec_base<int32_t, 4>; @@ -575,7 +632,11 @@ using uint2 = vec_base<uint32_t, 2>; using uint3 = vec_base<uint32_t, 3>; using uint4 = vec_base<uint32_t, 4>; +using short3 = blender::vec_base<int16_t, 3>; + using ushort2 = vec_base<uint16_t, 2>; +using ushort3 = blender::vec_base<uint16_t, 3>; +using ushort4 = blender::vec_base<uint16_t, 4>; using float2 = vec_base<float, 2>; using float3 = vec_base<float, 3>; diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 0b178064a4c..17fe25ec67b 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -155,7 +155,7 @@ MINLINE void mul_v3_v3db_db(double r[3], const double a[3], double f); MINLINE void mul_v2_v2(float r[2], const float a[2]); MINLINE void mul_v2_v2v2(float r[2], const float a[2], const float b[2]); MINLINE void mul_v3_v3(float r[3], const float a[3]); -MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3]); +MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3]); MINLINE void mul_v4_fl(float r[4], float f); MINLINE void mul_v4_v4(float r[4], const float a[4]); MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f); @@ -271,10 +271,10 @@ MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_manhattan_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT; MINLINE int len_manhattan_v2_int(const int v[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT; MINLINE double len_v2_db(const double v[2]) ATTR_WARN_UNUSED_RESULT; -MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; -MINLINE double len_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE double len_v2v2_db(const double v1[2], const double v2[2]) ATTR_WARN_UNUSED_RESULT; MINLINE float len_v2v2_int(const int v1[2], const int v2[2]); MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE double len_squared_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT; @@ -288,22 +288,22 @@ MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESU MINLINE double len_v3_db(const double a[3]) ATTR_WARN_UNUSED_RESULT; MINLINE double len_squared_v3_db(const double v[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE float normalize_v2_length(float r[2], float unit_scale); +MINLINE float normalize_v2_length(float n[2], float unit_length); /** * \note any vectors containing `nan` will be zeroed out. */ -MINLINE float normalize_v2_v2_length(float r[2], const float a[2], float unit_scale); -MINLINE float normalize_v3_length(float r[3], float unit_scale); +MINLINE float normalize_v2_v2_length(float r[2], const float a[2], float unit_length); +MINLINE float normalize_v3_length(float n[3], float unit_length); /** * \note any vectors containing `nan` will be zeroed out. */ -MINLINE float normalize_v3_v3_length(float r[3], const float a[3], float unit_scale); -MINLINE double normalize_v3_length_db(double n[3], double unit_scale); -MINLINE double normalize_v3_v3_length_db(double r[3], const double a[3], double unit_scale); +MINLINE float normalize_v3_v3_length(float r[3], const float a[3], float unit_length); +MINLINE double normalize_v3_length_db(double n[3], double unit_length); +MINLINE double normalize_v3_v3_length_db(double r[3], const double a[3], double unit_length); -MINLINE float normalize_v2(float r[2]); +MINLINE float normalize_v2(float n[2]); MINLINE float normalize_v2_v2(float r[2], const float a[2]); -MINLINE float normalize_v3(float r[3]); +MINLINE float normalize_v3(float n[3]); MINLINE float normalize_v3_v3(float r[3], const float a[3]); MINLINE double normalize_v3_v3_db(double r[3], const double a[3]); MINLINE double normalize_v3_db(double n[3]); @@ -424,45 +424,51 @@ void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]); /** \name Comparison * \{ */ -MINLINE bool is_zero_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool is_zero_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v4(const float v[4]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool is_zero_v2_db(const double a[2]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool is_zero_v3_db(const double a[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool is_zero_v4_db(const double a[4]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v2_db(const double v[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v3_db(const double v[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v4_db(const double v[4]) ATTR_WARN_UNUSED_RESULT; -bool is_finite_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT; -bool is_finite_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; -bool is_finite_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT; +bool is_finite_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT; +bool is_finite_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; +bool is_finite_v4(const float v[4]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool is_one_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_one_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool equals_v4v4(const float v1[4], const float v2[4]) ATTR_WARN_UNUSED_RESULT; MINLINE bool equals_v2v2_int(const int v1[2], const int v2[2]) ATTR_WARN_UNUSED_RESULT; MINLINE bool equals_v3v3_int(const int v1[3], const int v2[3]) ATTR_WARN_UNUSED_RESULT; MINLINE bool equals_v4v4_int(const int v1[4], const int v2[4]) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_v2v2(const float a[2], const float b[2], float limit) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_v3v3(const float a[3], const float b[3], float limit) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_v4v4(const float a[4], const float b[4], float limit) ATTR_WARN_UNUSED_RESULT; - -MINLINE bool compare_v2v2_relative(const float a[2], const float b[2], float limit, int max_ulps) +MINLINE bool compare_v2v2(const float v1[2], + const float v2[2], + float limit) ATTR_WARN_UNUSED_RESULT; +MINLINE bool compare_v3v3(const float v1[3], + const float v2[3], + float limit) ATTR_WARN_UNUSED_RESULT; +MINLINE bool compare_v4v4(const float v1[4], + const float v2[4], + float limit) ATTR_WARN_UNUSED_RESULT; + +MINLINE bool compare_v2v2_relative(const float v1[2], const float v2[2], float limit, int max_ulps) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_v3v3_relative(const float a[3], const float b[3], float limit, int max_ulps) +MINLINE bool compare_v3v3_relative(const float v1[3], const float v2[3], float limit, int max_ulps) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_v4v4_relative(const float a[4], const float b[4], float limit, int max_ulps) +MINLINE bool compare_v4v4_relative(const float v1[4], const float v2[4], float limit, int max_ulps) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_len_v3v3(const float a[3], - const float b[3], +MINLINE bool compare_len_v3v3(const float v1[3], + const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT; -MINLINE bool compare_size_v3v3(const float a[3], - const float b[3], +MINLINE bool compare_size_v3v3(const float v1[3], + const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT; /** @@ -606,8 +612,8 @@ void project_v3_plane(float out[3], const float plane_no[3], const float plane_c * out: result (negate for a 'bounce'). * </pre> */ -void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3]); -void reflect_v3_v3v3_db(double out[3], const double vec[3], const double normal[3]); +void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3]); +void reflect_v3_v3v3_db(double out[3], const double v[3], const double normal[3]); /** * Takes a vector and computes 2 orthogonal directions. * @@ -655,10 +661,10 @@ void print_vn(const char *str, const float v[], int n); #define print_v4_id(v) print_v4(STRINGIFY(v), v) #define print_vn_id(v, n) print_vn(STRINGIFY(v), v, n) -MINLINE void normal_float_to_short_v2(short r[2], const float n[2]); -MINLINE void normal_short_to_float_v3(float r[3], const short n[3]); -MINLINE void normal_float_to_short_v3(short r[3], const float n[3]); -MINLINE void normal_float_to_short_v4(short r[4], const float n[4]); +MINLINE void normal_float_to_short_v2(short out[2], const float in[2]); +MINLINE void normal_short_to_float_v3(float out[3], const short in[3]); +MINLINE void normal_float_to_short_v3(short out[3], const float in[3]); +MINLINE void normal_float_to_short_v4(short out[4], const float in[4]); void minmax_v4v4_v4(float min[4], float max[4], const float vec[4]); void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]); diff --git a/source/blender/blenlib/BLI_math_vector.hh b/source/blender/blenlib/BLI_math_vector.hh index 384c4b49070..e8303aa858b 100644 --- a/source/blender/blenlib/BLI_math_vector.hh +++ b/source/blender/blenlib/BLI_math_vector.hh @@ -357,16 +357,16 @@ inline vec_base<T, 3> cross(const vec_base<T, 3> &a, const vec_base<T, 3> &b) inline vec_base<float, 3> cross_high_precision(const vec_base<float, 3> &a, const vec_base<float, 3> &b) { - return {(float)((double)a.y * b.z - (double)a.z * b.y), - (float)((double)a.z * b.x - (double)a.x * b.z), - (float)((double)a.x * b.y - (double)a.y * b.x)}; + return {float(double(a.y) * double(b.z) - double(a.z) * double(b.y)), + float(double(a.z) * double(b.x) - double(a.x) * double(b.z)), + float(double(a.x) * double(b.y) - double(a.y) * double(b.x))}; } template<typename T, BLI_ENABLE_IF((is_math_float_type<T>))> inline vec_base<T, 3> cross_poly(Span<vec_base<T, 3>> poly) { /* Newell's Method. */ - int nv = static_cast<int>(poly.size()); + int nv = int(poly.size()); if (nv < 3) { return vec_base<T, 3>(0, 0, 0); } diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index c2ad3ea761a..b6ffa6d8b4a 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -372,7 +372,7 @@ template<size_t Size, size_t Alignment> class AlignedBuffer { */ template<typename T, int64_t Size = 1> class TypedBuffer { private: - BLI_NO_UNIQUE_ADDRESS AlignedBuffer<sizeof(T) * (size_t)Size, alignof(T)> buffer_; + BLI_NO_UNIQUE_ADDRESS AlignedBuffer<sizeof(T) * size_t(Size), alignof(T)> buffer_; public: operator T *() @@ -516,7 +516,7 @@ inline constexpr bool is_same_any_v = (std::is_same_v<T, Args> || ...); */ inline constexpr int64_t default_inline_buffer_capacity(size_t element_size) { - return (static_cast<int64_t>(element_size) < 100) ? 4 : 0; + return (int64_t(element_size) < 100) ? 4 : 0; } /** diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh index 22ea83760aa..4ed1fe5f513 100644 --- a/source/blender/blenlib/BLI_mesh_intersect.hh +++ b/source/blender/blenlib/BLI_mesh_intersect.hh @@ -354,12 +354,12 @@ struct BoundingBox { void combine(const double3 &p) { - min.x = min_ff(min.x, static_cast<float>(p.x)); - min.y = min_ff(min.y, static_cast<float>(p.y)); - min.z = min_ff(min.z, static_cast<float>(p.z)); - max.x = max_ff(max.x, static_cast<float>(p.x)); - max.y = max_ff(max.y, static_cast<float>(p.y)); - max.z = max_ff(max.z, static_cast<float>(p.z)); + min.x = min_ff(min.x, float(p.x)); + min.y = min_ff(min.y, float(p.y)); + min.z = min_ff(min.z, float(p.z)); + max.x = max_ff(max.x, float(p.x)); + max.y = max_ff(max.y, float(p.y)); + max.z = max_ff(max.z, float(p.z)); } void combine(const BoundingBox &bb) diff --git a/source/blender/blenlib/BLI_multi_value_map.hh b/source/blender/blenlib/BLI_multi_value_map.hh index 4b6300c09aa..81b536e7d3c 100644 --- a/source/blender/blenlib/BLI_multi_value_map.hh +++ b/source/blender/blenlib/BLI_multi_value_map.hh @@ -115,6 +115,14 @@ template<typename Key, typename Value> class MultiValueMap { } /** + * Get the number of keys. + */ + int64_t size() const + { + return map_.size(); + } + + /** * NOTE: This signature will change when the implementation changes. */ typename MapType::ItemIterator items() const @@ -137,6 +145,11 @@ template<typename Key, typename Value> class MultiValueMap { { return map_.values(); } + + void clear() + { + map_.clear(); + } }; } // namespace blender diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 06dd9ab0db9..d4d2ddead71 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -7,7 +7,9 @@ */ #include "BLI_compiler_attrs.h" +#include "BLI_compiler_compat.h" #include "BLI_utildefines.h" +#include "BLI_utildefines_variadic.h" #ifdef __cplusplus extern "C" { @@ -36,16 +38,6 @@ void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); const char *BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; /** - * Returns in `string` the concatenation of `dir` and `file` (also with `relabase` on the - * front if specified and `dir` begins with "//"). Normalizes all occurrences of path - * separators, including ensuring there is exactly one between the copies of `dir` and `file`, - * and between the copies of `relabase` and `dir`. - * - * \param relabase: Optional prefix to substitute for "//" on front of `dir`. - * \param string: Area to return result. - */ -void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); -/** * Ensures that the parent directory of `name` exists. * * \return true on success (i.e. given path now exists on file-system), false otherwise. @@ -79,26 +71,116 @@ const char *BLI_path_extension(const char *filepath) ATTR_NONNULL(); */ void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file) ATTR_NONNULL(); + /** - * Simple appending of filename to dir, does not check for valid path! - * Puts result into `dst`, which may be same area as `dir`. - * - * \note Consider using #BLI_path_join for more general path joining - * that de-duplicates separators and can handle an arbitrary number of paths. + * See #BLI_path_join doc-string. */ -void BLI_join_dirfile(char *__restrict dst, - size_t maxlen, - const char *__restrict dir, - const char *__restrict file) ATTR_NONNULL(); +size_t BLI_path_join_array(char *__restrict dst, + const size_t dst_len, + const char *path_array[], + const int path_array_num); + /** * Join multiple strings into a path, ensuring only a single path separator between each, * and trailing slash is kept. * + * \param path: The first patch which has special treatment, + * allowing `//` prefix which is kept intact unlike double-slashes which are stripped + * from the bounds of all other paths passed in. + * Passing in the following paths all result in the same output (`//a/b/c`): + * - `"//", "a", "b", "c"`. + * - `"//", "/a/", "/b/", "/c"`. + * - `"//a", "b/c"`. + * * \note If you want a trailing slash, add `SEP_STR` as the last path argument, * duplicate slashes will be cleaned up. */ -size_t BLI_path_join(char *__restrict dst, size_t dst_len, const char *path_first, ...) - ATTR_NONNULL(1, 3) ATTR_SENTINEL(0); +#define BLI_path_join(...) VA_NARGS_CALL_OVERLOAD(_BLI_path_join_, __VA_ARGS__) + +#define _BLI_PATH_JOIN_ARGS_1 char *__restrict dst, size_t dst_len, const char *a +#define _BLI_PATH_JOIN_ARGS_2 _BLI_PATH_JOIN_ARGS_1, const char *b +#define _BLI_PATH_JOIN_ARGS_3 _BLI_PATH_JOIN_ARGS_2, const char *c +#define _BLI_PATH_JOIN_ARGS_4 _BLI_PATH_JOIN_ARGS_3, const char *d +#define _BLI_PATH_JOIN_ARGS_5 _BLI_PATH_JOIN_ARGS_4, const char *e +#define _BLI_PATH_JOIN_ARGS_6 _BLI_PATH_JOIN_ARGS_5, const char *f +#define _BLI_PATH_JOIN_ARGS_7 _BLI_PATH_JOIN_ARGS_6, const char *g +#define _BLI_PATH_JOIN_ARGS_8 _BLI_PATH_JOIN_ARGS_7, const char *h +#define _BLI_PATH_JOIN_ARGS_9 _BLI_PATH_JOIN_ARGS_8, const char *i +#define _BLI_PATH_JOIN_ARGS_10 _BLI_PATH_JOIN_ARGS_9, const char *j + +BLI_INLINE size_t _BLI_path_join_3(_BLI_PATH_JOIN_ARGS_1) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_4(_BLI_PATH_JOIN_ARGS_2) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_5(_BLI_PATH_JOIN_ARGS_3) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_6(_BLI_PATH_JOIN_ARGS_4) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_7(_BLI_PATH_JOIN_ARGS_5) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_8(_BLI_PATH_JOIN_ARGS_6) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_9(_BLI_PATH_JOIN_ARGS_7) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_10(_BLI_PATH_JOIN_ARGS_8) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_11(_BLI_PATH_JOIN_ARGS_9) ATTR_NONNULL(); +BLI_INLINE size_t _BLI_path_join_12(_BLI_PATH_JOIN_ARGS_10) ATTR_NONNULL(); + +BLI_INLINE size_t _BLI_path_join_3(_BLI_PATH_JOIN_ARGS_1) +{ + const char *path_array[] = {a}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_4(_BLI_PATH_JOIN_ARGS_2) +{ + const char *path_array[] = {a, b}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_5(_BLI_PATH_JOIN_ARGS_3) +{ + const char *path_array[] = {a, b, c}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_6(_BLI_PATH_JOIN_ARGS_4) +{ + const char *path_array[] = {a, b, c, d}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_7(_BLI_PATH_JOIN_ARGS_5) +{ + const char *path_array[] = {a, b, c, d, e}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_8(_BLI_PATH_JOIN_ARGS_6) +{ + const char *path_array[] = {a, b, c, d, e, f}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_9(_BLI_PATH_JOIN_ARGS_7) +{ + const char *path_array[] = {a, b, c, d, e, f, g}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_10(_BLI_PATH_JOIN_ARGS_8) +{ + const char *path_array[] = {a, b, c, d, e, f, g, h}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_11(_BLI_PATH_JOIN_ARGS_9) +{ + const char *path_array[] = {a, b, c, d, e, f, g, h, i}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} +BLI_INLINE size_t _BLI_path_join_12(_BLI_PATH_JOIN_ARGS_10) +{ + const char *path_array[] = {a, b, c, d, e, f, g, h, i, j}; + return BLI_path_join_array(dst, dst_len, path_array, ARRAY_SIZE(path_array)); +} + +#undef _BLI_PATH_JOIN_ARGS_1 +#undef _BLI_PATH_JOIN_ARGS_2 +#undef _BLI_PATH_JOIN_ARGS_3 +#undef _BLI_PATH_JOIN_ARGS_4 +#undef _BLI_PATH_JOIN_ARGS_5 +#undef _BLI_PATH_JOIN_ARGS_6 +#undef _BLI_PATH_JOIN_ARGS_7 +#undef _BLI_PATH_JOIN_ARGS_8 +#undef _BLI_PATH_JOIN_ARGS_9 +#undef _BLI_PATH_JOIN_ARGS_10 + /** * Like Python's `os.path.basename()` * @@ -108,10 +190,10 @@ size_t BLI_path_join(char *__restrict dst, size_t dst_len, const char *path_firs const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; /** * Get an element of the path at an index, eg: - * "/some/path/file.txt" where an index of: - * - 0 or -3: "some" - * - 1 or -2: "path" - * - 2 or -1: "file.txt" + * `/some/path/file.txt` where an index of: + * - 0 or -3: `some` + * - 1 or -2: `path` + * - 2 or -1: `file.txt` * * Ignores multiple slashes at any point in the path (including start/end). */ @@ -367,8 +449,8 @@ void BLI_path_normalize_unc(char *path_16, int maxlen); /** * Appends a suffix to the string, fitting it before the extension * - * string = Foo.png, suffix = 123, separator = _ - * Foo.png -> Foo_123.png + * string = `Foo.png`, suffix = `123`, separator = `_`. + * `Foo.png` -> `Foo_123.png`. * * \param string: original (and final) string * \param maxlen: Maximum length of string diff --git a/source/blender/blenlib/BLI_pool.hh b/source/blender/blenlib/BLI_pool.hh new file mode 100644 index 00000000000..8745c019db5 --- /dev/null +++ b/source/blender/blenlib/BLI_pool.hh @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bli + * + * A `blender::Pool` allows fast allocation and deallocation of many elements of the same type. + * + * It is compatible with types that are not movable. + * + * Freed elements memory will be reused by next allocations. + * Elements are allocated in chunks to reduce memory fragmentation and avoid reallocation. + */ + +#pragma once + +#include "BLI_stack.hh" +#include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" + +namespace blender { + +template<typename T, int64_t ChunkLen = 64> class Pool : NonCopyable { + private: + using Chunk = TypedBuffer<T, ChunkLen>; + + /** Allocated item buffer. */ + Vector<std::unique_ptr<Chunk>> values_; + /** List of freed elements to be use for the next allocations. A Stack is best here to avoid + * overhead when growing the free list. It also offers better cache performance than a queue + * since last added entries will be reused first. */ + Stack<T *, 0> free_list_; + + public: + ~Pool() + { + /* All elements need to be freed before freeing the pool. */ + BLI_assert(this->size() == 0); + } + + /** + * Construct an object inside this pool's memory. + */ + template<typename... ForwardT> T &construct(ForwardT &&...value) + { + if (free_list_.is_empty()) { + values_.append(std::make_unique<Chunk>()); + T *chunk_start = values_.last()->ptr(); + for (auto i : IndexRange(ChunkLen)) { + free_list_.push(chunk_start + i); + } + } + T *ptr = free_list_.pop(); + new (ptr) T(std::forward<ForwardT>(value)...); + return *ptr; + } + + /** + * Destroy the given element inside this memory pool. Memory will be reused by next element + * construction. This invokes undefined behavior if the item is not from this pool. + */ + void destruct(T &value) + { + value.~T(); + free_list_.push(&value); + } + + /** + * Return the number of constructed elements in this pool. + */ + int64_t size() const + { + return values_.size() * ChunkLen - free_list_.size(); + } + + /** + * Returns true when the pool contains no elements, otherwise false. + */ + bool is_empty() const + { + return this->size() == 0; + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_probing_strategies.hh b/source/blender/blenlib/BLI_probing_strategies.hh index c6152e4d03d..d11bed9208e 100644 --- a/source/blender/blenlib/BLI_probing_strategies.hh +++ b/source/blender/blenlib/BLI_probing_strategies.hh @@ -2,6 +2,8 @@ #pragma once +#include <numeric> + /** \file * \ingroup bli * @@ -20,7 +22,7 @@ * clustering issues. However, more linear steps can also make things slower when the initial hash * produces many collisions. * - * Every probing strategy has to guarantee, that every possible uint64_t is returned eventually. + * Every probing strategy has to guarantee that every possible uint64_t is returned eventually. * This is necessary for correctness. If this is not the case, empty slots might not be found. * * The SLOT_PROBING_BEGIN and SLOT_PROBING_END macros can be used to implement a loop that iterates @@ -69,7 +71,7 @@ class LinearProbingStrategy { int64_t linear_steps() const { - return UINT32_MAX; + return std::numeric_limits<int64_t>::max(); } }; @@ -221,7 +223,7 @@ using DefaultProbingStrategy = PythonProbingStrategy<>; int64_t linear_offset = 0; \ uint64_t current_hash = probing_strategy.get(); \ do { \ - int64_t R_SLOT_INDEX = static_cast<int64_t>((current_hash + static_cast<uint64_t>(linear_offset)) & MASK); + int64_t R_SLOT_INDEX = int64_t((current_hash + uint64_t(linear_offset)) & MASK); #define SLOT_PROBING_END() \ } while (++linear_offset < probing_strategy.linear_steps()); \ diff --git a/source/blender/blenlib/BLI_rand.hh b/source/blender/blenlib/BLI_rand.hh index 2c4484bd63f..e4f35bef217 100644 --- a/source/blender/blenlib/BLI_rand.hh +++ b/source/blender/blenlib/BLI_rand.hh @@ -29,7 +29,7 @@ class RandomNumberGenerator { void seed(uint32_t seed) { constexpr uint64_t lowseed = 0x330E; - x_ = (static_cast<uint64_t>(seed) << 16) | lowseed; + x_ = (uint64_t(seed) << 16) | lowseed; } /** @@ -40,13 +40,13 @@ class RandomNumberGenerator { uint32_t get_uint32() { this->step(); - return static_cast<uint32_t>(x_ >> 17); + return uint32_t(x_ >> 17); } int32_t get_int32() { this->step(); - return static_cast<int32_t>(x_ >> 17); + return int32_t(x_ >> 17); } /** @@ -63,7 +63,7 @@ class RandomNumberGenerator { */ double get_double() { - return (double)this->get_int32() / 0x80000000; + return double(this->get_int32()) / 0x80000000; } /** diff --git a/source/blender/blenlib/BLI_resource_scope.hh b/source/blender/blenlib/BLI_resource_scope.hh index 9826b694e16..d3f6d5e3f13 100644 --- a/source/blender/blenlib/BLI_resource_scope.hh +++ b/source/blender/blenlib/BLI_resource_scope.hh @@ -128,7 +128,7 @@ template<typename Func> inline void ResourceScope::add_destruct_call(Func func) { void *buffer = allocator_.allocate(sizeof(Func), alignof(Func)); new (buffer) Func(std::move(func)); - this->add(buffer, [](void *data) { (*(Func *)data)(); }); + this->add(buffer, [](void *data) { (*static_cast<Func *>(data))(); }); } /** diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 04ac7cb05e4..b5b100ac27d 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -82,7 +82,7 @@ struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v2); enum { - /* NOTE(campbell): using BLI_SCANFILL_CALC_REMOVE_DOUBLES + /* NOTE(@campbellbarton): using #BLI_SCANFILL_CALC_REMOVE_DOUBLES * Assumes ordered edges, otherwise we risk an eternal loop * removing double verts. */ BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1), diff --git a/source/blender/blenlib/BLI_serialize.hh b/source/blender/blenlib/BLI_serialize.hh index bd91c522d06..e23d7d20d0b 100644 --- a/source/blender/blenlib/BLI_serialize.hh +++ b/source/blender/blenlib/BLI_serialize.hh @@ -55,7 +55,6 @@ * * To add a new formatter a new sub-class of `Formatter` must be created and the * `serialize`/`deserialize` methods should be implemented. - * */ #include <ostream> @@ -110,7 +109,6 @@ using ArrayValue = ContainerValue<Vector<std::shared_ptr<Value>>, eValueType::Ar * - `DoubleValue`: contains a double precision floating point number. * - `DictionaryValue`: represents an object (key value pairs where keys are strings and values can * be of different types. - * */ class Value { private: diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh index 62de4b79e41..8fb618edeb6 100644 --- a/source/blender/blenlib/BLI_set.hh +++ b/source/blender/blenlib/BLI_set.hh @@ -427,10 +427,10 @@ class Set { return *this; } - Iterator operator++(int) const + Iterator operator++(int) { Iterator copied_iterator = *this; - ++copied_iterator; + ++(*this); return copied_iterator; } @@ -493,6 +493,24 @@ class Set { } /** + * Remove all values for which the given predicate is true. + * + * This is similar to std::erase_if. + */ + template<typename Predicate> void remove_if(Predicate &&predicate) + { + for (Slot &slot : slots_) { + if (slot.is_occupied()) { + const Key &key = *slot.key(); + if (predicate(key)) { + slot.remove(); + removed_slots_++; + } + } + } + } + + /** * Print common statistics like size and collision count. This is useful for debugging purposes. */ void print_stats(StringRef name = "") const @@ -626,7 +644,7 @@ class Set { max_load_factor_.compute_total_and_usable_slots( SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots); BLI_assert(total_slots >= 1); - const uint64_t new_slot_mask = static_cast<uint64_t>(total_slots) - 1; + const uint64_t new_slot_mask = uint64_t(total_slots) - 1; /** * Optimize the case when the set was empty beforehand. We can avoid some copies here. @@ -854,7 +872,7 @@ template<typename Key> class StdUnorderedSetWrapper { public: int64_t size() const { - return static_cast<int64_t>(set_.size()); + return int64_t(set_.size()); } bool is_empty() const @@ -899,7 +917,7 @@ template<typename Key> class StdUnorderedSetWrapper { bool remove(const Key &key) { - return (bool)set_.erase(key); + return bool(set_.erase(key)); } void remove_contained(const Key &key) diff --git a/source/blender/blenlib/BLI_set_slots.hh b/source/blender/blenlib/BLI_set_slots.hh index 805c194ac90..8ef49e0a2d0 100644 --- a/source/blender/blenlib/BLI_set_slots.hh +++ b/source/blender/blenlib/BLI_set_slots.hh @@ -129,7 +129,7 @@ template<typename Key> class SimpleSetSlot { * key. The hash is used by other slot implementations to determine inequality faster. */ template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t /*hash*/) const { if (state_ == Occupied) { return is_equal(key, *key_buffer_); @@ -141,7 +141,7 @@ template<typename Key> class SimpleSetSlot { * Change the state of this slot from empty/removed to occupied. The key has to be constructed * by calling the constructor with the given key as parameter. */ - template<typename ForwardKey> void occupy(ForwardKey &&key, uint64_t UNUSED(hash)) + template<typename ForwardKey> void occupy(ForwardKey &&key, uint64_t /*hash*/) { BLI_assert(!this->is_occupied()); new (&key_buffer_) Key(std::forward<ForwardKey>(key)); @@ -226,7 +226,7 @@ template<typename Key> class HashedSetSlot { return state_ == Empty; } - template<typename Hash> uint64_t get_hash(const Hash &UNUSED(hash)) const + template<typename Hash> uint64_t get_hash(const Hash & /*hash*/) const { BLI_assert(this->is_occupied()); return hash_; @@ -306,13 +306,13 @@ template<typename Key, typename KeyInfo> class IntrusiveSetSlot { } template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t /*hash*/) const { BLI_assert(KeyInfo::is_not_empty_or_removed(key)); return is_equal(key_, key); } - template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t UNUSED(hash)) + template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t /*hash*/) { BLI_assert(!this->is_occupied()); BLI_assert(KeyInfo::is_not_empty_or_removed(key)); diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index 0f3fcea1270..adfccd8d6fe 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -112,13 +112,11 @@ template<typename T> class Span { * Span<int> span = {1, 2, 3, 4}; * call_function_with_array(span); */ - constexpr Span(const std::initializer_list<T> &list) - : Span(list.begin(), static_cast<int64_t>(list.size())) + constexpr Span(const std::initializer_list<T> &list) : Span(list.begin(), int64_t(list.size())) { } - constexpr Span(const std::vector<T> &vector) - : Span(vector.data(), static_cast<int64_t>(vector.size())) + constexpr Span(const std::vector<T> &vector) : Span(vector.data(), int64_t(vector.size())) { } @@ -718,7 +716,7 @@ template<typename T> class MutableSpan { { BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0); int64_t new_size = size_ * sizeof(T) / sizeof(NewT); - return MutableSpan<NewT>((NewT *)data_, new_size); + return MutableSpan<NewT>(reinterpret_cast<NewT *>(data_), new_size); } }; diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h index 8489871d5da..cc5b5dce363 100644 --- a/source/blender/blenlib/BLI_strict_flags.h +++ b/source/blender/blenlib/BLI_strict_flags.h @@ -9,16 +9,12 @@ */ #ifdef __GNUC__ -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ +/* NOTE(@campbellbarton): CLANG behaves slightly differently to GCC, + * these can be enabled but do so carefully as they can introduce build-errors. */ +# if !defined(__clang__) # pragma GCC diagnostic error "-Wsign-compare" -# endif -# if __GNUC__ >= 6 /* gcc6+ only */ # pragma GCC diagnostic error "-Wconversion" -# endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 -/* gcc4.8+ only (behavior changed to ignore globals). */ # pragma GCC diagnostic error "-Wshadow" -/* older gcc changed behavior with ternary */ # pragma GCC diagnostic error "-Wsign-conversion" # endif /* pedantic gives too many issues, developers can define this for own use */ diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 15926e8f2d2..17abcf52ecc 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -309,6 +309,28 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) A */ void BLI_str_format_decimal_unit(char dst[7], int number_to_format) ATTR_NONNULL(); /** + * Format a count to up to 3 places (plus minus sign, plus '\0' terminator) string using long + * number names abbreviations. Used to produce a compact representation of large numbers as + * integers. + * + * It shows a lower bound instead of rounding the number. + * + * 1 -> 1 + * 15 -> 15 + * 155 -> 155 + * 1555 -> 1K + * 15555 -> 15K + * 155555 -> .1M + * 1555555 -> 1M + * 15555555 -> 15M + * 155555555 -> .1B + * 1000000000 -> 1B + * ... + * + * Length of 5 is the maximum of the resulting string, for example, `-15K\0`. + */ +void BLI_str_format_integer_unit(char dst[5], int number_to_format) ATTR_NONNULL(); +/** * Compare two strings without regard to case. * * \retval True if the strings are equal, false otherwise. diff --git a/source/blender/blenlib/BLI_string_cursor_utf8.h b/source/blender/blenlib/BLI_string_cursor_utf8.h index 70ba5da8e5a..9c0589b230a 100644 --- a/source/blender/blenlib/BLI_string_cursor_utf8.h +++ b/source/blender/blenlib/BLI_string_cursor_utf8.h @@ -25,6 +25,9 @@ typedef enum eStrCursorJumpDirection { bool BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos); bool BLI_str_cursor_step_prev_utf8(const char *str, size_t maxlen, int *pos); +bool BLI_str_cursor_step_next_utf32(const char32_t *str, size_t maxlen, int *pos); +bool BLI_str_cursor_step_prev_utf32(const char32_t *str, size_t maxlen, int *pos); + void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, int *pos, diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh index 3823bd02630..14dee54d730 100644 --- a/source/blender/blenlib/BLI_string_ref.hh +++ b/source/blender/blenlib/BLI_string_ref.hh @@ -178,12 +178,12 @@ constexpr StringRefBase::operator Span<char>() const */ inline StringRefBase::operator std::string() const { - return std::string(data_, static_cast<size_t>(size_)); + return std::string(data_, size_t(size_)); } constexpr StringRefBase::operator std::string_view() const { - return std::string_view(data_, static_cast<size_t>(size_)); + return std::string_view(data_, size_t(size_)); } constexpr const char *StringRefBase::begin() const @@ -209,7 +209,7 @@ constexpr IndexRange StringRefBase::index_range() const inline void StringRefBase::unsafe_copy(char *dst) const { if (size_ > 0) { - memcpy(dst, data_, static_cast<size_t>(size_)); + memcpy(dst, data_, size_t(size_)); } dst[size_] = '\0'; } @@ -308,86 +308,79 @@ constexpr int64_t index_or_npos_to_int64(size_t index) if (index == std::string_view::npos) { return StringRef::not_found; } - return static_cast<int64_t>(index); + return int64_t(index); } constexpr int64_t StringRefBase::find(char c, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64(std::string_view(*this).find(c, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find(c, size_t(pos))); } constexpr int64_t StringRefBase::find(StringRef str, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64(std::string_view(*this).find(str, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find(str, size_t(pos))); } constexpr int64_t StringRefBase::rfind(char c, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64(std::string_view(*this).rfind(c, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).rfind(c, size_t(pos))); } constexpr int64_t StringRefBase::rfind(StringRef str, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64(std::string_view(*this).rfind(str, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).rfind(str, size_t(pos))); } constexpr int64_t StringRefBase::find_first_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_first_of(chars, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_first_of(chars, size_t(pos))); } constexpr int64_t StringRefBase::find_first_of(char c, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_first_of(c, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_first_of(c, size_t(pos))); } constexpr int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_last_of(chars, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_last_of(chars, size_t(pos))); } constexpr int64_t StringRefBase::find_last_of(char c, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64(std::string_view(*this).find_last_of(c, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_last_of(c, size_t(pos))); } constexpr int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_first_not_of(chars, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_first_not_of(chars, size_t(pos))); } constexpr int64_t StringRefBase::find_first_not_of(char c, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_first_not_of(c, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_first_not_of(c, size_t(pos))); } constexpr int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_last_not_of(chars, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_last_not_of(chars, size_t(pos))); } constexpr int64_t StringRefBase::find_last_not_of(char c, int64_t pos) const { BLI_assert(pos >= 0); - return index_or_npos_to_int64( - std::string_view(*this).find_last_not_of(c, static_cast<size_t>(pos))); + return index_or_npos_to_int64(std::string_view(*this).find_last_not_of(c, size_t(pos))); } constexpr StringRef StringRefBase::trim() const @@ -440,15 +433,14 @@ constexpr StringRefNull::StringRefNull() : StringRefBase("", 0) constexpr StringRefNull::StringRefNull(const char *str, const int64_t size) : StringRefBase(str, size) { - BLI_assert(static_cast<int64_t>(strlen(str)) == size); + BLI_assert(int64_t(strlen(str)) == size); } /** * Construct a StringRefNull from a null terminated c-string. The pointer must not point to * NULL. */ -inline StringRefNull::StringRefNull(const char *str) - : StringRefBase(str, static_cast<int64_t>(strlen(str))) +inline StringRefNull::StringRefNull(const char *str) : StringRefBase(str, int64_t(strlen(str))) { BLI_assert(str != nullptr); BLI_assert(data_[size_] == '\0'); @@ -504,7 +496,7 @@ constexpr StringRef::StringRef(StringRefNull other) : StringRefBase(other.data() * Create a StringRef from a null-terminated c-string. */ constexpr StringRef::StringRef(const char *str) - : StringRefBase(str, str ? static_cast<int64_t>(std::char_traits<char>::length(str)) : 0) + : StringRefBase(str, str ? int64_t(std::char_traits<char>::length(str)) : 0) { } @@ -560,7 +552,7 @@ constexpr char StringRef::operator[](int64_t index) const * second point points to a smaller address than the first one. */ constexpr StringRef::StringRef(const char *begin, const char *one_after_end) - : StringRefBase(begin, static_cast<int64_t>(one_after_end - begin)) + : StringRefBase(begin, int64_t(one_after_end - begin)) { BLI_assert(begin <= one_after_end); } @@ -570,12 +562,12 @@ constexpr StringRef::StringRef(const char *begin, const char *one_after_end) * will point to uninitialized memory. */ inline StringRef::StringRef(const std::string &str) - : StringRefBase(str.data(), static_cast<int64_t>(str.size())) + : StringRefBase(str.data(), int64_t(str.size())) { } constexpr StringRef::StringRef(std::string_view view) - : StringRefBase(view.data(), static_cast<int64_t>(view.size())) + : StringRefBase(view.data(), int64_t(view.size())) { } @@ -593,7 +585,7 @@ inline std::ostream &operator<<(std::ostream &stream, StringRef ref) inline std::ostream &operator<<(std::ostream &stream, StringRefNull ref) { - stream << std::string(ref.data(), (size_t)ref.size()); + stream << std::string(ref.data(), size_t(ref.size())); return stream; } @@ -619,7 +611,7 @@ constexpr bool operator==(StringRef a, StringRef b) /* This also avoids passing null to the call below, which would results in an ASAN warning. */ return true; } - return STREQLEN(a.data(), b.data(), (size_t)a.size()); + return STREQLEN(a.data(), b.data(), size_t(a.size())); } constexpr bool operator!=(StringRef a, StringRef b) diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 4c5cc3fd9c5..61a21fd8bbf 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -157,8 +157,8 @@ size_t BLI_strnlen_utf8(const char *strc, size_t maxlen) ATTR_NONNULL(1) ATTR_WA size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, size_t maxncpy) ATTR_NONNULL(1, 2); -size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, - const char *__restrict src, +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, + const char *__restrict src_c, size_t maxncpy) ATTR_NONNULL(1, 2); /** @@ -174,17 +174,17 @@ int BLI_str_utf8_char_width_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NON size_t BLI_str_partition_utf8(const char *str, const unsigned int delim[], - const char **sep, - const char **suf) ATTR_NONNULL(1, 2, 3, 4); + const char **r_sep, + const char **r_suf) ATTR_NONNULL(1, 2, 3, 4); size_t BLI_str_rpartition_utf8(const char *str, const unsigned int delim[], - const char **sep, - const char **suf) ATTR_NONNULL(1, 2, 3, 4); + const char **r_sep, + const char **r_suf) ATTR_NONNULL(1, 2, 3, 4); size_t BLI_str_partition_ex_utf8(const char *str, const char *end, const unsigned int delim[], - const char **sep, - const char **suf, + const char **r_sep, + const char **r_suf, bool from_right) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 3, 4, 5); int BLI_str_utf8_offset_to_index(const char *str, int offset) ATTR_WARN_UNUSED_RESULT diff --git a/source/blender/blenlib/BLI_task.hh b/source/blender/blenlib/BLI_task.hh index 904dea66f7a..9f9a57be634 100644 --- a/source/blender/blenlib/BLI_task.hh +++ b/source/blender/blenlib/BLI_task.hh @@ -31,6 +31,7 @@ #endif #include "BLI_index_range.hh" +#include "BLI_lazy_threading.hh" #include "BLI_utildefines.h" namespace blender::threading { @@ -56,6 +57,7 @@ void parallel_for(IndexRange range, int64_t grain_size, const Function &function #ifdef WITH_TBB /* Invoking tbb for small workloads has a large overhead. */ if (range.size() >= grain_size) { + lazy_threading::send_hint(); tbb::parallel_for( tbb::blocked_range<int64_t>(range.first(), range.one_after_last(), grain_size), [&](const tbb::blocked_range<int64_t> &subrange) { @@ -78,6 +80,7 @@ Value parallel_reduce(IndexRange range, { #ifdef WITH_TBB if (range.size() >= grain_size) { + lazy_threading::send_hint(); return tbb::parallel_reduce( tbb::blocked_range<int64_t>(range.first(), range.one_after_last(), grain_size), identity, @@ -105,6 +108,23 @@ template<typename... Functions> void parallel_invoke(Functions &&...functions) #endif } +/** + * Same #parallel_invoke, but allows disabling threading dynamically. This is useful because when + * the individual functions do very little work, there is a lot of overhead from starting parallel + * tasks. + */ +template<typename... Functions> +void parallel_invoke(const bool use_threading, Functions &&...functions) +{ + if (use_threading) { + lazy_threading::send_hint(); + parallel_invoke(std::forward<Functions>(functions)...); + } + else { + (functions(), ...); + } +} + /** See #BLI_task_isolate for a description of what isolating a task means. */ template<typename Function> void isolate_task(const Function &function) { diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 7f9470a9111..98177876f87 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -589,7 +589,7 @@ extern "C" { /** Performs `offsetof(typeof(data), member) + sizeof((data)->member)` for non-gcc compilers. */ #define OFFSETOF_STRUCT_AFTER(_struct, _member) \ - ((((const char *)&((_struct)->_member)) - ((const char *)(_struct))) + \ + ((size_t)(((const char *)&((_struct)->_member)) - ((const char *)(_struct))) + \ sizeof((_struct)->_member)) /** @@ -786,24 +786,23 @@ extern bool BLI_memory_is_zero(const void *arr, size_t arr_size); extern "C++" { \ inline constexpr _enum_type operator|(_enum_type a, _enum_type b) \ { \ - return static_cast<_enum_type>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); \ + return (_enum_type)(uint64_t(a) | uint64_t(b)); \ } \ inline constexpr _enum_type operator&(_enum_type a, _enum_type b) \ { \ - return static_cast<_enum_type>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); \ + return (_enum_type)(uint64_t(a) & uint64_t(b)); \ } \ inline constexpr _enum_type operator~(_enum_type a) \ { \ - return static_cast<_enum_type>(~static_cast<uint64_t>(a) & \ - (2 * static_cast<uint64_t>(_max_enum_value) - 1)); \ + return (_enum_type)(~uint64_t(a) & (2 * uint64_t(_max_enum_value) - 1)); \ } \ inline _enum_type &operator|=(_enum_type &a, _enum_type b) \ { \ - return a = static_cast<_enum_type>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); \ + return a = (_enum_type)(uint64_t(a) | uint64_t(b)); \ } \ inline _enum_type &operator&=(_enum_type &a, _enum_type b) \ { \ - return a = static_cast<_enum_type>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); \ + return a = (_enum_type)(uint64_t(a) & uint64_t(b)); \ } \ } /* extern "C++" */ diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 1f5f97d754d..cba58945546 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -96,8 +96,7 @@ class Vector { */ #ifndef NDEBUG int64_t debug_size_; -# define UPDATE_VECTOR_SIZE(ptr) \ - (ptr)->debug_size_ = static_cast<int64_t>((ptr)->end_ - (ptr)->begin_) +# define UPDATE_VECTOR_SIZE(ptr) (ptr)->debug_size_ = int64_t((ptr)->end_ - (ptr)->begin_) #else # define UPDATE_VECTOR_SIZE(ptr) ((void)0) #endif @@ -244,7 +243,7 @@ class Vector { /* Copy from inline buffer to newly allocated buffer. */ const int64_t capacity = size; begin_ = static_cast<T *>( - allocator_.allocate(sizeof(T) * static_cast<size_t>(capacity), alignof(T), AT)); + allocator_.allocate(sizeof(T) * size_t(capacity), alignof(T), AT)); capacity_end_ = begin_ + capacity; uninitialized_relocate_n(other.begin_, size, begin_); end_ = begin_ + size; @@ -693,7 +692,7 @@ class Vector { */ int64_t size() const { - const int64_t current_size = static_cast<int64_t>(end_ - begin_); + const int64_t current_size = int64_t(end_ - begin_); BLI_assert(debug_size_ == current_size); return current_size; } @@ -806,6 +805,17 @@ class Vector { } /** + * Remove all values for which the given predicate is true. + * + * This is similar to std::erase_if. + */ + template<typename Predicate> void remove_if(Predicate &&predicate) + { + end_ = std::remove_if(this->begin(), this->end(), predicate); + UPDATE_VECTOR_SIZE(this); + } + + /** * Do a linear search to find the value in the vector. * When found, return the first index, otherwise return -1. */ @@ -813,7 +823,7 @@ class Vector { { for (const T *current = begin_; current != end_; current++) { if (*current == value) { - return static_cast<int64_t>(current - begin_); + return int64_t(current - begin_); } } return -1; @@ -905,7 +915,7 @@ class Vector { */ int64_t capacity() const { - return static_cast<int64_t>(capacity_end_ - begin_); + return int64_t(capacity_end_ - begin_); } /** @@ -975,7 +985,7 @@ class Vector { const int64_t size = this->size(); T *new_array = static_cast<T *>( - allocator_.allocate(static_cast<size_t>(new_capacity) * sizeof(T), alignof(T), AT)); + allocator_.allocate(size_t(new_capacity) * sizeof(T), alignof(T), AT)); try { uninitialized_relocate_n(begin_, size, new_array); } diff --git a/source/blender/blenlib/BLI_vector_adaptor.hh b/source/blender/blenlib/BLI_vector_adaptor.hh deleted file mode 100644 index 82d731aacd8..00000000000 --- a/source/blender/blenlib/BLI_vector_adaptor.hh +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup bli - * - * A `blender::VectorAdaptor` is a container with a fixed maximum size and does not own the - * underlying memory. When an adaptor is constructed, you have to provide it with an uninitialized - * array that will be filled when elements are added to the vector. The vector adaptor is not able - * to grow. Therefore, it is undefined behavior to add more elements than fit into the provided - * buffer. - */ - -#include "BLI_span.hh" - -namespace blender { - -template<typename T> class VectorAdaptor { - private: - T *begin_; - T *end_; - T *capacity_end_; - - public: - VectorAdaptor() : begin_(nullptr), end_(nullptr), capacity_end_(nullptr) - { - } - - VectorAdaptor(T *data, int64_t capacity, int64_t size = 0) - : begin_(data), end_(data + size), capacity_end_(data + capacity) - { - } - - VectorAdaptor(MutableSpan<T> span) : VectorAdaptor(span.data(), span.size(), 0) - { - } - - void append(const T &value) - { - BLI_assert(end_ < capacity_end_); - new (end_) T(value); - end_++; - } - - void append(T &&value) - { - BLI_assert(end_ < capacity_end_); - new (end_) T(std::move(value)); - end_++; - } - - void append_n_times(const T &value, int64_t n) - { - BLI_assert(end_ + n <= capacity_end_); - uninitialized_fill_n(end_, n, value); - end_ += n; - } - - void extend(Span<T> values) - { - BLI_assert(end_ + values.size() <= capacity_end_); - uninitialized_copy_n(values.data(), values.size(), end_); - end_ += values.size(); - } - - int64_t capacity() const - { - return capacity_end_ - begin_; - } - - int64_t size() const - { - return end_ - begin_; - } - - bool is_empty() const - { - return begin_ == end_; - } - - bool is_full() const - { - return end_ == capacity_end_; - } -}; - -} // namespace blender diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh index b0a3696f245..d182e1f1678 100644 --- a/source/blender/blenlib/BLI_vector_set.hh +++ b/source/blender/blenlib/BLI_vector_set.hh @@ -349,6 +349,25 @@ class VectorSet { } /** + * Remove all values for which the given predicate is true. This may change the order of elements + * in the vector. + * + * This is similar to std::erase_if. + */ + template<typename Predicate> void remove_if(Predicate &&predicate) + { + for (Slot &slot : slots_) { + if (slot.is_occupied()) { + const int64_t index = slot.index(); + const Key &key = keys_[index]; + if (predicate(key)) { + this->remove_key_internal(slot); + } + } + } + } + + /** * Delete and return a key from the set. This will remove the last element in the vector. The * order of the remaining elements in the set is not changed. */ @@ -358,7 +377,7 @@ class VectorSet { } /** - * Return the location of the key in the vector. It is assumed, that the key is in the vector + * Return the location of the key in the vector. It is assumed that the key is in the vector * set. If this is not necessarily the case, use `index_of_try`. */ int64_t index_of(const Key &key) const @@ -513,7 +532,7 @@ class VectorSet { */ int64_t size_in_bytes() const { - return static_cast<int64_t>(sizeof(Slot) * slots_.size() + sizeof(Key) * usable_slots_); + return int64_t(sizeof(Slot) * slots_.size() + sizeof(Key) * usable_slots_); } /** @@ -557,7 +576,7 @@ class VectorSet { max_load_factor_.compute_total_and_usable_slots( SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots); BLI_assert(total_slots >= 1); - const uint64_t new_slot_mask = static_cast<uint64_t>(total_slots) - 1; + const uint64_t new_slot_mask = uint64_t(total_slots) - 1; /* Optimize the case when the set was empty beforehand. We can avoid some copies here. */ if (this->size() == 0) { @@ -839,7 +858,7 @@ class VectorSet { Key *allocate_keys_array(const int64_t size) { return static_cast<Key *>( - slots_.allocator().allocate(sizeof(Key) * static_cast<size_t>(size), alignof(Key), AT)); + slots_.allocator().allocate(sizeof(Key) * size_t(size), alignof(Key), AT)); } void deallocate_keys_array(Key *keys) diff --git a/source/blender/blenlib/BLI_vector_set_slots.hh b/source/blender/blenlib/BLI_vector_set_slots.hh index 35dedd57705..cc7f5d1ff1e 100644 --- a/source/blender/blenlib/BLI_vector_set_slots.hh +++ b/source/blender/blenlib/BLI_vector_set_slots.hh @@ -73,7 +73,7 @@ template<typename Key> class SimpleVectorSetSlot { template<typename ForwardKey, typename IsEqual> bool contains(const ForwardKey &key, const IsEqual &is_equal, - uint64_t UNUSED(hash), + uint64_t /*hash*/, const Key *keys) const { if (state_ >= 0) { @@ -86,7 +86,7 @@ template<typename Key> class SimpleVectorSetSlot { * Change the state of this slot from empty/removed to occupied. The hash can be used by other * slot implementations. */ - void occupy(int64_t index, uint64_t UNUSED(hash)) + void occupy(int64_t index, uint64_t /*hash*/) { BLI_assert(!this->is_occupied()); state_ = index; diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 438fcc4b8f7..36f5065c022 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -23,6 +23,8 @@ * see of the increased compile time and binary size is worth it. */ +#include <optional> + #include "BLI_any.hh" #include "BLI_array.hh" #include "BLI_index_mask.hh" @@ -106,25 +108,7 @@ template<typename T> class VArrayImpl { */ virtual void materialize(IndexMask mask, MutableSpan<T> r_span) const { - T *dst = r_span.data(); - /* Optimize for a few different common cases. */ - const CommonVArrayInfo info = this->common_info(); - switch (info.type) { - case CommonVArrayInfo::Type::Any: { - mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); - break; - } - case CommonVArrayInfo::Type::Span: { - const T *src = static_cast<const T *>(info.data); - mask.foreach_index([&](const int64_t i) { dst[i] = src[i]; }); - break; - } - case CommonVArrayInfo::Type::Single: { - const T single = *static_cast<const T *>(info.data); - mask.foreach_index([&](const int64_t i) { dst[i] = single; }); - break; - } - } + mask.foreach_index([&](const int64_t i) { r_span[i] = this->get(i); }); } /** @@ -133,24 +117,7 @@ template<typename T> class VArrayImpl { virtual void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const { T *dst = r_span.data(); - /* Optimize for a few different common cases. */ - const CommonVArrayInfo info = this->common_info(); - switch (info.type) { - case CommonVArrayInfo::Type::Any: { - mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); }); - break; - } - case CommonVArrayInfo::Type::Span: { - const T *src = static_cast<const T *>(info.data); - mask.foreach_index([&](const int64_t i) { new (dst + i) T(src[i]); }); - break; - } - case CommonVArrayInfo::Type::Single: { - const T single = *static_cast<const T *>(info.data); - mask.foreach_index([&](const int64_t i) { new (dst + i) T(single); }); - break; - } - } + mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); }); } /** @@ -188,7 +155,7 @@ template<typename T> class VArrayImpl { * arrays in all cases. * Return true when the virtual array was assigned and false when nothing was done. */ - virtual bool try_assign_GVArray(GVArray &UNUSED(varray)) const + virtual bool try_assign_GVArray(GVArray & /*varray*/) const { return false; } @@ -197,7 +164,7 @@ template<typename T> class VArrayImpl { * Return true when the other virtual array should be considered to be the same, e.g. because it * shares the same underlying memory. */ - virtual bool is_same(const VArrayImpl<T> &UNUSED(other)) const + virtual bool is_same(const VArrayImpl<T> & /*other*/) const { return false; } @@ -234,7 +201,7 @@ template<typename T> class VMutableArrayImpl : public VArrayImpl<T> { /** * Similar to #VArrayImpl::try_assign_GVArray but for mutable virtual arrays. */ - virtual bool try_assign_GVMutableArray(GVMutableArray &UNUSED(varray)) const + virtual bool try_assign_GVMutableArray(GVMutableArray & /*varray*/) const { return false; } @@ -286,8 +253,20 @@ template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> { return data_ == static_cast<const T *>(other_info.data); } + void materialize(IndexMask mask, MutableSpan<T> r_span) const override + { + mask.foreach_index([&](const int64_t i) { r_span[i] = data_[i]; }); + } + + void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const override + { + T *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { new (dst + i) T(data_[i]); }); + } + void materialize_compressed(IndexMask mask, MutableSpan<T> r_span) const override { + BLI_assert(mask.size() == r_span.size()); mask.to_best_mask_type([&](auto best_mask) { for (const int64_t i : IndexRange(best_mask.size())) { r_span[i] = data_[best_mask[i]]; @@ -298,6 +277,7 @@ template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> { void materialize_compressed_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const override { + BLI_assert(mask.size() == r_span.size()); T *dst = r_span.data(); mask.to_best_mask_type([&](auto best_mask) { for (const int64_t i : IndexRange(best_mask.size())) { @@ -315,6 +295,12 @@ template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_F public: using VArrayImpl_For_Span<T>::VArrayImpl_For_Span; + VArrayImpl_For_Span_final(const Span<T> data) + /* Cast const away, because the implementation for const and non const spans is shared. */ + : VArrayImpl_For_Span<T>({const_cast<T *>(data.data()), data.size()}) + { + } + private: CommonVArrayInfo common_info() const final { @@ -338,7 +324,7 @@ class VArrayImpl_For_ArrayContainer : public VArrayImpl_For_Span<T> { public: VArrayImpl_For_ArrayContainer(Container container) - : VArrayImpl_For_Span<T>((int64_t)container.size()), container_(std::move(container)) + : VArrayImpl_For_Span<T>(int64_t(container.size())), container_(std::move(container)) { this->data_ = const_cast<T *>(container_.data()); } @@ -360,7 +346,7 @@ template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> { } protected: - T get(const int64_t UNUSED(index)) const override + T get(const int64_t /*index*/) const override { return value_; } @@ -370,6 +356,17 @@ template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> { return CommonVArrayInfo(CommonVArrayInfo::Type::Single, true, &value_); } + void materialize(IndexMask mask, MutableSpan<T> r_span) const override + { + r_span.fill_indices(mask, value_); + } + + void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const override + { + T *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { new (dst + i) T(value_); }); + } + void materialize_compressed(IndexMask mask, MutableSpan<T> r_span) const override { BLI_assert(mask.size() == r_span.size()); @@ -797,6 +794,18 @@ template<typename T> class VArrayCommon { } /** + * Return the value that is returned for every index, if the array is stored as a single value. + */ + std::optional<T> get_if_single() const + { + const CommonVArrayInfo info = impl_->common_info(); + if (info.type != CommonVArrayInfo::Type::Single) { + return std::nullopt; + } + return *static_cast<const T *>(info.data); + } + + /** * Return true when the other virtual references the same underlying memory. */ bool is_same(const VArrayCommon<T> &other) const @@ -898,10 +907,7 @@ template<typename T> class VArray : public VArrayCommon<T> { VArray(varray_tag::span /* tag */, Span<T> span) { - /* Cast const away, because the virtual array implementation for const and non const spans is - * shared. */ - MutableSpan<T> mutable_span{const_cast<T *>(span.data()), span.size()}; - this->template emplace<VArrayImpl_For_Span_final<T>>(mutable_span); + this->template emplace<VArrayImpl_For_Span_final<T>>(span); } VArray(varray_tag::single /* tag */, T value, const int64_t size) diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 7201e1bb4a1..34f1b1a68f1 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -48,11 +48,6 @@ extern "C" { # define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR) #endif -/* Defines for using ISO C++ conferment names. */ -#if !defined(_MSC_VER) || _MSC_VER < 1900 -# define snprintf _snprintf -#endif - #if defined(_MSC_VER) # define R_OK 4 # define W_OK 2 diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index d39a586206f..2ac77f000e9 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -1,8 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-or-later # Copyright 2006 Blender Foundation. All rights reserved. +if(HAVE_EXECINFO_H) + add_definitions(-DHAVE_EXECINFO_H) +endif() + set(INC . + .. # ../blenkernel # don't add this back! ../makesdna ../../../intern/atomic @@ -19,7 +24,6 @@ set(INC_SYS ) set(SRC - intern/BLI_args.c intern/BLI_array.c intern/BLI_assert.c intern/BLI_color.cc @@ -44,11 +48,13 @@ set(SRC intern/array_store.c intern/array_store_utils.c intern/array_utils.c + intern/array_utils.cc intern/astar.c intern/bitmap.c intern/bitmap_draw_2d.c intern/boxpack_2d.c intern/buffer.c + intern/compute_context.cc intern/convexhull_2d.c intern/cpp_type.cc intern/delaunay_2d.cc @@ -79,6 +85,7 @@ set(SRC intern/kdtree_3d.c intern/kdtree_4d.c intern/lasso_2d.c + intern/lazy_threading.cc intern/length_parameterize.cc intern/listbase.c intern/math_base.c @@ -155,15 +162,16 @@ set(SRC BLI_alloca.h BLI_allocator.hh BLI_any.hh - BLI_args.h BLI_array.h BLI_array.hh BLI_array_store.h BLI_array_store_utils.h BLI_array_utils.h + BLI_array_utils.hh BLI_asan.h BLI_assert.h BLI_astar.h + BLI_bit_vector.hh BLI_bitmap.h BLI_bitmap_draw_2d.h BLI_blenlib.h @@ -175,6 +183,7 @@ set(SRC BLI_compiler_attrs.h BLI_compiler_compat.h BLI_compiler_typecheck.h + BLI_compute_context.hh BLI_console.h BLI_convexhull_2d.h BLI_cpp_type.hh @@ -230,6 +239,7 @@ set(SRC BLI_kdtree.h BLI_kdtree_impl.h BLI_lasso_2d.h + BLI_lazy_threading.hh BLI_length_parameterize.hh BLI_linear_allocator.hh BLI_link_utils.h @@ -279,6 +289,7 @@ set(SRC BLI_path_util.h BLI_polyfill_2d.h BLI_polyfill_2d_beautify.h + BLI_pool.hh BLI_probing_strategies.hh BLI_quadric.h BLI_rand.h @@ -323,7 +334,6 @@ set(SRC BLI_uuid.h BLI_uvproject.h BLI_vector.hh - BLI_vector_adaptor.hh BLI_vector_set.hh BLI_vector_set_slots.hh BLI_virtual_array.hh @@ -347,6 +357,14 @@ set(LIB ${ZSTD_LIBRARIES} ) +if(NOT WITH_PYTHON_MODULE) + list(APPEND SRC + intern/BLI_args.c + + BLI_args.h + ) +endif() + if(WITH_MEM_VALGRIND) add_definitions(-DWITH_MEM_VALGRIND) endif() @@ -424,6 +442,7 @@ if(WITH_GTESTS) tests/BLI_array_store_test.cc tests/BLI_array_test.cc tests/BLI_array_utils_test.cc + tests/BLI_bit_vector_test.cc tests/BLI_bitmap_test.cc tests/BLI_bounds_test.cc tests/BLI_color_test.cc @@ -470,6 +489,7 @@ if(WITH_GTESTS) tests/BLI_multi_value_map_test.cc tests/BLI_path_util_test.cc tests/BLI_polyfill_2d_test.cc + tests/BLI_pool_test.cc tests/BLI_ressource_strings.h tests/BLI_serialize_test.cc tests/BLI_session_uuid_test.cc diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c index 61447ab1a9e..ceb7f7f0aba 100644 --- a/source/blender/blenlib/intern/BLI_args.c +++ b/source/blender/blenlib/intern/BLI_args.c @@ -57,7 +57,7 @@ static uint case_strhash(const void *ptr) { const char *s = ptr; uint i = 0; - unsigned char c; + uchar c; while ((c = tolower(*s++))) { i = i * 37 + c; @@ -80,7 +80,7 @@ static bool keycmp(const void *a, const void *b) if (ka->case_str == 1 || kb->case_str == 1) { return (BLI_strcasecmp(ka->arg, kb->arg) != 0); } - return (!STREQ(ka->arg, kb->arg)); + return !STREQ(ka->arg, kb->arg); } return BLI_ghashutil_intcmp((const void *)ka->pass, (const void *)kb->pass); } diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index c6178ebb3a0..4bcb023691a 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -93,7 +93,7 @@ static int bli_compare(struct direntry *entry1, struct direntry *entry2) return 1; } - return (BLI_strcasecmp_natural(entry1->relname, entry2->relname)); + return BLI_strcasecmp_natural(entry1->relname, entry2->relname); } struct BuildDirCtx { @@ -174,10 +174,10 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) struct direntry *file = &dir_ctx->files[dir_ctx->files_num]; while (dlink) { char fullname[PATH_MAX]; + BLI_path_join(fullname, sizeof(fullname), dirname, dlink->name); memset(file, 0, sizeof(struct direntry)); file->relname = dlink->name; - file->path = BLI_strdupcat(dirname, dlink->name); - BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); + file->path = BLI_strdup(fullname); if (BLI_stat(fullname, &file->s) != -1) { file->type = file->s.st_mode; } @@ -215,7 +215,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) } } -unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist) +uint BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist) { struct BuildDirCtx dir_ctx; @@ -395,9 +395,9 @@ void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *s void BLI_filelist_duplicate(struct direntry **dest_filelist, struct direntry *const src_filelist, - const unsigned int nrentries) + const uint nrentries) { - unsigned int i; + uint i; *dest_filelist = MEM_mallocN(sizeof(**dest_filelist) * (size_t)(nrentries), __func__); for (i = 0; i < nrentries; i++) { @@ -417,9 +417,9 @@ void BLI_filelist_entry_free(struct direntry *entry) } } -void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries) +void BLI_filelist_free(struct direntry *filelist, const uint nrentries) { - unsigned int i; + uint i; for (i = 0; i < nrentries; i++) { BLI_filelist_entry_free(&filelist[i]); } diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c index e12e272832f..806d58df260 100644 --- a/source/blender/blenlib/intern/BLI_ghash_utils.c +++ b/source/blender/blenlib/intern/BLI_ghash_utils.c @@ -63,7 +63,7 @@ uint BLI_ghashutil_uinthash_v4(const uint key[4]) uint BLI_ghashutil_uinthash_v4_murmur(const uint key[4]) { - return BLI_hash_mm2((const unsigned char *)key, sizeof(int[4]) /* sizeof(key) */, 0); + return BLI_hash_mm2((const uchar *)key, sizeof(int[4]) /* sizeof(key) */, 0); } bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) @@ -101,7 +101,7 @@ uint BLI_ghashutil_inthash_p_murmur(const void *ptr) { uintptr_t key = (uintptr_t)ptr; - return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0); + return BLI_hash_mm2((const uchar *)&key, sizeof(key), 0); } uint BLI_ghashutil_inthash_p_simple(const void *ptr) @@ -143,7 +143,7 @@ uint BLI_ghashutil_strhash_p(const void *ptr) } uint BLI_ghashutil_strhash_p_murmur(const void *ptr) { - const unsigned char *key = ptr; + const uchar *key = ptr; return BLI_hash_mm2(key, strlen((const char *)key) + 1, 0); } diff --git a/source/blender/blenlib/intern/BLI_index_range.cc b/source/blender/blenlib/intern/BLI_index_range.cc index 398228ab461..624dcc39fc5 100644 --- a/source/blender/blenlib/intern/BLI_index_range.cc +++ b/source/blender/blenlib/intern/BLI_index_range.cc @@ -44,4 +44,34 @@ Span<int64_t> IndexRange::as_span_internal() const return Span<int64_t>(s_current_array + start_, size_); } +AlignedIndexRanges split_index_range_by_alignment(const IndexRange range, const int64_t alignment) +{ + BLI_assert(is_power_of_2_i(alignment)); + const int64_t mask = alignment - 1; + + AlignedIndexRanges aligned_ranges; + + const int64_t start_chunk = range.start() & ~mask; + const int64_t end_chunk = range.one_after_last() & ~mask; + if (start_chunk == end_chunk) { + aligned_ranges.prefix = range; + } + else { + int64_t prefix_size = 0; + int64_t suffix_size = 0; + if (range.start() != start_chunk) { + prefix_size = alignment - (range.start() & mask); + } + if (range.one_after_last() != end_chunk) { + suffix_size = range.one_after_last() - end_chunk; + } + aligned_ranges.prefix = IndexRange(range.start(), prefix_size); + aligned_ranges.suffix = IndexRange(end_chunk, suffix_size); + aligned_ranges.aligned = IndexRange(aligned_ranges.prefix.one_after_last(), + range.size() - prefix_size - suffix_size); + } + + return aligned_ranges; +} + } // namespace blender diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 62bf17bd415..de71147f015 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -58,7 +58,7 @@ /** \name Struct Definitions * \{ */ -typedef unsigned char axis_t; +typedef uchar axis_t; typedef struct BVHNode { struct BVHNode **children; @@ -386,12 +386,12 @@ static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int e /* for all Axes. */ for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { newmin = node_bv[(2 * axis_iter)]; - if ((newmin < bv[(2 * axis_iter)])) { + if (newmin < bv[(2 * axis_iter)]) { bv[(2 * axis_iter)] = newmin; } newmax = node_bv[(2 * axis_iter) + 1]; - if ((newmax > bv[(2 * axis_iter) + 1])) { + if (newmax > bv[(2 * axis_iter) + 1]) { bv[(2 * axis_iter) + 1] = newmax; } } @@ -1385,7 +1385,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap( static bool tree_intersect_plane_test(const float *bv, const float plane[4]) { - /* TODO(germano): Support other KDOP geometries. */ + /* TODO(@germano): Support other KDOP geometries. */ const float bb_min[3] = {bv[0], bv[2], bv[4]}; const float bb_max[3] = {bv[1], bv[3], bv[5]}; float bb_near[3], bb_far[3]; diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 3b73a81012d..3c353a1c8c8 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -38,7 +38,7 @@ struct MemBuf { }; struct MemArena { - unsigned char *curbuf; + uchar *curbuf; const char *name; struct MemBuf *bufs; @@ -53,7 +53,7 @@ static void memarena_buf_free_all(struct MemBuf *mb) while (mb != NULL) { struct MemBuf *mb_next = mb->next; - /* Unpoison memory because MEM_freeN might overwrite it. */ + /* Unpoison memory because #MEM_freeN might overwrite it. */ BLI_asan_unpoison(mb, (uint)MEM_allocN_len(mb)); MEM_freeN(mb); @@ -106,9 +106,9 @@ void BLI_memarena_free(MemArena *ma) /** Align alloc'ed memory (needed if `align > 8`). */ static void memarena_curbuf_align(MemArena *ma) { - unsigned char *tmp; + uchar *tmp; - tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align); + tmp = (uchar *)PADUP((intptr_t)ma->curbuf, (int)ma->align); ma->cursize -= (size_t)(tmp - ma->curbuf); ma->curbuf = tmp; } @@ -158,6 +158,7 @@ void *BLI_memarena_calloc(MemArena *ma, size_t size) BLI_assert(ma->use_calloc == false); ptr = BLI_memarena_alloc(ma, size); + BLI_assert(ptr != NULL); memset(ptr, 0, size); return ptr; @@ -208,7 +209,7 @@ void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) void BLI_memarena_clear(MemArena *ma) { if (ma->bufs) { - unsigned char *curbuf_prev; + uchar *curbuf_prev; size_t curbuf_used; if (ma->bufs->next) { diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c index f780d520301..b03efd2b8a2 100644 --- a/source/blender/blenlib/intern/BLI_memblock.c +++ b/source/blender/blenlib/intern/BLI_memblock.c @@ -5,7 +5,6 @@ * \ingroup bli * * Dead simple, fast memory allocator for allocating many elements of the same size. - * */ #include <stdlib.h> diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 9a8bda48c8d..65518427656 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -736,17 +736,17 @@ static void bchunk_list_fill_from_array(const BArrayInfo *info, BLI_INLINE uint hash_data_single(const uchar p) { - return ((HASH_INIT << 5) + HASH_INIT) + (unsigned int)(*((signed char *)&p)); + return ((HASH_INIT << 5) + HASH_INIT) + (uint)(*((signed char *)&p)); } /* hash bytes, from BLI_ghashutil_strhash_n */ static uint hash_data(const uchar *key, size_t n) { const signed char *p; - unsigned int h = HASH_INIT; + uint h = HASH_INIT; for (p = (const signed char *)key; n--; p++) { - h = ((h << 5) + h) + (unsigned int)*p; + h = (uint)((h << 5) + h) + (uint)*p; } return h; @@ -805,7 +805,7 @@ static void hash_array_from_cref(const BArrayInfo *info, static void hash_accum(hash_key *hash_array, const size_t hash_array_len, size_t iter_steps) { /* _very_ unlikely, can happen if you select a chunk-size of 1 for example. */ - if (UNLIKELY((iter_steps > hash_array_len))) { + if (UNLIKELY(iter_steps > hash_array_len)) { iter_steps = hash_array_len; } @@ -1403,7 +1403,7 @@ BArrayStore *BLI_array_store_create(uint stride, uint chunk_count) /* Triangle number, identifying now much read-ahead we need: * https://en.wikipedia.org/wiki/Triangular_number (+ 1) */ bs->info.accum_read_ahead_len = - (uint)((((bs->info.accum_steps * (bs->info.accum_steps + 1))) / 2) + 1); + (uint)(((bs->info.accum_steps * (bs->info.accum_steps + 1)) / 2) + 1); bs->info.accum_read_ahead_bytes = bs->info.accum_read_ahead_len * stride; #else bs->info.accum_read_ahead_bytes = BCHUNK_HASH_LEN * stride; diff --git a/source/blender/blenlib/intern/array_store_utils.c b/source/blender/blenlib/intern/array_store_utils.c index 9ac8630204a..51b5ce0519f 100644 --- a/source/blender/blenlib/intern/array_store_utils.c +++ b/source/blender/blenlib/intern/array_store_utils.c @@ -27,9 +27,9 @@ BArrayStore *BLI_array_store_at_size_ensure(struct BArrayStore_AtSize *bs_stride if ((*bs_p) == NULL) { /* calculate best chunk-count to fit a power of two */ - unsigned int chunk_count = chunk_size; + uint chunk_count = chunk_size; { - unsigned int size = chunk_count * stride; + uint size = chunk_count * stride; size = power_of_2_max_u(size); size = MEM_SIZE_OPTIMAL(size); chunk_count = size / stride; diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc new file mode 100644 index 00000000000..2a231228dcb --- /dev/null +++ b/source/blender/blenlib/intern/array_utils.cc @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_array_utils.hh" + +namespace blender::array_utils { + +void copy(const GVArray &src, + const IndexMask selection, + GMutableSpan dst, + const int64_t grain_size) +{ + BLI_assert(src.type() == dst.type()); + BLI_assert(src.size() == dst.size()); + threading::parallel_for(selection.index_range(), grain_size, [&](const IndexRange range) { + src.materialize_to_uninitialized(selection.slice(range), dst.data()); + }); +} + +void gather(const GVArray &src, + const IndexMask indices, + GMutableSpan dst, + const int64_t grain_size) +{ + BLI_assert(src.type() == dst.type()); + BLI_assert(indices.size() == dst.size()); + threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) { + src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data()); + }); +} + +void gather(const GSpan src, const IndexMask indices, GMutableSpan dst, const int64_t grain_size) +{ + gather(GVArray::ForSpan(src), indices, dst, grain_size); +} + +} // namespace blender::array_utils diff --git a/source/blender/blenlib/intern/boxpack_2d.c b/source/blender/blenlib/intern/boxpack_2d.c index 78f5088e8b1..309ae624305 100644 --- a/source/blender/blenlib/intern/boxpack_2d.c +++ b/source/blender/blenlib/intern/boxpack_2d.c @@ -491,7 +491,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r * flag verts on one or both of the boxes * as being used by checking the width or * height of both boxes */ - if (vert->tlb && vert->trb && (ELEM(box, vert->tlb, vert->trb))) { + if (vert->tlb && vert->trb && ELEM(box, vert->tlb, vert->trb)) { if (UNLIKELY(fabsf(vert->tlb->h - vert->trb->h) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->trb->v[TL]) @@ -522,7 +522,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r vert->tlb->v[TR]->free &= ~(TRF | BRF); } } - else if (vert->blb && vert->brb && (ELEM(box, vert->blb, vert->brb))) { + else if (vert->blb && vert->brb && ELEM(box, vert->blb, vert->brb)) { if (UNLIKELY(fabsf(vert->blb->h - vert->brb->h) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->blb->v[BR]) @@ -554,7 +554,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r } } /* Horizontal */ - if (vert->tlb && vert->blb && (ELEM(box, vert->tlb, vert->blb))) { + if (vert->tlb && vert->blb && ELEM(box, vert->tlb, vert->blb)) { if (UNLIKELY(fabsf(vert->tlb->w - vert->blb->w) < EPSILON_MERGE)) { #ifdef USE_MERGE # define A (vert->blb->v[TL]) @@ -585,7 +585,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r vert->tlb->v[BL]->free &= ~(BLF | BRF); } } - else if (vert->trb && vert->brb && (ELEM(box, vert->trb, vert->brb))) { + else if (vert->trb && vert->brb && ELEM(box, vert->trb, vert->brb)) { if (UNLIKELY(fabsf(vert->trb->w - vert->brb->w) < EPSILON_MERGE)) { #ifdef USE_MERGE @@ -712,7 +712,6 @@ void BLI_box_pack_2d_fixedarea(ListBase *boxes, int width, int height, ListBase * # Box * Small # # Box * # * # * # # * # * ################### ################### - * */ int area_hsplit_large = space->w * (space->h - box->h); int area_vsplit_large = (space->w - box->w) * space->h; diff --git a/source/blender/blenlib/intern/compute_context.cc b/source/blender/blenlib/intern/compute_context.cc new file mode 100644 index 00000000000..50a4a90a4a9 --- /dev/null +++ b/source/blender/blenlib/intern/compute_context.cc @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_compute_context.hh" +#include "BLI_hash_md5.h" + +namespace blender { + +void ComputeContextHash::mix_in(const void *data, int64_t len) +{ + DynamicStackBuffer<> buffer_owner(HashSizeInBytes + len, 8); + char *buffer = static_cast<char *>(buffer_owner.buffer()); + memcpy(buffer, this, HashSizeInBytes); + memcpy(buffer + HashSizeInBytes, data, len); + + BLI_hash_md5_buffer(buffer, HashSizeInBytes + len, this); +} + +std::ostream &operator<<(std::ostream &stream, const ComputeContextHash &hash) +{ + std::stringstream ss; + ss << "0x" << std::hex << hash.v1 << hash.v2; + stream << ss.str(); + return stream; +} + +void ComputeContext::print_stack(std::ostream &stream, StringRef name) const +{ + Stack<const ComputeContext *> stack; + for (const ComputeContext *current = this; current; current = current->parent_) { + stack.push(current); + } + stream << "Context Stack: " << name << "\n"; + while (!stack.is_empty()) { + const ComputeContext *current = stack.pop(); + stream << "-> "; + current->print_current_in_line(stream); + const ComputeContextHash ¤t_hash = current->hash_; + stream << " \t(hash: " << current_hash << ")\n"; + } +} + +std::ostream &operator<<(std::ostream &stream, const ComputeContext &compute_context) +{ + compute_context.print_stack(stream, ""); + return stream; +} + +} // namespace blender diff --git a/source/blender/blenlib/intern/convexhull_2d.c b/source/blender/blenlib/intern/convexhull_2d.c index 33d1a68a76e..9e3fb230d3c 100644 --- a/source/blender/blenlib/intern/convexhull_2d.c +++ b/source/blender/blenlib/intern/convexhull_2d.c @@ -39,8 +39,9 @@ static float is_left(const float p0[2], const float p1[2], const float p2[2]) return (p1[0] - p0[0]) * (p2[1] - p0[1]) - (p2[0] - p0[0]) * (p1[1] - p0[1]); } -int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points[]) +static int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points[]) { + BLI_assert(n >= 2); /* Doesn't handle trivial cases. */ /* the output array r_points[] will be used as the stack */ int bot = 0; int top = -1; /* indices for bottom and top of the stack */ @@ -66,6 +67,7 @@ int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points r_points[++top] = minmax; } r_points[++top] = minmin; /* add polygon endpoint */ + BLI_assert(top + 1 <= n); return top + 1; } @@ -122,16 +124,18 @@ int BLI_convexhull_2d_sorted(const float (*points)[2], const int n, int r_points } if (points[i][0] == points[r_points[0]][0] && points[i][1] == points[r_points[0]][1]) { + BLI_assert(top + 1 <= n); return top + 1; /* special case (mgomes) */ } r_points[++top] = i; /* push points[i] onto stack */ } - if (minmax != minmin) { + if (minmax != minmin && r_points[0] != minmin) { r_points[++top] = minmin; /* push joining endpoint onto stack */ } + BLI_assert(top + 1 <= n); return top + 1; } @@ -162,35 +166,38 @@ static int pointref_cmp_yx(const void *a_, const void *b_) int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) { + BLI_assert(n >= 0); + if (n < 2) { + if (n == 1) { + r_points[0] = 0; + } + return n; + } struct PointRef *points_ref = MEM_mallocN(sizeof(*points_ref) * (size_t)n, __func__); float(*points_sort)[2] = MEM_mallocN(sizeof(*points_sort) * (size_t)n, __func__); - int *points_map; - int points_hull_num, i; - for (i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { points_ref[i].pt = points[i]; } - /* Sort the points by X, then by Y (required by the algorithm) */ + /* Sort the points by X, then by Y. */ qsort(points_ref, (size_t)n, sizeof(struct PointRef), pointref_cmp_yx); - for (i = 0; i < n; i++) { + for (int i = 0; i < n; i++) { memcpy(points_sort[i], points_ref[i].pt, sizeof(float[2])); } - points_hull_num = BLI_convexhull_2d_sorted(points_sort, n, r_points); + int points_hull_num = BLI_convexhull_2d_sorted(points_sort, n, r_points); - /* map back to the original index values */ - points_map = (int *)points_sort; /* abuse float array for temp storage */ - for (i = 0; i < points_hull_num; i++) { - points_map[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points); + /* Map back to the unsorted index values. */ + for (int i = 0; i < points_hull_num; i++) { + r_points[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points); } - memcpy(r_points, points_map, (size_t)points_hull_num * sizeof(*points_map)); - MEM_freeN(points_ref); MEM_freeN(points_sort); + BLI_assert(points_hull_num <= n); return points_hull_num; } @@ -202,14 +209,13 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) /** \name Utility Convex-Hull Functions * \{ */ -float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n) +static float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], int n) { - unsigned int i, i_prev; float area_best = FLT_MAX; float dvec_best[2]; /* best angle, delay atan2 */ - i_prev = n - 1; - for (i = 0; i < n; i++) { + int i_prev = n - 1; + for (int i = 0; i < n; i++) { const float *ev_a = points_hull[i]; const float *ev_b = points_hull[i_prev]; float dvec[2]; /* 2d rotation matrix */ @@ -218,10 +224,9 @@ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned in if (normalize_v2(dvec) != 0.0f) { /* rotation matrix */ float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; - unsigned int j; float area; - for (j = 0; j < n; j++) { + for (int j = 0; j < n; j++) { float tvec[2]; mul_v2_v2_cw(tvec, dvec, points_hull[j]); @@ -249,32 +254,24 @@ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned in return (area_best != FLT_MAX) ? atan2f(dvec_best[0], dvec_best[1]) : 0.0f; } -float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n) +float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], int n) { - int *index_map; - int points_hull_num; + BLI_assert(n >= 0); + float angle = 0.0f; - float angle; + int *index_map = MEM_mallocN(sizeof(*index_map) * (size_t)n, __func__); - index_map = MEM_mallocN(sizeof(*index_map) * n * 2, __func__); + int points_hull_num = BLI_convexhull_2d(points, n, index_map); - points_hull_num = BLI_convexhull_2d(points, (int)n, index_map); - - if (points_hull_num) { - float(*points_hull)[2]; - int j; - - points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)points_hull_num, __func__); - for (j = 0; j < points_hull_num; j++) { + if (points_hull_num > 1) { + float(*points_hull)[2] = MEM_mallocN(sizeof(*points_hull) * (size_t)points_hull_num, __func__); + for (int j = 0; j < points_hull_num; j++) { copy_v2_v2(points_hull[j], points[index_map[j]]); } - angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)points_hull_num); + angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, points_hull_num); MEM_freeN(points_hull); } - else { - angle = 0.0f; - } MEM_freeN(index_map); diff --git a/source/blender/blenlib/intern/cpp_type.cc b/source/blender/blenlib/intern/cpp_type.cc index d6a087cf175..38de32d3ec8 100644 --- a/source/blender/blenlib/intern/cpp_type.cc +++ b/source/blender/blenlib/intern/cpp_type.cc @@ -26,3 +26,4 @@ BLI_CPP_TYPE_MAKE(ColorGeometry4f, blender::ColorGeometry4f, CPPTypeFlags::Basic BLI_CPP_TYPE_MAKE(ColorGeometry4b, blender::ColorGeometry4b, CPPTypeFlags::BasicType) BLI_CPP_TYPE_MAKE(string, std::string, CPPTypeFlags::BasicType) +BLI_CPP_TYPE_MAKE(StringVector, blender::Vector<std::string>, CPPTypeFlags::None) diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc index db6cb0824dc..afecf9ea838 100644 --- a/source/blender/blenlib/intern/delaunay_2d.cc +++ b/source/blender/blenlib/intern/delaunay_2d.cc @@ -45,7 +45,7 @@ template<> double math_abs<double>(const double v) return fabs(v); } -template<typename T> double math_to_double(const T UNUSED(v)) +template<typename T> double math_to_double(const T /*v*/) { BLI_assert(false); /* Need implementation for other type. */ return 0.0; @@ -520,10 +520,10 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen double height = maxy - miny; double aspect = height / width; int view_width = max_draw_width; - int view_height = static_cast<int>(view_width * aspect); + int view_height = int(view_width * aspect); if (view_height > max_draw_height) { view_height = max_draw_height; - view_width = static_cast<int>(view_height / aspect); + view_width = int(view_height / aspect); } double scale = view_width / width; @@ -2645,7 +2645,7 @@ void prepare_cdt_for_output(CDT_state<T> *cdt_state, const CDT_output_type outpu template<typename T> CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state, - const CDT_input<T> UNUSED(input), + const CDT_input<T> /*input*/, CDT_output_type output_type) { CDT_output_type oty = output_type; @@ -2822,8 +2822,8 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input, in.edge = blender::Array<std::pair<int, int>>(input->edges_len); in.face = blender::Array<blender::Vector<int>>(input->faces_len); for (int v = 0; v < input->verts_len; ++v) { - double x = static_cast<double>(input->vert_coords[v][0]); - double y = static_cast<double>(input->vert_coords[v][1]); + double x = double(input->vert_coords[v][0]); + double y = double(input->vert_coords[v][1]); in.vert[v] = blender::meshintersect::vec2<double>(x, y); } for (int e = 0; e < input->edges_len; ++e) { @@ -2836,7 +2836,7 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input, in.face[f][j] = input->faces[fstart + j]; } } - in.epsilon = static_cast<double>(input->epsilon); + in.epsilon = double(input->epsilon); in.need_ids = input->need_ids; blender::meshintersect::CDT_result<double> res = blender::meshintersect::delaunay_2d_calc( @@ -2903,8 +2903,8 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input, int v_orig_index = 0; for (int v = 0; v < nv; ++v) { - output->vert_coords[v][0] = static_cast<float>(res.vert[v][0]); - output->vert_coords[v][1] = static_cast<float>(res.vert[v][1]); + output->vert_coords[v][0] = float(res.vert[v][0]); + output->vert_coords[v][1] = float(res.vert[v][1]); if (input->need_ids) { int this_start = v_orig_index; output->verts_orig_start_table[v] = this_start; diff --git a/source/blender/blenlib/intern/dot_export.cc b/source/blender/blenlib/intern/dot_export.cc index 796fd6a934a..d577de9bc34 100644 --- a/source/blender/blenlib/intern/dot_export.cc +++ b/source/blender/blenlib/intern/dot_export.cc @@ -93,7 +93,7 @@ void Graph::set_random_cluster_bgcolors() void Cluster::set_random_cluster_bgcolors() { - float hue = rand() / (float)RAND_MAX; + float hue = rand() / float(RAND_MAX); float staturation = 0.3f; float value = 0.8f; this->attributes.set("bgcolor", color_attr_from_hsv(hue, staturation, value)); @@ -227,7 +227,7 @@ void Attributes::export__as_bracket_list(std::stringstream &ss) const void Node::export__as_id(std::stringstream &ss) const { - ss << '"' << (uintptr_t)this << '"'; + ss << '"' << uintptr_t(this) << '"'; } void Node::export__as_declaration(std::stringstream &ss) const diff --git a/source/blender/blenlib/intern/endian_switch.c b/source/blender/blenlib/intern/endian_switch.c index 10d0bfb815b..c1a5b69fb23 100644 --- a/source/blender/blenlib/intern/endian_switch.c +++ b/source/blender/blenlib/intern/endian_switch.c @@ -18,7 +18,7 @@ void BLI_endian_switch_int16_array(short *val, const int size) } } -void BLI_endian_switch_uint16_array(unsigned short *val, const int size) +void BLI_endian_switch_uint16_array(ushort *val, const int size) { if (size > 0) { int i = size; @@ -38,7 +38,7 @@ void BLI_endian_switch_int32_array(int *val, const int size) } } -void BLI_endian_switch_uint32_array(unsigned int *val, const int size) +void BLI_endian_switch_uint32_array(uint *val, const int size) { if (size > 0) { int i = size; diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 3abd482d6b3..a157302e51e 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -627,7 +627,7 @@ static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, c *alloc_len = len; - BLI_join_dirfile(*dst, len + 1, dir, file); + BLI_path_join(*dst, len + 1, dir, file); } static char *strip_last_slash(const char *dir) @@ -1184,7 +1184,7 @@ static const char *check_destination(const char *file, const char *to) len = strlen(to) + strlen(filename) + 1; path = MEM_callocN(len + 1, "check_destination path"); - BLI_join_dirfile(path, len + 1, to, filename); + BLI_path_join(path, len + 1, to, filename); MEM_freeN(str); diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc index f66b1e14fc6..b0623175dc7 100644 --- a/source/blender/blenlib/intern/generic_virtual_array.cc +++ b/source/blender/blenlib/intern/generic_virtual_array.cc @@ -51,7 +51,7 @@ CommonVArrayInfo GVArrayImpl::common_info() const return {}; } -bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const +bool GVArrayImpl::try_assign_VArray(void * /*varray*/) const { return false; } @@ -102,7 +102,7 @@ void GVMutableArray::fill(const void *value) } } -bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const +bool GVMutableArrayImpl::try_assign_VMutableArray(void * /*varray*/) const { return false; } @@ -172,11 +172,11 @@ void GVArrayImpl_For_GSpan::materialize_compressed_to_uninitialized(const IndexM /* Generic virtual array where each element has the same value. The value is not owned. */ -void GVArrayImpl_For_SingleValueRef::get(const int64_t UNUSED(index), void *r_value) const +void GVArrayImpl_For_SingleValueRef::get(const int64_t /*index*/, void *r_value) const { type_->copy_assign(value_, r_value); } -void GVArrayImpl_For_SingleValueRef::get_to_uninitialized(const int64_t UNUSED(index), +void GVArrayImpl_For_SingleValueRef::get_to_uninitialized(const int64_t /*index*/, void *r_value) const { type_->copy_construct(value_, r_value); @@ -261,11 +261,11 @@ template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public } private: - void get(const int64_t UNUSED(index), void *r_value) const override + void get(const int64_t /*index*/, void *r_value) const override { this->copy_value_to(r_value); } - void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override + void get_to_uninitialized(const int64_t /*index*/, void *r_value) const override { this->copy_value_to(r_value); } diff --git a/source/blender/blenlib/intern/generic_virtual_vector_array.cc b/source/blender/blenlib/intern/generic_virtual_vector_array.cc index 8fd1fb50b72..5d6985e16c8 100644 --- a/source/blender/blenlib/intern/generic_virtual_vector_array.cc +++ b/source/blender/blenlib/intern/generic_virtual_vector_array.cc @@ -16,12 +16,12 @@ void GVArray_For_GVVectorArrayIndex::get_to_uninitialized(const int64_t index_in vector_array_.get_vector_element(index_, index_in_vector, r_value); } -int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const +int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t /*index*/) const { return varray_.size(); } -void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t UNUSED(index), +void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t /*index*/, const int64_t index_in_vector, void *r_value) const { @@ -33,12 +33,12 @@ bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const return true; } -int64_t GVVectorArray_For_SingleGSpan::get_vector_size_impl(const int64_t UNUSED(index)) const +int64_t GVVectorArray_For_SingleGSpan::get_vector_size_impl(const int64_t /*index*/) const { return span_.size(); } -void GVVectorArray_For_SingleGSpan::get_vector_element_impl(const int64_t UNUSED(index), +void GVVectorArray_For_SingleGSpan::get_vector_element_impl(const int64_t /*index*/, const int64_t index_in_vector, void *r_value) const { diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c index 8411b49ef38..d13c20e4edb 100644 --- a/source/blender/blenlib/intern/hash_mm2a.c +++ b/source/blender/blenlib/intern/hash_mm2a.c @@ -41,7 +41,7 @@ } \ (void)0 -static void mm2a_mix_tail(BLI_HashMurmur2A *mm2, const unsigned char **data, size_t *len) +static void mm2a_mix_tail(BLI_HashMurmur2A *mm2, const uchar **data, size_t *len) { while (*len && ((*len < 4) || mm2->count)) { mm2->tail |= (uint32_t)(**data) << (mm2->count * 8); @@ -66,7 +66,7 @@ void BLI_hash_mm2a_init(BLI_HashMurmur2A *mm2, uint32_t seed) mm2->size = 0; } -void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t len) +void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const uchar *data, size_t len) { mm2->size += (uint32_t)len; @@ -83,7 +83,7 @@ void BLI_hash_mm2a_add(BLI_HashMurmur2A *mm2, const unsigned char *data, size_t void BLI_hash_mm2a_add_int(BLI_HashMurmur2A *mm2, int data) { - BLI_hash_mm2a_add(mm2, (const unsigned char *)&data, sizeof(data)); + BLI_hash_mm2a_add(mm2, (const uchar *)&data, sizeof(data)); } uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2) @@ -96,7 +96,7 @@ uint32_t BLI_hash_mm2a_end(BLI_HashMurmur2A *mm2) return mm2->hash; } -uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed) +uint32_t BLI_hash_mm2(const uchar *data, size_t len, uint32_t seed) { /* Initialize the hash to a 'random' value */ uint32_t h = seed ^ len; diff --git a/source/blender/blenlib/intern/hash_mm3.c b/source/blender/blenlib/intern/hash_mm3.c index cc1143bf55f..3c05ead5e62 100644 --- a/source/blender/blenlib/intern/hash_mm3.c +++ b/source/blender/blenlib/intern/hash_mm3.c @@ -69,7 +69,7 @@ BLI_INLINE uint64_t fmix64(uint64_t k) return k; } -uint32_t BLI_hash_mm3(const unsigned char *data, size_t len, uint32_t seed) +uint32_t BLI_hash_mm3(const uchar *data, size_t len, uint32_t seed) { const uint8_t *in_data = (const uint8_t *)data; const int nblocks = len / 4; diff --git a/source/blender/blenlib/intern/jitter_2d.c b/source/blender/blenlib/intern/jitter_2d.c index 8fa0f2c1e15..4b86f3cfeef 100644 --- a/source/blender/blenlib/intern/jitter_2d.c +++ b/source/blender/blenlib/intern/jitter_2d.c @@ -70,7 +70,7 @@ void BLI_jitterate1(float (*jit1)[2], float (*jit2)[2], int num, float radius1) jit2[i][0] = x; jit2[i][1] = y; } - memcpy(jit1, jit2, 2 * (unsigned int)num * sizeof(float)); + memcpy(jit1, jit2, 2 * (uint)num * sizeof(float)); } void BLI_jitterate2(float (*jit1)[2], float (*jit2)[2], int num, float radius2) @@ -120,7 +120,7 @@ void BLI_jitterate2(float (*jit1)[2], float (*jit2)[2], int num, float radius2) jit2[i][0] = x; jit2[i][1] = y; } - memcpy(jit1, jit2, (unsigned int)num * sizeof(float[2])); + memcpy(jit1, jit2, (uint)num * sizeof(float[2])); } void BLI_jitter_init(float (*jitarr)[2], int num) @@ -138,12 +138,12 @@ void BLI_jitter_init(float (*jitarr)[2], int num) number_fl = (float)num; number_fl_sqrt = sqrtf(number_fl); - jit2 = MEM_mallocN(12 + (unsigned int)num * sizeof(float[2]), "initjit"); + jit2 = MEM_mallocN(12 + (uint)num * sizeof(float[2]), "initjit"); rad1 = 1.0f / number_fl_sqrt; rad2 = 1.0f / number_fl; rad3 = number_fl_sqrt / number_fl; - rng = BLI_rng_new(31415926 + (unsigned int)num); + rng = BLI_rng_new(31415926 + (uint)num); x = 0; for (i = 0; i < num; i++) { diff --git a/source/blender/blenlib/intern/lasso_2d.c b/source/blender/blenlib/intern/lasso_2d.c index 13b0e416b76..4752864ea3a 100644 --- a/source/blender/blenlib/intern/lasso_2d.c +++ b/source/blender/blenlib/intern/lasso_2d.c @@ -12,9 +12,9 @@ #include "BLI_lasso_2d.h" /* own include */ -void BLI_lasso_boundbox(rcti *rect, const int mcoords[][2], const unsigned int mcoords_len) +void BLI_lasso_boundbox(rcti *rect, const int mcoords[][2], const uint mcoords_len) { - unsigned int a; + uint a; rect->xmin = rect->xmax = mcoords[0][0]; rect->ymin = rect->ymax = mcoords[0][1]; @@ -36,7 +36,7 @@ void BLI_lasso_boundbox(rcti *rect, const int mcoords[][2], const unsigned int m } bool BLI_lasso_is_point_inside(const int mcoords[][2], - const unsigned int mcoords_len, + const uint mcoords_len, const int sx, const int sy, const int error_value) @@ -50,7 +50,7 @@ bool BLI_lasso_is_point_inside(const int mcoords[][2], } bool BLI_lasso_is_edge_inside(const int mcoords[][2], - const unsigned int mcoords_len, + const uint mcoords_len, int x0, int y0, int x1, @@ -77,7 +77,7 @@ bool BLI_lasso_is_edge_inside(const int mcoords[][2], if (isect_seg_seg_v2_int(mcoords[0], mcoords[mcoords_len - 1], v1, v2) > 0) { return true; } - for (unsigned int a = 0; a < mcoords_len - 1; a++) { + for (uint a = 0; a < mcoords_len - 1; a++) { if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) { return true; } diff --git a/source/blender/blenlib/intern/lazy_threading.cc b/source/blender/blenlib/intern/lazy_threading.cc new file mode 100644 index 00000000000..803fd81a96d --- /dev/null +++ b/source/blender/blenlib/intern/lazy_threading.cc @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_lazy_threading.hh" +#include "BLI_vector.hh" + +namespace blender::lazy_threading { + +/** + * This is a #RawVector so that it can be destructed after Blender checks for memory leaks. + */ +thread_local RawVector<FunctionRef<void()>, 0> hint_receivers; + +void send_hint() +{ + for (const FunctionRef<void()> &fn : hint_receivers) { + fn(); + } +} + +HintReceiver::HintReceiver(const FunctionRef<void()> fn) +{ + hint_receivers.append(fn); +} + +HintReceiver::~HintReceiver() +{ + hint_receivers.pop_last(); +} + +} // namespace blender::lazy_threading diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index 257153dc6fe..8a791030fce 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -65,7 +65,7 @@ float floor_power_of_10(float f) { BLI_assert(!(f < 0.0f)); if (f != 0.0f) { - return 1.0f / (powf(10.0f, ceilf(log10f(1.0f / f)))); + return 1.0f / powf(10.0f, ceilf(log10f(1.0f / f))); } return 0.0f; } @@ -74,7 +74,7 @@ float ceil_power_of_10(float f) { BLI_assert(!(f < 0.0f)); if (f != 0.0f) { - return 1.0f / (powf(10.0f, floorf(log10f(1.0f / f)))); + return 1.0f / powf(10.0f, floorf(log10f(1.0f / f))); } return 0.0f; } diff --git a/source/blender/blenlib/intern/math_boolean.cc b/source/blender/blenlib/intern/math_boolean.cc index 132d5dfda65..e5352540dd6 100644 --- a/source/blender/blenlib/intern/math_boolean.cc +++ b/source/blender/blenlib/intern/math_boolean.cc @@ -193,7 +193,7 @@ static RobustInitCaller init_caller; y = b - bvirt #define Fast_Two_Sum(a, b, x, y) \ - x = (double)(a + b); \ + x = double(a + b); \ Fast_Two_Sum_Tail(a, b, x, y) #define Fast_Two_Diff_Tail(a, b, x, y) \ @@ -205,30 +205,30 @@ static RobustInitCaller init_caller; Fast_Two_Diff_Tail(a, b, x, y) #define Two_Sum_Tail(a, b, x, y) \ - bvirt = (double)(x - a); \ + bvirt = double(x - a); \ avirt = x - bvirt; \ bround = b - bvirt; \ around = a - avirt; \ y = around + bround #define Two_Sum(a, b, x, y) \ - x = (double)(a + b); \ + x = double(a + b); \ Two_Sum_Tail(a, b, x, y) #define Two_Diff_Tail(a, b, x, y) \ - bvirt = (double)(a - x); \ + bvirt = double(a - x); \ avirt = x + bvirt; \ bround = bvirt - b; \ around = a - avirt; \ y = around + bround #define Two_Diff(a, b, x, y) \ - x = (double)(a - b); \ + x = double(a - b); \ Two_Diff_Tail(a, b, x, y) #define Split(a, ahi, alo) \ - c = (double)(splitter * a); \ - abig = (double)(c - a); \ + c = double(splitter * a); \ + abig = double(c - a); \ ahi = c - abig; \ alo = a - ahi @@ -241,11 +241,11 @@ static RobustInitCaller init_caller; y = (alo * blo) - err3 #define Two_Product(a, b, x, y) \ - x = (double)(a * b); \ + x = double(a * b); \ Two_Product_Tail(a, b, x, y) #define Two_Product_Presplit(a, b, bhi, blo, x, y) \ - x = (double)(a * b); \ + x = double(a * b); \ Split(a, ahi, alo); \ err1 = x - (ahi * bhi); \ err2 = err1 - (alo * bhi); \ @@ -266,7 +266,7 @@ static RobustInitCaller init_caller; y = (alo * alo) - err3 #define Square(a, x, y) \ - x = (double)(a * a); \ + x = double(a * a); \ Square_Tail(a, x, y) #define Two_One_Sum(a1, a0, b, x2, x1, x0) \ @@ -647,10 +647,10 @@ static double orient2dadapt(const double *pa, const double *pb, const double *pc INEXACT double _i, _j; double _0; - acx = (double)(pa[0] - pc[0]); - bcx = (double)(pb[0] - pc[0]); - acy = (double)(pa[1] - pc[1]); - bcy = (double)(pb[1] - pc[1]); + acx = double(pa[0] - pc[0]); + bcx = double(pb[0] - pc[0]); + acy = double(pa[1] - pc[1]); + bcy = double(pb[1] - pc[1]); Two_Product(acx, bcy, detleft, detlefttail); Two_Product(acy, bcx, detright, detrighttail); @@ -834,15 +834,15 @@ static double orient3dadapt( INEXACT double _i, _j, _k; double _0; - adx = (double)(pa[0] - pd[0]); - bdx = (double)(pb[0] - pd[0]); - cdx = (double)(pc[0] - pd[0]); - ady = (double)(pa[1] - pd[1]); - bdy = (double)(pb[1] - pd[1]); - cdy = (double)(pc[1] - pd[1]); - adz = (double)(pa[2] - pd[2]); - bdz = (double)(pb[2] - pd[2]); - cdz = (double)(pc[2] - pd[2]); + adx = double(pa[0] - pd[0]); + bdx = double(pb[0] - pd[0]); + cdx = double(pc[0] - pd[0]); + ady = double(pa[1] - pd[1]); + bdy = double(pb[1] - pd[1]); + cdy = double(pc[1] - pd[1]); + adz = double(pa[2] - pd[2]); + bdz = double(pb[2] - pd[2]); + cdz = double(pc[2] - pd[2]); Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); @@ -1358,12 +1358,12 @@ static double incircleadapt( INEXACT double _i, _j; double _0; - adx = (double)(pa[0] - pd[0]); - bdx = (double)(pb[0] - pd[0]); - cdx = (double)(pc[0] - pd[0]); - ady = (double)(pa[1] - pd[1]); - bdy = (double)(pb[1] - pd[1]); - cdy = (double)(pc[1] - pd[1]); + adx = double(pa[0] - pd[0]); + bdx = double(pb[0] - pd[0]); + cdx = double(pc[0] - pd[0]); + ady = double(pa[1] - pd[1]); + bdy = double(pb[1] - pd[1]); + cdy = double(pc[1] - pd[1]); Two_Product(bdx, cdy, bdxcdy1, bdxcdy0); Two_Product(cdx, bdy, cdxbdy1, cdxbdy0); @@ -2191,18 +2191,18 @@ static double insphereadapt(const double *pa, INEXACT double _i, _j; double _0; - aex = (double)(pa[0] - pe[0]); - bex = (double)(pb[0] - pe[0]); - cex = (double)(pc[0] - pe[0]); - dex = (double)(pd[0] - pe[0]); - aey = (double)(pa[1] - pe[1]); - bey = (double)(pb[1] - pe[1]); - cey = (double)(pc[1] - pe[1]); - dey = (double)(pd[1] - pe[1]); - aez = (double)(pa[2] - pe[2]); - bez = (double)(pb[2] - pe[2]); - cez = (double)(pc[2] - pe[2]); - dez = (double)(pd[2] - pe[2]); + aex = double(pa[0] - pe[0]); + bex = double(pb[0] - pe[0]); + cex = double(pc[0] - pe[0]); + dex = double(pd[0] - pe[0]); + aey = double(pa[1] - pe[1]); + bey = double(pb[1] - pe[1]); + cey = double(pc[1] - pe[1]); + dey = double(pd[1] - pe[1]); + aez = double(pa[2] - pe[2]); + bez = double(pb[2] - pe[2]); + cez = double(pc[2] - pe[2]); + dez = double(pd[2] - pe[2]); Two_Product(aex, bey, aexbey1, aexbey0); Two_Product(bex, aey, bexaey1, bexaey0); diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index bdcf52ec521..51860c1abdb 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -176,7 +176,7 @@ void ycc_to_rgb(float y, float cb, float cr, float *r_r, float *r_g, float *r_b, void hex_to_rgb(const char *hexcol, float *r_r, float *r_g, float *r_b) { - unsigned int ri, gi, bi; + uint ri, gi, bi; if (hexcol[0] == '#') { hexcol++; @@ -329,29 +329,29 @@ void hsv_clamp_v(float hsv[3], float v_max) CLAMP(hsv[2], 0.0f, v_max); } -unsigned int hsv_to_cpack(float h, float s, float v) +uint hsv_to_cpack(float h, float s, float v) { - unsigned int r, g, b; + uint r, g, b; float rf, gf, bf; - unsigned int col; + uint col; hsv_to_rgb(h, s, v, &rf, &gf, &bf); - r = (unsigned int)(rf * 255.0f); - g = (unsigned int)(gf * 255.0f); - b = (unsigned int)(bf * 255.0f); + r = (uint)(rf * 255.0f); + g = (uint)(gf * 255.0f); + b = (uint)(bf * 255.0f); col = (r + (g * 256) + (b * 256 * 256)); return col; } -unsigned int rgb_to_cpack(float r, float g, float b) +uint rgb_to_cpack(float r, float g, float b) { - unsigned int ir, ig, ib; + uint ir, ig, ib; - ir = (unsigned int)floorf(255.0f * max_ff(r, 0.0f)); - ig = (unsigned int)floorf(255.0f * max_ff(g, 0.0f)); - ib = (unsigned int)floorf(255.0f * max_ff(b, 0.0f)); + ir = (uint)floorf(255.0f * max_ff(r, 0.0f)); + ig = (uint)floorf(255.0f * max_ff(g, 0.0f)); + ib = (uint)floorf(255.0f * max_ff(b, 0.0f)); if (ir > 255) { ir = 255; @@ -366,21 +366,21 @@ unsigned int rgb_to_cpack(float r, float g, float b) return (ir + (ig * 256) + (ib * 256 * 256)); } -void cpack_to_rgb(unsigned int col, float *r_r, float *r_g, float *r_b) +void cpack_to_rgb(uint col, float *r_r, float *r_g, float *r_b) { - *r_r = ((float)(((col)) & 0xFF)) * (1.0f / 255.0f); - *r_g = ((float)(((col) >> 8) & 0xFF)) * (1.0f / 255.0f); - *r_b = ((float)(((col) >> 16) & 0xFF)) * (1.0f / 255.0f); + *r_r = (float)(col & 0xFF) * (1.0f / 255.0f); + *r_g = (float)((col >> 8) & 0xFF) * (1.0f / 255.0f); + *r_b = (float)((col >> 16) & 0xFF) * (1.0f / 255.0f); } -void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3]) +void rgb_uchar_to_float(float r_col[3], const uchar col_ub[3]) { r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f); r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f); r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f); } -void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4]) +void rgba_uchar_to_float(float r_col[4], const uchar col_ub[4]) { r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f); r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f); @@ -388,12 +388,12 @@ void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4]) r_col[3] = ((float)col_ub[3]) * (1.0f / 255.0f); } -void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3]) +void rgb_float_to_uchar(uchar r_col[3], const float col_f[3]) { unit_float_to_uchar_clamp_v3(r_col, col_f); } -void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4]) +void rgba_float_to_uchar(uchar r_col[4], const float col_f[4]) { unit_float_to_uchar_clamp_v4(r_col, col_f); } @@ -500,7 +500,7 @@ void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset) hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2); } -void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset) +void rgb_byte_set_hue_float_offset(uchar rgb[3], float hue_offset) { float rgb_float[3]; @@ -515,13 +515,13 @@ void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset) */ float BLI_color_from_srgb_table[256]; -unsigned short BLI_color_to_srgb_table[0x10000]; +ushort BLI_color_to_srgb_table[0x10000]; -static unsigned short hipart(const float f) +static ushort hipart(const float f) { union { float f; - unsigned short us[2]; + ushort us[2]; } tmp; tmp.f = f; @@ -533,12 +533,12 @@ static unsigned short hipart(const float f) #endif } -static float index_to_float(const unsigned short i) +static float index_to_float(const ushort i) { union { float f; - unsigned short us[2]; + ushort us[2]; } tmp; /* positive and negative zeros, and all gradual underflow, turn into zero: */ @@ -567,7 +567,7 @@ static float index_to_float(const unsigned short i) void BLI_init_srgb_conversion(void) { static bool initialized = false; - unsigned int i, b; + uint i, b; if (initialized) { return; @@ -576,12 +576,12 @@ void BLI_init_srgb_conversion(void) /* Fill in the lookup table to convert floats to bytes: */ for (i = 0; i < 0x10000; i++) { - float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f; + float f = linearrgb_to_srgb(index_to_float((ushort)i)) * 255.0f; if (f <= 0) { BLI_color_to_srgb_table[i] = 0; } else if (f < 255) { - BLI_color_to_srgb_table[i] = (unsigned short)(f * 0x100 + 0.5f); + BLI_color_to_srgb_table[i] = (ushort)(f * 0x100 + 0.5f); } else { BLI_color_to_srgb_table[i] = 0xff00; @@ -594,6 +594,6 @@ void BLI_init_srgb_conversion(void) BLI_color_from_srgb_table[b] = f; i = hipart(f); /* replace entries so byte->float->byte does not change the data: */ - BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100); + BLI_color_to_srgb_table[i] = (ushort)(b * 0x100); } } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index e7ccdeab80a..08152976f7d 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -68,7 +68,7 @@ float normal_quad_v3( return normalize_v3(n); } -float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr) +float normal_poly_v3(float n[3], const float verts[][3], uint nr) { cross_poly_v3(n, verts, nr); return normalize_v3(n); @@ -122,14 +122,14 @@ float area_tri_signed_v3(const float v1[3], return area; } -float area_poly_v3(const float verts[][3], unsigned int nr) +float area_poly_v3(const float verts[][3], uint nr) { float n[3]; cross_poly_v3(n, verts, nr); return len_v3(n) * 0.5f; } -float area_squared_poly_v3(const float verts[][3], unsigned int nr) +float area_squared_poly_v3(const float verts[][3], uint nr) { float n[3]; @@ -138,9 +138,9 @@ float area_squared_poly_v3(const float verts[][3], unsigned int nr) return len_squared_v3(n); } -float cross_poly_v2(const float verts[][2], unsigned int nr) +float cross_poly_v2(const float verts[][2], uint nr) { - unsigned int a; + uint a; float cross; const float *co_curr, *co_prev; @@ -157,11 +157,11 @@ float cross_poly_v2(const float verts[][2], unsigned int nr) return cross; } -void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr) +void cross_poly_v3(float n[3], const float verts[][3], uint nr) { const float *v_prev = verts[nr - 1]; const float *v_curr = verts[0]; - unsigned int i; + uint i; zero_v3(n); @@ -171,17 +171,17 @@ void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr) } } -float area_poly_v2(const float verts[][2], unsigned int nr) +float area_poly_v2(const float verts[][2], uint nr) { return fabsf(0.5f * cross_poly_v2(verts, nr)); } -float area_poly_signed_v2(const float verts[][2], unsigned int nr) +float area_poly_signed_v2(const float verts[][2], uint nr) { return (0.5f * cross_poly_v2(verts, nr)); } -float area_squared_poly_v2(const float verts[][2], unsigned int nr) +float area_squared_poly_v2(const float verts[][2], uint nr) { float area = area_poly_signed_v2(verts, nr); return area * area; @@ -527,7 +527,7 @@ float dist_signed_squared_to_corner_v3v3v3(const float p[3], cross_v3_v3v3(axis, dir_a, dir_b); - if ((len_squared_v3(axis) < FLT_EPSILON)) { + if (len_squared_v3(axis) < FLT_EPSILON) { copy_v3_v3(axis, axis_ref); } else if (dot_v3v3(axis, axis_ref) < 0.0f) { @@ -1458,12 +1458,12 @@ int isect_line_sphere_v2(const float l1[2], bool isect_point_poly_v2(const float pt[2], const float verts[][2], - const unsigned int nr, + const uint nr, const bool UNUSED(use_holes)) { /* Keep in sync with #isect_point_poly_v2_int. */ - unsigned int i, j; + uint i, j; bool isect = false; for (i = 0, j = nr - 1; i < nr; j = i++) { if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) && @@ -1477,12 +1477,12 @@ bool isect_point_poly_v2(const float pt[2], } bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], - const unsigned int nr, + const uint nr, const bool UNUSED(use_holes)) { /* Keep in sync with #isect_point_poly_v2. */ - unsigned int i, j; + uint i, j; bool isect = false; for (i = 0, j = nr - 1; i < nr; j = i++) { if (((verts[i][1] > pt[1]) != (verts[j][1] > pt[1])) && @@ -1667,8 +1667,8 @@ bool isect_ray_tri_v3(const float ray_origin[3], float *r_lambda, float r_uv[2]) { - /* NOTE(campbell): these values were 0.000001 in 2.4x but for projection snapping on - * a human head (1BU == 1m), subsurf level 2, this gave many errors. */ + /* NOTE(@campbellbarton): these values were 0.000001 in 2.4x but for projection snapping on + * a human head `(1BU == 1m)`, subdivision-surface level 2, this gave many errors. */ const float epsilon = 0.00000001f; float p[3], s[3], e1[3], e2[3], q[3]; float a, f, u, v; @@ -2208,7 +2208,7 @@ bool isect_planes_v3_fn( int i_test; for (i_test = 0; i_test < planes_len; i_test++) { const float *np_test = planes[i_test]; - if (((dot_v3v3(np_test, co_test) + np_test[3]) > eps_isect)) { + if ((dot_v3v3(np_test, co_test) + np_test[3]) > eps_isect) { /* For low epsilon values the point could intersect its own plane. */ if (!ELEM(i_test, i, j, k)) { break; @@ -2696,7 +2696,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], z = x + y - (a * c - b * b); if (z <= 0.0f && (x >= 0.0f && y >= 0.0f)) { - //(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000) { + //(((uint)z)& ~(((uint)x)|((uint)y))) & 0x80000000) { *r_lambda = t0; copy_v3_v3(ipoint, point); return true; @@ -2748,7 +2748,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], edotv = dot_v3v3(e1, vel); edotbv = dot_v3v3(e1, bv); - a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; + a = elen2 * -dot_v3v3(vel, vel) + edotv * edotv; b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; @@ -2770,7 +2770,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], edotv = dot_v3v3(e2, vel); edotbv = dot_v3v3(e2, bv); - a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; + a = elen2 * -dot_v3v3(vel, vel) + edotv * edotv; b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; @@ -2797,7 +2797,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], edotv = dot_v3v3(e3, vel); edotbv = dot_v3v3(e3, bv); - a = elen2 * (-dot_v3v3(vel, vel)) + edotv * edotv; + a = elen2 * -dot_v3v3(vel, vel) + edotv * edotv; b = 2.0f * (elen2 * dot_v3v3(vel, bv) - edotv * edotbv); c = elen2 * (radius2 - dot_v3v3(bv, bv)) + edotbv * edotbv; @@ -3773,7 +3773,7 @@ void barycentric_weights_v2_quad(const float v1[2], const float co[2], float w[4]) { - /* NOTE(campbell): fabsf() here is not needed for convex quads + /* NOTE(@campbellbarton): fabsf() here is not needed for convex quads * (and not used in #interp_weights_poly_v2). * But in the case of concave/bow-tie quads for the mask rasterizer it * gives unreliable results without adding `absf()`. If this becomes an issue for more general @@ -5803,10 +5803,10 @@ bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], return (isect_seg_seg_v2(v1, v3, v2, v4) > 0); } -bool is_poly_convex_v2(const float verts[][2], unsigned int nr) +bool is_poly_convex_v2(const float verts[][2], uint nr) { - unsigned int sign_flag = 0; - unsigned int a; + uint sign_flag = 0; + uint a; const float *co_curr, *co_prev; float dir_curr[2], dir_prev[2]; diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index 34fcb583232..29907924bd8 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -56,7 +56,7 @@ static void vector_from_float(const float *data, float vector[4], int components } } -static void vector_from_byte(const unsigned char *data, float vector[4], int components) +static void vector_from_byte(const uchar *data, float vector[4], int components) { if (components == 1) { vector[0] = data[0]; @@ -75,9 +75,9 @@ static void vector_from_byte(const unsigned char *data, float vector[4], int com } /* BICUBIC INTERPOLATION */ -BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, +BLI_INLINE void bicubic_interpolation(const uchar *byte_buffer, const float *float_buffer, - unsigned char *byte_output, + uchar *byte_output, float *float_output, int width, int height, @@ -135,7 +135,7 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, vector_from_float(float_data, data, components); } else { - const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + const uchar *byte_data = byte_buffer + width * y1 * components + components * x1; vector_from_byte(byte_data, data, components); } @@ -174,7 +174,7 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, vector_from_float(float_data, data, components); } else { - const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + const uchar *byte_data = byte_buffer + width * y1 * components + components * x1; vector_from_byte(byte_data, data, components); } @@ -211,18 +211,18 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, } else { if (components == 1) { - byte_output[0] = (unsigned char)(out[0] + 0.5f); + byte_output[0] = (uchar)(out[0] + 0.5f); } else if (components == 3) { - byte_output[0] = (unsigned char)(out[0] + 0.5f); - byte_output[1] = (unsigned char)(out[1] + 0.5f); - byte_output[2] = (unsigned char)(out[2] + 0.5f); + byte_output[0] = (uchar)(out[0] + 0.5f); + byte_output[1] = (uchar)(out[1] + 0.5f); + byte_output[2] = (uchar)(out[2] + 0.5f); } else { - byte_output[0] = (unsigned char)(out[0] + 0.5f); - byte_output[1] = (unsigned char)(out[1] + 0.5f); - byte_output[2] = (unsigned char)(out[2] + 0.5f); - byte_output[3] = (unsigned char)(out[3] + 0.5f); + byte_output[0] = (uchar)(out[0] + 0.5f); + byte_output[1] = (uchar)(out[1] + 0.5f); + byte_output[2] = (uchar)(out[2] + 0.5f); + byte_output[3] = (uchar)(out[3] + 0.5f); } } } @@ -233,21 +233,16 @@ void BLI_bicubic_interpolation_fl( bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); } -void BLI_bicubic_interpolation_char(const unsigned char *buffer, - unsigned char *output, - int width, - int height, - int components, - float u, - float v) +void BLI_bicubic_interpolation_char( + const uchar *buffer, uchar *output, int width, int height, int components, float u, float v) { bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); } /* BILINEAR INTERPOLATION */ -BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, +BLI_INLINE void bilinear_interpolation(const uchar *byte_buffer, const float *float_buffer, - unsigned char *byte_output, + uchar *byte_output, float *float_output, int width, int height, @@ -351,8 +346,8 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, } } else { - const unsigned char *row1, *row2, *row3, *row4; - unsigned char empty[4] = {0, 0, 0, 0}; + const uchar *row1, *row2, *row3, *row4; + uchar empty[4] = {0, 0, 0, 0}; /* pixel value must be already wrapped, however values at boundaries may flip */ if (wrap_x) { @@ -418,26 +413,26 @@ BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, ma_mb = (1.0f - a) * (1.0f - b); if (components == 1) { - byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + - a_b * row4[0] + 0.5f); + byte_output[0] = (uchar)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + + 0.5f); } else if (components == 3) { - byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + - a_b * row4[0] + 0.5f); - byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + - a_b * row4[1] + 0.5f); - byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + - a_b * row4[2] + 0.5f); + byte_output[0] = (uchar)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + + 0.5f); + byte_output[1] = (uchar)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + + 0.5f); + byte_output[2] = (uchar)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + + 0.5f); } else { - byte_output[0] = (unsigned char)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + - a_b * row4[0] + 0.5f); - byte_output[1] = (unsigned char)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + - a_b * row4[1] + 0.5f); - byte_output[2] = (unsigned char)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + - a_b * row4[2] + 0.5f); - byte_output[3] = (unsigned char)(ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + - a_b * row4[3] + 0.5f); + byte_output[0] = (uchar)(ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0] + + 0.5f); + byte_output[1] = (uchar)(ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1] + + 0.5f); + byte_output[2] = (uchar)(ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2] + + 0.5f); + byte_output[3] = (uchar)(ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3] + + 0.5f); } } } @@ -449,13 +444,8 @@ void BLI_bilinear_interpolation_fl( NULL, buffer, NULL, output, width, height, components, u, v, false, false); } -void BLI_bilinear_interpolation_char(const unsigned char *buffer, - unsigned char *output, - int width, - int height, - int components, - float u, - float v) +void BLI_bilinear_interpolation_char( + const uchar *buffer, uchar *output, int width, int height, int components, float u, float v) { bilinear_interpolation( buffer, NULL, output, NULL, width, height, components, u, v, false, false); @@ -475,8 +465,8 @@ void BLI_bilinear_interpolation_wrap_fl(const float *buffer, NULL, buffer, NULL, output, width, height, components, u, v, wrap_x, wrap_y); } -void BLI_bilinear_interpolation_wrap_char(const unsigned char *buffer, - unsigned char *output, +void BLI_bilinear_interpolation_wrap_char(const uchar *buffer, + uchar *output, int width, int height, int components, @@ -634,10 +624,10 @@ void BLI_ewa_filter(const int width, U0 = uv[0] * (float)width; V0 = uv[1] * (float)height; - u1 = (int)(floorf(U0 - ue)); - u2 = (int)(ceilf(U0 + ue)); - v1 = (int)(floorf(V0 - ve)); - v2 = (int)(ceilf(V0 + ve)); + u1 = (int)floorf(U0 - ue); + u2 = (int)ceilf(U0 + ue); + v1 = (int)floorf(V0 - ve); + v2 = (int)ceilf(V0 + ve); /* sane clamping to avoid unnecessarily huge loops */ /* NOTE: if eccentricity gets clamped (see above), @@ -679,7 +669,7 @@ void BLI_ewa_filter(const int width, for (u = u1; u <= u2; u++) { if (Q < (float)(EWA_MAXIDX + 1)) { float tc[4]; - const float wt = EWA_WTS[(Q < 0.0f) ? 0 : (unsigned int)Q]; + const float wt = EWA_WTS[(Q < 0.0f) ? 0 : (uint)Q]; read_pixel_cb(userdata, u, v, tc); madd_v3_v3fl(result, tc, wt); result[3] += use_alpha ? tc[3] * wt : 0.0f; diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index fcd017b3082..d997eae26fb 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -113,7 +113,6 @@ void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */ m1[2][1] = m2[2][1]; m1[2][2] = m2[2][2]; - /* Reevan's Bugfix */ m1[0][3] = 0.0f; m1[1][3] = 0.0f; m1[2][3] = 0.0f; @@ -787,14 +786,14 @@ void mul_m2_v2(const float mat[2][2], float vec[2]) mul_v2_m2v2(vec, mat, vec); } -void mul_mat3_m4_v3(const float M[4][4], float r[3]) +void mul_mat3_m4_v3(const float mat[4][4], float r[3]) { const float x = r[0]; const float y = r[1]; - r[0] = x * M[0][0] + y * M[1][0] + M[2][0] * r[2]; - r[1] = x * M[0][1] + y * M[1][1] + M[2][1] * r[2]; - r[2] = x * M[0][2] + y * M[1][2] + M[2][2] * r[2]; + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * r[2]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * r[2]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * r[2]; } void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3]) @@ -1116,32 +1115,32 @@ double determinant_m3_array_db(const double m[3][3]) m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); } -bool invert_m2_m2(float m1[2][2], const float m2[2][2]) +bool invert_m2_m2(float inverse[2][2], const float mat[2][2]) { - adjoint_m2_m2(m1, m2); - float det = determinant_m2(m2[0][0], m2[1][0], m2[0][1], m2[1][1]); + adjoint_m2_m2(inverse, mat); + float det = determinant_m2(mat[0][0], mat[1][0], mat[0][1], mat[1][1]); bool success = (det != 0.0f); if (success) { - m1[0][0] /= det; - m1[1][0] /= det; - m1[0][1] /= det; - m1[1][1] /= det; + inverse[0][0] /= det; + inverse[1][0] /= det; + inverse[0][1] /= det; + inverse[1][1] /= det; } return success; } -bool invert_m3_ex(float m[3][3], const float epsilon) +bool invert_m3_ex(float mat[3][3], const float epsilon) { - float tmp[3][3]; - const bool success = invert_m3_m3_ex(tmp, m, epsilon); + float mat_tmp[3][3]; + const bool success = invert_m3_m3_ex(mat_tmp, mat, epsilon); - copy_m3_m3(m, tmp); + copy_m3_m3(mat, mat_tmp); return success; } -bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon) +bool invert_m3_m3_ex(float inverse[3][3], const float mat[3][3], const float epsilon) { float det; int a, b; @@ -1150,10 +1149,10 @@ bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon) BLI_assert(epsilon >= 0.0f); /* calc adjoint */ - adjoint_m3_m3(m1, m2); + adjoint_m3_m3(inverse, mat); /* then determinant old matrix! */ - det = determinant_m3_array(m2); + det = determinant_m3_array(mat); success = (fabsf(det) > epsilon); @@ -1161,33 +1160,33 @@ bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon) det = 1.0f / det; for (a = 0; a < 3; a++) { for (b = 0; b < 3; b++) { - m1[a][b] *= det; + inverse[a][b] *= det; } } } return success; } -bool invert_m3(float m[3][3]) +bool invert_m3(float mat[3][3]) { - float tmp[3][3]; - const bool success = invert_m3_m3(tmp, m); + float mat_tmp[3][3]; + const bool success = invert_m3_m3(mat_tmp, mat); - copy_m3_m3(m, tmp); + copy_m3_m3(mat, mat_tmp); return success; } -bool invert_m3_m3(float m1[3][3], const float m2[3][3]) +bool invert_m3_m3(float inverse[3][3], const float mat[3][3]) { float det; int a, b; bool success; /* calc adjoint */ - adjoint_m3_m3(m1, m2); + adjoint_m3_m3(inverse, mat); /* then determinant old matrix! */ - det = determinant_m3_array(m2); + det = determinant_m3_array(mat); success = (det != 0.0f); @@ -1195,7 +1194,7 @@ bool invert_m3_m3(float m1[3][3], const float m2[3][3]) det = 1.0f / det; for (a = 0; a < 3; a++) { for (b = 0; b < 3; b++) { - m1[a][b] *= det; + inverse[a][b] *= det; } } } @@ -1203,12 +1202,12 @@ bool invert_m3_m3(float m1[3][3], const float m2[3][3]) return success; } -bool invert_m4(float m[4][4]) +bool invert_m4(float mat[4][4]) { - float tmp[4][4]; - const bool success = invert_m4_m4(tmp, m); + float mat_tmp[4][4]; + const bool success = invert_m4_m4(mat_tmp, mat); - copy_m4_m4(m, tmp); + copy_m4_m4(mat, mat_tmp); return success; } @@ -2128,6 +2127,12 @@ void size_to_mat4(float R[4][4], const float size[3]) R[3][3] = 1.0f; } +void mat3_to_size_2d(float size[2], const float M[3][3]) +{ + size[0] = len_v2(M[0]); + size[1] = len_v2(M[1]); +} + void mat3_to_size(float size[3], const float M[3][3]) { size[0] = len_v3(M[0]); @@ -2191,11 +2196,11 @@ float mat4_to_scale(const float mat[4][4]) return len_v3(unit_vec); } -float mat4_to_xy_scale(const float M[4][4]) +float mat4_to_xy_scale(const float mat[4][4]) { /* unit length vector in xy plane */ float unit_vec[3] = {(float)M_SQRT1_2, (float)M_SQRT1_2, 0.0f}; - mul_mat3_m4_v3(M, unit_vec); + mul_mat3_m4_v3(mat, unit_vec); return len_v3(unit_vec); } @@ -2240,12 +2245,6 @@ void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]) copy_m3_m4(mat3, wmat); normalize_m3_m3(mat3_n, mat3); - /* So scale doesn't interfere with rotation T24291. */ - /* FIXME: this is a workaround for negative matrix not working for rotation conversion. */ - if (is_negative_m3(mat3)) { - negate_m3(mat3_n); - } - mat3_normalized_to_quat(quat, mat3_n); copy_v3_v3(loc, wmat[3]); } @@ -2254,7 +2253,7 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat { float rot[3][3]; mat4_to_loc_rot_size(loc, rot, size, wmat); - mat3_normalized_to_quat(quat, rot); + mat3_normalized_to_quat_fast(quat, rot); } /** @@ -2393,8 +2392,8 @@ void blend_m3_m3m3(float out[3][3], mat3_to_rot_size(drot, dscale, dst); mat3_to_rot_size(srot, sscale, src); - mat3_normalized_to_quat(dquat, drot); - mat3_normalized_to_quat(squat, srot); + mat3_normalized_to_quat_fast(dquat, drot); + mat3_normalized_to_quat_fast(squat, srot); /* do blending */ interp_qt_qtqt(fquat, dquat, squat, srcweight); @@ -2419,8 +2418,8 @@ void blend_m4_m4m4(float out[4][4], mat4_to_loc_rot_size(dloc, drot, dscale, dst); mat4_to_loc_rot_size(sloc, srot, sscale, src); - mat3_normalized_to_quat(dquat, drot); - mat3_normalized_to_quat(squat, srot); + mat3_normalized_to_quat_fast(dquat, drot); + mat3_normalized_to_quat_fast(squat, srot); /* do blending */ interp_v3_v3v3(floc, dloc, sloc, srcweight); @@ -2456,11 +2455,11 @@ void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], con * Note that a flip of two axes is just a rotation of 180 degrees around the third axis, and * three flipped axes are just an 180 degree rotation + a single axis flip. It is thus sufficient * to solve this problem for single axis flips. */ - if (determinant_m3_array(U_A) < 0) { + if (is_negative_m3(U_A)) { mul_m3_fl(U_A, -1.0f); mul_m3_fl(P_A, -1.0f); } - if (determinant_m3_array(U_B) < 0) { + if (is_negative_m3(U_B)) { mul_m3_fl(U_B, -1.0f); mul_m3_fl(P_B, -1.0f); } @@ -2501,16 +2500,14 @@ void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], con bool is_negative_m3(const float mat[3][3]) { - float vec[3]; - cross_v3_v3v3(vec, mat[0], mat[1]); - return (dot_v3v3(vec, mat[2]) < 0.0f); + return determinant_m3_array(mat) < 0.0f; } bool is_negative_m4(const float mat[4][4]) { - float vec[3]; - cross_v3_v3v3(vec, mat[0], mat[1]); - return (dot_v3v3(vec, mat[2]) < 0.0f); + /* Don't use #determinant_m4 as only the 3x3 components are needed + * when the matrix is used as a transformation to represent location/scale/rotation. */ + return determinant_m4_mat3_array(mat) < 0.0f; } bool is_zero_m3(const float mat[3][3]) @@ -2568,11 +2565,8 @@ void loc_eul_size_to_mat4(float R[4][4], R[3][2] = loc[2]; } -void loc_eulO_size_to_mat4(float R[4][4], - const float loc[3], - const float eul[3], - const float size[3], - const short rotOrder) +void loc_eulO_size_to_mat4( + float R[4][4], const float loc[3], const float eul[3], const float size[3], const short order) { float rmat[3][3], smat[3][3], tmat[3][3]; @@ -2580,7 +2574,7 @@ void loc_eulO_size_to_mat4(float R[4][4], unit_m4(R); /* Make rotation + scaling part. */ - eulO_to_mat3(rmat, eul, rotOrder); + eulO_to_mat3(rmat, eul, order); size_to_mat3(smat, size); mul_m3_m3m3(tmat, rmat, smat); @@ -3082,14 +3076,14 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) } } -void pseudoinverse_m4_m4(float Ainv[4][4], const float A_[4][4], float epsilon) +void pseudoinverse_m4_m4(float inverse[4][4], const float mat[4][4], float epsilon) { /* compute Moore-Penrose pseudo inverse of matrix, singular values * below epsilon are ignored for stability (truncated SVD) */ float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4]; int i; - transpose_m4_m4(A, A_); + transpose_m4_m4(A, mat); svd_m4(V, W, U, A); transpose_m4(U); transpose_m4(V); @@ -3101,18 +3095,18 @@ void pseudoinverse_m4_m4(float Ainv[4][4], const float A_[4][4], float epsilon) transpose_m4(V); - mul_m4_series(Ainv, U, Wm, V); + mul_m4_series(inverse, U, Wm, V); } -void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon) +void pseudoinverse_m3_m3(float inverse[3][3], const float mat[3][3], float epsilon) { /* try regular inverse when possible, otherwise fall back to slow svd */ - if (!invert_m3_m3(Ainv, A)) { - float tmp[4][4], tmpinv[4][4]; + if (!invert_m3_m3(inverse, mat)) { + float mat_tmp[4][4], tmpinv[4][4]; - copy_m4_m3(tmp, A); - pseudoinverse_m4_m4(tmpinv, tmp, epsilon); - copy_m3_m4(Ainv, tmpinv); + copy_m4_m3(mat_tmp, mat); + pseudoinverse_m4_m4(tmpinv, mat_tmp, epsilon); + copy_m3_m4(inverse, tmpinv); } } @@ -3122,22 +3116,50 @@ bool has_zero_axis_m4(const float matrix[4][4]) len_squared_v3(matrix[2]) < FLT_EPSILON; } -void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]) +void zero_axis_bias_m4(float mat[4][4]) +{ + const bool axis_x_degenerate = len_squared_v3(mat[0]) < FLT_EPSILON; + const bool axis_y_degenerate = len_squared_v3(mat[1]) < FLT_EPSILON; + const bool axis_z_degenerate = len_squared_v3(mat[2]) < FLT_EPSILON; + + /* X Axis. */ + if (axis_x_degenerate && !axis_y_degenerate && !axis_z_degenerate) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + mul_v3_fl(mat[0], FLT_EPSILON); + return; + } + + /* Y Axis. */ + if (!axis_x_degenerate && axis_y_degenerate && !axis_z_degenerate) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + mul_v3_fl(mat[1], FLT_EPSILON); + return; + } + + /* Z Axis. */ + if (!axis_x_degenerate && !axis_y_degenerate && axis_z_degenerate) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + mul_v3_fl(mat[2], FLT_EPSILON); + return; + } +} + +void invert_m4_m4_safe(float inverse[4][4], const float mat[4][4]) { - if (!invert_m4_m4(Ainv, A)) { - float Atemp[4][4]; + if (!invert_m4_m4(inverse, mat)) { + float mat_tmp[4][4]; - copy_m4_m4(Atemp, A); + copy_m4_m4(mat_tmp, mat); /* Matrix is degenerate (e.g. 0 scale on some axis), ideally we should * never be in this situation, but try to invert it anyway with tweak. */ - Atemp[0][0] += 1e-8f; - Atemp[1][1] += 1e-8f; - Atemp[2][2] += 1e-8f; + mat_tmp[0][0] += 1e-8f; + mat_tmp[1][1] += 1e-8f; + mat_tmp[2][2] += 1e-8f; - if (!invert_m4_m4(Ainv, Atemp)) { - unit_m4(Ainv); + if (!invert_m4_m4(inverse, mat_tmp)) { + unit_m4(inverse); } } } @@ -3157,24 +3179,24 @@ void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]) * where we want to specify the length of the degenerate axes. * \{ */ -void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4]) +void invert_m4_m4_safe_ortho(float inverse[4][4], const float mat[4][4]) { - if (UNLIKELY(!invert_m4_m4(Ainv, A))) { - float Atemp[4][4]; - copy_m4_m4(Atemp, A); - if (UNLIKELY(!(orthogonalize_m4_zero_axes(Atemp, 1.0f) && invert_m4_m4(Ainv, Atemp)))) { - unit_m4(Ainv); + if (UNLIKELY(!invert_m4_m4(inverse, mat))) { + float mat_tmp[4][4]; + copy_m4_m4(mat_tmp, mat); + if (UNLIKELY(!(orthogonalize_m4_zero_axes(mat_tmp, 1.0f) && invert_m4_m4(inverse, mat_tmp)))) { + unit_m4(inverse); } } } -void invert_m3_m3_safe_ortho(float Ainv[3][3], const float A[3][3]) +void invert_m3_m3_safe_ortho(float inverse[3][3], const float mat[3][3]) { - if (UNLIKELY(!invert_m3_m3(Ainv, A))) { - float Atemp[3][3]; - copy_m3_m3(Atemp, A); - if (UNLIKELY(!(orthogonalize_m3_zero_axes(Atemp, 1.0f) && invert_m3_m3(Ainv, Atemp)))) { - unit_m3(Ainv); + if (UNLIKELY(!invert_m3_m3(inverse, mat))) { + float mat_tmp[3][3]; + copy_m3_m3(mat_tmp, mat); + if (UNLIKELY(!(orthogonalize_m3_zero_axes(mat_tmp, 1.0f) && invert_m3_m3(inverse, mat_tmp)))) { + unit_m3(inverse); } } } diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index f0bfc7c21e1..ff45bbee5c9 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -176,7 +176,7 @@ void quat_to_compatible_quat(float q[4], const float a[4], const float old[4]) } } -/* skip error check, currently only needed by mat3_to_quat_is_ok */ +/* Skip error check, currently only needed by #mat3_to_quat_legacy. */ static void quat_to_mat3_no_error(float m[3][3], const float q[4]) { double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; @@ -269,9 +269,11 @@ void quat_to_mat4(float m[4][4], const float q[4]) m[3][3] = 1.0f; } -void mat3_normalized_to_quat(float q[4], const float mat[3][3]) +void mat3_normalized_to_quat_fast(float q[4], const float mat[3][3]) { BLI_ASSERT_UNIT_M3(mat); + /* Caller must ensure matrices aren't negative for valid results, see: T24291, T94231. */ + BLI_assert(!is_negative_m3(mat)); /* Check the trace of the matrix - bad precision if close to -1. */ const float trace = mat[0][0] + mat[1][1] + mat[2][2]; @@ -332,34 +334,54 @@ void mat3_normalized_to_quat(float q[4], const float mat[3][3]) normalize_qt(q); } -void mat3_to_quat(float q[4], const float m[3][3]) -{ - float unit_mat[3][3]; - /* work on a copy */ - /* this is needed AND a 'normalize_qt' in the end */ - normalize_m3_m3(unit_mat, m); - mat3_normalized_to_quat(q, unit_mat); +static void mat3_normalized_to_quat_with_checks(float q[4], float mat[3][3]) +{ + const float det = determinant_m3_array(mat); + if (UNLIKELY(!isfinite(det))) { + unit_m3(mat); + } + else if (UNLIKELY(det < 0.0f)) { + negate_m3(mat); + } + mat3_normalized_to_quat_fast(q, mat); } -void mat4_normalized_to_quat(float q[4], const float m[4][4]) +void mat3_normalized_to_quat(float q[4], const float mat[3][3]) { - float mat3[3][3]; + float unit_mat_abs[3][3]; + copy_m3_m3(unit_mat_abs, mat); + mat3_normalized_to_quat_with_checks(q, unit_mat_abs); +} - copy_m3_m4(mat3, m); - mat3_normalized_to_quat(q, mat3); +void mat3_to_quat(float q[4], const float mat[3][3]) +{ + float unit_mat_abs[3][3]; + normalize_m3_m3(unit_mat_abs, mat); + mat3_normalized_to_quat_with_checks(q, unit_mat_abs); } -void mat4_to_quat(float q[4], const float m[4][4]) +void mat4_normalized_to_quat(float q[4], const float mat[4][4]) { - float mat3[3][3]; + float unit_mat_abs[3][3]; + copy_m3_m4(unit_mat_abs, mat); + mat3_normalized_to_quat_with_checks(q, unit_mat_abs); +} - copy_m3_m4(mat3, m); - mat3_to_quat(q, mat3); +void mat4_to_quat(float q[4], const float mat[4][4]) +{ + float unit_mat_abs[3][3]; + copy_m3_m4(unit_mat_abs, mat); + normalize_m3(unit_mat_abs); + mat3_normalized_to_quat_with_checks(q, unit_mat_abs); } -void mat3_to_quat_is_ok(float q[4], const float wmat[3][3]) +void mat3_to_quat_legacy(float q[4], const float wmat[3][3]) { + /* Legacy version of #mat3_to_quat which has slightly different behavior. + * Keep for particle-system & boids since replacing this will make subtle changes + * that impact hair in existing files. See: D15772. */ + float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], angle, si, co, nor[3]; /* work on a copy */ @@ -498,7 +520,10 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q mul_qt_qtqt(q, tquat, q2); } -float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4], float r_twist[4]) +float quat_split_swing_and_twist(const float q_in[4], + const int axis, + float r_swing[4], + float r_twist[4]) { BLI_assert(axis >= 0 && axis <= 2); @@ -915,53 +940,63 @@ float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[ return len; } -void sin_cos_from_fraction(const int numerator, const int denominator, float *r_sin, float *r_cos) +void sin_cos_from_fraction(int numerator, int denominator, float *r_sin, float *r_cos) { - BLI_assert((numerator <= denominator) && (denominator > 0)); - if ((denominator & 3) == 0) { - const int denominator_4 = denominator / 4; - if (numerator <= denominator_4) { - /* Fall through. */ - } - else { - if (numerator <= denominator_4 * 2) { - const float phi = (float)(2.0 * M_PI) * - ((float)(numerator - denominator_4) / (float)denominator); - *r_sin = cosf(phi); - *r_cos = -sinf(phi); - } - else if (numerator <= denominator_4 * 3) { - const float phi = (float)(2.0 * M_PI) * - ((float)(numerator - (denominator_4 * 2)) / (float)denominator); - *r_sin = -sinf(phi); - *r_cos = -cosf(phi); - } - else { - const float phi = (float)(2.0 * M_PI) * - ((float)(numerator - (denominator_4 * 3)) / (float)denominator); - *r_cos = sinf(phi); - *r_sin = -cosf(phi); - } - return; - } - } - else if ((denominator & 1) == 0) { - const int denominator_2 = denominator / 2; - if (numerator <= denominator_2) { - /* Fall through. */ - } - else { - const float phi = (float)(2.0 * M_PI) * - ((float)(numerator - denominator_2) / (float)denominator); - *r_sin = -sinf(phi); - *r_cos = -cosf(phi); - return; - } + /* By default, creating a circle from an integer: calling #sinf & #cosf on the fraction doesn't + * create symmetrical values (because floats can't represent Pi exactly). + * Resolve this when the rotation is calculated from a fraction by mapping the `numerator` + * to lower values so X/Y values for points around a circle are exactly symmetrical, see T87779. + * + * Multiply both the `numerator` and `denominator` by eight to ensure we can divide the circle + * into 8 octants. For each octant, we then use symmetry and negation to bring the `numerator` + * closer to the origin where precision is highest. + * + * Cases 2, 4, 5 and 7, use the trigonometric identity sin(-x) == -sin(x). + * Cases 1, 2, 5 and 6, swap the pointers `r_sin` and `r_cos`. + */ + BLI_assert(0 <= numerator); + BLI_assert(numerator <= denominator); + BLI_assert(denominator > 0); + + numerator *= 8; /* Multiply numerator the same as denominator. */ + const int octant = numerator / denominator; /* Determine the octant. */ + denominator *= 8; /* Ensure denominator is a multiple of eight. */ + float cos_sign = 1.0f; /* Either 1.0f or -1.0f. */ + + switch (octant) { + case 0: + /* Primary octant, nothing to do. */ + break; + case 1: + case 2: + numerator = (denominator / 4) - numerator; + SWAP(float *, r_sin, r_cos); + break; + case 3: + case 4: + numerator = (denominator / 2) - numerator; + cos_sign = -1.0f; + break; + case 5: + case 6: + numerator = numerator - (denominator * 3 / 4); + SWAP(float *, r_sin, r_cos); + cos_sign = -1.0f; + break; + case 7: + numerator = numerator - denominator; + break; + default: + BLI_assert_unreachable(); } - const float phi = (float)(2.0 * M_PI) * ((float)numerator / (float)denominator); - *r_sin = sinf(phi); - *r_cos = cosf(phi); + BLI_assert(-denominator / 4 <= numerator); /* Numerator may be negative. */ + BLI_assert(numerator <= denominator / 4); + BLI_assert(cos_sign == -1.0f || cos_sign == 1.0f); + + const float angle = (float)(2.0 * M_PI) * ((float)numerator / (float)denominator); + *r_sin = sinf(angle); + *r_cos = cosf(angle) * cos_sign; } void print_qt(const char *str, const float q[4]) @@ -1371,10 +1406,10 @@ void mat4_normalized_to_eul(float eul[3], const float m[4][4]) copy_m3_m4(mat3, m); mat3_normalized_to_eul(eul, mat3); } -void mat4_to_eul(float eul[3], const float m[4][4]) +void mat4_to_eul(float eul[3], const float mat[4][4]) { float mat3[3][3]; - copy_m3_m4(mat3, m); + copy_m3_m4(mat3, mat); mat3_to_eul(eul, mat3); } @@ -1409,7 +1444,7 @@ void eul_to_quat(float quat[4], const float eul[3]) quat[3] = cj * cs - sj * sc; } -void rotate_eul(float beul[3], const char axis, const float ang) +void rotate_eul(float beul[3], const char axis, const float angle) { float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; @@ -1417,13 +1452,13 @@ void rotate_eul(float beul[3], const char axis, const float ang) eul[0] = eul[1] = eul[2] = 0.0f; if (axis == 'X') { - eul[0] = ang; + eul[0] = angle; } else if (axis == 'Y') { - eul[1] = ang; + eul[1] = angle; } else { - eul[2] = ang; + eul[2] = angle; } eul_to_mat3(mat1, eul); @@ -1442,7 +1477,7 @@ void compatible_eul(float eul[3], const float oldrot[3]) const float pi_x2 = (2.0f * (float)M_PI); float deul[3]; - unsigned int i; + uint i; /* correct differences of about 360 degrees first */ for (i = 0; i < 3; i++) { @@ -1779,23 +1814,23 @@ void mat3_to_compatible_eulO(float eul[3], void mat4_normalized_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, - const float m[4][4]) + const float mat[4][4]) { float mat3[3][3]; /* for now, we'll just do this the slow way (i.e. copying matrices) */ - copy_m3_m4(mat3, m); + copy_m3_m4(mat3, mat); mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3); } void mat4_to_compatible_eulO(float eul[3], const float oldrot[3], const short order, - const float m[4][4]) + const float mat[4][4]) { float mat3[3][3]; /* for now, we'll just do this the slow way (i.e. copying matrices) */ - copy_m3_m4(mat3, m); + copy_m3_m4(mat3, mat); normalize_m3(mat3); mat3_normalized_to_compatible_eulO(eul, oldrot, order, mat3); } @@ -1814,7 +1849,7 @@ void quat_to_compatible_eulO(float eul[3], /* rotate the given euler by the given angle on the specified axis */ /* NOTE: is this safe to do with different axis orders? */ -void rotate_eulO(float beul[3], const short order, char axis, float ang) +void rotate_eulO(float beul[3], const short order, const char axis, const float angle) { float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; @@ -1823,13 +1858,13 @@ void rotate_eulO(float beul[3], const short order, char axis, float ang) zero_v3(eul); if (axis == 'X') { - eul[0] = ang; + eul[0] = angle; } else if (axis == 'Y') { - eul[1] = ang; + eul[1] = angle; } else { - eul[2] = ang; + eul[2] = angle; } eulO_to_mat3(mat1, eul, order); @@ -2143,8 +2178,8 @@ void quat_apply_track(float quat[4], short axis, short upflag) * up axis is used X->Y, Y->X, Z->X, if this first up axis isn't used then rotate 90d * the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */ if (upflag != (2 - axis) >> 1) { - float q[4] = {sqrt_1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */ - q[axis + 1] = ((axis == 1)) ? sqrt_1_2 : -sqrt_1_2; /* flip non Y axis */ + float q[4] = {sqrt_1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */ + q[axis + 1] = (axis == 1) ? sqrt_1_2 : -sqrt_1_2; /* flip non Y axis */ mul_qt_qtqt(quat, quat, q); } } @@ -2325,8 +2360,8 @@ bool mat3_from_axis_conversion( value = ((src_forward << (0 * 3)) | (src_up << (1 * 3)) | (dst_forward << (2 * 3)) | (dst_up << (3 * 3))); - for (uint i = 0; i < (ARRAY_SIZE(_axis_convert_matrix)); i++) { - for (uint j = 0; j < (ARRAY_SIZE(*_axis_convert_lut)); j++) { + for (uint i = 0; i < ARRAY_SIZE(_axis_convert_matrix); i++) { + for (uint j = 0; j < ARRAY_SIZE(*_axis_convert_lut); j++) { if (_axis_convert_lut[i][j] == value) { copy_m3_m3(r_mat, _axis_convert_matrix[i]); return true; diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c index b5650410a70..1196c0bed7f 100644 --- a/source/blender/blenlib/intern/math_solvers.c +++ b/source/blender/blenlib/intern/math_solvers.c @@ -45,7 +45,7 @@ bool BLI_tridiagonal_solve( return false; } - size_t bytes = sizeof(double) * (unsigned)count; + size_t bytes = sizeof(double) * (uint)count; double *c1 = (double *)MEM_mallocN(bytes * 2, "tridiagonal_c1d1"); double *d1 = c1 + count; @@ -112,7 +112,7 @@ bool BLI_tridiagonal_solve_cyclic( return BLI_tridiagonal_solve(a, b, c, d, r_x, count); } - size_t bytes = sizeof(float) * (unsigned)count; + size_t bytes = sizeof(float) * (uint)count; float *tmp = (float *)MEM_mallocN(bytes * 2, "tridiagonal_ex"); float *b2 = tmp + count; diff --git a/source/blender/blenlib/intern/math_vec.cc b/source/blender/blenlib/intern/math_vec.cc index 99c873299fe..8d1f850d8e5 100644 --- a/source/blender/blenlib/intern/math_vec.cc +++ b/source/blender/blenlib/intern/math_vec.cc @@ -108,7 +108,7 @@ isect_result<mpq2> isect_seg_seg(const mpq2 &v1, const mpq2 &v2, const mpq2 &v3, uint64_t hash_mpq_class(const mpq_class &value) { /* TODO: better/faster implementation of this. */ - return get_default_hash(static_cast<float>(value.get_d())); + return get_default_hash(float(value.get_d())); } #endif diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 5dcdabaf760..f65a5acceae 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -499,7 +499,7 @@ float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const f /* calculate the sign (reuse 'tproj') */ cross_v3_v3v3(tproj, v2_proj, v1_proj); if (dot_v3v3(tproj, axis) < 0.0f) { - angle = ((float)(M_PI * 2.0)) - angle; + angle = (float)(M_PI * 2.0) - angle; } return angle; diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 700c126ca4c..3efe62d2984 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -1675,7 +1675,7 @@ static Edge find_good_sorting_edge(const Vert *testp, * The algorithm is similar to the one for find_ambient_cell, except that * instead of an arbitrary point known to be outside the whole mesh, we * have a particular point (v) and we just want to determine the patches - * that that point is between in sorting-around-an-edge order. + * that point is between in sorting-around-an-edge order. */ static int find_containing_cell(const Vert *v, int t, @@ -2527,7 +2527,7 @@ class InsideShapeTestData { static void inside_shape_callback(void *userdata, int index, const BVHTreeRay *ray, - BVHTreeRayHit *UNUSED(hit)) + BVHTreeRayHit * /*hit*/) { const int dbg_level = 0; if (dbg_level > 0) { @@ -2966,6 +2966,11 @@ static std::ostream &operator<<(std::ostream &os, const FaceMergeState &fms) * \a tris all have the same original face. * Find the 2d edge/triangle topology for these triangles, but only the ones facing in the * norm direction, and whether each edge is dissolvable or not. + * If we did the initial triangulation properly, and any Delaunay triangulations of intersections + * properly, then each triangle edge should have at most one neighbor. + * However, there can be anomalies. For example, if an input face is self-intersecting, we fall + * back on the floating point poly-fill triangulation, which, after which all bets are off. + * Hence, try to be tolerant of such unexpected topology. */ static void init_face_merge_state(FaceMergeState *fms, const Vector<int> &tris, @@ -3053,16 +3058,35 @@ static void init_face_merge_state(FaceMergeState *fms, std::cout << "me.v1 == mf.vert[i] so set edge[" << me_index << "].left_face = " << f << "\n"; } - BLI_assert(me.left_face == -1); - fms->edge[me_index].left_face = f; + if (me.left_face != -1) { + /* Unexpected in the normal case: this means more than one triangle shares this + * edge in the same orientation. But be tolerant of this case. By making this + * edge not dissolvable, we'll avoid future problems due to this non-manifold topology. + */ + if (dbg_level > 1) { + std::cout << "me.left_face was already occupied, so triangulation wasn't good\n"; + } + me.dissolvable = false; + } + else { + fms->edge[me_index].left_face = f; + } } else { if (dbg_level > 1) { std::cout << "me.v1 != mf.vert[i] so set edge[" << me_index << "].right_face = " << f << "\n"; } - BLI_assert(me.right_face == -1); - fms->edge[me_index].right_face = f; + if (me.right_face != -1) { + /* Unexpected, analogous to the me.left_face != -1 case above. */ + if (dbg_level > 1) { + std::cout << "me.right_face was already occupied, so triangulation wasn't good\n"; + } + me.dissolvable = false; + } + else { + fms->edge[me_index].right_face = f; + } } fms->face[f].edge.append(me_index); } diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index d5585f953ec..ee29662698a 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -710,7 +710,7 @@ bool IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshAr * mark with null pointer and caller should call remove_null_faces(). * the loop is done. */ - this->face_[f_index] = NULL; + this->face_[f_index] = nullptr; return true; } Array<const Vert *> new_vert(new_len); @@ -829,13 +829,13 @@ struct BBPadData { static void pad_face_bb_range_func(void *__restrict userdata, const int iter, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { BBPadData *pad_data = static_cast<BBPadData *>(userdata); (*pad_data->face_bounding_box)[iter].expand(pad_data->pad); } -static void calc_face_bb_reduce(const void *__restrict UNUSED(userdata), +static void calc_face_bb_reduce(const void *__restrict /*userdata*/, void *__restrict chunk_join, void *__restrict chunk) { @@ -2032,10 +2032,10 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena) } /* Project along negative face normal so (x,y) can be used in 2d. */ float axis_mat[3][3]; float(*projverts)[2]; - unsigned int(*tris)[3]; + uint(*tris)[3]; const int totfilltri = flen - 2; /* Prepare projected vertices and array to receive triangles in tessellation. */ - tris = static_cast<unsigned int(*)[3]>(MEM_malloc_arrayN(totfilltri, sizeof(*tris), __func__)); + tris = static_cast<uint(*)[3]>(MEM_malloc_arrayN(totfilltri, sizeof(*tris), __func__)); projverts = static_cast<float(*)[2]>(MEM_malloc_arrayN(flen, sizeof(*projverts), __func__)); axis_dominant_v3_to_m3_negate(axis_mat, no); for (int j = 0; j < flen; ++j) { @@ -2047,7 +2047,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena) /* Put tessellation triangles into Face form. Record original edges where they exist. */ Array<Face *> ans(totfilltri); for (int t = 0; t < totfilltri; ++t) { - unsigned int *tri = tris[t]; + uint *tri = tris[t]; int eo[3]; const Vert *v[3]; for (int k = 0; k < 3; k++) { @@ -2419,7 +2419,7 @@ class TriOverlaps { } } first_overlap_ = Array<int>(tm.face_size(), -1); - for (int i = 0; i < static_cast<int>(overlap_num_); ++i) { + for (int i = 0; i < int(overlap_num_); ++i) { int t = overlap_[i].indexA; if (first_overlap_[t] == -1) { first_overlap_[t] = i; @@ -2451,7 +2451,7 @@ class TriOverlaps { } private: - static bool only_different_shapes(void *userdata, int index_a, int index_b, int UNUSED(thread)) + static bool only_different_shapes(void *userdata, int index_a, int index_b, int /*thread*/) { CBData *cbdata = static_cast<CBData *>(userdata); return cbdata->tm.face(index_a)->orig != cbdata->tm.face(index_b)->orig; @@ -2487,7 +2487,7 @@ static std::pair<int, int> canon_int_pair(int a, int b) static void calc_overlap_itts_range_func(void *__restrict userdata, const int iter, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { constexpr int dbg_level = 0; OverlapIttsData *data = static_cast<OverlapIttsData *>(userdata); @@ -2682,7 +2682,7 @@ static CDT_data calc_cluster_subdivided(const CoplanarClusterInfo &clinfo, const IMesh &tm, const TriOverlaps &ov, const Map<std::pair<int, int>, ITT_value> &itt_map, - IMeshArena *UNUSED(arena)) + IMeshArena * /*arena*/) { constexpr int dbg_level = 0; BLI_assert(c < clinfo.tot_cluster()); @@ -2889,7 +2889,7 @@ static void degenerate_range_func(void *__restrict userdata, chunk_data->has_degenerate_tri |= is_degenerate; } -static void degenerate_reduce(const void *__restrict UNUSED(userdata), +static void degenerate_reduce(const void *__restrict /*userdata*/, void *__restrict chunk_join, void *__restrict chunk) { @@ -2931,7 +2931,7 @@ static IMesh remove_degenerate_tris(const IMesh &tm_in) IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena) { return trimesh_nary_intersect( - tm_in, 1, [](int UNUSED(t)) { return 0; }, true, arena); + tm_in, 1, [](int /*t*/) { return 0; }, true, arena); } IMesh trimesh_nary_intersect(const IMesh &tm_in, diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index c39a2b5a27e..8da35e5ab56 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -115,8 +115,8 @@ static const float hashpntf[768] = { 0.713870, 0.555261, 0.951333, }; -extern const unsigned char BLI_noise_hash_uchar_512[512]; /* Quiet warning. */ -const unsigned char BLI_noise_hash_uchar_512[512] = { +extern const uchar BLI_noise_hash_uchar_512[512]; /* Quiet warning. */ +const uchar BLI_noise_hash_uchar_512[512] = { 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, @@ -939,9 +939,9 @@ void BLI_noise_voronoi(float x, float y, float z, float *da, float *pa, float me break; } - int xi = (int)(floor(x)); - int yi = (int)(floor(y)); - int zi = (int)(floor(z)); + int xi = (int)floor(x); + int yi = (int)floor(y); + int zi = (int)floor(z); da[0] = da[1] = da[2] = da[3] = 1e10f; for (int xx = xi - 1; xx <= xi + 1; xx++) { for (int yy = yi - 1; yy <= yi + 1; yy++) { @@ -1112,10 +1112,10 @@ static float BLI_cellNoiseU(float x, float y, float z) y = (y + 0.000001f) * 1.00001f; z = (z + 0.000001f) * 1.00001f; - int xi = (int)(floor(x)); - int yi = (int)(floor(y)); - int zi = (int)(floor(z)); - unsigned int n = xi + yi * 1301 + zi * 314159; + int xi = (int)floor(x); + int yi = (int)floor(y); + int zi = (int)floor(z); + uint n = xi + yi * 1301 + zi * 314159; n ^= (n << 13); return ((float)(n * (n * n * 15731 + 789221) + 1376312589) / 4294967296.0f); } @@ -1125,20 +1125,20 @@ float BLI_noise_cell(float x, float y, float z) return (2.0f * BLI_cellNoiseU(x, y, z) - 1.0f); } -void BLI_noise_cell_v3(float x, float y, float z, float ca[3]) +void BLI_noise_cell_v3(float x, float y, float z, float r_ca[3]) { /* avoid precision issues on unit coordinates */ x = (x + 0.000001f) * 1.00001f; y = (y + 0.000001f) * 1.00001f; z = (z + 0.000001f) * 1.00001f; - int xi = (int)(floor(x)); - int yi = (int)(floor(y)); - int zi = (int)(floor(z)); + int xi = (int)floor(x); + int yi = (int)floor(y); + int zi = (int)floor(z); const float *p = HASHPNT(xi, yi, zi); - ca[0] = p[0]; - ca[1] = p[1]; - ca[2] = p[2]; + r_ca[0] = p[0]; + r_ca[1] = p[1]; + r_ca[2] = p[2]; } /** \} */ @@ -1329,8 +1329,8 @@ float BLI_noise_mg_fbm( float BLI_noise_mg_multi_fractal( float x, float y, float z, float H, float lacunarity, float octaves, int noisebasis) { - /* This one is in fact rather confusing, - * there seem to be errors in the original source code (in all three versions of proc.text&mod), + /* This one is in fact rather confusing, there seem to be errors in the original source code + * (in all three versions of `proc.text & mod`), * I modified it to something that made sense to me, so it might be wrong. */ float (*noisefunc)(float, float, float); diff --git a/source/blender/blenlib/intern/noise.cc b/source/blender/blenlib/intern/noise.cc index a514c9e5183..65a6f102a7b 100644 --- a/source/blender/blenlib/intern/noise.cc +++ b/source/blender/blenlib/intern/noise.cc @@ -150,7 +150,7 @@ uint32_t hash_float(float4 k) BLI_INLINE float uint_to_float_01(uint32_t k) { - return static_cast<float>(k) / static_cast<float>(0xFFFFFFFFu); + return float(k) / float(0xFFFFFFFFu); } float hash_to_float(uint32_t kx) @@ -263,7 +263,6 @@ BLI_INLINE float mix(float v0, float v1, float x) * + + | * @ + + + + @ @------> x * v0 v1 - * */ BLI_INLINE float mix(float v0, float v1, float v2, float v3, float x, float y) { @@ -380,7 +379,7 @@ BLI_INLINE float noise_grad(uint32_t hash, float x, float y, float z, float w) BLI_INLINE float floor_fraction(float x, int &i) { - i = (int)x - ((x < 0) ? 1 : 0); + i = int(x) - ((x < 0) ? 1 : 0); return x - i; } @@ -537,7 +536,7 @@ template<typename T> float perlin_fractal_template(T position, float octaves, fl float maxamp = 0.0f; float sum = 0.0f; octaves = CLAMPIS(octaves, 0.0f, 15.0f); - int n = static_cast<int>(octaves); + int n = int(octaves); for (int i = 0; i <= n; i++) { float t = perlin(fscale * position); sum += t * amp; @@ -730,7 +729,7 @@ float musgrave_fBm(const float co, const float pwHL = std::pow(lacunarity, -H); const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value += perlin_signed(p) * pwr; pwr *= pwHL; p *= lacunarity; @@ -755,7 +754,7 @@ float musgrave_multi_fractal(const float co, const float pwHL = std::pow(lacunarity, -H); const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value *= (pwr * perlin_signed(p) + 1.0f); pwr *= pwHL; p *= lacunarity; @@ -784,7 +783,7 @@ float musgrave_hetero_terrain(const float co, float value = offset + perlin_signed(p); p *= lacunarity; - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { float increment = (perlin_signed(p) + offset) * pwr * value; value += increment; pwr *= pwHL; @@ -809,15 +808,14 @@ float musgrave_hybrid_multi_fractal(const float co, { float p = co; const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - float value = perlin_signed(p) + offset; - float weight = gain * value; - p *= lacunarity; + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) { if (weight > 1.0f) { weight = 1.0f; } @@ -830,8 +828,12 @@ float musgrave_hybrid_multi_fractal(const float co, } const float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value += rmd * ((perlin_signed(p) + offset) * pwr); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (perlin_signed(p) + offset) * pwr; + value += rmd * weight * signal; } return value; @@ -855,7 +857,7 @@ float musgrave_ridged_multi_fractal(const float co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { p *= lacunarity; weight = CLAMPIS(signal * gain, 0.0f, 1.0f); signal = offset - std::abs(perlin_signed(p)); @@ -881,7 +883,7 @@ float musgrave_fBm(const float2 co, const float pwHL = std::pow(lacunarity, -H); const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value += perlin_signed(p) * pwr; pwr *= pwHL; p *= lacunarity; @@ -906,7 +908,7 @@ float musgrave_multi_fractal(const float2 co, const float pwHL = std::pow(lacunarity, -H); const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value *= (pwr * perlin_signed(p) + 1.0f); pwr *= pwHL; p *= lacunarity; @@ -936,7 +938,7 @@ float musgrave_hetero_terrain(const float2 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { float increment = (perlin_signed(p) + offset) * pwr * value; value += increment; pwr *= pwHL; @@ -961,15 +963,14 @@ float musgrave_hybrid_multi_fractal(const float2 co, { float2 p = co; const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - float value = perlin_signed(p) + offset; - float weight = gain * value; - p *= lacunarity; + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) { if (weight > 1.0f) { weight = 1.0f; } @@ -982,8 +983,12 @@ float musgrave_hybrid_multi_fractal(const float2 co, } const float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value += rmd * ((perlin_signed(p) + offset) * pwr); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (perlin_signed(p) + offset) * pwr; + value += rmd * weight * signal; } return value; @@ -1007,7 +1012,7 @@ float musgrave_ridged_multi_fractal(const float2 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { p *= lacunarity; weight = CLAMPIS(signal * gain, 0.0f, 1.0f); signal = offset - std::abs(perlin_signed(p)); @@ -1034,7 +1039,7 @@ float musgrave_fBm(const float3 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value += perlin_signed(p) * pwr; pwr *= pwHL; p *= lacunarity; @@ -1060,7 +1065,7 @@ float musgrave_multi_fractal(const float3 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value *= (pwr * perlin_signed(p) + 1.0f); pwr *= pwHL; p *= lacunarity; @@ -1090,7 +1095,7 @@ float musgrave_hetero_terrain(const float3 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { float increment = (perlin_signed(p) + offset) * pwr * value; value += increment; pwr *= pwHL; @@ -1115,15 +1120,14 @@ float musgrave_hybrid_multi_fractal(const float3 co, { float3 p = co; const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - float value = perlin_signed(p) + offset; - float weight = gain * value; - p *= lacunarity; + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) { if (weight > 1.0f) { weight = 1.0f; } @@ -1136,8 +1140,12 @@ float musgrave_hybrid_multi_fractal(const float3 co, } const float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value += rmd * ((perlin_signed(p) + offset) * pwr); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (perlin_signed(p) + offset) * pwr; + value += rmd * weight * signal; } return value; @@ -1161,7 +1169,7 @@ float musgrave_ridged_multi_fractal(const float3 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { p *= lacunarity; weight = CLAMPIS(signal * gain, 0.0f, 1.0f); signal = offset - std::abs(perlin_signed(p)); @@ -1188,7 +1196,7 @@ float musgrave_fBm(const float4 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value += perlin_signed(p) * pwr; pwr *= pwHL; p *= lacunarity; @@ -1214,7 +1222,7 @@ float musgrave_multi_fractal(const float4 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 0; i < (int)octaves; i++) { + for (int i = 0; i < int(octaves); i++) { value *= (pwr * perlin_signed(p) + 1.0f); pwr *= pwHL; p *= lacunarity; @@ -1244,7 +1252,7 @@ float musgrave_hetero_terrain(const float4 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { float increment = (perlin_signed(p) + offset) * pwr * value; value += increment; pwr *= pwHL; @@ -1269,15 +1277,14 @@ float musgrave_hybrid_multi_fractal(const float4 co, { float4 p = co; const float pwHL = std::pow(lacunarity, -H); - float pwr = pwHL; - float value = perlin_signed(p) + offset; - float weight = gain * value; - p *= lacunarity; + float pwr = 1.0f; + float value = 0.0f; + float weight = 1.0f; const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; (weight > 0.001f) && (i < (int)octaves); i++) { + for (int i = 0; (weight > 0.001f) && (i < int(octaves)); i++) { if (weight > 1.0f) { weight = 1.0f; } @@ -1290,8 +1297,12 @@ float musgrave_hybrid_multi_fractal(const float4 co, } const float rmd = octaves - floorf(octaves); - if (rmd != 0.0f) { - value += rmd * ((perlin_signed(p) + offset) * pwr); + if ((rmd != 0.0f) && (weight > 0.001f)) { + if (weight > 1.0f) { + weight = 1.0f; + } + float signal = (perlin_signed(p) + offset) * pwr; + value += rmd * weight * signal; } return value; @@ -1315,7 +1326,7 @@ float musgrave_ridged_multi_fractal(const float4 co, const float octaves = CLAMPIS(octaves_unclamped, 0.0f, 15.0f); - for (int i = 1; i < (int)octaves; i++) { + for (int i = 1; i < int(octaves); i++) { p *= lacunarity; weight = CLAMPIS(signal * gain, 0.0f, 1.0f); signal = offset - std::abs(perlin_signed(p)); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 5a96221c8d1..afe8c3cc033 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -121,7 +121,7 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort } void BLI_path_sequence_encode( - char *string, const char *head, const char *tail, unsigned short numlen, int pic) + char *string, const char *head, const char *tail, ushort numlen, int pic) { sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail); } @@ -466,8 +466,8 @@ void BLI_path_rel(char *file, const char *relfile) #ifdef WIN32 if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs(relfile)) { char *ptemp; - /* fix missing volume name in relative base, - * can happen with old recent-files.txt files */ + /* Fix missing volume name in relative base, + * can happen with old `recent-files.txt` files. */ BLI_windows_get_default_root_dir(temp); ptemp = &temp[2]; if (!ELEM(relfile[0], '\\', '/')) { @@ -625,7 +625,7 @@ bool BLI_path_parent_dir(char *path) const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ char tmp[FILE_MAX + 4]; - BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir); + BLI_path_join(tmp, sizeof(tmp), path, parent_dir); BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */ if (!BLI_path_extension_check(tmp, parent_dir)) { @@ -1025,7 +1025,7 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen) if (BLI_current_working_dir(cwd, sizeof(cwd))) { char origpath[FILE_MAX]; BLI_strncpy(origpath, path, FILE_MAX); - BLI_join_dirfile(path, maxlen, cwd, origpath); + BLI_path_join(path, maxlen, cwd, origpath); } else { printf("Could not get the current working directory - $PWD for an unknown reason.\n"); @@ -1105,29 +1105,29 @@ bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *na path = BLI_getenv("PATH"); if (path) { - char filename[FILE_MAX]; + char filepath_test[FILE_MAX]; const char *temp; do { temp = strchr(path, separator); if (temp) { - memcpy(filename, path, temp - path); - filename[temp - path] = 0; + memcpy(filepath_test, path, temp - path); + filepath_test[temp - path] = 0; path = temp + 1; } else { - BLI_strncpy(filename, path, sizeof(filename)); + BLI_strncpy(filepath_test, path, sizeof(filepath_test)); } - BLI_path_append(filename, maxlen, name); + BLI_path_append(filepath_test, maxlen, name); if ( #ifdef _WIN32 - BLI_path_program_extensions_add_win32(filename, maxlen) + BLI_path_program_extensions_add_win32(filepath_test, maxlen) #else - BLI_exists(filename) + BLI_exists(filepath_test) #endif ) { - BLI_strncpy(fullname, filename, maxlen); + BLI_strncpy(fullname, filepath_test, maxlen); retval = true; break; } @@ -1204,87 +1204,6 @@ bool BLI_make_existing_file(const char *name) return BLI_dir_create_recursive(di); } -void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) -{ - int sl; - - if (string) { - /* ensure this is always set even if dir/file are NULL */ - string[0] = '\0'; - - if (ELEM(NULL, dir, file)) { - return; /* We don't want any NULLs */ - } - } - else { - return; /* string is NULL, probably shouldn't happen but return anyway */ - } - - /* Resolve relative references */ - if (relabase && dir[0] == '/' && dir[1] == '/') { - char *lslash; - - /* Get the file name, chop everything past the last slash (ie. the filename) */ - strcpy(string, relabase); - - lslash = (char *)BLI_path_slash_rfind(string); - if (lslash) { - *(lslash + 1) = 0; - } - - dir += 2; /* Skip over the relative reference */ - } -#ifdef WIN32 - else { - if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') { - BLI_strncpy(string, dir, 3); - dir += 2; - } - else if (BLI_strnlen(dir, 3) >= 2 && BLI_path_is_unc(dir)) { - string[0] = 0; - } - else { /* no drive specified */ - /* first option: get the drive from the relabase if it has one */ - if (relabase && BLI_strnlen(relabase, 3) >= 2 && relabase[1] == ':') { - BLI_strncpy(string, relabase, 3); - string[2] = '\\'; - string[3] = '\0'; - } - else { /* we're out of luck here, guessing the first valid drive, usually c:\ */ - BLI_windows_get_default_root_dir(string); - } - - /* ignore leading slashes */ - while (ELEM(*dir, '/', '\\')) { - dir++; - } - } - } -#endif - - strcat(string, dir); - - /* Make sure string ends in one (and only one) slash */ - /* first trim all slashes from the end of the string */ - sl = strlen(string); - while ((sl > 0) && ELEM(string[sl - 1], '/', '\\')) { - string[sl - 1] = '\0'; - sl--; - } - /* since we've now removed all slashes, put back one slash at the end. */ - strcat(string, "/"); - - while (ELEM(*file, '/', '\\')) { - /* Trim slashes from the front of file */ - file++; - } - - strcat(string, file); - - /* Push all slashes to the system preferred direction */ - BLI_path_slash_native(string); -} - static bool path_extension_check_ex(const char *str, const size_t str_len, const char *ext, @@ -1428,7 +1347,7 @@ bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) ssize_t a; /* first check the extension is already there */ - if ((ext_len <= path_len) && (STREQ(path + (path_len - ext_len), ext))) { + if ((ext_len <= path_len) && STREQ(path + (path_len - ext_len), ext)) { return true; } @@ -1529,56 +1448,20 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__re BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } -void BLI_join_dirfile(char *__restrict dst, - const size_t maxlen, - const char *__restrict dir, - const char *__restrict file) -{ -#ifdef DEBUG_STRSIZE - memset(dst, 0xff, sizeof(*dst) * maxlen); -#endif - size_t dirlen = BLI_strnlen(dir, maxlen); - - /* Arguments can't match. */ - BLI_assert(!ELEM(dst, dir, file)); - - /* Files starting with a separator cause a double-slash which could later be interpreted - * as a relative path where: `dir == "/"` and `file == "/file"` would result in "//file". */ - BLI_assert(file[0] != SEP); - - if (dirlen == maxlen) { - memcpy(dst, dir, dirlen); - dst[dirlen - 1] = '\0'; - return; /* dir fills the path */ - } - - memcpy(dst, dir, dirlen + 1); - - if (dirlen + 1 >= maxlen) { - return; /* fills the path */ - } - - /* inline BLI_path_slash_ensure */ - if ((dirlen > 0) && !ELEM(dst[dirlen - 1], SEP, ALTSEP)) { - dst[dirlen++] = SEP; - dst[dirlen] = '\0'; - } - - if (dirlen >= maxlen) { - return; /* fills the path */ - } - - BLI_strncpy(dst + dirlen, file, maxlen - dirlen); -} - -size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) +size_t BLI_path_join_array(char *__restrict dst, + const size_t dst_len, + const char *path_array[], + const int path_array_num) { + BLI_assert(path_array_num > 0); #ifdef DEBUG_STRSIZE memset(dst, 0xff, sizeof(*dst) * dst_len); #endif if (UNLIKELY(dst_len == 0)) { return 0; } + const char *path = path_array[0]; + const size_t dst_last = dst_len - 1; size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); @@ -1586,8 +1469,8 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat return ofs; } - /* remove trailing slashes, unless there are _only_ trailing slashes - * (allow "//" as the first argument). */ + /* Remove trailing slashes, unless there are *only* trailing slashes + * (allow `//` or `//some_path` as the first argument). */ bool has_trailing_slash = false; if (ofs != 0) { size_t len = ofs; @@ -1600,9 +1483,8 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat has_trailing_slash = (path[len] != '\0'); } - va_list args; - va_start(args, path); - while ((path = (const char *)va_arg(args, const char *))) { + for (int path_index = 1; path_index < path_array_num; path_index++) { + path = path_array[path_index]; has_trailing_slash = false; const char *path_init = path; while (ELEM(path[0], SEP, ALTSEP)) { @@ -1637,7 +1519,6 @@ size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *pat has_trailing_slash = (path_init != path); } } - va_end(args); if (has_trailing_slash) { if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c index eed87eda436..2b59de5b569 100644 --- a/source/blender/blenlib/intern/polyfill_2d.c +++ b/source/blender/blenlib/intern/polyfill_2d.c @@ -373,12 +373,12 @@ static bool kdtree2d_isect_tri_recursive(const struct KDTree2D *tree, # define KDTREE2D_ISECT_TRI_RECURSE_NEG \ (((node->neg != KDNODE_UNSET) && (co[node->axis] >= bounds[node->axis].min)) && \ - (kdtree2d_isect_tri_recursive( \ - tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->neg]))) + kdtree2d_isect_tri_recursive( \ + tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->neg])) # define KDTREE2D_ISECT_TRI_RECURSE_POS \ (((node->pos != KDNODE_UNSET) && (co[node->axis] <= bounds[node->axis].max)) && \ - (kdtree2d_isect_tri_recursive( \ - tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->pos]))) + kdtree2d_isect_tri_recursive( \ + tree, tri_index, tri_coords, tri_center, bounds, &tree->nodes[node->pos])) if (tri_center[node->axis] > co[node->axis]) { if (KDTREE2D_ISECT_TRI_RECURSE_POS) { diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index f6d91cdcc4f..2e9b15c623e 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -24,7 +24,7 @@ #include "BLI_strict_flags.h" #include "BLI_sys_types.h" -extern "C" unsigned char BLI_noise_hash_uchar_512[512]; /* noise.c */ +extern "C" uchar BLI_noise_hash_uchar_512[512]; /* noise.c */ #define hash BLI_noise_hash_uchar_512 /** @@ -36,14 +36,14 @@ struct RNG { MEM_CXX_CLASS_ALLOC_FUNCS("RNG") }; -RNG *BLI_rng_new(unsigned int seed) +RNG *BLI_rng_new(uint seed) { RNG *rng = new RNG(); rng->rng.seed(seed); return rng; } -RNG *BLI_rng_new_srandom(unsigned int seed) +RNG *BLI_rng_new_srandom(uint seed) { RNG *rng = new RNG(); rng->rng.seed_random(seed); @@ -60,19 +60,19 @@ void BLI_rng_free(RNG *rng) delete rng; } -void BLI_rng_seed(RNG *rng, unsigned int seed) +void BLI_rng_seed(RNG *rng, uint seed) { rng->rng.seed(seed); } -void BLI_rng_srandom(RNG *rng, unsigned int seed) +void BLI_rng_srandom(RNG *rng, uint seed) { rng->rng.seed_random(seed); } void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) { - rng->rng.get_bytes(blender::MutableSpan(bytes, static_cast<int64_t>(bytes_len))); + rng->rng.get_bytes(blender::MutableSpan(bytes, int64_t(bytes_len))); } int BLI_rng_get_int(RNG *rng) @@ -80,7 +80,7 @@ int BLI_rng_get_int(RNG *rng) return rng->rng.get_int32(); } -unsigned int BLI_rng_get_uint(RNG *rng) +uint BLI_rng_get_uint(RNG *rng) { return rng->rng.get_uint32(); } @@ -117,21 +117,21 @@ void BLI_rng_get_tri_sample_float_v3( copy_v3_v3(r_pt, rng->rng.get_triangle_sample_3d(v1, v2, v3)); } -void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_num) +void BLI_rng_shuffle_array(RNG *rng, void *data, uint elem_size_i, uint elem_num) { if (elem_num <= 1) { return; } const uint elem_size = elem_size_i; - unsigned int i = elem_num; + uint i = elem_num; void *temp = malloc(elem_size); while (i--) { - const unsigned int j = BLI_rng_get_uint(rng) % elem_num; + const uint j = BLI_rng_get_uint(rng) % elem_num; if (i != j) { - void *iElem = (unsigned char *)data + i * elem_size_i; - void *jElem = (unsigned char *)data + j * elem_size_i; + void *iElem = (uchar *)data + i * elem_size_i; + void *jElem = (uchar *)data + j * elem_size_i; memcpy(temp, iElem, elem_size); memcpy(iElem, jElem, elem_size); memcpy(jElem, temp, elem_size); @@ -141,15 +141,15 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig free(temp); } -void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, unsigned int bits_num) +void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, uint bits_num) { if (bits_num <= 1) { return; } - unsigned int i = bits_num; + uint i = bits_num; while (i--) { - const unsigned int j = BLI_rng_get_uint(rng) % bits_num; + const uint j = BLI_rng_get_uint(rng) % bits_num; if (i != j) { const bool i_bit = BLI_BITMAP_TEST(bitmap, i); const bool j_bit = BLI_BITMAP_TEST(bitmap, j); @@ -161,12 +161,12 @@ void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, unsigned int bi void BLI_rng_skip(RNG *rng, int n) { - rng->rng.skip((uint)n); + rng->rng.skip(uint(n)); } /***/ -void BLI_array_frand(float *ar, int count, unsigned int seed) +void BLI_array_frand(float *ar, int count, uint seed) { RNG rng; @@ -177,7 +177,7 @@ void BLI_array_frand(float *ar, int count, unsigned int seed) } } -float BLI_hash_frand(unsigned int seed) +float BLI_hash_frand(uint seed) { RNG rng; @@ -185,10 +185,7 @@ float BLI_hash_frand(unsigned int seed) return BLI_rng_get_float(&rng); } -void BLI_array_randomize(void *data, - unsigned int elem_size, - unsigned int elem_num, - unsigned int seed) +void BLI_array_randomize(void *data, uint elem_size, uint elem_num, uint seed) { RNG rng; @@ -196,7 +193,7 @@ void BLI_array_randomize(void *data, BLI_rng_shuffle_array(&rng, data, elem_size, elem_num); } -void BLI_bitmap_randomize(BLI_bitmap *bitmap, unsigned int bits_num, unsigned int seed) +void BLI_bitmap_randomize(BLI_bitmap *bitmap, uint bits_num, uint seed) { RNG rng; @@ -208,7 +205,7 @@ void BLI_bitmap_randomize(BLI_bitmap *bitmap, unsigned int bits_num, unsigned in static RNG rng_tab[BLENDER_MAX_THREADS]; -void BLI_thread_srandom(int thread, unsigned int seed) +void BLI_thread_srandom(int thread, uint seed) { if (thread >= BLENDER_MAX_THREADS) { thread = 0; @@ -237,12 +234,12 @@ struct RNG_THREAD_ARRAY { RNG_THREAD_ARRAY *BLI_rng_threaded_new() { - unsigned int i; + uint i; RNG_THREAD_ARRAY *rngarr = (RNG_THREAD_ARRAY *)MEM_mallocN(sizeof(RNG_THREAD_ARRAY), "random_array"); for (i = 0; i < BLENDER_MAX_THREADS; i++) { - BLI_rng_srandom(&rngarr->rng_tab[i], (unsigned int)clock()); + BLI_rng_srandom(&rngarr->rng_tab[i], uint(clock())); } return rngarr; @@ -284,9 +281,9 @@ BLI_INLINE double halton_ex(double invprimes, double *offset) return *offset; } -void BLI_halton_1d(unsigned int prime, double offset, int n, double *r) +void BLI_halton_1d(uint prime, double offset, int n, double *r) { - const double invprime = 1.0 / (double)prime; + const double invprime = 1.0 / double(prime); *r = 0.0; @@ -295,9 +292,9 @@ void BLI_halton_1d(unsigned int prime, double offset, int n, double *r) } } -void BLI_halton_2d(const unsigned int prime[2], double offset[2], int n, double *r) +void BLI_halton_2d(const uint prime[2], double offset[2], int n, double *r) { - const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; + const double invprimes[2] = {1.0 / double(prime[0]), 1.0 / double(prime[1])}; r[0] = r[1] = 0.0; @@ -308,10 +305,10 @@ void BLI_halton_2d(const unsigned int prime[2], double offset[2], int n, double } } -void BLI_halton_3d(const unsigned int prime[3], double offset[3], int n, double *r) +void BLI_halton_3d(const uint prime[3], double offset[3], int n, double *r) { const double invprimes[3] = { - 1.0 / (double)prime[0], 1.0 / (double)prime[1], 1.0 / (double)prime[2]}; + 1.0 / double(prime[0]), 1.0 / double(prime[1]), 1.0 / double(prime[2])}; r[0] = r[1] = r[2] = 0.0; @@ -322,9 +319,9 @@ void BLI_halton_3d(const unsigned int prime[3], double offset[3], int n, double } } -void BLI_halton_2d_sequence(const unsigned int prime[2], double offset[2], int n, double *r) +void BLI_halton_2d_sequence(const uint prime[2], double offset[2], int n, double *r) { - const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; + const double invprimes[2] = {1.0 / double(prime[0]), 1.0 / double(prime[1])}; for (int s = 0; s < n; s++) { for (int i = 0; i < 2; i++) { @@ -335,7 +332,7 @@ void BLI_halton_2d_sequence(const unsigned int prime[2], double offset[2], int n /* From "Sampling with Hammersley and Halton Points" TT Wong * Appendix: Source Code 1 */ -BLI_INLINE double radical_inverse(unsigned int n) +BLI_INLINE double radical_inverse(uint n) { double u = 0; @@ -350,15 +347,15 @@ BLI_INLINE double radical_inverse(unsigned int n) return u; } -void BLI_hammersley_1d(unsigned int n, double *r) +void BLI_hammersley_1d(uint n, double *r) { *r = radical_inverse(n); } -void BLI_hammersley_2d_sequence(unsigned int n, double *r) +void BLI_hammersley_2d_sequence(uint n, double *r) { - for (unsigned int s = 0; s < n; s++) { - r[s * 2 + 0] = (double)(s + 0.5) / (double)n; + for (uint s = 0; s < n; s++) { + r[s * 2 + 0] = double(s + 0.5) / double(n); r[s * 2 + 1] = radical_inverse(s); } } @@ -380,12 +377,12 @@ int RandomNumberGenerator::round_probabilistic(float x) BLI_assert(x >= 0.0f); const float round_up_probability = fractf(x); const bool round_up = round_up_probability > this->get_float(); - return (int)x + (int)round_up; + return int(x) + int(round_up); } float2 RandomNumberGenerator::get_unit_float2() { - float a = (float)(M_PI * 2.0) * this->get_float(); + float a = float(M_PI * 2.0) * this->get_float(); return {cosf(a), sinf(a)}; } @@ -394,7 +391,7 @@ float3 RandomNumberGenerator::get_unit_float3() float z = (2.0f * this->get_float()) - 1.0f; float r = 1.0f - z * z; if (r > 0.0f) { - float a = (float)(M_PI * 2.0) * this->get_float(); + float a = float(M_PI * 2.0) * this->get_float(); r = sqrtf(r); float x = r * cosf(a); float y = r * sinf(a); @@ -444,7 +441,7 @@ float3 RandomNumberGenerator::get_triangle_sample_3d(float3 v1, float3 v2, float void RandomNumberGenerator::get_bytes(MutableSpan<char> r_bytes) { constexpr int64_t mask_bytes = 2; - constexpr int64_t rand_stride = static_cast<int64_t>(sizeof(x_)) - mask_bytes; + constexpr int64_t rand_stride = int64_t(sizeof(x_)) - mask_bytes; int64_t last_len = 0; int64_t trim_len = r_bytes.size(); diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 92fd7f5937b..4145125c1d7 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -33,9 +33,9 @@ /* local types */ typedef struct PolyFill { - unsigned int edges, verts; + uint edges, verts; float min_xy[2], max_xy[2]; - unsigned short nr; + ushort nr; bool f; } PolyFill; @@ -44,7 +44,7 @@ typedef struct ScanFillVertLink { ScanFillEdge *edge_first, *edge_last; } ScanFillVertLink; -/* local funcs */ +/* Local functions. */ #define SF_EPSILON 0.00003f #define SF_EPSILON_SQ (SF_EPSILON * SF_EPSILON) @@ -304,9 +304,7 @@ static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed) return true; } -static ScanFillVertLink *addedgetoscanlist(ScanFillVertLink *scdata, - ScanFillEdge *eed, - unsigned int len) +static ScanFillVertLink *addedgetoscanlist(ScanFillVertLink *scdata, ScanFillEdge *eed, uint len) { /* inserts edge at correct location in ScanFillVertLink list */ /* returns sc when edge already exists */ @@ -428,10 +426,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx) } } -static void splitlist(ScanFillContext *sf_ctx, - ListBase *tempve, - ListBase *temped, - unsigned short nr) +static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, ushort nr) { /* Everything is in temp-list, write only poly nr to fill-list. */ ScanFillVert *eve, *eve_next; @@ -457,14 +452,14 @@ static void splitlist(ScanFillContext *sf_ctx, } } -static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) +static uint scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) { ScanFillVertLink *scdata; ScanFillVertLink *sc = NULL, *sc1; ScanFillVert *eve, *v1, *v2, *v3; ScanFillEdge *eed, *eed_next, *ed1, *ed2, *ed3; - unsigned int a, b, verts, maxface, totface; - const unsigned short nr = pf->nr; + uint a, b, verts, maxface, totface; + const ushort nr = pf->nr; bool twoconnected = false; /* PRINTS */ @@ -810,7 +805,7 @@ void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, MemArena *arena) BLI_listbase_clear(&sf_ctx->fillfacebase); } -unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) +uint BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) { /* * - fill works with its own lists, so create that first (no faces!) @@ -825,8 +820,8 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const ScanFillEdge *eed, *eed_next; PolyFill *pflist, *pf; float *min_xy_p, *max_xy_p; - unsigned int totfaces = 0; /* total faces added */ - unsigned short a, c, poly = 0; + uint totfaces = 0; /* total faces added */ + ushort a, c, poly = 0; bool ok; float mat_2d[3][3]; @@ -895,7 +890,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const /* STEP 1: COUNT POLYS */ if (sf_ctx->poly_nr != SF_POLY_UNSET) { - poly = (unsigned short)(sf_ctx->poly_nr + 1); + poly = (ushort)(sf_ctx->poly_nr + 1); sf_ctx->poly_nr = SF_POLY_UNSET; } @@ -905,7 +900,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const /* get first vertex with no poly number */ if (eve->poly_nr == SF_POLY_UNSET) { - unsigned int toggle = 0; + uint toggle = 0; /* now a sort of select connected */ ok = true; eve->poly_nr = poly; @@ -962,7 +957,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const /* STEP 2: remove loose edges and strings of edges */ if (flag & BLI_SCANFILL_CALC_LOOSE) { - unsigned int toggle = 0; + uint toggle = 0; for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { if (eed->v1->edge_count++ > 250) { break; @@ -1069,7 +1064,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */ if ((flag & BLI_SCANFILL_CALC_HOLES) && (poly > 1)) { - unsigned short *polycache, *pc; + ushort *polycache, *pc; /* so, sort first */ qsort(pflist, (size_t)poly, sizeof(PolyFill), vergpoly); @@ -1086,7 +1081,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const polycache = pc = MEM_callocN(sizeof(*polycache) * (size_t)poly, "polycache"); pf = pflist; for (a = 0; a < poly; a++, pf++) { - for (c = (unsigned short)(a + 1); c < poly; c++) { + for (c = (ushort)(a + 1); c < poly; c++) { /* if 'a' inside 'c': join (bbox too) * Careful: 'a' can also be inside another poly. @@ -1142,7 +1137,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const return totfaces; } -unsigned int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) +uint BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) { return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); } diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c index 1d2225a5b56..6bf3c4719f6 100644 --- a/source/blender/blenlib/intern/scanfill_utils.c +++ b/source/blender/blenlib/intern/scanfill_utils.c @@ -41,14 +41,14 @@ typedef struct ScanFillIsect { #define EFLAG_SET(eed, val) \ { \ CHECK_TYPE(eed, ScanFillEdge *); \ - (eed)->user_flag = (eed)->user_flag | (unsigned int)val; \ + (eed)->user_flag = (eed)->user_flag | (uint)val; \ } \ (void)0 #if 0 # define EFLAG_CLEAR(eed, val) \ { \ CHECK_TYPE(eed, ScanFillEdge *); \ - (eed)->user_flag = (eed)->user_flag & ~(unsigned int)val; \ + (eed)->user_flag = (eed)->user_flag & ~(uint)val; \ } \ (void)0 #endif @@ -56,14 +56,14 @@ typedef struct ScanFillIsect { #define VFLAG_SET(eve, val) \ { \ CHECK_TYPE(eve, ScanFillVert *); \ - (eve)->user_flag = (eve)->user_flag | (unsigned int)val; \ + (eve)->user_flag = (eve)->user_flag | (uint)val; \ } \ (void)0 #if 0 # define VFLAG_CLEAR(eve, val) \ { \ CHECK_TYPE(eve, ScanFillVert *); \ - (eve)->user_flags = (eve)->user_flag & ~(unsigned int)val; \ + (eve)->user_flags = (eve)->user_flag & ~(uint)val; \ } \ (void)0 #endif @@ -72,7 +72,7 @@ typedef struct ScanFillIsect { void BLI_scanfill_obj_dump(ScanFillContext *sf_ctx) { FILE *f = fopen("test.obj", "w"); - unsigned int i = 1; + uint i = 1; ScanFillVert *eve; ScanFillEdge *eed; @@ -130,7 +130,7 @@ static int edge_isect_ls_sort_cb(void *thunk, const void *def_a_ptr, const void } static ScanFillEdge *edge_step(PolyInfo *poly_info, - const unsigned short poly_nr, + const ushort poly_nr, ScanFillVert *v_prev, ScanFillVert *v_curr, ScanFillEdge *e_curr) @@ -158,7 +158,7 @@ static ScanFillEdge *edge_step(PolyInfo *poly_info, static bool scanfill_preprocess_self_isect(ScanFillContext *sf_ctx, PolyInfo *poly_info, - const unsigned short poly_nr, + const ushort poly_nr, ListBase *filledgebase) { PolyInfo *pi = &poly_info[poly_nr]; @@ -359,8 +359,8 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, ListBase *remvertbase, ListBase *remedgebase) { - const unsigned int poly_num = (unsigned int)sf_ctx->poly_nr + 1; - unsigned int eed_index = 0; + const uint poly_num = (uint)sf_ctx->poly_nr + 1; + uint eed_index = 0; int totvert_new = 0; bool changed = false; @@ -378,7 +378,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, poly_info->edge_last = sf_ctx->filledgebase.last; } else { - unsigned short poly_nr; + ushort poly_nr; ScanFillEdge *eed; poly_nr = 0; @@ -407,7 +407,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx, /* self-intersect each polygon */ { - unsigned short poly_nr; + ushort poly_nr; for (poly_nr = 0; poly_nr < poly_num; poly_nr++) { changed |= scanfill_preprocess_self_isect(sf_ctx, poly_info, poly_nr, remedgebase); } diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 2d76f662611..8263f8ff34e 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -329,8 +329,7 @@ void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr /** \name Debugging & Introspection * \{ */ -/* NOTE(campbell): this was called _print_smhash in knifetool.c - * it may not be intended for general use. */ +/* NOTE(@campbellbarton): useful for debugging but may not be intended for general use. */ #if 0 void BLI_smallhash_print(SmallHash *sh) { diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index ff34cfe41cb..1a83e8cd86c 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -141,7 +141,7 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst) BLI_stack_discard(stack); } -void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) +void BLI_stack_pop_n(BLI_Stack *stack, void *dst, uint n) { BLI_assert(n <= BLI_stack_count(stack)); @@ -151,7 +151,7 @@ void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) } } -void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, unsigned int n) +void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, uint n) { BLI_assert(n <= BLI_stack_count(stack)); diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 4fa5ca0c088..c04fc41ab4d 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -259,7 +259,7 @@ eFileAttributes BLI_file_attributes(const char *path) #ifndef __APPLE__ bool BLI_file_alias_target(const char *filepath, /* This parameter can only be `const` on Linux since - * redirections are not supported there. + * redirection is not supported there. * NOLINTNEXTLINE: readability-non-const-parameter. */ char r_targetpath[/*FILE_MAXDIR*/]) { diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 976b9a5cd02..755d2dbd55d 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -314,7 +314,7 @@ size_t BLI_str_unescape_ex(char *__restrict dst, break; } char c = *src; - if (UNLIKELY(c == '\\') && (str_unescape_pair(*(src + 1), &c))) { + if (UNLIKELY(c == '\\') && str_unescape_pair(*(src + 1), &c)) { src++; } dst[len++] = c; @@ -329,7 +329,7 @@ size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t len = 0; for (const char *src_end = src + src_maxncpy; (src < src_end) && *src; src++) { char c = *src; - if (UNLIKELY(c == '\\') && (str_unescape_pair(*(src + 1), &c))) { + if (UNLIKELY(c == '\\') && str_unescape_pair(*(src + 1), &c)) { src++; } dst[len++] = c; @@ -1121,7 +1121,7 @@ size_t BLI_str_format_int_grouped(char dst[16], int num) size_t BLI_str_format_uint64_grouped(char dst[16], uint64_t num) { - /* NOTE: Buffer to hold maximum unsigned int64, which is 1.8e+19. but + /* NOTE: Buffer to hold maximum `uint64`, which is 1.8e+19. but * we also need space for commas and null-terminator. */ char src[27]; int num_len = sprintf(src, "%" PRIu64 "", num); @@ -1176,4 +1176,34 @@ void BLI_str_format_decimal_unit(char dst[7], int number_to_format) BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]); } +void BLI_str_format_integer_unit(char dst[5], const int number_to_format) +{ + float number_to_format_converted = number_to_format; + int order = 0; + const float base = 1000; + const char *units[] = {"", "K", "M", "B"}; + const int units_num = ARRAY_SIZE(units); + + while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) { + number_to_format_converted /= base; + order++; + } + + const bool add_dot = (abs(number_to_format) > 99999) && fabsf(number_to_format_converted) > 99; + + if (add_dot) { + number_to_format_converted /= 100; + order++; + } + + const size_t dst_len = 5; + BLI_snprintf(dst, + dst_len, + "%s%s%d%s", + number_to_format < 0 ? "-" : "", + add_dot ? "." : "", + (int)floorf(fabsf(number_to_format_converted)), + units[order]); +} + /** \} */ diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c index 7a23b4bb4ad..2405b134428 100644 --- a/source/blender/blenlib/intern/string_cursor_utf8.c +++ b/source/blender/blenlib/intern/string_cursor_utf8.c @@ -96,27 +96,35 @@ static eStrCursorDelimType cursor_delim_type_utf8(const char *ch_utf8, return cursor_delim_type_unicode(uch); } +/* Keep in sync with BLI_str_cursor_step_next_utf32. */ bool BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos) { + if ((*pos) >= (int)maxlen) { + return false; + } const char *str_end = str + (maxlen + 1); const char *str_pos = str + (*pos); - const char *str_next = BLI_str_find_next_char_utf8(str_pos, str_end); - if (str_next != str_end) { - (*pos) += (str_next - str_pos); - if ((*pos) > (int)maxlen) { - (*pos) = (int)maxlen; - } - return true; + const char *str_next = str_pos; + do { + str_next = BLI_str_find_next_char_utf8(str_next, str_end); + } while (str_next < str_end && str_next[0] != 0 && BLI_str_utf8_char_width(str_next) < 1); + (*pos) += (str_next - str_pos); + if ((*pos) > (int)maxlen) { + (*pos) = (int)maxlen; } - return false; + return true; } -bool BLI_str_cursor_step_prev_utf8(const char *str, size_t UNUSED(maxlen), int *pos) +/* Keep in sync with BLI_str_cursor_step_prev_utf32. */ +bool BLI_str_cursor_step_prev_utf8(const char *str, size_t maxlen, int *pos) { - if ((*pos) > 0) { + if ((*pos) > 0 && (*pos) <= maxlen) { const char *str_pos = str + (*pos); - const char *str_prev = BLI_str_find_prev_char_utf8(str_pos, str); + const char *str_prev = str_pos; + do { + str_prev = BLI_str_find_prev_char_utf8(str_prev, str); + } while (str_prev > str && BLI_str_utf8_char_width(str_prev) == 0); (*pos) -= (str_pos - str_prev); return true; } @@ -202,26 +210,29 @@ void BLI_str_cursor_step_utf8(const char *str, } } -/* UTF32 version of BLI_str_cursor_step_utf8 (keep in sync!) - * less complex since it doesn't need to do multi-byte stepping. - */ - -/* helper funcs so we can match BLI_str_cursor_step_utf8 */ -static bool cursor_step_next_utf32(const char32_t *UNUSED(str), size_t maxlen, int *pos) +/* Keep in sync with BLI_str_cursor_step_next_utf8. */ +bool BLI_str_cursor_step_next_utf32(const char32_t *str, size_t maxlen, int *pos) { if ((*pos) >= (int)maxlen) { return false; } - (*pos)++; + do { + (*pos)++; + } while (*pos < (int)maxlen && str[*pos] != 0 && BLI_wcwidth(str[*pos]) == 0); + return true; } -static bool cursor_step_prev_utf32(const char32_t *UNUSED(str), size_t UNUSED(maxlen), int *pos) +/* Keep in sync with BLI_str_cursor_step_prev_utf8. */ +bool BLI_str_cursor_step_prev_utf32(const char32_t *str, size_t UNUSED(maxlen), int *pos) { if ((*pos) <= 0) { return false; } - (*pos)--; + do { + (*pos)--; + } while (*pos > 0 && BLI_wcwidth(str[*pos]) == 0); + return true; } @@ -236,7 +247,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str, if (direction == STRCUR_DIR_NEXT) { if (use_init_step) { - cursor_step_next_utf32(str, maxlen, pos); + BLI_str_cursor_step_next_utf32(str, maxlen, pos); } else { BLI_assert(jump == STRCUR_JUMP_DELIM); @@ -250,7 +261,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str, * look at function cursor_delim_type_unicode() for complete * list of special character, ctr -> */ while ((*pos) < maxlen) { - if (cursor_step_next_utf32(str, maxlen, pos)) { + if (BLI_str_cursor_step_next_utf32(str, maxlen, pos)) { if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) { break; @@ -264,7 +275,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str, } else if (direction == STRCUR_DIR_PREV) { if (use_init_step) { - cursor_step_prev_utf32(str, maxlen, pos); + BLI_str_cursor_step_prev_utf32(str, maxlen, pos); } else { BLI_assert(jump == STRCUR_JUMP_DELIM); @@ -279,7 +290,7 @@ void BLI_str_cursor_step_utf32(const char32_t *str, * list of special character, ctr -> */ while ((*pos) > 0) { const int pos_prev = *pos; - if (cursor_step_prev_utf32(str, maxlen, pos)) { + if (BLI_str_cursor_step_prev_utf32(str, maxlen, pos)) { if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type_unicode((uint)str[*pos]))) { /* left only: compensate for index/change in direction */ diff --git a/source/blender/blenlib/intern/string_search.cc b/source/blender/blenlib/intern/string_search.cc index 14d85b99739..f87304863c9 100644 --- a/source/blender/blenlib/intern/string_search.cc +++ b/source/blender/blenlib/intern/string_search.cc @@ -11,14 +11,14 @@ #include "BLI_timeit.hh" /* Right arrow, keep in sync with #UI_MENU_ARROW_SEP in `UI_interface.h`. */ -#define UI_MENU_ARROW_SEP "\xe2\x96\xb6" -#define UI_MENU_ARROW_SEP_UNICODE 0x25b6 +#define UI_MENU_ARROW_SEP "\xe2\x96\xb8" +#define UI_MENU_ARROW_SEP_UNICODE 0x25b8 namespace blender::string_search { static int64_t count_utf8_code_points(StringRef str) { - return static_cast<int64_t>(BLI_strnlen_utf8(str.data(), static_cast<size_t>(str.size()))); + return int64_t(BLI_strnlen_utf8(str.data(), size_t(str.size()))); } int damerau_levenshtein_distance(StringRef a, StringRef b) @@ -205,7 +205,7 @@ static bool match_word_initials(StringRef query, StringRef word = words[word_index]; /* Try to match the current character with the current word. */ - if (static_cast<int>(char_index) < word.size()) { + if (int(char_index) < word.size()) { const uint32_t char_unicode = BLI_str_utf8_as_unicode_step( word.data(), word.size(), &char_index); if (query_unicode == char_unicode) { @@ -345,7 +345,7 @@ void extract_normalized_words(StringRef str, LinearAllocator<> &allocator, Vector<StringRef, 64> &r_words) { - const uint32_t unicode_space = (uint32_t)' '; + const uint32_t unicode_space = uint32_t(' '); const uint32_t unicode_right_triangle = UI_MENU_ARROW_SEP_UNICODE; BLI_assert(unicode_space == BLI_str_utf8_as_unicode(" ")); @@ -358,7 +358,7 @@ void extract_normalized_words(StringRef str, /* Make a copy of the string so that we can edit it. */ StringRef str_copy = allocator.copy_string(str); char *mutable_copy = const_cast<char *>(str_copy.data()); - const size_t str_size_in_bytes = static_cast<size_t>(str.size()); + const size_t str_size_in_bytes = size_t(str.size()); BLI_str_tolower_ascii(mutable_copy, str_size_in_bytes); /* Iterate over all unicode code points to split individual words. */ @@ -371,8 +371,7 @@ void extract_normalized_words(StringRef str, size -= offset; if (is_separator(unicode)) { if (is_in_word) { - r_words.append( - str_copy.substr(static_cast<int>(word_start), static_cast<int>(offset - word_start))); + r_words.append(str_copy.substr(int(word_start), int(offset - word_start))); is_in_word = false; } } @@ -386,7 +385,7 @@ void extract_normalized_words(StringRef str, } /* If the last word is not followed by a separator, it has to be handled separately. */ if (is_in_word) { - r_words.append(str_copy.drop_prefix(static_cast<int>(word_start))); + r_words.append(str_copy.drop_prefix(int(word_start))); } } @@ -419,7 +418,7 @@ void BLI_string_search_add(StringSearch *search, StringRef str_ref{str}; string_search::extract_normalized_words(str_ref, search->allocator, words); search->items.append({search->allocator.construct_array_copy(words.as_span()), - (int)str_ref.size(), + int(str_ref.size()), user_data, weight}); } @@ -458,7 +457,7 @@ int BLI_string_search_query(StringSearch *search, const char *query, void ***r_d if (score == found_scores[0] && !query_str.is_empty()) { /* Sort items with best score by length. Shorter items are more likely the ones you are * looking for. This also ensures that exact matches will be at the top, even if the query is - * a substring of another item. */ + * a sub-string of another item. */ std::sort(indices.begin(), indices.end(), [&](int a, int b) { return search->items[a].length < search->items[b].length; }); @@ -472,7 +471,7 @@ int BLI_string_search_query(StringSearch *search, const char *query, void ***r_d } void **sorted_data = static_cast<void **>( - MEM_malloc_arrayN(static_cast<size_t>(sorted_result_indices.size()), sizeof(void *), AT)); + MEM_malloc_arrayN(size_t(sorted_result_indices.size()), sizeof(void *), AT)); for (const int i : sorted_result_indices.index_range()) { const int result_index = sorted_result_indices[i]; SearchItem &item = search->items[result_index]; diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 0cbf62cce03..26facda7abf 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -55,11 +55,11 @@ ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length) * length is in bytes, since without knowing whether the string is valid * it's hard to know how many characters there are! */ - const unsigned char *p, *perr, *pend = (const unsigned char *)str + length; - unsigned char c; + const uchar *p, *perr, *pend = (const uchar *)str + length; + uchar c; int ab; - for (p = (const unsigned char *)str; p < pend; p++, length--) { + for (p = (const uchar *)str; p < pend; p++, length--) { c = *p; perr = p; /* Erroneous char is always the first of an invalid utf8 sequence... */ if (ELEM(c, 0xfe, 0xff, 0x00)) { @@ -403,7 +403,7 @@ int BLI_str_utf8_char_width_safe(const char *p) /* copied from glib's gutf8.c, added 'Err' arg */ -/* NOTE(campbell): glib uses uint for unicode, best we do the same, +/* NOTE(@campbellbarton): glib uses uint for unicode, best we do the same, * though we don't typedef it. */ #define UTF8_COMPUTE(Char, Mask, Len, Err) \ @@ -454,7 +454,7 @@ int BLI_str_utf8_size(const char *p) /* NOTE: uses glib functions but not from GLIB. */ int mask = 0, len; - const unsigned char c = (unsigned char)*p; + const uchar c = (uchar)*p; UTF8_COMPUTE(c, mask, len, -1); @@ -466,7 +466,7 @@ int BLI_str_utf8_size(const char *p) int BLI_str_utf8_size_safe(const char *p) { int mask = 0, len; - const unsigned char c = (unsigned char)*p; + const uchar c = (uchar)*p; UTF8_COMPUTE(c, mask, len, 1); @@ -482,7 +482,7 @@ uint BLI_str_utf8_as_unicode(const char *p) int i, len; uint mask = 0; uint result; - const unsigned char c = (unsigned char)*p; + const uchar c = (uchar)*p; UTF8_COMPUTE(c, mask, len, -1); if (UNLIKELY(len == -1)) { @@ -500,7 +500,7 @@ uint BLI_str_utf8_as_unicode_step_or_error(const char *__restrict p, int i, len; uint mask = 0; uint result; - const unsigned char c = (unsigned char)*(p += *index); + const uchar c = (uchar) * (p += *index); BLI_assert(*index < p_len); BLI_assert(c != '\0'); @@ -692,25 +692,25 @@ const char *BLI_str_find_next_char_utf8(const char *p, const char *str_end) size_t BLI_str_partition_utf8(const char *str, const uint delim[], - const char **sep, - const char **suf) + const char **r_sep, + const char **r_suf) { - return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, false); + return BLI_str_partition_ex_utf8(str, NULL, delim, r_sep, r_suf, false); } size_t BLI_str_rpartition_utf8(const char *str, const uint delim[], - const char **sep, - const char **suf) + const char **r_sep, + const char **r_suf) { - return BLI_str_partition_ex_utf8(str, NULL, delim, sep, suf, true); + return BLI_str_partition_ex_utf8(str, NULL, delim, r_sep, r_suf, true); } size_t BLI_str_partition_ex_utf8(const char *str, const char *end, const uint delim[], - const char **sep, - const char **suf, + const char **r_sep, + const char **r_suf, const bool from_right) { const size_t str_len = end ? (size_t)(end - str) : strlen(str); @@ -721,36 +721,32 @@ size_t BLI_str_partition_ex_utf8(const char *str, /* Note that here, we assume end points to a valid utf8 char! */ BLI_assert((end >= str) && (BLI_str_utf8_as_unicode(end) != BLI_UTF8_ERR)); - *suf = (char *)(str + str_len); - - size_t index; - for (*sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(end, str) : str), index = 0; - from_right ? (*sep > str) : ((*sep < end) && (**sep != '\0')); - *sep = (char *)(from_right ? (str != *sep ? BLI_str_find_prev_char_utf8(*sep, str) : NULL) : - str + index)) { + char *suf = (char *)(str + str_len); + size_t index = 0; + for (char *sep = (char *)(from_right ? BLI_str_find_prev_char_utf8(end, str) : str); + from_right ? (sep > str) : ((sep < end) && (*sep != '\0')); + sep = (char *)(from_right ? (str != sep ? BLI_str_find_prev_char_utf8(sep, str) : NULL) : + str + index)) { size_t index_ofs = 0; - const uint c = BLI_str_utf8_as_unicode_step_or_error(*sep, (size_t)(end - *sep), &index_ofs); - index += index_ofs; - - if (c == BLI_UTF8_ERR) { - *suf = *sep = NULL; + const uint c = BLI_str_utf8_as_unicode_step_or_error(sep, (size_t)(end - sep), &index_ofs); + if (UNLIKELY(c == BLI_UTF8_ERR)) { break; } + index += index_ofs; for (const uint *d = delim; *d != '\0'; d++) { if (*d == c) { - /* *suf is already correct in case from_right is true. */ - if (!from_right) { - *suf = (char *)(str + index); - } - return (size_t)(*sep - str); + /* `suf` is already correct in case from_right is true. */ + *r_sep = sep; + *r_suf = from_right ? suf : (char *)(str + index); + return (size_t)(sep - str); } } - *suf = *sep; /* Useful in 'from_right' case! */ + suf = sep; /* Useful in 'from_right' case! */ } - *suf = *sep = NULL; + *r_suf = *r_sep = NULL; return str_len; } @@ -790,9 +786,9 @@ int BLI_str_utf8_offset_to_column(const char *str, int offset) int BLI_str_utf8_offset_from_column(const char *str, int column) { - int offset = 0, pos = 0, col; + int offset = 0, pos = 0; while (*(str + offset) && pos < column) { - col = BLI_str_utf8_char_width_safe(str + offset); + const int col = BLI_str_utf8_char_width_safe(str + offset); if (pos + col > column) { break; } diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 35e26e0cb33..40a8fa24570 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -21,7 +21,9 @@ # include "BLI_winstuff.h" #else -# include <execinfo.h> +# if defined(HAVE_EXECINFO_H) +# include <execinfo.h> +# endif # include <unistd.h> #endif @@ -32,7 +34,7 @@ int BLI_cpu_support_sse2(void) return 1; #elif defined(__GNUC__) && defined(i386) /* for GCC x86 we check cpuid */ - unsigned int d; + uint d; __asm__( "pushl %%ebx\n\t" "cpuid\n\t" @@ -42,7 +44,7 @@ int BLI_cpu_support_sse2(void) return (d & 0x04000000) != 0; #elif (defined(_MSC_VER) && defined(_M_IX86)) /* also check cpuid for MSVC x86 */ - unsigned int d; + uint d; __asm { xor eax, eax inc eax @@ -61,9 +63,9 @@ int BLI_cpu_support_sse2(void) #if !defined(_MSC_VER) void BLI_system_backtrace(FILE *fp) { - /* ------------- */ - /* Linux / Apple */ -# if defined(__linux__) || defined(__APPLE__) + /* ----------------------- */ + /* If system as execinfo.h */ +# if defined(HAVE_EXECINFO_H) # define SIZE 100 void *buffer[SIZE]; @@ -152,12 +154,12 @@ void BLI_hostname_get(char *buffer, size_t bufsize) if (gethostname(buffer, bufsize - 1) < 0) { BLI_strncpy(buffer, "-unknown-", bufsize); } - /* When gethostname() truncates, it doesn't guarantee the trailing \0. */ + /* When `gethostname()` truncates, it doesn't guarantee the trailing `\0`. */ buffer[bufsize - 1] = '\0'; #else DWORD bufsize_inout = bufsize; if (!GetComputerName(buffer, &bufsize_inout)) { - strncpy(buffer, "-unknown-", bufsize); + BLI_strncpy(buffer, "-unknown-", bufsize); } #endif } diff --git a/source/blender/blenlib/intern/task_graph.cc b/source/blender/blenlib/intern/task_graph.cc index 6c1cc818d75..5bc84bf7573 100644 --- a/source/blender/blenlib/intern/task_graph.cc +++ b/source/blender/blenlib/intern/task_graph.cc @@ -75,7 +75,7 @@ struct TaskNode { } #ifdef WITH_TBB - tbb::flow::continue_msg run(const tbb::flow::continue_msg UNUSED(input)) + tbb::flow::continue_msg run(const tbb::flow::continue_msg /*input*/) { run_func(task_data); return tbb::flow::continue_msg(); diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index d5afbb2b117..99e966de975 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -26,10 +26,10 @@ * \{ */ /* Allows to avoid using malloc for userdata_chunk in tasks, when small enough. */ -#define MALLOCA(_size) ((_size) <= 8192) ? alloca((_size)) : MEM_mallocN((_size), __func__) +#define MALLOCA(_size) ((_size) <= 8192) ? alloca(_size) : MEM_mallocN((_size), __func__) #define MALLOCA_FREE(_mem, _size) \ if (((_mem) != NULL) && ((_size) > 8192)) { \ - MEM_freeN((_mem)); \ + MEM_freeN(_mem); \ } \ ((void)0) diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index a29dbe95ba9..c335d04413c 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -84,11 +84,11 @@ class Task { free_taskdata(other.free_taskdata), freedata(other.freedata) { - ((Task &)other).pool = NULL; - ((Task &)other).run = NULL; - ((Task &)other).taskdata = NULL; + ((Task &)other).pool = nullptr; + ((Task &)other).run = nullptr; + ((Task &)other).taskdata = nullptr; ((Task &)other).free_taskdata = false; - ((Task &)other).freedata = NULL; + ((Task &)other).freedata = nullptr; } #else Task(const Task &other) = delete; diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index 7e405529f03..20551aba93b 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -12,6 +12,7 @@ #include "DNA_listBase.h" +#include "BLI_lazy_threading.hh" #include "BLI_task.h" #include "BLI_threads.h" @@ -104,6 +105,8 @@ void BLI_task_parallel_range(const int start, const size_t grainsize = MAX2(settings->min_iter_per_thread, 1); const tbb::blocked_range<int> range(start, stop, grainsize); + blender::lazy_threading::send_hint(); + if (settings->func_reduce) { parallel_reduce(range, task); if (settings->userdata_chunk) { @@ -129,7 +132,7 @@ void BLI_task_parallel_range(const int start, } } -int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls)) +int BLI_task_parallel_thread_id(const TaskParallelTLS * /*tls*/) { #ifdef WITH_TBB /* Get a unique thread ID for texture nodes. In the future we should get rid diff --git a/source/blender/blenlib/intern/threads.cc b/source/blender/blenlib/intern/threads.cc index 37fccf6f4fe..f99a27c2475 100644 --- a/source/blender/blenlib/intern/threads.cc +++ b/source/blender/blenlib/intern/threads.cc @@ -37,17 +37,6 @@ #include "atomic_ops.h" -#if defined(__APPLE__) && defined(_OPENMP) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) && \ - !defined(__clang__) -# define USE_APPLE_OMP_FIX -#endif - -#ifdef USE_APPLE_OMP_FIX -/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */ -extern pthread_key_t gomp_tls_key; -static void *thread_tls_data; -#endif - /** * Basic Thread Control API * ======================== @@ -108,7 +97,7 @@ static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t mainid; -static unsigned int thread_levels = 0; /* threads can be invoked inside threads */ +static uint thread_levels = 0; /* threads can be invoked inside threads */ static int threads_override_num = 0; /* just a max for security reasons */ @@ -153,15 +142,7 @@ void BLI_threadpool_init(ListBase *threadbase, void *(*do_thread)(void *), int t } } - unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); - if (level == 0) { -#ifdef USE_APPLE_OMP_FIX - /* Workaround for Apple gcc 4.2.1 OMP vs background thread bug, - * we copy GOMP thread local storage pointer to setting it again - * inside the thread that we start. */ - thread_tls_data = pthread_getspecific(gomp_tls_key); -#endif - } + atomic_fetch_and_add_u(&thread_levels, 1); } int BLI_available_threads(ListBase *threadbase) @@ -194,13 +175,6 @@ int BLI_threadpool_available_thread_index(ListBase *threadbase) static void *tslot_thread_start(void *tslot_p) { ThreadSlot *tslot = (ThreadSlot *)tslot_p; - -#ifdef USE_APPLE_OMP_FIX - /* Workaround for Apple gcc 4.2.1 OMP vs background thread bug, - * set GOMP thread local storage pointer which was copied beforehand */ - pthread_setspecific(gomp_tls_key, thread_tls_data); -#endif - return tslot->do_thread(tslot->callerdata); } @@ -293,7 +267,7 @@ int BLI_system_thread_count() #ifdef WIN32 SYSTEM_INFO info; GetSystemInfo(&info); - t = (int)info.dwNumberOfProcessors; + t = int(info.dwNumberOfProcessors); #else # ifdef __APPLE__ int mib[2]; @@ -304,7 +278,7 @@ int BLI_system_thread_count() len = sizeof(t); sysctl(mib, 2, &t, &len, nullptr, 0); # else - t = (int)sysconf(_SC_NPROCESSORS_ONLN); + t = int(sysconf(_SC_NPROCESSORS_ONLN)); # endif #endif } @@ -524,7 +498,7 @@ void BLI_rw_mutex_free(ThreadRWMutex *mutex) struct TicketMutex { pthread_cond_t cond; pthread_mutex_t mutex; - unsigned int queue_head, queue_tail; + uint queue_head, queue_tail; }; TicketMutex *BLI_ticket_mutex_alloc() @@ -547,7 +521,7 @@ void BLI_ticket_mutex_free(TicketMutex *ticket) void BLI_ticket_mutex_lock(TicketMutex *ticket) { - unsigned int queue_me; + uint queue_me; pthread_mutex_lock(&ticket->mutex); queue_me = ticket->queue_tail++; diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c index fc78b0ad98d..ecaa469984d 100644 --- a/source/blender/blenlib/intern/timecode.c +++ b/source/blender/blenlib/intern/timecode.c @@ -176,7 +176,7 @@ size_t BLI_timecode_string_from_time_simple(char *str, const int hr = ((int)time_seconds) / (60 * 60); const int min = (((int)time_seconds) / 60) % 60; const int sec = ((int)time_seconds) % 60; - const int hun = ((int)(fmod(time_seconds, 1.0) * 100)); + const int hun = (int)(fmod(time_seconds, 1.0) * 100); if (hr) { rlen = BLI_snprintf_rlen(str, maxncpy, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun); diff --git a/source/blender/blenlib/intern/uuid.cc b/source/blender/blenlib/intern/uuid.cc index 890a721a9d1..023dd1ec409 100644 --- a/source/blender/blenlib/intern/uuid.cc +++ b/source/blender/blenlib/intern/uuid.cc @@ -136,10 +136,10 @@ bUUID::bUUID(const std::initializer_list<uint32_t> field_values) const auto *field_iter = field_values.begin(); this->time_low = *field_iter++; - this->time_mid = static_cast<uint16_t>(*field_iter++); - this->time_hi_and_version = static_cast<uint16_t>(*field_iter++); - this->clock_seq_hi_and_reserved = static_cast<uint8_t>(*field_iter++); - this->clock_seq_low = static_cast<uint8_t>(*field_iter++); + this->time_mid = uint16_t(*field_iter++); + this->time_hi_and_version = uint16_t(*field_iter++); + this->clock_seq_hi_and_reserved = uint8_t(*field_iter++); + this->clock_seq_low = uint8_t(*field_iter++); std::copy(field_iter, field_values.end(), this->node); } diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index e90a0ee02db..7e2c5e8f1dd 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -63,23 +63,17 @@ bool BLI_windows_register_blend_extension(const bool background) char buffer[256]; char BlPath[MAX_PATH]; - char InstallDir[FILE_MAXDIR]; - char SysDir[FILE_MAXDIR]; - const char *ThumbHandlerDLL; - char RegCmd[MAX_PATH * 2]; char MBox[256]; - char *blender_app; -# ifndef _WIN64 - BOOL IsWOW64; -# endif printf("Registering file extension..."); GetModuleFileName(0, BlPath, MAX_PATH); /* Replace the actual app name with the wrapper. */ - blender_app = strstr(BlPath, "blender.exe"); - if (blender_app != NULL) { - strcpy(blender_app, "blender-launcher.exe"); + { + char *blender_app = strstr(BlPath, "blender.exe"); + if (blender_app != NULL) { + strcpy(blender_app, "blender-launcher.exe"); + } } /* root is HKLM by default */ @@ -157,12 +151,17 @@ bool BLI_windows_register_blend_extension(const bool background) } # ifdef WITH_BLENDER_THUMBNAILER - BLI_windows_get_executable_dir(InstallDir); - GetSystemDirectory(SysDir, FILE_MAXDIR); - ThumbHandlerDLL = "BlendThumb.dll"; - snprintf( - RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL); - system(RegCmd); + { + char RegCmd[MAX_PATH * 2]; + char InstallDir[FILE_MAXDIR]; + char SysDir[FILE_MAXDIR]; + BLI_windows_get_executable_dir(InstallDir); + GetSystemDirectory(SysDir, FILE_MAXDIR); + const char *ThumbHandlerDLL = "BlendThumb.dll"; + snprintf( + RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL); + system(RegCmd); + } # endif RegCloseKey(root); diff --git a/source/blender/blenlib/tests/BLI_array_store_test.cc b/source/blender/blenlib/tests/BLI_array_store_test.cc index 20e2a4d88f8..c52d439308f 100644 --- a/source/blender/blenlib/tests/BLI_array_store_test.cc +++ b/source/blender/blenlib/tests/BLI_array_store_test.cc @@ -168,7 +168,7 @@ static void testbuffer_list_state_from_data__stride_expand(ListBase *lb, #define testbuffer_list_state_from_string_array(lb, data_array) \ { \ - unsigned int i_ = 0; \ + uint i_ = 0; \ const char *data; \ while ((data = data_array[i_++])) { \ testbuffer_list_state_from_data(lb, data, strlen(data)); \ @@ -181,7 +181,7 @@ static void testbuffer_list_state_from_data__stride_expand(ListBase *lb, #define TESTBUFFER_STRINGS_CREATE(lb, ...) \ { \ BLI_listbase_clear(lb); \ - const char *data_array[] = {__VA_ARGS__ NULL}; \ + const char *data_array[] = {__VA_ARGS__ nullptr}; \ testbuffer_list_state_from_string_array((lb), data_array); \ } \ ((void)0) @@ -224,7 +224,7 @@ static bool testbuffer_list_validate(const ListBase *lb) return true; } -static void testbuffer_list_data_randomize(ListBase *lb, unsigned int random_seed) +static void testbuffer_list_data_randomize(ListBase *lb, uint random_seed) { for (TestBuffer *tb = (TestBuffer *)lb->first; tb; tb = tb->next) { BLI_array_randomize((void *)tb->data, 1, tb->data_len, random_seed++); @@ -301,7 +301,7 @@ TEST(array_store, Nop) TEST(array_store, NopState) { BArrayStore *bs = BLI_array_store_create(1, 32); - const unsigned char data[] = "test"; + const uchar data[] = "test"; BArrayState *state = BLI_array_store_state_add(bs, data, sizeof(data) - 1, nullptr); EXPECT_EQ(BLI_array_store_state_size_get(state), sizeof(data) - 1); BLI_array_store_state_remove(bs, state); @@ -556,18 +556,15 @@ TEST(array_store, TextSentencesRandom_Stride128_Chunk6) /* -------------------------------------------------------------------- */ /* Random Data Tests */ -static unsigned int rand_range_i(RNG *rng, - unsigned int min_i, - unsigned int max_i, - unsigned int step) +static uint rand_range_i(RNG *rng, uint min_i, uint max_i, uint step) { if (min_i == max_i) { return min_i; } BLI_assert(min_i <= max_i); BLI_assert(((min_i % step) == 0) && ((max_i % step) == 0)); - unsigned int range = (max_i - min_i); - unsigned int value = BLI_rng_get_uint(rng) % range; + uint range = (max_i - min_i); + uint value = BLI_rng_get_uint(rng) % range; value = (value / step) * step; return min_i + value; } @@ -577,7 +574,7 @@ static void testbuffer_list_state_random_data(ListBase *lb, const size_t data_min_len, const size_t data_max_len, - const unsigned int mutate, + const uint mutate, RNG *rng) { size_t data_len = rand_range_i(rng, data_min_len, data_max_len + stride, stride); @@ -607,12 +604,12 @@ static void testbuffer_list_state_random_data(ListBase *lb, MUTATE_TOTAL, }; - switch ((BLI_rng_get_uint(rng) % MUTATE_TOTAL)) { + switch (BLI_rng_get_uint(rng) % MUTATE_TOTAL) { case MUTATE_NOP: { break; } case MUTATE_ADD: { - const unsigned int offset = rand_range_i(rng, 0, data_len, stride); + const uint offset = rand_range_i(rng, 0, data_len, stride); if (data_len < data_max_len) { data_len += stride; data = (char *)MEM_reallocN((void *)data, data_len); @@ -622,7 +619,7 @@ static void testbuffer_list_state_random_data(ListBase *lb, break; } case MUTATE_REMOVE: { - const unsigned int offset = rand_range_i(rng, 0, data_len, stride); + const uint offset = rand_range_i(rng, 0, data_len, stride); if (data_len > data_min_len) { memmove(&data[offset], &data[offset + stride], data_len - (offset + stride)); data_len -= stride; @@ -638,7 +635,7 @@ static void testbuffer_list_state_random_data(ListBase *lb, } case MUTATE_RANDOMIZE: { if (data_len > 0) { - const unsigned int offset = rand_range_i(rng, 0, data_len - stride, stride); + const uint offset = rand_range_i(rng, 0, data_len - stride, stride); BLI_rng_get_char_n(rng, &data[offset], stride); } break; @@ -795,10 +792,10 @@ TEST(array_store, TestChunk_Rand31_Stride11_Chunk21) /* Test From Files (disabled, keep for local tests.) */ -void *file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size) +static void *file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size) { FILE *fp = fopen(filepath, "rb"); - void *mem = NULL; + void *mem = nullptr; if (fp) { long int filelen_read; @@ -810,14 +807,14 @@ void *file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t *r_ fseek(fp, 0L, SEEK_SET); mem = MEM_mallocN(filelen + pad_bytes, __func__); - if (mem == NULL) { + if (mem == nullptr) { goto finally; } filelen_read = fread(mem, 1, filelen, fp); if ((filelen_read != filelen) || ferror(fp)) { MEM_freeN(mem); - mem = NULL; + mem = nullptr; goto finally; } diff --git a/source/blender/blenlib/tests/BLI_bit_vector_test.cc b/source/blender/blenlib/tests/BLI_bit_vector_test.cc new file mode 100644 index 00000000000..210f2be012d --- /dev/null +++ b/source/blender/blenlib/tests/BLI_bit_vector_test.cc @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "BLI_bit_vector.hh" +#include "BLI_exception_safety_test_utils.hh" +#include "BLI_strict_flags.h" + +#include "testing/testing.h" + +namespace blender::tests { + +TEST(bit_vector, DefaultConstructor) +{ + BitVector vec; + EXPECT_EQ(vec.size(), 0); +} + +TEST(bit_vector, CopyConstructorInline) +{ + BitVector<> vec({false, false, true, true, false}); + BitVector<> vec2 = vec; + + EXPECT_EQ(vec.size(), 5); + EXPECT_EQ(vec2.size(), 5); + + vec2[1].set(); + EXPECT_FALSE(vec[1]); + + EXPECT_FALSE(vec2[0]); + EXPECT_TRUE(vec2[1]); + EXPECT_TRUE(vec2[2]); + EXPECT_TRUE(vec2[3]); + EXPECT_FALSE(vec2[4]); +} + +TEST(bit_vector, CopyConstructorLarge) +{ + BitVector<> vec(500, false); + vec[1].set(); + + BitVector<> vec2 = vec; + + EXPECT_EQ(vec.size(), 500); + EXPECT_EQ(vec2.size(), 500); + + vec2[2].set(); + EXPECT_FALSE(vec[2]); + + EXPECT_FALSE(vec2[0]); + EXPECT_TRUE(vec2[1]); + EXPECT_TRUE(vec2[2]); +} + +TEST(bit_vector, MoveConstructorInline) +{ + BitVector<> vec({false, false, true, true, false}); + BitVector<> vec2 = std::move(vec); + + EXPECT_EQ(vec.size(), 0); + EXPECT_EQ(vec2.size(), 5); + + EXPECT_FALSE(vec2[0]); + EXPECT_FALSE(vec2[1]); + EXPECT_TRUE(vec2[2]); + EXPECT_TRUE(vec2[3]); + EXPECT_FALSE(vec2[4]); +} + +TEST(bit_vector, MoveConstructorLarge) +{ + BitVector<> vec(500, false); + vec[3].set(); + + BitVector<> vec2 = std::move(vec); + + EXPECT_EQ(vec.size(), 0); + EXPECT_EQ(vec2.size(), 500); + + EXPECT_FALSE(vec2[0]); + EXPECT_FALSE(vec2[1]); + EXPECT_FALSE(vec2[2]); + EXPECT_TRUE(vec2[3]); + EXPECT_FALSE(vec2[4]); +} + +TEST(bit_vector, SizeConstructor) +{ + { + BitVector<> vec(0); + EXPECT_EQ(vec.size(), 0); + } + { + BitVector<> vec(5); + EXPECT_EQ(vec.size(), 5); + for (BitRef bit : vec) { + EXPECT_FALSE(bit); + } + } + { + BitVector<> vec(123); + EXPECT_EQ(vec.size(), 123); + for (BitRef bit : vec) { + EXPECT_FALSE(bit); + } + } +} + +TEST(bit_vector, SizeFillConstructor) +{ + { + BitVector<> vec(5, false); + for (const int64_t i : IndexRange(5)) { + EXPECT_FALSE(vec[i]); + } + } + { + BitVector<> vec(123, true); + for (const int64_t i : IndexRange(123)) { + EXPECT_TRUE(vec[i]); + } + } +} + +TEST(bit_vector, IndexAccess) +{ + BitVector<> vec(100, false); + vec[55].set(); + EXPECT_FALSE(vec[50]); + EXPECT_FALSE(vec[51]); + EXPECT_FALSE(vec[52]); + EXPECT_FALSE(vec[53]); + EXPECT_FALSE(vec[54]); + EXPECT_TRUE(vec[55]); + EXPECT_FALSE(vec[56]); + EXPECT_FALSE(vec[57]); + EXPECT_FALSE(vec[58]); +} + +TEST(bit_vector, Iterator) +{ + BitVector<> vec(100, false); + { + int64_t index = 0; + for (MutableBitRef bit : vec) { + bit.set(ELEM(index, 0, 4, 7, 10, 11)); + index++; + } + } + { + int64_t index = 0; + for (BitRef bit : const_cast<const BitVector<> &>(vec)) { + EXPECT_EQ(bit, ELEM(index, 0, 4, 7, 10, 11)); + index++; + } + } +} + +TEST(bit_vector, Append) +{ + BitVector<> vec; + vec.append(false); + vec.append(true); + vec.append(true); + vec.append(false); + + EXPECT_EQ(vec.size(), 4); + EXPECT_FALSE(vec[0]); + EXPECT_TRUE(vec[1]); + EXPECT_TRUE(vec[2]); + EXPECT_FALSE(vec[3]); +} + +TEST(bit_vector, AppendMany) +{ + BitVector<> vec; + for (const int64_t i : IndexRange(1000)) { + vec.append(i % 2); + } + EXPECT_FALSE(vec[0]); + EXPECT_TRUE(vec[1]); + EXPECT_FALSE(vec[2]); + EXPECT_TRUE(vec[3]); + EXPECT_FALSE(vec[4]); + EXPECT_TRUE(vec[5]); +} + +} // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_cpp_type_test.cc b/source/blender/blenlib/tests/BLI_cpp_type_test.cc index 6a59bedc649..5823d54f51b 100644 --- a/source/blender/blenlib/tests/BLI_cpp_type_test.cc +++ b/source/blender/blenlib/tests/BLI_cpp_type_test.cc @@ -63,7 +63,7 @@ struct TestType { return stream; } - friend bool operator==(const TestType &UNUSED(a), const TestType &UNUSED(b)) + friend bool operator==(const TestType & /*a*/, const TestType & /*b*/) { return false; } diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc index 25ee523ebc0..ca99c678754 100644 --- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc @@ -99,7 +99,7 @@ template<typename T> CDT_input<T> fill_input_from_string(const char *spec) */ static int get_orig_index(const Array<Vector<int>> &out_to_orig, int orig_index) { - int n = static_cast<int>(out_to_orig.size()); + int n = int(out_to_orig.size()); for (int i = 0; i < n; ++i) { for (int orig : out_to_orig[i]) { if (orig == orig_index) { @@ -110,7 +110,7 @@ static int get_orig_index(const Array<Vector<int>> &out_to_orig, int orig_index) return -1; } -template<typename T> static double math_to_double(const T UNUSED(v)) +template<typename T> static double math_to_double(const T /*v*/) { BLI_assert(false); /* Need implementation for other type. */ return 0.0; @@ -147,7 +147,7 @@ template<> double math_abs(const double v) */ template<typename T> int get_vertex_by_coord(const CDT_result<T> &out, double x, double y) { - int nv = static_cast<int>(out.vert.size()); + int nv = int(out.vert.size()); for (int i = 0; i < nv; ++i) { double vx = math_to_double(out.vert[i][0]); double vy = math_to_double(out.vert[i][1]); @@ -162,7 +162,7 @@ template<typename T> int get_vertex_by_coord(const CDT_result<T> &out, double x, template<typename T> int get_output_edge_index(const CDT_result<T> &out, int out_index_1, int out_index_2) { - int ne = static_cast<int>(out.edge.size()); + int ne = int(out.edge.size()); for (int i = 0; i < ne; ++i) { if ((out.edge[i].first == out_index_1 && out.edge[i].second == out_index_2) || (out.edge[i].first == out_index_2 && out.edge[i].second == out_index_1)) { @@ -175,7 +175,7 @@ int get_output_edge_index(const CDT_result<T> &out, int out_index_1, int out_ind template<typename T> bool output_edge_has_input_id(const CDT_result<T> &out, int out_edge_index, int in_edge_index) { - return out_edge_index < static_cast<int>(out.edge_orig.size()) && + return out_edge_index < int(out.edge_orig.size()) && out.edge_orig[out_edge_index].contains(in_edge_index); } @@ -184,8 +184,8 @@ bool output_edge_has_input_id(const CDT_result<T> &out, int out_edge_index, int */ template<typename T> int get_output_face_index(const CDT_result<T> &out, const Array<int> &poly) { - int nf = static_cast<int>(out.face.size()); - int npolyv = static_cast<int>(poly.size()); + int nf = int(out.face.size()); + int npolyv = int(poly.size()); for (int f = 0; f < nf; ++f) { if (out.face[f].size() != poly.size()) { continue; @@ -218,7 +218,7 @@ int get_output_tri_index(const CDT_result<T> &out, template<typename T> bool output_face_has_input_id(const CDT_result<T> &out, int out_face_index, int in_face_index) { - return out_face_index < static_cast<int>(out.face_orig.size()) && + return out_face_index < int(out.face_orig.size()) && out.face_orig[out_face_index].contains(in_face_index); } @@ -310,10 +310,10 @@ void graph_draw(const std::string &label, double height = maxy - miny; double aspect = height / width; int view_width = max_draw_width; - int view_height = static_cast<int>(view_width * aspect); + int view_height = int(view_width * aspect); if (view_height > max_draw_height) { view_height = max_draw_height; - view_width = static_cast<int>(view_height / aspect); + view_width = int(view_height / aspect); } double scale = view_width / width; diff --git a/source/blender/blenlib/tests/BLI_edgehash_test.cc b/source/blender/blenlib/tests/BLI_edgehash_test.cc index 301fa226016..f6e987c7060 100644 --- a/source/blender/blenlib/tests/BLI_edgehash_test.cc +++ b/source/blender/blenlib/tests/BLI_edgehash_test.cc @@ -308,7 +308,7 @@ TEST(edgehash, StressTest) std::vector<Edge> edges; for (int i = 0; i < amount; i++) { - edges.push_back({(uint)i, amount + (uint)std::rand() % 12345}); + edges.push_back({uint(i), amount + uint(std::rand()) % 12345}); } EdgeHash *eh = BLI_edgehash_new(__func__); diff --git a/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh b/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh index 63943e48f0e..367d8508a20 100644 --- a/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh +++ b/source/blender/blenlib/tests/BLI_exception_safety_test_utils.hh @@ -87,7 +87,7 @@ class ExceptionThrower { uint64_t hash() const { - return static_cast<uint64_t>(value); + return uint64_t(value); } friend bool operator==(const ExceptionThrower &a, const ExceptionThrower &b) diff --git a/source/blender/blenlib/tests/BLI_float3x3_test.cc b/source/blender/blenlib/tests/BLI_float3x3_test.cc index d22993ee69e..cd823b6e368 100644 --- a/source/blender/blenlib/tests/BLI_float3x3_test.cc +++ b/source/blender/blenlib/tests/BLI_float3x3_test.cc @@ -34,6 +34,15 @@ TEST(float3x3, Rotation) EXPECT_FLOAT_EQ(result[1], 1.0f); } +TEST(float3x3, Scale) +{ + float2 point(1.0f, 2.0f); + float3x3 transformation = float3x3::from_scale(float2(2.0f, 3.0f)); + float2 result = transformation * point; + EXPECT_FLOAT_EQ(result[0], 2.0f); + EXPECT_FLOAT_EQ(result[1], 6.0f); +} + TEST(float3x3, TranslationRotationScale) { float2 point(1.0f, 2.0f); @@ -116,4 +125,11 @@ TEST(float3x3, Origin) EXPECT_FLOAT_EQ(result[1], 3.0f); } +TEST(float3x3, GetScale2D) +{ + float2 scale(2.0f, 3.0f); + float3x3 transformation = float3x3::from_scale(scale); + EXPECT_EQ(scale, transformation.scale_2d()); +} + } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_generic_array_test.cc b/source/blender/blenlib/tests/BLI_generic_array_test.cc index 52bc7728a6a..8e32430eede 100644 --- a/source/blender/blenlib/tests/BLI_generic_array_test.cc +++ b/source/blender/blenlib/tests/BLI_generic_array_test.cc @@ -20,7 +20,7 @@ TEST(generic_array, TypeConstructor) TEST(generic_array, MoveConstructor) { - GArray array_a(CPPType::get<int32_t>(), (int64_t)10); + GArray array_a(CPPType::get<int32_t>(), int64_t(10)); GMutableSpan span_a = array_a.as_mutable_span(); MutableSpan<int32_t> typed_span_a = span_a.typed<int32_t>(); typed_span_a.fill(42); @@ -40,7 +40,7 @@ TEST(generic_array, MoveConstructor) TEST(generic_array, CopyConstructor) { - GArray array_a(CPPType::get<int32_t>(), (int64_t)10); + GArray array_a(CPPType::get<int32_t>(), int64_t(10)); GMutableSpan span_a = array_a.as_mutable_span(); MutableSpan<int32_t> typed_span_a = span_a.typed<int32_t>(); typed_span_a.fill(42); @@ -79,7 +79,7 @@ TEST(generic_array, BufferAndSizeConstructor) TEST(generic_array, Reinitialize) { - GArray array(CPPType::get<int32_t>(), (int64_t)5); + GArray array(CPPType::get<int32_t>(), int64_t(5)); EXPECT_FALSE(array.data() == nullptr); GMutableSpan span = array.as_mutable_span(); MutableSpan<int32_t> typed_span = span.typed<int32_t>(); @@ -106,7 +106,7 @@ TEST(generic_array, InContainer) { blender::Array<GArray<>> arrays; for (GArray<> &array : arrays) { - array = GArray(CPPType::get<int32_t>(), (int64_t)5); + array = GArray(CPPType::get<int32_t>(), int64_t(5)); array.as_mutable_span().typed<int32_t>().fill(55); } for (GArray<> &array : arrays) { @@ -114,4 +114,13 @@ TEST(generic_array, InContainer) } } +TEST(generic_array, ReinitEmpty) +{ + GArray<> array(CPPType::get<int>()); + array.reinitialize(10); + array.as_mutable_span().typed<int>()[9] = 7; + EXPECT_EQ(array.size(), 10); + EXPECT_EQ(array.as_span().typed<int>()[9], 7); +} + } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_ghash_test.cc b/source/blender/blenlib/tests/BLI_ghash_test.cc index da5207cb3f8..5e763dc928f 100644 --- a/source/blender/blenlib/tests/BLI_ghash_test.cc +++ b/source/blender/blenlib/tests/BLI_ghash_test.cc @@ -34,10 +34,10 @@ /* NOTE: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here * we just use mere random integers stored in pointers. */ -static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed) +static void init_keys(uint keys[TESTCASE_SIZE], const int seed) { RNG *rng = BLI_rng_new(seed); - unsigned int *k; + uint *k; int i; for (i = 0, k = keys; i < TESTCASE_SIZE;) { @@ -61,7 +61,7 @@ static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed) TEST(ghash, InsertLookup) { GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); - unsigned int keys[TESTCASE_SIZE], *k; + uint keys[TESTCASE_SIZE], *k; int i; init_keys(keys, 0); @@ -85,7 +85,7 @@ TEST(ghash, InsertLookup) TEST(ghash, InsertRemove) { GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); - unsigned int keys[TESTCASE_SIZE], *k; + uint keys[TESTCASE_SIZE], *k; int i, bkt_size; init_keys(keys, 10); @@ -112,7 +112,7 @@ TEST(ghash, InsertRemove) TEST(ghash, InsertRemoveShrink) { GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); - unsigned int keys[TESTCASE_SIZE], *k; + uint keys[TESTCASE_SIZE], *k; int i, bkt_size; BLI_ghash_flag_set(ghash, GHASH_FLAG_ALLOW_SHRINK); @@ -141,7 +141,7 @@ TEST(ghash, Copy) { GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); GHash *ghash_copy; - unsigned int keys[TESTCASE_SIZE], *k; + uint keys[TESTCASE_SIZE], *k; int i; init_keys(keys, 30); @@ -170,7 +170,7 @@ TEST(ghash, Copy) TEST(ghash, Pop) { GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__); - unsigned int keys[TESTCASE_SIZE], *k; + uint keys[TESTCASE_SIZE], *k; int i; BLI_ghash_flag_set(ghash, GHASH_FLAG_ALLOW_SHRINK); diff --git a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc index 99bb107840f..90f5aa6189f 100644 --- a/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc +++ b/source/blender/blenlib/tests/BLI_hash_mm2a_test.cc @@ -16,7 +16,7 @@ TEST(hash_mm2a, MM2ABasic) const char *data = "Blender"; BLI_hash_mm2a_init(&mm2, 0); - BLI_hash_mm2a_add(&mm2, (const unsigned char *)data, strlen(data)); + BLI_hash_mm2a_add(&mm2, (const uchar *)data, strlen(data)); #ifdef __LITTLE_ENDIAN__ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145); #else @@ -35,12 +35,12 @@ TEST(hash_mm2a, MM2AConcatenateStrings) const char *data123 = "Blender is FaNtAsTiC"; BLI_hash_mm2a_init(&mm2, 0); - BLI_hash_mm2a_add(&mm2, (const unsigned char *)data1, strlen(data1)); - BLI_hash_mm2a_add(&mm2, (const unsigned char *)data2, strlen(data2)); - BLI_hash_mm2a_add(&mm2, (const unsigned char *)data3, strlen(data3)); + BLI_hash_mm2a_add(&mm2, (const uchar *)data1, strlen(data1)); + BLI_hash_mm2a_add(&mm2, (const uchar *)data2, strlen(data2)); + BLI_hash_mm2a_add(&mm2, (const uchar *)data3, strlen(data3)); hash = BLI_hash_mm2a_end(&mm2); BLI_hash_mm2a_init(&mm2, 0); - BLI_hash_mm2a_add(&mm2, (const unsigned char *)data123, strlen(data123)); + BLI_hash_mm2a_add(&mm2, (const uchar *)data123, strlen(data123)); #ifdef __LITTLE_ENDIAN__ EXPECT_EQ(hash, 1545105348); #else @@ -63,7 +63,7 @@ TEST(hash_mm2a, MM2AIntegers) BLI_hash_mm2a_add_int(&mm2, ints[3]); hash = BLI_hash_mm2a_end(&mm2); BLI_hash_mm2a_init(&mm2, 0); - BLI_hash_mm2a_add(&mm2, (const unsigned char *)ints, sizeof(ints)); + BLI_hash_mm2a_add(&mm2, (const uchar *)ints, sizeof(ints)); /* Yes, same hash here on little and big endian. */ #ifdef __LITTLE_ENDIAN__ EXPECT_EQ(hash, 405493096); diff --git a/source/blender/blenlib/tests/BLI_heap_simple_test.cc b/source/blender/blenlib/tests/BLI_heap_simple_test.cc index 818de67740b..96a5e42374e 100644 --- a/source/blender/blenlib/tests/BLI_heap_simple_test.cc +++ b/source/blender/blenlib/tests/BLI_heap_simple_test.cc @@ -18,7 +18,7 @@ static void range_fl(float *array_tar, const int size) float *array_pt = array_tar + (size - 1); int i = size; while (i--) { - *(array_pt--) = (float)i; + *(array_pt--) = float(i); } } @@ -53,7 +53,7 @@ TEST(heap, SimpleRange) const int items_total = SIZE; HeapSimple *heap = BLI_heapsimple_new(); for (int in = 0; in < items_total; in++) { - BLI_heapsimple_insert(heap, (float)in, POINTER_FROM_INT(in)); + BLI_heapsimple_insert(heap, float(in), POINTER_FROM_INT(in)); } for (int out_test = 0; out_test < items_total; out_test++) { EXPECT_EQ(out_test, POINTER_AS_INT(BLI_heapsimple_pop_min(heap))); @@ -67,7 +67,7 @@ TEST(heap, SimpleRangeReverse) const int items_total = SIZE; HeapSimple *heap = BLI_heapsimple_new(); for (int in = 0; in < items_total; in++) { - BLI_heapsimple_insert(heap, (float)-in, POINTER_FROM_INT(-in)); + BLI_heapsimple_insert(heap, float(-in), POINTER_FROM_INT(-in)); } for (int out_test = items_total - 1; out_test >= 0; out_test--) { EXPECT_EQ(-out_test, POINTER_AS_INT(BLI_heapsimple_pop_min(heap))); @@ -97,7 +97,7 @@ static void random_heapsimple_helper(const int items_total, const int random_see range_fl(values, items_total); BLI_array_randomize(values, sizeof(float), items_total, random_seed); for (int i = 0; i < items_total; i++) { - BLI_heapsimple_insert(heap, values[i], POINTER_FROM_INT((int)values[i])); + BLI_heapsimple_insert(heap, values[i], POINTER_FROM_INT(int(values[i]))); } for (int out_test = 0; out_test < items_total; out_test++) { EXPECT_EQ(out_test, POINTER_AS_INT(BLI_heapsimple_pop_min(heap))); diff --git a/source/blender/blenlib/tests/BLI_heap_test.cc b/source/blender/blenlib/tests/BLI_heap_test.cc index 333a1530b6d..f2368ce4abf 100644 --- a/source/blender/blenlib/tests/BLI_heap_test.cc +++ b/source/blender/blenlib/tests/BLI_heap_test.cc @@ -17,7 +17,7 @@ static void range_fl(float *array_tar, const int size) float *array_pt = array_tar + (size - 1); int i = size; while (i--) { - *(array_pt--) = (float)i; + *(array_pt--) = float(i); } } @@ -52,7 +52,7 @@ TEST(heap, Range) const int items_total = SIZE; Heap *heap = BLI_heap_new(); for (int in = 0; in < items_total; in++) { - BLI_heap_insert(heap, (float)in, POINTER_FROM_INT(in)); + BLI_heap_insert(heap, float(in), POINTER_FROM_INT(in)); } for (int out_test = 0; out_test < items_total; out_test++) { EXPECT_EQ(out_test, POINTER_AS_INT(BLI_heap_pop_min(heap))); @@ -66,7 +66,7 @@ TEST(heap, RangeReverse) const int items_total = SIZE; Heap *heap = BLI_heap_new(); for (int in = 0; in < items_total; in++) { - BLI_heap_insert(heap, (float)-in, POINTER_FROM_INT(-in)); + BLI_heap_insert(heap, float(-in), POINTER_FROM_INT(-in)); } for (int out_test = items_total - 1; out_test >= 0; out_test--) { EXPECT_EQ(-out_test, POINTER_AS_INT(BLI_heap_pop_min(heap))); @@ -81,7 +81,7 @@ TEST(heap, RangeRemove) Heap *heap = BLI_heap_new(); HeapNode **nodes = (HeapNode **)MEM_mallocN(sizeof(HeapNode *) * items_total, __func__); for (int in = 0; in < items_total; in++) { - nodes[in] = BLI_heap_insert(heap, (float)in, POINTER_FROM_INT(in)); + nodes[in] = BLI_heap_insert(heap, float(in), POINTER_FROM_INT(in)); } for (int i = 0; i < items_total; i += 2) { BLI_heap_remove(heap, nodes[i]); @@ -116,7 +116,7 @@ static void random_heap_helper(const int items_total, const int random_seed) range_fl(values, items_total); BLI_array_randomize(values, sizeof(float), items_total, random_seed); for (int i = 0; i < items_total; i++) { - BLI_heap_insert(heap, values[i], POINTER_FROM_INT((int)values[i])); + BLI_heap_insert(heap, values[i], POINTER_FROM_INT(int(values[i]))); } for (int out_test = 0; out_test < items_total; out_test++) { EXPECT_EQ(out_test, POINTER_AS_INT(BLI_heap_pop_min(heap))); @@ -145,10 +145,10 @@ TEST(heap, ReInsertSimple) Heap *heap = BLI_heap_new(); HeapNode **nodes = (HeapNode **)MEM_mallocN(sizeof(HeapNode *) * items_total, __func__); for (int in = 0; in < items_total; in++) { - nodes[in] = BLI_heap_insert(heap, (float)in, POINTER_FROM_INT(in)); + nodes[in] = BLI_heap_insert(heap, float(in), POINTER_FROM_INT(in)); } for (int i = 0; i < items_total; i++) { - BLI_heap_node_value_update(heap, nodes[i], (float)(items_total + i)); + BLI_heap_node_value_update(heap, nodes[i], float(items_total + i)); } for (int out_test = 0; out_test < items_total; out_test++) { @@ -165,11 +165,11 @@ static void random_heap_reinsert_helper(const int items_total, const int random_ Heap *heap = BLI_heap_new(); HeapNode **nodes = (HeapNode **)MEM_mallocN(sizeof(HeapNode *) * items_total, __func__); for (int in = 0; in < items_total; in++) { - nodes[in] = BLI_heap_insert(heap, (float)in, POINTER_FROM_INT(in)); + nodes[in] = BLI_heap_insert(heap, float(in), POINTER_FROM_INT(in)); } BLI_array_randomize(nodes, sizeof(HeapNode *), items_total, random_seed); for (int i = 0; i < items_total; i++) { - BLI_heap_node_value_update(heap, nodes[i], (float)i); + BLI_heap_node_value_update(heap, nodes[i], float(i)); } EXPECT_TRUE(BLI_heap_is_valid(heap)); @@ -177,7 +177,7 @@ static void random_heap_reinsert_helper(const int items_total, const int random_ HeapNode *node_top = BLI_heap_top(heap); float out = BLI_heap_node_value(node_top); EXPECT_EQ(out, BLI_heap_top_value(heap)); - EXPECT_EQ((float)out_test, out); + EXPECT_EQ(float(out_test), out); BLI_heap_pop_min(heap); } EXPECT_TRUE(BLI_heap_is_empty(heap)); diff --git a/source/blender/blenlib/tests/BLI_index_range_test.cc b/source/blender/blenlib/tests/BLI_index_range_test.cc index f5b994d409a..8ec7ad85d9c 100644 --- a/source/blender/blenlib/tests/BLI_index_range_test.cc +++ b/source/blender/blenlib/tests/BLI_index_range_test.cc @@ -126,6 +126,17 @@ TEST(index_range, Slice) EXPECT_EQ(slice.last(), 12); } +TEST(index_range, Intersect) +{ + IndexRange range = IndexRange(5, 15); + EXPECT_EQ(range.intersect(IndexRange(2, 2)), IndexRange(5, 0)); + EXPECT_EQ(range.intersect(IndexRange(4, 2)), IndexRange(5, 1)); + EXPECT_EQ(range.intersect(IndexRange(3, 20)), IndexRange(5, 15)); + EXPECT_EQ(range.intersect(IndexRange(5, 15)), IndexRange(5, 15)); + EXPECT_EQ(range.intersect(IndexRange(15, 10)), IndexRange(15, 5)); + EXPECT_EQ(range.intersect(IndexRange(22, 2)), IndexRange(20, 0)); +} + TEST(index_range, SliceRange) { IndexRange range = IndexRange(5, 15); @@ -235,4 +246,50 @@ TEST(index_range, GenericAlgorithms) EXPECT_EQ(std::count_if(range.begin(), range.end(), [](int v) { return v < 7; }), 3); } +TEST(index_range, SplitByAlignment) +{ + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(0, 0), 16); + EXPECT_EQ(ranges.prefix, IndexRange()); + EXPECT_EQ(ranges.aligned, IndexRange()); + EXPECT_EQ(ranges.suffix, IndexRange()); + } + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(0, 24), 8); + EXPECT_EQ(ranges.prefix, IndexRange()); + EXPECT_EQ(ranges.aligned, IndexRange(0, 24)); + EXPECT_EQ(ranges.suffix, IndexRange()); + } + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(1, 2), 4); + EXPECT_EQ(ranges.prefix, IndexRange(1, 2)); + EXPECT_EQ(ranges.aligned, IndexRange()); + EXPECT_EQ(ranges.suffix, IndexRange()); + } + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(3, 50), 8); + EXPECT_EQ(ranges.prefix, IndexRange(3, 5)); + EXPECT_EQ(ranges.aligned, IndexRange(8, 40)); + EXPECT_EQ(ranges.suffix, IndexRange(48, 5)); + } + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(3, 50), 1); + EXPECT_EQ(ranges.prefix, IndexRange()); + EXPECT_EQ(ranges.aligned, IndexRange(3, 50)); + EXPECT_EQ(ranges.suffix, IndexRange()); + } + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(64, 16), 16); + EXPECT_EQ(ranges.prefix, IndexRange()); + EXPECT_EQ(ranges.aligned, IndexRange(64, 16)); + EXPECT_EQ(ranges.suffix, IndexRange()); + } + { + AlignedIndexRanges ranges = split_index_range_by_alignment(IndexRange(3, 5), 8); + EXPECT_EQ(ranges.prefix, IndexRange(3, 5)); + EXPECT_EQ(ranges.aligned, IndexRange()); + EXPECT_EQ(ranges.suffix, IndexRange()); + } +} + } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_kdopbvh_test.cc b/source/blender/blenlib/tests/BLI_kdopbvh_test.cc index 756219cd733..83eeabaea40 100644 --- a/source/blender/blenlib/tests/BLI_kdopbvh_test.cc +++ b/source/blender/blenlib/tests/BLI_kdopbvh_test.cc @@ -18,7 +18,7 @@ static void rng_v3_round(float *coords, int coords_len, struct RNG *rng, int rou { for (int i = 0; i < coords_len; i++) { float f = BLI_rng_get_float(rng) * 2.0f - 1.0f; - coords[i] = ((float)((int)(f * round)) / (float)round) * scale; + coords[i] = (float(int(f * round)) / float(round)) * scale; } } @@ -90,7 +90,7 @@ static void find_nearest_points_test( if (j != i) { #if 0 const float dist = len_v3v3(points[i], points[j]); - if (dist > (1.0f / (float)round)) { + if (dist > (1.0f / float(round))) { printf("%.15f (%d %d)\n", dist, i, j); print_v3_id(points[i]); print_v3_id(points[j]); diff --git a/source/blender/blenlib/tests/BLI_linear_allocator_test.cc b/source/blender/blenlib/tests/BLI_linear_allocator_test.cc index b67683d0558..2ed1786f9e0 100644 --- a/source/blender/blenlib/tests/BLI_linear_allocator_test.cc +++ b/source/blender/blenlib/tests/BLI_linear_allocator_test.cc @@ -9,7 +9,7 @@ namespace blender::tests { static bool is_aligned(void *ptr, uint alignment) { - BLI_assert(is_power_of_2_i(static_cast<int>(alignment))); + BLI_assert(is_power_of_2_i(int(alignment))); return (POINTER_AS_UINT(ptr) & (alignment - 1)) == 0; } @@ -36,13 +36,13 @@ TEST(linear_allocator, PackedAllocation) blender::AlignedBuffer<256, 32> buffer; allocator.provide_buffer(buffer); - uintptr_t ptr1 = (uintptr_t)allocator.allocate(10, 4); /* 0 - 10 */ - uintptr_t ptr2 = (uintptr_t)allocator.allocate(10, 4); /* 12 - 22 */ - uintptr_t ptr3 = (uintptr_t)allocator.allocate(8, 32); /* 32 - 40 */ - uintptr_t ptr4 = (uintptr_t)allocator.allocate(16, 8); /* 40 - 56 */ - uintptr_t ptr5 = (uintptr_t)allocator.allocate(1, 8); /* 56 - 57 */ - uintptr_t ptr6 = (uintptr_t)allocator.allocate(1, 4); /* 60 - 61 */ - uintptr_t ptr7 = (uintptr_t)allocator.allocate(1, 1); /* 61 - 62 */ + uintptr_t ptr1 = uintptr_t(allocator.allocate(10, 4)); /* 0 - 10 */ + uintptr_t ptr2 = uintptr_t(allocator.allocate(10, 4)); /* 12 - 22 */ + uintptr_t ptr3 = uintptr_t(allocator.allocate(8, 32)); /* 32 - 40 */ + uintptr_t ptr4 = uintptr_t(allocator.allocate(16, 8)); /* 40 - 56 */ + uintptr_t ptr5 = uintptr_t(allocator.allocate(1, 8)); /* 56 - 57 */ + uintptr_t ptr6 = uintptr_t(allocator.allocate(1, 4)); /* 60 - 61 */ + uintptr_t ptr7 = uintptr_t(allocator.allocate(1, 1)); /* 61 - 62 */ EXPECT_EQ(ptr2 - ptr1, 12); /* 12 - 0 = 12 */ EXPECT_EQ(ptr3 - ptr2, 20); /* 32 - 12 = 20 */ @@ -130,7 +130,7 @@ TEST(linear_allocator, ManyAllocations) RandomNumberGenerator rng; for (int i = 0; i < 1000; i++) { int size = rng.get_int32(10000); - int alignment = 1 << (rng.get_int32(7)); + int alignment = 1 << rng.get_int32(7); void *buffer = allocator.allocate(size, alignment); EXPECT_NE(buffer, nullptr); } diff --git a/source/blender/blenlib/tests/BLI_listbase_test.cc b/source/blender/blenlib/tests/BLI_listbase_test.cc index aa2f885e39d..abdd4f90221 100644 --- a/source/blender/blenlib/tests/BLI_listbase_test.cc +++ b/source/blender/blenlib/tests/BLI_listbase_test.cc @@ -222,7 +222,7 @@ static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_nu link_step = (LinkData *)lb->first; for (i = 0; i < arr_num; i++) { - if (strcmp(arr[i], (char *)link_step->data) != 0) { + if (!STREQ(arr[i], (char *)link_step->data)) { return false; } link_step = link_step->next; @@ -241,7 +241,7 @@ static bool testsort_listbase_sort_is_stable(ListBase *lb, bool forward) link_step = (LinkData *)lb->first; while (link_step && link_step->next) { - if (strcmp((const char *)link_step->data, (const char *)link_step->next->data) == 0) { + if (STREQ((const char *)link_step->data, (const char *)link_step->next->data)) { if ((link_step < link_step->next) != forward) { return false; } diff --git a/source/blender/blenlib/tests/BLI_map_test.cc b/source/blender/blenlib/tests/BLI_map_test.cc index dbbd4843abc..69ae82d6f05 100644 --- a/source/blender/blenlib/tests/BLI_map_test.cc +++ b/source/blender/blenlib/tests/BLI_map_test.cc @@ -560,8 +560,8 @@ TEST(map, PopExceptions) TEST(map, AddOrModifyExceptions) { Map<ExceptionThrower, ExceptionThrower> map; - auto create_fn = [](ExceptionThrower *UNUSED(v)) { throw std::runtime_error(""); }; - auto modify_fn = [](ExceptionThrower *UNUSED(v)) {}; + auto create_fn = [](ExceptionThrower * /*v*/) { throw std::runtime_error(""); }; + auto modify_fn = [](ExceptionThrower * /*v*/) {}; EXPECT_ANY_THROW({ map.add_or_modify(3, create_fn, modify_fn); }); } @@ -640,6 +640,24 @@ TEST(map, RemoveDuringIteration) EXPECT_EQ(map.lookup(3), 3); } +TEST(map, RemoveIf) +{ + Map<int64_t, int64_t> map; + for (const int64_t i : IndexRange(100)) { + map.add(i * i, i); + } + map.remove_if([](auto item) { return item.key > 100; }); + EXPECT_EQ(map.size(), 11); + for (const int64_t i : IndexRange(100)) { + if (i <= 10) { + EXPECT_EQ(map.lookup(i * i), i); + } + else { + EXPECT_FALSE(map.contains(i * i)); + } + } +} + TEST(map, LookupKey) { Map<std::string, int> map; diff --git a/source/blender/blenlib/tests/BLI_math_color_test.cc b/source/blender/blenlib/tests/BLI_math_color_test.cc index 4d928477870..0b6f9340379 100644 --- a/source/blender/blenlib/tests/BLI_math_color_test.cc +++ b/source/blender/blenlib/tests/BLI_math_color_test.cc @@ -68,7 +68,7 @@ TEST(math_color, LinearRGBTosRGBRoundtrip) const int N = 50; int i; for (i = 0; i < N; ++i) { - float orig_linear_color = (float)i / N; + float orig_linear_color = float(i) / N; float srgb_color = linearrgb_to_srgb(orig_linear_color); float linear_color = srgb_to_linearrgb(srgb_color); EXPECT_NEAR(orig_linear_color, linear_color, 1e-5); diff --git a/source/blender/blenlib/tests/BLI_math_rotation_test.cc b/source/blender/blenlib/tests/BLI_math_rotation_test.cc index a283118bea2..e37b212e1df 100644 --- a/source/blender/blenlib/tests/BLI_math_rotation_test.cc +++ b/source/blender/blenlib/tests/BLI_math_rotation_test.cc @@ -7,6 +7,8 @@ #include "BLI_math_rotation.hh" #include "BLI_math_vector.hh" +#include "BLI_vector.hh" + #include <cmath> /* Test that quaternion converts to itself via matrix. */ @@ -150,6 +152,107 @@ TEST(math_rotation, quat_split_swing_and_twist_negative) EXPECT_V4_NEAR(twist, expected_twist, FLT_EPSILON); } +/* -------------------------------------------------------------------- */ +/** \name Test `sin_cos_from_fraction` Accuracy & Exact Symmetry + * \{ */ + +static void test_sin_cos_from_fraction_accuracy(const int range, const float expected_eps) +{ + for (int i = 0; i < range; i++) { + float sin_cos_fl[2]; + sin_cos_from_fraction(i, range, &sin_cos_fl[0], &sin_cos_fl[1]); + const float phi = float(2.0 * M_PI) * (float(i) / float(range)); + const float sin_cos_test_fl[2] = {sinf(phi), cosf(phi)}; + EXPECT_V2_NEAR(sin_cos_fl, sin_cos_test_fl, expected_eps); + } +} + +/** Ensure the result of #sin_cos_from_fraction match #sinf & #cosf. */ +TEST(math_rotation, sin_cos_from_fraction_accuracy) +{ + for (int range = 1; range <= 64; range++) { + test_sin_cos_from_fraction_accuracy(range, 1e-6f); + } +} + +/** Ensure values are exactly symmetrical where possible. */ +static void test_sin_cos_from_fraction_symmetry(const int range) +{ + /* The expected number of unique numbers depends on the range being a multiple of 4/2/1. */ + const enum { + MULTIPLE_OF_1 = 1, + MULTIPLE_OF_2 = 2, + MULTIPLE_OF_4 = 3, + } multiple_of = (range & 1) ? MULTIPLE_OF_1 : ((range & 3) ? MULTIPLE_OF_2 : MULTIPLE_OF_4); + + blender::Vector<blender::float2> coords; + coords.reserve(range); + for (int i = 0; i < range; i++) { + float sin_cos_fl[2]; + sin_cos_from_fraction(i, range, &sin_cos_fl[0], &sin_cos_fl[1]); + switch (multiple_of) { + case MULTIPLE_OF_1: { + sin_cos_fl[0] = fabsf(sin_cos_fl[0]); + break; + } + case MULTIPLE_OF_2: { + sin_cos_fl[0] = fabsf(sin_cos_fl[0]); + sin_cos_fl[1] = fabsf(sin_cos_fl[1]); + break; + } + case MULTIPLE_OF_4: { + sin_cos_fl[0] = fabsf(sin_cos_fl[0]); + sin_cos_fl[1] = fabsf(sin_cos_fl[1]); + if (sin_cos_fl[0] > sin_cos_fl[1]) { + SWAP(float, sin_cos_fl[0], sin_cos_fl[1]); + } + break; + } + } + coords.append_unchecked(sin_cos_fl); + } + /* Sort, then count unique items. */ + std::sort(coords.begin(), coords.end(), [](const blender::float2 &a, const blender::float2 &b) { + float delta = b[0] - a[0]; + if (delta == 0.0f) { + delta = b[1] - a[1]; + } + return delta > 0.0f; + }); + int unique_coords_count = 1; + if (range > 1) { + int i_prev = 0; + for (int i = 1; i < range; i_prev = i++) { + if (coords[i_prev] != coords[i]) { + unique_coords_count += 1; + } + } + } + switch (multiple_of) { + case MULTIPLE_OF_1: { + EXPECT_EQ(unique_coords_count, (range / 2) + 1); + break; + } + case MULTIPLE_OF_2: { + EXPECT_EQ(unique_coords_count, (range / 4) + 1); + break; + } + case MULTIPLE_OF_4: { + EXPECT_EQ(unique_coords_count, (range / 8) + 1); + break; + } + } +} + +TEST(math_rotation, sin_cos_from_fraction_symmetry) +{ + for (int range = 1; range <= 64; range++) { + test_sin_cos_from_fraction_symmetry(range); + } +} + +/** \} */ + namespace blender::math::tests { TEST(math_rotation, RotateDirectionAroundAxis) diff --git a/source/blender/blenlib/tests/BLI_memory_utils_test.cc b/source/blender/blenlib/tests/BLI_memory_utils_test.cc index ab716e5d011..939ac6151b0 100644 --- a/source/blender/blenlib/tests/BLI_memory_utils_test.cc +++ b/source/blender/blenlib/tests/BLI_memory_utils_test.cc @@ -20,7 +20,7 @@ struct MyValue { alive++; } - MyValue(const MyValue &UNUSED(other)) + MyValue(const MyValue & /*other*/) { if (alive == 15) { throw std::exception(); diff --git a/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc b/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc index fabc2412828..ea324534d78 100644 --- a/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc +++ b/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc @@ -106,7 +106,7 @@ class IMeshBuilder { } }; -static int all_shape_zero(int UNUSED(t)) +static int all_shape_zero(int /*t*/) { return 0; } diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc index c155068b94a..67a5771593a 100644 --- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc +++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc @@ -153,7 +153,7 @@ static int find_edge_pos_in_tri(const Vert *v0, const Vert *v1, const Face *f) for (int pos : f->index_range()) { int nextpos = f->next_pos(pos); if (((*f)[pos] == v0 && (*f)[nextpos] == v1) || ((*f)[pos] == v1 && (*f)[nextpos] == v0)) { - return static_cast<int>(pos); + return int(pos); } } return -1; diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 4f6f4a5c413..89e537235db 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -207,7 +207,7 @@ TEST(path_util, NameAtIndex_NoneComplexNeg) char result[(out_size) + 1024]; \ /* check we don't write past the last byte */ \ result[out_size] = '\0'; \ - BLI_path_join(result, out_size, __VA_ARGS__, NULL); \ + BLI_path_join(result, out_size, __VA_ARGS__); \ /* simplify expected string */ \ BLI_str_replace_char(result, '\\', '/'); \ EXPECT_STREQ(result, expect); \ @@ -298,6 +298,13 @@ TEST(path_util, JoinComplex) JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\"); } +TEST(path_util, JoinRelativePrefix) +{ + JOIN("//a/b/c", 100, "//a", "b", "c"); + JOIN("//a/b/c", 100, "//", "//a//", "//b//", "//c"); + JOIN("//a/b/c", 100, "//", "//", "a", "//", "b", "//", "c"); +} + #undef JOIN /* BLI_path_frame */ @@ -459,7 +466,7 @@ TEST(path_util, PathFrameStrip) #define PATH_EXTENSION_CHECK(input_path, input_ext, expect_ext) \ { \ const bool ret = BLI_path_extension_check(input_path, input_ext); \ - if (strcmp(input_ext, expect_ext) == 0) { \ + if (STREQ(input_ext, expect_ext)) { \ EXPECT_TRUE(ret); \ } \ else { \ @@ -644,7 +651,7 @@ TEST(path_util, PathRelPath) abs_path_in[FILE_MAX - 1] = '\0'; abs_path_out[0] = '/'; abs_path_out[1] = '/'; - for (int i = 2; i < FILE_MAX - ((int)ref_path_in_len - 1); i++) { + for (int i = 2; i < FILE_MAX - (int(ref_path_in_len) - 1); i++) { abs_path_out[i] = 'A'; } abs_path_out[FILE_MAX - (ref_path_in_len - 1)] = '\0'; diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc index db2fb1ba671..f3b66bedf88 100644 --- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc @@ -29,20 +29,20 @@ static void polyfill_to_obj(const char *id, const float poly[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num); + const uint poly_num, + const uint tris[][3], + const uint tris_num); /* -------------------------------------------------------------------- */ /* test utility functions */ -#define TRI_ERROR_VALUE (unsigned int)-1 +#define TRI_ERROR_VALUE (uint) - 1 -static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_num) +static void test_valid_polyfill_prepare(uint tris[][3], uint tris_num) { - unsigned int i; + uint i; for (i = 0; i < tris_num; i++) { - unsigned int j; + uint j; for (j = 0; j < 3; j++) { tris[i][j] = TRI_ERROR_VALUE; } @@ -57,14 +57,14 @@ static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tri * - all verts used at least once. */ static void test_polyfill_simple(const float /*poly*/[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + const uint tris[][3], + const uint tris_num) { - unsigned int i; + uint i; int *used_num = (int *)MEM_callocN(poly_num * sizeof(int), __func__); for (i = 0; i < tris_num; i++) { - unsigned int j; + uint j; for (j = 0; j < 3; j++) { EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]); used_num[tris[i][j]] += 1; @@ -80,41 +80,41 @@ static void test_polyfill_simple(const float /*poly*/[][2], } static void test_polyfill_topology(const float /*poly*/[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + const uint tris[][3], + const uint tris_num) { EdgeHash *edgehash = BLI_edgehash_new(__func__); EdgeHashIterator *ehi; - unsigned int i; + uint i; for (i = 0; i < tris_num; i++) { - unsigned int j; + uint j; for (j = 0; j < 3; j++) { - const unsigned int v1 = tris[i][j]; - const unsigned int v2 = tris[i][(j + 1) % 3]; + const uint v1 = tris[i][j]; + const uint v2 = tris[i][(j + 1) % 3]; void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); if (p) { - *p = (void *)((intptr_t)*p + (intptr_t)1); + *p = (void *)(intptr_t(*p) + intptr_t(1)); } else { - BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1); + BLI_edgehash_insert(edgehash, v1, v2, (void *)intptr_t(1)); } } } EXPECT_EQ(BLI_edgehash_len(edgehash), poly_num + (poly_num - 3)); for (i = 0; i < poly_num; i++) { - const unsigned int v1 = i; - const unsigned int v2 = (i + 1) % poly_num; + const uint v1 = i; + const uint v2 = (i + 1) % poly_num; void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); EXPECT_NE((void *)p, nullptr); - EXPECT_EQ((intptr_t)*p, 1); + EXPECT_EQ(intptr_t(*p), 1); } for (ehi = BLI_edgehashIterator_new(edgehash), i = 0; BLI_edgehashIterator_isDone(ehi) == false; BLI_edgehashIterator_step(ehi), i++) { void **p = BLI_edgehashIterator_getValue_p(ehi); - EXPECT_TRUE(ELEM((intptr_t)*p, 1, 2)); + EXPECT_TRUE(ELEM(intptr_t(*p), 1, 2)); } BLI_edgehashIterator_free(ehi); @@ -125,12 +125,12 @@ static void test_polyfill_topology(const float /*poly*/[][2], * Check all faces are flipped the same way */ static void test_polyfill_winding(const float poly[][2], - const unsigned int /*poly_num*/, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint /*poly_num*/, + const uint tris[][3], + const uint tris_num) { - unsigned int i; - unsigned int count[2] = {0, 0}; + uint i; + uint count[2] = {0, 0}; for (i = 0; i < tris_num; i++) { float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]); if (fabsf(winding_test) > FLT_EPSILON) { @@ -144,11 +144,11 @@ static void test_polyfill_winding(const float poly[][2], * Check the accumulated triangle area is close to the original area. */ static void test_polyfill_area(const float poly[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + const uint tris[][3], + const uint tris_num) { - unsigned int i; + uint i; const float area_total = area_poly_v2(poly, poly_num); float area_total_tris = 0.0f; const float eps_abs = 0.00001f; @@ -167,9 +167,9 @@ static void test_polyfill_area(const float poly[][2], static void test_polyfill_template_check(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + const uint tris[][3], + const uint tris_num) { test_polyfill_simple(poly, poly_num, tris, tris_num); test_polyfill_topology(poly, poly_num, tris, tris_num); @@ -184,9 +184,9 @@ static void test_polyfill_template_check(const char *id, static void test_polyfill_template(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_num, - unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + uint tris[][3], + const uint tris_num) { test_valid_polyfill_prepare(tris, tris_num); BLI_polyfill_calc(poly, poly_num, 0, tris); @@ -213,9 +213,9 @@ static void test_polyfill_template(const char *id, static void test_polyfill_template_flip_sign(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_num, - unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + uint tris[][3], + const uint tris_num) { float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_num, id); for (int flip_x = 0; flip_x < 2; flip_x++) { @@ -236,19 +236,19 @@ static void test_polyfill_template_flip_sign(const char *id, static void test_polyfill_template_main(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_num, - unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + uint tris[][3], + const uint tris_num) { /* overkill? - try at _every_ offset & reverse */ - unsigned int poly_reverse; + uint poly_reverse; float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_num, id); float tmp[2]; memcpy(poly_copy, poly, sizeof(float[2]) * poly_num); for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) { - unsigned int poly_cycle; + uint poly_cycle; if (poly_reverse) { BLI_array_reverse(poly_copy, poly_num); @@ -271,9 +271,9 @@ static void test_polyfill_template_main(const char *id, static void test_polyfill_template_main(const char *id, bool is_degenerate, const float poly[][2], - const unsigned int poly_num, - unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + uint tris[][3], + const uint tris_num) { test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num); } @@ -281,9 +281,9 @@ static void test_polyfill_template_main(const char *id, #define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \ { \ - unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \ - const unsigned int poly_num = ARRAY_SIZE(poly); \ - const unsigned int tris_num = ARRAY_SIZE(tris); \ + uint tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \ + const uint poly_num = ARRAY_SIZE(poly); \ + const uint tris_num = ARRAY_SIZE(tris); \ const char *id = typeid(*this).name(); \ \ test_polyfill_template_main(id, is_degenerate, poly, poly_num, tris, tris_num); \ @@ -296,13 +296,13 @@ static void test_polyfill_template_main(const char *id, #ifdef USE_OBJ_PREVIEW static void polyfill_to_obj(const char *id, const float poly[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + const uint tris[][3], + const uint tris_num) { char path[1024]; FILE *f; - unsigned int i; + uint i; BLI_snprintf(path, sizeof(path), "%s.obj", id); @@ -324,9 +324,9 @@ static void polyfill_to_obj(const char *id, #else static void polyfill_to_obj(const char *id, const float poly[][2], - const unsigned int poly_num, - const unsigned int tris[][3], - const unsigned int tris_num) + const uint poly_num, + const uint tris[][3], + const uint tris_num) { (void)id; (void)poly, (void)poly_num; diff --git a/source/blender/blenlib/tests/BLI_pool_test.cc b/source/blender/blenlib/tests/BLI_pool_test.cc new file mode 100644 index 00000000000..31cb255d997 --- /dev/null +++ b/source/blender/blenlib/tests/BLI_pool_test.cc @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "BLI_exception_safety_test_utils.hh" +#include "BLI_pool.hh" +#include "BLI_strict_flags.h" +#include "testing/testing.h" + +namespace blender::tests { + +TEST(pool, DefaultConstructor) +{ + Pool<int> pool; + EXPECT_EQ(pool.size(), 0); +} + +TEST(pool, Allocation) +{ + Vector<int *> ptrs; + Pool<int> pool; + for (int i = 0; i < 100; i++) { + ptrs.append(&pool.construct(i)); + } + EXPECT_EQ(pool.size(), 100); + + for (int *ptr : ptrs) { + pool.destruct(*ptr); + } + EXPECT_EQ(pool.size(), 0); +} + +TEST(pool, Reuse) +{ + Vector<int *> ptrs; + Pool<int> pool; + for (int i = 0; i < 32; i++) { + ptrs.append(&pool.construct(i)); + } + + int *freed_ptr = ptrs[6]; + pool.destruct(*freed_ptr); + + ptrs[6] = &pool.construct(0); + + EXPECT_EQ(ptrs[6], freed_ptr); + + for (int *ptr : ptrs) { + pool.destruct(*ptr); + } +} + +} // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_set_test.cc b/source/blender/blenlib/tests/BLI_set_test.cc index 5a97b2c7999..79439eb9079 100644 --- a/source/blender/blenlib/tests/BLI_set_test.cc +++ b/source/blender/blenlib/tests/BLI_set_test.cc @@ -532,8 +532,14 @@ TEST(set, ForwardIterator) Set<int>::iterator iter1 = set.begin(); int value1 = *iter1; Set<int>::iterator iter2 = iter1++; - EXPECT_EQ(*iter1, value1); - EXPECT_EQ(*iter2, *(++iter1)); + EXPECT_EQ(*iter2, value1); + EXPECT_EQ(*(++iter2), *iter1); + /* Interesting find: On GCC & MSVC this will succeed, as the 2nd argument is evaluated before the + * 1st. On Apple Clang it's the other way around, and the test fails. */ + // EXPECT_EQ(*iter1, *(++iter1)); + Set<int>::iterator iter3 = ++iter1; + /* Check that #iter1 itself changed. */ + EXPECT_EQ(*iter3, *iter1); } TEST(set, GenericAlgorithms) @@ -570,6 +576,19 @@ TEST(set, RemoveDuringIteration) EXPECT_TRUE(set.contains(3)); } +TEST(set, RemoveIf) +{ + Set<int64_t> set; + for (const int64_t i : IndexRange(100)) { + set.add(i * i); + } + set.remove_if([](const int64_t key) { return key > 100; }); + EXPECT_EQ(set.size(), 11); + for (const int64_t i : IndexRange(100)) { + EXPECT_EQ(set.contains(i * i), i <= 10); + } +} + /** * Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot. */ diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc index 0bd34250deb..2dec84c4206 100644 --- a/source/blender/blenlib/tests/BLI_span_test.cc +++ b/source/blender/blenlib/tests/BLI_span_test.cc @@ -237,7 +237,7 @@ TEST(span, SizeInBytes) { std::array<int, 10> a{}; Span<int> a_span(a); - EXPECT_EQ(a_span.size_in_bytes(), static_cast<int64_t>(sizeof(a))); + EXPECT_EQ(a_span.size_in_bytes(), int64_t(sizeof(a))); EXPECT_EQ(a_span.size_in_bytes(), 40); } @@ -280,7 +280,7 @@ TEST(span, ContainsPtr) EXPECT_TRUE(a_span.contains_ptr(&a[0] + 1)); EXPECT_TRUE(a_span.contains_ptr(&a[0] + 2)); EXPECT_FALSE(a_span.contains_ptr(&a[0] + 3)); - int *ptr_before = reinterpret_cast<int *>(reinterpret_cast<uintptr_t>(a.data()) - 1); + int *ptr_before = reinterpret_cast<int *>(uintptr_t(a.data()) - 1); EXPECT_FALSE(a_span.contains_ptr(ptr_before)); EXPECT_FALSE(a_span.contains_ptr(&other)); } diff --git a/source/blender/blenlib/tests/BLI_stack_cxx_test.cc b/source/blender/blenlib/tests/BLI_stack_cxx_test.cc index 0707759666d..13d417d4374 100644 --- a/source/blender/blenlib/tests/BLI_stack_cxx_test.cc +++ b/source/blender/blenlib/tests/BLI_stack_cxx_test.cc @@ -118,19 +118,19 @@ TEST(stack, PushPopMany) Stack<int> stack; for (int i = 0; i < 1000; i++) { stack.push(i); - EXPECT_EQ(stack.size(), static_cast<unsigned int>(i + 1)); + EXPECT_EQ(stack.size(), uint(i + 1)); } for (int i = 999; i > 50; i--) { EXPECT_EQ(stack.pop(), i); - EXPECT_EQ(stack.size(), static_cast<unsigned int>(i)); + EXPECT_EQ(stack.size(), uint(i)); } for (int i = 51; i < 5000; i++) { stack.push(i); - EXPECT_EQ(stack.size(), static_cast<unsigned int>(i + 1)); + EXPECT_EQ(stack.size(), uint(i + 1)); } for (int i = 4999; i >= 0; i--) { EXPECT_EQ(stack.pop(), i); - EXPECT_EQ(stack.size(), static_cast<unsigned int>(i)); + EXPECT_EQ(stack.size(), uint(i)); } } @@ -191,7 +191,7 @@ TEST(stack, OveralignedValues) Stack<AlignedBuffer<1, 512>, 2> stack; for (int i = 0; i < 100; i++) { stack.push({}); - EXPECT_EQ((uintptr_t)&stack.peek() % 512, 0); + EXPECT_EQ(uintptr_t(&stack.peek()) % 512, 0); } } diff --git a/source/blender/blenlib/tests/BLI_stack_test.cc b/source/blender/blenlib/tests/BLI_stack_test.cc index 216c8bd6d55..5f361a78929 100644 --- a/source/blender/blenlib/tests/BLI_stack_test.cc +++ b/source/blender/blenlib/tests/BLI_stack_test.cc @@ -28,7 +28,7 @@ TEST(stack, Empty) TEST(stack, One) { BLI_Stack *stack; - unsigned int in = -1, out = 1; + uint in = -1, out = 1; stack = BLI_stack_new(sizeof(in), __func__); diff --git a/source/blender/blenlib/tests/BLI_string_ref_test.cc b/source/blender/blenlib/tests/BLI_string_ref_test.cc index c3bb53f39d5..478b68a005e 100644 --- a/source/blender/blenlib/tests/BLI_string_ref_test.cc +++ b/source/blender/blenlib/tests/BLI_string_ref_test.cc @@ -357,7 +357,7 @@ TEST(string_ref, Constexpr) constexpr StringRef sref("World"); BLI_STATIC_ASSERT(sref[2] == 'r', ""); BLI_STATIC_ASSERT(sref.size() == 5, ""); - std::array<int, static_cast<std::size_t>(sref.find_first_of('o'))> compiles = {1}; + std::array<int, std::size_t(sref.find_first_of('o'))> compiles = {1}; EXPECT_EQ(compiles[0], 1); } } // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_string_search_test.cc b/source/blender/blenlib/tests/BLI_string_search_test.cc index aa6adae8d76..ab1d073ed33 100644 --- a/source/blender/blenlib/tests/BLI_string_search_test.cc +++ b/source/blender/blenlib/tests/BLI_string_search_test.cc @@ -9,7 +9,7 @@ namespace blender::string_search::tests { /* Right arrow, keep in sync with #UI_MENU_ARROW_SEP in `UI_interface.h`. */ -#define UI_MENU_ARROW_SEP "\xe2\x96\xb6" +#define UI_MENU_ARROW_SEP "\xe2\x96\xb8" TEST(string_search, damerau_levenshtein_distance) { diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index eaaa65dd39f..d726fbccf20 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -174,7 +174,7 @@ TEST(string, StrPartitionEx) /* BLI_str_partition_utf8 */ TEST(string, StrPartitionUtf8) { - const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; + const uint delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; size_t pre_len; @@ -233,7 +233,7 @@ TEST(string, StrPartitionUtf8) /* BLI_str_rpartition_utf8 */ TEST(string, StrRPartitionUtf8) { - const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; + const uint delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; size_t pre_len; @@ -292,7 +292,7 @@ TEST(string, StrRPartitionUtf8) /* BLI_str_partition_ex_utf8 */ TEST(string, StrPartitionExUtf8) { - const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; + const uint delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'}; const char *sep, *suf; size_t pre_len; @@ -515,6 +515,103 @@ TEST(string, StrFormatDecimalUnits) EXPECT_STREQ("-2.1B", size_str); } +/* BLI_str_format_integer_unit */ +TEST(string, StrFormatIntegerUnits) +{ + char size_str[7]; + int size; + + BLI_str_format_integer_unit(size_str, size = 0); + EXPECT_STREQ("0", size_str); + BLI_str_format_integer_unit(size_str, size = 1); + EXPECT_STREQ("1", size_str); + BLI_str_format_integer_unit(size_str, size = 10); + EXPECT_STREQ("10", size_str); + BLI_str_format_integer_unit(size_str, size = 15); + EXPECT_STREQ("15", size_str); + BLI_str_format_integer_unit(size_str, size = 100); + EXPECT_STREQ("100", size_str); + BLI_str_format_integer_unit(size_str, size = 155); + EXPECT_STREQ("155", size_str); + BLI_str_format_integer_unit(size_str, size = 1000); + EXPECT_STREQ("1K", size_str); + BLI_str_format_integer_unit(size_str, size = 1555); + EXPECT_STREQ("1K", size_str); + BLI_str_format_integer_unit(size_str, size = 10000); + EXPECT_STREQ("10K", size_str); + BLI_str_format_integer_unit(size_str, size = 15555); + EXPECT_STREQ("15K", size_str); + BLI_str_format_integer_unit(size_str, size = 100000); + EXPECT_STREQ(".1M", size_str); + BLI_str_format_integer_unit(size_str, size = 155555); + EXPECT_STREQ(".1M", size_str); + BLI_str_format_integer_unit(size_str, size = 1000000); + EXPECT_STREQ("1M", size_str); + BLI_str_format_integer_unit(size_str, size = 1555555); + EXPECT_STREQ("1M", size_str); + BLI_str_format_integer_unit(size_str, size = 2555555); + EXPECT_STREQ("2M", size_str); + BLI_str_format_integer_unit(size_str, size = 10000000); + EXPECT_STREQ("10M", size_str); + BLI_str_format_integer_unit(size_str, size = 15555555); + EXPECT_STREQ("15M", size_str); + BLI_str_format_integer_unit(size_str, size = 100000000); + EXPECT_STREQ(".1B", size_str); + BLI_str_format_integer_unit(size_str, size = 155555555); + EXPECT_STREQ(".1B", size_str); + BLI_str_format_integer_unit(size_str, size = 255555555); + EXPECT_STREQ(".2B", size_str); + BLI_str_format_integer_unit(size_str, size = 1000000000); + EXPECT_STREQ("1B", size_str); + + /* Largest possible value. */ + BLI_str_format_integer_unit(size_str, size = INT32_MAX); + EXPECT_STREQ("2B", size_str); + + BLI_str_format_integer_unit(size_str, size = -0); + EXPECT_STREQ("0", size_str); + BLI_str_format_integer_unit(size_str, size = -1); + EXPECT_STREQ("-1", size_str); + BLI_str_format_integer_unit(size_str, size = -10); + EXPECT_STREQ("-10", size_str); + BLI_str_format_integer_unit(size_str, size = -15); + EXPECT_STREQ("-15", size_str); + BLI_str_format_integer_unit(size_str, size = -100); + EXPECT_STREQ("-100", size_str); + BLI_str_format_integer_unit(size_str, size = -155); + EXPECT_STREQ("-155", size_str); + BLI_str_format_integer_unit(size_str, size = -1000); + EXPECT_STREQ("-1K", size_str); + BLI_str_format_integer_unit(size_str, size = -1555); + EXPECT_STREQ("-1K", size_str); + BLI_str_format_integer_unit(size_str, size = -10000); + EXPECT_STREQ("-10K", size_str); + BLI_str_format_integer_unit(size_str, size = -15555); + EXPECT_STREQ("-15K", size_str); + BLI_str_format_integer_unit(size_str, size = -100000); + EXPECT_STREQ("-.1M", size_str); + BLI_str_format_integer_unit(size_str, size = -155555); + EXPECT_STREQ("-.1M", size_str); + BLI_str_format_integer_unit(size_str, size = -1000000); + EXPECT_STREQ("-1M", size_str); + BLI_str_format_integer_unit(size_str, size = -1555555); + EXPECT_STREQ("-1M", size_str); + BLI_str_format_integer_unit(size_str, size = -10000000); + EXPECT_STREQ("-10M", size_str); + BLI_str_format_integer_unit(size_str, size = -15555555); + EXPECT_STREQ("-15M", size_str); + BLI_str_format_integer_unit(size_str, size = -100000000); + EXPECT_STREQ("-.1B", size_str); + BLI_str_format_integer_unit(size_str, size = -155555555); + EXPECT_STREQ("-.1B", size_str); + BLI_str_format_integer_unit(size_str, size = -1000000000); + EXPECT_STREQ("-1B", size_str); + + /* Smallest possible value. */ + BLI_str_format_integer_unit(size_str, size = -INT32_MAX); + EXPECT_STREQ("-2B", size_str); +} + struct WordInfo { WordInfo() = default; WordInfo(int start, int end) : start(start), end(end) diff --git a/source/blender/blenlib/tests/BLI_string_utf8_test.cc b/source/blender/blenlib/tests/BLI_string_utf8_test.cc index 2da439dad18..d66bade40ed 100644 --- a/source/blender/blenlib/tests/BLI_string_utf8_test.cc +++ b/source/blender/blenlib/tests/BLI_string_utf8_test.cc @@ -4,6 +4,7 @@ #include "BLI_rand.h" #include "BLI_string.h" +#include "BLI_string_cursor_utf8.h" #include "BLI_string_utf8.h" #include "BLI_utildefines.h" @@ -274,7 +275,7 @@ TEST(string, Utf8InvalidBytes) for (int i = 0; utf8_invalid_tests[i][0] != nullptr; i++) { const char *tst = utf8_invalid_tests[i][0]; const char *tst_stripped = utf8_invalid_tests[i][1]; - const int errors_num = (int)utf8_invalid_tests[i][2][0]; + const int errors_num = int(utf8_invalid_tests[i][2][0]); char buff[80]; memcpy(buff, tst, sizeof(buff)); @@ -352,13 +353,13 @@ template<size_t Size> void utf8_as_char32_test_at_buffer_size() /* Offset trailing bytes up and down in steps of 1, 2, 4 .. etc. */ if (Size > 1) { for (int mul = 1; mul < 256; mul *= 2) { - for (int ofs = 1; ofs < (int)Size; ofs++) { - utf8_src[ofs] = (char)(i + (ofs * mul)); + for (int ofs = 1; ofs < int(Size); ofs++) { + utf8_src[ofs] = char(i + (ofs * mul)); } utf8_as_char32_test_compare<Size>(utf8_src); - for (int ofs = 1; ofs < (int)Size; ofs++) { - utf8_src[ofs] = (char)(i - (ofs * mul)); + for (int ofs = 1; ofs < int(Size); ofs++) { + utf8_src[ofs] = char(i - (ofs * mul)); } utf8_as_char32_test_compare<Size>(utf8_src); } @@ -393,3 +394,484 @@ TEST(string, Utf8AsUnicodeStep) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf32_empty + * \{ */ + +TEST(string, StrCursorStepNextUtf32Empty) +{ + const char32_t empty[] = U""; + const size_t len = 0; + int pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(empty, len, &pos)); + pos = 1; + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(empty, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf32_single + * \{ */ + +TEST(string, StrCursorStepNextUtf32Single) + +{ + const char32_t single[] = U"0"; + const size_t len = 1; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(single, len, &pos) && pos == 1); + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(single, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf32_simple + * \{ */ + +TEST(string, StrCursorStepNextUtf32Simple) +{ + const char32_t simple[] = U"012"; + const size_t len = 3; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(simple, len, &pos) && pos == 1); + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(simple, len, &pos) && pos == 2); + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(simple, len - 1, &pos)); + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(simple, len, &pos) && pos == 3); + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(simple, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf32_allcombining + * \{ */ + +TEST(string, StrCursorStepNextUtf32AllCombining) +{ + const char32_t allcombining[] = U"\u0300\u0300\u0300"; + const size_t len = 3; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos) && pos == 3); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos) && pos == 3); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos) && pos == 3); + pos = 3; + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(allcombining, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf32_complex + * \{ */ + +TEST(string, StrCursorStepNextUtf32Complex) +{ + /* Combining character, "A", two combining characters, "B".*/ + const char32_t complex[] = U"\u0300\u0041\u0300\u0320\u0042"; + const size_t len = 5; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 1); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 4); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 4); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 4); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(complex, len, &pos) && pos == 5); + pos = 5; + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(complex, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf32_invalid + * \{ */ + +TEST(string, StrCursorStepNextUtf32Invalid) +{ + /* Latin1 "À", tab, carriage return, linefeed, separated by combining characters.*/ + const char32_t invalid[] = U"\u00C0\u0300\u0009\u0300\u000D\u0300\u000A\u0300"; + const size_t len = 8; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 2); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 2); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 4); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 4); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 6); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 6); + pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 8); + pos = 7; + EXPECT_TRUE(BLI_str_cursor_step_next_utf32(invalid, len, &pos) && pos == 8); + pos = 8; + EXPECT_FALSE(BLI_str_cursor_step_next_utf32(invalid, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf32_empty + * \{ */ + +TEST(string, StrCursorStepPrevUtf32Empty) +{ + const char32_t emtpy[] = U""; + const size_t len = 0; + int pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(emtpy, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf32_single + * \{ */ + +TEST(string, StrCursorStepPrevUtf32Single) +{ + const char32_t single[] = U"0"; + const size_t len = 1; + int pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(single, len, &pos) && pos == 0); + EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(single, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf32_simple + * \{ */ + +TEST(string, StrCursorStepPrevUtf32Simple) +{ + const char32_t simple[] = U"012"; + const size_t len = 3; + int pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(simple, len, &pos) && pos == 2); + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(simple, len, &pos) && pos == 1); + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(simple, len, &pos) && pos == 0); + EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(simple, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf32_allcombining + * \{ */ + +TEST(string, StrCursorStepPrevUtf32AllCombining) +{ + const char32_t allcombining[] = U"\u0300\u0300\u0300"; + const size_t len = 3; + int pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos) && pos == 0); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos) && pos == 0); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos) && pos == 0); + pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(allcombining, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf32_complex + * \{ */ + +TEST(string, StrCursorStepPrevUtf32Complex) +{ + /* Combining character, "A", two combining characters, "B".*/ + const char32_t complex[] = U"\u0300\u0041\u0300\u0320\u0042"; + const size_t len = 5; + int pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 4); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 1); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 1); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 1); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(complex, len, &pos) && pos == 0); + pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(complex, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf32_invalid + * \{ */ + +TEST(string, StrCursorStepPrevUtf32Invalid) +{ + /* Latin1 "À", tab, carriage return, linefeed, separated by combining characters.*/ + const char32_t invalid[] = U"\u00C0\u0300\u0009\u0300\u000D\u0300\u000A\u0300"; + const size_t len = 8; + int pos = 8; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 6); + pos = 7; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 6); + pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 4); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 4); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 2); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 2); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 0); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos) && pos == 0); + pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf32(invalid, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf8_empty + * \{ */ +TEST(string, StrCursorStepNextUtf8Empty) +{ + const char empty[] = ""; + const size_t len = 0; + int pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(empty, len, &pos)); + pos = 1; + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(empty, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf8_single + * \{ */ +TEST(string, StrCursorStepNextUtf8Single) +{ + const char single[] = "0"; + const size_t len = 1; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(single, len, &pos) && pos == 1); + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(single, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf8_simple + * \{ */ + +TEST(string, StrCursorStepNextUtf8Simple) +{ + const char simple[] = "012"; + const size_t len = 3; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(simple, len, &pos) && pos == 1); + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(simple, len, &pos) && pos == 2); + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(simple, len - 1, &pos)); + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(simple, len, &pos) && pos == 3); + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(simple, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf8_allcombining + * \{ */ + +TEST(string, StrCursorStepNextUtf8AllCombining) +{ + const char allcombining[] = "\xCC\x80\xCC\x80\xCC\x80"; + const size_t len = 6; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos) && pos == 6); + pos = 6; + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(allcombining, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf8_complex + * \{ */ + +TEST(string, StrCursorStepNextUtf8AllComplex) +{ + /* Combining character, "A", "©", two combining characters, "B".*/ + const char complex[] = "\xCC\x80\x41\xC2\xA9\xCC\x80\xCC\xA0\x42"; + const size_t len = 10; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 2); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 2); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 3); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9); + pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9); + pos = 7; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9); + pos = 8; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 9); + pos = 9; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(complex, len, &pos) && pos == 10); + pos = 10; + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(complex, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_next_utf8_invalid + * \{ */ + +TEST(string, StrCursorStepNextUtf8Invalid) +{ + /* Latin1 "À", combining, tab, carriage return, linefeed, combining.*/ + const char invalid[] = "\xC0\xCC\x80\x09\x0D\x0A\xCC\x80"; + const size_t len = 8; + int pos = 0; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 7; + EXPECT_TRUE(BLI_str_cursor_step_next_utf8(invalid, len, &pos) && pos == 8); + pos = 8; + EXPECT_FALSE(BLI_str_cursor_step_next_utf8(invalid, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf8_empty + * \{ */ + +TEST(string, StrCursorStepPrevUtf8Empty) +{ + const char empty[] = ""; + const size_t len = 0; + int pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(empty, len, &pos)); + pos = 1; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(empty, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf8_single + * \{ */ + +TEST(string, StrCursorStepPrevUtf8Single) +{ + const char single[] = "0"; + const size_t len = 1; + int pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(single, len, &pos) && pos == 0); + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(single, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf8_single + * \{ */ + +TEST(string, StrCursorStepPrevUtf8Simple) +{ + const char simple[] = "012"; + const size_t len = 3; + int pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(simple, len, &pos) && pos == 2); + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(simple, len, &pos) && pos == 1); + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(simple, len, &pos) && pos == 0); + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(simple, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf8_allcombining + * \{ */ + +TEST(string, StrCursorStepPrevUtf8AllCombining) +{ + const char allcombining[] = "\xCC\x80\xCC\x80\xCC\x80"; + const size_t len = 6; + int pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos) && pos == 0); + pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(allcombining, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf8_complex + * \{ */ + +TEST(string, StrCursorStepPrevUtf8Complex) +{ + /* Combining character, "A", "©", two combining characters, "B".*/ + const char complex[] = "\xCC\x80\x41\xC2\xA9\xCC\x80\xCC\xA0\x42"; + const size_t len = 10; + int pos = 10; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 9); + pos = 9; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3); + pos = 8; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3); + pos = 7; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3); + pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 3); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 2); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 0); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(complex, len, &pos) && pos == 0); + pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(complex, len, &pos)); +} + +/* -------------------------------------------------------------------- */ +/** \name Test #BLI_str_cursor_step_prev_utf8_invalid + * \{ */ + +TEST(string, StrCursorStepPrevUtf8Invalid) +{ + /* Latin1 "À", combining, tab, carriage return, linefeed, combining.*/ + const char invalid[] = "\xC0\xCC\x80\x09\x0D\x0A\xCC\x80"; + const size_t len = 8; + int pos = 8; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 5); + pos = 7; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 5); + pos = 6; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 5); + pos = 5; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 4); + pos = 4; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 3); + pos = 3; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 0); + pos = 2; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 0); + pos = 1; + EXPECT_TRUE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos) && pos == 0); + pos = 0; + EXPECT_FALSE(BLI_str_cursor_step_prev_utf8(invalid, len, &pos)); +} + +/** \} */ diff --git a/source/blender/blenlib/tests/BLI_task_test.cc b/source/blender/blenlib/tests/BLI_task_test.cc index a933d45e7cd..63bb767466f 100644 --- a/source/blender/blenlib/tests/BLI_task_test.cc +++ b/source/blender/blenlib/tests/BLI_task_test.cc @@ -27,7 +27,7 @@ static void task_range_iter_func(void *userdata, int index, const TaskParallelTL // printf("%d, %d, %d\n", index, data[index], *((int *)tls->userdata_chunk)); } -static void task_range_iter_reduce_func(const void *__restrict UNUSED(userdata), +static void task_range_iter_reduce_func(const void *__restrict /*userdata*/, void *__restrict join_v, void *__restrict userdata_chunk) { @@ -71,7 +71,7 @@ TEST(task, RangeIter) static void task_mempool_iter_func(void *userdata, MempoolIterData *item, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { int *data = (int *)item; int *count = (int *)userdata; @@ -147,7 +147,7 @@ using TaskMemPool_Chunk = struct TaskMemPool_Chunk { ListBase *accumulate_items; }; -static void task_mempool_iter_tls_func(void *UNUSED(userdata), +static void task_mempool_iter_tls_func(void * /*userdata*/, MempoolIterData *item, const TaskParallelTLS *__restrict tls) { @@ -165,7 +165,7 @@ static void task_mempool_iter_tls_func(void *UNUSED(userdata), BLI_addtail(task_data->accumulate_items, BLI_genericNodeN(data)); } -static void task_mempool_iter_tls_reduce(const void *__restrict UNUSED(userdata), +static void task_mempool_iter_tls_reduce(const void *__restrict /*userdata*/, void *__restrict chunk_join, void *__restrict chunk) { @@ -180,8 +180,7 @@ static void task_mempool_iter_tls_reduce(const void *__restrict UNUSED(userdata) } } -static void task_mempool_iter_tls_free(const void *UNUSED(userdata), - void *__restrict userdata_chunk) +static void task_mempool_iter_tls_free(const void * /*userdata*/, void *__restrict userdata_chunk) { TaskMemPool_Chunk *task_data = (TaskMemPool_Chunk *)userdata_chunk; MEM_freeN(task_data->accumulate_items); @@ -240,7 +239,7 @@ TEST(task, MempoolIterTLS) static void task_listbase_iter_func(void *userdata, void *item, int index, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { LinkData *data = (LinkData *)item; int *count = (int *)userdata; diff --git a/source/blender/blenlib/tests/BLI_vector_set_test.cc b/source/blender/blenlib/tests/BLI_vector_set_test.cc index 34685c76e00..c3fbac1200a 100644 --- a/source/blender/blenlib/tests/BLI_vector_set_test.cc +++ b/source/blender/blenlib/tests/BLI_vector_set_test.cc @@ -128,6 +128,19 @@ TEST(vector_set, RemoveContained) EXPECT_EQ(set.size(), 0); } +TEST(vector_set, RemoveIf) +{ + VectorSet<int64_t> set; + for (const int64_t i : IndexRange(100)) { + set.add(i * i); + } + set.remove_if([](const int64_t key) { return key % 2 == 0; }); + EXPECT_EQ(set.size(), 50); + for (const int64_t i : IndexRange(100)) { + EXPECT_EQ(set.contains(i * i), i % 2 == 1); + } +} + TEST(vector_set, AddMultipleTimes) { VectorSet<int> set; diff --git a/source/blender/blenlib/tests/BLI_vector_test.cc b/source/blender/blenlib/tests/BLI_vector_test.cc index 3a12fe14de3..29bf6c0cfb1 100644 --- a/source/blender/blenlib/tests/BLI_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_vector_test.cc @@ -317,7 +317,7 @@ TEST(vector, BecomeLarge) } EXPECT_EQ(vec.size(), 100); for (int i = 0; i < 100; i++) { - EXPECT_EQ(vec[i], static_cast<int>(i * 5)); + EXPECT_EQ(vec[i], int(i * 5)); } } @@ -416,7 +416,16 @@ TEST(vector, Remove) vec.remove(1); EXPECT_TRUE(std::equal(vec.begin(), vec.end(), Span<int>({2}).begin())); vec.remove(0); - EXPECT_TRUE(std::equal(vec.begin(), vec.end(), Span<int>({}).begin())); + EXPECT_EQ(vec.begin(), vec.end()); +} + +TEST(vector, RemoveIf) +{ + Vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8}; + vec.remove_if([](const int x) { return x % 2 == 0; }); + const Vector<int> expected_vec = {1, 3, 5, 7}; + EXPECT_EQ(vec.size(), expected_vec.size()); + EXPECT_EQ_ARRAY(vec.data(), expected_vec.data(), size_t(vec.size())); } TEST(vector, ExtendSmallVector) @@ -497,11 +506,11 @@ class TypeConstructMock { { } - TypeConstructMock(const TypeConstructMock &UNUSED(other)) : copy_constructed(true) + TypeConstructMock(const TypeConstructMock & /*other*/) : copy_constructed(true) { } - TypeConstructMock(TypeConstructMock &&UNUSED(other)) noexcept : move_constructed(true) + TypeConstructMock(TypeConstructMock && /*other*/) noexcept : move_constructed(true) { } @@ -635,7 +644,7 @@ TEST(vector, OveralignedValues) Vector<AlignedBuffer<1, 512>, 2> vec; for (int i = 0; i < 100; i++) { vec.append({}); - EXPECT_EQ((uintptr_t)&vec.last() % 512, 0); + EXPECT_EQ(uintptr_t(&vec.last()) % 512, 0); } } diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc index 14f5480f751..6d6580c52d4 100644 --- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc +++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc @@ -98,7 +98,7 @@ TEST(virtual_array, VectorSet) TEST(virtual_array, Func) { - auto func = [](int64_t index) { return (int)(index * index); }; + auto func = [](int64_t index) { return int(index * index); }; VArray<int> varray = VArray<int>::ForFunc(10, func); EXPECT_EQ(varray.size(), 10); EXPECT_EQ(varray[0], 0); @@ -108,7 +108,7 @@ TEST(virtual_array, Func) TEST(virtual_array, AsSpan) { - auto func = [](int64_t index) { return (int)(10 * index); }; + auto func = [](int64_t index) { return int(10 * index); }; VArray<int> func_varray = VArray<int>::ForFunc(10, func); VArraySpan span_varray{func_varray}; EXPECT_EQ(span_varray.size(), 10); @@ -210,7 +210,7 @@ TEST(virtual_array, MaterializeCompressed) EXPECT_EQ(compressed_array[2], 4); } { - VArray<int> varray = VArray<int>::ForFunc(10, [](const int64_t i) { return (int)(i * i); }); + VArray<int> varray = VArray<int>::ForFunc(10, [](const int64_t i) { return int(i * i); }); std::array<int, 3> compressed_array; varray.materialize_compressed({5, 7, 8}, compressed_array); EXPECT_EQ(compressed_array[0], 25); diff --git a/source/blender/blenlib/tests/performance/BLI_ghash_performance_test.cc b/source/blender/blenlib/tests/performance/BLI_ghash_performance_test.cc index 09bb1e7239f..efcf8dea922 100644 --- a/source/blender/blenlib/tests/performance/BLI_ghash_performance_test.cc +++ b/source/blender/blenlib/tests/performance/BLI_ghash_performance_test.cc @@ -177,12 +177,12 @@ TEST(ghash, TextMurmur2a) /* Int: uniform 100M first integers. */ -static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int count) +static void int_ghash_tests(GHash *ghash, const char *id, const uint count) { printf("\n========== STARTING %s ==========\n", id); { - unsigned int i = count; + uint i = count; TIMEIT_START(int_insert); @@ -200,7 +200,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int cou PRINTF_GHASH_STATS(ghash); { - unsigned int i = count; + uint i = count; TIMEIT_START(int_lookup); @@ -266,13 +266,13 @@ TEST(ghash, IntMurmur2a100000000) /* Int: random 50M integers. */ -static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int count) +static void randint_ghash_tests(GHash *ghash, const char *id, const uint count) { printf("\n========== STARTING %s ==========\n", id); - unsigned int *data = (unsigned int *)MEM_mallocN(sizeof(*data) * (size_t)count, __func__); - unsigned int *dt; - unsigned int i; + uint *data = (uint *)MEM_mallocN(sizeof(*data) * size_t(count), __func__); + uint *dt; + uint i; { RNG *rng = BLI_rng_new(1); @@ -347,7 +347,7 @@ TEST(ghash, IntRandMurmur2a50000000) } #endif -static unsigned int ghashutil_tests_nohash_p(const void *p) +static uint ghashutil_tests_nohash_p(const void *p) { return POINTER_AS_UINT(p); } @@ -375,14 +375,14 @@ TEST(ghash, Int4NoHash50000000) /* Int_v4: 20M of randomly-generated integer vectors. */ -static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int count) +static void int4_ghash_tests(GHash *ghash, const char *id, const uint count) { printf("\n========== STARTING %s ==========\n", id); - void *data_v = MEM_mallocN(sizeof(unsigned int[4]) * (size_t)count, __func__); - unsigned int(*data)[4] = (unsigned int(*)[4])data_v; - unsigned int(*dt)[4]; - unsigned int i, j; + void *data_v = MEM_mallocN(sizeof(uint[4]) * size_t(count), __func__); + uint(*data)[4] = (uint(*)[4])data_v; + uint(*dt)[4]; + uint i, j; { RNG *rng = BLI_rng_new(1); @@ -483,11 +483,11 @@ TEST(ghash, Int2NoHash50000000) /* MultiSmall: create and manipulate a lot of very small ghash's * (90% < 10 items, 9% < 100 items, 1% < 1000 items). */ -static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const unsigned int count) +static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const uint count) { - unsigned int *data = (unsigned int *)MEM_mallocN(sizeof(*data) * (size_t)count, __func__); - unsigned int *dt; - unsigned int i; + uint *data = (uint *)MEM_mallocN(sizeof(*data) * size_t(count), __func__); + uint *dt; + uint i; for (i = count, dt = data; i--; dt++) { *dt = BLI_rng_get_uint(rng); @@ -510,7 +510,7 @@ static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const unsigned i MEM_freeN(data); } -static void multi_small_ghash_tests(GHash *ghash, const char *id, const unsigned int count) +static void multi_small_ghash_tests(GHash *ghash, const char *id, const uint count) { printf("\n========== STARTING %s ==========\n", id); @@ -518,7 +518,7 @@ static void multi_small_ghash_tests(GHash *ghash, const char *id, const unsigned TIMEIT_START(multi_small_ghash); - unsigned int i = count; + uint i = count; while (i--) { const int count = 1 + (BLI_rng_get_int(rng) % TESTCASE_SIZE_SMALL) * (!(i % 100) ? 100 : (!(i % 10) ? 10 : 1)); @@ -529,7 +529,7 @@ static void multi_small_ghash_tests(GHash *ghash, const char *id, const unsigned TIMEIT_START(multi_small2_ghash); - unsigned int i = count; + uint i = count; while (i--) { const int count = 1 + (BLI_rng_get_int(rng) % TESTCASE_SIZE_SMALL) / 2 * (!(i % 100) ? 100 : (!(i % 10) ? 10 : 1)); diff --git a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc index a86e9b0b86d..68fdf4031ab 100644 --- a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc +++ b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc @@ -36,10 +36,10 @@ static uint gen_pseudo_random_number(uint num) /* *** Parallel iterations over double-linked list items. *** */ -static void task_listbase_light_iter_func(void *UNUSED(userdata), +static void task_listbase_light_iter_func(void * /*userdata*/, void *item, int index, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { LinkData *data = (LinkData *)item; @@ -50,7 +50,7 @@ static void task_listbase_light_iter_func(void *UNUSED(userdata), static void task_listbase_light_membarrier_iter_func(void *userdata, void *item, int index, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { LinkData *data = (LinkData *)item; @@ -60,16 +60,16 @@ static void task_listbase_light_membarrier_iter_func(void *userdata, atomic_sub_and_fetch_uint32((uint32_t *)count, 1); } -static void task_listbase_heavy_iter_func(void *UNUSED(userdata), +static void task_listbase_heavy_iter_func(void * /*userdata*/, void *item, int index, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { LinkData *data = (LinkData *)item; /* 'Random' number of iterations. */ - const uint num = gen_pseudo_random_number((uint)index); + const uint num = gen_pseudo_random_number(uint(index)); for (uint i = 0; i < num; i++) { data->data = POINTER_FROM_INT(POINTER_AS_INT(data->data) + ((i % 2) ? -index : index)); @@ -79,14 +79,14 @@ static void task_listbase_heavy_iter_func(void *UNUSED(userdata), static void task_listbase_heavy_membarrier_iter_func(void *userdata, void *item, int index, - const TaskParallelTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict /*tls*/) { LinkData *data = (LinkData *)item; int *count = (int *)userdata; /* 'Random' number of iterations. */ - const uint num = gen_pseudo_random_number((uint)index); + const uint num = gen_pseudo_random_number(uint(index)); for (uint i = 0; i < num; i++) { data->data = POINTER_FROM_INT(POINTER_AS_INT(data->data) + ((i % 2) ? -index : index)); diff --git a/source/blender/blenlib/tests/performance/CMakeLists.txt b/source/blender/blenlib/tests/performance/CMakeLists.txt index c4f03255a11..aa26f796e0d 100644 --- a/source/blender/blenlib/tests/performance/CMakeLists.txt +++ b/source/blender/blenlib/tests/performance/CMakeLists.txt @@ -4,9 +4,13 @@ set(INC . .. + ../.. + ../../../makesdna + ../../../../../intern/atomic + ../../../../../intern/guardedalloc ) include_directories(${INC}) -BLENDER_TEST_PERFORMANCE(BLI_ghash_performance "bf_blenlib") -BLENDER_TEST_PERFORMANCE(BLI_task_performance "bf_blenlib") +blender_test_performance(BLI_ghash_performance "bf_blenlib") +blender_test_performance(BLI_task_performance "bf_blenlib") |