agreement.C 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // (c) Daniel Llorens - 2015-2016
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. /// @file agreement.C
  7. /// @brief Demo shape agreement rules
  8. #include "ra/operators.H"
  9. #include "ra/io.H"
  10. #include <iostream>
  11. using std::cout; using std::endl;
  12. int main()
  13. {
  14. // The general shape agreement rule is 'prefix agreement': all the first
  15. // dimensions must match, all the second dimensions, etc. If some arguments
  16. // have lower rank than others, then the missing dimensions are ignored.
  17. // For example:
  18. ra::Big<float, 3> A({3, 4, 5}, 1.);
  19. ra::Big<float, 2> B({3, 4}, 2.);
  20. ra::Big<float, 1> C({3}, 3.);
  21. ra::Big<float, 3> X({3, 4, 5}, 99.);
  22. // In the following expression, the shapes of the arguments are:
  23. // A: [3 4 5]
  24. // B: [3 4]
  25. // C: [3]
  26. // X: [3 4 5] (taken from the shape of the right hand side)
  27. // All the first dimensions are 3, all the second dimensions are 4, and all
  28. // the third dimensions are 5, so the expression is valid.
  29. // Note that the agreement rules are applied equally to the destination argument.
  30. X = map([](auto && a, auto && b, auto && c) { return a+b-c; }, A, B, C);
  31. cout << "\nX: " << X << endl;
  32. // (you can write the expression above as X = A+B-C).
  33. // This rule comes from the array language J (for function rank 0; see J's
  34. // documentation). Obvious examples include:
  35. {
  36. // multiply any array by a scalar. The shape of a scalar is [];
  37. // therefore, a scalar agrees with anything.
  38. ra::Big<float, 2> X = B*7.;
  39. cout << "\nB*7: " << X << endl;
  40. }
  41. {
  42. // multiply each row of B by a different element of C, X(i, j) = B(i, j)*C(i)
  43. ra::Big<float, 2> X = B*C;
  44. cout << "\nB*C: " << X << endl;
  45. }
  46. {
  47. // multiply arrays componentwise (identical shapes agree).
  48. ra::Big<float, 2> X = B*B;
  49. cout << "\nB*B: " << X << endl;
  50. }
  51. // Some special expressions, such as tensor indices, do not have a
  52. // shape. Therefore they need to be accompanied by some other expression
  53. // that does have a shape, or the overall expression is not valid. That's
  54. // why you can do
  55. {
  56. ra::TensorIndex<0> i;
  57. ra::TensorIndex<1> j;
  58. ra::Big<float, 2> X({3, 4}, i-j);
  59. cout << "\ni-j: " << X << endl;
  60. }
  61. // but the following would be invalid:
  62. {
  63. // ra::TensorIndex<0> i;
  64. // ra::TensorIndex<1> j;
  65. // ra::Big<float, 2> X = i-j; // no shape to construct X with
  66. }
  67. return 0;
  68. }