2

The macro would allow you to write any M x N matrix in a natural way. For example:

matrix![
    1.0, 3.0, 5.0;
    2.0, 4.0, 6.0;
]

which corresponds to the following matrix.

┌                 ┐
│  1.0  3.0  5.0  │
│  2.0  4.0  6.0  │
└                 ┘

The macro would output an array of arrays like the following:

[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]

I know that I can parse row-major order quite simply using the following. But how can I can convert this to a column-major order. I can't figure out how to switch the order of the repeating groups.

macro_rules! matrix {
    ($($($e:expr),*);*) => {(
        [$([$($e),*]),*]
    }
}
Ross MacArthur
  • 4,735
  • 1
  • 24
  • 36

1 Answers1

1

Here you go:

macro_rules! matrix {
    ($($($v:expr),* );*) => {
        matrix!(@phase2 [] $($($v),* );*)
    };
    (@phase2 [$([$($col:expr),*])*] $($v:expr);* ) => {
        [$([$($col),*],)* [$($v),*]]
    };
    (@phase2 [$([$($col:expr),*])*] $($v0:expr, $($v:expr),* );* $(;)?) => {
        matrix!(@phase2 [$([$($col),*]),* [$($v0),*]] $($($v),* );*)
    };
}
phimuemue
  • 34,669
  • 9
  • 84
  • 115
  • See also [What does an @ symbol mean in a Rust declarative macro?](https://stackoverflow.com/q/54406388/155423) – Shepmaster Jan 11 '21 at 17:48
  • Wow thanks, this is fantastic. I tweaked the solution a bit [here](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1d4afdc2266db7a9688bf8a13ea34aa1) in order to handle a few edge cases. Do you think there is anyway this can be simplified, I had to add a new rule. – Ross MacArthur Jan 11 '21 at 21:28