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

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

see also