How do I align matrix elements?

Hello,

I’m trying to figure out if I can get the I and not I_M be aligned with 0?

I tried the following, but it doesn’t quite work…

$ mat(upright(bold(I))_M ; underbrace(upright(bold(0)), (N-M) times M)) $

Additionally, attempts at using the align options seem not to work due to the under-brace applied to 0… Any ideas?

Hello. I guess you probably need to add a pinch of hacks to do that.

#let Mh = hide($""_M$)
$
  mat(
    Mh upright(bold(I))_M;
    underbrace(bold(0), (N - M) times M)
  )
$

Hi!

Oh, I see. That does look nice, but… Do you know if there might be a way to get a general solution? I imagine that if I were to have a matrix with many elements that this could quickly get onerous.

You are adding a non-matrix part inside the matrix layout, which is already a “non-general” matrix form (how am I supposed to know at which positions and how often will you use underbrace so that it can be automatically handled by the general solution?), so you can’t expect to have a general solution for a niche use case. If it was just a matrix, then you can align stuff in some ways:

$
  mat(
    align: #left,
    upright(bold(I))_M;
    // underbrace(bold(0), (N - M) times M)
    bold(0)
  )
$

image

I can’t come up with a general solution without knowing the constraints, possible values, and other stuff that you want to do with a matrix.

Thanks! That makes sense to me…

I agree that underbrace is supposed to use rarely anyways, but let’s say that we just have I_M and 0. Do you think there’s a general solution, then? Because I think it would fairly standard to have a matrix with subscripts and for those subscripts to be differently sized…

One thing about left align is that the 0 has unequal amounts of whitespace from the brackets which feels awkward to me…

#show math.attach.where(bl: none): it => {
  math.attach(b: it.b, bl: hide(it.b), it.base)
}

$
  mat(
    upright(bold(I))_M, bold(0), bold(0);
    bold(0), bold(0), bold(0);
    upright(bold(I))_M, upright(bold(I))_M, bold(0);
  )
$

#show "0": it => math.attach(b: hide($M$), it)
// #show math.equation: it => {
//   show regex("\\d+"): it => math.attach(b: hide($M$), it)
//   it
// }

$
  mat(
    upright(bold(I))_M, bold(0), bold(0);
    bold(0), bold(0), bold(0);
    upright(bold(I))_M, upright(bold(I))_M, bold(0);
  )
$

Or check conditionally each column if it needs an alignment hack:

#show math.mat: it => {
  let custom-column-gap = 0.500001em
  if it.column-gap == custom-column-gap { return it }
  let fields = it.fields()
  fields.column-gap = custom-column-gap
  let rows = fields.remove("rows")
  let transform(x) = math.attach(b: hide($M$), x)
  let map-columns = c => if not c.any(x => x.func() == math.attach) { c } else {
    c.map(x => if x.func() == math.attach { x } else { transform(x) })
  }
  math.mat(..fields, ..array.zip(..array.zip(..rows).map(map-columns)))
}

$
  mat(
    upright(bold(I))_M, bold(0), bold(0);
    bold(0), bold(0), bold(0);
    upright(bold(I))_M, upright(bold(I))_M, bold(0);
  )
$

Yes.