GCC Code Coverage Report


Directory: ./
File: numerics/expansion_nt.cpp
Date: 2026-09-27 03:24:14
Exec Total Coverage
Lines: 53 140 37.9%
Functions: 7 17 41.2%
Branches: 49 276 17.8%

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/numerics/expansion_nt.h>
41
42 namespace GEO {
43
44 ✗ expansion_nt& expansion_nt::operator+= (const expansion_nt& rhs) {
45 ✗ index_t e_capa = expansion::sum_capacity(rep(), rhs.rep());
46 ✗ expansion* e = expansion::new_expansion_on_heap(e_capa);
47 ✗ e->assign_sum(rep(), rhs.rep());
48 ✗ cleanup();
49 ✗ rep_ = e;
50 ✗ return *this;
51 }
52
53 ✗ expansion_nt& expansion_nt::operator+= (double rhs) {
54 ✗ index_t e_capa = expansion::sum_capacity(rep(), rhs);
55
56 // TODO: optimized in-place version to be used
57 // if(!shared() && e_capa < rep().capacity())
58
59 ✗ expansion* e = expansion::new_expansion_on_heap(e_capa);
60 ✗ e->assign_sum(rep(), rhs);
61 ✗ cleanup();
62 ✗ rep_ = e;
63 ✗ return *this;
64 }
65
66 ✗ expansion_nt& expansion_nt::operator-= (const expansion_nt& rhs) {
67 ✗ index_t e_capa = expansion::diff_capacity(rep(), rhs.rep());
68 ✗ expansion* e = expansion::new_expansion_on_heap(e_capa);
69 ✗ e->assign_diff(rep(), rhs.rep());
70 ✗ cleanup();
71 ✗ rep_ = e;
72 ✗ return *this;
73 }
74
75 ✗ expansion_nt& expansion_nt::operator-= (double rhs) {
76 ✗ index_t e_capa = expansion::diff_capacity(rep(), rhs);
77
78 // TODO: optimized in-place version to be used
79 // if(!shared() && e_capa < rep().capacity())
80
81 ✗ expansion* e = expansion::new_expansion_on_heap(e_capa);
82 ✗ e->assign_diff(rep(), rhs);
83 ✗ cleanup();
84 ✗ rep_ = e;
85 ✗ return *this;
86 }
87
88 ✗ expansion_nt& expansion_nt::operator*= (const expansion_nt& rhs) {
89 ✗ index_t e_capa = expansion::product_capacity(rep(), rhs.rep());
90 ✗ expansion* e = expansion::new_expansion_on_heap(e_capa);
91 ✗ e->assign_product(rep(), rhs.rep());
92 ✗ cleanup();
93 ✗ rep_ = e;
94 ✗ return *this;
95 }
96
97 ✗ expansion_nt& expansion_nt::operator*= (double rhs) {
98 ✗ index_t e_capa = expansion::product_capacity(rep(), rhs);
99
100 // TODO: optimized in-place version to be used
101 // if(!shared() && e_capa < rep().capacity())
102
103 ✗ expansion* e = expansion::new_expansion_on_heap(e_capa);
104 ✗ e->assign_product(rep(), rhs);
105 ✗ cleanup();
106 ✗ rep_ = e;
107 ✗ return *this;
108 }
109
110 /************************************************************************/
111
112 437531 expansion_nt expansion_nt::operator+ (const expansion_nt& rhs) const {
113 437531 expansion* e = expansion::new_expansion_on_heap(
114 expansion::sum_capacity(rep(), rhs.rep())
115 );
116 437531 e->assign_sum(rep(), rhs.rep());
117 437531 return expansion_nt(e);
118 }
119
120 2004149 expansion_nt expansion_nt::operator- (const expansion_nt& rhs) const {
121 2004149 expansion* e = expansion::new_expansion_on_heap(
122 expansion::diff_capacity(rep(), rhs.rep())
123 );
124 2004149 e->assign_diff(rep(), rhs.rep());
125 2004149 return expansion_nt(e);
126 }
127
128 2563050 expansion_nt expansion_nt::operator* (const expansion_nt& rhs) const {
129 2563050 expansion* e = expansion::new_expansion_on_heap(
130 expansion::product_capacity(rep(), rhs.rep())
131 );
132 2563050 e->assign_product(rep(), rhs.rep());
133 2563050 return expansion_nt(e);
134 }
135
136 ✗ expansion_nt expansion_nt::operator+ (double rhs) const {
137 ✗ expansion* e = expansion::new_expansion_on_heap(
138 expansion::sum_capacity(rep(), rhs)
139 );
140 ✗ e->assign_sum(rep(), rhs);
141 ✗ return expansion_nt(e);
142 }
143
144 ✗ expansion_nt expansion_nt::operator- (double rhs) const {
145 ✗ expansion* e = expansion::new_expansion_on_heap(
146 expansion::diff_capacity(rep(), rhs)
147 );
148 ✗ e->assign_diff(rep(), rhs);
149 ✗ return expansion_nt(e);
150 }
151
152 ✗ expansion_nt expansion_nt::operator* (double rhs) const {
153 ✗ expansion* e = expansion::new_expansion_on_heap(
154 expansion::product_capacity(rep(), rhs)
155 );
156 ✗ e->assign_product(rep(), rhs);
157 ✗ return expansion_nt(e);
158 }
159
160 /************************************************************************/
161
162 67566 expansion_nt expansion_nt::operator- () const {
163 67566 expansion_nt result(*this);
164 67566 result.rep().negate();
165 67566 return result;
166 }
167
168 /************************************************************************/
169
170 2441048 expansion_nt expansion_nt_determinant(
171 const expansion_nt& a00,const expansion_nt& a01,
172 const expansion_nt& a10,const expansion_nt& a11
173 ) {
174 2441048 expansion* result = expansion::new_expansion_on_heap(
175 expansion::det2x2_capacity(a00.rep(),a01.rep(),a10.rep(),a11.rep())
176 );
177 2441048 result->assign_det2x2(a00.rep(),a01.rep(),a10.rep(),a11.rep());
178 2441048 return expansion_nt(result);
179 }
180
181
182 17370 expansion_nt expansion_nt_determinant(
183 const expansion_nt& a00,const expansion_nt& a01,const expansion_nt& a02,
184 const expansion_nt& a10,const expansion_nt& a11,const expansion_nt& a12,
185 const expansion_nt& a20,const expansion_nt& a21,const expansion_nt& a22
186 ) {
187 // First compute the det2x2
188 const expansion& m01 =
189
2/6
✓ Branch 18 taken 17370 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 17370 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
17370 expansion_det2x2(a00.rep(), a10.rep(), a01.rep(), a11.rep());
190 const expansion& m02 =
191
2/6
✓ Branch 18 taken 17370 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 17370 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
17370 expansion_det2x2(a00.rep(), a20.rep(), a01.rep(), a21.rep());
192 const expansion& m12 =
193
2/6
✓ Branch 18 taken 17370 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 17370 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
17370 expansion_det2x2(a10.rep(), a20.rep(), a11.rep(), a21.rep());
194
195 // Now compute the minors of rank 3
196
2/6
✓ Branch 9 taken 17370 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 17370 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
17370 const expansion& z1 = expansion_product(m01,a22.rep());
197
2/6
✓ Branch 9 taken 17370 times.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 17370 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
17370 const expansion& z2 = expansion_product(m02,a12.rep()).negate();
198
2/6
✓ Branch 9 taken 17370 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 17370 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
17370 const expansion& z3 = expansion_product(m12,a02.rep());
199
200 17370 return expansion_nt(expansion_nt::SUM, z1, z2, z3);
201 }
202
203 ✗ expansion_nt expansion_nt_determinant(
204 const expansion_nt& a00,const expansion_nt& a01,
205 const expansion_nt& a02,const expansion_nt& a03,
206 const expansion_nt& a10,const expansion_nt& a11,
207 const expansion_nt& a12,const expansion_nt& a13,
208 const expansion_nt& a20,const expansion_nt& a21,
209 const expansion_nt& a22,const expansion_nt& a23,
210 const expansion_nt& a30,const expansion_nt& a31,
211 const expansion_nt& a32,const expansion_nt& a33
212 ) {
213
214 // First compute the det2x2
215 const expansion& m01 =
216 ✗ expansion_det2x2(a10.rep(),a00.rep(),a11.rep(),a01.rep());
217 const expansion& m02 =
218 ✗ expansion_det2x2(a20.rep(),a00.rep(),a21.rep(),a01.rep());
219 const expansion& m03 =
220 ✗ expansion_det2x2(a30.rep(),a00.rep(),a31.rep(),a01.rep());
221 const expansion& m12 =
222 ✗ expansion_det2x2(a20.rep(),a10.rep(),a21.rep(),a11.rep());
223 const expansion& m13 =
224 ✗ expansion_det2x2(a30.rep(),a10.rep(),a31.rep(),a11.rep());
225 const expansion& m23 =
226 ✗ expansion_det2x2(a30.rep(),a20.rep(),a31.rep(),a21.rep());
227
228 // Now compute the minors of rank 3
229 ✗ const expansion& m012_1 = expansion_product(m12,a02.rep());
230 ✗ expansion& m012_2 = expansion_product(m02,a12.rep()); m012_2.negate();
231 ✗ const expansion& m012_3 = expansion_product(m01,a22.rep());
232 ✗ const expansion& m012 = expansion_sum3(m012_1, m012_2, m012_3);
233
234 ✗ const expansion& m013_1 = expansion_product(m13,a02.rep());
235 ✗ expansion& m013_2 = expansion_product(m03,a12.rep()); m013_2.negate();
236
237 ✗ const expansion& m013_3 = expansion_product(m01,a32.rep());
238 ✗ const expansion& m013 = expansion_sum3(m013_1, m013_2, m013_3);
239
240 ✗ const expansion& m023_1 = expansion_product(m23,a02.rep());
241 ✗ expansion& m023_2 = expansion_product(m03,a22.rep()); m023_2.negate();
242 ✗ const expansion& m023_3 = expansion_product(m02,a32.rep());
243 ✗ const expansion& m023 = expansion_sum3(m023_1, m023_2, m023_3);
244
245 ✗ const expansion& m123_1 = expansion_product(m23,a12.rep());
246 ✗ expansion& m123_2 = expansion_product(m13,a22.rep()); m123_2.negate();
247 ✗ const expansion& m123_3 = expansion_product(m12,a32.rep());
248 ✗ const expansion& m123 = expansion_sum3(m123_1, m123_2, m123_3);
249
250 // Now compute the minors of rank 4
251 ✗ const expansion& m0123_1 = expansion_product(m123,a03.rep());
252 ✗ const expansion& m0123_2 = expansion_product(m023,a13.rep());
253 ✗ const expansion& m0123_3 = expansion_product(m013,a23.rep());
254 ✗ const expansion& m0123_4 = expansion_product(m012,a33.rep());
255
256 ✗ const expansion& z1 = expansion_sum(m0123_1, m0123_3);
257 ✗ const expansion& z2 = expansion_sum(m0123_2, m0123_4);
258
259 ✗ return expansion_nt(expansion_nt::DIFF,z1,z2);
260 }
261
262 /***********************************************************************/
263
264 namespace Numeric {
265
266 2240723 template<> Sign ratio_compare(
267 const expansion_nt& a_num, const expansion_nt& a_denom,
268 const expansion_nt& b_num, const expansion_nt& b_denom
269 ) {
270 // TODO HERE: CHECK THAT THIS FITS ON STACK
271
272 2240723 Sign s1 = Sign(a_num.sign()*a_denom.sign());
273 2240723 Sign s2 = Sign(b_num.sign()*b_denom.sign());
274
4/4
✓ Branch 0 taken 30066 times.
✓ Branch 1 taken 2210657 times.
✓ Branch 2 taken 15243 times.
✓ Branch 3 taken 14823 times.
2240723 if(s1 == ZERO && s2 == ZERO) {
275 15243 return ZERO;
276 }
277
2/2
✓ Branch 0 taken 273522 times.
✓ Branch 1 taken 1951958 times.
2225480 if(s1 != s2) {
278
2/2
✓ Branch 0 taken 117872 times.
✓ Branch 1 taken 155650 times.
273522 return (int(s1) > int(s2) ? POSITIVE : NEGATIVE);
279 }
280
281
2/2
✓ Branch 1 taken 237683 times.
✓ Branch 2 taken 1714275 times.
1951958 if(a_denom == b_denom) {
282
3/6
✓ Branch 1 taken 237683 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 237683 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 237683 times.
✗ Branch 8 not taken.
237683 if(std::max(a_num.length(),b_num.length()) < 16) {
283
2/6
✓ Branch 12 taken 237683 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 237683 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
237683 const expansion& diff_num = expansion_diff(
284 a_num.rep(), b_num.rep()
285 );
286 237683 return Sign(diff_num.sign() * a_denom.sign());
287 } else {
288 ✗ expansion_nt diff_num = a_num - b_num;
289 ✗ return Sign(diff_num.sign() * a_denom.sign());
290 ✗ }
291 }
292
293 1714275 if(
294
4/6
✓ Branch 1 taken 1714275 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1714275 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1191238 times.
✓ Branch 8 taken 523037 times.
2905513 std::max(a_num.length(),b_num.length()) < 4 &&
295
6/8
✓ Branch 1 taken 1191238 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1191238 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1191230 times.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 1191230 times.
✓ Branch 10 taken 523045 times.
2905513 std::max(a_denom.length(),b_denom.length()) < 4
296 ) {
297
2/6
✓ Branch 12 taken 1191230 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1191230 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
1191230 const expansion& num_a = expansion_product(
298 a_num.rep(), b_denom.rep()
299 );
300
2/6
✓ Branch 12 taken 1191230 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1191230 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
1191230 const expansion& num_b = expansion_product(
301 b_num.rep(), a_denom.rep()
302 );
303
2/6
✓ Branch 6 taken 1191230 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1191230 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
1191230 const expansion& diff_num = expansion_diff(num_a, num_b);
304 return Sign(
305 1191230 diff_num.sign() * a_denom.sign() * b_denom.sign()
306 1191230 );
307 } else {
308
1/2
✓ Branch 1 taken 523045 times.
✗ Branch 2 not taken.
523045 expansion_nt num_a = a_num * b_denom;
309
1/2
✓ Branch 1 taken 523045 times.
✗ Branch 2 not taken.
523045 expansion_nt num_b = b_num * a_denom;
310
1/2
✓ Branch 1 taken 523045 times.
✗ Branch 2 not taken.
523045 expansion_nt diff_num = num_a - num_b;
311 return Sign(
312
3/6
✓ Branch 1 taken 523045 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 523045 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 523045 times.
✗ Branch 8 not taken.
523045 diff_num.sign() * a_denom.sign() * b_denom.sign()
313 523045 );
314 523045 }
315 }
316
317 }
318
319 }
320