Sorting for plain Fortran arrays and for this library's own column types.
This module is the public face of the radix engine that orders everything this library
sorts: a read-time parquet_open_reader(..., sort_by=), a post-open parquet_reader_set_sort,
parquet_table%sort_by, and a raw-array pf_sort/pf_argsort alike. Sharing one engine is
the point: those paths can never disagree about where nulls go, where NaNs go, or how ties are
broken, because there is only one answer to disagree about.
The ordering reproduces arrow::compute::SortIndices exactly, and a second, independent C++
implementation is kept in src/parquet_wrapper.cpp purely so the tests can check this one
against it -- see that file's sort-engine banner. No user-facing path reaches it.
Naming. Everything public here carries the pf_ prefix (parquet-fortran) rather than
parquet_, because the subject is not a parquet file -- see CLAUDE.md's "Naming
conventions". The module is parquet_sorting rather than parquet_sort because a module
cannot share its name with a procedure it declares.
Four operations, over eleven element types:
pf_argsort(values, perm) -- the permutation that would sort values. Never modifies it.
pf_sort(values, sorted) -- an independent sorted copy. Never modifies its input.
pf_permute(values, perm) -- applies a permutation to values IN PLACE.
pf_is_sorted(values, answer) -- whether values is already in the stated order.
Ordering reproduces arrow::compute::SortIndices exactly. Null and NaN placement is
absolute: descending reverses the values, never the tiers. Ascending gives values, then
NaNs, then nulls; nulls_first=.true. gives nulls, then NaNs, then values. Ties always keep
their original order -- every sort here is stable, unconditionally, so there is no
stable= argument to pass.
Where nullness comes from depends on the type. The six types with no null state of their
own (integer, real, logical, character) take an optional is_valid(:) mask; the
temporal types and the two column types carry their own and take no such argument.
Sorting one column of a table desynchronises it. %col hands back a writable pointer
into a table's live storage, so call pf_permute(p, perm) on it reorders that column and
leaves every other column where it was, silently breaking row correspondence. Use
parquet_table%sort_by, which reorders every column together.
Interfaces
Extends parquet_argsort's pf_argsort with the element types that need a parquet
column, a packed string store or a temporal element, and with the multi-key form.
-
private interface argsort_date_i32()
Arguments
None
-
private interface argsort_date_i64()
Arguments
None
-
private interface argsort_time_i32()
Arguments
None
-
private interface argsort_time_i64()
Arguments
None
-
private interface argsort_ts_i32()
Arguments
None
-
private interface argsort_ts_i64()
Arguments
None
-
private interface argsort_strcol_i32()
Arguments
None
-
private interface argsort_strcol_i64()
Arguments
None
-
private interface argsort_col_i32()
Arguments
None
-
private interface argsort_col_i64()
Arguments
None
-
private interface argsort_keys_i32()
Arguments
None
-
private interface argsort_keys_i64()
Arguments
None
An independent sorted copy of values, leaving values untouched.
Deliberately not defined for parquet_string_column or parquet_column: copying a
whole column to sort it serves no purpose, and reordering one in place is
pf_argsort followed by pf_permute, which says what it does at the call site.
-
private interface sort_i32()
Arguments
None
-
private interface sort_i64()
Arguments
None
-
private interface sort_f32()
Arguments
None
-
private interface sort_f64()
Arguments
None
-
private interface sort_bool()
Arguments
None
-
private interface sort_chr()
Arguments
None
-
private interface sort_date()
Arguments
None
-
private interface sort_time()
Arguments
None
-
private interface sort_ts()
Arguments
None
Applies perm to values IN PLACE: afterwards element k is what was at perm(k).
perm itself is not modified.
perm is validated as a true permutation of 1..n before anything is written, since an
invalid one would silently duplicate some elements and drop others. Pass
assume_valid=.true. to skip that check when the permutation came from pf_argsort
and is known good -- it means the same thing for all eleven types, the two column ones
included.
assume_valid skips the O(n) contents check only. perm's LENGTH is checked either
way, because a short permutation would make the gather read past the end of values and
no promise from the caller can make that defined.
-
private interface permute_i32_i32()
Arguments
None
-
private interface permute_i32_i64()
Arguments
None
-
private interface permute_i64_i32()
Arguments
None
-
private interface permute_i64_i64()
Arguments
None
-
private interface permute_f32_i32()
Arguments
None
-
private interface permute_f32_i64()
Arguments
None
-
private interface permute_f64_i32()
Arguments
None
-
private interface permute_f64_i64()
Arguments
None
-
private interface permute_bool_i32()
Arguments
None
-
private interface permute_bool_i64()
Arguments
None
-
private interface permute_chr_i32()
Arguments
None
-
private interface permute_chr_i64()
Arguments
None
-
private interface permute_date_i32()
Arguments
None
-
private interface permute_date_i64()
Arguments
None
-
private interface permute_time_i32()
Arguments
None
-
private interface permute_time_i64()
Arguments
None
-
private interface permute_ts_i32()
Arguments
None
-
private interface permute_ts_i64()
Arguments
None
-
private interface permute_strcol_i32()
Arguments
None
-
private interface permute_strcol_i64()
Arguments
None
-
private interface permute_col_i32()
Arguments
None
-
private interface permute_col_i64()
Arguments
None
Whether values is already in the stated order. O(n) with an early exit, and no copy.
Uses the same comparison pf_sort does, so the two can never disagree about nulls,
NaNs or direction on one array. A run of equal values is sorted.
-
private interface is_sorted_i32()
Arguments
None
-
private interface is_sorted_i64()
Arguments
None
-
private interface is_sorted_f32()
Arguments
None
-
private interface is_sorted_f64()
Arguments
None
-
private interface is_sorted_bool()
Arguments
None
-
private interface is_sorted_chr()
Arguments
None
-
private interface is_sorted_date()
Arguments
None
-
private interface is_sorted_time()
Arguments
None
-
private interface is_sorted_ts()
Arguments
None
-
private interface is_sorted_strcol()
Arguments
None
-
private interface is_sorted_col()
Arguments
None
-
private interface is_sorted_keys()
Arguments
None
The permutation that would sort the FIRST n elements of values, without ordering
the rest. perm comes back with exactly n entries (fewer if the array is shorter).
n is CLAMPED to the array size rather than being an error, so a caller whose n is
derived -- a fraction of a row count, a config value, a post-filter survivor count --
needs no min(n, size(v)) of their own. A negative n is still an error.
"The last n" is descending=.true., not a separate procedure.
-
private interface partial_argsort_i32_i32()
Arguments
None
-
private interface partial_argsort_i32_i64()
Arguments
None
-
private interface partial_argsort_i64_i32()
Arguments
None
-
private interface partial_argsort_i64_i64()
Arguments
None
-
private interface partial_argsort_f32_i32()
Arguments
None
-
private interface partial_argsort_f32_i64()
Arguments
None
-
private interface partial_argsort_f64_i32()
Arguments
None
-
private interface partial_argsort_f64_i64()
Arguments
None
-
private interface partial_argsort_bool_i32()
Arguments
None
-
private interface partial_argsort_bool_i64()
Arguments
None
-
private interface partial_argsort_chr_i32()
Arguments
None
-
private interface partial_argsort_chr_i64()
Arguments
None
-
private interface partial_argsort_date_i32()
Arguments
None
-
private interface partial_argsort_date_i64()
Arguments
None
-
private interface partial_argsort_time_i32()
Arguments
None
-
private interface partial_argsort_time_i64()
Arguments
None
-
private interface partial_argsort_ts_i32()
Arguments
None
-
private interface partial_argsort_ts_i64()
Arguments
None
-
private interface partial_argsort_strcol_i32()
Arguments
None
-
private interface partial_argsort_strcol_i64()
Arguments
None
-
private interface partial_argsort_col_i32()
Arguments
None
-
private interface partial_argsort_col_i64()
Arguments
None
-
private interface partial_argsort_keys_i32()
Arguments
None
-
private interface partial_argsort_keys_i64()
Arguments
None
The first n elements of values in order, as an independent copy of length n.
Same clamping rule as pf_partial_argsort. Never modifies its input.
Cheaper than pf_sort only while n stays well below the array size -- the underlying
std::partial_sort degrades past a full sort as n approaches it. At n = size this
is strictly worse than calling pf_sort.
-
private interface partial_sort_i32()
Arguments
None
-
private interface partial_sort_i64()
Arguments
None
-
private interface partial_sort_f32()
Arguments
None
-
private interface partial_sort_f64()
Arguments
None
-
private interface partial_sort_bool()
Arguments
None
-
private interface partial_sort_chr()
Arguments
None
-
private interface partial_sort_date()
Arguments
None
-
private interface partial_sort_time()
Arguments
None
-
private interface partial_sort_ts()
Arguments
None
The element a full sort would place at 1-based rank nth, without sorting -- O(n)
rather than O(n log n). index optionally reports which element of values that was.
The reported index is the one a full STABLE sort would give. std::nth_element
normally leaves an arbitrary member of an equal-comparing run at that position; here
the comparator ends with a tiebreaker on the original index, making it a total order
under which no two elements compare equal, so the answer is deterministic and agrees
with pf_sort element for element.
nth counts NULLS too, placed by the same tier rules as the sort (last by default).
Takes descending/nulls_first/is_valid exactly as pf_argsort does.
-
private interface nth_i32_i32()
Arguments
None
-
private interface nth_i32_i32_i32()
Arguments
None
-
private interface nth_i32_i32_i64()
Arguments
None
-
private interface nth_i32_i64()
Arguments
None
-
private interface nth_i32_i64_i32()
Arguments
None
-
private interface nth_i32_i64_i64()
Arguments
None
-
private interface nth_i64_i32()
Arguments
None
-
private interface nth_i64_i32_i32()
Arguments
None
-
private interface nth_i64_i32_i64()
Arguments
None
-
private interface nth_i64_i64()
Arguments
None
-
private interface nth_i64_i64_i32()
Arguments
None
-
private interface nth_i64_i64_i64()
Arguments
None
-
private interface nth_f32_i32()
Arguments
None
-
private interface nth_f32_i32_i32()
Arguments
None
-
private interface nth_f32_i32_i64()
Arguments
None
-
private interface nth_f32_i64()
Arguments
None
-
private interface nth_f32_i64_i32()
Arguments
None
-
private interface nth_f32_i64_i64()
Arguments
None
-
private interface nth_f64_i32()
Arguments
None
-
private interface nth_f64_i32_i32()
Arguments
None
-
private interface nth_f64_i32_i64()
Arguments
None
-
private interface nth_f64_i64()
Arguments
None
-
private interface nth_f64_i64_i32()
Arguments
None
-
private interface nth_f64_i64_i64()
Arguments
None
-
private interface nth_bool_i32()
Arguments
None
-
private interface nth_bool_i32_i32()
Arguments
None
-
private interface nth_bool_i32_i64()
Arguments
None
-
private interface nth_bool_i64()
Arguments
None
-
private interface nth_bool_i64_i32()
Arguments
None
-
private interface nth_bool_i64_i64()
Arguments
None
-
private interface nth_chr_i32()
Arguments
None
-
private interface nth_chr_i32_i32()
Arguments
None
-
private interface nth_chr_i32_i64()
Arguments
None
-
private interface nth_chr_i64()
Arguments
None
-
private interface nth_chr_i64_i32()
Arguments
None
-
private interface nth_chr_i64_i64()
Arguments
None
-
private interface nth_date_i32()
Arguments
None
-
private interface nth_date_i32_i32()
Arguments
None
-
private interface nth_date_i32_i64()
Arguments
None
-
private interface nth_date_i64()
Arguments
None
-
private interface nth_date_i64_i32()
Arguments
None
-
private interface nth_date_i64_i64()
Arguments
None
-
private interface nth_time_i32()
Arguments
None
-
private interface nth_time_i32_i32()
Arguments
None
-
private interface nth_time_i32_i64()
Arguments
None
-
private interface nth_time_i64()
Arguments
None
-
private interface nth_time_i64_i32()
Arguments
None
-
private interface nth_time_i64_i64()
Arguments
None
-
private interface nth_ts_i32()
Arguments
None
-
private interface nth_ts_i32_i32()
Arguments
None
-
private interface nth_ts_i32_i64()
Arguments
None
-
private interface nth_ts_i64()
Arguments
None
-
private interface nth_ts_i64_i32()
Arguments
None
-
private interface nth_ts_i64_i64()
Arguments
None
-
private interface nth_strcol_i32()
Arguments
None
-
private interface nth_strcol_i32_i32()
Arguments
None
-
private interface nth_strcol_i32_i64()
Arguments
None
-
private interface nth_strcol_i64()
Arguments
None
-
private interface nth_strcol_i64_i32()
Arguments
None
-
private interface nth_strcol_i64_i64()
Arguments
None
The value at quantile (on a 0-1 scale, not 0-100) of the NON-NULL values.
index optionally reports which element that was; n_null how many were excluded.
Nulls are excluded from the population, not placed in it -- unlike every other
operation in this module, which is why this one takes neither descending nor
nulls_first: there is no null tier to position, and a descending quantile is just
1 - quantile.
rounding= selects how a fractional position is resolved: "nearest" (the default),
"down" or "up", matched case-insensitively. An unrecognized token aborts.
Aborts when EVERY value is null: there is no value to return, and no sentinel exists
across all ten types. n_null is for PARTIAL nullness; the all-null case never
reaches it. Guard with count(mask) (or a column's own null count) if that matters.
-
private interface quantile_i32()
Arguments
None
-
private interface quantile_i32_i32()
Arguments
None
-
private interface quantile_i32_i64()
Arguments
None
-
private interface quantile_i64()
Arguments
None
-
private interface quantile_i64_i32()
Arguments
None
-
private interface quantile_i64_i64()
Arguments
None
-
private interface quantile_f32()
Arguments
None
-
private interface quantile_f32_i32()
Arguments
None
-
private interface quantile_f32_i64()
Arguments
None
-
private interface quantile_f64()
Arguments
None
-
private interface quantile_f64_i32()
Arguments
None
-
private interface quantile_f64_i64()
Arguments
None
-
private interface quantile_bool()
Arguments
None
-
private interface quantile_bool_i32()
Arguments
None
-
private interface quantile_bool_i64()
Arguments
None
-
private interface quantile_chr()
Arguments
None
-
private interface quantile_chr_i32()
Arguments
None
-
private interface quantile_chr_i64()
Arguments
None
-
private interface quantile_date()
Arguments
None
-
private interface quantile_date_i32()
Arguments
None
-
private interface quantile_date_i64()
Arguments
None
-
private interface quantile_time()
Arguments
None
-
private interface quantile_time_i32()
Arguments
None
-
private interface quantile_time_i64()
Arguments
None
-
private interface quantile_ts()
Arguments
None
-
private interface quantile_ts_i32()
Arguments
None
-
private interface quantile_ts_i64()
Arguments
None
-
private interface quantile_strcol()
Arguments
None
-
private interface quantile_strcol_i32()
Arguments
None
-
private interface quantile_strcol_i64()
Arguments
None
The first position at which target could be inserted into an already-sorted
values without breaking its order -- i.e. the first element not ordered BEFORE it.
pos lands in 1 .. size(values)+1; it is size(values)+1 when every element is
ordered before the target. Together with pf_upper_bound it brackets every element
equal to the target, which is what pf_equal_range returns in one call.
values is checked for sortedness first, and that check is O(n). Searching an
unsorted array returns a plausible index with no symptom at all, so the check is on by
default. Check once with pf_is_sorted and pass assume_sorted=.true. in a loop:
call pf_is_sorted(v, ok) ! O(N), once
do k = 1, m
call pf_lower_bound(v, targets(k), pos, assume_sorted=.true.) ! O(log N) each
end do
descending/nulls_first must describe the order values is ACTUALLY in -- they
select the comparison, they do not reorder anything.
-
private interface lower_bound_i32_i32()
Arguments
None
-
private interface lower_bound_i32_i64()
Arguments
None
-
private interface lower_bound_i64_i32()
Arguments
None
-
private interface lower_bound_i64_i64()
Arguments
None
-
private interface lower_bound_f32_i32()
Arguments
None
-
private interface lower_bound_f32_i64()
Arguments
None
-
private interface lower_bound_f64_i32()
Arguments
None
-
private interface lower_bound_f64_i64()
Arguments
None
-
private interface lower_bound_bool_i32()
Arguments
None
-
private interface lower_bound_bool_i64()
Arguments
None
-
private interface lower_bound_chr_i32()
Arguments
None
-
private interface lower_bound_chr_i64()
Arguments
None
-
private interface lower_bound_date_i32()
Arguments
None
-
private interface lower_bound_date_i64()
Arguments
None
-
private interface lower_bound_time_i32()
Arguments
None
-
private interface lower_bound_time_i64()
Arguments
None
-
private interface lower_bound_ts_i32()
Arguments
None
-
private interface lower_bound_ts_i64()
Arguments
None
-
private interface lower_bound_strcol_i32()
Arguments
None
-
private interface lower_bound_strcol_i64()
Arguments
None
The first position at which target is ordered BEFORE the element there -- i.e. one
past the last element equal to the target.
Same arguments, same sortedness rule and same 1 .. size(values)+1 range as
pf_lower_bound; pf_upper_bound - pf_lower_bound is how many elements equal the
target.
-
private interface upper_bound_i32_i32()
Arguments
None
-
private interface upper_bound_i32_i64()
Arguments
None
-
private interface upper_bound_i64_i32()
Arguments
None
-
private interface upper_bound_i64_i64()
Arguments
None
-
private interface upper_bound_f32_i32()
Arguments
None
-
private interface upper_bound_f32_i64()
Arguments
None
-
private interface upper_bound_f64_i32()
Arguments
None
-
private interface upper_bound_f64_i64()
Arguments
None
-
private interface upper_bound_bool_i32()
Arguments
None
-
private interface upper_bound_bool_i64()
Arguments
None
-
private interface upper_bound_chr_i32()
Arguments
None
-
private interface upper_bound_chr_i64()
Arguments
None
-
private interface upper_bound_date_i32()
Arguments
None
-
private interface upper_bound_date_i64()
Arguments
None
-
private interface upper_bound_time_i32()
Arguments
None
-
private interface upper_bound_time_i64()
Arguments
None
-
private interface upper_bound_ts_i32()
Arguments
None
-
private interface upper_bound_ts_i64()
Arguments
None
-
private interface upper_bound_strcol_i32()
Arguments
None
-
private interface upper_bound_strcol_i64()
Arguments
None
The INCLUSIVE range first .. last of elements equal to target, from one pass.
first is pf_lower_bound's answer and last is pf_upper_bound's minus one, so a
target that is absent comes back with last == first - 1 and last - first + 1 == 0.
Do not read values(first) without checking that count first.
Cheaper than calling the two bounds separately: the values are extracted once.
-
private interface equal_range_i32_i32()
Arguments
None
-
private interface equal_range_i32_i64()
Arguments
None
-
private interface equal_range_i64_i32()
Arguments
None
-
private interface equal_range_i64_i64()
Arguments
None
-
private interface equal_range_f32_i32()
Arguments
None
-
private interface equal_range_f32_i64()
Arguments
None
-
private interface equal_range_f64_i32()
Arguments
None
-
private interface equal_range_f64_i64()
Arguments
None
-
private interface equal_range_bool_i32()
Arguments
None
-
private interface equal_range_bool_i64()
Arguments
None
-
private interface equal_range_chr_i32()
Arguments
None
-
private interface equal_range_chr_i64()
Arguments
None
-
private interface equal_range_date_i32()
Arguments
None
-
private interface equal_range_date_i64()
Arguments
None
-
private interface equal_range_time_i32()
Arguments
None
-
private interface equal_range_time_i64()
Arguments
None
-
private interface equal_range_ts_i32()
Arguments
None
-
private interface equal_range_ts_i64()
Arguments
None
-
private interface equal_range_strcol_i32()
Arguments
None
-
private interface equal_range_strcol_i64()
Arguments
None
How many DISTINCT non-null values values holds. n_null optionally reports how many
were null.
Nulls are excluded from the population, not counted as one value -- the same rule
pf_nth_quantile follows, and the reason this takes neither descending (a count does
not depend on direction) nor nulls_first (there is no null tier to place).
Distinctness is the sort comparator's own equality, so on a floating-point array it is
EXACT: 0.1 + 0.2 and 0.3 are two distinct values. Every NaN counts as one value,
collectively, since NaNs compare equal to each other here (they do not under ==).
-
private interface unique_count_i32_i32()
Arguments
None
-
private interface unique_count_i32_i64()
Arguments
None
-
private interface unique_count_i64_i32()
Arguments
None
-
private interface unique_count_i64_i64()
Arguments
None
-
private interface unique_count_f32_i32()
Arguments
None
-
private interface unique_count_f32_i64()
Arguments
None
-
private interface unique_count_f64_i32()
Arguments
None
-
private interface unique_count_f64_i64()
Arguments
None
-
private interface unique_count_bool_i32()
Arguments
None
-
private interface unique_count_bool_i64()
Arguments
None
-
private interface unique_count_chr_i32()
Arguments
None
-
private interface unique_count_chr_i64()
Arguments
None
-
private interface unique_count_date_i32()
Arguments
None
-
private interface unique_count_date_i64()
Arguments
None
-
private interface unique_count_time_i32()
Arguments
None
-
private interface unique_count_time_i64()
Arguments
None
-
private interface unique_count_ts_i32()
Arguments
None
-
private interface unique_count_ts_i64()
Arguments
None
-
private interface unique_count_strcol_i32()
Arguments
None
-
private interface unique_count_strcol_i64()
Arguments
None
-
private interface unique_count_col_i32()
Arguments
None
-
private interface unique_count_col_i64()
Arguments
None
The distinct non-null values of values, in order, as an independent copy.
Same distinctness rule as pf_unique_count -- exact for reals, all NaNs collapsing to
one. descending chooses the order the distinct values come back in; there is no
nulls_first, because nulls are excluded rather than placed.
Each distinct value is taken from its FIRST occurrence in the sorted order, which for
equal-comparing-but-not-identical values (a character array's trailing blanks, a
parquet_string_column's empty strings) is the earliest such element of values.
-
private interface unique_i32()
Arguments
None
-
private interface unique_i64()
Arguments
None
-
private interface unique_f32()
Arguments
None
-
private interface unique_f64()
Arguments
None
-
private interface unique_bool()
Arguments
None
-
private interface unique_chr()
Arguments
None
-
private interface unique_date()
Arguments
None
-
private interface unique_time()
Arguments
None
-
private interface unique_ts()
Arguments
None
-
private interface unique_strcol()
Arguments
None
The rank of every element of values, without reordering it. ranks(i) is the rank of
values(i), so this is a per-element answer rather than a permutation.
method= chooses how ties are handled, matched case-insensitively:
| token |
ranks of 10, 20, 20, 30 |
"competition" (the default) |
1, 2, 2, 4 |
"dense" |
1, 2, 2, 3 |
"ordinal" |
1, 2, 3, 4 |
A null gets rank 0, which is why this takes descending but NOT nulls_first: a
null has no rank at all, so there is no position for nulls_first to choose. NaNs are
ranked as ordinary values (all tying with each other), unlike nulls.
"ordinal" ranks are exactly the inverse of pf_argsort's permutation.
-
private interface rank_i32_i32()
Arguments
None
-
private interface rank_i32_i64()
Arguments
None
-
private interface rank_i64_i32()
Arguments
None
-
private interface rank_i64_i64()
Arguments
None
-
private interface rank_f32_i32()
Arguments
None
-
private interface rank_f32_i64()
Arguments
None
-
private interface rank_f64_i32()
Arguments
None
-
private interface rank_f64_i64()
Arguments
None
-
private interface rank_bool_i32()
Arguments
None
-
private interface rank_bool_i64()
Arguments
None
-
private interface rank_chr_i32()
Arguments
None
-
private interface rank_chr_i64()
Arguments
None
-
private interface rank_date_i32()
Arguments
None
-
private interface rank_date_i64()
Arguments
None
-
private interface rank_time_i32()
Arguments
None
-
private interface rank_time_i64()
Arguments
None
-
private interface rank_ts_i32()
Arguments
None
-
private interface rank_ts_i64()
Arguments
None
-
private interface rank_strcol_i32()
Arguments
None
-
private interface rank_strcol_i64()
Arguments
None
-
private interface rank_col_i32()
Arguments
None
-
private interface rank_col_i64()
Arguments
None
The smallest and largest value in values, skipping nulls and NaNs.
Takes no descending/nulls_first: a minimum and a maximum are absolute, and reversing
the order would only exchange the two answers.
Aborts when every value is null or NaN -- there is nothing to return, and no
sentinel exists across all nine types. This matches pf_nth_quantile's decision for the
same degenerate case; guard with count(is_valid) where that can happen.
Use pf_argminmax when the positions matter rather than the values.
-
private interface minmax_i32()
Arguments
None
-
private interface minmax_i64()
Arguments
None
-
private interface minmax_f32()
Arguments
None
-
private interface minmax_f64()
Arguments
None
-
private interface minmax_chr()
Arguments
None
-
private interface minmax_date()
Arguments
None
-
private interface minmax_time()
Arguments
None
-
private interface minmax_ts()
Arguments
None
-
private interface minmax_strcol()
Arguments
None
WHERE the smallest and largest value of values are: imin/imax are 1-based indices
into values, skipping nulls and NaNs.
The index-returning twin of pf_minmax, split off because Fortran cannot offer both
answers from one generic -- optional imin/imax varying only by integer kind would
make a positional call ambiguous. A caller wanting both pays one extra call.
Ties report the FIRST occurrence, which is the element a full stable sort would place at
either end. Aborts on an all-null-or-NaN input, exactly as pf_minmax does. Defined for
parquet_column as well, since an index needs no compile-time element type.
-
private interface argminmax_i32_i32()
Arguments
None
-
private interface argminmax_i32_i64()
Arguments
None
-
private interface argminmax_i64_i32()
Arguments
None
-
private interface argminmax_i64_i64()
Arguments
None
-
private interface argminmax_f32_i32()
Arguments
None
-
private interface argminmax_f32_i64()
Arguments
None
-
private interface argminmax_f64_i32()
Arguments
None
-
private interface argminmax_f64_i64()
Arguments
None
-
private interface argminmax_chr_i32()
Arguments
None
-
private interface argminmax_chr_i64()
Arguments
None
-
private interface argminmax_date_i32()
Arguments
None
-
private interface argminmax_date_i64()
Arguments
None
-
private interface argminmax_time_i32()
Arguments
None
-
private interface argminmax_time_i64()
Arguments
None
-
private interface argminmax_ts_i32()
Arguments
None
-
private interface argminmax_ts_i64()
Arguments
None
-
private interface argminmax_strcol_i32()
Arguments
None
-
private interface argminmax_strcol_i64()
Arguments
None
-
private interface argminmax_col_i32()
Arguments
None
-
private interface argminmax_col_i64()
Arguments
None
Merges two ALREADY-SORTED arrays into one sorted array, in O(size(a) + size(b)) rather
than the O(n log n) of sorting their concatenation.
descending/nulls_first must match the order a and b are actually in -- they
select the comparison, exactly as in the searches. Both inputs are checked for
sortedness unless assume_sorted=.true..
Supply is_valid_a/is_valid_b whenever either input has nulls. A sorted array
containing nulls is what pf_sort(..., is_valid=) produces, and a merge that is not told
which elements are null compares them as ordinary values and interleaves them into the
middle of the result. The precondition cannot be checked, either: a null's stored value
is indistinguishable from a real one without the mask.
merged_valid reports the result's validity and is ALWAYS allocated when asked for, all
.true. when neither input mask was supplied. Ties take from a first, so the result
matches pf_sort of the concatenation element for element.
-
private interface merge_i32()
Arguments
None
-
private interface merge_i64()
Arguments
None
-
private interface merge_f32()
Arguments
None
-
private interface merge_f64()
Arguments
None
-
private interface merge_bool()
Arguments
None
-
private interface merge_chr()
Arguments
None
-
private interface merge_date()
Arguments
None
-
private interface merge_time()
Arguments
None
-
private interface merge_ts()
Arguments
None
-
public module function parquet_debug_sort_row_less(keys, a, b) result(less)
Test-only view of what the Fortran SORT comparator says about one pair of rows.
Public only because it has to be: sort_key_buf is private to this module, so a
test cannot reach sort_row_less any other way, and the C++-side hook convention
is unavailable for a decision that Stage 1 exists to move out of C++. Not called by
library code. Rows are 1-based, as everywhere else in this module's public API.
Arguments
| Type |
Intent | Optional | Attributes |
|
Name |
|
|
type(pf_sort_keys),
|
intent(in) |
|
|
:: |
keys |
the built key set.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
a |
first row, 1-based.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
b |
second row, 1-based.
|
Return Value
logical
.true. when a sorts before b.
-
public module function parquet_debug_sort_keys_compare(keys, a, b, nkeys) result(c)
Test-only view of what the Fortran TIE-FREE comparator says about one pair of rows.
Same reasoning as parquet_debug_sort_row_less. nkeys counts ENGINE keys and is
clamped to how many the set holds; note a parquet_timestamp key binds as two.
Arguments
| Type |
Intent | Optional | Attributes |
|
Name |
|
|
type(pf_sort_keys),
|
intent(in) |
|
|
:: |
keys |
the built key set.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
a |
first row, 1-based.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
b |
second row, 1-based.
|
|
integer,
|
intent(in) |
|
|
:: |
nkeys |
leading engine keys taking part.
|
Return Value
integer
-1, 0 or +1.
-
public module function parquet_debug_sort_sweep_less(keys, nrows, nreps) result(count)
Test-only sweep of nreps passes of nrows comparisons, returning a checksum.
For bench/benchmark_sort_comparator.f90, which needs the comparator's own cost rather
than the cost of reaching it: at ~5 ns per comparison a per-call harness measures
its own overhead. The C++ twin is parquet_debug_sort_sweep_less_cpp in
src/parquet_wrapper.cpp and the two loops are deliberately identical, down to the
stride walk — their checksums must agree, which is what proves they did the same
work. Neither uses mod on a runtime divisor: that is an integer division, and it
would cost more than the comparison being timed.
Arguments
| Type |
Intent | Optional | Attributes |
|
Name |
|
|
type(pf_sort_keys),
|
intent(in) |
|
|
:: |
keys |
the built key set.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
nrows |
rows to walk per pass.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
nreps |
passes.
|
Return Value
integer(kind=int64)
how many pairs compared less; -1 if unusable.
-
public module function parquet_debug_sort_sweep_compare(keys, nrows, nreps, nkeys) result(total)
Test-only twin of that sweep for the tie-free comparator, summing its answers.
Arguments
| Type |
Intent | Optional | Attributes |
|
Name |
|
|
type(pf_sort_keys),
|
intent(in) |
|
|
:: |
keys |
the built key set.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
nrows |
rows to walk per pass.
|
|
integer(kind=int64),
|
intent(in) |
|
|
:: |
nreps |
passes.
|
|
integer,
|
intent(in) |
|
|
:: |
nkeys |
leading engine keys taking part.
|
Return Value
integer(kind=int64)
sum of the answers; -1 if unusable.
Derived Types
A list of sort keys, applied in the order added -- the first key added is the primary one.
Read more…
Type-Bound Procedures
| generic, public ::
add => add_i32, add_i64, add_f32, add_f64, add_bool, add_chr, add_date, add_time, add_ts, add_strcol, add_col |
Appends one sort key. Keys apply in the order added, the first being primary. |
| procedure, public ::
nkeys_added => keys_count |
Keys added so far, one per %add call. |
| procedure, public ::
clear => keys_clear |
Drops every key, leaving the object reusable. |