#include "cblas.h"
#include <iostream>
#include <string>
#include <sstream>

using namespace std;

string expect = R"(20 40 10 20 30 60 )";

void setup() {
  // put your setup code here, to run once:
  // Define vector x with 2 float elements
  float x[2] = {1.0, 2.0};

  // Define vector y with 3 float elements
  float y[3] = {2.0, 1.0, 3.0};

  // Define matrix A initialized to zeros, size 2x3
  float A[6] = {0};

  // Define number of rows and columns of matrix A
  blasint rows = 2, 
          cols = 3;

  // Define scalar alpha for scaling the outer product
  float alpha = 10;

  // Define increments (strides) for vectors x and y
  blasint inc_x = 1, 
          inc_y = 1;

  // Define leading dimension of matrix A
  // In column-major storage, lda represents the number of rows
  blasint lda = 2;

  // Perform the rank-1 update operation A := alpha * x * y' + A
  // - CblasColMajor: column-major storage
  // - rows: number of rows of A
  // - cols: number of columns of A
  // - alpha: scalar multiplier
  // - x: input vector x
  // - inc_x: stride for x
  // - y: input vector y
  // - inc_y: stride for y
  // - A: output matrix A
  // - lda: leading dimension of A
  cblas_sger(CblasColMajor, rows, cols, alpha, x, inc_x, y, inc_y, A, lda);

  // Create a stringstream to capture matrix A output
  stringstream ss;
  // Save the current standard output buffer
  streambuf *buffer = cout.rdbuf();
  // Redirect standard output to stringstream
  cout.rdbuf(ss.rdbuf());

  // Iterate through each row of matrix A
  for (int i = 0; i < rows; i++) {
      // Iterate through each column of matrix A
      for (int j = 0; j < cols; j++) {
          // Print the element at row i, column j followed by a space
          cout << A[i*cols + j] << " ";
      }
  }

  // Restore the original standard output buffer
  cout.rdbuf(buffer);
  // Convert stringstream content to string
  string s(ss.str());

  // Print separator line
  cout << "*********************************************************" << endl;
  // Print result header
  cout << "This is the result:" << endl;
  // Print computed matrix A
  cout << s << endl;
  // Print separator line
  cout << "*********************************************************" << endl;
  // Print reference header
  cout << "This is the reference:" << endl;
  // Print expected result
  cout << expect << endl;

  // Compare actual result with reference
  if (expect == s)
      // If they match, print test pass message
      cout << "{Test PASS}." << endl;
  else
      // If they differ, print test fail message
      cout << "{Test FAIL}." << endl;
}

void loop() {
  // put your main code here, to run repeatedly:

}
