open-space-toolkit-mathematics 3.0.0__py39-none-manylinux2014_aarch64.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.

Potentially problematic release.


This version of open-space-toolkit-mathematics might be problematic. Click here for more details.

Files changed (55) hide show
  1. open_space_toolkit_mathematics-3.0.0.dist-info/METADATA +28 -0
  2. open_space_toolkit_mathematics-3.0.0.dist-info/RECORD +55 -0
  3. open_space_toolkit_mathematics-3.0.0.dist-info/WHEEL +5 -0
  4. open_space_toolkit_mathematics-3.0.0.dist-info/top_level.txt +1 -0
  5. open_space_toolkit_mathematics-3.0.0.dist-info/zip-safe +1 -0
  6. ostk/__init__.py +1 -0
  7. ostk/mathematics/OpenSpaceToolkitMathematicsPy.cpython-39-aarch64-linux-gnu.so +0 -0
  8. ostk/mathematics/__init__.py +5 -0
  9. ostk/mathematics/libopen-space-toolkit-mathematics.so.3 +0 -0
  10. ostk/mathematics/test/__init__.py +1 -0
  11. ostk/mathematics/test/curve_fitting/__init__.py +1 -0
  12. ostk/mathematics/test/curve_fitting/interpolator/__init__.py +1 -0
  13. ostk/mathematics/test/curve_fitting/interpolator/test_barycentric_rational.py +34 -0
  14. ostk/mathematics/test/curve_fitting/interpolator/test_cubic_spline.py +45 -0
  15. ostk/mathematics/test/curve_fitting/interpolator/test_interpolator.py +71 -0
  16. ostk/mathematics/test/curve_fitting/interpolator/test_linear.py +36 -0
  17. ostk/mathematics/test/geometry/__init__.py +1 -0
  18. ostk/mathematics/test/geometry/d2/__init__.py +1 -0
  19. ostk/mathematics/test/geometry/d2/conftest.py +82 -0
  20. ostk/mathematics/test/geometry/d2/object/__init__.py +1 -0
  21. ostk/mathematics/test/geometry/d2/object/test_composite.py +96 -0
  22. ostk/mathematics/test/geometry/d2/object/test_line.py +57 -0
  23. ostk/mathematics/test/geometry/d2/object/test_linestring.py +174 -0
  24. ostk/mathematics/test/geometry/d2/object/test_multipolygon.py +101 -0
  25. ostk/mathematics/test/geometry/d2/object/test_point.py +213 -0
  26. ostk/mathematics/test/geometry/d2/object/test_point_set.py +102 -0
  27. ostk/mathematics/test/geometry/d2/object/test_polygon.py +370 -0
  28. ostk/mathematics/test/geometry/d2/object/test_segment.py +104 -0
  29. ostk/mathematics/test/geometry/d2/test_object.py +25 -0
  30. ostk/mathematics/test/geometry/d2/test_transformation.py +84 -0
  31. ostk/mathematics/test/geometry/d3/__init__.py +1 -0
  32. ostk/mathematics/test/geometry/d3/object/__init__.py +1 -0
  33. ostk/mathematics/test/geometry/d3/object/test_composite.py +262 -0
  34. ostk/mathematics/test/geometry/d3/object/test_cuboid.py +20 -0
  35. ostk/mathematics/test/geometry/d3/object/test_line.py +68 -0
  36. ostk/mathematics/test/geometry/d3/object/test_linestring.py +166 -0
  37. ostk/mathematics/test/geometry/d3/object/test_point.py +234 -0
  38. ostk/mathematics/test/geometry/d3/object/test_point_set.py +113 -0
  39. ostk/mathematics/test/geometry/d3/object/test_polygon.py +141 -0
  40. ostk/mathematics/test/geometry/d3/object/test_segment.py +120 -0
  41. ostk/mathematics/test/geometry/d3/objects/test_cuboid.py +20 -0
  42. ostk/mathematics/test/geometry/d3/test_intersection.py +3 -0
  43. ostk/mathematics/test/geometry/d3/test_object.py +3 -0
  44. ostk/mathematics/test/geometry/d3/test_transformation.py +3 -0
  45. ostk/mathematics/test/geometry/d3/transformation/__init__.py +1 -0
  46. ostk/mathematics/test/geometry/d3/transformation/rotation/__init__.py +1 -0
  47. ostk/mathematics/test/geometry/d3/transformation/rotation/test_quaternion.py +183 -0
  48. ostk/mathematics/test/geometry/d3/transformation/rotation/test_rotation_matrix.py +24 -0
  49. ostk/mathematics/test/geometry/d3/transformation/rotation/test_rotation_vector.py +34 -0
  50. ostk/mathematics/test/geometry/test_angle.py +345 -0
  51. ostk/mathematics/test/object/__init__.py +1 -0
  52. ostk/mathematics/test/object/test_interval.py +445 -0
  53. ostk/mathematics/test/object/test_vector.py +5 -0
  54. ostk/mathematics/test/solver/test_numerical_solver.py +176 -0
  55. ostk/mathematics/test/test_object.py +24 -0
@@ -0,0 +1,445 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import ostk.mathematics as mathematics
6
+
7
+ from ostk.core.type import Real, String
8
+
9
+
10
+ RealInterval = mathematics.object.RealInterval
11
+ Type = RealInterval.Type
12
+
13
+
14
+ class TestInterval:
15
+ def test_type(self):
16
+ enum_members = Type.__members__
17
+
18
+ assert list(enum_members.keys()) == [
19
+ "Undefined",
20
+ "Closed",
21
+ "Open",
22
+ "HalfOpenLeft",
23
+ "HalfOpenRight",
24
+ ]
25
+ assert list(enum_members.values()) == [
26
+ Type.Undefined,
27
+ Type.Closed,
28
+ Type.Open,
29
+ Type.HalfOpenLeft,
30
+ Type.HalfOpenRight,
31
+ ]
32
+
33
+ def test_default_constructor(self):
34
+ # Input types for RealInterval
35
+ interval_1 = RealInterval(-4.31, 1.0, Type.Open)
36
+ interval_2 = RealInterval(-2.0, -1.0, Type.Closed)
37
+ interval_3 = RealInterval(3.5, 4567.35566, Type.HalfOpenRight)
38
+ interval_4 = RealInterval(1.45, 1.45, Type.Open)
39
+ interval_5 = RealInterval(1.45, 1.45, Type.Closed)
40
+
41
+ assert isinstance(interval_1, RealInterval)
42
+ assert isinstance(interval_2, RealInterval)
43
+ assert isinstance(interval_3, RealInterval)
44
+ assert isinstance(interval_4, RealInterval)
45
+ assert isinstance(interval_5, RealInterval)
46
+ assert interval_1 is not None
47
+ assert interval_2 is not None
48
+ assert interval_3 is not None
49
+ assert interval_4 is not None
50
+ assert interval_5 is not None
51
+
52
+ with pytest.raises(TypeError):
53
+ interval = RealInterval(3.0, 1, Type.Closed)
54
+
55
+ interval_6 = RealInterval(Real(-4.31), Real(1.0), Type.Open)
56
+ interval_7 = RealInterval(Real(-2.0), Real(-1.0), Type.Closed)
57
+ interval_8 = RealInterval(Real(3.5), Real(4567.35566), Type.HalfOpenRight)
58
+ interval_9 = RealInterval(Real(1.45), Real(1.45), Type.Open)
59
+ interval_10 = RealInterval(Real(1.45), Real(1.45), Type.Closed)
60
+
61
+ assert isinstance(interval_6, RealInterval)
62
+ assert isinstance(interval_7, RealInterval)
63
+ assert isinstance(interval_8, RealInterval)
64
+ assert isinstance(interval_9, RealInterval)
65
+ assert isinstance(interval_10, RealInterval)
66
+ assert interval_6 is not None
67
+ assert interval_7 is not None
68
+ assert interval_8 is not None
69
+ assert interval_9 is not None
70
+ assert interval_10 is not None
71
+
72
+ # Interval Bounds
73
+ a = -4.31
74
+ b = 3.0
75
+
76
+ # Types of RealInterval
77
+ interval_undefined = RealInterval(a, b, Type.Undefined)
78
+ interval_closed = RealInterval(a, b, Type.Closed)
79
+ interval_open = RealInterval(a, b, Type.Open)
80
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
81
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
82
+
83
+ assert isinstance(interval_undefined, RealInterval)
84
+ assert isinstance(interval_closed, RealInterval)
85
+ assert isinstance(interval_open, RealInterval)
86
+ assert isinstance(interval_halfopenleft, RealInterval)
87
+ assert isinstance(interval_halfopenright, RealInterval)
88
+
89
+ # Unvalid interval definition
90
+
91
+ with pytest.raises(RuntimeError):
92
+ invalid_interval_1 = RealInterval(4.8, 3.5, Type.Open)
93
+
94
+ with pytest.raises(RuntimeError):
95
+ invalid_interval_2 = RealInterval(4.8, 3.5, Type.Closed)
96
+
97
+ with pytest.raises(RuntimeError):
98
+ invalid_interval_3 = RealInterval(4.8, 3.5, Type.HalfOpenLeft)
99
+
100
+ with pytest.raises(RuntimeError):
101
+ invalid_interval_4 = RealInterval(4.8, 3.5, Type.HalfOpenRight)
102
+
103
+ def test_undefined_constructor(self):
104
+ undefined_interval = RealInterval.undefined()
105
+
106
+ assert isinstance(undefined_interval, RealInterval)
107
+ assert undefined_interval is not None
108
+ assert undefined_interval.is_defined() is False
109
+
110
+ def test_closed_constructor(self):
111
+ a = -3.1
112
+ b = 45.6
113
+
114
+ closed_interval = RealInterval.closed(a, b)
115
+
116
+ assert isinstance(closed_interval, RealInterval)
117
+ assert closed_interval is not None
118
+ assert closed_interval.is_defined()
119
+ assert closed_interval.get_lower_bound() == a
120
+ assert closed_interval.get_upper_bound() == b
121
+
122
+ def test_is_defined(self):
123
+ # Interval Bounds
124
+ a = -4.31
125
+ b = 3.0
126
+
127
+ # Types of RealInterval
128
+ interval_undefined = RealInterval(a, b, Type.Undefined)
129
+ interval_closed = RealInterval(a, b, Type.Closed)
130
+ interval_open = RealInterval(a, b, Type.Open)
131
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
132
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
133
+
134
+ assert interval_undefined.is_defined() is False
135
+ assert interval_closed.is_defined() is True
136
+ assert interval_open.is_defined() is True
137
+ assert interval_halfopenleft.is_defined() is True
138
+ assert interval_halfopenright.is_defined() is True
139
+ assert RealInterval.undefined().is_defined() is False
140
+
141
+ # def test_is_degenerate ():
142
+
143
+ def test_intersects(self):
144
+ # Interval Bounds
145
+ a = -4.31
146
+ b = 3.0
147
+
148
+ # Types of RealInterval
149
+ interval_undefined = RealInterval(a, b, Type.Undefined)
150
+ interval_closed = RealInterval(a, b, Type.Closed)
151
+ interval_open = RealInterval(a, b, Type.Open)
152
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
153
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
154
+
155
+ # Define Test Intervals
156
+ interval_left = RealInterval(-5.0, -4.5, Type.Closed)
157
+ interval_intersects_left = RealInterval(-5.0, -4.26, Type.Closed)
158
+ interval_right = RealInterval(4.56, 4.67, Type.Closed)
159
+ interval_intersects_right = RealInterval(2.78, 46.09, Type.Closed)
160
+ interval_between = RealInterval(-3.4, 2.45, Type.Closed)
161
+ interval_bigger = RealInterval(-45.0, 34.12, Type.Closed)
162
+
163
+ # Add test cases with contained intervals not Type.Closed...
164
+ # Add test cases with open intervals and half open intervals...
165
+
166
+ # Test intersects on undefined
167
+
168
+ # with pytest.raises(RuntimeError):
169
+
170
+ # interval_undefined.intersects
171
+
172
+ # Test intersects on closed
173
+
174
+ assert interval_closed.intersects(interval_left) is False
175
+ assert interval_closed.intersects(interval_intersects_left) is True
176
+ assert interval_closed.intersects(interval_right) is False
177
+ assert interval_closed.intersects(interval_intersects_right) is True
178
+ assert interval_closed.intersects(interval_between) is True
179
+ assert interval_closed.intersects(interval_bigger) is True
180
+
181
+ # Test intersects on open
182
+
183
+ assert interval_open.intersects(interval_left) is False
184
+ assert interval_open.intersects(interval_intersects_left) is True
185
+ assert interval_open.intersects(interval_right) is False
186
+ assert interval_open.intersects(interval_intersects_right) is True
187
+ assert interval_open.intersects(interval_between) is True
188
+ assert interval_open.intersects(interval_bigger) is True
189
+
190
+ # Test intersects on halfopenleft
191
+
192
+ assert interval_halfopenleft.intersects(interval_left) is False
193
+ assert interval_halfopenleft.intersects(interval_intersects_left) is True
194
+ assert interval_halfopenleft.intersects(interval_right) is False
195
+ assert interval_halfopenleft.intersects(interval_intersects_right) is True
196
+ assert interval_halfopenleft.intersects(interval_between) is True
197
+ assert interval_halfopenleft.intersects(interval_bigger) is True
198
+
199
+ # Test intersects on halfopenright
200
+
201
+ assert interval_halfopenright.intersects(interval_left) is False
202
+ assert interval_halfopenright.intersects(interval_intersects_left) is True
203
+ assert interval_halfopenright.intersects(interval_right) is False
204
+ assert interval_halfopenright.intersects(interval_intersects_right) is True
205
+ assert interval_halfopenright.intersects(interval_between) is True
206
+ assert interval_halfopenright.intersects(interval_bigger) is True
207
+
208
+ def test_contains_real(self):
209
+ # Interval Bounds
210
+ a = -4.31
211
+ b = 3.0
212
+
213
+ # Types of RealInterval
214
+ interval_undefined = RealInterval(a, b, Type.Undefined)
215
+ interval_closed = RealInterval(a, b, Type.Closed)
216
+ interval_open = RealInterval(a, b, Type.Open)
217
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
218
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
219
+
220
+ # Define Reals
221
+ real_left = -5.43
222
+ real_right = 3.1
223
+ real_leftbound = a
224
+ real_rightbound = b
225
+ real_between_1 = 2.3
226
+ real_between_2 = 2.999999999
227
+
228
+ # Test contains on undefined
229
+
230
+ with pytest.raises(RuntimeError):
231
+ interval_undefined.contains(real_left)
232
+
233
+ # Test contains on closed
234
+
235
+ assert interval_closed.contains(real_left) is False
236
+ assert interval_closed.contains(real_right) is False
237
+ assert interval_closed.contains(real_leftbound) is True
238
+ assert interval_closed.contains(real_rightbound) is True
239
+ assert interval_closed.contains(real_between_1) is True
240
+ assert interval_closed.contains(real_between_2) is True
241
+
242
+ # Test contains on open
243
+
244
+ assert interval_open.contains(real_left) is False
245
+ assert interval_open.contains(real_right) is False
246
+ assert interval_open.contains(real_leftbound) is False
247
+ assert interval_open.contains(real_rightbound) is False
248
+ assert interval_open.contains(real_between_1) is True
249
+ assert interval_open.contains(real_between_2) is True
250
+
251
+ # Test contains on halfopenleft
252
+
253
+ assert interval_halfopenleft.contains(real_left) is False
254
+ assert interval_halfopenleft.contains(real_right) is False
255
+ assert interval_halfopenleft.contains(real_leftbound) is False
256
+ assert interval_halfopenleft.contains(real_rightbound) is True
257
+ assert interval_halfopenleft.contains(real_between_1) is True
258
+ assert interval_halfopenleft.contains(real_between_2) is True
259
+
260
+ # Test contains on halfopenright
261
+
262
+ assert interval_halfopenright.contains(real_left) is False
263
+ assert interval_halfopenright.contains(real_right) is False
264
+ assert interval_halfopenright.contains(real_leftbound) is True
265
+ assert interval_halfopenright.contains(real_rightbound) is False
266
+ assert interval_halfopenright.contains(real_between_1) is True
267
+ assert interval_halfopenright.contains(real_between_2) is True
268
+
269
+ def test_contains_interval(self):
270
+ # Interval Bounds
271
+ a = -4.31
272
+ b = 3.0
273
+
274
+ # Types of RealInterval
275
+ interval_undefined = RealInterval(a, b, Type.Undefined)
276
+ interval_closed = RealInterval(a, b, Type.Closed)
277
+ interval_open = RealInterval(a, b, Type.Open)
278
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
279
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
280
+
281
+ # Define Test Intervals
282
+ interval_left = RealInterval(-5.0, -4.5, Type.Closed)
283
+ interval_intersects_left = RealInterval(-5.0, -4.56, Type.Closed)
284
+ interval_right = RealInterval(4.56, 4.67, Type.Closed)
285
+ interval_intersects_right = RealInterval(2.78, 46.09, Type.Closed)
286
+ interval_between = RealInterval(-3.4, 2.45, Type.Closed)
287
+ interval_bigger = RealInterval(-45.0, 34.12, Type.Closed)
288
+
289
+ # Add test cases with contained intervals not Type.Closed...
290
+
291
+ # Test contains on undefined
292
+
293
+ with pytest.raises(RuntimeError):
294
+ interval_undefined.contains(interval_left)
295
+
296
+ # Test contains on closed
297
+
298
+ assert interval_closed.contains(interval_left) is False
299
+ assert interval_closed.contains(interval_intersects_left) is False
300
+ assert interval_closed.contains(interval_right) is False
301
+ assert interval_closed.contains(interval_intersects_right) is False
302
+ assert interval_closed.contains(interval_between) is True
303
+ assert interval_closed.contains(interval_bigger) is False
304
+
305
+ # Test contains on open
306
+
307
+ assert interval_open.contains(interval_left) is False
308
+ assert interval_open.contains(interval_intersects_left) is False
309
+ assert interval_open.contains(interval_right) is False
310
+ assert interval_open.contains(interval_intersects_right) is False
311
+ assert interval_open.contains(interval_between) is True
312
+ assert interval_open.contains(interval_bigger) is False
313
+
314
+ # Test contains on halfopenleft
315
+
316
+ assert interval_halfopenleft.contains(interval_left) is False
317
+ assert interval_halfopenleft.contains(interval_intersects_left) is False
318
+ assert interval_halfopenleft.contains(interval_right) is False
319
+ assert interval_halfopenleft.contains(interval_intersects_right) is False
320
+ assert interval_halfopenleft.contains(interval_between) is True
321
+ assert interval_halfopenleft.contains(interval_bigger) is False
322
+
323
+ # Test contains on halfopenright
324
+
325
+ assert interval_halfopenright.contains(interval_left) is False
326
+ assert interval_halfopenright.contains(interval_intersects_left) is False
327
+ assert interval_halfopenright.contains(interval_right) is False
328
+ assert interval_halfopenright.contains(interval_intersects_right) is False
329
+ assert interval_halfopenright.contains(interval_between) is True
330
+ assert interval_halfopenright.contains(interval_bigger) is False
331
+
332
+ def test_get_bounds(self):
333
+ # Interval Bounds
334
+ a = -4.31
335
+ b = 3.0
336
+
337
+ # Types of RealInterval
338
+ interval_undefined = RealInterval(a, b, Type.Undefined)
339
+ interval_closed = RealInterval(a, b, Type.Closed)
340
+ interval_open = RealInterval(a, b, Type.Open)
341
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
342
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
343
+
344
+ # get_lower_bound
345
+ with pytest.raises(RuntimeError):
346
+ interval_undefined.get_lower_bound()
347
+
348
+ assert interval_closed.get_lower_bound() == a
349
+ assert interval_open.get_lower_bound() == a
350
+ assert interval_halfopenleft.get_lower_bound() == a
351
+ assert interval_halfopenright.get_lower_bound() == a
352
+
353
+ # get_upper_bound
354
+ with pytest.raises(RuntimeError):
355
+ interval_undefined.get_upper_bound()
356
+
357
+ assert interval_closed.get_upper_bound() == b
358
+ assert interval_open.get_upper_bound() == b
359
+ assert interval_halfopenleft.get_upper_bound() == b
360
+ assert interval_halfopenright.get_upper_bound() == b
361
+
362
+ def test_to_string(self):
363
+ # Interval Bounds
364
+ a = -4.31
365
+ b = 3.0
366
+
367
+ # Types of RealInterval
368
+ interval_undefined = RealInterval(a, b, Type.Undefined)
369
+ interval_closed = RealInterval(a, b, Type.Closed)
370
+ interval_open = RealInterval(a, b, Type.Open)
371
+ interval_halfopenleft = RealInterval(a, b, Type.HalfOpenLeft)
372
+ interval_halfopenright = RealInterval(a, b, Type.HalfOpenRight)
373
+
374
+ with pytest.raises(RuntimeError):
375
+ interval_undefined.to_string()
376
+
377
+ assert isinstance(interval_closed.to_string(), String)
378
+ assert interval_closed.to_string() == "[-4.3099999999999996, 3.0]"
379
+ assert interval_open.to_string() == "]-4.3099999999999996, 3.0["
380
+ assert interval_halfopenleft.to_string() == "]-4.3099999999999996, 3.0]"
381
+ assert interval_halfopenright.to_string() == "[-4.3099999999999996, 3.0["
382
+
383
+ def test_get_intersection_with(self):
384
+ test_cases = [
385
+ (
386
+ RealInterval(0.0, 10.0, Type.HalfOpenLeft),
387
+ RealInterval(5.0, 7.0, Type.HalfOpenLeft),
388
+ RealInterval(5.0, 7.0, Type.HalfOpenLeft),
389
+ ),
390
+ (
391
+ RealInterval(0.0, 10.0, Type.HalfOpenRight),
392
+ RealInterval(-15.0, 25.0, Type.HalfOpenRight),
393
+ RealInterval(0.0, 10.0, Type.HalfOpenRight),
394
+ ),
395
+ (
396
+ RealInterval(0.0, 10.0, Type.Open),
397
+ RealInterval(-5.0, 7.0, Type.Open),
398
+ RealInterval(0.0, 7.0, Type.Open),
399
+ ),
400
+ (
401
+ RealInterval(0.0, 10.0, Type.Closed),
402
+ RealInterval(5.0, 15.0, Type.Closed),
403
+ RealInterval(5.0, 10.0, Type.Closed),
404
+ ),
405
+ ]
406
+
407
+ for test_case in test_cases:
408
+ first_interval = test_case[0]
409
+ second_interval = test_case[1]
410
+ expected_interval = test_case[2]
411
+
412
+ assert (
413
+ first_interval.get_intersection_with(second_interval) == expected_interval
414
+ )
415
+
416
+ def test_get_union_with(self):
417
+ test_cases = [
418
+ (
419
+ RealInterval(0.0, 10.0, Type.HalfOpenLeft),
420
+ RealInterval(5.0, 7.0, Type.HalfOpenLeft),
421
+ RealInterval(0.0, 10.0, Type.HalfOpenLeft),
422
+ ),
423
+ (
424
+ RealInterval(0.0, 10.0, Type.HalfOpenRight),
425
+ RealInterval(-15.0, 25.0, Type.HalfOpenRight),
426
+ RealInterval(-15.0, 25.0, Type.HalfOpenRight),
427
+ ),
428
+ (
429
+ RealInterval(0.0, 10.0, Type.Open),
430
+ RealInterval(-5.0, 7.0, Type.Open),
431
+ RealInterval(-5.0, 10.0, Type.Open),
432
+ ),
433
+ (
434
+ RealInterval(0.0, 10.0, Type.Closed),
435
+ RealInterval(5.0, 15.0, Type.Closed),
436
+ RealInterval(0.0, 15.0, Type.Closed),
437
+ ),
438
+ ]
439
+
440
+ for test_case in test_cases:
441
+ first_interval = test_case[0]
442
+ second_interval = test_case[1]
443
+ expected_interval = test_case[2]
444
+
445
+ assert first_interval.get_union_with(second_interval) == expected_interval
@@ -0,0 +1,5 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import ostk.mathematics as mathematics
@@ -0,0 +1,176 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+ import math
7
+
8
+ from ostk.mathematics.solver import NumericalSolver
9
+
10
+
11
+ def oscillator(x, dxdt, _):
12
+ dxdt[0] = x[1]
13
+ dxdt[1] = -x[0]
14
+ return dxdt
15
+
16
+
17
+ def get_state_vec(time: float) -> np.ndarray:
18
+ return np.array([math.sin(time), math.cos(time)])
19
+
20
+
21
+ @pytest.fixture
22
+ def initial_state_vec() -> np.ndarray:
23
+ return get_state_vec(0.0)
24
+
25
+
26
+ @pytest.fixture
27
+ def numerical_solver_default_inputs() -> (
28
+ tuple[NumericalSolver.LogType, NumericalSolver.StepperType, float, float, float]
29
+ ):
30
+ log_type = NumericalSolver.LogType.NoLog
31
+ stepper_type = NumericalSolver.StepperType.RungeKuttaCashKarp54
32
+ initial_time_step = 5.0
33
+ relative_tolerance = 1.0e-15
34
+ absolute_tolerance = 1.0e-15
35
+
36
+ return (
37
+ log_type,
38
+ stepper_type,
39
+ initial_time_step,
40
+ relative_tolerance,
41
+ absolute_tolerance,
42
+ )
43
+
44
+
45
+ @pytest.fixture
46
+ def numerical_solver(numerical_solver_default_inputs) -> NumericalSolver:
47
+ return NumericalSolver(*numerical_solver_default_inputs)
48
+
49
+
50
+ @pytest.fixture
51
+ def numerical_solver_conditional() -> NumericalSolver:
52
+ return NumericalSolver(
53
+ NumericalSolver.LogType.NoLog,
54
+ NumericalSolver.StepperType.RungeKuttaDopri5,
55
+ 5.0,
56
+ 1.0e-15,
57
+ 1.0e-15,
58
+ )
59
+
60
+
61
+ class TestNumericalSolver:
62
+ def test_constructors(self, numerical_solver: NumericalSolver):
63
+ assert numerical_solver is not None
64
+ assert isinstance(numerical_solver, NumericalSolver)
65
+ assert numerical_solver.is_defined()
66
+
67
+ def test_comparators(self, numerical_solver: NumericalSolver):
68
+ assert numerical_solver == numerical_solver
69
+ assert (numerical_solver != numerical_solver) is False
70
+
71
+ def test_get_types(
72
+ self,
73
+ numerical_solver_default_inputs: tuple[
74
+ NumericalSolver.LogType, NumericalSolver.StepperType, float, float, float
75
+ ],
76
+ numerical_solver: NumericalSolver,
77
+ ):
78
+ (
79
+ log_type,
80
+ stepper_type,
81
+ initial_time_step,
82
+ relative_tolerance,
83
+ absolute_tolerance,
84
+ ) = numerical_solver_default_inputs
85
+
86
+ assert numerical_solver.get_log_type() == log_type
87
+ assert numerical_solver.get_stepper_type() == stepper_type
88
+ assert numerical_solver.get_time_step() == initial_time_step
89
+ assert numerical_solver.get_relative_tolerance() == relative_tolerance
90
+ assert numerical_solver.get_absolute_tolerance() == absolute_tolerance
91
+ assert numerical_solver.get_observed_state_vectors() is not None
92
+
93
+ def test_get_string_from_types(self):
94
+ assert (
95
+ NumericalSolver.string_from_stepper_type(
96
+ NumericalSolver.StepperType.RungeKutta4
97
+ )
98
+ == "RungeKutta4"
99
+ )
100
+ assert (
101
+ NumericalSolver.string_from_stepper_type(
102
+ NumericalSolver.StepperType.RungeKuttaCashKarp54
103
+ )
104
+ == "RungeKuttaCashKarp54"
105
+ )
106
+ assert (
107
+ NumericalSolver.string_from_stepper_type(
108
+ NumericalSolver.StepperType.RungeKuttaFehlberg78
109
+ )
110
+ == "RungeKuttaFehlberg78"
111
+ )
112
+ assert (
113
+ NumericalSolver.string_from_log_type(NumericalSolver.LogType.NoLog) == "NoLog"
114
+ )
115
+ assert (
116
+ NumericalSolver.string_from_log_type(NumericalSolver.LogType.LogConstant)
117
+ == "LogConstant"
118
+ )
119
+ assert (
120
+ NumericalSolver.string_from_log_type(NumericalSolver.LogType.LogAdaptive)
121
+ == "LogAdaptive"
122
+ )
123
+
124
+ def test_integrate_duration(
125
+ self, numerical_solver: NumericalSolver, initial_state_vec: np.ndarray
126
+ ):
127
+ integration_duration: float = 100.0
128
+
129
+ state_vector, _ = numerical_solver.integrate_duration(
130
+ initial_state_vec, integration_duration, oscillator
131
+ )
132
+
133
+ assert 5e-9 >= abs(state_vector[0] - math.sin(integration_duration))
134
+ assert 5e-9 >= abs(state_vector[1] - math.cos(integration_duration))
135
+
136
+ integration_durations = np.arange(100.0, 1000.0, 50.0)
137
+ solutions = numerical_solver.integrate_duration(
138
+ initial_state_vec, integration_durations, oscillator
139
+ )
140
+
141
+ for solution, integration_duration in zip(solutions, integration_durations):
142
+ state_vector, _ = solution
143
+
144
+ assert 5e-9 >= abs(state_vector[0] - math.sin(integration_duration))
145
+ assert 5e-9 >= abs(state_vector[1] - math.cos(integration_duration))
146
+
147
+ def test_integrate_time(self, numerical_solver: NumericalSolver):
148
+ start_time: float = 500.0
149
+ end_time: float = start_time + 100.0
150
+
151
+ initial_state_vec = get_state_vec(start_time)
152
+
153
+ state_vector, _ = numerical_solver.integrate_time(
154
+ initial_state_vec, start_time, end_time, oscillator
155
+ )
156
+
157
+ assert 5e-9 >= abs(state_vector[0] - math.sin(end_time))
158
+ assert 5e-9 >= abs(state_vector[1] - math.cos(end_time))
159
+
160
+ end_times = np.arange(600.0, 1000.0, 50.0)
161
+ solutions = numerical_solver.integrate_time(
162
+ initial_state_vec, start_time, end_times, oscillator
163
+ )
164
+
165
+ for solution, end_time in zip(solutions, end_times):
166
+ state_vector, _ = solution
167
+
168
+ assert 5e-9 >= abs(state_vector[0] - math.sin(end_time))
169
+ assert 5e-9 >= abs(state_vector[1] - math.cos(end_time))
170
+
171
+ def test_default(self):
172
+ assert NumericalSolver.default() is not None
173
+
174
+ def test_undefined(self):
175
+ assert NumericalSolver.undefined() is not None
176
+ assert NumericalSolver.undefined().is_defined() is False
@@ -0,0 +1,24 @@
1
+ # Apache License 2.0
2
+
3
+ import ostk.mathematics as mathematics
4
+
5
+
6
+ Angle = mathematics.geometry.Angle
7
+
8
+ Point2d = mathematics.geometry.d2.object.Point
9
+ Polygon2d = mathematics.geometry.d2.object.Polygon
10
+ Transformation2d = mathematics.geometry.d2.Transformation
11
+ Point3d = mathematics.geometry.d3.object.Point
12
+ PointSet3d = mathematics.geometry.d3.object.PointSet
13
+ Line3d = mathematics.geometry.d3.object.Line
14
+ Ray3d = mathematics.geometry.d3.object.Ray
15
+ Segment3d = mathematics.geometry.d3.object.Segment
16
+ Plane = mathematics.geometry.d3.object.Plane
17
+ Polygon3d = mathematics.geometry.d3.object.Polygon
18
+ Cuboid = mathematics.geometry.d3.object.Cuboid
19
+ Sphere = mathematics.geometry.d3.object.Sphere
20
+ Ellipsoid = mathematics.geometry.d3.object.Ellipsoid
21
+ Transformation3d = mathematics.geometry.d3.Transformation
22
+ Quaternion = mathematics.geometry.d3.transformation.rotation.Quaternion
23
+ RotationVector = mathematics.geometry.d3.transformation.rotation.RotationVector
24
+ RotationMatrix = mathematics.geometry.d3.transformation.rotation.RotationMatrix