Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P1673R12: LWG review 2023/06/28 #395

Open
mhoemmen opened this issue Jun 28, 2023 · 1 comment
Open

P1673R12: LWG review 2023/06/28 #395

mhoemmen opened this issue Jun 28, 2023 · 1 comment

Comments

@mhoemmen
Copy link
Contributor

mhoemmen commented Jun 28, 2023

LWG review of P1673R12: 2023/06/28

linalg.algs.reqs

2.4, spell out "unary plus" as well as unary minus.

Not comfortable with saying that "any addend" is well formed, as that just says a value is well formed, rather than an expression on it. That mixes just an operand (value), which can't be well formed or ill formed, and operations on them, which can be. Addend could just be a subexpression. "Any addend expression," "any subtrahend expression." -- works. OR: "is a well-formed expression" instead of "is well formed." Just change "is well formed" to "is a well-formed expression," in 2.4 and 2.5.

2.5 etc. doesn't affect overload resolution. It's a precondition, not a constraint.

Should we separate "core linear algebra value types" vs. "bring your own," for the sake of specification? Or add a note: "arithmetic types fulfil these requirements trivially"? complex and int don't interoperate. Compare with duration's "emulating an arithmetic type" (where nobody has any idea what it actually means) -- where we separate standard and user-provided types.

linalg.reqs.flpt

Demmel 2007, not Demmel 2002.

Editorial: can remove parentheses; doesn't need them, just part of sentence.

"Performing floating-point operations on floating-point" is not observable. Isn't the implementer already allowed to do 2.1, 2.2, or 2.3? But this is about the implementation of the algorithms, not about the types. But the user can't observe that. This is thus more like an implementer note.

2.4 is implied. 2.5 is actually useful.

Regarding Demmel 2007: Normative references can't be in bibliography. Can we paste the definition here? Otherwise, it needs to be in the normative reference section. It's OK to use the definition, because if floating point doesn't behave with bounded rounding, under the simple assumptions of Demmel 2007, then the definition is vacuous.

For special math functions, it's all just QoI. Just make it a Note.

linalg.algs.blas2

Introduce a new heading, e.g., gemm.intro, before the Note. Otherwise, it's a hanging paragraph. We had the same issue in mdspan.

(para 4) Complexity: "For all algorithms in [linalg.algs.blas2] ... the number of ... is linear in ...." In general, use the stable tag instead of "in this Clause" etc.

It's OK to use "equals" to express a statement of truth. (A.extent(1) == x.extent(0) is true is also fine.)

It's clear that dimension checking should be Mandates. Should we try to express the Mandates as a concept? (After the LWG meeting, Christian and I decided to explore this. We could implement it as two functions: constexpr function to check compile-time extents (for Mandates), and a function to check run-time dimensions (for Preconditions). Don't change paper yet; just implement wording to show them, and ask. The idea is that we could reuse function definitions and thus save wording (and also give a good hint for how the checks could be implemented).)

Next time (in two weeks)

Review 17.11.3.1 linalg.algs.blas2.gemv.

@crtrott crtrott pinned this issue Jun 28, 2023
@crtrott
Copy link
Collaborator

crtrott commented Jul 12, 2023

Idea for unifying mandates and preconditions further:

  • have exposition only functions which check compile time and runtime extent compatibility respectively:
  • each version has a mandates and a precondition variant
    • not sure what is good naming, say the precondition one is "combinable" the mandates one could be
      • "possibly-combinable", or the inverse "never-combinable" and we check for it being false?
    • need a few:
      • addable or elementwise-combinable
      • multipliable
  • identify all size combinations we need, mostly we can do this with three argument things

Exposition only Mandates Checker

template<out-matrix Out, in-matrix In1, in-matrix In2>
constexpr bool possibly-elementwise-combinable() {
  bool out_in1_ext0 =  
     Out::static_extent(0) == dynamic_extent || In1::static_extent(0) == dynamic_extent || 
     Out::static_extent(0) == In1::static_extent(0));
  bool out_in1_ext1 =  
     Out::static_extent(1) == dynamic_extent || In1::static_extent(1) == dynamic_extent || 
     Out::static_extent(1) == In1::static_extent(1));
  bool out_in2_ext0 =  
     Out::static_extent(0) == dynamic_extent || In2::static_extent(0) == dynamic_extent || 
     Out::static_extent(0) == In2::static_extent(0));
  bool out_in2_ext1 =  
     Out::static_extent(1) == dynamic_extent || In2::static_extent(1) == dynamic_extent || 
     Out::static_extent(1) == In2::static_extent(1));
  bool in1_in2_ext0 =  
     In1::static_extent(0) == dynamic_extent || In2::static_extent(0) == dynamic_extent || 
     In1::static_extent(0) == In2::static_extent(0));
  bool in1_in2_ext1 =  
     In1::static_extent(1) == dynamic_extent || In2::static_extent(1) == dynamic_extent || 
     In1::static_extent(1) == In2::static_extent(1));
  return out_in1_ext0 && out_in1_ext1 && out_in2_ext0 && out_in2_ext1 && in1_in2_ext0 && in1_in2_ext1;
}
template<out-vector Out, in-vector In1, in-vector In2>
constexpr bool possibly-elementwise-combinable() {
  bool out_in1_ext0 =  
     Out::static_extent(0) == dynamic_extent || In1::static_extent(0) == dynamic_extent || 
     Out::static_extent(0) == In1::static_extent(0));
  bool out_in2_ext0 =  
     Out::static_extent(0) == dynamic_extent || In2::static_extent(0) == dynamic_extent || 
     Out::static_extent(0) == In2::static_extent(0));
  bool in1_in2_ext0 =  
     In1::static_extent(0) == dynamic_extent || In2::static_extent(0) == dynamic_extent || 
     In1::static_extent(0) == In2::static_extent(0));
  return out_in1_ext0 && out_in2_ext0 && in1_in2_ext0;
}
template<out-vector Out, in-matrix In1, in-vector In2>
constexpr bool possibly-multiplyable() {
  bool out_in1 =  
     Out::static_extent(0) == dynamic_extent || In1::static_extent(0) == dynamic_extent || 
     Out::static_extent(0) == In1::static_extent(0));
  bool in1_in2 =  
     In1::static_extent(1) == dynamic_extent || In2::static_extent(0) == dynamic_extent || 
     In1::static_extent(1) == In2::static_extent(0));
  return out_in1 && in1_in2;
}
template<out-vector Out, in-vector In1, in-matrix In2>
constexpr bool possibly-multiplyable() {
  bool out_in2 =  
     Out::static_extent(0) == dynamic_extent || In2::static_extent(1) == dynamic_extent || 
     Out::static_extent(0) == In2::static_extent(1));
  bool in1_in2 =  
     In1::static_extent(0) == dynamic_extent || In2::static_extent(0) == dynamic_extent || 
     In1::static_extent(0) == In2::static_extent(0));
  return out_in1 && in1_in2;
}

Exposition only Precondition Checkers

template<out-matrix Out, in-matrix In1, in-matrix In2>
constexpr bool elementwise-combinable(Out out, In1 in1, In2 in2) {
  return out.extent(0) == in1.extent(0) && in1.extent(0) == in2.extent(0) &&
       out.extent(1) == in1.extent(1) && in1.extent(1) == in2.extent(1);
}
template<out-vector Out, in-vector In1, in-vector In2>
constexpr bool elementwise-combinable(Out out, In1 in1, In2 in2) {
  return out.extent(0) == in1.extent(0) && in1.extent(0) == in2.extent(0);
}
template<out-vector Out, in-matrix In1, in-vector In2>
constexpr bool multiplyable(Out out, In1 in1, In2 in2) {
   return out.extent(0) == in1.extent(0) &&
               in1.extent(1) === in2.extent(0);
}
template<out-vector Out, in-vector In1, in-matrix In2>
constexpr bool multiplyable(Out out, In1 in1, In2 in2) {
   return out.extent(0) == in2.extent(1) &&
               in1.extent(0) === in2.extent(0);
}

With these guys we can write the mandates and preconditions a bit simpler for matrix-vector-product:

Mandates: possibly-multiplyable<OutVec, InMat, InVec>()
Preconditions: multiplyable(y, A, x)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants