The Standard Library (stdlib)
Broad collection of Rel relations that perform essential and commonly used tasks.
^Date
^Date(n, d)
Create a Date, d
, representing the date at day n
of the proleptic Gregorian calendar.
Example:
def output(d) = ^Date(734503, d)
//output> 2012-01-01
For more details, see the rel:base:^Date
docstring.
^Date
^Date[year in Int, month in Int, day in Int]
Create a Date from its three components: year, month and day. The three arguments are required to be Int64.
^Date
^Date[dt in DateTime, tz in String]
Create a Date
from a DateTime
, with timezone tz
.
The timezone argument is necessary for the Date
because DateTime
is an instant of time
that is timezone independent. For different locations on earth (timezones), a DateTime
has
different dates.
^DateTime
^DateTime(n, dt)
Create a DateTime, dt
, representing the date at millisecond n
of the proleptic Gregorian calendar.
Example:
def output(dt) = ^DateTime(63568386000000, dt)
//output> 2015-05-27T05:00:00.000Z
For more details, see the rel:base:^DateTime
docstring.
^DateTime
^DateTime[year, month, day, hour, minute, second, millisecond, tz in String]
Create a DateTime
from a year, month, day, hour, minute, second, and millisecond.
The timezone argument tz
is necessary to correctly interpret what instant in time this is.
There can be multiple DateTime
values for one set of arguments: for example, with the
ending of daylight saving time at 2am, every time between 1am and 2am occurs twice and has
two corresponding instants of time.
For part values that are out of range, there are no tuples (there is no error).
^DateTime
^DateTime[date, hour, minute, second, millisecond, tz in String]
Create a DateTime
from a date, hour, minute, second, and millisecond.
This constructor uses the year, month, and day from the date
and then
constructs a DateTime
in the same way as the constructor with all parts as arguments.
^DateTime
^DateTime[year, month, day, tz in String]
Create a DateTime
for the given year, month, and day, with the time components all set to 0.
The resulting DateTime
is the first millisecond for the given date and time zone tz
.
See the ^DateTime constructor with time components as arguments for more details.
^DateTime
^DateTime[date in Date, tz in String]
Create a DateTime
for the given Date
, with the time components all set to 0.
The resulting DateTime
is the first millisecond of the given Date
and time zone tz
.
See the ^DateTime constructor with time components as arguments for more details.
^Day
^Day[n]
Create a period of n
days.
^FilePos
^FilePos(y, x)
Brings the value type constructor ^FilePos
from the module rel:base
into the global namespace.
For more details, see the rel:base:^FilePos
docstring.
^Hour
^Hour[n]
Create a period of n
hours.
^Microsecond
^Microsecond[n]
Create a period of n
microseconds.
^Millisecond
^Millisecond[n]
Create a period of n
milliseconds.
^Minute
^Minute[n]
Create a period of n
minutes.
^Month
^Month[n]
Create a period of n
months.
^Nanosecond
^Nanosecond[n]
Create a period of n
nanoseconds.
^Second
^Second[n]
Create a period of n
seconds.
^Week
^Week[n]
Create a period of n
weeks.
^Year
^Year[n]
Create a period of n
years.
⇒
F implies G
F ⇒ G
G ⇐ F
Logical implication, for boolean (arity 0, true or false) arguments F and G.
¬
not F
¬F
Logical negation, for boolean (arity 0, true or false) argument F.
∧
F and G
F ∧ G
Logical and (conjunction).
∨
F or G
F ∨ G
Logical or (disjunction), for boolean (arity 0, true or false) arguments F and G.
≢
F ≢ G
Relational inequality, see equal
.
abs
abs[x]
The absolute value of x.
Examples:
abs[-2] = 2
abs[-2.0] = 2.0
acos
acos[x]
acos(x, ac)
Arccosine of x
. ac
is the arccosine of x
given in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Cosine of ac . Must be grounded. |
ac | Floating[64] | Arccosine of x in radians. |
Explanation
Defined for x
between -1 and 1 (inclusive).
The value of ac
ranges from 0 to π.
Arccosine is sometimes called “inverse cosine.”
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the arccosine of 0:
def output = acos[0]
//output> 1.5707963267948966
Calculate the arccosine of -1 using full expression:
def output(x) = acos(-1, x)
//output> 3.141592653589793
Confirm that 1.5707963267948966 is the arccosine of 0:
def output = acos(0, 1.5707963267948966)
//output> () // true
See Also
sin
, cos
, asin
, asinh
, acosh
, sinh
, cosh
, and haversine
.
acosh
acosh[x]
acosh(x, ach)
Hyperbolic arccosine. ach
is the hyperbolic arccosine of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Hyperbolic cosine of ach . Must be grounded. |
ach | Floating[64] | Hyperbolic arccosine of x . |
Explanation
Defined for x
>= 1.
Hyperbolic arccosine is sometimes called “inverse hyperbolic cosine.”
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the hyperbolic arccosine of 90:
def output = acosh[90]
//output> 5.192925985263684
Calculate the hyperbolic arccosine of 180 using full expression:
def output(x) = acosh(180, x)
//output> 5.886096315311465
Confirm that 5.192925985263684 is the hyperbolic arccosine of 90:
def output = acosh(90, 5.192925985263684)
//output> () // true
See Also
sin
, cos
, asin
, acos
, asinh
, acosh
, sinh
, and haversine
.
acot
acot[x]
acot(x, act)
Arccotangent. act
is the arccotangent of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Cotangent of act . Must be grounded. |
act | Floating[64] | Arccotangent of x . |
Explanation
Arccotangent is sometimes called “inverse cotangent.”
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the arccotangent of 1:
def output = acot[1]
//output> 0.7853981633974483
Calculate the arccotangent of -1 using full expression:
def output(x) = acot(-1, x)
//output = -0.7853981633974483
Confirm that 0.7853981633974483 is the arccotangent of 1:
def output = acot(1, 0.7853981633974483)
//output> () // true
See Also
tan
, atan
, atan2
, cot
, tanh
, and atanh
.
add
add[x, y]
add(x, y, s)
x + y
Addition of two numbers.
Addition of a DateTime
/Date
, x
, with a time duration y
.
Parameters
Numeric Data
Parameter | Type | Description |
---|---|---|
x | Number | First summand. |
y | Number | Second summand. |
s | Number | Sum x + y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | s |
---|---|---|
Number | Same as x | Same as x |
Rational , FixedDecimal | SignedInt[64] | Same as x |
SignedInt[64] | SignedInt[128] , Rational , FixedDecimal , Floating[64] | Same as y |
SignedInt[128] | SignedInt[64] | SignedInt[128] |
Floating[64] | SignedInt[64] | Floating[64] |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
x
andy
.x
ands
.y
ands
.
Time Data
Parameter | Type | Description |
---|---|---|
x | Date , DateTime , date period, time period | First summand. |
y | Date , DateTime , date period, time period | Second summand. |
s | Date , DateTime , date period, time period | Sum x + y . |
The following combinations work:
x | y | s |
---|---|---|
date period, time period | Same date period, time period as x | Same date period, time period as x |
date period, time period | DateTime | DateTime |
DateTime | date period, time period | DateTime |
date period | Date | Date |
Date | date period | Date |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
x
andy
.x
ands
.y
ands
.
Explanation
Addition evaluates the sum of x
and y
and assigns it to s
.
In procedural languages, usually x
and y
are given.
In Rel — a declarative language — addition can be thought of as a mapping where x
and y
are the keys and s
is the value, which is functionally dependent on x
and y
.
However, with addition — add(x, y, s)
— it is sufficient to know any two of the three arguments.
The third one can always be inferred.
Usually x
and y
are given, but knowing x
and s
is enough to infer y
.
Examples
Addition of Numbers
Add two integers using +
:
def output = 1 + 2
//output> 3
Add an integer and a float using add
:
def output = add[1, 2.5]
//output> 3.5
Add two floats using full expression:
def output(x) = add(1.7, 2.8, x)
//output> 4.5
Add integer to a rational:
def output = 1 + rational[16][2, 3]
//output> 5/3
Addition of Time
Add time to a timestamp:
def output:tomorrow = datetime_now + ^Day[1]
def output:next_hour = datetime_now + ^Hour[1]
Add weeks to a date:
def output = 2022-12-24 + ^Week[2]
//output> 2023-01-07
Add seconds together:
def output = ^Second[1] + ^Second[2]
//output> 3
See Also
subtract
, divide
, and multiply
.
Any
Any(x)
Holds for any x
, where x
exists. (Any
functions as a wildcard.)
Example:
Integrity constraint that tests whether x
is of any type:
def R = (1, 3) ; (1, "foo")
ic any_ic {subset(R, (Int, Any) )}
approx_eq
approx_eq(tolerance, x, y)
Approximate equality.
Use to compare scalar numbers and check if x
and y
are within the absolute tolerance (tolerance
) of each other.
Parameters
Parameter | Type | Description |
---|---|---|
tolerance | SignedInt[64] or Floating[64] | Tolerance of the approximation. A positive number. Must be grounded. |
x | Number | A valid number. Must be the same data type as y . Must be grounded. |
y | Number | A valid number. Must be the same data type as x . Must be grounded. |
Explanation
“approximately equal” is defined as number values being within the absolute tolerance (tolerance
)
of each other, or non-number values being equal.
The parameter tolerance
stands for the absolute tolerance and must be of type SignedInt[64]
or Floating[64]
.
Also, tolerance
must be a positive number; negative numbers will return false
x
and y
should be of the exact same data type.
For example, x
and y
can be of type FixedDecimal
or Rational
, but types must have the same bits and precision.
If x
or y
is not a number, approx_eq
defaults to eq
.
Examples
Approximate equality determined as true
:
def output = approx_eq(0.05, 0.1, 0.15)
//output> () // true
Approximate equality determined as false
:
def output = approx_eq(0.01, 0.1, 0.15)
//output> // false
See Also
equal
, eq
, approx_equal
, and full_relation_approx_equal
.
approx_equal
approx_equal(tolerance, R, S)
Approximate relational equality.
To hold true, the values in the last column of R
must be approximately equal to values in the last column of S
given the same key (prefix).
Parameters
Parameter | Type | Description |
---|---|---|
tolerance | SignedInt[64] or Floating[64] | A positive integer or float. Must be grounded. |
R | Relation | A relation with corresponding keys and last elements that can be compared to S . Must be grounded. |
S | Relation | A relation with corresponding keys and last elements that can be compared to R . Must be grounded. |
Explanation
Two relations R
and S
are considered “relationally approximately equal” when for each tuple (k..., x)
in S
there exists a tuple (k..., y)
in R
where x
and y
are considered approximately equal.
This approximate equality is symmetric and holds equally true when the places of R
and S
are swapped.
See approx_eq
for the details about approximate equality between two data values.
The parameter tolerance
stands for the absolute tolerance and must be of type SignedInt[64]
or Floating[64]
.
tolerance
must be a positive number; negative numbers will evaluate to false
.
Keys must match for approx_equal
to be true
.
All values of the last column in R
and S
must be of the exact same data type.
For example, the values can all be of type FixedDecimal
or Rational
, but types must have the same bits and precision.
Otherwise, approx_equal
evaluates to false
.
Note the correspondence between approx_equal
and equal
:
approx_equal(0, R, S)
if and
only if equal(R, S)
.
approx_equal
applies only to the values in the last column in R
and S
.
That is, if the values are not within tolerance
, approx_equal
will evaluate to false
even if other arguments in the relations are within tolerance
.
If full relation comparison functionality is required, see full_relation_approx_equal
.
Examples
Approximate relational equality determined as true
:
def salary1 = {("John", 10.0) ; ("Mary", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def salary2 = {("John", 9.99) ; ("Mary", 20.01); ("Paul", 17.0) ; ("Peter", 15.0) }
def output = approx_equal(0.1, salary1, salary2)
//output> () // true
Approximate relational equality determined as false
:
def salary1 = {("John", 10.0) ; ("Mary", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def salary2 = {("John", 11.0) ; ("Mary", 21.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def output = approx_equal(0.1, salary1, salary2)
//output> // false
Approximate relational equality determined as false
because keys are different:
def salary1 = {("John", 10.0) ; ("Mary", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def salary3 = {("John", 9.99) ; ("Ben", 20.0); ("Paul", 17.0) ; ("Peter", 15.0) }
def output = approx_equal(0.1, salary1, salary3)
//output> // false
Approximate relational equality determined as false, even though the first arguments are within tolerance
:
def coordinates1 = (1.0, 2.0); (3.0, 6.0)
def coordinates2 = (1.0000001, 2.0); (2.9999999, 6.0000001)
def output = approx_equal(0.001, coordinates1, coordinates2)
//output> // false
See Also
full_relation_approx_equal
, approx_eq
, equal
, and eq
.
argmax
argmax[R]
argmax(R, am)
For a relation R
, find the tuples whose last elements are largest and return those tuples with the last element omitted.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A relation whose tuples contain key-value pairs. Must be grounded. |
am | Number | A tuple in R with the largest last element, with last element omitted. |
Explanation
If tuples in R
contain keys and values, argmax
returns all the keys for the largest value.
Typically, argmax
is used when the last elements of each tuple are numeric.
argmax
is typically used with relations whose shortest tuple has length two since.
Note that, for all unary relations, argmax
results in a relation containing an empty tuple.
Examples
Find key for largest value of R
:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(am) = argmax(R, am)
//output> "C"
Find key for largest value of R
where values are rationals:
def R = {("A", rational[64, 8, 3]); ("B", rational[64, 9, 7]); ("C", rational[64, 11, 4]); ("D", rational[64, 8, 3])}
def output = argmax[R]
//output> "C"
Find the teams with the largest aggregated salary:
def salary = {("Burrow", 11,515,044); ("Chase", 18,211,606); ("Allen", 77,289,124); ("Diggs", 45,466,111)}
def member = {("Bengals", "Burrow"); ("Bengals", "Chase"); ("Bills", "Allen"); ("Bills", "Diggs")}
def team = {"Bengals"; "Bills"}
def output = argmax[d in team: sum[salary[p] for p in member[d]]]
//output> "Bengals"
See Also
argmin
, maximum
, min
, argmax
, sum
, product
, and average
.
ArgMax
ArgMax[R]
Please use argmax[R]. Deprecates in near future
argmin
argmin[R]
argmin(R, am)
For a relation R
, find the tuples whose last elements are smallest and return those tuples with the last element omitted.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
am | Any | A tuple in R with the smallest last element, with last element omitted. |
Explanation
If tuples in R
contain keys and values, argmin
returns all the keys for the largest value.
Typically, argmin
is used when the last elements of each tuple are numeric.
argmin
is typically used with relations whose shortest tuple has length two since.
Note that, for all unary relations, argmin
results in a relation containing an empty tuple.
Examples
Find key for smallest value of R
:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(am) = argmin(R, am)
//output> "A"
// "C"
Find key for smallest value of R
where values are rationals:
def R = {("A", rational[64, 8, 3]); ("B", rational[64, 9, 7]); ("C", rational[64, 11, 4]); ("D", rational[64, 7, 3])}
def output = argmin[R]
//output> "B"
Find key for smallest value of R
with tuples of various arity:
def R = {("A", 7.5); ("B", 8.6); ("C", "W", 9.7); ("D", "X", 7.5)}
def output = argmin[R]
//output> "A"
// "D", "X"
Find the teams with the smallest aggregated salary:
def salary = {("Burrow", 11,515,044); ("Chase", 18,211,606); ("Allen", 77,289,124); ("Diggs", 45,466,111)}
def member = {("Bengals", "Burrow"); ("Bengals", "Chase"); ("Bills", "Allen"); ("Bills", "Diggs")}
def team = {"Bengals"; "Bills"}
def output = argmin[d in team: sum[salary[p] for p in member[d]]]
//output> "Bills"
See Also
argmax
, minimum
, min
, argmax
, sum
, product
, and average
.
ArgMin
ArgMin[R]
Please use argmin[R]. Deprecates in near future
arity
arity[R]
The arity of a relation. In some cases, it can be an over-approximation.
Arity is a higher-order relation that is always evaluated at compile-time.
Examples:
def output = arity[3]
//output> 1
def output = arity[{1; 2; 3}]
//output> 1
def output = arity[(1, 2)]
//output> 2
def output = arity[add]
//output> 3
def output = arity[{1; 2; (1,2)}]
//output> 1
// 2
Arity can be used to do meta-programming in logic. For example, the following
abstraction verbalize
implements specific cases using arity
.
Examples:
@inline def verbalize[R] = "nullary", arity[R] = 0;
"unary", arity[R] = 1;
"binary", arity[R] = 2
def output = verbalize[true]
//output> "nullary"
def output = verbalize[1]
//output> "unary"
Arity can be used in higher-order abstractions to check at compile-time that they are used correctly.
Arity can be used in integrity constraints to state expectation on EDB or IDB
relations. Because arity
is evaluated at compile-time, it can catch mistakes in the
logic before the logic executes.
Example:
def p = (1, 2, 3)
ic { arity[p] = 3 }
Note that there is a difference between R(_, _)
and arity(R) = 2
. The first requires
R
to be non-empty, which is a run-time property of R
.
asin
asin[x]
asin(x, as)
Arcsine of x
. ac
is the arcsine of x
given in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Sine of as . Must be grounded. |
as | Floating[64] | Arcsine of x . |
Explanation
Defined for x
between -1 and 1 (inclusive). The value of as
ranges from -π/2 to π/2.
Only 64-bit float and 64-bit integer values for x
are supported.
Arcsine is sometimes called “inverse sine.”
Examples
Calculate the arcsine of 1:
def output = asin[1]
//output> 1.5707963267948966
Calculate the arcsine of -.5 using full expression:
def output(x) = asin(-.5, x)
//output> -0.5235987755982989
Confirm that 1.5707963267948966 is the arcsine of 1:
def output = asin(1, 1.5707963267948966)
//output> () // true
See Also
sin
, cos
, acos
, asinh
, acosh
, sinh
, cosh
, and haversine
.
asinh
asinh[x]
asinh(x, ash)
Hyperbolic arcsine. ash
is the hyperbolic arcsine of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Hyperbolic sine of ash . Must be grounded. |
ash | Floating[64] | Hyperbolic arcsine of x . |
Explanation
Hyperbolic arcsine is sometimes called “inverse hyperbolic sine.”
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the hyperbolic arcsine of 10:
def output = asinh[10]
//output> 2.99822295029797
Calculate the hyperbolic arcsine of -1 using full expression:
def output(x) = asinh(-1, x)
//output> -0.881373587019543
Confirm that 2.99822295029797 is the hyperbolic arcsine of 10:
def output = asinh(10, 2.99822295029797)
//output> () // true
See Also
sin
, cos
, asin
, acos
, acosh
, sinh
, cosh
, and haversine
.
atan
atan[x]
atan(x, at)
Arctangent. at
is the arctangent of x
in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Tangent of at . Must be gounded. |
at | Floating[64] | Arctangent of x . |
Explanation
Arctangent is sometimes called “inverse tangent.”
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the arctangent of π/4:
def output = atan[pi_float64/4]
//output> 0.6657737500283538
Convert degrees to radians and calculate arctangent using full expression:
def x = deg2rad[90]
def output(at) = atan(x, at)
//output> 1.0038848218538872
Confirm that 0.6657737500283538 is the tangent of π/4:
def output = atan(pi_float64/4, 0.6657737500283538)
//output> () // true
See Also
tan
, atan2
, cot
, acot
, tanh
, and atanh
.
atan2
atan2[y, x]
atan2(y, x, at)
Arctangent. at
is the arctangent of the quotient y/x
in radians.
Parameters
Parameter | Type | Description |
---|---|---|
y | Floating[64] , SignedInt[64] , UnsignedInt[64] | coordinate of the 2D point . Must be gounded. |
x | UnsignedInt[64] , SignedInt[64] , Floating[64] | coordinate of the 2D point . Must be gounded. |
at | Floating[64] | Arctangent of x . |
Explanation
Arctangent is sometimes called “inverse tangent.”
The parameters x
and y
can be thought of as the and coordinates of the 2D point .
Examples
Calculate the arctangent of 50:
def output = atan2[100, 2.0]
//output> 1.550798992821746
See Also
atan
, tan
, cot
, acot
, tanh
, and atanh
.
atanh
atanh[x]
atanh(x, ath)
Hyperbolic arctangent. ath
is the hyperbolic arctangent of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Hyperbolic tangent of ath . Must be grounded. |
ath | Floating[64] | Hyperbolic arctangent of x . |
Explanation
Hyperbolic arctangent is sometimes called “inverse hyperbolic tangent.”
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the hyperbolic arctangent of -.7:
def output = atanh[-.7]
//output> -0.8673005276940532
Calculate the hyperbolic arctangent of .7 using full expression:
def output(x) = atanh(.7, x)
//output> 0.8673005276940532
Confirm that -0.8673005276940532 is the hyperbolic arctangent of -.7:
def output = atanh(-.7, -0.8673005276940532)
//output> () // true
See Also
tan
, atan
, atan2
, cot
, acot
, tanh
, and atanh
.
auto_number
auto_number[R]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
AutoNumber a relation.
auto_number
takes a relation R(xs...)
and produces a relation R(xs..., i)
where i
is a distinct AutoNumberValue
index.
Note that auto_number
can give different results each time it is called.
Example:
def sample = 'a'
def output = auto_number[sample]
//output> ('a', AutoNumberValue(0x12))
def sample = {'a'; 'b'; 'c'}
def output = auto_number[sample]
//output> ('a', AutoNumberValue(0x132))
// ('b', AutoNumberValue(0x133))
// ('c', AutoNumberValue(0x134))
AutoNumber
AutoNumber(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Test if the given value is an AutoNumberValue.
average
average[R]
average(R, m)
The average (arithmetic mean) of a relation R
.
average
is an alias for mean
.
For details, see the docstring for mean
.
bigint
bigint[i]
Create a BigInteger value from the given integer.
Examples:
string[factorial[bigint[50]]] = "30414093201713378043612608166064768844377641568960512000000000000"
bigint_int64_convert
Convert a BigInteger to an Int64.
Examples:
bigint_int64_convert[bigint[50]] = 50
bitwise_and
bitwise_and[x, y]
bitwise_and(x, y, z)
Bitwise and of two integers.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Left operand. Must be grounded. |
y | SignedInt , UnsignedInt | Right operand. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise and of x and y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt[64] , UnsignedInt[32] | Same as x . |
Examples
Bitwise and of 3
and 2
:
def output = bitwise_and[3, 2]
//output> 2
Bitwise and of two unsigned integers using full expression:
def output(z) = bitwise_and(0x11100, 0x00101, z)
//output> 256
Bitwise and of unsigned and signed integers:
def output = bitwise_and[0x010b, -265]
//output> 3 // is an UnsignedInt[16]
See Also
bitwise_or
, bitwise_xor
, bitwise_left_shift
, bitwise_right_shift
, bitwise_unsigned_right_shift
, and bitwise_not
.
bitwise_left_shift
bitwise_left_shift[x, y]
bitwise_left_shift(x, y, z)
Bitwise left shift of an integer x
by y
bits.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Operand. Must be grounded. |
y | SignedInt , UnsignedInt | Bits for left shift. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise left shift of x and y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt[64] , UnsignedInt[32] | Same as x . |
Explanation
The type of shift done depends on the type of x
.
If x
is signed, bitwise_left_shift
performs a signed left shift (also known as an “arithmetic left shift”).
If x
is unsigned, bitwise_left_shift
performs an unsigned left shift (also known as a “logical left shift”).
Examples
Bitwise left shift of 8
by 1
bit:
def output = bitwise_left_shift[8, 1]
//output> 16
Bitwise left shift of 1
by 10
bits using full expression:
def output(z) = bitwise_left_shift(1, 10, z)
//output> 1024
Bitwise left shift of 0xf by 1
bit:
def output = bitwise_left_shift[0xF, 1]
//output> 30
Bitwise left shift of unsigned integer:
def output = bitwise_left_shift[uint[64, 4028], 1]
//output> 8056
See Also
bitwise_and
, bitwise_or
, bitwise_xor
, bitwise_right_shift
, bitwise_unsigned_right_shift
, and bitwise_not
.
bitwise_not
bitwise_not[x]
bitwise_not(x, z)
Bitwise not of an integer.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Operand. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise not of x . |
Not all numeric values can be mixed with each other. The following combinations work:
x | z | |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
Examples
Bitwise not of -9
:
def output = bitwise_not[-9]
//output> 8
Bitwise not of 8
using full expression:
def output(z) = bitwise_not(8, z)
//output> -9
Bitwise not of 0x00011
:
def output = bitwise_not[0x00011]
//output> 4294967278
See Also
bitwise_and
, bitwise_or
, bitwise_xor
, bitwise_left_shift
, bitwise_right_shift
, and bitwise_unsigned_right_shift
.
bitwise_or
bitwise_or[x, y]
bitwise_or(x, y, z)
Bitwise or
of two integers.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Left operand. Must be grounded. |
y | SignedInt , UnsignedInt | Right operand. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise or of x and y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt[64] , UnsignedInt[32] | Same as x . |
Examples
def output = bitwise_or[3, 2]
//output> 3
Bitwise or of 0x00011
and 0x11100
using full expression:
def output(z) = bitwise_or(0x00011, 0x11100, z)
//output> 69905
Bitwise xor of two unsigned integers:
def output = bitwise_or[uint[64, 1024], uint[64, 2048]]
//output> 3072
See Also
bitwise_and
, bitwise_xor
, bitwise_left_shift
, bitwise_right_shift
, bitwise_unsigned_right_shift
, and bitwise_not
.
bitwise_right_shift
bitwise_right_shift[x, y]
bitwise_right_shift(x, y, z)
Bitwise right shift of an integer x
by y
bits that preserves the sign.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Operand. Must be grounded. |
y | SignedInt , UnsignedInt | Bits for right shift. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise right shift of x and y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt[64] , UnsignedInt[32] | Same as x . |
Examples
Bitwise right shift of 1024
by 1
bit:
def output = bitwise_right_shift[1024, 1]
//output> 512
Bitwise right shift of -1024
by 1
bit using full expression:
def output(z) = bitwise_right_shift(-1024, 1, z)
//output> -512
Bitwise right shift of unsigned integer by 2 bits:
def output = bitwise_right_shift[uint[64, 2048], 2]
//output> 512
See Also
bitwise_and
, bitwise_or
, bitwise_xor
, bitwise_left_shift
, bitwise_unsigned_right_shift
, and bitwise_not
.
bitwise_unsigned_right_shift
bitwise_unsigned_right_shift[x, y]
bitwise_unsigned_right_shift(x, y, z)
Bitwise unsigned right shift of an integer by y
bits.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Operand. Must be grounded. |
y | SignedInt , UnsignedInt | Bits for unsigned right shift. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise unsigned right shift of x and y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt[64] , UnsignedInt[32] | Same as x . |
Examples
Bitwise unsigned right shift of 8
by 1
bit:
def output = bitwise_unsigned_right_shift[8, 1]
//output> 4
Bitwise unsigned right shift of -8
by 2
bits:
def output(z) = bitwise_unsigned_right_shift(-8, 2, z)
//output> 4611686018427387902
Bitwise unsigned right shift of unsigned integer by 3
bits:
def output = bitwise_unsigned_right_shift[uint[64, 8], 3]
//output> 1
See Also
bitwise_and
, bitwise_or
, bitwise_xor
, bitwise_left_shift
, bitwise_right_shift
, and bitwise_not
.
bitwise_xor
bitwise_xor[x, y]
bitwise_xor(x, y, z)
Bitwise xor (exclusive or) of two integers.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt , UnsignedInt | Left operand. Must be grounded. |
y | SignedInt , UnsignedInt | Right operand. Must be grounded. |
z | SignedInt , UnsignedInt | The bitwise xor of x and y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | z |
---|---|---|
SignedInt , UnsignedInt | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt[64] , UnsignedInt[32] | Same as x . |
Examples
Bitwise xor of 3
and 2
:
def output = bitwise_xor[3, 2]
//output> 1 // is a SignedInt[64]
Bitwise xor of 0x00011
and 0x11100
using full expression:
def output(z) = bitwise_xor(0x00011, 0x11100, z)
//output> 69905
Bitwise xor of two unsigned integers:
def output = bitwise_xor[uint[64, 1024], uint[64, 2048]]
//output> 3072
See Also
bitwise_and
, bitwise_or
, bitwise_left_shift
, bitwise_right_shift
, bitwise_unsigned_right_shift
, and bitwise_not
.
Boolean
Boolean(x)
Holds if x
is a Boolean
.
Example:
def json = parse_json["""{"a": true, "b": false}"""]
def output(x) = json(:a, x) and Boolean(x)
boolean_and
boolean_and(x, y, z)
Logical AND operator for the Boolean
data type.
Example:
def output(x, y, z) = boolean_and(x, y, z) and boolean_true(z)
boolean_false
boolean_false(x)
Holds if x
is a Boolean
of value false
.
boolean_not
boolean_not(x,y)
Negation(not
) operator for the Boolean
data type.
Example:
def output(x, y) = boolean_not(x, y) and boolean_false(x)
boolean_or
boolean_or(x, y, z)
Logical or
operator for the Boolean
data type.
Example:
def output(x, y, z) = boolean_or(x, y, z) and boolean_false(z)
boolean_true
boolean_true(x)
Holds if x
is a Boolean
of value true
.
bottom
bottom[k, R]
bottom(k, R, index, x...)
Select the bottom k
tuples of relation R
according to the sort order of R
and add enumeration.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
k | Int | Number of tuples to sort from the bottom of R . Must be grounded. |
index | Int | The new enumeration index starting at 1. |
x... | Tuple | A tuple in R associated with the new index index . |
Explanation
bottom
is reverse_sort
restricted to the last k
tuples of R
.
bottom
puts the tuples of R
in lexicographical order and then limits the result to the last k
tuples.
The index indicates the tuples of R
in reverse order.
For details on lexicographical ordering — particularly across data types — see enumerate
.
Simlar to reverse_sort
, bottom
takes a relation R(x...)
and produces a relation with the tuples (index, x...)
,
where the first element of each tuple (index
) is an integer index that enumerates the bottom k
tuples
in the original relation R
.
Examples
Apply bottom
to a relation with arity-1 tuples:
def output = bottom[2, {'a'; 'b'; 'c'; 'd'}]
//output> (1, 'd')
// (2, 'c')
Apply bottom
to a relation with arity-2 tuples:
def R = {('a', 1); ('b', 2); ('c', 3); ('d', 4); ('e', 5)}
def output = bottom[3, R]
//output> 1, e, 5
// 2, d, 4
// 3, c, 3
See Also
top
, enumerate
, sort
, and reverse_sort
.
byte
byte[str]
byte[str, i]
byte(str, i, b)
Indexes into a string at byte position i
, mapping each position i
to a byte b
, as a UInt8 value.
If a string contains Unicode characters, the byte at index i
might be only a partial character.
Be careful with your indexing logic.
Both i
and b
can be optionally bound externally. When only str
is bound, this is
the mapping from each index to its corresponding byte.
Examples: Indexing into a known byte index:
byte["abcd", 2] = 0x62
byte["中文例子", 2] = 0xb8
Abstracting over the byte index:
equal(byte["中文"],
{ 1, 0xe4;
2, 0xb8;
3, 0xad;
4, 0xe6;
5, 0x96;
6, 0x87; })
equal((i : byte["awesome", i](0x65)), {3; 7})
capture_group_by_index
capture_group_by_index[regex, input_string, offset]
A set of capture groups, each of the form (index, substring)
, where index
is the capture group index, and substring
is the first regex match in input_string
, starting at the character index specified by offset
.
regex
can be a string or a pattern.
Offsets (character indexes) start at 1.
Example:
capture_group_by_index["(\\d+):(\\d+)",
"Appointment from 12:45 to 1:30",
19]
is equal to
{(1, "12"); (2, "45")}
capture_group_by_name
capture_group_by_name[regex, input_string, offset]
A set of capture groups, each of the form (name, substring)
, where name
is the capture group name, and substring
is the first regex match in input_string
, starting at the character index specified by offset
.
regex
can be a string or a pattern.
Offsets (character indexes) start at 1.
Each capture group should have a unique name.
Example:
capture_group_by_name["(?<hour>\\d+):(?<minute>\\d+)",
"Appointment from 12:45 to 1:30",
19]
is equal to
(("hour","12"); ("minute","45"))
cart
cart[R, S]
R × S
Cartesian product.
Examples:
def output = 1 ✕ 2
//output> (1,2)
def output = {1; 2} ✕ {3; 4}
//output> (1,3)
// (1,4)
// (2,3)
// (2,4)
cbrt
cbrt[x]
The cube root of x.
Example:
cbrt[27] = 3.0
ceil
ceil[x]
ceil(x, c)
Round up to the nearest integer.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Number to be rounded up. Must be grounded. |
c | SignedInt[64 | Ceiling of x . |
Return type is the same as x
.
Explanation
For positive x
, ceil
rounds away from 0.
For negative x
, ceil
rounds toward 0.
Examples
Calculate ceil
for positive float:
def output = ceil[4.5]
//output> 5.0
Calculate ceil
for negative float using full expression:
def output(c) = ceil(-4.5, c)
//output> -4.0
Calculate ceil
for rational:
def output = ceil[rational[64, 8, 3]]
//output> 3/1
See Also
floor
, floor_to_int
, trunc
, trunc_to_int
, and round
.
char
char[str]
char[str, i]
char(str, i, c)
Indexes into a string at (Int) position i
, mapping each index i
to the i
-th character, c
.
Since this is indexed using character positions, the characters will always be whole Unicode characters.
A character is also known as a “Code Point” in the Unicode specification.
Both i
and c
can be optionally bound externally. When only str
is bound, this is
the mapping from each character index to its corresponding character.
Examples:
Indexing into a known character index:
char["abcd", 2] = 'b'
char["中文例子", 2] = '文'
Abstracting over the character index:
equal(char["中文"],
{ 1, "中"; 2, "文" })
equal((i : char["awesome", i]('e')), {3; 7})
Char
Char(x)
Holds if x
is of type Char
, which has a Unicode character as its value and is specified with single quotes.
Examples:
Integrity constraint that tests whether x
is of type Char
:
def R = 't'
ic mychar_ic(x in R)
Char(x)
}
Schema defined in a relation using Char
:
def myrelation(x in Char, y in Int) {
x = 'a' and y = 123
}
def output = myrelation
//output> (a, 123)
clamp
clamp[low, high, value]
clamp(low, high, value, clamped)
Limit value
to a range between low
and high
.
The parameter clamped
contains the “clamped” result.
Parameters
Parameter | Type | Description |
---|---|---|
low | Same as value . | Lower bound. Must be grounded. |
high | Same as value . | Upper bound. Must be grounded. |
value | Number | Value to be clamped. Must be grounded. |
clamped | Same as value | value limited to between low and high . |
Explanation
The resulting value clamped
is equivalant to value
as long as it is within the lower and upper bounds.
If value
lies outside of these bounds, then clamped
will take on the value of the bound that is closest to value
.
In mathematical terms, this reads:
For example, if low
and high
are of type Float
, value
should also be of type Float
.
Note that relations never contain duplicates.
If value
is a relation with multiple values lower than low
(or higher than high
), clamp[low, high, value]
will contain only once the value low
(high
).
Examples
Clamp relation with integer values:
def low = 1
def high = 4
def value = {-4; 2; 7}
def output = clamp[low, high, value]
//output> 1
// 2
// 4
Clamp relation with rationals. Note that relations never contain duplicates, thus only low and high values are included in output
.
def low = rational[64, 7, 27]
def high = rational[64, 26, 27]
def value = {rational[64, 1, 27]; rational[64, 6, 27]; rational[64, 31, 27]}
def output = clamp[low, high, value]
//output> 7/27
// 26/27
See Also
range
complement
complement[R]
The complement of the relation R.
concat
concat[val1, val2]
String concatenation of two arbitrary values
Example:
concat["a", "b"] = "ab"
concat["a", 'b'] = "ab"
concat['a', "b"] = "ab"
concat['a', 'b'] = "ab"
concat["a_", 1] = "a_1"
concat[1, 3.14] = "13.14"
contains
contains(s, substring)
True iff the second argument, substring
, occurs as a substring in the first argument, s
.
Examples:
contains("Rel is cool!", "Rel is cool!") // true
contains("Rel is cool!", " is coo") // true
contains("Rel is cool!", 'c') // true
contains("Rel is cool!", 'C') // false
cos
cos[x]
cos(x, c)
Cosine of of x
, where x
is an angle given in radians.
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Angle in radians. Must be grounded. |
c | Floating[64] | Cosine of x . |
Explanation
Defined for non-infinite x
.
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the cosine of π/6:
def output = cos[pi_float64/6]
//output> 0.8660254037844387
Calculate the cosine of π/4 using full expression:
def output(x) = cos(pi_float64/4, x)
//output> 0.7071067811865476
Confirm that 0.5000000000000001 is the cosine of π/3:
def output = cos(pi_float64/3, 0.5000000000000001)
//output> () // true
See Also
sin
, asin
, acos
, asinh
, acosh
, sinh
, cosh
, and haversine
.
cosh
cosh[x]
cosh(x, ch)
Hyperbolic cosine. ch
is the hyperbolic cosine of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Hyperbolic angle. Must be grounded. |
ch | Floating[64] | Hyberbolic cosine of x . |
Explanation
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the hyperbolic cosine of 1:
def output = cosh[1]
//output> 1.5430806348152437
Calculate the hyperbolic cosine of -7 using full expression:
def output(x) = cosh(-7, x)
//output> 548.317035155212
Confirm that 1.5430806348152437 is the hyperbolic cosine of 1:
def output = cosh(1, 1.5430806348152437)
//output> () // true
See Also
sin
, cos
, asin
, acos
, asinh
, sinh
, cosh
, and haversine
.
cot
cot[x]
cot(x, ct)
Cotangent. ct
is the cotangent of x
, where x
is in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Angle in radians. Must be grounded. |
ct | Floating[64] | Cotangent of x . |
Explanation
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the cotangent of π/4:
def output = cot[pi_float64/4]
//output> 1.0000000000000002
Convert degrees to radians and calculate cotangent using full expression:
def x = deg2rad[90]
def output(t) = cot(x, t)
//output> 6.123233995736766e-17
Confirm that 1.0000000000000002 is the cotangent of π/4:
def output = cot(pi_float64/4, 1.0000000000000002)
//output> () // true
See Also
tan
, atan
, atan2
, acot
, tanh
, and atanh
.
count
count[R]
count(R, n)
Count the number n
of tuples contained in the relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A general relation. Must be grounded. |
n | Integer | Number of tuples in R . |
Explanation
The relation count
contains the higher-order tuple (R, n)
if R
is a relation with n
tuples.
The form count[R]
is generally used to count the number of tuples in a relation R
.
The form count(R, n)
is generally used to test whether R
contains n
tuples.
If R
is empty, count[R]
is false
.
To get 0 instead, use left_override
, as in count[R] <++ 0
.
Examples
Count the number of tuples in a relation called employees
:
def employees = {
("jane", 12);
("tran", 24);
("miguel", 36)
}
def output = count[employees]
//output> 3
Count a singleton relation:
def output = count[5]
//output> 1
Test if employees
contains three tuples:
def output = count(employees, 3)
//output> () // true
See Also
argmax
, argmin
, average
, bottom
, top
, first
, last
, max
, min
, mode
, and product
.
csv_string
csv_string[R]
The string representation of relation that encodes as CSV using the configuration relation R
.
Required keywords are:
:data
: A set of relations mapping a file position, which can be a key of arbitrary length or type, to the corresponding value. This is the data that will be exported. We expect the data relation to be of form: data(:COLUMN_NAME, pos, val) Optional keywords::syntax
: A relation containing syntax configuration.
Example using default CSV syntax
def csv_data(:ORDER, pos, v) = ((1,1); (2,2); (3,3))(pos, v)
def csv_data(:LINEITEM, pos, v) = ((1,100); (2,101); (3,102))(pos, v)
def csv_data(:QUANTITY, pos, v) = ((1,2); (2,15); (3,42))(pos, v)
def config[:data] = csv_data
def output = csv_string[config]
Example using custom CSV syntax
def csv_data(:ORDER, pos, v) = ((1,1); (2,2); (3,3))(pos, v)
def csv_data(:LINEITEM, pos, v) = ((1,100); (2,101); (3,102))(pos, v)
def csv_data(:QUANTITY, pos, v) = ((1,2); (2,15); (3,42))(pos, v)
def config[:data] = csv_data
def config[:syntax, :delim] = '\t'
def config[:syntax, :quotechar] = '_'
def output = csv_string[config]
current_transaction_id
current_transaction_id
The Transaction ID of the current transaction as an unsigned 128-bit integer.
This is comparable to Snowflake CURRENT_TRANSACTION
, SQL Server CURRENT_TRANSACTION_ID
,
and PostgreSQL txid_current
.
Date
Date(x)
Holds if x
is a Date
.
date_add
date_add[d, period]
d + period
Add a Period to a Date
Example:
def d = parse_date["2021-09-21", "Y-m-d"]
def output = date_add[d, ^Day[20]]
//output> 2021-10-11
date_day
date_day[d]
Day of the month for a Date, as an integer between 1 and 31, inclusive.
Example:
def d = parse_date["2014-10-31", "Y-m-d"]
date_day[d] = 31
date_dayname
date_dayname[d]
Name of week-day (a String, e.g., Friday
)
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
def output = date_dayname[t]
//output> "Friday"
date_dayofquarter
date_dayofquarter[d]
Day of quarter
Example:
def d = parse_date["2014-01-31", "Y-m-d"]
date_dayofquarter[d] = 31
date_dayofweek
date_dayofweek[d]
Day of the week for a date, as an integer between 1 and 7, where 1 is Monday and 7 is Sunday. (That is, 5
for Friday
.)
Example:
def d = parse_date["2014-01-31", "Y-m-d"]
date_dayofweek[d] = 5
date_dayofweekofmonth
date_dayofweekofmonth[d]
Day of week of month, as an integer (e.g. 2 for second Friday of the month, 1 for the first Tuesday).
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
date_dayofweekofmonth[t] = 5 // fifth Friday of that month
date_dayofyear
date_dayofyear[d]
Day of year
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
def output = date_dayofyear[t]
//output> 31
date_daysinmonth
date_daysinmonth[d]
The number of days in the month for date d
Examples:
def d1 = parse_date["2014-01-30", "Y-m-d"]
date_daysinmonth[t] = 31
def d2 = parse_date["2014-02-11", "Y-m-d"]
date_daysinmonth[d2] = 28
def d = parse_date["2016-02-11", "Y-m-d"]
date_daysinmonth[d] = 29
date_isleapyear
date_isleapyear[d]
True iff the year for date d
is a leap year.
Examples:
def notleap = parse_date["2014-01-31", "Y-m-d"]
def leap = parse_date["2016-01-31", "Y-m-d"]
def output = date_isleapyear[notleap]
//output> // false
def output = date_isleapyear[leap]
//output> () // true
date_month
date_month[d]
Month of a Date, as an integer between 1 and 12.
date_monthname
date_monthname[d]
The month name for date d
, as a string.
Example:
def t = parse_date["2014-01-31", "Y-m-d"]
date_monthname[t] = "January"
date_quarterofyear
date_quarterofyear[d]
Quarter to year
Example:
def d = parse_date["2014-01-31", "Y-m-d"]
date_quarterofyear[d] = 1
date_subtract
date_subtract[date, period]
date - period
Subtract a Period from a Date, giving another Date.
Example:
def d = parse_date["2021-09-21", "Y-m-d"]
def output = date_subtract[d, ^Day[1000]]
//output> 2018-12-26
date_week
date_week[d]
Week of the year for a Date, as an integer, where the first week is the week that contains the first Thursday of the year. Ranges between 1 and 53, inclusive.
Example:
week[parse_date["2005-01-01", "Y-m-d"]] = 53 // 53rd week of 2004.
week[parse_date["2001-01-01", "Y-m-d"]] = 1
date_year
date_year[d]
Year of a Date, as an integer.
Example:
date_year[parse_date["2020-05-22", "Y-m-d"]]
2020
^Year[date_year[parse_date["2020-05-22", "Y-m-d"]]]
(2020 years,)
dates_period_days
dates_period_days[date1, date2]
The difference in days between two dates date2
and date1
as a Day
data type.
Example:
def days = dates_period_days[
2022-05-12,
2022-05-15
]
ic { equal(days, ^Day[3]) }
DateTime
DateTime(x)
Holds if x
is a DateTime
.
datetime_add
datetime_add[dt, period]
dt + period
Add a Period to a DateTime
Examples:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_add[dt, ^Year[1]]
//output> 2022-01-01T01:00:00.000Z
def output = datetime_add[dt, ^Month[13]]
//output> 2022-02-01T01:00:00.000Z
def output = datetime_add[dt, ^Hour[1000]]
//output> 2021-02-11T17:00:00.000Z
datetime_day
datetime_day[dt, tz]
Day of the month, for a DateTime.
Note that DateTime properties require a timezone string tz
.
Example:
datetime_day[unix_epoch, "UTC"] = 1
datetime_day[unix_epoch, "UTC-10"] = 31
datetime_day_UTC
datetime_day_UTC[dt]
Day assuming datetime is in UTC.
datetime_dayname
datetime_dayname[t, tz]
Name of week-day (a string, e.g., Friday
)
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayname[t, "+03:00"] = "Friday"
datetime_dayofquarter
datetime_dayofquarter[dt, tz]
Day of quarter
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofquarter[t, "+03:00"] = 31
datetime_dayofweek
datetime_dayofweek[dt, tz]
Day of week (a number, e.g., 5
for Friday
)
Example:
def dt = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofweek[dt, "+03:00"] = 5
datetime_dayofweek[dt, "UTC"] = 4
datetime_dayofweekofmonth
datetime_dayofweekofmonth[dt, tz]
Day of week of month, as an integer (e.g. 2 for second Friday of the month, 1 for the first Tuesday).
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofweekofmonth[t, "+03:00"] = 5
datetime_dayofyear
datetime_dayofyear[dt, tz]
Day of year
Examples:
def dt = parse_datetime["2014-03-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_dayofyear[dt, "+03:00"] = 90
datetime_dayofyear[dt, "+00:00"] = 89
datetime_daysinmonth
datetime_daysinmonth[dt, tz]
The number of days in a datetime’s month, adjusting for timezone tz
.
Examples:
def t = parse_datetime["2014-02-28 23:00 +00:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_daysinmonth[t, "+03:00"] = 31
datetime_daysinmonth[t, "-03:00"] = 28
datetime_hour
datetime_hour[dt, tz]
Hour of a DateTime.
Note that DateTime properties require a timezone string tz
.
datetime_hour_UTC
datetime_hour_UTC[dt]
Hour assuming datetime is in UTC.
datetime_isleapyear
datetime_isleapyear[dt, tz]
Is it a leap year?
Examples:
def dt = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
def output = datetime_isleapyear[dt, "+03:00"]
//output> // false
def dtleap = parse_datetime["2016-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
def output = datetime_isleapyear[dtleap, "+00:00"]
//output> () // true
datetime_minute
datetime_minute[dt, tz]
Minute of a DateTime.
Note that DateTime properties require a timezone string tz
.
datetime_minute_UTC
datetime_minute_UTC[dt]
Minute assuming datetime is in UTC.
datetime_month
datetime_month[dt, tz]
Month of a DateTime, as an integer between 1 and 12.
Note that DateTime properties require a timezone tz
.
Examples:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
datetime_month[dt, "Europe/Berlin"] = 1
datetime_month[dt, "America/New_York"] = 12
datetime_month[dt, "-03:00"] = 12
datetime_month_UTC
datetime_month_UTC[dt]
Month assuming datetime is in UTC.
datetime_monthname
datetime_monthname[dt, tz]
The month name
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_monthname[t, "+03:00"] = "January"
datetime_now
datetime_now
The current UTC time (the start time of the transaction) as a DateTime
value.
Example:
def output = datetime_now
datetime_quarterofyear
datetime_quarterofyear[dt, tz]
Quarter of the year for datetime dt
, as a number between 1 and 4.
Example:
def t = parse_datetime["2014-01-31 01:00 +03:00", "YYYY-mm-dd HH:MM zzzz"]
datetime_quarterofyear[t, "+03:00"] = 1
datetime_second
datetime_second[dt]
Second of a DateTime.
Unlike other DateTime functions, datetime_second
does not require a timezone argument.
Example:
datetime_second[unix_epoch] = 0
datetime_subtract
datetime_subtract[dt, period]
dt - period
Subtract a Period from a DateTime, giving another DateTime.
Example:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
def output = datetime_subtract[dt, ^Hour[1000]]
//output> 2020-11-20T09:00:00.000Z
datetime_to_nanoseconds
datetime_to_nanoseconds[dt]
Convert datetime to nanoseconds since the epoch. Assumes dt
is in UTC.
datetime_week
datetime_week[dt, tz]
Week of the year for a DateTime dt
, as an integer between 0 and 53 (see date_week
).
Note that DateTime properties require a timezone tz
.
datetime_week_UTC
datetime_week_UTC[dt]
Week assuming datetime is in UTC.
datetime_year
datetime_year[dt, tz]
Year of a DateTime dt
, as an Int
.
Note that DateTime properties require a timezone tz
.
Examples:
def dt = parse_datetime["2021-01-01 01:00:00", "Y-m-d H:M:S"]
datetime_year[dt, "Europe/Berlin"] = 2021
datetime_year[dt, "America/New_York"] = 2020
datetime_year[dt, "-03:00"] = 2020
datetime_year_UTC
datetime_year_UTC[dt]
Year assuming datetime is in UTC.
datetimes_period_milliseconds
datetimes_period_milliseconds[dt1, dt2]
The difference between two datetimes, dt2 - dt1
, as a Millisecond
data type.
In other words, equal to the milliseconds time period between dt1
and dt2
— which when added to dt1
gives dt2
.
Example:
def output = datetimes_period_milliseconds[
unix_epoch,
parse_datetime["2021-03-19 11:00:40", "YYYY-mm-dd HH:MM:SS"]
]
ic {rel:base:Millisecond(output)}
Day
Day[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Day constructor, ^Day
, instead.
Create a period of n
days.
decimal
decimal[n, digits, v]
The n
-bit decimal value with digits
precision from number value v
.
n
must be among #8, #16, #32, #64, and #128. The precision digits
must be:
- between #0 and #2 if
n
= #8 - between #0 and #4 if
n
= #16 - between #0 and #9 if
n
= #32 - between #0 and #18 if
n
= #64 - between #0 and #32 if
n
= #128
Note that the value v * 10^digits
must be encodable with n
-bits.
Examples:
decimal[#64, #2, 3.14156] = 3.14
empty(decimal[#64, #20, 1000])
empty(decimal[#8, #2, 2])
decimal_bit_length
decimal_bit_length[decimal]
The bit length of a fixed-point decimal number.
Example:
def g = parse_decimal[#64, #2, "3.14"]
decimal_bit_length[g] = 64
decimal_int_convert
decimal_int_convert[x]
Conversion from n
-bit fixed-point decimal with d
precision to n
-bit int.
If the argument is not equivalent to an int, decimal_int_convert
returns false
.
Example:
decimal_int_convert[decimal[#32, #2, 3.00]] = 3
decimal_int_convert[decimal[#32, #2, 3.20]] = false
decimal_precision
decimal_precision[decimal]
The precision of a fixed-point decimal number.
Example:
def g = parse_decimal[#64, #2, "3.14"]
decimal_precision[g] = 2
decode_base16
decode_base16[encoded_str]
Decodes the base-16 encoded string to string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = decode_base16["48656C6C6F21"]
//output> "Hello!"
def output = decode_base16["E4BDA0E5A5BD"]
//output> "你好"
decode_base32
decode_base32[encoded_str]
Decodes the base-32 encoded string to string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = decode_base32["JBSWY3DPEE======"]
//output> "Hello!"
def output = decode_base32["4S62BZNFXU======"]
//output> "你好"
decode_base64
decode_base64[encoded_str]
Decodes the base-64 encoded string to string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = decode_base64["SGVsbG8h"]
//output> "Hello!"
def output = decode_base64["5L2g5aW9"]
//output> "你好"
default_value
default_value[D, F, c]
Make function or relation F
total for domain D
by defaulting to c
.
The arity of F must be the arity of D + 1.
Example:
def dom = {1;2;3;4}
def f = {(1, 321); (3, 123)}
def output = default_value[dom, f, 42]
//output> (1, 321)
// (2, 42)
// (3, 123)
// (4, 42)
See also: left_override
(<++
) and right_override
(++>
).
deg2rad
deg2rad[d]
deg2rad(d, r)
Convert degrees to radians.
Parameters
Parameter | Type | Description |
---|---|---|
d | Float , Int | r in degrees. Must be grounded. |
r | Float | d in radians. |
Examples
Convert 180
degrees to radians:
def output = deg2rad[180]
//output> 3.141592653589793
Convert -90
degrees to radians using full expression:
def output = deg2rad[-90]
//output> -1.5707963267948966
denominator
denominator[x]
Denominator of a rational-like number.
Examples:
denominator[rational[64, 1, 3]] = 3
denominator[rational[64, 1, 100]] = 100
denominator[rational[64, 1, 100] + rational[64, 1, 3]] = 300
denominator[parse_decimal[#64, #2, "3.14"]] = 100
denominator[parse_decimal[#64, #5, "3.14159"]] = 10000
denominator[5] = 1
describe
describe[R]
A summary of statistics for a dataset R
. R
should be a relation given in the form
R(:feature_name, keys..., value)
. For example, data loaded using load_csv
.
For each feature in the dataset, describe
computes a set of statistics depending on the
data type of that feature.
For numerical data, describe
computes the count, mean, standard deviation, minimum, 25th,
50th, 75th percentiles, and maximum for that feature.
For non-numerical data, describe
computes the count, unique count, mode, and mode
frequency. It will also compute maximum and minimum values if the data is sortable.
If a dataset has multiple data types, it will print the numerical stats for the numerical subset, and non-numerical stats for the non-numerical subset of the data.
For example, given a dataset R
in the form (produced by the CSV loader):
R = {
(:date, ^FilePos[29], 2020-01-01);
(:date, ^FilePos[60], 2020-02-02);
(:date, ^FilePos[91], 2020-03-03);
(:date, ^FilePos[127], 2020-04-04);
(:price, ^FilePos[29], 12.5);
(:price, ^FilePos[60], 14.25);
(:price, ^FilePos[91], 11.0);
(:price, ^FilePos[127], 12.25);
(:quantity, ^FilePos[29], 2);
(:quantity, ^FilePos[60], 4);
(:quantity, ^FilePos[91], 4);
(:quantity, ^FilePos[127], 3);
(:cocktail, ^FilePos[29], "martini");
(:cocktail, ^FilePos[60], "sazerac");
(:cocktail, ^FilePos[91], "cosmopolitan");
(:cocktail, ^FilePos[127], "bellini");
}
describe
will compute a summary:
Example:
def d = describe[R]
d[:date]
(:mode, 2020-01-01)
(:count, 4)
(:mode_freq, 1)
(:min, 2020-01-01)
(:max, 2020-04-04)
(:unique, 4)
d[:quantity]
(:max, 4)
(:count, 4)
(:std, 0.9574271077563381)
(:min, 2)
(:percentile75, 4.0)
(:percentile25, 2.75)
(:percentile50, 3.5)
(:mean, 3.25)
A describe_full
method is also provided, which does not aggregate over columns, and
instead computes the statistics for the whole dataset. However, describe_full
may cause
errors if any unsortable data (e.g., symbols) exists in the relation.
For example, given the relation R
defined above:
Example:
describe_full[R]
(:min, 32)
(:unique, 3)
(:mode, "a")
(:std, 49.47186262580647)
(:percentile25, 89.2175)
(:min, 3.27)
(:percentile50, 53.6)
(:mean, 16.75)
(:mean, 18.8675)
(:count, 7)
(:max, 72.2)
(:max, 35)
(:mode_freq, 1)
despecialize
despecialize[sv]
despecialize(sv, v)
Maps a specialized value sv
to the value v
.
Specialized values are used for schema information. Non-specialized values are used for storing the “actual” data.
Example:
def output = despecialize[#(55)]
//output> 55
def output = despecialize[:hello]
//output> "hello"
To verify the despecialization, one can write
def output = equal(despecialize[#(int[8, 0])], int[8, 0])
//output> () // true
diff
diff[R, S]
Set difference (complement): removes the tuples of S
from R
, if present.
Example:
def output = diff[{1;2;3;4} , {1;3} ]
//output> 2
// 4
disjoint
disjoint(R, S)
R
and S
are disjoint if they have no fact in common.
divide
divide[x, y]
divide(x, y, q)
x / y
Division of two numbers.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Numerator. Must be grounded. |
y | Number | Denominator. Must be grounded. |
q | Number | Quotient x / y . |
Not all numeric types can be combined with one another. The following combinations work:
x | y | q |
---|---|---|
Floating , Rational , FixedDecimal | Same as x | Same as x |
SignedInt , UnsignedInt | SignedInt , UnsignedInt | Floating[64] |
Floating[64] | Number | Floating[64] |
Number | Floating[64] | Floating[64] |
SignedInt , UnsignedInt | SignedInt[64] | Floating[64] |
SignedInt[64] | SignedInt , UnsignedInt | Floating[64] |
Floating | SignedInt[64] | Same as x |
SignedInt[64] | Floating | Same as y |
FixedDecimal | SignedInt , UnsignedInt | Same as x |
SignedInt , UnsignedInt | FixedDecimal | Same as y |
Rational | SignedInt | Rational with the larger bitsize of x and y |
SignedInt | Rational | Rational with the larger bitsize of x and y |
Explanation
In contrast to add
and subtract
, x
and y
need to be grounded and specified by the user.
Specifying only x
and q
or only y
and q
is not sufficient as the system can’t compute the inverse.
Examples
Divide two integers using /
:
def output = 24 / 2
//output> 12.0
Divide two rationals using /
:
def output = rational[64, 8, 3] / rational[64, 5, 2]
//output> 16/15
Divide one float by another using divide
:
def output = divide[8.4, 2.1]
//output> 4.0
Divide a rational by an integer using full expression:
def output(x) = divide(rational[16, 8, 3], 2, x)
//output> 4/3
docstring
docstring[:R]
The docstring of a relation as a string.
Example:
doc"The number 0." def zero = 0
def output = docstring[:zero]
//output> "The number 0."
domain
domain[F]
The domain of a scalar function F
. The domain represents all but the last argument of F
.
Example:
def output = domain[{(1, 'a', 1); (2, 'b', 4); (3, 'c', 9)}]
//output> (1, 'a')
// (2, 'b')
// (3, 'c')
dot_join
dot_join[R, S]
R . S
Compose
double_metaphone
double_metaphone[string_value]
double_metaphone_alt[string_value]
Double Metaphone is an improvement
of metaphone
that considers spelling particularities in a number of other languages.
double_metaphone
and double_metaphone_alt
returns an encoding of
the phonetic representation of string_value
. For many strings, double_metaphone
and
double_metaphone_alt
returns the very same encoding. However, it may differs based on the
spelling in a non-English language.
string_value
could be any arbitrary long string
Examples:
@inline def dm[string] = double_metaphone[string] ; double_metaphone_alt[string]
def output = dm["Smith"]
//output> sm0
def output = dm["Smythe"]
//output> sm0
// xmt
def output = dm["Christina"]
//output> krstn
def output = dm["Cristine"]
//output> krstn
def output = dm["I like Music"]
//output> ilkm
def output = dm["i loak Museek"]
//output> ilkm
def output = dm["RelationalAI"]
//output> rlxnl
def output = dm["rellationalleAI"]
//output> rlxnl
empty
empty(R)
Examples:
empty(1)
isfalse
empty(true)
isfalse
empty(false)
istrue
encode_base16
encode_base16[input_str]
Encodes the given string(input_str
) to base16-encoded string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Examples:
def output = encode_base16["Hello!"]
//output> 48656C6C6F21
def output = encode_base16["你好"]
//output> "E4BDA0E5A5BD"
encode_base32
encode_base32[input_str]
Encodes the given string(input_str
) to base32-encoded string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = encode_base32["Hello!"]
//output> "JBSWY3DPEE======"
def output = encode_base32["你好"]
//output> "4S62BZNFXU======"
encode_base64
encode_base64[input_str]
Encodes the given string(input_str
) to base64-encoded string, as per rfc4648 specifications.
Encoding/decoding specifications are found at https://datatracker.ietf.org/doc/html/rfc4648 (opens in a new tab).
Example:
def output = encode_base64["Hello!"]
//output> "SGVsbG8h"
def output = encode_base64["你好"]
//output> "5L2g5aW9"
ends_with
ends_with(s, suffix)
True if and only if the given string, s
, ends with the given suffix, suffix
.
The suffix can be a string of characters or a single character.
Example:
ends_with("abc", "c") // true
ends_with("abc", 'c') // true
ends_with("abc", "abc") // true
ends_with("abc", "C") // false
ends_with("abc", "ab") // false
ends_with("abc", "abcd") // false
Entity
Entity(x)
Holds if x
is an entity.
Example:
Integrity constraint specifying that mymodule
always contains an entity:
def mymodule:f = 1
ic my_entity_ic(x) { mymodule(x) implies Entity(x) }
enumerate
enumerate[R]
enumerate(R, index, x...)
Enumerate the tuples in the relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Relation to be enumerated. Must be grounded. |
index | Int | The new enumartion index starting at 1. |
x... | Tuples | A tuple in R associated with the new index index . |
Explanation
enumerate
takes a relation R(x...)
and produces a relation with the tuples(index, x...)
where the first element of each tuple (index
) is an integer index that enumerates the tuples x...
in the original relation R
.
enumerate
supports relations of multiple arities, which are relations that contain tuples of various lengths.
Lexicographical Order
Lexicographical order of the tuples is determined by first sorting them according to their data schema, according to the following rules:
- Tuples are first ordered by the data types in the first column, then second, and so on.
- Tuples with no data in the current column come first. For example,
(Int)
comes before(Int, Int)
. - Within each column, types are put in alphabetical order. For example,
Char
precedesDate
, which precedesFloating
. - If types have parameters, they are ordered by parameters. For example,
Floating[32]
precedesFloating[64]
, and so on.
After the schemas of the tuples are sorted, the tuples with the same schema are sorted based on the actual values in the tuples, according to the following rules:
- Tuples are first sorted by the data values in the first column, then second, and so on.
- Tuples are ordered based on the intrinsic order of the data type.
- Numeric data types: Sorting numerically. For example,
1
comes before2
. - Text-based data types:
Char
andString
are sorted “asciibetically”, which means that digits and punctuation marks come before letters, and uppercase letters come before lowercase letters; for example, “Z” precedes “a”. - Date-based data types:
Date
andDateTime
are sorted so that older timestamps come first.
- Numeric data types: Sorting numerically. For example,
Examples
Enumerate an arity-1 relation:
def sample = {'a'; 'b'; 'c'}
def output = enumerate[sample]
//output> (1, 'a')
// (2, 'b')
// (3, 'c')
//first column is index
Enumerate an arity-2 relation (alphabetical on first column):
def sample = {
("phone", 45);
("laptop", 89);
("memory", 100)
}
def output(index, x...) = enumerate(sample,index, x...)
//output> (1,"laptop",89)
// (2,"memory",100)
// (3,"phone",45)
Just as with aggregations, it is possible to enumerate separately per group.
In the following example, the enumeration is grouped by the group-by variable x
,
which iterates over the values in the first column of sample
.
def sample = { (:g, 'a'); (:g, 'b'); (:g, 'c'); (:h, 'd'); (:h, 'e'); (:h, 'f') }
def output[x] = enumerate[sample[x]]
//output> (:g, 1, 'a')
// (:g, 2, 'b')
// (:g, 3, 'c')
// (:h, 1, 'd')
// (:h, 2, 'e')
// (:h, 3, 'f')
Enumerate a relation containing various tuple lengths and types:
def sample = {
2; 3;
"a"; "b";
(1, 3); (1, 10);
}
def output = enumerate[sample]
//output> (1, 2)
// (2, 3)
// (3, 1, 3)
// (4, 1, 10)
// (5, "a")
// (6, "b")
Here you can see the impact of sorting the data schemas first: tuples of the form (Int)
come before tuples of the form (Int, Int)
.
Because the sorting of data type per column is more important than the length of the tuples, the tuples of the form (String)
come after (Int, Int)
tuples, making ("b")
the tuple with the largest index.
See Also
sort
and reverse_sort
.
epoch_milliseconds
epoch_milliseconds[dt]
Milliseconds since Epoch time, as a value of type Int64
.
eq
eq(x, y)
x = y
Equality between scalar (single) values, such as integers, strings, symbols. (For equality between relations, use equal
.)
Examples:
1 = 1
istrue
.:a = :a
istrue
"a" = "a"
istrue
2 = 2.0
isfalse
1 = "a"
isfalse
equal
equal(R, S)
F ≡ G
Relational equality. Note that eq
and =
should be used only for scalar values, while
equal
should be used to check that two relations are the same.
erf
erf[x]
The error function of x
.
External link: https://en.wikipedia.org/wiki/Error_function (opens in a new tab)
Examples:
erf[2] = 0.9953222650189527
erf[-0.5] = -0.5204998778130465
erfinv
erfinv[x]
The inverse error function of x
.
External link: https://en.wikipedia.org/wiki/Error_function#Inverse_functions (opens in a new tab)
Examples:
erfinv[0.1] = 0.08885599049425769
erfinv[-0.5] = -0.4769362762044699
erfinv[erf[1]] = 1.0
escape_regex_metachars
escape_regex_metachars(string, escaped_string)
Escape the necessary regular expression metacharacters in string
such that
escaped_string
can be used as a regular expression and have none of its
characters interpreted as metacharacters.
Example:
def ere = escape_regex_metachars["."]
def output = regex_match_all[ere, "abc.123"]
will only give
{(4, ".")}
since .
is escaped and is not treated as a metacharacter.
export_csv
export_csv[R]
This is the main entry point to specify relations that should be
exported to CSV. The payload relation R
is expected to be a
configuration relation mapping keys to relations.
Required keywords are:
:path
: A string specifying the location of the file that is to be created.
Optional keywords:
:data
: A set of relations mapping a file position, which can be a key of arbitrary length or type, to the corresponding value. This is the data that will be exported. We expect the data relation to be of form: data(:COLUMN_NAME, pos, val):integration
: A relation containing storage integration configuration.:schema
: A relation containing schema information.:syntax
: A relation containing syntax configuration.:partition_size
: An int specifying at what estimated file size in MB the produced CSV file should be split into partitions. For example, if the exported CSV file is estimated to have a size of 1GB, with:partition_size=100
it will be exported into 10 partitions of roughly 100MB each. Set:partition_size=0
to suppress partitioning even for very large exports at the cost of export performance. By default,:partition_size=0
is used.:compression
: The algorithm that is used to compress the CSV output file. We only supportgzip
at the current stage.
Example using default CSV schema and syntax and no storage integration.
def csv_data(:ORDER, pos, v) = ((1,1); (2,2); (3,3))(pos, v)
def csv_data(:LINEITEM, pos, v) = ((1,100); (2,101); (3,102))(pos, v)
def csv_data(:QUANTITY, pos, v) = ((1,2); (2,15); (3,42))(pos, v)
def export = export_csv[(:path, "/path/to/local/file.csv"); (:data, csv_data)]
Example using a custom CSV schema.
def csv_syntax[:delim] = ';'
def csv_syntax[:quotechar] = '_'
def export = export_csv[(:path, "/path/to/local/file.csv");
(:data, csv_data);
(:syntax, csv_syntax)]
Example using an Azure storage integration using a SAS token:
def integration[:provider] = "azure"
def integration[:credentials, :azure_sas_token] = "<azure_sas_token>"
def export = export_csv[(:path, "azure://<account_name>.blob.core.windows.net/container/file.csv");
(:data, csv_data);
(:integration, integration)]
Example with compound keys:
def csv_data(:ORDER, pos..., v) = (1, 2, 100; 2, 1, 40)(pos..., v)
def csv_data(:QUANTITY, pos..., v) = (1, 3, 10; 2, 3, 11; 3, 1, 12; 3, 2 ,13)(pos..., v)
def export = export_csv[(:data, csv_data; :path, "/path/to/data.csv")]
export_json
export_json[R]
This is the main entry point to specify relations that should be
exported to JSON. The payload relation R
is expected to be a
configuration relation mapping keys to relations.
Required keywords are:
:path
: A string specifying the location of the file that is to be created.
Optional keywords:
:data
: The relation(s) that should be exported.:integration
: A relation containing storage integration configuration.:indent
: Number of spaces to indent the resulting document. If not present, we’ll write a compact form.
Example for a simple JSON object
def json[:author] = "David Foster Wallace"
def json[:title, :name] = "Infinite Jest"
def json[:title, :isbn] = "978-0-316-92004-9"
def export = export_json[(:path, "/path/to/file.json");
(:data, json);
(:indent, 2)]
This results in the following JSON:
{
"author": "David Foster Wallace",
"title": {
"name": "Infinite Jest",
"isbn": "10: 0316921173"
}
}
Since authors usually write more than one book,
we’ll make the :title
path an array of objects.
Examples:
def json[:author] = "David Foster Wallace"
def titles = (1, "Infinite Jest", "978-0-316-92004-9");
(2, "The Pale King", "978-0-316-07423-0")
def json[:titles, :[], idx] = ((:name, name);
(:isbn, isbn)
from name, isbn where titles(idx, name, isbn))
def export = export_json[(:path, "/path/to/file.json");
(:data, json);
(:indent, 2)]
The :[]
marker, i.e. array marker, needs to be present when an array is to be correctly produced.
This yields the following output:
{
"author": "David Foster Wallace",
"titles": [
{
"name": "Infinite Jest",
"isbn": "978-0-316-92004-9"
},
{
"name": "The Pale King",
"isbn": "978-0-316-07423-0"
}
]
}
factorial
factorial[x]
Factorial of x.
Defined for non-negative x
.
The result is promoted to at least 64-bits.
If x
is up to 64-bits, factorial
is defined for values up to 20 (inclusive).
If x
is Int128
, factorial
is defined for values up to 33 (inclusive).
If x
is UInt128
, factorial
is defined for values up to 34 (inclusive).
filepos
filepos[v]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the FilePos constructor, ^FilePos
, instead.
Creates a FilePos representing position v
in a file.
FilePos
FilePos(x)
Brings the data type relation FilePos
from the module rel:base
into the global namespace.
For more details, see the rel:base:FilePos
docstring.
filepos_value
filepos_value[fp]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the FilePos constructor, ^FilePos
, instead.
Retrieves the numeric position represented by a FilePos.
first
first[R]
Projection to the first argument of R.
first
supports heterogeneous relations, both in arity and types.
Examples:
def output = first[(1, 2, 3); (4, 5, 6)]
//output> 1
// 4
def output = first[(1, 2, 3); (4, 5); 6]
//output> 1
// 4
// 6
def output = first[("a", 1); (2, 3)]
//output> 2
// "a"
FixedDecimal
FixedDecimal(nbits, ndecimals, x)
Holds if x
is of type FixedDecimal
with a bit size of nbits
and ndecimals
decimal precision.
nbits
and ndecimals
are specialized integers.
Examples:
Integrity constraint that tests whether x
is a FixedDecimal
with a bit size of #64
and #4
decimal precision:
def R = decimal[#64, #4, pi_float64]
ic float_type_check(x in R) {
FixedDecimal(#64, #4, x)
}
Query to check whether x
is a FixedDecimal
with a bit size of #64
and #4
decimal precision.
def R = {decimal[#64, #4, pi_float64]; decimal[#64, #10, pi_float64]}
def output(x) = R(x) and FixedDecimal(#64, #4, x)
//output> 3.1416
FixedDecimal_spread
FixedDecimal_spread[mode, R, val]
FixedDecimal_spread(mode, R, value, x..., spread)
Spread value
to the tuples in relation R
as decimals, either evenly or proportionally to their
weight, which is the last element in each tuple.
Parameter | Type | Description |
---|---|---|
mode | RelName | :even or :ratio . |
R | Relation | Source relation. Must be grounded. |
value | FixedDecimal | Decimal to be divided among tuples as spread . |
x... | Tuple | A tuple in R . |
spread | Floating[64] | Spread associated with x... . |
Explanation
FixedDecimal_spread
takes a relation R(x...)
and produces a relation with the
tuples (x..., spread)
where the last element of each tuple (spread
)
is a spread of value
distributed among tuples.
When mode
is :even
, spread
is value
divided evenly among tuples.
When mode
is :ratio
, spread
is value
divided proportionally to a tuple’s
weight — the last element in each tuple.
In contrast to int_spread_by_even
and int_spread_by_ratio
, here spread
is a decimal, 10^(-d)
, where d
is the
number of digits used in value
.
For example, if value
is 3.140
, the smallest unit to spread will be 0.001
.
FixedDecimal_spread
is empty if value
is negative.
Examples
Spread 3.14
among three tuples:
def R = {("Atlanta", 50);
("Seattle", 80);
("San Francisco", 10)}
def output = FixedDecimal_spread[:even, R, decimal[#64, #3, 3.14]]
//output> Atlanta, 50, 1.047
// San Francisco, 10, 1.047
// Seattle, 80, 1.046
Spread 10.5
among three tuples using :ratio
:
def R = {("Atlanta", 10);
("Seattle", 80);
("San Francisco", 10)}
def output = FixedDecimal_spread[:ratio, R, decimal[#64, #3, 10.5]]
//output> Atlanta, 50, 1.05
// San Francisco, 10, 1.05
// Seattle, 80, 8.4
Spread 88.55
among three tuples using full expression:
def R = {("Miles Davis", 65); ("Jimmy Smith", 76); ("Ornette Coleman", 85)}
def output(x...) = FixedDecimal_spread(:ratio, R, decimal[#64, #3, 88.55], x...)
//output> Jimmy Smith, 29.778
// Miles Davis, 25.468
// Ornette Coleman, 33.304
Spread using group-by:
def R = {
("Seattle", "Washington", 1);
("San Francisco", "California", 0.4);
("Los Angeles", "California", 0.6)
}
def amount = {
("Washington", decimal[#64, #3, 50]);
("California", decimal[#64, #3, 100.0])
}
def output[state] = FixedDecimal_spread[
:ratio,
(city, v : R(city, state, v)),
amount[state]
]
//output> California, Los Angeles, 60.0
// California, San Francisco, 40.0
// Washington, Seattle, 50.0
See Also
int_spread_by_ratio
, int_spread_by_even
, and spread
.
float
float[n, v]
The n-bit floating point value from the number v
.
n
must be among 16, 32, and 64.
Examples:
float[64, 3.0] = 3.0
float[16, 3.14156] = 3.14
empty(float[11, 3.14])
float_int_convert
float_int_convert[x]
Conversion from float to int.
If the argument is not equivalent to an int, float_int_convert
returns false
. (See trunc_to_int
, floor_to_int
for general conversion.)
Example:
float_int_convert[3.0] = 3
float_int_convert[3.2] = false
float64
float64[v]
The 64-bit floating point value from the number v
, which must be a float.
Floating
Floating(nbits, x)
Holds if x
is an nbits' floating point number.
Float(x)is a shorthand that holds if
x` is a 64-bit float.
Example:
Integrity constraint that tests if x
is a 32-bit float (will throw if x
is not a 32-bit Float):
def R = float[32, 1.321]
ic float_type_check(x in R) {
Floating(32, x)
}
floor
floor[x]
floor(x, f)
Round down to the nearest integer toward negative infinity.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Number to be rounded down. Must be grounded. |
f | Number | Floor of x . |
Return type is the same as x
.
Explanation
For positive x
, floor
rounds toward 0.
For negative x
, floor
rounds away from 0.
Examples
Calculate floor for decimal:
def output = floor[4.569]
//output> 4.0
Calculate floor for negative decimal using full expression:
def output(f) = floor(-4.569, f)
//output> -5.0
Calculate floor for positive rational:
def output = floor[rational[64, 8, 3]]
//output> 2/1
See Also
floor_to_int
, ceil
, trunc
, trunc_to_int
, and round
.
floor_divide
floor_divide[x, y]
floor_divide(x, y, q)
Division of two numbers, rounding the result to the nearest integer toward negative infinity.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Numerator. Must be grounded. |
y | Number | Denominator. Must be grounded. |
q | Number | Largest integer less than or equal to x / y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | q |
---|---|---|
SignedInt[64] | SignedInt[64] | SignedInt[64] |
SignedInt[64] | Floating[64] | Floating[64] |
Floating[64] | SignedInt[64] , Floating[64] | Floating[64] |
Rational | SignedInt[64] | SignedInt[64] |
FixedDecimal | SignedInt[64] | Same as x |
Explanation
Largest integer less than or equal to x/y
.
Computes x/y
rounded towards negative infinity.
floor_divide
maps the pair x
, y
to q
, which is the floored quotient x/y
.
Similar to divide
and in contrast to add
and subtract
, x
and y
need to be grounded and specified by the user.
Specifying only x
and q
or only y
and q
is not sufficient, because the system can’t compute the inverse.
Is false
(empty) when y = 0
for integer arguments.
Examples
Use floor division to divide a postiive integer by a positive integer:
def output = floor_divide[5, 2]
//output> 2
Use floor division with full expression to divide a negative integer by a positive integer:
def output(q) = floor_divide(-5, 2, q)
//output> -3
Use floor division to divide a float by an integer:
def output = floor_divide[5.1, 2]
//output> 2.0
Confirm that floor_division[R]
is empty
when y
= O:
def output = empty(floor_divide[5.1, 0])
//output> () // true
floor_to_int
floor_to_int[x]
floor_to_int(x, f)
Convert float to integer using floor.
Parameters
Parameter | Type | Description |
---|---|---|
x | Float | Float to be converted to integer using floor. Must be grounded. |
f | Int | Floor of x . |
Explanation
For positive x
, floor_to_int
rounds toward 0.
For negative x
, floor_to_int
rounds away from 0 toward negatve infinity.
Examples
Convert float to integer:
floor_to_int[3.1]
//output> 3
Convert negative float to integer using full expression. Note that rounding goes away from 0 toward negative infinity.
def output(f) = floor_to_int(-3.1, f)
//output> -4
Returns false
because x
is an integer:
def output = floor_to_int[3]
//output> // false
See Also
floor
, ceil
, trunc
, trunc_to_int
, and round
.
format_date
format_date[d, format]
A string where the Date d
is formatted according to format
.
Example:
def d = parse_date["2018-06-12", "Y-m-d"]
def output = format_date[d, "Y-mm-d"]
//output> 2018-06-12
For details on the format parameter, see the Julia documentation for Dates.DateFormat
(opens in a new tab).
format_datetime
format_datetime[dt, format, tz]
Format a DateTime dt
, with timezone tz
.
Example:
def format = "yyyy-mm-dd HH:MM ZZZ"
def dt = parse_datetime["2018-03-11 01:00 America/New_York", "Y-m-d H:M Z"]
def output = format_datetime[dt, format, "America/New_York"]
//output> "2018-03-11 01:00 EST"
For details on the format parameter, see the Julia documentation for Dates.DateFormat
(opens in a new tab).
formula_card_est
formula_card_est[R]
The cardinality estimate of a given relational abstraction R
as estimated by the
physical query optimizer. The estimate is represented as a Float
. It is typically
an upper bound on the actual cardinality and can suffer from a numeric overflow, e.g. if the
formula R
is a big cross-product of relations. To avoid this, use the log-version
log_card_est[R]
. See log_card_est
for more details.
Examples:
def card = formula_card_est[R]
def card = formula_card_est[a, b, c: R(a, b) and S(b, c) and T(a, c)]
frequency
frequency[R, elem]
frequency(R, elem, freq)
frequency[R]
Find the frequency freq
of elem
in the set of all
last elements of tuples in the relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A general relation. Must be grounded. |
elem | Any | Element whose frequency will be found. |
freq | Number | The frequency of elem . |
Explanation
If elem
is omitted, frequency[R]
finds the frequency of each element.
Examples
Find the frequency of a single value:
def example = {(1, "a"); (2, "b"); (3, 123); (4, 12.5); (3, "b")}
def output = frequency[example, "b"]
//output> 2
Find the frequency of all values:
def example = {(1, "a"); (2, "b"); (3, 123); (4, 123); (5, "b"); (6, "b")}
def output = frequency[example]
//output> 123, 2
// "a", 1
// "b", 3
full_relation_approx_equal
full_relation_approx_equal(tolerance, R, S)
Approximate relational equality of the entire relation.
To hold true, all tuples (and the values they hold) in R
and S
must be approximately equal to each other.
Parameter | Type | Description |
---|---|---|
tolerance | SignedInt[64] or Floating[64] | A positive integer or float. |
R | Relation | A relation whose arguments can be compared to S . |
S | Relation | A relation whose arguments can be compared to R . |
Explanation
Two relations R
and S
are considered “fully relationally approximately equal” when there exists for each tuple in R
a tuple in S
that is considered approximately equal (and vice versa).
Two tuples are considered approximately equal if each element within one tuple is approximately equal to the element in the other tuple which is located at the same position. This implies tuples that are approximately equal need to have the same length.
See approx_eq
for the details about approximate equality between two data values.
The parameter tolerance
stands for the absolute tolerance and must be of type SignedInt[64]
or Floating[64]
.
tolerance
must be a positive number; negative numbers will return false
.
full_relation_approx_equal
is quite slow and should not be used for large data sets.
Example
Approximate relational equality determined as true
:
def coordinates1 = (1.0, 2.0); (3.0, 6.0)
def coordinates2 = (1.0000001, 2.0); (2.9999999, 6.0000001)
def output = full_relation_approx_equal(0.001, coordinates1, coordinates2)
//output> () // true
Approximate relational equality determined as false:
def coordinates1 = (1.0, 2.0); (3.0, 6.0)
def coordinates2 = (1.0000001, 2.05); (2.9999999, 6.0000001)
def output = full_relation_approx_equal(0.001, coordinates1, coordinates2)
//output> // false
See Also
approx_equal
, approx_eq
, equal
, and eq
.
function
function(R)
Holds if R
is a function.
Parameter | Type | Description |
---|---|---|
R | Relation | A general relation. Must be grounded. |
Given a relation R
, function(R)
is true
if R
is a function and false
if not.
Functions are relations where values — the last elements of tuples — are uniquely determined by the keys — the initial elements of tuples.
That is, a relation R(x, y, z)
is a function if and only if each initial set of elements x, y
— the “key” —
map to only one value each for z
.
For example, the relation {(1, “one”); (2, “two”)}
is a function, but the relation
{(1, “one”); (1, “uno”); (2, “two”); (2, “dos”)}
is not a function, because the keys 1
and 2
have multiple values.
Similarly, R{(1, 2, 3); (1, 3, 5)}
is a function but R{(1, 2, 3); (1, 2, 4)}
is not a function, because multiple tuples start with (1, 2)
.
This understanding of function is also consistent with mathematical functions — as with sin
or power
/^
— where the argument(s) of the function map to one value.
In this sense, mathematical functions are relations with a functional dependency.
The arguments, x..
, and value, v
, of the function map to the tuples (x..., y)
in the relation.
For mathematical function, the domain of x...
is usually continuous and unbound.
Examples
Evaluates to true
:
def output = function({(1, 2); (2, 5)})
//output> () // true
Evaluates to false
:
def output = function({(1, 2); (1, 3)})
//output> // false
Arity-3 function that evaluates to true
:
def output = function({(1, 2, 3) ; (1, 3, 4)})
//output> () // true
Integrity constraint ensuring that R
is a function:
ic R_is_a_function { function(R) }
See Also
domain
and default_value
.
geometric_mean
geometric_mean[R]
geometric_mean(R, gm)
The geometric mean of the last element of each tuple in a relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A relation whose tuples contain numeric data types. Must be grounded. |
gm | SignedInt , Floating | The geometric mean of R . |
Explanation
The geometric mean of a relation R
that contains n
tuples is the n
-th root
of the product of the last elements in each tuple.
geometric_mean
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that geometric_mean
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, geometric_mean
is used when the last elements of each tuple have the same type
If R
is empty, geometric_mean[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Calculate geometric mean for R
:
def R = {("A", 1); ("B", 3); ("C", 5); ("D", 7); ("E", 9)}
def output = geometric_mean[R]
//output> 3.936283427035352
Calculate geometric mean for R
using full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(gm) = geometric_mean(R, gm)
//output> 8.276527798701737
See Also
mean
, harmonic_mean
, weighted_mean
, mode
, max
, min
, sum
, and product
.
gt
gt(x, y)
x > y
gt_eq
gt_eq(x, y)
x ≥ y
x >= y
harmonic_mean
harmonic_mean[R]
harmonic_mean(R, hm)
The harmonic mean (hm
) of the last elements of each tuple in a relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A relation whose tuples contain numeric data types. Must be grounded. |
hm | Number | The harmonic mean of R . |
Explanation
The harmonic mean of a relation R
is the reciprocal of
the arithmetic mean of the reciprocals of the last elements in each tuple.
harmonic_mean
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that harmonic_mean
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, harmonic_mean
is used when the last elements of each tuple have the same type.
If R
is empty, harmonic_mean[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Calculate the harmonic mean of R
:
def output = harmonic_mean[{('a',1); ('b',2); ('a',3); ('b',4); ('c',5); ('d',6}]
2.44897959184
Calculate the harmonic mean of R
using the full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(hm) = harmonic_mean(R, hm)
//output> 8.229800388043014
Find the harmonic mean for relation with tuples of various lengths:
def R = {(10); (2, 30); (3, 50, 2)}
def output = harmonic_mean[R]
//output> 4.736842105263158
See Also
geometric_mean
, weighted_mean
, mean
, mode
, max
, min
, sum
, and product
.
hash
hash[R]
hash(R, x..., h)
Hash each of the tuples in the relation and add it as a new column in the result.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Relation to be hashed. Must be grounded. |
x... | Tuples | A tuple in R associated with hash . |
h | Hash | A 128-bit HashValue index. |
Explanation
hash
takes a relation R(x...)
and produces a relation R(x..., h)
where the last element of the relation, h
, is a 128-bit HashValue
that is the result of hashing all elements in the tuple x...
and combining them into one value.
hash
is identical to hash128
.
Examples
Hash a single value:
def output = hash['a']
//output> a, 59209653874858713274180299714158372840
Hash a relation with tuples that have multiple elements:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output = hash[sample]
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913
Hash a relation using full expression:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output(x..., h) = hash(sample, x..., h)
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913
Confirm that identical tuples in different relations hash to the same value:
def R = (:a, 1); (:b, 2)
def S = (:a, 1); (:b, 2)
def output = equal[hash[R], hash[S]]
//output> () // true
See Also
hash_value_uint128_convert
, murmurhash3f
, and murmurhash3f_with_seed
.
Hash
Hash(x)
Holds if x
is a RelationalAI HashValue generated by hash128
.
Examples:
Integrity constraint that tests whether x
is Hash (will throw if x
is not Hash):
def R = (9, "a")
def my_hash = hash128[R]
//three value relation with hash value as third value
ic hash_type_check{
subset(my_hash, (Any, Any, Hash))
}
Defines Hash as schema for a relation:
def R = (9, "a")
def my_hash = hash128[R]
def hashed_relation(x in Hash) = my_hash(_, _, x)
def output = hashed_relation
//output> -107770920621774551289984725953057040743
hash_value_uint128_convert
hash_value_uint128_convert[v]
Convert a HashValue v
to UInt128.
hash128
hash128[R]
hash128(R, x..., h)
Hash each of the tuples in the relation and add it as a new column in the result.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Relation to be hashed. Must be grounded. |
x... | Tuple | A tuple in R associated with hash . |
h | Hash | A 128-bit HashValue index. |
Explanation
hash128
takes each tuple x...
in R
and produces a relation (x..., h)
where the last element of the relation, h
, is a 128-bit HashValue
that is the result of hashing all elements in the tuple x...
and combining them into one value.
Examples
Hash a single value:
def output = hash128['a']
//output> a, 59209653874858713274180299714158372840
Hash a relation with tuples that have multiple elements:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output(x..., h) = hash128(sample, x..., h)
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913
Hash a relation using full expression:
def sample = {('a', 1); ('b', 2); ('c', 3)}
def output(x..., h) = hash128(sample, x..., h)
//output> a, 1, 218658623352236411286898175739604563355
// b, 2, 183357509907040413044473069762065340376
// c, 3, 153679601071624610141668476986592179913
Confirm that identical tuples in different relations hash to the same value:
def R = (:a, 1); (:b, 2)
def S = (:a, 1); (:b, 2)
def output = equal[hash128[R], hash128[S]]
//output> () // true
<p className="docstring-level-2">See Also</p>
`hash_value_uint128_convert`, `murmurhash3f`, and `murmurhash3f_with_seed`.
haversine
haversine[x1, y1, x2, y2, r]
haversine(x1, y1, x2, y2, r, hs)
The great circle distance of two points, and , on a sphere of radius , using the Haversine formula. The two points are specified by their latitude and longitude in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x1 | Floating[64] , SignedInt[64] , UnsignedInt[64] | coordinate of the 2D point . Must be gounded. |
y1 | Floating[64] , SignedInt[64] , UnsignedInt[64] | coordinate of the 2D point . Must be gounded. |
x2 | Floating[64] , SignedInt[64] , UnsignedInt[64] | coordinate of the 2D point . Must be gounded. |
y2 | Floating[64] , SignedInt[64] , UnsignedInt[64] | coordinate of the 2D point . Must be gounded. |
r | Floating[64] , SignedInt[64] , UnsignedInt[64] | radius of sphere. Must be grounded. |
hs | UnsignedInt[64] , SignedInt[64] , Floating[64] | Haversine of and on sphere of radius . |
Examples
Calculate the haversine of (10, 0) and (0, 0) on sphere of radius π/2:
def output = haversine[10, 0, 0, 0, pi_float64/2]
//output> 15.707963267948964
Calculate the haversine of (10, 10) and (-10, 0) on sphere of radius 2π using full expression:
def output(hs) = haversine(10, 10, -10, 0, 2*pi_float64, hs)
//output> 7.897244441795649
Hour
Hour[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Hour constructor, ^Hour
, instead.
Create a period of n
hours.
iff
F iff G
F ⇔ G
If and only if (boolean equivalence), for boolean (arity 0, true or false) arguments F and G.
int
int[n, v]
The n
-bit signed integer value from the integer value v
.
n
must be among 8, 16, 32, 64, and 128 and v
is encodable with n
-bits.
Examples:
int[8][42] = 42
empty(int[8][300])
int_float_convert
int_float_convert[x]
Conversion from int to float. Argument must be an int.
Example:
int_float_convert[3] = 3.0
int_float_convert[3.2] : error
int_spread_by_even
int_spread_by_even[R, value]
int_spread_by even(R, value, x..., spread)
Spread value
to the tuples in relation R
evenly as whole units.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
value | Int | Integer to be divided among tuples as spread . Must be grounded. |
x... | Tuple | A tuple in R . |
spread | Floating[64] | Spread associated with x... . |
Explanation
int_spread_by_even
produces a relation with the tuples (x..., spread)
where the last element of each tuple (spread
)
is value
divided equally among the tuples in R
.
For example, if value
is 50
and R
has five tuples, spread
will be 10
for each tuple.
In cases of uneven spread, as when value
is 51
and R
has five tuples, the remainder is distributed by units to as many tuples as possible according to their lexicographic order.
int_spread_by_even
is empty if value
is negative.
Examples
Spread 30
evenly over three tuples:
def R = {"apple"; "banana"; "strawberry"}
def output = int_spread_by_even[R, 30]
//output> apple, 10
// banana, 10
// strawberry, 10
Spread 32
over three tuples, remainder applied to first two tuples:
def R = {"Atlanta"; "Seattle"; "San Francisco"}
def output = int_spread_by_even[R, 32]
//output> Atlanta, 11
// San Francisco, 11
// Seattle, 10
Spread 45
over three tuples using full expression:
def R = {"Miles Davis"; "Jimmy Smith"; "Ornette Coleman"}
def output(x...) = int_spread_by_even(R, 45, x...)
//output> Jimmy Smith, 15
// Miles Davis, 15
// Ornette Coleman, 15
See Also
int_spread_by_ratio
, FixedDecimal_spread
, and spread
.
int_spread_by_ratio
int_spread_by_ratio[R, value]
int_spread_by_ratio(R, value, x..., w, spread)
Spread value
to the tuples in relation R
as whole units proportionally to their
weight, which is the last element in each tuple.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
value | SignedInt[64] | Integer to be divided among tuples as spread . Must be grounded. |
x... | Tuple | A tuple in R . |
spread | Floating[64] | Spread associated with x... . |
Explanation
int_spread_by_ratio
takes as input a relation R(x..., w)
, where x...
are one or more elements that serve as the key
and w
is a weight of type Floating[64]
or SignedInt[64]
.
int_spread_by_ratio
produces a relation with the tuples (x..., w, spread)
where the last element of each tuple (spread
)
is a spread among tuples, determined proportionally to a tuple’s weight as whole units.
For example, if the relation is {("X", 90); ("Y", 10)}
, "X"
will get 90%
of value
and "Y"
will get 10%
.
In cases where this split results in a decimal, int_spread_by_ratio
first distributes the floor value of the decimal number computed.
The remainder is distributed as single units in order starting from the
element with the highest decimal value.
int_spread_by_ratio
is empty if value
is negative.
Examples
Spread 100
over three tuples:
def R = {("Atlanta", 50);
("Seattle", 10);
("San Francisco", 40)}
def output = int_spread_by_ratio[R, 100]
//output> Atlanta, 50
// San Francisco, 40
// Seattle, 10
Spread 102
over three tuples with remainder:
def R = {("Atlanta", 50);
("Seattle", 10);
("San Francisco", 40)}
def output = int_spread_by_ratio[R, 102]
//output> Atlanta, 51
// San Francisco, 41
// Seattle, 10
Spread 1000
over three tuples using full expression:
def R = {("apple", 17);
("banana", 18);
("strawberry", 15)}
def output(x...) = int_spread_by_ratio(R, 1000, x...)
//output> apple, 340
// banana, 360
// strawberry, 300
See Also
int_spread_by_even
, FixedDecimal_spread
, and spread
.
int128
int128[v]
The 128-bit signed integer value from the integer value v
.
int64
int64[v]
The 64-bit signed integer value from the integer value v
.
intersect
intersect[R, S]
R ∩ S
Intersect two n-ary relations R and S
is_Day
is_Day(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Day(x)
instead.
Note that you have to include the rel:base
, because Day
is the deprecated constructor.
Holds if x
is a Day
period.
is_Hour
is_Hour(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Hour(x)
instead.
Note that you have to include the rel:base
, because Hour
is the deprecated constructor.
Holds if x
is a Hour
period.
is_Microsecond
is_Microsecond(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Microsecond(x)
instead.
Note that you have to include the rel:base
, because Microsecond
is the deprecated constructor.
Holds if x
is a Microsecond
period.
is_Millisecond
is_Millisecond(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Millisecond(x)
instead.
Note that you have to include the rel:base
, because Millisecond
is the deprecated constructor.
Holds if x
is a Millisecond
period.
is_Minute
is_Minute(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Minute(x)
instead.
Note that you have to include the rel:base
, because Minute
is the deprecated constructor.
Holds if x
is a Minute
period.
is_Month
is_Month(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Month(x)
instead.
Note that you have to include the rel:base
, because Month
is the deprecated constructor.
Holds if x
is a Month
period.
is_Nanosecond
is_Nanosecond(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Nanosecond(x)
instead.
Note that you have to include the rel:base
, because Nanosecond
is the deprecated constructor.
Holds if x
is a Nanosecond
period.
is_Second
is_Second(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Second(x)
instead.
Note that you have to include the rel:base
, because Second
is the deprecated constructor.
Holds if x
is a Second
period.
is_Week
is_Week(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Week(x)
instead.
Note that you have to include the rel:base
, because Week
is the deprecated constructor.
Holds if x
is a Week
period.
is_Year
is_Year(x)
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use rel:base:Year(x)
instead.
Note that you have to include the rel:base
, because Year
is the deprecated constructor.
Holds if x
is a Year
period.
jacobian
jacobian[S, R]
jacobian(S, R, J)
Compute the Jacobian (e.g. the derivative or gradient) of relation S
w.r.t. relation R
.
jacobian
computes the derivatives of one scalar- or vector-valued relation (R
) with respect to a second scalar- or vector-valued relation (S
).
It returns a matrix of all of them (J
) using (relational) automatic differentiation techniques.
Both relations (S
and R
) must be key value pairs.
This is true even of scalars such as x[1]
, which cannot be rendered as x
.
Examples
Derivative of a scalar-valued relation of one scalar variable:
def y[1] = 1.0
def z[1] = 3.0 * y[1]^2
def output = jacobian[z, y]
//output> 1,1,6.0
Derivative of a more complicated scalar-valued relation of one scalar variable:
def x[1] = 1.0
def y[1] = 3.0 * x[1]^2
def z[1] = y[1] / 2
def output = jacobian[z, x]
//output> 1,1,3.0
Gradient of a vector-valued relation with respect to a scalar input:
def y[1] = 2.0
def z[1] = 3.0 * y[1]^2
def w[1] = z[1]^2
def w[2] = y[1]
def output = jacobian[w, y]
//output> 1,1,288.0
// 2,2,1.0
Jacobian of a vector-valued relation with respect to a vector input:
def y[1] = 1.0
def y[2] = 4.0
def z[1] = 2*y[1] + 3*y[2]
def z[2] = y[1] - y[2]
def output = jacobian[z, y]
//output> 1,1,2.0
// 1,2,3.0
// 2,1,1.0
// 2,2,-1.0
json_string
json_string[json_relation]
The string representation of a relation that encodes JSON data.
Example:
def json_relation[:name] = "Amira"
def json_relation[:age] = 32
def json_relation[:height] = missing
def json_relation[:pets, :[], 1] = "dog"
def json_relation[:pets, :[], 2] = "rabbit"
def result = json_string[json_relation]
results in the following JSON:
{
"name": "Amira",
"age": 32,
"height": null,
"pets": [
"dog",
"rabbit"
]
}
last
last[R]
Projection to the last argument of the relation R
.
last
supports heterogeneous relations, both in arity and types.
Examples:
def output = last[(1, 2, 3); (4, 5, 6)]
//output> 3
// 6
def output = last[1; 2; 3]
//output> 1
// 2
// 3
def output = last[(1, 2); (3, "abc")]
//output> 2
// "abc"
def output = last[(1, 2, 3); (4, 5)]
//output> 3
// 5
left_override
left_override[R, S]
R <++ S
The (left) override operator is usually applied to relations of tuples (k..., v)
with a functional
dependency from the initial (key) arguments (k...)
to the last (value) argument v
.
R <++ S
contains all the tuples of R
, plus all the tuples in S
whose key is not in R
. Often, S
specifies default values for keys that are missing in R
.
In the result, a value in R
overrides a value in S
.
There are two equivalent ways to think about R <++ S
:
(1) S
is providing default values for keys that are missing in R
.
(2) The entries in R
are overriding the entries in S
.
Example | Value |
---|---|
2 <++ 3 | 2 |
1.5 <++ 3 | 1.5 |
(1,2) <++ (1,3) | (1,2) |
(3,4) <++ (1,2); (3,5) | (1,2); (3,4) |
(3,"abc") <++ (1,2); (3,5) | (1,2); (3,"abc") |
(1,2); (3,5) <++ (3,4); (6,7) | (1,2); (3,5); (6,7) |
Override can be applied to heterogeneous relations, notably JSON-like relations. The
following examples show <++
operators applied to JSON inputs.
default_value[D, F, c]
. right_override
levenshtein
levenshtein[string1, string2]
Calculate the Levenshtein distance between two strings.
Example:
levenshtein["kitten", "sitting"]
3
like_match
like_match(like_string, string)
Match string with a SQL “LIKE” pattern; case-sensitive.
The %
character is a wildcard, and is not escapable.
Example:
like_match("\%PROMO\%", "this is a PROMOtion")
//output> () // true
like_match(raw"%PROMO%", "this is a PROMOtion")
//output> () // true
lined_csv
lined_csv[R]
Given an already loaded CSV relation R
, lined_csv[R]
is a copy of the relation, but with the
file position field replaced with a line number. Only lines containing data, including
errors, are included in the numbering. Headers and empty lines are not counted. Thus,
line number 1 is the first non-empty, non-header line of the CSV relation.
Example:
def csv = load_csv[config]
def csv_with_lines = lined_csv[csv]
load_binary
load_binary[URI_string]
load_binary[R]
This is the main in-language API for loading files as binary string.
To load a file, either provide the string URI where the data resides,
or a configuration relation R
that describes the data load.
The relation R
, which must be an EDB or an IDB but not a formula,
can configure the data load with the following options:
Required:
:path
: The path to the file, e.g."azure://<account_name>.blob.core.windows.net/container/image.jpeg"
.
Optional:
:integration
: A relation containing storage integration configuration.
Example:
def config[:path] = "azure://<account_name>.blob.core.windows.net/container/file.bin"
def config[:integration, :provider] = "azure"
def config[:integration, :credentials, :azure_sas_token] = "<azure_sas_token>"
def output = load_binary[config]
load_csv
load_csv[URI_string]
load_csv[R]
This is the main in-language API for loading CSV data.
To load a CSV, either provide the string URI where the data resides,
or a configuration relation R
that describes the data load.
In the first case, all columns are imported with type String
.
The relation R
, which must be an EDB or an IDB but not a formula,
can configure the data load with the following options:
Required: Either
:path
: The path to the CSV file, e.g."azure://storage.blob.core.net/container/file.csv"
Or:data
: A CSV formatted string value
Optional:
:schema
: A relation containing schema information.:syntax
: A relation containing syntax configuration.:integration
: A relation containing storage integration configuration.
The resulting relation is of the form (column_name, file_position, value)
.
The file_position
uniquely identifies each row in the CSV.
Examples:
Loading from literal string value:
def config[:data] = """
A,B,C
1,2,3
"""
def my_data = load_csv[config]
Loading a CSV file using a constant path:
def y = load_csv["azure://<account_name>.blob.core.windows.net/container/data.csv"]
def x = y[:A, _]
In the example above, all values for column :A
(“A” in the original file) are stored in x
.
This can also be used to only load specific columns: load_csv[path](:A, xs...)
.
Loading a CSV file using a configuration relation config
:
def config[:path] = "/path/to/file.csv"
def config[:syntax, :delim] = '_'
def config[:syntax, :header] = (1, :A); (2, :B); (3, :C)
def config[:schema, :A] = "int"
def config[:schema, :B] = "string"
def config[:schema, :C] = "decimal(64,2)"
def csv = load_csv[config]
Lastly, load_csv
also supports error handling. If the CSV can’t be read (e.g. if it is
badly formatted), parsing errors are stored in the :load_errors
“column”, which can be
accessed the same way as any other column. It has the format (:load_errors, file_position, error_column, raw_line)
.
Note : Since the arities of regular columns and the error relations differ, use the
splat operator (”…”) to make your program as resilient as possible
(cf. examples above).
load_csv_row_wise
load_csv_row_wise[R]
Load a CSV file into a “row-wise” relation, with the position as the first argument, and the column name second.
Included for backward compatibility, we now recommend using load_csv
instead, which puts the column name first.
load_json
load_json[filename_or_url]
load_json[R]
The relation R
, which currently needs to either be an EDB or an
IDB but no formula, can be used to configure the data load with
the following options:
Required: Either
:path
: The path to the JSON file, e.g."azure://storage.blob.core.net/container/file.json"
Or:data
: A JSON formatted string value
Optional:
:integration
: A relation containing storage integration configuration.
Examples:
Loading literal JSON values:
def data = """{"name": "Anton", "age": 56}"""
def config[:data] = data
def json = load_json[config]
Loading a JSON file using a constant path:
def y = load_json["test.json"]
Loading a JSON file using a configuration relation:
def config[:path] = "/path/to/file.json"
def json = load_json[config]
Loading a JSON file from behind a private Azure container using a SAS token:
def config[:path] = "azure://<account_name>.blob.core.windows.net/container/file.json"
def config[:integration, :provider] = "azure"
def config[:integration, :credentials, :azure_sas_token] = "<azure_sas_token>"
def json = load_json[config]
load_json_general
load_json_general[filename_or_url]
load_json_general[R]
Load a JSON file using the JSON General representation. This representation does not use the
data in the JSON document to make any schema (unlike load_json
). This means that arbitrary
JSON files can be loaded without scaling issues, even if the file has millions of distinct
property names.
The result consists of the following relations:
(:root, Entity)
: for the root of the JSON document(:child, Entity, Entity, Entity)
: for JSON objects and arrays, where the 1st argument is the parent, the 2nd argument is the name (for object) or index (for array) (the actual string name or index is in:value
), and the 3rd is the child node.(:name, Entity)
: for named JSON entities.(:value, Entity, <value>)
: for leaf values, like strings, integers etc, where<value>
is one the JSON data types (String
,Int64
,Float64
,Bool
,Missing
).(:array, Entity)
: for JSON arrays (necessary to distinguish empty object vs array)(:object, Entity)
: for JSON objects
Identical sub-trees in the document use the same entity, so the result is a directed-acyclic graph (DAG). It is important to consider the shared sub-trees when analyzing the JSON document.
Examples:
A single value:
def config:data = """
"abc"
"""
def json = load_json_general[config]
with json use value, child, root
ic { root.value ≡ "abc" }
A JSON array:
def config:data = """
[ "abc", "def", "ghi" ]
"""
def json = load_json_general[config]
with json use value, child, root
def index[v, x] = value(x, v) and Int(v)
ic { count[root.child] ≡ 3 }
ic { root.child[_].value ≡ ("abc"; "def"; "ghi") }
ic { root.child[index[1]].value ≡ "abc" }
ic { root.child[index[2]].value ≡ "def" }
ic { root.child[index[3]].value ≡ "ghi" }
A JSON object:
def config:data = """
{ "a": 1, "b": 2, "c": 3 }
"""
def json = load_json_general[config]
with json use value, child, root
def name[s, x] = value(x, s) and String(s)
ic { count[root.child] ≡ 3 }
ic { root.child[name["a"]].value ≡ 1}
ic { root.child[name["b"]].value ≡ 2}
ic { root.child[name["c"]].value ≡ 3}
load_jsonlines
load_jsonlines[filename_or_url]
load_jsonlines[R]
Parse and load a JSONLines file. JSONLines is a file format that considers each line of the text file as a separate JSON object.
Example:
def data = """{"name": "Anton", "age":56}\n{"name": "Alex", "age":44}"""
def config[:data] = data
def output = load_jsonlines[config]
ic {equal(output[1,:name], "Anton")}
ic {equal(output[1,:age], 56)}
ic {equal(output[2,:name], "Alex")}
ic {equal(output[2,:age], 44)}
load_jsonlines_general
load_jsonlines_general[filename_or_url]
load_jsonlines_general[R]
Load a JSON Lines file using the JSON General representation. See load_json_general
for a
description of the JSON General representation.
The JSON Lines file is represented identical to a JSON array. The root
node is an array,
and every line is a child of this array.
As opposed to load_jsonlines
, the line number is not the first argument in the result.
This makes it possible to share common sub-trees and values across documents.
log
log[x, y]
Logarithm of y with given base x.
Defined for non-negative x
and y
.
Example:
log[2, 8] = 3.0
log_card_est
log_card_est[R]
The log base 2 of the cardinality estimate of a given relational abstraction R
.
log10
log10[x]
Base 10 logarithm.
Defined for non-negative x
.
log10[1000] = 3.0
lowercase
lowercase[string_or_char]
A string where all the characters are converted to lowercase. If a character is already lowercase or has no lowercase version, it remains unchanged.
Example:
def output = lowercase["aB1c"]
//output> "ab1c"
def output = lowercase['Â']
//output> 'â'
lowercase
does not take a locale option and does not handle local-specific case mapping
rules.
lt
lt(x, y)
x < y
lt_eq
lt_eq(x, y)
x ≤ y
x <= y
mae
mae[YHAT, Y]
Mean absolute error (MAE, L1)
max
max[R]
max(R, m)
The maximum value (m
) of the last element of all tuples in a relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The maximum of the last element of the tuples in R . |
Explanation
max
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R
contains key-value pairs, max[R]
finds the maximum value for R
.
Note that max
groups the tuples by the data type of the final numeric element.
Typically, max
is used when the last elements of each tuple have the same type.
max
can be used with strings.
In this case, max
is determined according to lexicographical order.
For details on lexicographical ordering — particularly across data types — see enumerate
.
If R
is empty, max[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Find the maximum value of a relation’s last element:
def output = max[{(2, 3); (1, 6)}]
//output> 6
Find the maximum value for each data type:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7)}
def output = max[R]
//output> 2/5
// 6.7
Find the maximum value of a relation’s last element using full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", rational[64, 3, 5])}
def output(x) = max(R, x)
//output> 3/5
Find the maximum value for relation with tuples of various lengths (the last element in each tuple is used to find the maximum value).
def R = { (10); (2, 30); (3, 50, 2)
}
def output = max[R]
//output> 30
See Also
maximum
, min
, argmax
, sum
, product
, and average
.
Max
Max[R]
Please use max[R]. Deprecates in near future
max_k
max_k[k, R]
max_k(k, R, mk)
The k
largest values in the set of all last elements
of tuples in a relation R
, excluding duplicates.
Parameters
Parameter | Type | Description |
---|---|---|
k | SignedInt[64] | Number of distinct largest values to be calculated for R . |
R | Relation | Source relation. Must be grounded. |
mk | Number | The maximum k of the last element of the tuples in R . |
Explanation
max_k
identifies the k
largest values in the last element of any tuple in R, excluding duplicates.
For example, if the last column contains 1, 2, 2, 3
and k = 2
, then max_k[2, R] = {2; 3}
.
max_k
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that max_k
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, max_k
is used when the last elements of each tuple have the same type.
If R
contains fewer then k
distinct values, then max_k
will have fewer than k
elements as well.
The maximum supported value for k
is 10000
.
If R
is empty, max_k[K, R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Determine the two largest distinct values for a relation:
def R = {(2, 3); (1, 6); (3, 5); (1, 1); (4, 1); (2, 6)}
def output = max_k[2, R]
//output> 5, 6
Find the two largest distinct values in a relation using the full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(mk) = max_k(2, R, mk)
//output> 8.6
// 9.7
See Also
min_k
, argmin
, maximum
, min
, argmax
, sum
, product
, and average
.
maximum
maximum[x, y]
Maximum of two arguments. The arguments should have the same type.
Examples:
maximum[3, 4] = 4
maximum[3.0, 4.0] = 4.0
See Also
max
, minimum
, and min
.
mean
mean[R]
mean(R, m)
The arithmetic mean (m
) of the last elements of each tuple in the relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The arithmetic mean of R . |
Explanation
mean
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Note that mean
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, mean
is used when the last elements of each tuple have the same numeric type.
If the relation R
contains tuples with a non-numeric last element, the result may not be accurate.
If R
is empty, mean[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Calculate the arithmetic mean of the last elements of each tuple in a relation:
def output = mean[{(2, 3); (1, 6)}]
//output> 4.5
Calculate the arithmetic mean of the values in a relation using the full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", rational[64, 3, 5])}
def output(m) = mean(R, m)
//output> 8/21
Calculate the arithmetic mean of the values in a relation with tuples of various lengths:
def R = {(10); (2, 30); (3, 50, 2)}
def output = mean[R]
//output> 14.0
Calculate the arithmetic mean of salary by department:
def salary = {("John", 126) ; ("Mary", 90); ("Paul", 117); ("Peter", 115); ("Tran", 145) }
def member = {("A", "John"); ("B", "Mary"); ("A", "Paul"); ("C" , "Peter"); ("C", "Tran") }
def department = {"A"; "B"; "C" }
def output = d in department: mean[salary[p] for p in member[d]]
//output> "A", 121.5
// "B", 90.0
// "C", 130.0
See Also
geometric_mean
, harmonic_mean
, weighted_mean
, mode
, max
, min
, sum
, and product
.
mean_normalization
mean_normalization[R]
Mean normalization:
median
median[R]
median(R, m)
The median value of the last elements of each tuple in the relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The median of R . |
Explanation
Computes the median, or “middle” value of the set of last elements of each tuple in R
.
If there are two “middle values”, then the mean of the two values is used.
For best results, tuples in R
should all have the same length,
and the last element of each tuple should be a Number
.
Note that, unlike other aggregations, median
does not group tuples by data type.
Examples
Determine median of a relation:
def R = {("A", 7); ("B", 8); ("C", 9.7); ("D", 7.5)}
def output = median[R]
//output> 8.35
Determine median of a relation using full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7); ("e", 1.2)}
def output(m) = median(R, m)
//output> 6.7
Determine median salary across departments:
def salary = {("John", 126) ; ("Mary", 90); ("Paul", 117); ("Peter", 115); ("Tran", 145) }
def member = {("A", "John"); ("B", "Mary"); ("A", "Paul"); ("C" , "Peter"); ("C", "Tran") }
def department = {"A"; "B"; "C" }
def output = d in department: median[salary[p] for p in member[d]]
//output> "A", 121.5
// "B", 90.0
// "C", 130.0
metaphone
metaphone[string_value, length]
metaphone
returns an encoding of the phonetic representation of string_value
.
metaphone
lets you compare words and sentences based on how they sound in English. The
metaphone is considered as an improvement of the soundex
algorithm, and does a better job
at matching words and names which sound
similar.
string_value
could be any arbitrary long string.
length
is the length of the encoding that is used for comparison purpose. A length of 4
is commonly used.
Examples:
def output = metaphone["Smith", 4]
//output> sm0
def output = metaphone["Smythe", 4]
//output> sm0
def output = metaphone["Christina", 4]
//output> xrst
def output = metaphone["Cristine", 4]
//output> krst
def output = metaphone["I like Music", 4]
//output> ilkm
def output = metaphone["i loak Museek", 4]
//output> ilkm
def output = metaphone["RelationalAI", 4]
//output> rlxn
def output = metaphone["rellationalleAI", 4]
//output> rlxn
Here a simple illustration. Consider the following:
def my_favorite_bands = { "Metallica"; "Iron Maiden"; "Wolfheart"; "Insomium" }
def do_I_like = "Mee ta li ka"
def output = {y in my_favorite_bands : metaphone(do_I_like, 4, z), metaphone[y, 4] = z from z}
the script above returns "Metallica"
since since "Mee ta li ka"
and "Metallica"
have
the same metaphone code.
Microsecond
Microsecond[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Microsecond constructor, ^Microsecond
, instead.
Create a period of n
microseconds.
Millisecond
Millisecond[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Millisecond constructor, ^Millisecond
, instead.
Create a period of n
milliseconds.
min
min[R]
min(R, m)
The minimum value (m
) of the last element of all tuples in a relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
m | Number | The minimum of the last element of the tuples in R . |
Explanation
min
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R
contains key-value pairs, min[R]
finds the minimum value for R
.
Note that min
groups the tuples by the data type of the final numeric element.
Typically, min
is used when the last elements of each tuple have the same type.
min
can be used with strings.
In this case, min
is determined according to lexicographical order.
For details on lexicographical ordering, see enumerate
.
If R
is empty, min[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Find the minimum value of a relation’s last element:
def output = min[{(2, 3); (1, 6)}]
//output> 3
Find the minimum value for each data type:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7) }
def output = min[R]
//output> 4.5
// 1/7
Find the minimum value of a relation’s last element using full expression:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", rational[64, 3, 5])
}
def output(x) = min(R, x)
//output> 1/7
Find the minimum value for a relation with tuples of various lengths (the last element in each tuple is used to find the minimum value):
def R = { (10); (2, 30); (3, 50, 2)}
def output = min[R]
//output> 2
See Also
minimum
, max
, argmax
, sum
, product
, and average
.
Min
Min[R]
Please use min[R]. Deprecates in near future
min_k
min_k[k, R]
min_k(k, R, m)
Find the k
smallest values in the set of all last elements
of tuples in a relation R
, excluding duplicates.
Parameters
Parameter | Type | Description |
---|---|---|
k | SignedInt[64] | The number of distinct minimum values to be calculated for R . |
R | Relation | Source relation. Must be grounded. |
mk | Number | The minimum k of the last element of the tuples in R . |
Explanation
min_k
identifies the k
smallest values in the last element of any tuple in R, excluding duplicates.
For example, if the last column contains 1, 2, 2, 3
and k = 2
, then min_k[2, R] = {1; 2}
.
min_k
aggregates over all tuples in R
.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that min_k
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, min_k
is used when the last elements of each tuple have the same type.
If R
contains fewer then k
distinct values, then min_k
will have fewer than k
elements as well.
The maximum supported value for K
is 10000
.
If R
is empty, min_k[k, R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Determine the two smallest distinct values for in relation:
def R = {(2, 3); (1, 6); (3, 5); (1, 1); (4, 1); (2, 6)}
def output = min_k[2, R]
//output> 1, 3
Determine the two smallest distinct values in a relation using the full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(mk) = min_k(2, R, mk)
//output> 7.5
// 8.6
See Also
max_k
, argmin
, minimum
, min
, argmax
, sum
, product
, and average
.
min_max_normalization
min_max_normalization[R]
Min-Max normalization: .
Also known as min-max scaling or rescaling.
minimum
minimum[x, y]
Minimum of two arguments. The arguments should have the same type.
Examples:
minimum[3, 4] = 3
minimum[3.0, 4.0] = 3.0
Minute
Minute[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Minute constructor, ^Minute
, instead.
Create a period of n
minutes.
missing
missing
Singleton missing value.
Examples:
missing[] = missing
equal( (x : missing(x)) , {missing} )
Missing
Missing(x)
Tests whether x
has the data type Missing
.
The only data value that is of type Missing
is missing
.
Used for imported data that contain explicit nulls (such as JSON data).
Missing
(with a capital) refers to the data type, while missing
refers to the data.
Examples:
Query that returns all relations without missing
as the second argument:
def R = { (1, 2); (3, missing) }
def output(x, y) = R(x, y) and not Missing(y)
//output> (1, 2)
mode
mode[R]
mode(R, md)
Find the most common value in the last element of all tuples in a relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Any | Source relation. Must be grounded. |
md | Any | The mode of R . |
Explanation
If there are multiple mode values, then mode
chooses the first one according to lexicographical order.
For details on lexicographical ordering — particularly across data types — see enumerate
.
mode
aggregates over all tuples in R
whose last element is numeric.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that mode
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, mode
is used when the last elements of each tuple have the same type.
If R
is empty, mode[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Find the most common value in a relation:
def R = {(5, 8); (8, 6); (13, 12); (9, 6); (2, 9); (7, 6)}
def output = mode[R]
//output> 6
Find most common value in relation using full expression:
```rel
def R = {("A", "A"); ("B", "A"); ("C", "C"); ("D", "A"); ("E", "B");}
def output(md) = mode(R, md)
//output> "A"
Find most common value in a relation with tuples of various lengths:
def R = {("A", 6, "A"); ("B", 7, "C"); ("C", "C"); ("D", "A"); ("E", "A")}
def output = mode[R]
//output> "A"
model_is_function (IC)
ic model_is_function
An integrity constraint ensuring that rel:catalog:model
has a functional dependency
from the name to the actual value.
modulo
modulo[x, y]
modulo(x, y, m)
Remainder after floored division.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Dividend. Must be grounded. |
y | Number | Divisor. Must be grounded. |
m | Number | Remainder. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | m |
---|---|---|
Number | Same as x | Same as x |
SignedInt , UnsignedInt | SignedInt , UnsignedInt | Type of y . Bit size is the larger of the bit sizes of x and y . |
SignedInt[64] , Floating[64] | Number | Type of x . |
Number | SignedInt[64] , Floating[64] | Type of y . |
Floating | SignedInt[64] | Type of x . |
SignedInt[64] | Floating | Type of y . |
Rational | SignedInt[64] | Rational[n] where n is the greater of the number of bits in x and y . |
SignedInt[64] | Rational | Rational[n] where n is the greater of the number of bits in x and y . |
The remainder in the division algorithm for dividing x
by y
using floored division for the quotient.
That is, modulo[x, y]
is equivalent to x - (y * floor_divide[x, y])
.
The sign of the remainder is the same as the divisor y
.
If y
is positive, the range is from 0 to y, inclusive.
If y
is negative, range is from y to 0, inclusive.
modulo[x, y]
is defined when either the types of x
and y
are the same, or
either operand is of type SignedInt[64]
or Floating[64]
.
modulo[x, y]
is false
when y
= 0 for integer arguments.
Examples
Compute remainder for two integers:
def output = modulo[8, 3]
//output> 2
Compute remainder for two integers using full expression:
def output(m) = modulo(8, -3, m)
//output> -1
Compute remainder for rational and integer:
def output = modulo[rational[64, 8, 3], 2]
//output> 2/3
Confirm that modulo
is empty when y
= 0
:
def output = empty(modulo[3, 0])
//output> () // true
Month
Month[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Month constructor, ^Month
, instead.
Create a period of n
months.
mse
mse[YHAT, Y]
Mean squared error (MSE, L2)
multiply
multiply[x, y]
multiply(x, y, p)
x * y
Multiplication of two numbers.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | First factor. Must be grounded. |
y | Number | Second factor. Must be grounded. |
p | Number | Product x * y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | p |
---|---|---|
Number | Same as x | Same as x |
Rational , FixedDecimal | SignedInt , UnsignedInt | Same as x |
SignedInt , UnsignedInt | Rational , FixedDecimal | Same as y |
SignedInt[64] | SignedInt[128] | SignedInt[128] |
SignedInt[128] | SignedInt[64] | SignedInt[128] |
Number | Floating[64] | Floating[64] |
Floating[64] | Number | Floating[64] |
Explanation
In contrast to add
and subtract
, x
and y
need to be grounded and specified by the user.
Specifying only x
and p
or only y
and p
is not sufficient as the system can’t compute the inverse.
Examples
Multiply two integers using *
:
def output = 24 * 2
//output> 48
Multiply one float by another using multiply
:
def output = multiply[8.4, 2.1]
//output> 17.64
Multiply a rational by an integer using full expression:
def output(x) = multiply(rational[64, 8, 3], 2, x)
//output> 16/3
See Also
add
, subtract
, and divide
.
murmurhash3f
murmurhash3f[v]
Hash v
according to the MurmurHash3f algorithm with the default seed 0
,
as a UInt128.
Equivalent to murmurhash3f_with_seed[0, v]
.
murmurhash3f_with_seed
murmurhash3f_with_seed[seed in (Int64 ∪ UInt128), key]
Hash key
with seed
via the MurmurHash3F algorithm, and yield the result as a UInt128
.
The key
may be any singleton value supported in Rel, (e.g. [U]Int{8,16,32,64,128}
,
Float{16,32,64}
, Char
, String
, RelName
, FilePos
, Missing
, …).
The seed
must be a value in (Int64 ∪ UInt128)
.
Note that the standard specification for MurmurHash3F does not include 128-bit seeds, so
the result of hashing with a 128-bit seed will be different than a hash with the same value
stored in a smaller integer type (i.e. hashing with the seeds uint64[1]
and uint128[1]
will result in different hashes).
This function is an implementation (in Julia) of the reference implementation of MurmurHash3F, i.e. MurmurHash3_x64_128. The original can be retrieved via:
https://github.com/aappleby/smhasher/blob/ (opens in a new tab) 61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash3.cpp
The reference implementation was written by Austin Appleby and made public domain.
Note that this implementation departs from the standard, in order to provide different
hashes for byte-identical values of different types. While this implementation’s internals
should produce byte-identical results to the reference implementation, the primary
entrypoint here, (murmurhash3f[seed, key]
) typically will not: To distinguish
byte-identical values of different types, this function mixes type information into seeds
prior to hashing.
Also note that the reference implementation supports only UInt32
seed
s; for such
seed
s, this implementation’s internals should provide byte-identical results.
But this implementation accepts seed
s up to and including 128-bit integer types.
(For UInt32
seed
s, the reference implementation initializes h1
/h2
,
the two UInt64
s in which it accumulates/mixes the digest, with copies of seed
.
This implementation does the same for UInt32
seed
s, and also for all other
seed
types that are less than or equal to 64 bits. For 128-bit seed
s, this implementation
initializes h1
with the seed
’s low bits and h2
with the seed
’s high bits.)
Examples
// Without a seed
murmurhash3f["cat"] = 0x37322aa78b4b4ef4816da65505e8efaa
// With a seed
murmurhash3f_with_seed[8675309, "cat"] = 0x9fd1d18093ba94b6f454b48e58011643
murmurhash3f_with_seed[8675309, :bunny] = 0x56f800aed5ff3b7300ace61c691e7568
// byte-identical values of different types hash differently
murmurhash3f[0x01] = 0x6ed3439777f613f7df39df0849d45e09
murmurhash3f[1] = 0x9116cd3f0a651c49f1674100935b29bf
Nanosecond
Nanosecond[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Nanosecond constructor, ^Nanosecond
, instead.
Create a period of n
nanoseconds.
nanoseconds_to_datetime
nanoseconds_to_datetime[ns]
Convert nanoseconds (from the unix epoch) to datetime.
Analogous to datetime.datetime.utcfromtimestamp(seconds) in python.
Example:
nanoseconds_to_datetime[24 * 60 * 60 * 10^9]
is 1970-01-02T00:00:00
(one day after unix_epoch
).
natural_exp
natural_exp[x]
Exponentiation with the base of the natural log, e.
natural_log
natural_log[x]
Natural logarithm (ln) (base e).
Defined for non-negative x
.
neq
neq(x, y)
x ≠ y
x != y
Examples:
1 != 2
istrue
1 != 1.0
istrue
1 != "a"
istrue
num_bytes
num_bytes[str]
The number of bytes in a string value.
If a string contains Unicode characters, it’s possible that some characters take up more
than one byte, so num_bytes[str]
may be larger than num_chars[str]
.
Example:
num_bytes["abcd"] = 4
num_bytes["中文例子"] = 12
num_chars
num_chars[str]
The number of (Unicode) characters in a string, i.e. the length of the string.
A character is also known as a “Code Point” in the Unicode specification.
Example:
num_chars["abcd"] = 4
num_chars["中文例子"] = 4
Number
Number(x)
Holds if x
is a number (for example, Int
,Float
, or their fixed-width versions).
See also: Int
and Float
in intrinsics.rel
.
Example:
Integrity constraint that tests whether x
is of type Number
(throws if x
is not of type Number
):
def R = {1; 1.5; uint[8,3]; 4; float[32, 1.321]}
ic number_ic { subset(R, Number) }
numerator
numerator[x]
Numerator of a rational-like number.
Examples:
numerator[rational[64, 1, 3]] = 1
numerator[rational[64, 1, 100]] = 1
numerator[rational[64, 1, 100] + rational[64, 1, 3]] = 103
numerator[parse_decimal[#64, #2, "3.14"]] = 314
numerator[parse_decimal[#64, #5, "3.14159"]] = 314159
numerator[5] = 5
pack
pack(x₁, ..., xₙ, v)
Creates a packed structure v
storing the values (x₁, ..., xₙ)
in sequence.
pack
cannot be used with point-free syntax.
Direct usage of pack
should be avoided, as it serves primarily as a low-level
interface for value types.
parse_date
parse_date[d, format]
Parse Date.
This function is only defined for a valid combination of date string
d
and format string format
, and invalid arguments will evaluate
to false
(the empty relation, {}
).
Examples:
def output = parse_date["2018-06-12", "Y-m-d"]
//output> 2018-06-12
For details on the format parameter, see the Julia documentation for Dates.DateFormat
(opens in a new tab).
parse_datetime
parse_datetime[date_string, format]
parse_datetime(date_string, format, date)
Parses datetime information (date_string
) given a date-time format (format
).
Parameters
Parameter | Type | Description |
---|---|---|
date_string | String | A string with date and time information formatted according to format . Must be grounded. |
format | String | A valid date-time format. Must be grounded. |
date | DateTime | A DateTime object containing the parsed date and time information. |
Explanation
The form parse_datetime[date_string, format]
can be used to create the Datetime
value (date
).
The form parse_datetime(date_string, format, date)
can be used to check that date
maps to date_string
given the date-time format format
.
parse_datetime
evaluates to false
if date_string
or format
is invalid.
Parameters for DateTime Format Strings
Parameter | Example | Description |
---|---|---|
y | 2024 | Matches year. |
m | 1, 01 | Matches 1 or 2-digit months. |
d | 1, 01 | Matches 1 or 2-digit days. |
H | 00 | Matches hours (24-hour clock). |
I | 00 | For outputting hours with 12-hour clock. |
M | 00 | Matches minutes. |
S | 00 | Matches seconds. |
s | .500 | Matches milliseconds. |
e | Mon, Tues | Matches abbreviated days of the week. |
E | Monday | Matches full name days of the week. |
p | AM | Matches AM/PM (case-insensitive). |
yyyymmdd | 19960101 | Matches fixed-width year, month, and day. |
z | +04:00, +0400, UTC+4 | Matches a numeric UTC offset. |
Z | Asia/Dubai, UTC | Matches names of time zones from the TZ database. |
u | Jan | Matches abbreviated months according to the _locale_keyword. |
U | January | Matches full month names according to the _locale_keyword. |
Examples
Parse a string with date and time information:
def output = parse_datetime["2022-03-01 02:21:09", "y-m-d H:M:S"]
//output> 2022-03-01T02:21:09.000Z
Parse a string with date and time (incl. milliseconds) information:
def output(x) = parse_datetime("2024-01-15 00:00:00.003","y-m-d H:M:S.sss", x)
//output> 2024-01-15T00:00:00.003Z
Parse a string with timezone information:
def output = parse_datetime["2018-03-11 01:00 America/New_York", "Y-m-d H:M Z"]
//output> 2018-03-11T06:00:00.000Z
where the time-zone name must match the names in the time-zone (tz) database.
See Also
string
, parse_int
, parse_float
, and parse_date
.
parse_decimal
parse_decimal[bits, precision, string]
Parse a string representation of a fixed-point decimal number to a decimal[bits, precision]
The implementation does not consider a locale. The decimal separator is always .
and
the thousands separator is always ,
. The thousands separator is optional.
If the string has more digits after the decimal point than supported by the precision
parameter, then the number is rounded to the nearest number.
This function is only defined for valid arguments. For invalid arguments it will be false
(the empty relation, {}
).
Examples:
parse_decimal[#64, #2, "3.14"]
FixedDecimal{Int64,2}(3.14)
parse_decimal[#64, #1, "4.27"]
FixedDecimal{Int64,1}(4.3)
parse_decimal[#64, #2, ""]
FixedDecimal{Int64,2}(0.00)
parse_decimal[#64, #2, "1,234.567"]
FixedDecimal{Int64,2}(1234.57)
parse_decimal[#64, #2, "invalid"]
{}
parse_float
parse_float[string]
Parse a string representation of a float to a Floating[64]
Note that this currently does not consider a locale (decimal separator is always .
)
Is false
(empty) if the string fails to parse as an integer.
Examples:
parse_float["3.14"] = 3.14
parse_float["3"] = 3.0
empty(parse_int["hello"])
parse_int
parse_int[string]
Parse a string representation of an integer to a SignedInt[64]
Is false
(empty) if the string fails to parse as an integer.
Example:
parse_int["123"] = 123
empty(parse_int["hello"])
parse_int128
parse_int128[string]
Parse a string representation of an integer to a SignedInt[128]
Is false
(empty) if the string fails to parse as an integer.
Example:
parse_int128["9223372036854775808"] = 9223372036854775808
empty(parse_int["hello"])
parse_json
parse_json[json_string_value]
Parses a JSON value directly from a string.
Example:
def json = parse_json["""{"name": "Anton", "age": 56}"""]
parse_json_general
parse_json_general[json_string_value]
Parse a JSON document directly from a string using the JSON General representation. See
load_json_general
for a description of the JSON General representation.
Example:
def json = parse_json_general["123"]
with json use value, child, root
ic { root.value ≡ 123 }
parse_jsonlines
parse_jsonlines[jsonlines_string_value]
Parse a JSON Lines file directly from a string.
The result of parse_jsonlines
is an Int64
line number followed by the Rel representation
of the JSON document as in load_json
.
Example:
def output = parse_jsonlines["""
{"name": "Luca", "age": 44}
{"name": "Kai", "age": 23}
{"name": "Harper", "age": 21}
"""]
ic { equal(count[output], 6) }
ic { equal(output[1, :name], "Luca") }
ic { equal(output[2, :name], "Kai") }
ic { equal(output[3, :name], "Harper") }
parse_jsonlines_general
parse_jsonlines_general[json_string_value]
Parse a JSON Lines file directly from a string using the JSON General representaiton. See
load_json_general
for a description of the JSON General representation.
The result of parse_jsonlines_general
has the same representation as
load_jsonlines_general
.
parse_uuid
parse_uuid[str]
Parse a UUID string (in the standard 8-4-4-4-12 format) to a UInt128 value.
Example:
parse_uuid["22b4a8a1-e548-4eeb-9270-60426d66a48e"] = 0x22b4a8a1e5484eeb927060426d66a48e
Pattern
Pattern(x)
Holds if x
is of type Pattern
, which is a compiled regular expression (see regex_compile
).
Example:
Integrity constraint that tests whether x
is of type Pattern
:
def R = regex_compile["a.*b"]
ic pattern_ic(x in R) {
Pattern(x)
}
pattern_match
pattern_match(pattern, string)
Match string with a pattern (pre-compiled regular expression)
Example:
def p = regex_compile["^.*@.*$"]
def output = pattern_match(p, "foo@example.com")
//output> () // true
percentile
percentile[R, p]
Select the element of R
corresponding to the p-th percentile, computed with linear
interpolation.
If the p-th percentile does not correspond to a single element, then
percentile_continuous
computes a weighted average of the two values surrounding the
p-th percentile.
There are a number of different approaches for computing linearly interpolated percentiles.
Here, the rank of the percentile is computed by x = p(N - 1) + 1
, which corresponds to
the C = 1
variant in https://en.wikipedia.org/wiki/Percentile (opens in a new tab). This is also the approach
used in Julia’s libraries and NumPy.
Note that percentile
is not defined for p <= 0
or p > 100
.
Example:
def output = percentile[{(1, 12); (2, 24); (3, 16)}, 60]
//output> 17.6
percentile_nearest
percentile_nearest[R, p]
Select the element of R
corresponding to the p-th percentile.
The p-th percentile is the smallest value in the list such that no more than p
percent of
the data is strictly less than the value and at least p
percent of the data is less than
or equal to that value (nearest-rank method in https://en.wikipedia.org/wiki/Percentile (opens in a new tab)).
This function computes the p-th percentile based on ranking the last argument of R
.
Note that percentile_nearest
is not defined for p <= 0
or p > 100
.
Example, here 33% of the values are strictly less than 16, and 66% of the values are less than or equal to 16, so the 60-th percentile is 16:
def output = percentile_nearest[{(1, 12); (2, 24); (3, 16)}, 60]
//output> 16
period_add
period_add[period1, period2]
Add two periods. For now, they need to be of the same type.
def output = period_add[Minute[3], Minute[4]]
//output> 7
period_day_to_int
period_day_to_int[day]
Conversion from period Day
to int
.
In other words, returns the value of Day
data type as an integer.
Example:
def num_of_days = period_day_to_int[^Day[3]]
ic { equal(num_of_days, 3) }
period_max
period_max[period1, period2]
Maximum of two periods. The result is expressed as a nanosecond period.
Example:
def output = period_max[Minute[3], Minute[4]] = Minute[4]
//output> () // true
period_min
period_min[period1, period2]
Minimum of two periods. The result is expressed as a nanosecond period.
Example:
def output = period_min[Minute[3], Minute[4]] = Minute[3]
//output> () // true
pi_float64
pi_float64
The constant pi.
Example:
cos[pi_float64] = -1.0
pivot
pivot[T]
pivot(T, tuple_position, value)
Pivot a relation T
.
The pivoted relation has the form (tuple_position, value)
, where tuple_position
is the tuple position of each element within T
and value
is its corresponding value.
pivot
in Rel performs a transformation that is known elsewhere as unpivot.
Parameters
Parameter | Type | Description |
---|---|---|
T | Relation | Source relation. Must be grounded. |
tuple_position | Int | The position of the element value within T . |
value | Any | An individual element within T . |
Explanation
If a relation is seen as a table, then pivot
(known elsewhere as unpivot) rotates the table, such that columns in the relations become rows.
Each row in the rotated relation is prefixed with its column position.
More precisely, pivot
maps a relation T
to a binary relation that contains all elements in T
which are keyed by their tuple position(s) in T
.
That is, pivot[(t1, ..., tn)]
maps to the relations {(1, t1);... (n, tn)}
.
If a relation has three elements, for example, pivot
keys first elements with 1
, second elements with 2
,and third elements with 3
.
pivot
will work for relations with many tuples, even if the tuples do not have the same arity.
That is, the table need not be “rectangular” for pivot
to work.
pivot[true]
and pivot[false]
are both false
(the empty relation).
Examples
Pivot an arity-4 relation using shorthand:
def output = pivot[(5, 60, 7, 2.0)]
//output> (1, 5)
// (2, 60)
// (3, 7)
// (4, 2.0)
Pivot mixed-arity relation using full expression:
def employees = {
("jane", 42, "engineering");
("tran", 24)
}
def output = x... : pivot(employees, x...)
//output> 1, jane
// 1, tran
// 2, 24
// 2, 42
// 3, engineering
If relation R
is unary, pivot[R]
will turn it into a binary relation where the first element of each tuple is 1
.
def output = pivot[{5; 6}]
//output> 1, 5
// 1, 6
pop_standard_deviation
pop_standard_deviation[R]
pop_stddev[R]
Population standard deviation
pop_variance
pop_variance[R]
Population variance
pop_zscore_normalization
pop_zscore_normalization[R]
Z-score normalization (population) of (the last argument of) the relation R
.
power
power[b, n]
power(b, n, e)
b ^ n
Exponentiation of b
to the power of n
.
Parameters
Parameter | Type | Description |
---|---|---|
b | Number | Base. Must be grounded. |
n | Number | Exponent. Must be grounded. |
e | Number | Exponentiation b ^ n . |
Not all numeric values can be mixed with each other. The following combinations are valid:
b | n | e |
---|---|---|
Number | SignedInt[64] | Same as b |
SignedInt[64] , Floating[64] | Floating[64] | Floating[64] |
BigInteger | BigInteger | BigInteger |
When both b
and n
are integer types, n
cannot be negative.
When b
is negative, n
must have an integer value like 2
, -3
, or 4.0
.
The data type of n
doesn’t need to be integer. Floating point numbers are also allowed as long as their value represents an integer number.
Examples
Using only positive integers ensures the result is an integer too:
def output = 2 ^ 8, power[5, 2]
// output> 256, 25
One can also mix integer and floating-point numbers:
def output = power(3.0, 2, 9.0)
//output> () // true
However, the exponent needs to have an integer value when the base is negative:
def output = (-10)^-4.0
// output> 0.0001
prefix_join
prefix_join[R, S]
R <: S
The prefix join (or restriction) of S
to R
consists of the tuples (x..., y...)
in S
where the prefix (x...)
is in R
.
That is, R <: S
contains the tuples in S
that have a prefix in R
.
Example | Normalized |
---|---|
n <: edge | x, y: edge(x, y) and x = n |
female <: parent | x, y: female(x) and parent(x, y) |
t <: players | x, p: players(x, p) and t = x |
t.players <: age | p, v: players(t, p) and age(p, v) |
intern <: salary | p, v: intern(p) and salary(p, v) |
The restriction operator can also be used to select subsets of JSON-like relations:
-
:a <: json
wherejson
is{"a": {"b": 1, "c": 2}, "d": 3}
has value{"a": {"b": 1, "c": 2}}
-
(:[], _, :a) <: json
wherejson
is[ {"a": 1, "b": 2}, {"a": 3, "b": 4} ]
has value[ {"a": 1}, {"a": 3} ]
.
product
product[R]
product(R, p)
The product (p
) of the last element of all tuples in a relation R
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A relation whose tuples contain numeric data types. Must be grounded. |
p | Number | The product of the last element of the tuples in R . |
Explanation
product
aggregates over all tuples in R
whose last element is numeric.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R
contains key-value pairs, product[R]
finds the product of values for R
.
Note that product
groups the tuples by the data type of the final numeric element.
Typically, product
is used when the last elements of each tuple have the same type.
If R
is empty, product[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Find the product of a relation’s last element:
def output = product[{(1, 4); (2, 5)}]
//output> 20
Calculate the product for each data type:
def R = {("a", rational[64, 2, 5]); ("b", rational[64, 1, 7]); ("c", 4.5); ("d", 6.7)}
def output = product[R]
//output> 30.150000000000002
// 2/35
Calculate the product of a relation’s last element using full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7); ("D", 7.5)}
def output(p) = product(R, p)
//output> 4692.375
Calculate the product of relations whose last elements are rationals:
def R = {("A", rational[64, 8, 3]); ("B", rational[64, 9, 7]); ("C", rational[64, 11, 4]); ("D", rational[64, 8, 3])}
def output = product[R]
//output> 176/7
See Also
multiply
, min
, argmax
, sum
, and average
.
proper_subset
proper_subset(R, S)
R ⊂ S
R
is a proper subset of S
if subset(R, S)
and R
and S
are not equal. This means
there has to be at least one fact in S
that is not in R
.
proper_superset
proper_superset(R, S)
R ⊃ S
Inverse of proper_subset. See proper_subset.
rad2deg
rad2deg[r]
rad2deg(r, d)
Convert radians to degrees.
Parameters
Parameter | Type | Description |
---|---|---|
r | Float , Int | d in radians. Must be grounded. |
d | Float | r in degrees. |
Examples
Convert -π/2 to degrees:
def output = rad2deg[-pi_float64/2]
//output> -90.0
Convert π to degrees using full expression:
def output(d) = rad2deg(pi_float64, d)
//output> 180.0
random_mersenne_twister
random_mersenne_twister[seed, R]
Generates a pseudorandom number for every tuple in R
using the Mersenne Twister PRNG.
random_mersenne_twister
takes a relation R(xs...)
and produces a relation with the
tuples (xs..., r)
where r
is a pseudorandom number generated by using the Mersenne
Twister algorithm with the given seed
. The value r
is a Float64 in the range of [0, 1].
The seed is required to be a number convertible to an unsigned 128-bit integer (UInt128
)
or a DateTime
. For a seed dt
of type DateTime
the value of epoch_milliseconds[dt]
is
used as seed.
Please note that if seed
has more than one value, then the smallest value in seed
will
be used as the seed (according to the native sort order that is used by sort
). If seed
is empty, then the result is empty.
Example:
def output = random_mersenne_twister[0, true]
//output> (0.8236475079774124,)
def output = random_mersenne_twister[random_uint128, 'a']
//output> ('a', 0.590845)
def sample = {'a'; 'b'; 'c'}
def output = random_mersenne_twister[random_uint128, sample]
//output> ('a', 0.590845)
// ('b', 0.766797)
// ('c', 0.566237)
def output = random_mersenne_twister[datetime_now, true]
//output> (0.09946255273771532,)
random_threefry_float64
random_threefry_float64[key1, key2]
Generates a pseudorandom number of type Float64
between 0.0 and 1.0 using the Threefry algorithm.
The Threefry algorithm depends on two keys: key1
and key2
of type UInt64
or Int64
.
One key can be used as the seed. The other key can be used as the stream position.
Which key is used for what is up to the user.
Examples:
Getting a single random Float64
number:
def output = random_threefry_float64[1234, 1]
//output> 0.14708645730224323
Generating a sequence of random Float64
numbers using a user-specific seed:
def output = random_threefry_float64[1234, i] for i in range[1, 3, 1]
//output> (1, 0.14708645730224323)
// (2, 0.18124311325337028)
// (3, 0.14463837673485513)
Using a randomly generated (but deterministic) seed via random_threefry_uint64
:
def seed = random_threefry_uint64[1234, 0]
def output = random_threefry_float64[seed, i] for i in range[1, 3, 1]
//output> (1, 0.2959011588531637)
// (2, 0.5971368640131505)
// (3, 0.4259318598026802)
Generating a random Float64
number from the indeterministic random seed random_uint64
:
def output = random_threefry_float64[random_uint64, 0]
random_threefry_uint64
random_threefry_uint64[key1, key2]
Generates a pseudorandom number of type UInt64
using the Threefry algorithm.
The Threefry algorithm depends on two keys: key1
and key2
of type UInt64
or Int64
.
One key can be used as the seed. The other key can be used as the stream position.
Which key is used for what is up to the user.
Note that the output of random_threefry_uint64
can be used as a key again in a subsequent call.
This capability allows the user to start a new random sequence from a previous sequence without
the need to track which keys have already been used.
Examples:
Getting a single random UInt64
number:
def output = random_threefry_uint64[1234, 1]
//output> 0xbf025a77543cc31d
Generating a sequence of random UInt64
numbers:
def output = random_threefry_uint64[1234, i] for i in range[1, 3, 1]
//output> (1, 0xbf025a77543cc31d)
// (2, 0xe532e65f2dc0c673)
// (3, 0x1bb25070549d29e7)
Generating two sequences of random UInt64
numbers by creating a new seed from the previous seed:
def seed1 = random_threefry_uint64[1234, 0]
def seed2 = random_threefry_uint64[seed1, 0]
def output:one = random_threefry_uint64[seed1, i] for i in range[1, 3, 1]
def output:two = random_threefry_uint64[seed2, i] for i in range[1, 3, 1]
//output> (:one, 1, 0x2ca4bc02da81f726)
// (:one, 2, 0x12898ddf6262c27b)
// (:one, 3, 0xd606d09ded02d4dd)
// (:two, 1, 0x48879dd755a393be)
// (:two, 2, 0xc5683a27c1e876a7)
// (:two, 3, 0xfdb025894557c350)
random_uint128
random_uint128
Random number generated using the random device. It is an unsigned 128-bit integer.
A single random number is generated using the random device of the operating system for every transaction. Within the transaction, the random number does not change. The random number can be used as the seed of a pseudo-random number generator.
Examples:
def output = random_uint128
//output> (0x648fa1de9056c1c7de7fc61bc138f5a8,)
Please note that random numbers need to be used with caution in views that need to be materialized or even incrementally maintained. If a view depends on a random number, then it needs to be recomputed every time the view is needed because the random number changes with every transaction and the view is always be consistent with its inputs.
If a random seed should not change with every transaction, then the state of a seed should be managed explicitly as an EDB. For example, a seed uses for a PRNG can be initialized in one transaction and then the same value is used from that point. In this way, materialized views involving random numbers can be reused.
random_uint64
random_uint64
Random number generated using the random device. It is an unsigned 64-bit integer.
This is a truncation of random_uint128
to the lower 64 bits. It does not provide an
additional source of random numbers.
Please check out the documentation for random_uint128
to get more information about how to
use random numbers in various situations.
Example:
def output = random_uint64
//output> (0xde7fc61bc138f5a8,)
range
range[start, stop, step]
range(start, stop, step, x)
Generate a relation with integer values between start
and stop
, inclusive, advancing by step
each time.
Parameters
Parameter | Type | Description |
---|---|---|
start | Int , Float | Starting point for range (inclusive). Must be grounded. |
stop | Int , Float | Ending point for range (inclusive). Must be grounded. |
step | Int , Float | Step size. Positive integer. Must be grounded. |
x | Int , Float | Result of range . |
All parameters must have the same numeric data type. That is, they must be all 64-bit integers or all floats.
Explanation
range
produces a one-column relation containg the values start
, start + step
, start + 2*step
and so on as long as the values don’t exceed the value defined by stop
.
That is, if start <= stop
and step > 0
, then range[start, stop, step]
has all the values
x = start + i * step <= stop
for non-negative integers i
.
Can be used to generate a sequence of numbers.
step
must be a positive integer.
If start > stop
or step <= 0
, then range[start, stop, step]
is empty.
Examples
Generate a sequence of numbers from 2 to 10, incrementing by 2:
def output(x) = range(2, 10, 2, x)
//output> 2
// 4
// 6
// 8
// 10
Generate a sequence of numbers from 0 to 6, incrementing by 1.2:
def output = range[0.0, 6.0, 1.2]
//output> 0.0
// 1.2
// 2.4
// 3.6
// 4.8
// 6.0
rational
rational[n, num, denom]
The n
-bit rational value from integer numerator num
and denominator denom
.
Both num
and denom
must be encodable with n
-bits.
The result is invalid when both the numerator and the denominator are zero.
Rational
Rational(nbits, x)
Holds if x
is an nbits
rational constructed with rational[nbits, numerator, denominator]
.
Example:
Query that checks that x
is of type Rational with a bit size of nbits
, a numerator of -5
, and a denominator of -7
:
def my_rational = rational[16, -5, -7]
def output(x) = my_rational(x) and Rational(16, x)
//output> 5/7
rational_convert
rational_convert[n, x]
Convert a number x
to a rational with n
-bit integer representation.
Any type that supports numerator
and denominator
is supported.
Examples:
rational_convert[64, 3] = (3//1,)
rational_convert[64, decimal[#64, #2, 0.75]] = (3//4,)
regex_compile
regex_compile(regex, pattern)
Compile a regular expression to a pattern. If regex
is a pattern, rather than a string,
then pattern = regex
.
Example:
def p = regex_compile["^.*@.*$"]
pattern_match(p, "foo@example.com")
//output> () // true
regex_match
regex_match(regex, string)
Match string with a regular expression (string or pattern).
Note that if the entire string needs to be matched, then a leading ^
and
trailing $
are required in the regular expression.
Example:
regex_match("^.*@.*$", "a@b")
regex_match_all
regex_match_all[regex, input_string]
All the occurrences of a regular expression regex
(string or pattern)
in string
, including all the matches and offsets.
Each match is a pair (i, s)
with the character index i
where that matching string starts and
the matching string s
.
Example:
regex_match_all["(?<hour>\\d+):(?<minute>\\d+)",
"Appointment from 12:45 to 1:30"]
is equal to
{(19, "12:45"); (28, "1:30")}
rel:catalog:model (bound)
bound rel:catalog:model
Declare that rel:catalog:model
has type (String, String)
.
This declaration generates an IC ensuring that rel:catalog:model
contains
only tuples of type (String, String)
.
rel:catalog:model_creation_time (bound)
bound rel:catalog:model_creation_time
Declare that rel:catalog:model_creation_time
has type (String, DateTime)
.
This declaration generates an IC ensuring that rel:catalog:model_creation_time
contains
only tuples of type (String, DateTime)
.
rel:catalog:model_update_time (bound)
bound rel:catalog:model_update_time
Declare that rel:catalog:model_update_time
has type (String, DateTime)
.
This declaration generates an IC ensuring that rel:catalog:model_update_time
contains
only tuples of type (String, DateTime)
.
rel:integration:load_partitioned_csv
rel:integration:load_partitioned_csv[URI_string]
rel:integration:load_partitioned_csv[R]
This is the main in-language API for loading partitioned CSV data into a single logical relation.
For detailed information on CSV loading, see load_csv.
To load a partitioned CSV, specify the following:
:path
: The path to the first CSV partition, e.g."azure://storage.blob.core.net/container/file_1_of_24.csv"
. For more than one partition to get picked up, please note the naming schema: Name partitions using[...]_m_of_n[...]
, wherem
is the current partition andn
the total number of partitions (e.g.mycsv_1_of_16.csv
,mycsv_2_of_16.csv
, etc.).- Only the first partition should include header information.
- Make sure all partitions are stored under the same
:path
prefix.
The resulting relation is of the form (column_name, partition, line, value)
. partition, line
uniquely identifies each row in the CSV.
If errors occur, the resulting relation is of the form (:load_errors, partition, line, error_column, raw_line)
.
partition
and line
are UInt32s. To address them, please use uint[32, <number>]
.
If only a single partition is provided or data is directly passed into the load, the
resulting relation looks just like a load_csv
call with an added partition = uint[32, 1]
.
rel:mirror:argument
rel:mirror:argument[T]
rel:mirror:argument(T, tuple_position, value)
Maps the arguments of a relation T
to a new binary relation containing all the elements of T
keyed by their position in the argument tuple.
Examples
Pivot an arity-3 relation:
def output = rel:mirror:argument[{"first", "second, "third"}]
//output> (#1, "first")
// (#2, "second")
// (#3, "third")
rel:mirror:arity
rel:mirror:arity[R]
rel:mirror:precise_arity[R](v)
The specialized form of the arity of a relation.
rel:mirror:precise_arity[R]
is similar to rel:mirror:arity[R]
but only outputs the arities for which there are run-time values in R
.
Example:
def p = (1, 2, 3)
ic { rel:mirror:arity[p] = #3 }
ic { rel:mirror:precise_arity[p] = #3 }
def q = p ∩ (4, 5, 6) // empty
ic { rel:mirror:arity[q] = #3 }
ic { not exists(rel:mirror:precise_arity[q]) }
RelName
RelName(x)
Holds if x
is a relation name.
Examples:
Integrity constraint specifying that mymodule
always contains a RelName
and an integer:
def mymodule:f = 1
ic { subset(mymodule, (RelName, Int)) }
def output = mymodule
//output> (:f, 1)
relname_string
relname_string[my_relname]
relname_string(my_relname, my_string)
Convert RelName (my_relname
) data into String data (my_string
).
Parameters
Parameter | Type | Description |
---|---|---|
my_relname | RelName | A valid RelName. |
my_string | String | A valid string. |
Explanation
The relation relname_string
maps a RelName
value to its corresponding String
value.
RelName
is a specialized data type version of the String
data type.
RelName
data types are used for metadata information.
Relation, module, and IC names are all stored as RelName
.
relname_string
can be used to:
- Verify that a RelName and string match.
relname_string(relation_name, string)
evaluates totrue
ifrelation_name
matchesstring
. Ifrelation_name
does not matchstring
,relname_string(relation_name, string)
evaluates tofalse
(the empty relation,{}
). - Convert a RelName to a string (
relname_string[relation_name]
provides shorthand for this use).
Using relname_string
to convert a String to a RelName is not yet supported.
Examples
Verify that a RelName matches a string.
relname_string(:rel, "rel")
//evaluates to `true` because the RelName `:rel` matches the string `"rel"`.
Convert RelName :employees
to string:
def output(x) = relname_string(:employees, x)
//output> "employees"
Convert RelName :employees
to string using equivalent shorthand:
def output = relname_string[:employees]
See Also
string
remainder
remainder[x, y]
remainder(x, y, r)
x % y
Remainder from truncated division.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Dividend. Must be grounded. |
y | Number | Divisor. Must be grounded. |
r | Number | Remainder. |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | r |
---|---|---|
Number | Same as x . | Same as x . |
SignedInt , UnsignedInt | SignedInt , UnsignedInt | SignedInt[n] or UnsignedInt[n] , where n is the greater of the number of bits in the types of x or y . Signedness matches the type of x . |
Floating , FixedDecimal | SignedInt[64] | Same as x . |
SignedInt[64] | Floating , FixedDecimal | Same as y . |
Rational | SignedInt[64] | Rational[n] , where n is the greater of the number of bits in the the types of x and y . |
SignedInt[64] | Rational | Rational[n] , where n is the greater of the number of bits in the the types of x and y . |
Explanation
remainder
is the remainder of x
after truncated division of y
.
That is, remainder[x, y]
is equivalent to x - (y * trunc_divide[x, y])
.
x % y
is equivalent to remainder[x, y]
.
r
has the same sign as x
, and is smaller in magnitude than y
.
The value for r
is always exact.
remainder[x, y]
is defined when either the types of x
and y
are the same, or
either operand is of type SignedInt[64]
or Floating[64]
.
remainder
is false
(empty) when y = 0
for integer arguments.
Examples
Compute remainder of integer divided by integer using %
.
def output = 8 % 3
//output> 2
Compute remainder of integer divided by integer using remainder
:
def output = remainder[-8, 3]
//output> -2
Compute remainder of integer divided by negative integer using full expression:
def output(r) = remainder(8, -3, r)
//output> 2
Compute remainder of rational divided by negative integer:
def output = remainder[rational[64, 8, 3], -2]
//output> 2/3
Confirm that remainder is false
(empty) when y
is 0
:
def output = empty(remainder[6, 0])
//output> () // true
reverse_sort
reverse_sort[R]
Reverse Sort
Like sort
, except the ordering is reversed.
Example:
def sample = {'a'; 'b'; 'c'}
def output = reverse_sort[sample]
//output> (1, 'c')
// (2, 'b')
// (3, 'a')
def sample = {(:g, 'a'); (:g, 'b'); (:g, 'c'); (:h, 'd'); (:h, 'e'); (:h, 'f')}
def output = x: reverse_sort[sample[x]]
//output> (:g, 1, 'c')
// (:g, 2, 'b')
// (:g, 3, 'a')
// (:h, 1, 'f')
// (:h, 2, 'e')
// (:h, 3, 'd')
right_override
right_override[R, S]
R ++> S
Right override is identical to left override, except the arguments are swapped.
R ++> S
contains all of S
, plus all the tuples in R
whose key is not in S
.
There are two equivalent ways to think about R ++> S
:
(1) R
is providing default values for keys that are missing in S
.
(2) The entries in S
are overriding the entries in R
.
A few examples to illustrate the difference with left-override:
Example | Value |
---|---|
2 ++> 3 | 3 |
(1,2) ++> (1,3) | (1,3) |
(3,4) ++> (1,2); (3,5) | (1,2); (3,5) |
(3,"abc") ++> (1,2); (3,5) | (1,2); (3,5) |
(1,2); (3,5) ++> (3,4); (6,7) | (1,2); (3,4); (6,7) |
rmse
rmse[YHAT, Y]
Root mean square error (RMSE)
round
round[mode, x]
round(mode, x, r)
Round x
to an integer according to the given rounding mode. The rounded number is of the same data type as x
.
Parameters
Parameter | Type | Description |
---|---|---|
mode | RelName | Mode for rounding. Must be grounded. |
x | Number | Number to be rounded. Must be grounded. |
r | Number | Result of rounding x . Same type as x . |
Available Modes
mode | Description |
---|---|
:ROUND_UP | Round up to the nearest integer. |
:ROUND_DOWN | Round down to the nearest integer. |
:ROUND_NEAREST | Round to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. |
:ROUND_NEAREST_TIES_AWAY | Round to the nearest integer, with ties rounded away from zero. |
:ROUND_NEAREST_TIES_UP | Round to the nearest integer, with ties rounded toward positive infinity. |
:ROUND_TO_ZERO | Round toward zero to the nearest integer. |
Examples
Round nearest float:
def output = round[:ROUND_NEAREST, -8.555]
//output> 9.0
Round up rational:
def output = round[:ROUND_UP, rational[64, 8, 3]]
//output> 3/1
Round down float using full expression:
def output(r) = round(:ROUND_DOWN, 8.4, r)
//output> 8.0
Round nearest float, showing ties away and ties up:
def output:away = round[:ROUND_NEAREST_TIES_AWAY, -8.5]
def output:up = round[:ROUND_NEAREST_TIES_UP, -8.5]
//output> (:away, -9.0)
// (:up, -8.0)
Round to 0:
def output = round[:ROUND_TO_ZERO, -8.5]
//output> -8.0
See Also
floor
, floor_to_int
, ceil
, trunc
, and trunc_to_int
.
round
round[x]
round(x, r)
Round x
to the nearest integer. The rounded number is of the same data type as x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Number to be rounded. Must be grounded. |
r | Number | Result of rounding x . Same type as x . |
Explanation
round[x]
rounds to the nearest integer, with ties rounded to the nearest even integer.
It is equivalent to round[:ROUND_NEAREST, x]
.
For details see the docstring for round(mode, x, r)
.
Example
Rounding a floating-point number:
def output = round[9.7]
//output> 10.0
Rounding a fractional:
def output = round[rational[64, 7, 3]]
//output> 2/1
sample_standard_deviation
sample_standard_deviation[R]
sample_stddev[R]
Sample standard deviation of (the last argument of) the relation R
.
sample_stddev
see: sample_standard_deviation
sample_variance
sample_variance[R]
Sample variance
sample_zscore_normalization
sample_zscore_normalization[R]
Z-score normalization (sample) of (the last argument of) the relation R
.
Often simply referred to as ‘standardization’.
Second
Second[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Second constructor, ^Second
, instead.
Create a period of n
seconds.
second
second[R]
Projection to the second argument of R.
second
supports heterogeneous relations, both in arity and types.
Examples:
def output = second[(1, 2, 3); (4, 5)]
//output> 2
// 5
def output = second[(1, 2); (3, "abc")]
//output> 2
// "abc"
sign
sign[x]
The sign of x: either 0, -1, or 1.
SignedInt
SignedInt(nbits, x)
Holds if x
is an nbits
signed integer.
Examples:
Integrity constraint that tests whether x
is an 8-bit signed integer:
def R = int[8, 5]
ic unsigned_type_check(x in R) {
SignedInt(8, x)
}
sin
sin[x]
sin(x, s)
Sine of x
, where x
is an angle given in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x | SignedInt[64] , Floating[64] | Angle in radians. Must be grounded. |
s | Floating[64] | Sine of x . |
Currently, only 64-bit float and integer values for x
are supported.
Examples
Calculate the sine of π/2::
def output = sin[pi_float64/2]
//output> 1
Calculate the sine of 5π/6:
def output = sin[5 * pi_float64/6]
//output> 0.49999999999999994
See Also
asin
, sinh
, asinh
, cos
, acos
, cosh
, acosh
, tan
, atan
, tanh
, and atanh
.
sinh
sinh[x]
sinh(x, sh)
Hyperbolic sine. sh
is the hyperbolic sine of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Hyperbolic angle. Must be grounded. |
sh | Floating[64] | Hyberbolic sine of x . |
Explanation
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the hyperbolic sine of 7:
def output = sinh[7]
//output> 548.3161232732465
Calculate the hyperbolic sine of -1 using full expression:
def output(x) = sinh(-1, x)
//output> -1.1752011936438014
Confirm that 548.3161232732465 is the hyperbolic sine of 7:
def output = sinh(7, 548.3161232732465)
//output> () // true
See Also
sin
, cos
, asin
, acos
, asinh
, acosh
, cosh
, and haversine
.
sort
sort[R]
sort(index, R, x...)
Enumerate a relation.
It is an alias for enumerate
.
For details, see the docstring for enumerate
.
soundex
soundex[string_value]
soundex
returns a four-letter encoding the phonetic representation of string_value
.
soundex
lets you compare words and sentences based on how they sound in English.
string_value
could be any arbitrary long string, but only the first few syllables are
considered for the result.
Examples:
def output = soundex["Smith"]
//output> s530
def output = soundex["Smythe"]
//output> s530
def output = soundex["Christina"]
//output> c623
def output = soundex["Cristine"]
//output> c623
Here is a simple illustration. Consider the following:
def my_favorite_bands = { "Metallica"; "Iron Maiden"; "Wolfheart"; "Insomium" }
def do_I_like = "Mee ta li ka"
def output = exists({ y : soundex[my_favorite_bands][y] and equal(y, soundex[do_I_like]) })
The script above evaluates to true
since "Mee ta li ka"
and
"Metallica"
have the same soundex code.
spread
spread[mode, R, value]
spread(mode, R, value, x..., spread)
Spread value
to the tuples in relation R
, either evenly or proportionally to their
weight, which is the last element in each tuple.
Parameter
Parameter | Type | Description |
---|---|---|
mode | RelName | :even or :ratio . |
R | Relation | Source relation. Must be grounded. |
value | Int , FixedDecimal | Integer or decimal to be divided among tuples as spread . Must be grounded. |
x... | Tuple | A tuple in R . |
spread | Float | Spread associated with x... . |
Explanation
spread
takes a relation R(x...)
and produces a relation with the tuples (x..., spread)
where the last element of each tuple (spread
)
is a spread of value
distributed among tuples.
When mode
is :even
, spread
is value
divided evenly among tuples.
When mode
is :ratio
, spread
is value
divided proportionally to a tuple’s
weight — the last element in each tuple.
spread
can be either an integer or a decimal depending on the type of value
.
That is, if you use a decimal for value
, spread
behaves like FixedDecimal_spread
.
If you use an integer for value
, spread
behaves like either int_spread_by_even
or int_spread_by_ratio
, depending on mode
.
spread
is empty if value
is negative.
Examples
Spread using a value
that is a decimal.
Note that spread
is a decimal with the same number of places as value
, just as would be the case with FixedDecimal_spread
:
def R = {("Atlanta", 50);
("Seattle", 80);
("San Francisco", 10)}
def output = spread[:even, R, decimal[#64, #3, 31.0] ]
//output> Atlanta, 50, 10.334
// San Francisco, 10, 10.333
// Seattle, 80, 10.333
Spread using a value
that is an integer.
Note that spread
is an integer:
def R = {("Atlanta", 50);
("Seattle", 80);
("San Francisco", 10)}
def output = spread[:even, R, 31]
//output> Atlanta, 50, 11
// San Francisco, 10, 10
// Seattle, 80, 10
Spread using full expression, using a decimal as spread
:
def R = {("Miles Davis", 65); ("Jimmy Smith", 76); ("Ornette Coleman", 85)}
def output = spread[:ratio, R, decimal[#64, #3, 88.55]]
//output> Jimmy Smith, 29.778
// Miles Davis, 25.468
// Ornette Coleman, 33.304
See Also
int_spread_by_ratio
, int_spread_by_even
, and FixedDecimal_spread
.
sqrt
sqrt[x]
The non-negative square root of x
.
Defined for non-negative x
.
squared
squared[R]
Square of a relation: the value of each last element is squared.
Examples:
def example = {(1, 2); (3, 4)}
equal(square[example], {(1, 4); (3, 16)}
squared_deviation
squared_deviation[R]
Squared deviation: squared deviation from the mean of (the last argument of) the relation R
.
starts_with
starts_with(s, prefix)
True if and only if the specified string s
begins with the given prefix prefix
.
Examples:
starts_with("abc", "ab") // true
starts_with("abc", "bc") // false
starts_with("abc", "abcd") // false
starts_with("abc", "Ab") // false
string
string[x]
Convert ints, floats, dates, periods, to strings:
Examples:
string[1] = "1"
string[3.4] = "3.4"
string[unix_epoch] = "1970-01-01T00:00:00"
string[^Hour[1]] = "1 hour"
string["a"] = "a"
string[:a] = "a"
String
String(x)
Holds if x
is a String
. Strings are specified by double quotes, for example, "abc"
.
Examples:
Integrity constraint that tests whether x
is of type String
:
def R = "foo"
ic string_type_check(x in R) {
String(x)
}
Schema defined in a relation using String
:
def myrelation(x in String, y in Int) {
x = "abc" and y = 123
}
def output = myrelation
//output> (abc, 123)
string_join
string_join[separator, R]
string_join(separator, R, new_string)
Concatenate the string values in the binary relation R
into one string and insert the string, separator
, between two adjacent strings.
Parameters
Parameter | Type | Description |
---|---|---|
separator | Char or String | Character or String used to separate adjacent strings. Must be grounded. |
R | Relation | A binary relation containing tuples of the form (Int, String) . Must be grounded. |
new_string | String | Resulting string containing all the strings in R separated by separator . |
Explanation
The binary relation R
can only contain tuples (index, text)
with the signature (Int, String)
.
The purpose of the two elements are:
- The integer
index
represents the order of the strings to be joined, and serves as the sort key for concatenation. - The string
text
represents the Strings that will be concatenated together.
If R
is empty, the expression string_join[separator, R]
is false
and no new string is created.
Examples
Concatenate using ", "
as separator:
def output = string_join[", ", {(1, "a"); (2, "b"); (3, "c")}]
//output> "a,b,c"
Concatenate using the character ' '
as separator:
def output = string_join[' ', {(1, "hello"); (2, "world")}]
//output> "hello world"
Using string_join
and sort
to order a set of Strings alphabetically and join them together with "->"
as separator:
def output = string_join["->", sort[{"x"; "y"; "z"}]]
//output> "x->y->z"
See Also
string_length
, string_replace
, string_replace_multiple
, string_split
, and string_trim
.
string_length
string_length[string]
DEPRECATED
This function is deprecated. Use num_chars[string]
or num_bytes[string]
,
depending on your need.
Example:
string_length["foo"] = 3
string_replace
string_replace[string, old_str, new_str]
Replace a string or character in string with the specific string or character.
Examples:
string_replace["One Two Three", "One", "1"] = "1 Two Three"
string_replace["Rel", 'R', 'r'] = "rel"
string_replace_multiple
string_replace_multiple[input, R]
Replaces all occurrences of old
string in input
with the corresponding new
string, for each tuple (old, new)
in relation R
.
Examples:
string_replace_multiple["One Two Three", {("One", "1"); ("Two", "2")}]
// "1 2 Three"
string_replace_multiple["One Two Three", {('O', 'o'); ('T', 't')}]
// "one two three"
The behavior is undefined if new
generates more occurrences of old
.
string_split
string_split[delimiter, text]
Split the string text
into the substrings delimited by delimiter
(and the
start/end of text
).
The expression string_split[delimiter, string]
evaluates to a relation of the format
(index, sub_string)
where index
is the substring’s position of type Int
and
sub_string
is the matched substring of type String
.
delimiter
can be a String
or a Char
.
Example:
string_split['@', "user@email.com"] = {(1, "user"); (2, "email.com")}
string_split[" ", "a b c"] = {(1, "a"); (2, "b"); (3, ""); (4, "c")}
string_trim
string_trim[s]
To remove leading and tailing white spaces in given string s
.
Example:
string_trim[" Good Day!!! "] = "Good Day!!!"
subset
subset(R, S)
R ⊆ S
R
is a subset of S
if all facts in R
are also in S
.
Subset is the relational variant of implication, but note that there is a subtle difference for arity-overloaded relations due to usage of varargs.
-
forall(x, y: R(x, y) implies S(x, y))
is true if the implication is true for all binary facts ofR
. IfR
also contains facts of a different arity, then the implication remains true, even whenR ⊈ S
. -
subset(R, S)
, defined asforall(xs... where R(xs...) : S(xs...))
, is true only if there exists no fact inR
, of any arity, that is not also inS
.
substring
substring[mystring, i, j]
substring(mystring, i, j, substring)
Find a substring (substring
) within mystring
that starts at index i
and ends at index j
.
Parameters
Parameter | Type | Description |
---|---|---|
mystring | String | Source text. Must be grounded. |
i | SignedInt , UnsignedInt | The position where substring begins. Must be grounded. |
j | SignedInt , UnsignedInt | The position where substring ends. Must be grounded. |
substring | String | A string that begins at the i -th character and ends at the j -th character. |
Explanation
The index of a string’s first character is 1.
When i
and j
are out of bounds on the same end, or i
> j
, the empty string is returned.
If i < 1
the substring will start with the first character in mystring
.
If j > length[mystring]
the substring ends with the last character in mystring
.
Examples
Get the two-character string beginning with position 2
:
def output = substring["abcd", 2, 3]
//output> bc
Get a two-character string beginning with position 2
using full expression:
def output(x) = substring("中文例子", 2, 3, x)
//output> 文例
Substring that returns empty because i
> j
:
def output = substring["abcd", 3, 2]
//output> ""
Substring that returns empty because i
and j
are out of bounds:
def output = substring["abcd", 5, 7]
//output> ""
Get the substring containing the first three characters with i
out of bounds:
def output = substring["abcd", -2, 3]
//output> abc
Get the substring containing the characters starting at index 2
and with j
out of bounds:
def output = substring["abcd", 2, 7]
//output> bcd
See Also
substring_bytes
, starts_with
, ends_with
, and string_replace
.
substring_bytes
substring_bytes[string, index1, index2]
Extracts substring of a string
between the byte range [index1:index2]
(both inclusive).
The byte index starts with 1.
When index1
and index2
are out of bounds on the same end, or index2
< index1
,
the empty string is returned.
Otherwise, both indices are clamped in range.
Use substring
to extract substrings by character indices.
Examples:
substring_bytes["abcd", 2, 3] = "bc"
substring_bytes["abcd", 3, 2] = ""
substring_bytes["word", 0, 10] = "word"
Note that non-ASCII characters require usually more than one byte per character:
substring_bytes["中文例子", 1, 6] = """中文"""
subtract
subtract[x, y]
subtract(x, y, d)
x - y
Subtraction of one number from another. Subtraction of a date, datetimes, and periods.
Parameters
Numeric Data
Parameter | Type | Description |
---|---|---|
x | Number | Subtrahend. |
y | Number | Minuend. |
d | Number | Difference x - y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | d |
---|---|---|
Number | Same as x | Same as x |
SignedInt[64] | SignedInt[128] , Floating[64] , FixedDecimal , Rational | Same as y |
SignedInt[128] , Floating[64] , FixedDecimal , Rational | SignedInt[64] | Same as x |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
x
andy
.x
andd
.y
andd
.
Time Data
Parameter | Type | Description |
---|---|---|
x | Date , DateTime , date period, time period | Minuend. |
y | Date , DateTime , date period, time period | Subtrahend. |
d | Date , DateTime , date period, time period | Difference x - y . |
The following combinations work:
x | y | d |
---|---|---|
date period, time period | Same date period, time period as x | Same Date period, time period as x |
DateTime | date period, time period | DateTime |
DateTime | DateTime | Time period in Millisecond |
Date | date period | Date |
Date | Date | date period in Day |
Two of the three arguments need to be grounded. Valid grounding combinations are as follows:
x
andy
.x
andd
.y
andd
.
Explanation
subtract
maps the pair x
, y
to d
, which is the difference x - y
.
In procedural languages, usually x
and y
are given.
In Rel — a declarative language — subtraction can be thought of as a mapping where x
and y
are the keys and d
is the value, which is functionally dependent on x
and y
.
However, with subtraction — subtract(x, y, d)
— it is sufficient to know any two of the three arguments.
The third argument can always be inferred.
Usually x
and y
are given, but knowing x
and d
is enough to infer y
.
Examples
Subtract two numerals using -
:
def output = 8 - 5
//output> 3
Subtract a float from an integer using subtract
:
def output = subtract[7, 5.25]
//output> 1.75
Subtract two floats using full expression:
def output(x) = subtract(8.5, 5.25, x)
//output> 3.25
Subtract a rational from an integer:
def output = x - rational[16, 2, 3]
//output> 4/3
Calculate integer subtracted by providing x
and d
:
def output(y) = subtract(2899, y, 2865)
//output> 34
Subtraction of Time
Subtract a time period and a date period from a timestamp:
def output:yesterday = datetime_now - ^Day[1]
def output:last_hour = datetime_now - ^Hour[1]
//output> (:last_hour, 2022-11-17T13:01:52.537Z)
// (:yesterday, 2022-11-16T14:01:52.537Z)
Subtract a timestamp from a timestamp and get the difference in milliseconds. Note that the second date is defined in a different time zone and the time difference is 58 hours, or 136800000 milliseconds:
def output = 2021-10-12T01:00:00+00:00 - 2021-10-10T01:00:00+10:00
//output> 136800000
Subtract weeks from a date:
def output = 2024-01-10 - ^Week[2]
//output> 2023-12-27
Subtract two dates from each other and retrieve the number of days between them. Here, the date period is negative because the second date occurs later:
def output = 2023-12-30 - 2024-01-10
//output> -11
Calculate date subtracted by providing date and resulting period:
def output(y) = subtract(2022-10-01, y, ^Day[10])
//output> 2022-09-21
Subtract 2 seconds from 6 seconds:
def output = ^Second[6] - ^Second[2]
//output> 4
See Also
add
, divide
, and multiply
.
suffix_join
suffix_join[R, S]
R :> S
The suffix join (or restriction) of R
to S
consists of the tuples (x..., y...)
in R
where the suffix (y...)
is in S
.
That is, R :> S
contains the tuples in R
that have a suffix in S
.
Example | Normalized |
---|---|
edge :> n | x, y: edge(x, y) and y = n |
parent :> female | x, y: parent(x, y) and female(y) |
account_balance :> positive | x, v: account_balance(x, v) and positive(v) |
brand_name :> "Tesla" | b, s: brand_name(b, s) and s = "Tesla" |
The restriction operator can also be used to select subsets of JSON-like relations:
-
json :> even
wherejson
is[ {"a": 1, "b": 2}, {"a": 3, "b": 4, "c": 6} ]
has value[ {"b": 2}, {"b": 4, "c": 6} ]
-
json :> (:b, even)
wherejson
is[ {"a": 1, "b": 2}, {"a": 3, "b": 4, "c": 6} ]
has value[ {"b": 2}, {"b": 4} ]
sum
sum[R]
sum(R, s)
Σ[R]
Σ(R, s)
Sum of the last element of all tuples in a relation.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
s | Number | The sum of the last element of R . |
Explanation
sum
aggregates over all tuples in R
whose last element is numeric.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
For example, if R
contains key-value pairs, sum[R]
calculates the sum of values for R
.
Note that sum
groups the tuples by the data type of the final numeric element.
Typically, sum
is used when the last elements of each tuple have the same type.
If R
is empty, sum[R]
is false
(empty).
To get 0 instead, use left override, as in sum[R] <++ 0
.
Examples
Calculate the sum of integers:
def salary = {("John", 10) ; ("Mary", 20); ("Paul", 17) ; ("Peter", 15) }
def output = sum[salary]
//output> 62
Calculate the sum of R
for each data type:
def R = {(1, "1"); (2, 2); (3, 3.0); (4, 4)}
def output = sum[R]
//output> 3.0
6
Calculate the sum of R
using full expression:
def R = {("A", 7.5); ("B", 8.6); ("C", 9.7)}
def output(s) = sum(R, s)
//output> 25.8
Calculate the total salary by department using group-by:
def department = {"A"; "B"; "C" }
def member = {("A", "John"); ("B", "Mary"); ("A", "Paul"); ("C" , "Peter"); ("C", "Tran")}
def salary = {("John", 126) ; ("Mary", 90); ("Paul", 117); ("Peter", 115); ("Tran", 145)}
def output = d in department: sum[salary[p] for p in member[d]]
//output> "A", 243
// "B", 90
// "C", 260
See Also
add
, sum_int
, min
, argmax
, sum
, and average
.
sum_int
sum_int[R]
sum_int(R, si)
Integer sum of the last element of the relation R
, which should contain integers.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A grounded relation. The last element of every tuple must be an integer. |
si | SignedInt[64] | The integer sum of the last element of R . |
Explanation
sum_int
sums over the last elements of every tuple in R
.
The last elements must be integers.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
If R
is empty, sum_int[R]
is false
(empty).
Use <++
(left override) if you need a specific value for the case where R
is empty.
Examples
Find the integer sum of a relation:
def R = {("Oakland", 22); ("Fresno", 11); ("Palo Alto", 15); ("Eureka", 40)}
def output = sum_int[R]
//output> 88
Find the integer sum of a relation using full expression:
def salary = {("John", 10) ; ("Mary", 20); ("Paul", 17) ; ("Peter", 15) }
def output(si) = sum_int(salary, si)
//output> 62
See Also
add
, sum
, min
, max
, product
, and average
.
superset
superset(R, S)
R ⊇ S
Inverse of subset. See subset.
tan
tan[x]
tan(x, t)
Tangent. t
is the tangent of x
, where x
is in radians.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Angle in radians. Must be grounded. |
t | Floating[64] | Tangent of x . |
Defined for non-infinite x
.
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the tangent of π/4:
def output = tan[pi_float64/4]
//output> 0.9999999999999999
Convert degrees to radians and calculate tangent using full expression:
def x = deg2rad[90]
def output(t) = tan(x, t)
//output> 16331239353195370.0
Confirm that 0.9999999999999999 is the tangent of π/4:
def output = tan(pi_float64/4, 0.9999999999999999)
//output> () // true
See Also
atan
, atan2
, cot
, acot
, tanh
, and atanh
.
tanh
tanh[x]
tanh(x, th)
Hyperbolic tangent. th
is the hyperbolic tangent of x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | Floating[64] , SignedInt[64] | Hyperbolic angle. Must be grounded. |
th | Floating[64] | Hyberbolic tangent of x . |
Explanation
Only 64-bit float and 64-bit integer values for x
are supported.
Examples
Calculate the hyperbolic tangent of 7:
def output = tanh[7]
//output> 0.9999983369439447
Calculate the hyperbolic tangent of -1 using full expression:
def output(x) = tanh(-1, x)
//output> -0.7615941559557649
Confirm that 0.9999983369439447 is the hyperbolic tangent of 7:
def output = tanh(7, 0.9999983369439447)
//output> () // true
See Also
tan
, atan
, atan2
, cot
, acot
, and atanh
.
top
top[k, R]
top(k, R, index, x...)
Select the top k
tuples of relation R
according to the lexicographic order of R
and add enumeration.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | Source relation. Must be grounded. |
k | Int | Number of tuples to enumerate from the top of R . Must be grounded. |
index | Int | The new enumaration index starting at 1. |
x... | Tuple | A tuple in R associated with the new index index . |
Explanation
top
is enumerate
restricted to the first k
tuples of R
.
top
first puts the tuples of R
in lexicographical order and then limits the result to the first k
tuples.
For details on lexicographical ordering — particularly across data types — see enumerate
.
Similar to enumerate
, top
takes a relation R(x...)
and produces a relation with the tuples (index, x...)
,
where the first element of each tuple (index
) is an integer index that enumerates the top k
tuples
in the original relation R
.
If k
is bigger than the number of tuples in the relation R
, then top[k, R]
is equivalent to enumerate[R]
.
The relation R
can contain tuples of various sizes.
top[k, R]
supports group-bys in R
but not in k
.
For example, the following is supported:
def output[g] = top[k, R[g]]
However, the following is not supported:
def output[g] = top[k[g], R]
Examples
Apply top
to a relation with arity-1 tuples:
def output = top[2, {'a'; 'b'; 'c'; 'd'}]
// output> (1, 'a')
// (2, 'b')
Apply top
to a relation with arity-2 tuples:
def R = {('a', 1); ('b', 2); ('c', 3); ('d', 4); ('e', 5)}
def output = top[3, R]
//output> 1, a, 1
// 2, b, 2
// 3, c, 3
See Also
bottom
, enumerate
, sort
, and reverse_sort
.
total
total(D, F)
Given a domain D and a relation F, check that there is a value in F for every element of the domain D. The arity of F must be the arity of D + 1.
transpose
transpose[R]
Transpose a binary relation (swap the two arguments).
Example:
def output = transpose[{(1, 2); (3, 4)}]
//output> (2, 1)
// (4, 3)
trunc
trunc[x]
trunc(x, t)
Round toward zero to the nearest integer.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Number to be rounded toward zero. Must be grounded. |
t | Int | Truncated x . |
Return type is the same as x
.
Explanation
Rounds toward zero for both positive and negative x
.
Examples
Truncate float:
def output = trunc[3.9]
//output> 3.0
Truncate negative float using full expression:
def output(t) = trunc(-4.9, t)
//output> -4.0
Truncate rational:
def output = trunc[rational[64, 27, 5]]
//output> 5/1
See Also
floor
, floor_to_int
, ceil
, trunc_to_int
, and round
.
trunc_divide
trunc_divide[x, y]
trunc_divide(x, y, q)
x ÷ y
Division of two numbers, rounding the result to the nearest integer toward zero.
Parameters
Parameter | Type | Description |
---|---|---|
x | Number | Numerator. Must be grounded. |
y | Number | Denominator. Must be grounded. |
q | Number | Truncated quotient x / y . |
Not all numeric values can be mixed with each other. The following combinations work:
x | y | q |
---|---|---|
SignedInt[64] | SignedInt[64] | SignedInt[64] |
SignedInt[64] | Floating[64] | Floating[64] |
Floating[64] | SignedInt[64] , Floating[64] | Floating[64] |
Rational | SignedInt[64] | SignedInt[64] |
FixedDecimal | SignedInt[64] | Same as x |
Explanation
trunc_divide
maps the pair x
, y
to q
, which is the truncated quotient x/y
.
Similar to divide
and in contrast to add
and subtract
, x
and y
need to be grounded and specified by the user.
Specifying only x
and q
or only y
and q
is not sufficient, because the system can’t compute the inverse.
trunc_divide
is false
(empty) when y = 0
for integer arguments.
Examples
Use truncated division to divide an integer by another integer using ÷
:
def output = 5 ÷ 2
//output> 2
Use truncated division to divide an integer by another integer using trunc_divide
:
def output = trunc_divide[5, 2]
//output> 2
Use truncated division to divide a negative integer by a positive integer:
def output = trunc_divide[-5, 2]
//output> -2
Use truncated division to divide a decimal by an integer using full expression:
def output(x) = trunc_divide(5.1, 2, x)
//output> 2.0
Use truncated division to divide a rational by an integer using full expression:
def output(t) = trunc_divide(rational[64, 26, 3], 2, t)
//output> 4
trunc_to_int
trunc_to_int[x]
trunc_to_int(x, t)
Convert float to integer, truncating.
Parameters
Parameter | Type | Description |
---|---|---|
x | Float | Number to be rounded down. Must be grounded. |
t | Int | Truncated x , integer. |
Explanation
Rounding goes toward zero for both postivie and negative x
.
Examples
Convert float to integer, truncating:
def output = trunc_to_int[3.1]
//output> 3
Convert negative float to integer, truncating, using full expression. Note that rounding goes toward zero.
def output = trunc_to_int[-3.1]
//output> -3
Confirm that trunc_to_int
returns false
(empty) when x
is an integer:
def output = trunc_to_int[3]
//output> // false
See Also
floor
, floor_to_int
, ceil
, trunc
, and round
.
uint
uint[n, v]
The n
-bit unsigned integer value from the positive integer value v
.
n
must be among 8, 16, 32, 64, and 128 and v
is encodable with n
-bits.
Examples:
int[8, 42] = 42
empty(uint[128, -300])
empty(uint[8, 300])
uint128
uint128[v]
The 128-bit unsigned integer value from the integer value v
.
uint128_hash_value_convert
uint128_hash_value_convert[v]
Convert a provided UInt128 value v
to the HashValue type.
This is an internal-facing function, used for the implementation of hashing.
uint128_uint64_truncate
uint128_uint64_truncate[v]
Truncates v
of type UInt128
to a UInt64
number.
Truncates the high order bits in v
and converts the remaining bits to UInt64.
Truncate always succeeds. For values larger than 2^64, consists of only the lower bits.
Examples:
uint128_uint64_truncate[uint128[1]] = 1
uint128_uint64_truncate[uint128[2] ^ 64 + uint128[1]] = 1
uint64
uint64[v]
The 64-bit unsigned integer value from the integer value v
.
union
union[R, S]
R ∪ S
Union two n-ary relations R and S
unit_normalization
unit_normalization[R]
Unit vector normalization:
unix_epoch
unix_epoch
The beginning of the UNIX Epoch, midnight on 1 January 1970 (UTC).
unpack
unpack(v, x₁, ..., xₙ)
Unpacks a packed structure v
into its arguments x₁, ..., xₙ
.
unpack
cannot be used with point-free syntax.
Direct usage of unpack
should be avoided, as it serves primarily as a low-level
interface for value types.
UnsignedInt
UnsignedInt(nbits, x)
Holds if x
is an unsigned integer of the bit length nbits
.
Example:
Integrity constraint that tests whether x
is a 32-bit unsigned integer:
def my_unsigned_int = uint[32, 1234]
ic my_unsigned_ic(x) {
my_unsigned_int(x) implies UnsignedInt(32, x)
}
uppercase
uppercase[string_or_char]
A string where all the characters are converted to uppercase. If a character is already uppercase or has no uppercase version, it remains unchanged.
Example:
def output = uppercase["aB1c"]
//output> "AB1C"
def output = uppercase['â']
//output> 'Â'
uppercase
does not take a locale option and does not handle local-specific case mapping
rules.
uuid_string
uuid_string[v]
Convert a UInt128
, Hash
or rel:base:UUID
value to the standard UUID string format.
Example:
uuid_string[0x22b4a8a1e5484eeb927060426d66a48e] = "22b4a8a1-e548-4eeb-9270-60426d66a48e"
Week
Week[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Week constructor, ^Week
, instead.
Create a period of n
weeks.
weighted_mean
weighted_mean[R, W]
weighted_mean(R, W, wm)
The weighted mean of the last element of each tuple in a relation R
with weights defined by W
.
Parameters
Parameter | Type | Description |
---|---|---|
R | Relation | A relation whose last elements contain numeric data types and whose first elements match W . Must be grounded. |
W | Relation | Weight for weighted mean. A relation whose last elements contain numeric data types and whose first elements match R . Must be grounded. |
wm | Number | The weighted mean of R . |
Explanation
The weighted mean of a relation R
is the sum of the last elements in each tuple of R
,
weighted by the last element of the corresponding tuple in W
.
A tuple in R
corresponds to a tuple in W
if the first elements of the tuples match
— that is, they have the same key.
weighted_mean
aggregates over all tuples in R
whose last element is numeric.
Tuples in R
can have different lengths, and the length may vary from tuple to tuple.
Tuples with a non-numeric last element are ignored.
Note that weighted_mean
groups the tuples by the data type of the last element.
This may cause unexpected results when used in relations with values of mixed types.
Typically, weighted_mean
is used when the last elements of each tuple have the same type.
Examples
Calculate weighted mean of a relation:
def inputs = {(:class_participation , 90); (:assignment_1, 85); (:assignment_2, 81); (:midterm, 76); (:final, 83)}
def weights = {(:class_participation, 10); (:assignment_1, 20); (:assignment_2, 20); (:midterm, 20); (:final, 30)}
def output = weighted_mean[inputs, weights]
//output> 82.3
Calculate weighted mean when the arities of R
and W
are different:
def R = {(1, "cp", 90); (2, "a1", 85); (3, "a2", 81); (4, "mt", 76); (5, "f", 83)}
def W = {(1, 10); (2, 20); (3, 20); (4, 20); (5, 30)}
def output = weighted_mean[R, (k1, k2, v: W(k1, v) and Any(k2))]
//output> 82.3
Calculate weighted mean when the arities of R
and W
are different:
def R = {(1, 'a', 100, 90); (2, 'a', 200, 85); (3, 'b', 300, 81); (4, 'c', 400, 76); (5, 'b', 500, 83)}
def W = {(1, 'a', 10); (2, 'a', 20); (3, 'b', 20); (4, 'c', 20); (5, 'b', 30)}
def output = weighted_mean[R, (n, c: _, W[n, c])]
//output> 82.3
See Also
geometric_mean
, harmonic_mean
, mean
, mode
, max
, min
, sum
, and product
.
xor
F xor G
F ⇎ G
F ⊻ G
Exclusive OR, for boolean (arity 0, true or false) arguments F and G.
Year
Year[n]
DEPRECATED
This function is deprecated and should be avoided. It will be removed soon.
Please use the Year constructor, ^Year
, instead.
Create a period of n
years.
zip
zip[R, S]
Pair-wise combine two n
-ary tuples into a relation of n
pairs.
Example:
def foods = {(:hamburger, :chicken, :hot_dog, :fries, :macaroni, :pizza, :salad, :milk, :ice_cream)}
def cost = { (2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59) }
def output = zip[foods, cost]
//output> (:chicken, 2.89)
// (:fries, 1.89)
// (:hamburger, 2.49)
// (:hot_dog, 1.5)
// (:ice_cream, 1.59)
// (:macaroni, 2.09)
// (:milk, 0.89)
// (:pizza, 1.99)
// (:salad, 2.49)
Σ
Σ[R]
Σ(R, s)
Sum of the last element of all tuples in a relation. Alias for sum
.
Module: rel:base
FilePos
FilePos(x)
^FilePos(y, x)
The data type FilePos
.
The type relation Filepos
checks whether x
is of type FilePos
.
The constructor ^FilePos
maps an integer, y
, to its corresponding FilePos
value, x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | FilePos | FilePos variable. |
y | Integer | The value of the FilePos data type. |
Explanation
The data type FilePos
is defined via a value type declaration, and provides the semantic meaning of a file position to its integer value y
.
Filepos
values are used to identify CSV rows when CSV data is loaded into the RKGS.
For more information on CSV loading, see the CSV data and import guides in the RAI documentation (opens in a new tab).
Examples
A FilePos
value can be created with the constructor ^FilePos
:
def output = ^FilePos[10]
The constructor can also be used to extract the integer value “back out” of the value type.
def fp = ^FilePos[4]
def output(i) = exists(x: ^FilePos(i, x) and fp(x))
The type relation FilePos
can be used to check that a value is of this data type.
def data = { 1; ^FilePos[2]}
def output(x) { data(x) and FilePos(x)}
The relation load_csv
that loads CSV data into the system automatically generates FilePos
values that identify the row of the CSV file.
def config:data = """
item, category
laptop, computer
monitor, peripheral
"""
//FilePos automatically generated
def csv = load_csv[config]
def output = csv
def csv_ic {
subset(csv, (RelName, FilePos, String))
}
UUID
UUID(x)
^UUID(y, x)
The data type UUID
.
The type relation UUID(x)
checks whether x
is of type UUID
.
The constructor ^UUID(x, y)
maps a UInt128, y
, to its corresponding UUID
value, x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | UUID | UUID variable. |
y | UInt128 | The value of the UUID data type. |
Explanation
UUID
is an efficient representation of UUID values (compared to treating UUIDs as
strings). Compared to a plain UInt128, it provides tools with the information to format
and treat the value as a UUID.
To use rel:base:UUID
or rel:base:^UUID
the full name must be used or abbreviated
as with rel:base use UUID, ^UUID
. The relations UUID
and ^UUID
are not
available as an alias without rel:base
.
Examples
A UUID
value can be created with the constructor ^UUID
with a UInt128
argument:
with rel:base use ^UUID
def output = ^UUID[0x8f9924a8494741e80c464d9df14fe1d0]
//output> (:rel, :base, :UUID, 190874768316354382993454873408336552400)
To create a UUID from a string, use uuid_from_string
:
with rel:base use uuid_from_string
def output = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
//output> (:rel, :base, :UUID, 32314330545176713121947364484890423080)
To format UUID
as a standard UUID string, use string
.
with rel:base use uuid_from_string
def example = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
def output = string[example]
//output> "184f8380-ba48-494a-9d77-2f410c9aef28"
The constructor can be used to extract the integer value “back out” of the value type.
with rel:base use uuid_from_string, ^UUID
def example = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
def output(i) = exists(x: ^UUID(i, x) and example(x))
//output> 32314330545176713121947364484890423080
The type relation UUID
can be used to check that a value is of this data type.
with rel:base use uuid_from_string, UUID
def example = uuid_from_string["184f8380-ba48-494a-9d77-2f410c9aef28"]
def data = 1; example
def output(x) = data(x) and UUID(x)
//output> (:rel, :base, :UUID, 32314330545176713121947364484890423080)
The UUID value type is used by load_csv
for columns with schema "uuid"
:
def config:data = """
A,B
1,b3b8a827-685f-4239-b0b3-afc41dfdc75c
2,6c8440c6-c441-4c75-9d36-1deb97f734ea
3,72327575-620b-4540-b13b-bdfe8e3ea24c
"""
def config:schema:A = "int"
def config:schema:B = "uuid"
def output = load_csv[config]
// output>
// (:A, 2, 1)
// (:A, 3, 2)
// (:A, 4, 3)
// (:B, 2, (:rel, :base, :UUID, 238890604434483702785039736746549299036))
// (:B, 3, (:rel, :base, :UUID, 144243320552226326224531778065386648810))
// (:B, 4, (:rel, :base, :UUID, 151793988704368948489985156409689285196))
JSON export formats UUID values automatically to the standard string representation.
uuid_from_string
uuid_from_string(s in String, x in UUID)
Parse a UUID string (in the standard 8-4-4-4-12 format) to a UUID value.
Example:
with rel:base use uuid_from_string
def output = uuid_from_string["22b4a8a1-e548-4eeb-9270-60426d66a48e"]
//output> (:rel, :base, :UUID, 46131785562730469527277340045557015694)
SHA1
SHA1(x)
^SHA1(a in UInt128, b in UInt32, x)
The data type SHA1
.
The type relation SHA1(x)
checks whether x
is of type SHA1
.
The constructor ^SHA1(a, b, x)
maps a UInt128 a
and a UInt32 b
to the SHA1
value x
.
Parameters
Parameter | Type | Description |
---|---|---|
x | SHA1 | SHA1 variable. |
a | UInt128 | The first 128 bits of the 160 bits SHA-1 value. |
b | UInt32 | The last 32 bits of the 160 bits SHA-1 value. |
Explanation
SHA1
is an efficient representation of SHA-1 values (compared to treating SHA-1 as
strings). The value type provides tools with the information to format and treat the
value as a SHA-1 hash.
To use rel:base:SHA1
or rel:base:^SHA1
the full name must be used or abbreviated
as with rel:base use SHA1, ^SHA1
. The relations SHA1
and ^SHA1
are not
available as an alias without rel:base
.
Examples
A SHA1
value can be created with the constructor, though it requires passing in the
two separate parameters. SHA-1 uses 160 bits and Rel does not have 160-bit integer type.
with rel:base use ^SHA1
def output = ^SHA1[0x0d7d4a744fd92effd1ed88e48ac8231e, 0x7f7e9e6c]
//output> (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524)
To format SHA1
as a standard hexadecimal string, use string
.
with rel:base use ^SHA1
def example = ^SHA1[0x0d7d4a744fd92effd1ed88e48ac8231e, 0x7f7e9e6c]
def output = string[example]
//output> "0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c"
The type relation SHA1
can be used to check that a value is of this data type.
with rel:base use SHA1, sha1_from_string
def example = sha1_from_string["0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c"]
def data = 1; example
def output(x) = data(x) and SHA1(x)
//output> (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524)
The SHA1
value type is used by load_csv
for columns with schema "sha-1"
:
def config:data = """
A,B
1,0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c
2,10bb3e970ba01ec67439f1764da9ff43b5a7edd5
3,187ca6345d5d759f23d37e5060e023b9888cbbd7
"""
def config:schema:A = "int"
def config:schema:B = "sha-1"
def output = load_csv[config]
//output>
// (:A, 2, 1)
// (:A, 3, 2)
// (:A, 4, 3)
// (:B, 2, (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524))
// (:B, 3, (:rel, :base, :SHA1, 22239876921550541361475316713022684995, 3047681493))
// (:B, 4, (:rel, :base, :SHA1, 32548687738050047961766682367612691385, 2290924503))
JSON export formats SHA-1 values automatically to the standard string representation.
sha1_from_string
sha1_from_string(s in String, v in SHA1)
Parse a SHA-1 string (in hexadecimal format) to a SHA1 value.
Example:
with rel:base use sha1_from_string
def output = sha1_from_string["0d7d4a744fd92effd1ed88e48ac8231e7f7e9e6c"]
//output> (:rel, :base, :SHA1, 17930511166010156306237819770844488478, 2139004524)
Date
Date(d)
^Date(n, d)
The Date
data type representing a date in days of the proleptic Gregorian calendar.
The type relation Date
checks if d
is of type Date
.
The constructor ^Date
creates a date d
of n
days in the
Gregorian calendar starting at 0000-12-31
, which is “day 0”.
Parameters
Parameter | Type | Description |
---|---|---|
d | Date | Date variable. |
n | Integer | The value of the Date data type, in days of the Gregorian calendar. |
Explanation
To use the ^Date(n, d)
constructor, one has to specify all arguments and partial application, ^Date[n]
, can’t be used due to the overloaded nature of the ^Date
constructor.
Examples
Construct a date from the duration in days.
def output(d) = ^Date(734638, d) // 734638 days since 0000-12-31
//output> 2012-05-15
Construct a date from its parts (year, month, day).
^Date[2012, 5, 15]
//output> 2012-05-15
Subtract two date literals. The result is of type Day
.
def output = 2012-06-15 - 2012-05-15
//output> 31
DateTime
DateTime(dt)
^DateTime(n, dt)
The DateTime
data type representing an instant in milliseconds of the proleptic
Gregorian calendar.
The type relation DateTime
checks if dt
is of type DateTime
.
The constructor ^DateTime
creates an instant d
of n
milliseconds in the
Gregorian calendar, where the reference timestamp 0000-12-31T00:00:00Z
.
Parameters
Parameter | Type | Description |
---|---|---|
dt | DateTime | DateTime variable. |
n | Integer | The value of the DateTime data type, in milliseconds of the Gregorian calendar. |
Explanation
To use the ^DateTime(n, d)
constructor, one has to specify all arguments and partial application, ^DateTime[n]
, can’t be used due to the overloaded nature of the ^DateTime
constructor.
Examples
Construct a datetime from the duration in milliseconds.
def output(dt) = ^DateTime(63472766399000, dt)
//output> 2012-05-15T11:59:59.000Z
Construct a datetime from its parts (year, month, day, hour, minute, second, millisecond, timezone).
^DateTime[2012, 5, 15, 11, 59, 59, 0, "UTC"]
//output> 2012-05-15T11:59:59.000Z
Subtract two datetime literals. The result is of type Millisecond
.
def output = 2012-05-15T00:00:00Z - 2012-05-14T00:00:00Z
//output> 86400000
Year
Year(p)
^Year(n, p)
A period that spans n
years. The period is given in units of Year
.
The type relation rel:base:Year
checks if p
is of type Year
.
The constructor ^Year
maps the integer n
to the corresponding Year
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Year | A period representing n years. |
n | Integer | The number of the years represented by p . |
Explanation
To use the rel:base:Year(p)
type relation, one must include the rel:base
module name.
Examples
Add 10 years to a datetime.
datetime_add[unix_epoch, ^Year[10]]
//output> 1980-01-01T00:00:00.000Z
Add two Year
periods together.
def output = ^Year[10] + ^Year[2]
//output> 12
Month
Month(p)
^Month(n, p)
A period that spans n
months. The period is given in units of Month
.
The type relation rel:base:Month
checks if p
is of type Month
.
The constructor ^Month
maps the integer n
to the corresponding Month
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Month | A period representing n months. |
n | Integer | The number of the months represented by p . |
Explanation
To use the rel:base:Month(p)
type relation, one must include the rel:base
module name.
Examples
Add 10 months to a datetime.
datetime_add[unix_epoch, ^Month[10]]
//output> 1970-11-01T00:00:00.000Z
Add two Month
periods together.
def output = ^Month[10] + ^Month[2]
//output> 12
Week
Week(p)
^Week(n, p)
A period that spans n
weeks. The period is given in units of Week
.
The type relation rel:base:Week
checks if p
is of type Week
.
The constructor ^Week
maps the integer n
to the corresponding Week
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Week | A period representing n weeks. |
n | Integer | The number of the weeks represented by p . |
Explanation
To use the rel:base:Week(p)
type relation, one must include the rel:base
module name.
Examples
Add 10 weeks to a datetime.
datetime_add[unix_epoch, ^Week[10]]
//output> 1970-03-12T00:00:00.000Z
Add two Week
periods together.
def output = ^Week[10] + ^Week[2]
//output> 12
Day
Day(p)
^Day(n, p)
A period that spans n
days. The period is given in units of Day
.
The type relation rel:base:Day
checks if p
is of type Day
.
The constructor ^Day
maps the integer n
to the corresponding Day
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Day | A period representing n days. |
n | Integer | The number of the days represented by p . |
Explanation
To use the rel:base:Day(p)
type relation, one must include the rel:base
module name.
Examples
Add 10 days to a datetime.
datetime_add[unix_epoch, ^Day[10]]
//output> 1970-01-11T00:00:00.000Z
Add two Day
periods together.
def output = ^Day[10] + ^Day[2]
//output> 12
Hour
Hour(p)
^Hour(n, p)
A period that spans n
hours. The period is given in units of Hour
.
The type relation rel:base:Hour
checks if p
is of type Hour
.
The constructor ^Hour
maps the integer n
to the corresponding Hour
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Hour | A period representing n hours. |
n | Integer | The number of the hours represented by p . |
Explanation
To use the rel:base:Hour(p)
type relation, one must include the rel:base
module name.
Examples
Add 10 hours to a datetime.
datetime_add[unix_epoch, ^Hour[10]]
//output> 1970-01-01T10:00:00.000Z
Add two Hour
periods together.
def output = ^Hour[10] + ^Hour[2]
//output> 12
Minute
Minute(p)
^Minute(n, p)
A period that spans n
minutes. The period is given in units of Minute
.
The type relation rel:base:Minute
checks if p
is of type Minute
.
The constructor ^Minute
maps the integer n
to the corresponding Minute
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Minute | A period representing n minutes. |
n | Integer | The number of the minutes represented by p . |
Explanation
To use the rel:base:Minute(p)
type relation, one must include the rel:base
module name.
Examples
Add 100 minutes to a datetime.
datetime_add[unix_epoch, ^Minute[100]]
//output> 1970-01-01T01:40:00.000Z
Add two Minute
periods together.
def output = ^Minute[10] + ^Minute[2]
//output> 12
Second
Second(p)
^Second(n, p)
A period that spans n
seconds. The period is given in units of Second
.
The type relation rel:base:Second
checks if p
is of type Second
.
The constructor ^Second
maps the integer n
to the corresponding Second
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Second | A period representing n seconds. |
n | Integer | The number of the seconds represented by p . |
Explanation
To use the rel:base:Second(p)
type relation, one must include the rel:base
module name.
Examples
Add 100 seconds to a datetime.
datetime_add[unix_epoch, ^Second[100]]
//output> 1970-01-01T00:01:40.000Z
Add two Second
periods together.
def output = ^Second[10] + ^Second[2]
//output> 12
Millisecond
Millisecond(p)
^Millisecond(n, p)
A period that spans n
milliseconds. The period is given in units of Millisecond
( seconds).
The type relation rel:base:Millisecond
checks if p
is of type Millisecond
.
The constructor ^Millisecond
maps the integer n
to the corresponding Millisecond
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Millisecond | A period representing n milliseconds. |
n | Integer | The number of the milliseconds represented by p . |
Explanation
To use the rel:base:Millisecond(p)
type relation, one must include the rel:base
module name.
Examples
Add 20 thousand milliseconds (aka 20 s) to a datetime.
datetime_add[unix_epoch, ^Millisecond[20 * 10^3]]
//output> 1970-01-01T00:00:20.000Z
Add two Millisecond
periods together.
def output = ^Millisecond[10] + ^Millisecond[2]
//output> 12
Microsecond
Microsecond(p)
^Microsecond(n, p)
A period that spans n
microseconds. The period is given in units of Microsecond
( seconds).
The type relation rel:base:Microsecond
checks if p
is of type Microsecond
.
The constructor ^Microsecond
maps the integer n
to the corresponding Microsecond
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Microsecond | A period representing n microseconds. |
n | Integer | The number of the microseconds represented by p . |
Explanation
To use the rel:base:Microsecond(p)
type relation, one must include the rel:base
module name.
Examples
Add 5 million microseconds (aka 5 s) to a datetime.
datetime_add[unix_epoch, ^Microsecond[5 * 10^6]]
//output> 1970-01-01T00:00:05.000Z
Add two Microsecond
periods together.
def output = ^Microsecond[10] + ^Microsecond[2]
//output> 12
Nanosecond
Nanosecond(p)
^Nanosecond(n, p)
A period that spans n
nanoseconds. The period is given in units of Nanosecond
( seconds).
The type relation rel:base:Nanosecond
checks if p
is of type Nanosecond
.
The constructor ^Nanosecond
maps the integer n
to the corresponding Nanosecond
period p
.
Parameters
Parameter | Type | Description |
---|---|---|
p | Nanosecond | A period representing n nanoseconds. |
n | Integer | The number of the nanoseconds represented by p . |
Explanation
To use the rel:base:Nanosecond(p)
type relation, one must include the rel:base
module name.
Examples
Add 20 million nanoseconds (aka 20 ms) to a datetime.
def dt = parse_datetime["2020-01-01 01:00:00.001", "Y-m-d H:M:S.sss"]
def output = dt + ^Nanosecond[20 * 10^6]
//output> 2020-01-01T01:00:00.021.000Z
Add two Nanosecond
periods together.
def output = ^Nanosecond[10] + ^Nanosecond[2]
//output> 12
Module: rel:base
FixedDecimal
FixedDecimal(v)
^FixedDecimal[bits, precision]
^FixedDecimal(bits, precision, v)
Data type of fixed precision numbers with the type relation FixedDecimal
and the constructor ^FixedDecimal
.
bits
is the width of the integer type used to back the fixed decimal,
precision
is the number of decimal places, and v
is the integer
representation of the fixed decimal. v
must fit into a bits
-wide
integer.
The integer representation of a fixed decimal is that number multiplied
by 10 ^ precision
. For example, to represent the number 2.3 with a
precision of 3, we would use 2.3 * (10 ^ 3) = 2300
.
Other constructors like decimal
and parse_decimal
are a simpler
way to construct a FixedDecimal
.
Examples
Construct a 32-bit FixedDecimal
with a precision of 3 decimal places equivalent to 5.5.
def output = rel:base:^FixedDecimal[#32, #3, 5500]
//output> (:rel, :base, :FixedDecimal, #32, #3, 5500)
Attempt to construct a 8-bit FixedDecimal
with a precision of 2 decimal places representing 200.
def output = rel:base:^FixedDecimal[#8, #2, 20000]
//output> {} // produces empty output as 20000 is too large to fit into an 8-bit integer.
Check values are fixed decimals:
with rel:base use ^FixedDecimal, FixedDecimal
def output = FixedDecimal(^FixedDecimal[#8, #1, 1])
//output> () // true
def output = FixedDecimal(^FixedDecimal[#32, #3, 5500])
//output> () // true
def output = FixedDecimal(decimal[#32, #3, 5.5])
//output> () // true
def output = FixedDecimal(parse_decimal[#32, #3, "5.5"])
//output> () // true
def output = FixedDecimal(5.5)
//output> {} // false, the provided value is a Float
Module: rel:bignum
BigInteger
Type for arbitrary precision integers.
A Rel representation of the GMP integer type, as in https://gmplib.org/manual/Integer-Internals (opens in a new tab)
The Int8 is a sign (+/- 1) and the String is GMP’s “array of limbs” (a little-endian byte representation of abs(x)):