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#[macro_export]
424macro_rules! match_each_pscalar_pair {
425    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
426        match ($left, $right) {
427            (
428                $crate::primitive::PrimitiveScalar::U8($l),
429                $crate::primitive::PrimitiveScalar::U8($r),
430            ) => $body,
431            (
432                $crate::primitive::PrimitiveScalar::U16($l),
433                $crate::primitive::PrimitiveScalar::U16($r),
434            ) => $body,
435            (
436                $crate::primitive::PrimitiveScalar::U32($l),
437                $crate::primitive::PrimitiveScalar::U32($r),
438            ) => $body,
439            (
440                $crate::primitive::PrimitiveScalar::U64($l),
441                $crate::primitive::PrimitiveScalar::U64($r),
442            ) => $body,
443            (
444                $crate::primitive::PrimitiveScalar::I8($l),
445                $crate::primitive::PrimitiveScalar::I8($r),
446            ) => $body,
447            (
448                $crate::primitive::PrimitiveScalar::I16($l),
449                $crate::primitive::PrimitiveScalar::I16($r),
450            ) => $body,
451            (
452                $crate::primitive::PrimitiveScalar::I32($l),
453                $crate::primitive::PrimitiveScalar::I32($r),
454            ) => $body,
455            (
456                $crate::primitive::PrimitiveScalar::I64($l),
457                $crate::primitive::PrimitiveScalar::I64($r),
458            ) => $body,
459            (
460                $crate::primitive::PrimitiveScalar::F16($l),
461                $crate::primitive::PrimitiveScalar::F16($r),
462            ) => $body,
463            (
464                $crate::primitive::PrimitiveScalar::F32($l),
465                $crate::primitive::PrimitiveScalar::F32($r),
466            ) => $body,
467            (
468                $crate::primitive::PrimitiveScalar::F64($l),
469                $crate::primitive::PrimitiveScalar::F64($r),
470            ) => $body,
471            _ => $else,
472        }
473    }};
474}
475
476/// Matches on pairs of integer [`PrimitiveScalar`] with the same type and executes the provided
477/// code.
478///
479/// This macro matches two primitive scalars when they have the same underlying integer type.
480/// For type mismatches, the `$else` block is executed.
481///
482/// [`PrimitiveScalar`]: crate::primitive::PrimitiveScalar
483#[macro_export]
484macro_rules! match_each_integer_pscalar_pair {
485    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
486        match ($left, $right) {
487            (
488                $crate::primitive::PrimitiveScalar::U8($l),
489                $crate::primitive::PrimitiveScalar::U8($r),
490            ) => $body,
491            (
492                $crate::primitive::PrimitiveScalar::U16($l),
493                $crate::primitive::PrimitiveScalar::U16($r),
494            ) => $body,
495            (
496                $crate::primitive::PrimitiveScalar::U32($l),
497                $crate::primitive::PrimitiveScalar::U32($r),
498            ) => $body,
499            (
500                $crate::primitive::PrimitiveScalar::U64($l),
501                $crate::primitive::PrimitiveScalar::U64($r),
502            ) => $body,
503            (
504                $crate::primitive::PrimitiveScalar::I8($l),
505                $crate::primitive::PrimitiveScalar::I8($r),
506            ) => $body,
507            (
508                $crate::primitive::PrimitiveScalar::I16($l),
509                $crate::primitive::PrimitiveScalar::I16($r),
510            ) => $body,
511            (
512                $crate::primitive::PrimitiveScalar::I32($l),
513                $crate::primitive::PrimitiveScalar::I32($r),
514            ) => $body,
515            (
516                $crate::primitive::PrimitiveScalar::I64($l),
517                $crate::primitive::PrimitiveScalar::I64($r),
518            ) => $body,
519            _ => $else,
520        }
521    }};
522}
523
524/// Matches on pairs of float [`PrimitiveScalar`] with the same type and executes the provided code.
525///
526/// This macro matches two primitive scalars when they have the same underlying float type.
527/// For type mismatches, the `$else` block is executed.
528///
529/// [`PrimitiveScalar`]: crate::primitive::PrimitiveScalar
530#[macro_export]
531macro_rules! match_each_float_pscalar_pair {
532    (($left:expr, $right:expr), | $l:ident, $r:ident | $body:block, $else:block) => {{
533        match ($left, $right) {
534            (
535                $crate::primitive::PrimitiveScalar::F16($l),
536                $crate::primitive::PrimitiveScalar::F16($r),
537            ) => $body,
538            (
539                $crate::primitive::PrimitiveScalar::F32($l),
540                $crate::primitive::PrimitiveScalar::F32($r),
541            ) => $body,
542            (
543                $crate::primitive::PrimitiveScalar::F64($l),
544                $crate::primitive::PrimitiveScalar::F64($r),
545            ) => $body,
546            _ => $else,
547        }
548    }};
549}