combine_rel
Relational functions combine_rel, first_rel, second_rel, …, sixteenth_rel
combine_rel(x_rel, position) and first_rel(x_rel) to sixteenth_rel(x_rel) give, for each element of x_rel, the relation to one factor of the Combined Domain unit that x_rel refers to: the inverse of Combine_data.
syntax
- combine_rel(x_rel, position)
- first_rel(x_rel), second_rel(x_rel), third_rel(x_rel), fourth_rel(x_rel), fifth_rel(x_rel), sixth_rel(x_rel), seventh_rel(x_rel), eighth_rel(x_rel), ninth_rel(x_rel), tenth_rel(x_rel), eleventh_rel(x_rel), twelfth_rel(x_rel), thirteenth_rel(x_rel), fourteenth_rel(x_rel), fifteenth_rel(x_rel), sixteenth_rel(x_rel)
definition
combine_rel(x_rel, position) results in an Attribute with the Domain unit of x_rel and as Values unit the factor at position of the Combine that made the values unit of x_rel. Positions count from 0: first_rel(x_rel) is combine_rel(x_rel, 0), second_rel(x_rel) is combine_rel(x_rel, 1), and so on up to sixteenth_rel(x_rel), which is combine_rel(x_rel, 15).
description
A unit X := combine(A, B, C) numbers its elements with the last factor varying fastest: the element with Index numbers a, b and c in A, B and C is ((a × #B) + b) × #C + c. Combine_data computes that element from one relation per factor; combine_rel and first_rel to sixteenth_rel compute the relations back.
They work per element of x_rel and hold no data over X, so they also work for a combined unit of 1012 elements or more. That is what sets them apart from the subitems first_rel, second_rel, … that Combine gives X: those are attributes over the whole of X, so X/second_rel[x_rel] calculates an attribute of #A × #B elements to look up a few of them, and combine_unit_uint8_16_32_64 does not make them at all.
So instead of decoding a combined relation with index arithmetic:
attribute<Time> time_rel (Dep) := value(x_rel / uint64(#Places), Time);
attribute<Places> place_rel (Dep) := value(x_rel % uint64(#Places), Places);
write:
attribute<Time> time_rel (Dep) := first_rel(x_rel);
attribute<Places> place_rel (Dep) := second_rel(x_rel);
The order of the factors is then stated once, in the definition of X, and not again in the choice between / and % and in the divisor of each place that decodes.
- A factor whose range does not start at 0, or a factor with a point value type such as a grid domain, gets its own values back, not index numbers.
- With a nested combine, X := combine_unit(A, combine_unit(B, C)), second_rel(x_rel) is the relation to combine_unit(B, C), and first_rel and second_rel of that are the relations to B and C.
- A null in x_rel gives null, and so does a value outside X, as with Lookup. A factor of value type bool has no null value: there it gives false.
applies to
- x_rel: Attribute or Parameter with a values unit made by Combine, Combine_uint8_16_32_64, combine_unit or combine_unit_uint8_16_32_64, of value type uint8, uint16, uint32 or uint64.
- position: Parameter of value type uint32 whose value is known when the configuration is read.
conditions
- The values unit of x_rel must be made by a combine function, or be a unit that refers to one. A unit with the same number of elements made otherwise, by Unique or Range or read from a storage, has no factors, and an error says so.
- position must be less than the number of factors.
since version
20.24.0
performance
O(n) where n = number of elements in the domain of x_rel: one division and one remainder per element.
example
unit<uint32> City : nrofrows = 3;
unit<uint32> Year : nrofrows = 2;
unit<uint64> CityYear := combine_unit_uint64(City, Year);
attribute<CityYear> cityyear_rel (Visit) := combine_data(CityYear, city_rel, year_rel);
attribute<City> city_back (Visit) := first_rel(cityyear_rel); // equals city_rel
attribute<Year> year_back (Visit) := second_rel(cityyear_rel); // equals year_rel
| city_rel | year_rel | cityyear_rel | city_back | year_back |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 1 | 3 | 1 | 1 |
| 2 | 0 | 4 | 2 | 0 |
| null | 1 | null | null | null |
domain Visit, nr of rows = 5