decoint 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,566 @@
1
+ from .decorated_interval import DecoratedInterval
2
+ from .decorations import Decoration, combine
3
+ from .functions import exp as bare_exp, sqrt as bare_sqrt, log as bare_log, pow_int as bare_pow_int, sign as bare_sign, interval_min as bare_interval_min, interval_max as bare_interval_max, nth_root as bare_nth_root, sin as bare_sin, cos as bare_cos, tan as bare_tan, asin as bare_asin, acos as bare_acos, atan as bare_atan, sinh as bare_sinh, cosh as bare_cosh, tanh as bare_tanh, asinh as bare_asinh, acosh as bare_acosh, atanh as bare_atanh, abs as bare_abs, atan2 as bare_atan2, contains_periodic_point as bare_contains_periodic_point, sqr as bare_sqr, pow_interval as bare_pow_interval, exp2 as bare_exp2, exp10 as bare_exp10, log2 as bare_log2, log10 as bare_log10, interval_ceil as bare_interval_ceil, interval_floor as bare_interval_floor, interval_trunc as bare_interval_trunc
4
+ from .constants import PI, HALF_PI, TWO_PI
5
+ from .interval import Interval
6
+ from gmpy2 import mpfr, is_integer, is_infinite, floor, ceil, trunc
7
+
8
+ def exp(x):
9
+ x = DecoratedInterval._coerce(x)
10
+ if x.is_nai:
11
+ return DecoratedInterval.new_nai()
12
+ interval = bare_exp(x.interval)
13
+ dec = combine(x.decoration)
14
+
15
+ if dec == Decoration.COM and not interval.is_bounded:
16
+ dec = Decoration.DAC
17
+ return DecoratedInterval(interval, dec)
18
+
19
+ def sqrt(x):
20
+ x = DecoratedInterval._coerce(x)
21
+ if x.is_nai:
22
+ return DecoratedInterval.new_nai()
23
+ if x.interval.hi < 0:
24
+ return DecoratedInterval.empty()
25
+ elif x.interval.lo < 0:
26
+ op_dec = Decoration.TRV
27
+ else:
28
+ op_dec = Decoration.COM
29
+ interval = bare_sqrt(x.interval)
30
+ dec = combine(x.decoration, op_dec)
31
+
32
+ if dec == Decoration.COM and not interval.is_bounded:
33
+ dec = Decoration.DAC
34
+
35
+ return DecoratedInterval(interval, dec)
36
+
37
+ def log(x):
38
+ x = DecoratedInterval._coerce(x)
39
+ if x.is_nai:
40
+ return DecoratedInterval.new_nai()
41
+ if x.interval.hi <= 0:
42
+ return DecoratedInterval.empty()
43
+ elif x.interval.lo <= 0:
44
+ op_dec = Decoration.TRV
45
+ else:
46
+ op_dec = Decoration.COM
47
+ interval = bare_log(x.interval)
48
+ dec = combine(x.decoration, op_dec)
49
+ if dec == Decoration.COM and not interval.is_bounded:
50
+ dec = Decoration.DAC
51
+ return DecoratedInterval(interval, dec)
52
+
53
+ def pow_int(x, n):
54
+ x = DecoratedInterval._coerce(x)
55
+ try:
56
+ n_int = int(n)
57
+ if n_int != n:
58
+ return DecoratedInterval.new_nai()
59
+ except Exception:
60
+ return DecoratedInterval.new_nai()
61
+ if x.is_nai:
62
+ return DecoratedInterval.new_nai()
63
+
64
+ if n_int < 0 and x.interval.contains(0):
65
+ op_dec = Decoration.TRV
66
+ else:
67
+ op_dec = Decoration.COM
68
+
69
+ interval = bare_pow_int(x.interval, n_int)
70
+ dec = combine(x.decoration, op_dec)
71
+
72
+ if dec == Decoration.COM and not interval.is_bounded:
73
+ dec = Decoration.DAC
74
+ return DecoratedInterval(interval, dec)
75
+
76
+ def sign(x):
77
+ x = DecoratedInterval._coerce(x)
78
+ if x.is_nai:
79
+ return DecoratedInterval.new_nai()
80
+ if x.interval.contains(0) and not x.interval.is_point:
81
+ op_dec = Decoration.DEF
82
+ else:
83
+ op_dec = Decoration.COM
84
+
85
+ interval = bare_sign(x.interval)
86
+ dec = combine(x.decoration, op_dec)
87
+
88
+ if dec == Decoration.COM and not interval.is_bounded:
89
+ dec = Decoration.DAC
90
+ return DecoratedInterval(interval, dec)
91
+
92
+ def interval_min(x, y):
93
+ x = DecoratedInterval._coerce(x)
94
+ y = DecoratedInterval._coerce(y)
95
+
96
+ if x.is_nai or y.is_nai:
97
+ return DecoratedInterval.new_nai()
98
+ op_dec = Decoration.COM
99
+ interval = bare_interval_min(x.interval, y.interval)
100
+
101
+ dec = combine(op_dec, y.decoration, x.decoration)
102
+
103
+ if dec == Decoration.COM and not interval.is_bounded:
104
+ dec = Decoration.DAC
105
+ return DecoratedInterval(interval, dec)
106
+
107
+ def interval_max(x, y):
108
+ x = DecoratedInterval._coerce(x)
109
+ y = DecoratedInterval._coerce(y)
110
+
111
+ if x.is_nai or y.is_nai:
112
+ return DecoratedInterval.new_nai()
113
+ op_dec = Decoration.COM
114
+ interval = bare_interval_max(x.interval, y.interval)
115
+
116
+ dec = combine(op_dec, y.decoration, x.decoration)
117
+
118
+ if dec == Decoration.COM and not interval.is_bounded:
119
+ dec = Decoration.DAC
120
+ return DecoratedInterval(interval, dec)
121
+
122
+ def nth_root(x, n):
123
+ x = DecoratedInterval._coerce(x)
124
+ try:
125
+ n_int = int(n)
126
+ if n_int != n:
127
+ return DecoratedInterval.new_nai()
128
+ except Exception:
129
+ return DecoratedInterval.new_nai()
130
+ if x.is_nai:
131
+ return DecoratedInterval.new_nai()
132
+ if n_int <= 0:
133
+ return DecoratedInterval.new_nai()
134
+ if n_int % 2 == 1:
135
+ op_dec = Decoration.COM
136
+ else:
137
+ if x.interval.hi < 0:
138
+ return DecoratedInterval.empty()
139
+ elif x.interval.lo < 0:
140
+ op_dec = Decoration.TRV
141
+ else:
142
+ op_dec = Decoration.COM
143
+ interval = bare_nth_root(x.interval, n_int)
144
+ dec = combine(x.decoration, op_dec)
145
+
146
+ if dec == Decoration.COM and not interval.is_bounded:
147
+ dec = Decoration.DAC
148
+
149
+ return DecoratedInterval(interval, dec)
150
+
151
+ def sin(x):
152
+ x = DecoratedInterval._coerce(x)
153
+ if x.is_nai:
154
+ return DecoratedInterval.new_nai()
155
+ op_dec = Decoration.COM
156
+
157
+ interval = bare_sin(x.interval)
158
+ dec = combine(op_dec, x.decoration)
159
+
160
+ if dec == Decoration.COM and not interval.is_bounded:
161
+ dec = Decoration.DAC
162
+
163
+ return DecoratedInterval(interval, dec)
164
+
165
+
166
+ def cos(x):
167
+ x = DecoratedInterval._coerce(x)
168
+ if x.is_nai:
169
+ return DecoratedInterval.new_nai()
170
+ op_dec = Decoration.COM
171
+
172
+ interval = bare_cos(x.interval)
173
+ dec = combine(op_dec, x.decoration)
174
+
175
+ if dec == Decoration.COM and not interval.is_bounded:
176
+ dec = Decoration.DAC
177
+
178
+ return DecoratedInterval(interval, dec)
179
+
180
+ def tan(x):
181
+ x = DecoratedInterval._coerce(x)
182
+ if x.is_nai:
183
+ return DecoratedInterval.new_nai()
184
+ if x.interval.is_empty:
185
+ return DecoratedInterval.empty()
186
+ if not x.interval.is_bounded:
187
+ return DecoratedInterval(Interval.entire(), Decoration.TRV)
188
+
189
+ if bare_contains_periodic_point(x.interval, HALF_PI, PI):
190
+ op_dec = Decoration.TRV
191
+ else:
192
+ op_dec = Decoration.COM
193
+
194
+ interval = bare_tan(x.interval)
195
+ dec = combine(x.decoration, op_dec)
196
+
197
+ if dec == Decoration.COM and not interval.is_bounded:
198
+ dec = Decoration.DAC
199
+
200
+ return DecoratedInterval(interval, dec)
201
+
202
+ def asin(x):
203
+ x = DecoratedInterval._coerce(x)
204
+ if x.is_nai:
205
+ return DecoratedInterval.new_nai()
206
+
207
+ if x.interval.hi < -1 or x.interval.lo > 1:
208
+ return DecoratedInterval.empty()
209
+ elif x.interval.lo < -1 or x.interval.hi > 1:
210
+ op_dec = Decoration.TRV
211
+ else:
212
+ op_dec = Decoration.COM
213
+
214
+ interval = bare_asin(x.interval)
215
+ dec = combine(x.decoration, op_dec)
216
+
217
+ if dec == Decoration.COM and not interval.is_bounded:
218
+ dec = Decoration.DAC
219
+
220
+ return DecoratedInterval(interval, dec)
221
+
222
+ def acos(x):
223
+ x = DecoratedInterval._coerce(x)
224
+ if x.is_nai:
225
+ return DecoratedInterval.new_nai()
226
+
227
+ if x.interval.hi < -1 or x.interval.lo > 1:
228
+ return DecoratedInterval.empty()
229
+ elif x.interval.lo < -1 or x.interval.hi > 1:
230
+ op_dec = Decoration.TRV
231
+ else:
232
+ op_dec = Decoration.COM
233
+
234
+ interval = bare_acos(x.interval)
235
+ dec = combine(x.decoration, op_dec)
236
+
237
+ if dec == Decoration.COM and not interval.is_bounded:
238
+ dec = Decoration.DAC
239
+
240
+ return DecoratedInterval(interval, dec)
241
+
242
+ def atan(x):
243
+ x = DecoratedInterval._coerce(x)
244
+ if x.is_nai:
245
+ return DecoratedInterval.new_nai()
246
+ op_dec = Decoration.COM
247
+
248
+ interval = bare_atan(x.interval)
249
+ dec = combine(x.decoration, op_dec)
250
+
251
+ if dec == Decoration.COM and not interval.is_bounded:
252
+ dec = Decoration.DAC
253
+
254
+ return DecoratedInterval(interval, dec)
255
+
256
+ def sinh(x):
257
+ x = DecoratedInterval._coerce(x)
258
+ if x.is_nai:
259
+ return DecoratedInterval.new_nai()
260
+ op_dec = Decoration.COM
261
+
262
+ interval = bare_sinh(x.interval)
263
+ dec = combine(x.decoration, op_dec)
264
+
265
+ if dec == Decoration.COM and not interval.is_bounded:
266
+ dec = Decoration.DAC
267
+
268
+ return DecoratedInterval(interval, dec)
269
+
270
+ def cosh(x):
271
+ x = DecoratedInterval._coerce(x)
272
+ if x.is_nai:
273
+ return DecoratedInterval.new_nai()
274
+ op_dec = Decoration.COM
275
+
276
+ interval = bare_cosh(x.interval)
277
+ dec = combine(x.decoration, op_dec)
278
+
279
+ if dec == Decoration.COM and not interval.is_bounded:
280
+ dec = Decoration.DAC
281
+
282
+ return DecoratedInterval(interval, dec)
283
+
284
+ def tanh(x):
285
+ x = DecoratedInterval._coerce(x)
286
+ if x.is_nai:
287
+ return DecoratedInterval.new_nai()
288
+ op_dec = Decoration.COM
289
+
290
+ interval = bare_tanh(x.interval)
291
+ dec = combine(x.decoration, op_dec)
292
+
293
+ if dec == Decoration.COM and not interval.is_bounded:
294
+ dec = Decoration.DAC
295
+
296
+ return DecoratedInterval(interval, dec)
297
+
298
+ def asinh(x):
299
+ x = DecoratedInterval._coerce(x)
300
+ if x.is_nai:
301
+ return DecoratedInterval.new_nai()
302
+ op_dec = Decoration.COM
303
+
304
+ interval = bare_asinh(x.interval)
305
+ dec = combine(x.decoration, op_dec)
306
+
307
+ if dec == Decoration.COM and not interval.is_bounded:
308
+ dec = Decoration.DAC
309
+
310
+ return DecoratedInterval(interval, dec)
311
+
312
+ def acosh(x):
313
+ x = DecoratedInterval._coerce(x)
314
+ if x.is_nai:
315
+ return DecoratedInterval.new_nai()
316
+ if x.interval.hi < 1:
317
+ return DecoratedInterval.empty()
318
+ elif x.interval.lo < 1:
319
+ op_dec = Decoration.TRV
320
+ else:
321
+ op_dec = Decoration.COM
322
+
323
+ interval = bare_acosh(x.interval)
324
+ dec = combine(x.decoration, op_dec)
325
+
326
+ if dec == Decoration.COM and not interval.is_bounded:
327
+ dec = Decoration.DAC
328
+
329
+ return DecoratedInterval(interval, dec)
330
+
331
+ def atanh(x):
332
+ x = DecoratedInterval._coerce(x)
333
+ if x.is_nai:
334
+ return DecoratedInterval.new_nai()
335
+
336
+ if x.interval.hi <= -1 or x.interval.lo >= 1:
337
+ return DecoratedInterval.empty()
338
+ elif x.interval.lo <= -1 or x.interval.hi >= 1:
339
+ op_dec = Decoration.TRV
340
+ else:
341
+ op_dec = Decoration.COM
342
+
343
+ interval = bare_atanh(x.interval)
344
+ dec = combine(x.decoration, op_dec)
345
+
346
+ if dec == Decoration.COM and not interval.is_bounded:
347
+ dec = Decoration.DAC
348
+
349
+ return DecoratedInterval(interval, dec)
350
+
351
+
352
+ def abs(x):
353
+ x = DecoratedInterval._coerce(x)
354
+ if x.is_nai:
355
+ return DecoratedInterval.new_nai()
356
+ op_dec = Decoration.COM
357
+
358
+ interval = bare_abs(x.interval)
359
+ dec = combine(x.decoration, op_dec)
360
+
361
+ if dec == Decoration.COM and not interval.is_bounded:
362
+ dec = Decoration.DAC
363
+
364
+ return DecoratedInterval(interval, dec)
365
+
366
+ def atan2(y, x):
367
+ y = DecoratedInterval._coerce(y)
368
+ x = DecoratedInterval._coerce(x)
369
+
370
+ if y.is_nai or x.is_nai:
371
+ return DecoratedInterval.new_nai()
372
+
373
+ if y.interval.contains(0) and x.interval.contains(0):
374
+ if y.interval.lo == 0 and y.interval.hi == 0 and x.interval.lo == 0 and x.interval.hi == 0:
375
+ return DecoratedInterval.empty()
376
+ op_dec = Decoration.TRV
377
+ elif x.interval.lo < 0 and y.interval.contains(0):
378
+ op_dec = Decoration.DEF if y.interval.lo < 0 else Decoration.DAC
379
+ else:
380
+ op_dec = Decoration.COM
381
+
382
+ interval = bare_atan2(y.interval, x.interval)
383
+ dec = combine(x.decoration, op_dec, y.decoration)
384
+
385
+ if dec == Decoration.COM and not interval.is_bounded:
386
+ dec = Decoration.DAC
387
+
388
+ return DecoratedInterval(interval, dec)
389
+
390
+ def sqr(x):
391
+ x = DecoratedInterval._coerce(x)
392
+
393
+ if x.is_nai:
394
+ return DecoratedInterval.new_nai()
395
+
396
+ op_dec = Decoration.COM
397
+
398
+ interval = bare_sqr(x.interval)
399
+ dec = combine(x.decoration, op_dec)
400
+
401
+ if dec == Decoration.COM and not interval.is_bounded:
402
+ dec = Decoration.DAC
403
+ return DecoratedInterval(interval, dec)
404
+
405
+ def pow_interval(x, y):
406
+ x = DecoratedInterval._coerce(x)
407
+ y = DecoratedInterval._coerce(y)
408
+
409
+ if x.is_nai or y.is_nai:
410
+ return DecoratedInterval.new_nai()
411
+
412
+ interval = bare_pow_interval(x.interval, y.interval)
413
+
414
+ if interval.is_empty:
415
+ return DecoratedInterval(interval, Decoration.TRV)
416
+
417
+ dec = combine(x.decoration, y.decoration)
418
+
419
+ if x.interval.lo < 0 or (x.interval.lo <= 0 <= x.interval.hi and y.interval.lo <= 0):
420
+ dec = Decoration.TRV
421
+ elif dec == Decoration.COM and not interval.is_bounded:
422
+ dec = Decoration.DAC
423
+
424
+ return DecoratedInterval(interval, dec)
425
+
426
+ def exp2(x):
427
+ x = DecoratedInterval._coerce(x)
428
+ if x.is_nai:
429
+ return DecoratedInterval.new_nai()
430
+ interval = bare_exp2(x.interval)
431
+ dec = combine(x.decoration)
432
+
433
+ if dec == Decoration.COM and not interval.is_bounded:
434
+ dec = Decoration.DAC
435
+ return DecoratedInterval(interval, dec)
436
+
437
+ def exp10(x):
438
+ x = DecoratedInterval._coerce(x)
439
+ if x.is_nai:
440
+ return DecoratedInterval.new_nai()
441
+ interval = bare_exp10(x.interval)
442
+ dec = combine(x.decoration)
443
+
444
+ if dec == Decoration.COM and not interval.is_bounded:
445
+ dec = Decoration.DAC
446
+ return DecoratedInterval(interval, dec)
447
+
448
+ def log2(x):
449
+ x = DecoratedInterval._coerce(x)
450
+ if x.is_nai:
451
+ return DecoratedInterval.new_nai()
452
+ if x.interval.hi <= 0:
453
+ return DecoratedInterval.empty()
454
+ elif x.interval.lo <= 0:
455
+ op_dec = Decoration.TRV
456
+ else:
457
+ op_dec = Decoration.COM
458
+ interval = bare_log2(x.interval)
459
+ dec = combine(x.decoration, op_dec)
460
+ if dec == Decoration.COM and not interval.is_bounded:
461
+ dec = Decoration.DAC
462
+ return DecoratedInterval(interval, dec)
463
+
464
+ def log10(x):
465
+ x = DecoratedInterval._coerce(x)
466
+ if x.is_nai:
467
+ return DecoratedInterval.new_nai()
468
+ if x.interval.hi <= 0:
469
+ return DecoratedInterval.empty()
470
+ elif x.interval.lo <= 0:
471
+ op_dec = Decoration.TRV
472
+ else:
473
+ op_dec = Decoration.COM
474
+ interval = bare_log10(x.interval)
475
+ dec = combine(x.decoration, op_dec)
476
+ if dec == Decoration.COM and not interval.is_bounded:
477
+ dec = Decoration.DAC
478
+ return DecoratedInterval(interval, dec)
479
+
480
+ def interval_ceil(x):
481
+ x = DecoratedInterval._coerce(x)
482
+ if x.is_nai:
483
+ return DecoratedInterval.new_nai()
484
+
485
+ res_interval = bare_interval_ceil(x.interval)
486
+
487
+ if not x.interval.is_bounded:
488
+ has_jump = True
489
+ contains_integer = True
490
+ else:
491
+ has_jump = (x.interval.lo < x.interval.hi and ceil(x.interval.lo) < x.interval.hi)
492
+ contains_integer = floor(x.interval.hi) >= ceil(x.interval.lo)
493
+
494
+ if has_jump:
495
+ dec = min(x.decoration, Decoration.DEF)
496
+ elif contains_integer:
497
+ dec = min(x.decoration, Decoration.DAC)
498
+ else:
499
+ dec = x.decoration
500
+
501
+ return DecoratedInterval(res_interval, dec)
502
+
503
+ def interval_floor(x):
504
+ x = DecoratedInterval._coerce(x)
505
+ if x.is_nai:
506
+ return DecoratedInterval.new_nai()
507
+
508
+ res_interval = bare_interval_floor(x.interval)
509
+
510
+ x_low = mpfr(x.interval.lo)
511
+ x_high = mpfr(x.interval.hi)
512
+
513
+ if x.interval.is_bounded:
514
+ has_jump = x_low < x_high and x_low < floor(x_high)
515
+ contains_integer = floor(x_high) >= ceil(x_low)
516
+ else:
517
+ has_jump = True
518
+
519
+ if has_jump:
520
+ dec = min(x.decoration, Decoration.DEF)
521
+ elif contains_integer:
522
+ dec = min(x.decoration, Decoration.DAC)
523
+ else:
524
+ dec = x.decoration
525
+
526
+ return DecoratedInterval(res_interval, dec)
527
+
528
+ def interval_trunc(x):
529
+ x = DecoratedInterval._coerce(x)
530
+ if x.is_nai:
531
+ return DecoratedInterval.new_nai()
532
+
533
+ res_interval = bare_interval_trunc(x.interval)
534
+
535
+ x_low = x.interval.lo
536
+ x_high = x.interval.hi
537
+
538
+ if not x.interval.is_bounded:
539
+ has_jump = True
540
+ contains_integer = True
541
+ else:
542
+
543
+ has_jump = False
544
+ if x_low < x_high:
545
+ if x_low < 0:
546
+ bound_high = min(x_high, mpfr(0))
547
+ if ceil(x_low) < bound_high:
548
+ has_jump = True
549
+ if x_high > 0 and not has_jump:
550
+ bound_low = max(x_low, mpfr(0))
551
+ if bound_low < floor(x_high):
552
+ has_jump = True
553
+
554
+ contains_nonzero_integer = (
555
+ (floor(x_high) >= ceil(x_low)) and
556
+ not (floor(x_low) == -1 and floor(x_high) == 0)
557
+ ) or (is_integer(x_low) and x_low != 0) or (is_integer(x_high) and x_high != 0)
558
+
559
+ if has_jump:
560
+ dec = min(x.decoration, Decoration.DEF)
561
+ elif contains_nonzero_integer:
562
+ dec = min(x.decoration, Decoration.DAC)
563
+ else:
564
+ dec = x.decoration
565
+
566
+ return DecoratedInterval(res_interval, dec)