relationalai 1.0.0a3__py3-none-any.whl → 1.0.0a5__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.
Files changed (118) hide show
  1. relationalai/config/config.py +47 -21
  2. relationalai/config/connections/__init__.py +5 -2
  3. relationalai/config/connections/duckdb.py +2 -2
  4. relationalai/config/connections/local.py +31 -0
  5. relationalai/config/connections/snowflake.py +0 -1
  6. relationalai/config/external/raiconfig_converter.py +235 -0
  7. relationalai/config/external/raiconfig_models.py +202 -0
  8. relationalai/config/external/utils.py +31 -0
  9. relationalai/config/shims.py +1 -0
  10. relationalai/semantics/__init__.py +10 -8
  11. relationalai/semantics/backends/sql/sql_compiler.py +1 -4
  12. relationalai/semantics/experimental/__init__.py +0 -0
  13. relationalai/semantics/experimental/builder.py +295 -0
  14. relationalai/semantics/experimental/builtins.py +154 -0
  15. relationalai/semantics/frontend/base.py +67 -42
  16. relationalai/semantics/frontend/core.py +34 -6
  17. relationalai/semantics/frontend/front_compiler.py +209 -37
  18. relationalai/semantics/frontend/pprint.py +6 -2
  19. relationalai/semantics/metamodel/__init__.py +7 -0
  20. relationalai/semantics/metamodel/metamodel.py +2 -0
  21. relationalai/semantics/metamodel/metamodel_analyzer.py +58 -16
  22. relationalai/semantics/metamodel/pprint.py +6 -1
  23. relationalai/semantics/metamodel/rewriter.py +11 -7
  24. relationalai/semantics/metamodel/typer.py +116 -41
  25. relationalai/semantics/reasoners/__init__.py +11 -0
  26. relationalai/semantics/reasoners/graph/__init__.py +35 -0
  27. relationalai/semantics/reasoners/graph/core.py +9028 -0
  28. relationalai/semantics/std/__init__.py +30 -10
  29. relationalai/semantics/std/aggregates.py +641 -12
  30. relationalai/semantics/std/common.py +146 -13
  31. relationalai/semantics/std/constraints.py +71 -1
  32. relationalai/semantics/std/datetime.py +904 -21
  33. relationalai/semantics/std/decimals.py +143 -2
  34. relationalai/semantics/std/floats.py +57 -4
  35. relationalai/semantics/std/integers.py +98 -4
  36. relationalai/semantics/std/math.py +857 -35
  37. relationalai/semantics/std/numbers.py +216 -20
  38. relationalai/semantics/std/re.py +213 -5
  39. relationalai/semantics/std/strings.py +437 -44
  40. relationalai/shims/executor.py +60 -52
  41. relationalai/shims/fixtures.py +85 -0
  42. relationalai/shims/helpers.py +26 -2
  43. relationalai/shims/hoister.py +28 -9
  44. relationalai/shims/mm2v0.py +204 -173
  45. relationalai/tools/cli/cli.py +192 -10
  46. relationalai/tools/cli/components/progress_reader.py +1 -1
  47. relationalai/tools/cli/docs.py +394 -0
  48. relationalai/tools/debugger.py +11 -4
  49. relationalai/tools/qb_debugger.py +435 -0
  50. relationalai/tools/typer_debugger.py +1 -2
  51. relationalai/util/dataclasses.py +3 -5
  52. relationalai/util/docutils.py +1 -2
  53. relationalai/util/error.py +2 -5
  54. relationalai/util/python.py +23 -0
  55. relationalai/util/runtime.py +1 -2
  56. relationalai/util/schema.py +2 -4
  57. relationalai/util/structures.py +4 -2
  58. relationalai/util/tracing.py +8 -2
  59. {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/METADATA +8 -5
  60. {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/RECORD +118 -95
  61. {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/WHEEL +1 -1
  62. v0/relationalai/__init__.py +1 -1
  63. v0/relationalai/clients/client.py +52 -18
  64. v0/relationalai/clients/exec_txn_poller.py +122 -0
  65. v0/relationalai/clients/local.py +23 -8
  66. v0/relationalai/clients/resources/azure/azure.py +36 -11
  67. v0/relationalai/clients/resources/snowflake/__init__.py +4 -4
  68. v0/relationalai/clients/resources/snowflake/cli_resources.py +12 -1
  69. v0/relationalai/clients/resources/snowflake/direct_access_resources.py +124 -100
  70. v0/relationalai/clients/resources/snowflake/engine_service.py +381 -0
  71. v0/relationalai/clients/resources/snowflake/engine_state_handlers.py +35 -29
  72. v0/relationalai/clients/resources/snowflake/error_handlers.py +43 -2
  73. v0/relationalai/clients/resources/snowflake/snowflake.py +277 -179
  74. v0/relationalai/clients/resources/snowflake/use_index_poller.py +8 -0
  75. v0/relationalai/clients/types.py +5 -0
  76. v0/relationalai/errors.py +19 -1
  77. v0/relationalai/semantics/lqp/algorithms.py +173 -0
  78. v0/relationalai/semantics/lqp/builtins.py +199 -2
  79. v0/relationalai/semantics/lqp/executor.py +68 -37
  80. v0/relationalai/semantics/lqp/ir.py +28 -2
  81. v0/relationalai/semantics/lqp/model2lqp.py +215 -45
  82. v0/relationalai/semantics/lqp/passes.py +13 -658
  83. v0/relationalai/semantics/lqp/rewrite/__init__.py +12 -0
  84. v0/relationalai/semantics/lqp/rewrite/algorithm.py +385 -0
  85. v0/relationalai/semantics/lqp/rewrite/constants_to_vars.py +70 -0
  86. v0/relationalai/semantics/lqp/rewrite/deduplicate_vars.py +104 -0
  87. v0/relationalai/semantics/lqp/rewrite/eliminate_data.py +108 -0
  88. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +25 -3
  89. v0/relationalai/semantics/lqp/rewrite/period_math.py +77 -0
  90. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +65 -31
  91. v0/relationalai/semantics/lqp/rewrite/unify_definitions.py +317 -0
  92. v0/relationalai/semantics/lqp/utils.py +11 -1
  93. v0/relationalai/semantics/lqp/validators.py +14 -1
  94. v0/relationalai/semantics/metamodel/builtins.py +2 -1
  95. v0/relationalai/semantics/metamodel/compiler.py +2 -1
  96. v0/relationalai/semantics/metamodel/dependency.py +12 -3
  97. v0/relationalai/semantics/metamodel/executor.py +11 -1
  98. v0/relationalai/semantics/metamodel/factory.py +2 -2
  99. v0/relationalai/semantics/metamodel/helpers.py +7 -0
  100. v0/relationalai/semantics/metamodel/ir.py +3 -2
  101. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +30 -20
  102. v0/relationalai/semantics/metamodel/rewrite/flatten.py +50 -13
  103. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +9 -3
  104. v0/relationalai/semantics/metamodel/typer/checker.py +6 -4
  105. v0/relationalai/semantics/metamodel/typer/typer.py +4 -3
  106. v0/relationalai/semantics/metamodel/visitor.py +4 -3
  107. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +1 -1
  108. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +336 -86
  109. v0/relationalai/semantics/rel/compiler.py +2 -1
  110. v0/relationalai/semantics/rel/executor.py +3 -2
  111. v0/relationalai/semantics/tests/lqp/__init__.py +0 -0
  112. v0/relationalai/semantics/tests/lqp/algorithms.py +345 -0
  113. v0/relationalai/tools/cli.py +339 -186
  114. v0/relationalai/tools/cli_controls.py +216 -67
  115. v0/relationalai/tools/cli_helpers.py +410 -6
  116. v0/relationalai/util/format.py +5 -2
  117. {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/entry_points.txt +0 -0
  118. {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,22 @@
1
+ """
2
+ Mathematical functions.
3
+
4
+ This module provides comprehensive mathematical functions including:
5
+ - Basic operations
6
+ - Power and logarithmic functions
7
+ - Trigonometric functions
8
+ - Hyperbolic functions
9
+ - Comparison functions
10
+ - Float checks
11
+ """
1
12
  from __future__ import annotations
2
13
 
3
14
  from . import NumberValue, FloatValue, _get_number_value
4
15
  from ..frontend.base import Library, Expression, Field
5
16
  from ..frontend.core import Numeric, Number, Integer, Float, make_overloads, minus, mul, div, power
17
+ from relationalai.util.docutils import include_in_docs
18
+
19
+ __include_in_docs__ = True
6
20
 
7
21
  # the front-end library object
8
22
  library = Library("math")
@@ -11,59 +25,321 @@ library = Library("math")
11
25
  # Basics
12
26
  # ------------------------------
13
27
  _abs = library.Relation("abs", [Field.input("value", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 2))
14
- _ceil = library.Relation("ceil", [Field.input("value", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 2))
15
- _clip = library.Relation("clip", [Field.input("value", Numeric), Field.input("lower", Numeric), Field.input("upper", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 4))
16
- _factorial = library.Relation("factorial", [Field.input("value", Integer), Field("result", Integer)])
17
- _floor = library.Relation("floor", [Field.input("value", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 2))
18
- _isclose = library.Relation("isclose", [Field.input("tolerance", Numeric), Field.input("x", Numeric), Field.input("y", Numeric)], overloads=make_overloads([Number, Float], 3))
19
- _sign = library.Relation("sign", [Field.input("x", Numeric), Field("result", Integer)], overloads=[[Number, Integer], [Float, Integer]])
20
- _trunc_divide = library.Relation("trunc_divide", [Field.input("numerator", Number), Field.input("denominator", Number), Field("result", Number)])
21
- _maximum = library.Relation("maximum", [Field.input("left", Numeric), Field.input("right", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 3))
22
- _minimum = library.Relation("minimum", [Field.input("left", Numeric), Field.input("right", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 3))
23
- _isinf = library.Relation("isinf", [Field.input("value", Float)])
24
- _isnan = library.Relation("isnan", [Field.input("value", Float)])
25
28
 
29
+ @include_in_docs
26
30
  def abs(value: NumberValue) -> Expression:
31
+ """
32
+ Compute the absolute value.
33
+
34
+ Parameters
35
+ ----------
36
+ value: NumberValue
37
+ The input value.
38
+
39
+ Returns
40
+ -------
41
+ Expression
42
+ An `Expression` computing the absolute value of the input. Returns `Number` if the
43
+ input is `Number`, or `Float` if the input is `Float`.
44
+
45
+ Examples
46
+ --------
47
+ Compute absolute value:
48
+
49
+ >>> select(math.abs(Transaction.amount))
50
+ >>> select(math.abs(Temperature.deviation + 1.0))
51
+ """
27
52
  return _abs(value)
28
53
 
54
+ _ceil = library.Relation("ceil", [Field.input("value", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 2))
55
+
56
+ @include_in_docs
29
57
  def ceil(value: NumberValue) -> Expression:
58
+ """
59
+ Round up to the nearest integer.
60
+
61
+ Parameters
62
+ ----------
63
+ value: NumberValue
64
+ The input value.
65
+
66
+ Returns
67
+ -------
68
+ Expression
69
+ An `Expression` computing the ceiling value of the input. Returns `Number` if the
70
+ input is `Number`, or `Float` if the input is `Float`.
71
+
72
+ Examples
73
+ --------
74
+ Round up to nearest integer:
75
+
76
+ >>> select(math.ceil(Product.price))
77
+ >>> select(math.ceil(3.14))
78
+ """
30
79
  return _ceil(value)
31
80
 
81
+ _clip = library.Relation("clip", [Field.input("value", Numeric), Field.input("lower", Numeric), Field.input("upper", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 4))
82
+
83
+ @include_in_docs
32
84
  def clip(value: NumberValue, lower: NumberValue, upper: NumberValue) -> Expression:
85
+ """
86
+ Clip (clamp) a value to a range.
87
+
88
+ Parameters
89
+ ----------
90
+ value: NumberValue
91
+ The value to clip.
92
+ lower: NumberValue
93
+ The lower bound.
94
+ upper: NumberValue
95
+ The upper bound.
96
+
97
+ Returns
98
+ -------
99
+ Expression
100
+ An `Expression` computing the clipped value (min(upper, max(lower, value))). Returns
101
+ `Number` if the input is `Number`, or `Float` if the input is `Float`.
102
+
103
+ Examples
104
+ --------
105
+ Clip values to a range:
106
+
107
+ >>> select(math.clip(Employee.score, 0, 100))
108
+ >>> select(math.clip(Temperature.reading, -10, 40))
109
+ """
33
110
  # CLIP = CLAMP(v,min,max) = LEAST(max,GREATEST(min,v))
34
111
  return _clip(lower, upper, value)
35
112
 
113
+ _factorial = library.Relation("factorial", [Field.input("value", Integer), Field("result", Integer)])
114
+
115
+ @include_in_docs
36
116
  def factorial(value: NumberValue) -> Expression:
117
+ """
118
+ Compute the factorial of a non-negative integer.
119
+
120
+ Parameters
121
+ ----------
122
+ value: NumberValue
123
+ The non-negative integer input.
124
+
125
+ Returns
126
+ -------
127
+ Expression
128
+ An `Expression` computing the factorial. Returns `Integer`. If the input value is
129
+ not statically known to be non-negative, but turns out to be negative at runtime,
130
+ returns `NaN`.
131
+
132
+ Raises
133
+ ------
134
+ ValueError
135
+ If value can be computed statically and is negative.
136
+
137
+ Examples
138
+ --------
139
+ Compute factorial:
140
+
141
+ >>> select(math.factorial(5))
142
+ >>> select(math.factorial(Calculation.n))
143
+ """
37
144
  v = _get_number_value(value)
38
145
  if v is not None and v < 0:
39
146
  raise ValueError("Cannot take the factorial of a negative number")
40
147
  return _factorial(value)
41
148
 
149
+ _floor = library.Relation("floor", [Field.input("value", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 2))
150
+
151
+ @include_in_docs
42
152
  def floor(value: NumberValue) -> Expression:
153
+ """
154
+ Round down to the nearest integer.
155
+
156
+ Parameters
157
+ ----------
158
+ value: NumberValue
159
+ The input value.
160
+
161
+ Returns
162
+ -------
163
+ Expression
164
+ An `Expression` computing the floor value of the input. Returns `Number` if the
165
+ input is `Number`, or `Float` if the input is `Float`.
166
+
167
+ Examples
168
+ --------
169
+ Round down to nearest integer:
170
+
171
+ >>> select(math.floor(Product.price))
172
+ >>> select(math.floor(3.99))
173
+ """
43
174
  return _floor(value)
44
175
 
176
+ _isclose = library.Relation("isclose", [Field.input("tolerance", Numeric), Field.input("x", Numeric), Field.input("y", Numeric)], overloads=make_overloads([Number, Float], 3))
177
+
178
+ @include_in_docs
45
179
  def isclose(x: NumberValue, y: NumberValue, tolerance: NumberValue = 1e-9) -> Expression:
180
+ """
181
+ Check if two values are approximately equal within a tolerance.
182
+
183
+ Parameters
184
+ ----------
185
+ x: NumberValue
186
+ First value.
187
+ y: NumberValue
188
+ Second value.
189
+ tolerance: NumberValue
190
+ Absolute tolerance for comparison. Default: 1e-9.
191
+
192
+ Returns
193
+ -------
194
+ Expression
195
+ An `Expression` that evaluates to true if abs(x - y) < tolerance.
196
+ """
46
197
  # APPROX_EQUAL = ABS(x - y) < tolerance
47
198
  return _isclose(tolerance, x, y)
48
199
 
200
+ _sign = library.Relation("sign", [Field.input("x", Numeric), Field("result", Integer)], overloads=[[Number, Integer], [Float, Integer]])
201
+
202
+ @include_in_docs
49
203
  def sign(x: NumberValue) -> Expression:
204
+ """
205
+ Compute the sign of a number.
206
+
207
+ Parameters
208
+ ----------
209
+ x: NumberValue
210
+ The input value.
211
+
212
+ Returns
213
+ -------
214
+ Expression
215
+ An `Expression` computing -1 for negative, 0 for zero, 1 for positive. Returns `Integer`.
216
+
217
+ Examples
218
+ --------
219
+ Get sign of values:
220
+
221
+ >>> select(math.sign(Account.balance))
222
+ >>> select(math.sign(Temperature.deviation))
223
+ """
50
224
  return _sign(x)
51
225
 
226
+ _trunc_divide = library.Relation("trunc_divide", [Field.input("numerator", Number), Field.input("denominator", Number), Field("result", Number)])
227
+
228
+ @include_in_docs
52
229
  def trunc_divide(numerator: NumberValue, denominator: NumberValue) -> Expression:
230
+ """
231
+ Perform truncated division.
232
+
233
+ Parameters
234
+ ----------
235
+ numerator: NumberValue
236
+ The numerator.
237
+ denominator: NumberValue
238
+ The denominator.
239
+
240
+ Returns
241
+ -------
242
+ Expression
243
+ An `Expression` computing the truncated quotient. Returns `Number`.
244
+ """
53
245
  return _trunc_divide(numerator, denominator)
54
246
 
247
+ _maximum = library.Relation("maximum", [Field.input("left", Numeric), Field.input("right", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 3))
248
+
249
+ @include_in_docs
55
250
  def maximum(left: NumberValue, right: NumberValue) -> Expression:
251
+ """
252
+ Find the maximum of two values.
253
+
254
+ Parameters
255
+ ----------
256
+ left: NumberValue
257
+ First value.
258
+ right: NumberValue
259
+ Second value.
260
+
261
+ Returns
262
+ -------
263
+ Expression
264
+ An `Expression` computing the maximum value. Returns `Number` if the inputs are
265
+ `Number`, or `Float` if the inputs are `Float`.
266
+
267
+ Examples
268
+ --------
269
+ Find maximum of two values:
270
+
271
+ >>> select(math.maximum(Employee.salary, Employee.bonus))
272
+ >>> select(math.maximum(10, Product.discount))
273
+ """
56
274
  # GREATEST
57
275
  return _maximum(left, right)
58
276
 
277
+ _minimum = library.Relation("minimum", [Field.input("left", Numeric), Field.input("right", Numeric), Field("result", Numeric)], overloads=make_overloads([Number, Float], 3))
278
+
279
+ @include_in_docs
59
280
  def minimum(left: NumberValue, right: NumberValue) -> Expression:
281
+ """
282
+ Find the minimum of two values.
283
+
284
+ Parameters
285
+ ----------
286
+ left: NumberValue
287
+ First value.
288
+ right: NumberValue
289
+ Second value.
290
+
291
+ Returns
292
+ -------
293
+ Expression
294
+ An `Expression` computing the minimum value. Returns `Number` if the inputs are
295
+ `Number`, or `Float` if the inputs are `Float`.
296
+
297
+ Examples
298
+ --------
299
+ Find minimum of two values:
300
+
301
+ >>> select(math.minimum(Product.list_price, Product.sale_price))
302
+ >>> select(math.minimum(100, Order.total))
303
+ """
60
304
  # LEAST
61
305
  return _minimum(left, right)
62
306
 
307
+ _isinf = library.Relation("isinf", [Field.input("value", Float)])
308
+
309
+ @include_in_docs
63
310
  def isinf(value: FloatValue) -> Expression:
311
+ """
312
+ Check if a float value is infinite.
313
+
314
+ Parameters
315
+ ----------
316
+ value: FloatValue
317
+ The float value to check.
318
+
319
+ Returns
320
+ -------
321
+ Expression
322
+ An `Expression` that evaluates to true if value is infinite.
323
+ """
64
324
  return _isinf(value)
65
325
 
326
+ _isnan = library.Relation("isnan", [Field.input("value", Float)])
327
+
328
+ @include_in_docs
66
329
  def isnan(value: FloatValue) -> Expression:
330
+ """
331
+ Check if a float value is NaN (Not a Number).
332
+
333
+ Parameters
334
+ ----------
335
+ value: FloatValue
336
+ The float value to check.
337
+
338
+ Returns
339
+ -------
340
+ Expression
341
+ An `Expression` that evaluates to true if value is NaN.
342
+ """
67
343
  return _isnan(value)
68
344
 
69
345
  # -------------------------------
@@ -71,34 +347,177 @@ def isnan(value: FloatValue) -> Expression:
71
347
  # -------------------------------
72
348
 
73
349
  _cbrt = library.Relation("cbrt", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
74
- _sqrt = library.Relation("sqrt", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
75
- _exp = library.Relation("exp", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
76
- _power = library.Relation("power", [Field.input("base", Numeric), Field.input("exponent", Numeric), Field("result", Float)],
77
- overloads=[
78
- #[Number, Number, Float], # v0 and engines are not handling this correctly
79
- [Float, Float, Float]])
80
- _log = library.Relation("log", [Field.input("base", Numeric), Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Number, Float], [Float, Float, Float]])
81
- _natural_log = library.Relation("natural_log", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
82
350
 
351
+ @include_in_docs
83
352
  def cbrt(value: NumberValue) -> Expression:
353
+ """
354
+ Compute the cube root.
355
+
356
+ Parameters
357
+ ----------
358
+ value: NumberValue
359
+ The input value.
360
+
361
+ Returns
362
+ -------
363
+ Expression
364
+ An `Expression` computing the cube root. Returns `Float`.
365
+ """
84
366
  return _cbrt(value)
85
367
 
368
+ _sqrt = library.Relation("sqrt", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
369
+
370
+ @include_in_docs
86
371
  def sqrt(value: NumberValue) -> Expression:
372
+ """
373
+ Compute the square root.
374
+
375
+ Parameters
376
+ ----------
377
+ value: NumberValue
378
+ The non-negative input value.
379
+
380
+ Returns
381
+ -------
382
+ Expression
383
+ An `Expression` computing the square root. Returns `Float`. If the input value is
384
+ not statically known to be non-negative, but turns out to be negative at runtime,
385
+ returns `NaN`.
386
+
387
+ Raises
388
+ ------
389
+ ValueError
390
+ If value is negative.
391
+
392
+ Examples
393
+ --------
394
+ Compute square root:
395
+
396
+ >>> select(math.sqrt(16))
397
+ >>> select(math.sqrt(Geometry.area))
398
+ """
87
399
  v = _get_number_value(value)
88
400
  if v is not None and v < 0:
89
401
  raise ValueError("Cannot take the square root of a negative number")
90
402
  return _sqrt(value)
91
403
 
404
+ _exp = library.Relation("exp", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
405
+
406
+ @include_in_docs
92
407
  def exp(value: NumberValue) -> Expression:
408
+ """
409
+ Compute the exponential function (e^value).
410
+
411
+ Parameters
412
+ ----------
413
+ value: NumberValue
414
+ The exponent.
415
+
416
+ Returns
417
+ -------
418
+ Expression
419
+ An `Expression` computing e raised to the power of value. Returns `Float`.
420
+
421
+ Examples
422
+ --------
423
+ Compute exponential:
424
+
425
+ >>> select(math.exp(1))
426
+ >>> select(math.exp(Growth.rate))
427
+ """
93
428
  return _exp(value)
94
429
 
430
+ _power = library.Relation("power", [Field.input("base", Numeric), Field.input("exponent", Numeric), Field("result", Float)],
431
+ overloads=[
432
+ #[Number, Number, Float], # v0 and engines are not handling this correctly
433
+ [Float, Float, Float]])
434
+
435
+ @include_in_docs
95
436
  def pow(base: NumberValue, exponent: NumberValue) -> Expression:
437
+ """
438
+ Raise a base to an exponent.
439
+
440
+ Parameters
441
+ ----------
442
+ base: NumberValue
443
+ The base value.
444
+ exponent: NumberValue
445
+ The exponent.
446
+
447
+ Returns
448
+ -------
449
+ Expression
450
+ An `Expression` computing `base^exponent`. Returns `Float`.
451
+
452
+ Examples
453
+ --------
454
+ Raise to a power:
455
+
456
+ >>> select(math.pow(2, 8))
457
+ >>> select(math.pow(Investment.principal, Investment.years))
458
+ """
96
459
  return _power(base, exponent)
97
460
 
461
+ _natural_log = library.Relation("natural_log", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
462
+
463
+ @include_in_docs
98
464
  def natural_log(value: NumberValue) -> Expression:
465
+ """
466
+ Compute the natural logarithm (ln).
467
+
468
+ Parameters
469
+ ----------
470
+ value: NumberValue
471
+ A positive input number value. If the input value is not statically known to be
472
+ non-positive, but turns out to be non-positive at runtime, returns `NaN`.
473
+
474
+ Returns
475
+ -------
476
+ Expression
477
+ An `Expression` computing ln(value). Always returns a `Float`.
478
+
479
+ Raises
480
+ ------
481
+ ValueError
482
+ If `value` is can be computed statically and is non-positive.
483
+ """
484
+ v = _get_number_value(value)
485
+ if v is not None and v <= 0:
486
+ raise ValueError("Cannot take the logarithm of a non-positive number")
99
487
  return _natural_log(value)
100
488
 
489
+ _log = library.Relation("log", [Field.input("base", Numeric), Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Number, Float], [Float, Float, Float]])
490
+
491
+ @include_in_docs
101
492
  def log(x: NumberValue, base: NumberValue | None = None) -> Expression:
493
+ """
494
+ Compute the logarithm with optional base.
495
+
496
+ Parameters
497
+ ----------
498
+ x: NumberValue
499
+ The positive input value. If the input value is not statically known to be
500
+ non-positive, but turns out to be non-positive at runtime, returns `NaN`.
501
+ base: NumberValue | None
502
+ The logarithm base. If None, computes natural log. Default: None.
503
+
504
+ Returns
505
+ -------
506
+ Expression
507
+ An `Expression` computing log_base(x), or ln(x) if base is None. Returns `Float`.
508
+
509
+ Raises
510
+ ------
511
+ ValueError
512
+ If `x` can be computed statically and is non-positive.
513
+
514
+ Examples
515
+ --------
516
+ Compute logarithm:
517
+
518
+ >>> select(math.log(100, 10))
519
+ >>> select(math.log(Signal.amplitude))
520
+ """
102
521
  v = _get_number_value(x)
103
522
  if v is not None and v <= 0:
104
523
  raise ValueError("Cannot take the logarithm of a non-positive number")
@@ -106,10 +525,64 @@ def log(x: NumberValue, base: NumberValue | None = None) -> Expression:
106
525
  return natural_log(x)
107
526
  return _log(base, x)
108
527
 
528
+ @include_in_docs
109
529
  def log2(value: NumberValue) -> Expression:
530
+ """
531
+ Compute the base-2 logarithm.
532
+
533
+ Parameters
534
+ ----------
535
+ value: NumberValue
536
+ The positive input value. If the input value is not statically known to be
537
+ non-positive, but turns out to be non-positive at runtime, returns `NaN`.
538
+
539
+ Returns
540
+ -------
541
+ Expression
542
+ An `Expression` computing log_2(value). Returns `Float`.
543
+
544
+ Raises
545
+ ------
546
+ ValueError
547
+ If `x` can be computed statically and is non-positive.
548
+
549
+ Examples
550
+ --------
551
+ Compute base-2 logarithm:
552
+
553
+ >>> select(math.log2(1024))
554
+ >>> select(math.log2(Data.size))
555
+ """
110
556
  return log(value, 2)
111
557
 
558
+ @include_in_docs
112
559
  def log10(value: NumberValue) -> Expression:
560
+ """
561
+ Compute the base-10 logarithm.
562
+
563
+ Parameters
564
+ ----------
565
+ value: NumberValue
566
+ The positive input value. If the input value is not statically known to be
567
+ non-positive, but turns out to be non-positive at runtime, returns `NaN`.
568
+
569
+ Returns
570
+ -------
571
+ Expression
572
+ An `Expression` computing log_10(value). Returns `Float`.
573
+
574
+ Raises
575
+ ------
576
+ ValueError
577
+ If `x` can be computed statically and is non-positive.
578
+
579
+ Examples
580
+ --------
581
+ Compute base-10 logarithm:
582
+
583
+ >>> select(math.log10(1000))
584
+ >>> select(math.log10(Signal.power))
585
+ """
113
586
  return log(value, 10)
114
587
 
115
588
 
@@ -119,71 +592,355 @@ def log10(value: NumberValue) -> Expression:
119
592
  # ------------------------------
120
593
 
121
594
  _degrees = library.Relation("degrees", [Field.input("radians", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
122
- _radians = library.Relation("radians", [Field.input("degrees", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
123
- _cos = library.Relation("cos", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
124
- _sin = library.Relation("sin", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
125
- _tan = library.Relation("tan", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
126
- _cot = library.Relation("cot", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
127
- _acos = library.Relation("acos", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
128
- _asin = library.Relation("asin", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
129
- _atan = library.Relation("atan", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
130
- _acot = library.Relation("acot", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
131
- _cosh = library.Relation("cosh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
132
- _sinh = library.Relation("sinh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
133
- _tanh = library.Relation("tanh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
134
- _acosh = library.Relation("acosh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
135
- _asinh = library.Relation("asinh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
136
- _atanh = library.Relation("atanh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
137
595
 
596
+ @include_in_docs
138
597
  def degrees(radians: NumberValue) -> Expression:
598
+ """
599
+ Convert radians to degrees.
600
+
601
+ Parameters
602
+ ----------
603
+ radians: NumberValue
604
+ The angle in radians.
605
+
606
+ Returns
607
+ -------
608
+ Expression
609
+ An `Expression` computing the angle in degrees. Returns `Float`.
610
+
611
+ Examples
612
+ --------
613
+ Convert radians to degrees:
614
+
615
+ >>> select(math.degrees(3.14159))
616
+ >>> select(math.degrees(Location.lat_rad))
617
+ """
139
618
  return _degrees(radians)
140
619
 
620
+ _radians = library.Relation("radians", [Field.input("degrees", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
621
+
622
+ @include_in_docs
141
623
  def radians(degrees: NumberValue) -> Expression:
624
+ """
625
+ Convert degrees to radians.
626
+
627
+ Parameters
628
+ ----------
629
+ degrees: NumberValue
630
+ The angle in degrees.
631
+
632
+ Returns
633
+ -------
634
+ Expression
635
+ An `Expression` computing the angle in radians. Returns `Float`.
636
+
637
+ Examples
638
+ --------
639
+ Convert degrees to radians:
640
+
641
+ >>> select(math.radians(180))
642
+ >>> select(math.radians(Location.lat_deg))
643
+ """
142
644
  return _radians(degrees)
143
645
 
646
+ _cos = library.Relation("cos", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
647
+
648
+ @include_in_docs
144
649
  def cos(value: NumberValue) -> Expression:
650
+ """
651
+ Compute the cosine.
652
+
653
+ Parameters
654
+ ----------
655
+ value: NumberValue
656
+ The angle in radians.
657
+
658
+ Returns
659
+ -------
660
+ Expression
661
+ An `Expression` computing cos(value). Returns `Float`.
662
+
663
+ Examples
664
+ --------
665
+ Compute cosine:
666
+
667
+ >>> select(math.cos(0))
668
+ >>> select(math.cos(Wave.angle))
669
+ """
145
670
  return _cos(value)
146
671
 
672
+ _sin = library.Relation("sin", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
673
+
674
+ @include_in_docs
147
675
  def sin(value: NumberValue) -> Expression:
676
+ """
677
+ Compute the sine.
678
+
679
+ Parameters
680
+ ----------
681
+ value: NumberValue
682
+ The angle in radians.
683
+
684
+ Returns
685
+ -------
686
+ Expression
687
+ An `Expression` computing sin(value). Returns `Float`.
688
+
689
+ Examples
690
+ --------
691
+ Compute sine:
692
+
693
+ >>> select(math.sin(0))
694
+ >>> select(math.sin(Wave.phase))
695
+ """
148
696
  return _sin(value)
149
697
 
698
+ _tan = library.Relation("tan", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
699
+
700
+ @include_in_docs
150
701
  def tan(value: NumberValue) -> Expression:
702
+ """
703
+ Compute the tangent.
704
+
705
+ Parameters
706
+ ----------
707
+ value: NumberValue
708
+ The angle in radians.
709
+
710
+ Returns
711
+ -------
712
+ Expression
713
+ An `Expression` computing tan(value). Returns `Float`.
714
+
715
+ Examples
716
+ --------
717
+ Compute tangent:
718
+
719
+ >>> select(math.tan(0.785))
720
+ >>> select(math.tan(Angle.radians))
721
+ """
151
722
  return _tan(value)
152
723
 
724
+ _cot = library.Relation("cot", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
725
+
726
+ @include_in_docs
153
727
  def cot(value: NumberValue) -> Expression:
728
+ """
729
+ Compute the cotangent.
730
+
731
+ Parameters
732
+ ----------
733
+ value: NumberValue
734
+ The angle in radians.
735
+
736
+ Returns
737
+ -------
738
+ Expression
739
+ An `Expression` computing cot(value). Returns `Float`.
740
+ """
154
741
  return _cot(value)
155
742
 
743
+ _acos = library.Relation("acos", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
744
+
745
+ @include_in_docs
156
746
  def acos(value: NumberValue) -> Expression:
747
+ """
748
+ Compute the arccosine (inverse cosine).
749
+
750
+ Parameters
751
+ ----------
752
+ value: NumberValue
753
+ The input value (must be in [-1, 1]).
754
+
755
+ Returns
756
+ -------
757
+ Expression
758
+ An `Expression` computing acos(value) in radians. Returns `Float`.
759
+ """
157
760
  return _acos(value)
158
761
 
762
+ _asin = library.Relation("asin", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
763
+
764
+ @include_in_docs
159
765
  def asin(value: NumberValue) -> Expression:
766
+ """
767
+ Compute the arcsine (inverse sine).
768
+
769
+ Parameters
770
+ ----------
771
+ value: NumberValue
772
+ The input value (must be in [-1, 1]).
773
+
774
+ Returns
775
+ -------
776
+ Expression
777
+ An `Expression` computing asin(value) in radians. Returns `Float`.
778
+ """
160
779
  return _asin(value)
161
780
 
781
+ _atan = library.Relation("atan", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
782
+
783
+ @include_in_docs
162
784
  def atan(value: NumberValue) -> Expression:
785
+ """
786
+ Compute the arctangent (inverse tangent).
787
+
788
+ Parameters
789
+ ----------
790
+ value: NumberValue
791
+ The input value.
792
+
793
+ Returns
794
+ -------
795
+ Expression
796
+ An `Expression` computing atan(value) in radians. Returns `Float`.
797
+ """
163
798
  return _atan(value)
164
799
 
800
+ _acot = library.Relation("acot", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
801
+
802
+ @include_in_docs
165
803
  def acot(value: NumberValue) -> Expression:
804
+ """
805
+ Compute the arccotangent (inverse cotangent).
806
+
807
+ Parameters
808
+ ----------
809
+ value: NumberValue
810
+ The input value.
811
+
812
+ Returns
813
+ -------
814
+ Expression
815
+ An `Expression` computing acot(value) in radians. Returns `Float`.
816
+ """
166
817
  return _acot(value)
167
818
 
819
+ _cosh = library.Relation("cosh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
820
+
821
+ @include_in_docs
168
822
  def cosh(value: NumberValue) -> Expression:
823
+ """
824
+ Compute the hyperbolic cosine.
825
+
826
+ Parameters
827
+ ----------
828
+ value: NumberValue
829
+ The input value.
830
+
831
+ Returns
832
+ -------
833
+ Expression
834
+ An `Expression` computing cosh(value). Returns `Float`.
835
+ """
169
836
  return _cosh(value)
170
837
 
838
+ _sinh = library.Relation("sinh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
839
+
840
+ @include_in_docs
171
841
  def sinh(value: NumberValue) -> Expression:
842
+ """
843
+ Compute the hyperbolic sine.
844
+
845
+ Parameters
846
+ ----------
847
+ value: NumberValue
848
+ The input value.
849
+
850
+ Returns
851
+ -------
852
+ Expression
853
+ An `Expression` computing sinh(value). Returns `Float`.
854
+ """
172
855
  return _sinh(value)
173
856
 
857
+ _tanh = library.Relation("tanh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
858
+
859
+ @include_in_docs
174
860
  def tanh(value: NumberValue) -> Expression:
861
+ """
862
+ Compute the hyperbolic tangent.
863
+
864
+ Parameters
865
+ ----------
866
+ value: NumberValue
867
+ The input value.
868
+
869
+ Returns
870
+ -------
871
+ Expression
872
+ An `Expression` computing tanh(value). Returns `Float`.
873
+ """
175
874
  return _tanh(value)
176
875
 
876
+ _acosh = library.Relation("acosh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
877
+
878
+ @include_in_docs
177
879
  def acosh(value: NumberValue) -> Expression:
880
+ """
881
+ Compute the inverse hyperbolic cosine.
882
+
883
+ Parameters
884
+ ----------
885
+ value: NumberValue
886
+ The input value (must be >= 1).
887
+
888
+ Returns
889
+ -------
890
+ Expression
891
+ An `Expression` computing acosh(value). Returns `Float`.
892
+
893
+ Raises
894
+ ------
895
+ ValueError
896
+ If value is less than 1.
897
+ """
178
898
  v = _get_number_value(value)
179
899
  if v is not None and v < 1:
180
900
  raise ValueError("acosh expects a value greater than or equal to 1.")
181
901
  return _acosh(value)
182
902
 
903
+ _asinh = library.Relation("asinh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
904
+
905
+ @include_in_docs
183
906
  def asinh(value: NumberValue) -> Expression:
907
+ """
908
+ Compute the inverse hyperbolic sine.
909
+
910
+ Parameters
911
+ ----------
912
+ value: NumberValue
913
+ The input value.
914
+
915
+ Returns
916
+ -------
917
+ Expression
918
+ An `Expression` computing asinh(value). Returns `Float`.
919
+ """
184
920
  return _asinh(value)
185
921
 
922
+ _atanh = library.Relation("atanh", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
923
+
924
+ @include_in_docs
186
925
  def atanh(value: NumberValue) -> Expression:
926
+ """
927
+ Compute the inverse hyperbolic tangent.
928
+
929
+ Parameters
930
+ ----------
931
+ value: NumberValue
932
+ The input value (must be in (-1, 1) exclusive).
933
+
934
+ Returns
935
+ -------
936
+ Expression
937
+ An `Expression` computing atanh(value). Returns `Float`.
938
+
939
+ Raises
940
+ ------
941
+ ValueError
942
+ If value is not in the range (-1, 1).
943
+ """
187
944
  v = _get_number_value(value)
188
945
  if v is not None and (v <= -1 or v >= 1):
189
946
  raise ValueError("atanh expects a value between -1 and 1, exclusive.")
@@ -193,18 +950,83 @@ def atanh(value: NumberValue) -> Expression:
193
950
  # Special Functions
194
951
  # ------------------------------
195
952
  _erf = library.Relation("erf", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
196
- _erfinv = library.Relation("erfinv", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
197
953
 
954
+ @include_in_docs
198
955
  def erf(value: NumberValue) -> Expression:
956
+ """
957
+ Compute the error function.
958
+
959
+ Parameters
960
+ ----------
961
+ value: NumberValue
962
+ The input value.
963
+
964
+ Returns
965
+ -------
966
+ Expression
967
+ An `Expression` computing erf(value). Returns `Float`.
968
+ """
199
969
  return _erf(value)
200
970
 
971
+ _erfinv = library.Relation("erfinv", [Field.input("value", Numeric), Field("result", Float)], overloads=[[Number, Float], [Float, Float]])
972
+
973
+ @include_in_docs
201
974
  def erfinv(value: NumberValue) -> Expression:
975
+ """
976
+ Compute the inverse error function.
977
+
978
+ Parameters
979
+ ----------
980
+ value: NumberValue
981
+ The input value (must be in [-1, 1]).
982
+
983
+ Returns
984
+ -------
985
+ Expression
986
+ An `Expression` computing erfinv(value). Returns `Float`.
987
+
988
+ Raises
989
+ ------
990
+ ValueError
991
+ If value is not in the range [-1, 1].
992
+ """
202
993
  v = _get_number_value(value)
203
994
  if v is not None and (v < -1 or v > 1):
204
995
  raise ValueError("erfinv expects a value between -1 and 1, inclusive.")
205
996
  return _erfinv(value)
206
997
 
998
+ @include_in_docs
207
999
  def haversine(lat1: NumberValue, lon1: NumberValue, lat2: NumberValue, lon2: NumberValue, radius: NumberValue = 1.0) -> Expression:
1000
+ """
1001
+ Compute the haversine distance between two points on a sphere.
1002
+
1003
+ The haversine formula determines the great-circle distance between two points
1004
+ on a sphere given their longitudes and latitudes.
1005
+
1006
+ Parameters
1007
+ ----------
1008
+ lat1: NumberValue
1009
+ Latitude of the first point in radians.
1010
+ lon1: NumberValue
1011
+ Longitude of the first point in radians.
1012
+ lat2: NumberValue
1013
+ Latitude of the second point in radians.
1014
+ lon2: NumberValue
1015
+ Longitude of the second point in radians.
1016
+ radius: NumberValue
1017
+ Radius of the sphere. Default: 1.0.
1018
+
1019
+ Returns
1020
+ -------
1021
+ Expression
1022
+ An `Expression` computing the haversine distance. Returns `Float`.
1023
+
1024
+ Examples
1025
+ --------
1026
+ Calculate distance between two points on Earth (radius ~6371 km):
1027
+
1028
+ >>> math.haversine(lat1, lon1, lat2, lon2, radius=6371)
1029
+ """
208
1030
  # 2 * r * asin[sqrt[sin[(lat2 - lat1)/2] ^ 2 + cos[lat1] * cos[lat2] * sin[(lon2 - lon1) / 2] ^ 2]]
209
1031
  return mul(2, radius, _asin(_sqrt(
210
1032
  power(_sin(div(minus(lat2, lat1), 2)), 2) +