vortex_vector/primitive/
macros.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Helper macros for working with the different variants of [`PrimitiveVector`] and
5//! [`PrimitiveVectorMut`].
6//!
7//! [`PrimitiveVector`]: crate::primitive::PrimitiveVector
8//! [`PrimitiveVectorMut`]: crate::primitive::PrimitiveVectorMut
9
10/// Matches on all primitive type variants of [`PrimitiveVector`] and executes the same code for
11/// each variant branch.
12///
13/// This macro eliminates repetitive match statements when implementing operations that need to work
14/// uniformly across all primitive type variants (`U8`, `U16`, `U32`, `U64`, `I8`, `I16`, `I32`,
15/// `I64`, `F16`, `F32`, `F64`).
16///
17/// # Examples
18///
19/// ```
20/// use vortex_vector::primitive::{PrimitiveVector, PVectorMut};
21/// use vortex_vector::{VectorOps, VectorMutOps, match_each_pvector};
22///
23/// fn get_primitive_len(vector: &PrimitiveVector) -> usize {
24///     match_each_pvector!(vector, |v| { v.len() })
25/// }
26///
27/// // Works with `I32` primitive vectors.
28/// let i32_vec: PrimitiveVector = PVectorMut::<i32>::from_iter([1, 2, 3].map(Some))
29///     .freeze()
30///     .into();
31/// assert_eq!(get_primitive_len(&i32_vec), 3);
32///
33/// // Works with `F64` primitive vectors.
34/// let f64_vec: PrimitiveVector = PVectorMut::<f64>::from_iter([1.0, 2.5].map(Some))
35///     .freeze()
36///     .into();
37/// assert_eq!(get_primitive_len(&f64_vec), 2);
38/// ```
39///
40/// Note: The `len` method is already provided by the [`VectorOps`] trait implementation.
41///
42/// [`PrimitiveVector`]: crate::primitive::PrimitiveVector
43/// [`VectorOps`]: crate::VectorOps
44#[macro_export]
45macro_rules! match_each_pvector {
46    ($self:expr, | $vec:ident | $body:block) => {{
47        match $self {
48            $crate::primitive::PrimitiveVector::U8($vec) => $body,
49            $crate::primitive::PrimitiveVector::U16($vec) => $body,
50            $crate::primitive::PrimitiveVector::U32($vec) => $body,
51            $crate::primitive::PrimitiveVector::U64($vec) => $body,
52            $crate::primitive::PrimitiveVector::I8($vec) => $body,
53            $crate::primitive::PrimitiveVector::I16($vec) => $body,
54            $crate::primitive::PrimitiveVector::I32($vec) => $body,
55            $crate::primitive::PrimitiveVector::I64($vec) => $body,
56            $crate::primitive::PrimitiveVector::F16($vec) => $body,
57            $crate::primitive::PrimitiveVector::F32($vec) => $body,
58            $crate::primitive::PrimitiveVector::F64($vec) => $body,
59        }
60    }};
61}
62
63/// Matches on all integer type variants of [`PrimitiveVector`] and executes the same code for each
64/// of the integer variant branches.
65///
66/// This macro eliminates repetitive match statements when implementing operations that need to work
67/// uniformly across all integer type variants (`U8`, `U16`, `U32`, `U64`, `I8`, `I16`, `I32`,
68/// `I64`).
69///
70/// See [`match_each_pvector`] for similar usage.
71///
72/// [`PrimitiveVector`]: crate::primitive::PrimitiveVector
73///
74/// # Panics
75///
76/// Panics if the vector passed in to the macro is a float vector variant.
77#[macro_export]
78macro_rules! match_each_integer_pvector {
79    ($self:expr, | $vec:ident | $body:block) => {{
80        match $self {
81            $crate::primitive::PrimitiveVector::U8($vec) => $body,
82            $crate::primitive::PrimitiveVector::U16($vec) => $body,
83            $crate::primitive::PrimitiveVector::U32($vec) => $body,
84            $crate::primitive::PrimitiveVector::U64($vec) => $body,
85            $crate::primitive::PrimitiveVector::I8($vec) => $body,
86            $crate::primitive::PrimitiveVector::I16($vec) => $body,
87            $crate::primitive::PrimitiveVector::I32($vec) => $body,
88            $crate::primitive::PrimitiveVector::I64($vec) => $body,
89            $crate::primitive::PrimitiveVector::F16(_)
90            | $crate::primitive::PrimitiveVector::F32(_)
91            | $crate::primitive::PrimitiveVector::F64(_) => {
92                ::vortex_error::vortex_panic!(
93                    "Tried to match a float vector in an integer match statement"
94                )
95            }
96        }
97    }};
98}
99
100/// Matches on all unsigned type variants of [`PrimitiveVector`] and executes the same code for each
101/// of the unsigned variant branches.
102///
103/// This macro eliminates repetitive match statements when implementing operations that need to work
104/// uniformly across all unsigned type variants (`U8`, `U16`, `U32`, `U64`).
105///
106/// See [`match_each_pvector`] for similar usage.
107///
108/// [`PrimitiveVector`]: crate::primitive::PrimitiveVector
109///
110/// # Panics
111///
112/// Panics if the vector passed in to the macro is not an unsigned vector variant.
113#[macro_export]
114macro_rules! match_each_unsigned_pvector {
115    ($self:expr, | $vec:ident | $body:block) => {{
116        match $self {
117            $crate::primitive::PrimitiveVector::U8($vec) => $body,
118            $crate::primitive::PrimitiveVector::U16($vec) => $body,
119            $crate::primitive::PrimitiveVector::U32($vec) => $body,
120            $crate::primitive::PrimitiveVector::U64($vec) => $body,
121            $crate::primitive::PrimitiveVector::I8(_)
122            | $crate::primitive::PrimitiveVector::I16(_)
123            | $crate::primitive::PrimitiveVector::I32(_)
124            | $crate::primitive::PrimitiveVector::I64(_)
125            | $crate::primitive::PrimitiveVector::F16(_)
126            | $crate::primitive::PrimitiveVector::F32(_)
127            | $crate::primitive::PrimitiveVector::F64(_) => {
128                ::vortex_error::vortex_panic!(
129                    "Tried to match a non-unsigned vector in an unsigned match statement"
130                )
131            }
132        }
133    }};
134}
135
136/// Matches on all primitive type variants of [`PrimitiveVectorMut`] and executes the same code
137/// for each variant branch.
138///
139/// This macro eliminates repetitive match statements when implementing mutable operations that need
140/// to work uniformly across all primitive type variants (`U8`, `U16`, `U32`, `U64`, `I8`, `I16`,
141/// `I32`, `I64`, `F16`, `F32`, `F64`).
142///
143/// # Examples
144///
145/// ```
146/// use vortex_vector::primitive::{PrimitiveVectorMut, PVectorMut};
147/// use vortex_vector::{VectorMutOps, match_each_pvector_mut};
148///
149/// fn reserve_primitive_space(vector: &mut PrimitiveVectorMut, additional: usize) {
150///     match_each_pvector_mut!(vector, |v| { v.reserve(additional) })
151/// }
152///
153/// // Works with `U8` mutable primitive vectors.
154/// let mut u8_vec: PrimitiveVectorMut = PVectorMut::<u8>::from_iter([1, 2].map(Some)).into();
155/// reserve_primitive_space(&mut u8_vec, 10);
156/// assert!(u8_vec.capacity() >= 12);
157///
158/// // Works with `I64` mutable primitive vectors.
159/// let mut i64_vec: PrimitiveVectorMut = PVectorMut::<i64>::from_iter([100].map(Some)).into();
160/// reserve_primitive_space(&mut i64_vec, 5);
161/// assert!(i64_vec.capacity() >= 6);
162/// ```
163///
164/// Note: The `reserve` method is already provided by the [`VectorMutOps`] trait implementation.
165///
166/// [`PrimitiveVectorMut`]: crate::primitive::PrimitiveVectorMut
167/// [`VectorMutOps`]: crate::VectorMutOps
168#[macro_export]
169macro_rules! match_each_pvector_mut {
170    ($self:expr, | $vec:ident | $body:block) => {{
171        match $self {
172            $crate::primitive::PrimitiveVectorMut::U8($vec) => $body,
173            $crate::primitive::PrimitiveVectorMut::U16($vec) => $body,
174            $crate::primitive::PrimitiveVectorMut::U32($vec) => $body,
175            $crate::primitive::PrimitiveVectorMut::U64($vec) => $body,
176            $crate::primitive::PrimitiveVectorMut::I8($vec) => $body,
177            $crate::primitive::PrimitiveVectorMut::I16($vec) => $body,
178            $crate::primitive::PrimitiveVectorMut::I32($vec) => $body,
179            $crate::primitive::PrimitiveVectorMut::I64($vec) => $body,
180            $crate::primitive::PrimitiveVectorMut::F16($vec) => $body,
181            $crate::primitive::PrimitiveVectorMut::F32($vec) => $body,
182            $crate::primitive::PrimitiveVectorMut::F64($vec) => $body,
183        }
184    }};
185}
186
187/// Matches on all integer type variants of [`PrimitiveVectorMut`] and executes the same code for
188/// each of the integer variant branches.
189///
190/// This macro eliminates repetitive match statements when implementing operations that need to work
191/// uniformly across all integer type variants (`U8`, `U16`, `U32`, `U64`, `I8`, `I16`, `I32`,
192/// `I64`).
193///
194/// See [`match_each_pvector_mut`] for similar usage.
195///
196/// [`PrimitiveVectorMut`]: crate::primitive::PrimitiveVectorMut
197///
198/// # Panics
199///
200/// Panics if the vector passed in to the macro is a float vector variant.
201#[macro_export]
202macro_rules! match_each_integer_pvector_mut {
203    ($self:expr, | $vec:ident | $body:block) => {{
204        match $self {
205            $crate::primitive::PrimitiveVectorMut::U8($vec) => $body,
206            $crate::primitive::PrimitiveVectorMut::U16($vec) => $body,
207            $crate::primitive::PrimitiveVectorMut::U32($vec) => $body,
208            $crate::primitive::PrimitiveVectorMut::U64($vec) => $body,
209            $crate::primitive::PrimitiveVectorMut::I8($vec) => $body,
210            $crate::primitive::PrimitiveVectorMut::I16($vec) => $body,
211            $crate::primitive::PrimitiveVectorMut::I32($vec) => $body,
212            $crate::primitive::PrimitiveVectorMut::I64($vec) => $body,
213            $crate::primitive::PrimitiveVectorMut::F16(_)
214            | $crate::primitive::PrimitiveVectorMut::F32(_)
215            | $crate::primitive::PrimitiveVectorMut::F64(_) => {
216                ::vortex_error::vortex_panic!(
217                    "Tried to match a mutable float vector in an integer match statement"
218                )
219            }
220        }
221    }};
222}
223
224/// Matches on all unsigned type variants of [`PrimitiveVectorMut`] and executes the same code for
225/// each of the unsigned variant branches.
226///
227/// This macro eliminates repetitive match statements when implementing operations that need to work
228/// uniformly across all unsigned type variants (`U8`, `U16`, `U32`, `U64`).
229///
230/// See [`match_each_pvector_mut`] for similar usage.
231///
232/// [`PrimitiveVectorMut`]: crate::primitive::PrimitiveVectorMut
233///
234/// # Panics
235///
236/// Panics if the vector passed in to the macro is not an unsigned vector variant.
237#[macro_export]
238macro_rules! match_each_unsigned_pvector_mut {
239    ($self:expr, | $vec:ident | $body:block) => {{
240        match $self {
241            $crate::primitive::PrimitiveVectorMut::U8($vec) => $body,
242            $crate::primitive::PrimitiveVectorMut::U16($vec) => $body,
243            $crate::primitive::PrimitiveVectorMut::U32($vec) => $body,
244            $crate::primitive::PrimitiveVectorMut::U64($vec) => $body,
245            $crate::primitive::PrimitiveVectorMut::I8(_)
246            | $crate::primitive::PrimitiveVectorMut::I16(_)
247            | $crate::primitive::PrimitiveVectorMut::I32(_)
248            | $crate::primitive::PrimitiveVectorMut::I64(_)
249            | $crate::primitive::PrimitiveVectorMut::F16(_)
250            | $crate::primitive::PrimitiveVectorMut::F32(_)
251            | $crate::primitive::PrimitiveVectorMut::F64(_) => {
252                ::vortex_error::vortex_panic!(
253                    "Tried to match a non-unsigned mutable vector in an unsigned match statement"
254                )
255            }
256        }
257    }};
258}
259
260/// Matches on pairs of [`crate::primitive::PrimitiveVector`] with the same type and executes the provided code.
261#[macro_export]
262macro_rules! match_each_pvector_pair {
263    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
264        match ($left, $right) {
265            (
266                $crate::primitive::PrimitiveVector::U8($l),
267                $crate::primitive::PrimitiveVector::U8($r),
268            ) => $body,
269            (
270                $crate::primitive::PrimitiveVector::U16($l),
271                $crate::primitive::PrimitiveVector::U16($r),
272            ) => $body,
273            (
274                $crate::primitive::PrimitiveVector::U32($l),
275                $crate::primitive::PrimitiveVector::U32($r),
276            ) => $body,
277            (
278                $crate::primitive::PrimitiveVector::U64($l),
279                $crate::primitive::PrimitiveVector::U64($r),
280            ) => $body,
281            (
282                $crate::primitive::PrimitiveVector::I8($l),
283                $crate::primitive::PrimitiveVector::I8($r),
284            ) => $body,
285            (
286                $crate::primitive::PrimitiveVector::I16($l),
287                $crate::primitive::PrimitiveVector::I16($r),
288            ) => $body,
289            (
290                $crate::primitive::PrimitiveVector::I32($l),
291                $crate::primitive::PrimitiveVector::I32($r),
292            ) => $body,
293            (
294                $crate::primitive::PrimitiveVector::I64($l),
295                $crate::primitive::PrimitiveVector::I64($r),
296            ) => $body,
297            (
298                $crate::primitive::PrimitiveVector::F16($l),
299                $crate::primitive::PrimitiveVector::F16($r),
300            ) => $body,
301            (
302                $crate::primitive::PrimitiveVector::F32($l),
303                $crate::primitive::PrimitiveVector::F32($r),
304            ) => $body,
305            (
306                $crate::primitive::PrimitiveVector::F64($l),
307                $crate::primitive::PrimitiveVector::F64($r),
308            ) => $body,
309            _ => $else,
310        }
311    }};
312}
313
314/// Matches on pairs of integer [`PrimitiveVector`] with the same type and executes the provided
315/// code.
316///
317/// This macro matches two primitive vectors when they have the same underlying integer type.
318/// For type mismatches, the `$else` block is executed.
319///
320/// [`PrimitiveVector`]: crate::primitive::PrimitiveVector
321#[macro_export]
322macro_rules! match_each_integer_pvector_pair {
323    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
324        match ($left, $right) {
325            (
326                $crate::primitive::PrimitiveVector::U8($l),
327                $crate::primitive::PrimitiveVector::U8($r),
328            ) => $body,
329            (
330                $crate::primitive::PrimitiveVector::U16($l),
331                $crate::primitive::PrimitiveVector::U16($r),
332            ) => $body,
333            (
334                $crate::primitive::PrimitiveVector::U32($l),
335                $crate::primitive::PrimitiveVector::U32($r),
336            ) => $body,
337            (
338                $crate::primitive::PrimitiveVector::U64($l),
339                $crate::primitive::PrimitiveVector::U64($r),
340            ) => $body,
341            (
342                $crate::primitive::PrimitiveVector::I8($l),
343                $crate::primitive::PrimitiveVector::I8($r),
344            ) => $body,
345            (
346                $crate::primitive::PrimitiveVector::I16($l),
347                $crate::primitive::PrimitiveVector::I16($r),
348            ) => $body,
349            (
350                $crate::primitive::PrimitiveVector::I32($l),
351                $crate::primitive::PrimitiveVector::I32($r),
352            ) => $body,
353            (
354                $crate::primitive::PrimitiveVector::I64($l),
355                $crate::primitive::PrimitiveVector::I64($r),
356            ) => $body,
357            _ => $else,
358        }
359    }};
360}
361
362/// Matches on pairs of float [`PrimitiveVector`] with the same type and executes the provided code.
363///
364/// This macro matches two primitive vectors when they have the same underlying float type.
365/// For type mismatches, the `$else` block is executed.
366///
367/// [`PrimitiveVector`]: crate::primitive::PrimitiveVector
368#[macro_export]
369macro_rules! match_each_float_pvector_pair {
370    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, | $l1:ident, $r2:ident | $else:block) => {{
371        match ($left, $right) {
372            (
373                $crate::primitive::PrimitiveVector::F16($l),
374                $crate::primitive::PrimitiveVector::F16($r),
375            ) => $body,
376            (
377                $crate::primitive::PrimitiveVector::F32($l),
378                $crate::primitive::PrimitiveVector::F32($r),
379            ) => $body,
380            (
381                $crate::primitive::PrimitiveVector::F64($l),
382                $crate::primitive::PrimitiveVector::F64($r),
383            ) => $body,
384            ($l1, $r2) => $else,
385        }
386    }};
387}
388
389/// Matches on all primitive type variants of [`PrimitiveScalar`] and executes the same code for
390/// each variant branch.
391///
392/// This macro eliminates repetitive match statements when implementing operations that need to work
393/// uniformly across all primitive type variants (`U8`, `U16`, `U32`, `U64`, `I8`, `I16`, `I32`,
394/// `I64`, `F16`, `F32`, `F64`).
395///
396/// Works with both owned `PrimitiveScalar` and `&PrimitiveScalar` (the bound variable will be
397/// `PScalar<T>` or `&PScalar<T>` respectively due to Rust's match ergonomics).
398///
399/// [`PrimitiveScalar`]: crate::primitive::PrimitiveScalar
400#[macro_export]
401macro_rules! match_each_pscalar {
402    ($self:expr, | $scalar:ident | $body:block) => {{
403        match $self {
404            $crate::primitive::PrimitiveScalar::U8($scalar) => $body,
405            $crate::primitive::PrimitiveScalar::U16($scalar) => $body,
406            $crate::primitive::PrimitiveScalar::U32($scalar) => $body,
407            $crate::primitive::PrimitiveScalar::U64($scalar) => $body,
408            $crate::primitive::PrimitiveScalar::I8($scalar) => $body,
409            $crate::primitive::PrimitiveScalar::I16($scalar) => $body,
410            $crate::primitive::PrimitiveScalar::I32($scalar) => $body,
411            $crate::primitive::PrimitiveScalar::I64($scalar) => $body,
412            $crate::primitive::PrimitiveScalar::F16($scalar) => $body,
413            $crate::primitive::PrimitiveScalar::F32($scalar) => $body,
414            $crate::primitive::PrimitiveScalar::F64($scalar) => $body,
415        }
416    }};
417}
418
419/// Matches on pairs of [`crate::primitive::PrimitiveScalar`] with the same type and executes the provided code.
420///
421/// This macro matches two primitive scalars when they have the same underlying type.
422/// For type mismatches, the `$else` block is executed.
423///
424/// [`PrimitiveScalar`]: crate::primitive::PrimitiveScalar
425#[macro_export]
426macro_rules! match_each_pscalar_pair {
427    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
428        match ($left, $right) {
429            (
430                $crate::primitive::PrimitiveScalar::U8($l),
431                $crate::primitive::PrimitiveScalar::U8($r),
432            ) => $body,
433            (
434                $crate::primitive::PrimitiveScalar::U16($l),
435                $crate::primitive::PrimitiveScalar::U16($r),
436            ) => $body,
437            (
438                $crate::primitive::PrimitiveScalar::U32($l),
439                $crate::primitive::PrimitiveScalar::U32($r),
440            ) => $body,
441            (
442                $crate::primitive::PrimitiveScalar::U64($l),
443                $crate::primitive::PrimitiveScalar::U64($r),
444            ) => $body,
445            (
446                $crate::primitive::PrimitiveScalar::I8($l),
447                $crate::primitive::PrimitiveScalar::I8($r),
448            ) => $body,
449            (
450                $crate::primitive::PrimitiveScalar::I16($l),
451                $crate::primitive::PrimitiveScalar::I16($r),
452            ) => $body,
453            (
454                $crate::primitive::PrimitiveScalar::I32($l),
455                $crate::primitive::PrimitiveScalar::I32($r),
456            ) => $body,
457            (
458                $crate::primitive::PrimitiveScalar::I64($l),
459                $crate::primitive::PrimitiveScalar::I64($r),
460            ) => $body,
461            (
462                $crate::primitive::PrimitiveScalar::F16($l),
463                $crate::primitive::PrimitiveScalar::F16($r),
464            ) => $body,
465            (
466                $crate::primitive::PrimitiveScalar::F32($l),
467                $crate::primitive::PrimitiveScalar::F32($r),
468            ) => $body,
469            (
470                $crate::primitive::PrimitiveScalar::F64($l),
471                $crate::primitive::PrimitiveScalar::F64($r),
472            ) => $body,
473            _ => $else,
474        }
475    }};
476}
477
478/// Matches on pairs of integer [`PrimitiveScalar`] with the same type and executes the provided
479/// code.
480///
481/// This macro matches two primitive scalars when they have the same underlying integer type.
482/// For type mismatches, the `$else` block is executed.
483///
484/// [`PrimitiveScalar`]: crate::primitive::PrimitiveScalar
485#[macro_export]
486macro_rules! match_each_integer_pscalar_pair {
487    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
488        match ($left, $right) {
489            (
490                $crate::primitive::PrimitiveScalar::U8($l),
491                $crate::primitive::PrimitiveScalar::U8($r),
492            ) => $body,
493            (
494                $crate::primitive::PrimitiveScalar::U16($l),
495                $crate::primitive::PrimitiveScalar::U16($r),
496            ) => $body,
497            (
498                $crate::primitive::PrimitiveScalar::U32($l),
499                $crate::primitive::PrimitiveScalar::U32($r),
500            ) => $body,
501            (
502                $crate::primitive::PrimitiveScalar::U64($l),
503                $crate::primitive::PrimitiveScalar::U64($r),
504            ) => $body,
505            (
506                $crate::primitive::PrimitiveScalar::I8($l),
507                $crate::primitive::PrimitiveScalar::I8($r),
508            ) => $body,
509            (
510                $crate::primitive::PrimitiveScalar::I16($l),
511                $crate::primitive::PrimitiveScalar::I16($r),
512            ) => $body,
513            (
514                $crate::primitive::PrimitiveScalar::I32($l),
515                $crate::primitive::PrimitiveScalar::I32($r),
516            ) => $body,
517            (
518                $crate::primitive::PrimitiveScalar::I64($l),
519                $crate::primitive::PrimitiveScalar::I64($r),
520            ) => $body,
521            _ => $else,
522        }
523    }};
524}
525
526/// Matches on pairs of float [`PrimitiveScalar`] with the same type and executes the provided code.
527///
528/// This macro matches two primitive scalars when they have the same underlying float type.
529/// For type mismatches, the `$else` block is executed.
530///
531/// [`PrimitiveScalar`]: crate::primitive::PrimitiveScalar
532#[macro_export]
533macro_rules! match_each_float_pscalar_pair {
534    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
535        match ($left, $right) {
536            (
537                $crate::primitive::PrimitiveScalar::F16($l),
538                $crate::primitive::PrimitiveScalar::F16($r),
539            ) => $body,
540            (
541                $crate::primitive::PrimitiveScalar::F32($l),
542                $crate::primitive::PrimitiveScalar::F32($r),
543            ) => $body,
544            (
545                $crate::primitive::PrimitiveScalar::F64($l),
546                $crate::primitive::PrimitiveScalar::F64($r),
547            ) => $body,
548            _ => $else,
549        }
550    }};
551}