GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/packed_arrays.cpp
Date: 2026-09-07 02:37:58
Exec Total Coverage
Lines: 90 134 67.2%
Functions: 8 10 80.0%
Branches: 27 158 17.1%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #include <geogram/basic/packed_arrays.h>
41 #include <geogram/basic/logger.h>
42 #include <geogram/basic/string.h>
43
44 namespace {
45
46 using namespace GEO;
47
48 /**
49 * \brief Computes a percentage of a reference value
50 * \param[in] num the value to compute the percentage of
51 * \param[in] denom the reference value
52 * \return a formatted string that contains the \p num and its percentage
53 * of \p denom
54 */
55 std::string percent_str(index_t num, index_t denom) {
56 if(denom == 0) {
57 return String::to_string(num);
58 }
59 double x = double(num) / double(denom) * 100.0;
60 return String::to_string(num) + "(" + String::to_string(x) + "%)";
61 }
62 }
63
64 namespace GEO {
65
66 76 PackedArrays::PackedArrays() {
67 76 nb_arrays_ = 0;
68 76 Z1_block_size_ = 0;
69 76 Z1_stride_ = 0;
70 76 Z1_ = nullptr;
71 76 ZV_ = nullptr;
72 76 thread_safe_ = false;
73 76 }
74
75 void PackedArrays::show_stats() {
76 index_t nb_items_in_Z1 = 0;
77 index_t nb_items_in_ZV = 0;
78 index_t nb_arrays_in_ZV = 0;
79 index_t nb_items = 0;
80 for(index_t i = 0; i < nb_arrays_; i++) {
81 index_t sz = array_size(i);
82 nb_items += sz;
83 if(sz > Z1_block_size_) {
84 nb_items_in_ZV += (sz - Z1_block_size_);
85 nb_arrays_in_ZV++;
86 }
87 nb_items_in_Z1 += std::min(sz, Z1_block_size_);
88 }
89
90 Logger::out("PArrays")
91 << "stats (nb_arrays=" << nb_arrays_
92 << ", Z1 block size=" << Z1_block_size_ << ") "
93 << (static_mode() ? "static" : "dynamic")
94 << std::endl;
95
96 index_t Z1_total = nb_arrays_ * Z1_block_size_;
97
98 Logger::out("PArrays")
99 << "Z1 filling:"
100 << percent_str(nb_items_in_Z1, Z1_total) << std::endl;
101
102 if(!static_mode()) {
103 Logger::out("PArrays")
104 << "arrays in ZV:" << percent_str(nb_arrays_in_ZV, nb_arrays_)
105 << std::endl;
106 Logger::out("PArrays")
107 << "items in Z1:" << percent_str(nb_items_in_Z1, nb_items)
108 << std::endl;
109 Logger::out("PArrays")
110 << "items in ZV:" << percent_str(nb_items_in_ZV, nb_items)
111 << std::endl;
112 }
113 }
114
115 76 PackedArrays::~PackedArrays() {
116 76 clear();
117 76 }
118
119 140 void PackedArrays::clear() {
120
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 76 times.
140 if(ZV_ != nullptr) {
121
2/2
✓ Branch 0 taken 68860 times.
✓ Branch 1 taken 64 times.
68924 for(index_t i = 0; i < nb_arrays_; i++) {
122 68860 free(ZV_[i]);
123 }
124 64 free(ZV_);
125 64 ZV_ = nullptr;
126 }
127 140 nb_arrays_ = 0;
128 140 Z1_block_size_ = 0;
129 140 Z1_stride_ = 0;
130 140 free(Z1_);
131 140 Z1_ = nullptr;
132 140 }
133
134 65 void PackedArrays::set_thread_safe(bool x) {
135 65 thread_safe_ = x;
136
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 if(x) {
137 65 Z1_spinlocks_.resize(nb_arrays_);
138 } else {
139 Z1_spinlocks_.clear();
140 }
141 65 }
142
143 64 void PackedArrays::init(
144 index_t nb_arrays,
145 index_t Z1_block_size,
146 bool static_mode
147 ) {
148 64 clear();
149 64 nb_arrays_ = nb_arrays;
150 64 Z1_block_size_ = Z1_block_size;
151 64 Z1_stride_ = Z1_block_size_ + 1; // +1 for storing array size.
152 64 Z1_ = (index_t*) calloc(
153 64 nb_arrays_, sizeof(index_t) * Z1_stride_
154 );
155
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if(!static_mode) {
156 64 ZV_ = (index_t**) calloc(
157 64 nb_arrays_, sizeof(index_t*)
158 );
159 }
160
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if(thread_safe_) {
161 64 Z1_spinlocks_.resize(nb_arrays_);
162 }
163 64 }
164
165 3972079 void PackedArrays::get_array(
166 index_t array_index, index_t* array, bool lock
167 ) const {
168
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3972079 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3972079 geo_debug_assert(array_index < nb_arrays_);
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3972079 times.
3972079 if(lock) {
170 lock_array(array_index);
171 }
172 3972079 const index_t* array_base = Z1_ + array_index * Z1_stride_;
173 3972079 index_t array_size = *array_base;
174 3972079 index_t nb = array_size;
175 3972079 array_base++;
176 3972079 index_t nb_in_block = std::min(nb, Z1_block_size_);
177 3972079 Memory::copy(array, array_base, sizeof(index_t) * nb_in_block);
178
2/2
✓ Branch 0 taken 644443 times.
✓ Branch 1 taken 3327636 times.
3972079 if(nb > nb_in_block) {
179 644443 nb -= nb_in_block;
180 644443 array += nb_in_block;
181 644443 array_base = ZV_[array_index];
182 644443 Memory::copy(array, array_base, sizeof(index_t) * nb);
183 }
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3972079 times.
3972079 if(lock) {
185 unlock_array(array_index);
186 }
187 3972079 }
188
189 1287599 void PackedArrays::set_array(
190 index_t array_index,
191 index_t array_size, const index_t* array,
192 bool lock
193 ) {
194
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1287599 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1287599 geo_debug_assert(array_index < nb_arrays_);
195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1287599 times.
1287599 if(lock) {
196 lock_array(array_index);
197 }
198 1287599 index_t* array_base = Z1_ + array_index * Z1_stride_;
199 1287599 index_t old_array_size = *array_base;
200 1287599 array_base++;
201
2/2
✓ Branch 0 taken 33027 times.
✓ Branch 1 taken 1254572 times.
1287599 if(array_size != old_array_size) {
202
1/2
✓ Branch 1 taken 33027 times.
✗ Branch 2 not taken.
33027 resize_array(array_index, array_size, false);
203 }
204 1287599 index_t nb = array_size;
205 1287599 index_t nb_in_block = std::min(nb, Z1_block_size_);
206 1287599 Memory::copy(array_base, array, sizeof(index_t) * nb_in_block);
207
2/2
✓ Branch 0 taken 67006 times.
✓ Branch 1 taken 1220593 times.
1287599 if(nb > nb_in_block) {
208 67006 nb -= nb_in_block;
209 67006 array += nb_in_block;
210 67006 array_base = ZV_[array_index];
211 67006 Memory::copy(array_base, array, sizeof(index_t) * nb);
212 }
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1287599 times.
1287599 if(lock) {
214 unlock_array(array_index);
215 }
216 1287599 }
217
218 101887 void PackedArrays::resize_array(
219 index_t array_index, index_t array_size, bool lock
220 ) {
221
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 101887 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
101887 geo_debug_assert(array_index < nb_arrays_);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101887 times.
101887 if(lock) {
223 lock_array(array_index);
224 }
225 101887 index_t* array_base = Z1_ + array_index * Z1_stride_;
226 101887 index_t old_array_size = *array_base;
227
1/2
✓ Branch 0 taken 101887 times.
✗ Branch 1 not taken.
101887 if(old_array_size != array_size) {
228 101887 *array_base = array_size;
229
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 101887 times.
101887 if(static_mode()) {
230 geo_assert(array_size <= Z1_block_size_);
231 } else {
232 69048 index_t nb_in_ZV =
233
2/2
✓ Branch 0 taken 32839 times.
✓ Branch 1 taken 69048 times.
101887 (array_size > Z1_block_size_) ?
234 32839 array_size - Z1_block_size_ : 0;
235 101887 ZV_[array_index] = (index_t*) realloc(
236 101887 ZV_[array_index], sizeof(index_t) * nb_in_ZV
237 );
238 }
239 }
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101887 times.
101887 if(lock) {
241 unlock_array(array_index);
242 }
243 101887 }
244 }
245