Coverage Report

Created: 2026-07-16 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/geos/src/math/DD.cpp
Line
Count
Source
1
/**********************************************************************
2
 *
3
 * GEOS - Geometry Engine Open Source
4
 * http://geos.osgeo.org
5
 *
6
 * Copyright (C) 2020 Crunchy Data
7
 *
8
 * This is free software; you can redistribute and/or modify it under
9
 * the terms of the GNU Lesser General Public Licence as published
10
 * by the Free Software Foundation.
11
 * See the COPYING file for more information.
12
 *
13
 **********************************************************************/
14
15
#include <cmath>
16
17
#include <geos/profiler.h>
18
#include <geos/math/DD.h>
19
20
namespace geos {
21
namespace math { // geos.util
22
23
/* private */
24
void DD::setNaN()
25
0
{
26
0
    hi = std::numeric_limits<double>::quiet_NaN();
27
0
}
28
/* public */
29
bool DD::isInf() const
30
0
{
31
0
    return std::isinf(hi);
32
0
}
33
/* public */
34
bool DD::isNaN() const
35
0
{
36
0
    return std::isnan(hi);
37
0
}
38
/* public */
39
bool DD::isNegative() const
40
0
{
41
0
    return hi < 0.0 || (hi == 0.0 && lo < 0.0);
42
0
}
43
/* public */
44
bool DD::isPositive() const
45
0
{
46
0
    return hi > 0.0 || (hi == 0.0 && lo > 0.0);
47
0
}
48
/* public */
49
bool DD::isZero() const
50
86.5M
{
51
86.5M
    return hi == 0.0 && lo == 0.0;
52
86.5M
}
53
54
/* public */
55
double DD::doubleValue() const
56
172M
{
57
172M
    return hi + lo;
58
172M
}
59
60
/* public */
61
int DD::intValue() const
62
0
{
63
0
    return (int) hi;
64
0
}
65
66
/* public */
67
void DD::selfAdd(const DD &y)
68
800M
{
69
800M
    return selfAdd(y.hi, y.lo);
70
800M
}
71
72
/* public */
73
void DD::selfAdd(double yhi, double ylo)
74
1.78G
{
75
1.78G
    double H, h, T, t, S, s, e, f;
76
1.78G
    S = hi + yhi;
77
1.78G
    T = lo + ylo;
78
1.78G
    e = S - hi;
79
1.78G
    f = T - lo;
80
1.78G
    s = S-e;
81
1.78G
    t = T-f;
82
1.78G
    s = (yhi-e)+(hi-s);
83
1.78G
    t = (ylo-f)+(lo-t);
84
1.78G
    e = s+T; H = S+e; h = e+(S-H); e = t+h;
85
86
1.78G
    double zhi = H + e;
87
1.78G
    double zlo = e + (H - zhi);
88
1.78G
    hi = zhi;
89
1.78G
    lo = zlo;
90
1.78G
    return;
91
1.78G
}
92
93
/* public */
94
void DD::selfAdd(double y)
95
0
{
96
0
    double H, h, S, s, e, f;
97
0
    S = hi + y;
98
0
    e = S - hi;
99
0
    s = S - e;
100
0
    s = (y - e) + (hi - s);
101
0
    f = s + lo;
102
0
    H = S + f;
103
0
    h = f + (S - H);
104
0
    hi = H + h;
105
0
    lo = h + (H - hi);
106
0
    return;
107
0
}
108
109
/* public */
110
DD operator+(const DD &lhs, const DD &rhs)
111
800M
{
112
800M
    DD rv(lhs.hi, lhs.lo);
113
800M
    rv.selfAdd(rhs);
114
800M
    return rv;
115
800M
}
116
117
/* public */
118
DD operator+(const DD &lhs, double rhs)
119
0
{
120
0
    DD rv(lhs.hi, lhs.lo);
121
0
    rv.selfAdd(rhs);
122
0
    return rv;
123
0
}
124
125
/* public */
126
void DD::selfSubtract(const DD &d)
127
979M
{
128
979M
    return selfAdd(-1*d.hi, -1*d.lo);
129
979M
}
130
131
/* public */
132
void DD::selfSubtract(double p_hi, double p_lo)
133
0
{
134
0
    return selfAdd(-1*p_hi, -1*p_lo);
135
0
}
136
137
/* public */
138
void DD::selfSubtract(double y)
139
0
{
140
0
    return selfAdd(-1*y, 0.0);
141
0
}
142
143
/* public */
144
DD operator-(const DD &lhs, const DD &rhs)
145
979M
{
146
979M
    DD rv(lhs.hi, lhs.lo);
147
979M
    rv.selfSubtract(rhs);
148
979M
    return rv;
149
979M
}
150
151
/* public */
152
DD operator-(const DD &lhs, double rhs)
153
0
{
154
0
    DD rv(lhs.hi, lhs.lo);
155
0
    rv.selfSubtract(rhs);
156
0
    return rv;
157
0
}
158
159
/* public */
160
void DD::selfMultiply(double yhi, double ylo)
161
1.26G
{
162
1.26G
    double hx, tx, hy, ty, C, c;
163
1.26G
    C = SPLIT * hi; hx = C-hi; c = SPLIT * yhi;
164
1.26G
    hx = C-hx; tx = hi-hx; hy = c-yhi;
165
1.26G
    C = hi*yhi; hy = c-hy; ty = yhi-hy;
166
1.26G
    c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+(hi*ylo+lo*yhi);
167
1.26G
    double zhi = C+c; hx = C-zhi;
168
1.26G
    double zlo = c+hx;
169
1.26G
    hi = zhi;
170
1.26G
    lo = zlo;
171
1.26G
    return;
172
1.26G
}
173
174
/* public */
175
void DD::selfMultiply(DD const &d)
176
1.26G
{
177
1.26G
    return selfMultiply(d.hi, d.lo);
178
1.26G
}
179
180
/* public */
181
void DD::selfMultiply(double y)
182
0
{
183
0
    return selfMultiply(y, 0.0);
184
0
}
185
186
/* public */
187
DD operator*(const DD &lhs, const DD &rhs)
188
1.26G
{
189
1.26G
    DD rv(lhs.hi, lhs.lo);
190
1.26G
    rv.selfMultiply(rhs);
191
1.26G
    return rv;
192
1.26G
}
193
194
/* public */
195
DD operator*(const DD &lhs, double rhs)
196
0
{
197
0
    DD rv(lhs.hi, lhs.lo);
198
0
    rv.selfMultiply(rhs);
199
0
    return rv;
200
0
}
201
202
203
/* public */
204
void DD::selfDivide(double yhi, double ylo)
205
172M
{
206
172M
    double hc, tc, hy, ty, C, c, U, u;
207
172M
    C = hi/yhi; c = SPLIT*C; hc =c-C;
208
172M
    u = SPLIT*yhi; hc = c-hc;
209
172M
    tc = C-hc; hy = u-yhi; U = C * yhi;
210
172M
    hy = u-hy; ty = yhi-hy;
211
172M
    u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;
212
172M
    c = ((((hi-U)-u)+lo)-C*ylo)/yhi;
213
172M
    u = C+c;
214
172M
    hi = u;
215
172M
    lo = (C-u)+c;
216
172M
    return;
217
172M
}
218
219
/* public */
220
void DD::selfDivide(const DD &d)
221
172M
{
222
172M
    return selfDivide(d.hi, d.lo);
223
172M
}
224
225
/* public */
226
void DD::selfDivide(double y)
227
0
{
228
0
    return selfDivide(y, 0.0);
229
0
}
230
231
/* public */
232
DD operator/(const DD &lhs, const DD &rhs)
233
172M
{
234
172M
    DD rv(lhs.hi, lhs.lo);
235
172M
    rv.selfDivide(rhs);
236
172M
    return rv;
237
172M
}
238
239
/* public */
240
DD operator/(const DD &lhs, double rhs)
241
0
{
242
0
    DD rv(lhs.hi, lhs.lo);
243
0
    rv.selfDivide(rhs);
244
0
    return rv;
245
0
}
246
247
DD operator- (const DD& x)
248
0
{
249
0
    return x.negate();
250
0
}
251
252
/* public */
253
DD DD::negate() const
254
0
{
255
0
    DD rv(hi, lo);
256
0
    if (rv.isNaN())
257
0
    {
258
0
        return rv;
259
0
    }
260
0
    rv.hi = -hi;
261
0
    rv.lo = -lo;
262
0
    return rv;
263
0
}
264
265
/* public static */
266
DD DD::reciprocal() const
267
0
{
268
0
    double  hc, tc, hy, ty, C, c, U, u;
269
0
    C = 1.0/hi;
270
0
    c = SPLIT*C;
271
0
    hc = c-C;
272
0
    u = SPLIT*hi;
273
0
    hc = c-hc; tc = C-hc; hy = u-hi; U = C*hi; hy = u-hy; ty = hi-hy;
274
0
    u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;
275
0
    c = ((((1.0-U)-u))-C*lo)/hi;
276
0
    double zhi = C+c;
277
0
    double zlo = (C-zhi)+c;
278
0
    return DD(zhi, zlo);
279
0
}
280
281
DD DD::floor() const
282
0
{
283
0
    DD rv(hi, lo);
284
0
    if (isNaN()) return rv;
285
0
    double fhi = std::floor(hi);
286
0
    double flo = 0.0;
287
    // Hi is already integral.  Floor the low word
288
0
    if (fhi == hi) {
289
0
      flo = std::floor(lo);
290
0
    }
291
      // do we need to renormalize here?
292
0
    rv.hi = fhi;
293
0
    rv.lo = flo;
294
0
    return rv;
295
0
}
296
297
DD DD::ceil() const
298
0
{
299
0
    DD rv(hi, lo);
300
0
    if (isNaN()) return rv;
301
0
    double fhi = std::ceil(hi);
302
0
    double flo = 0.0;
303
    // Hi is already integral.  Ceil the low word
304
0
    if (fhi == hi) {
305
0
      flo = std::ceil(lo);
306
      // do we need to renormalize here?
307
0
    }
308
0
    rv.hi = fhi;
309
0
    rv.lo = flo;
310
0
    return rv;
311
0
}
312
313
int DD::signum() const
314
0
{
315
0
    if (hi > 0) return 1;
316
0
    if (hi < 0) return -1;
317
0
    if (lo > 0) return 1;
318
0
    if (lo < 0) return -1;
319
0
    return 0;
320
0
}
321
322
DD DD::rint() const
323
0
{
324
0
    DD rv(hi, lo);
325
0
    if (isNaN()) return rv;
326
0
     return (rv + 0.5).floor();
327
0
}
328
329
/* public static */
330
DD DD::trunc(const DD &d)
331
0
{
332
0
    DD rv(d);
333
0
    if (rv.isNaN()) return rv;
334
0
    if (rv.isPositive())
335
0
        return rv.floor();
336
0
    return rv.ceil();
337
0
}
338
339
/* public static */
340
DD DD::abs(const DD &d)
341
0
{
342
0
    DD rv(d);
343
0
    if (rv.isNaN()) return rv;
344
0
    if (rv.isNegative())
345
0
        return rv.negate();
346
347
0
    return rv;
348
0
}
349
350
/* public static */
351
DD DD::determinant(const DD &x1, const DD &y1, const DD &x2, const DD &y2)
352
0
{
353
0
    return (x1 * y2) - (y1 * x2);
354
0
}
355
356
/* public static */
357
DD DD::determinant(double x1, double y1, double x2, double y2)
358
0
{
359
0
    return determinant(DD(x1), DD(y1), DD(x2), DD(y2) );
360
0
}
361
362
363
/**
364
* Computes the value of this number raised to an integral power.
365
* Follows semantics of Java Math.pow as closely as possible.
366
*/
367
/* public static */
368
DD DD::pow(const DD &d, int exp)
369
0
{
370
0
    if (exp == 0.0)
371
0
        return DD(1.0);
372
373
0
    DD r(d);
374
0
    DD s(1.0);
375
0
    int n = std::abs(exp);
376
377
0
    if (n > 1) {
378
        /* Use binary exponentiation */
379
0
        while (n > 0) {
380
0
        if (n % 2 == 1) {
381
0
            s.selfMultiply(r);
382
0
        }
383
0
        n /= 2;
384
0
        if (n > 0)
385
0
            r = r*r;
386
0
        }
387
0
    } else {
388
0
        s = r;
389
0
    }
390
391
    /* Compute the reciprocal if n is negative. */
392
0
    if (exp < 0)
393
0
        return s.reciprocal();
394
0
    return s;
395
0
}
396
397
398
}
399
}