text: #include <php.h>
  #include <Zend/zend_interfaces.h>
  #include <Zend/zend_exceptions.h>
  #include <ext/spl/spl_iterators.h>
  #include <ext/spl/spl_exceptions.h>
  #include <ext/standard/php_rand.h>
  #include <cblas.h>
  #include <stdint.h>
  #include <Interop/Polite/Math/Matrix.h>
  
  
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif
  
  #include "php_rindow_openblas.h"
  
  static float s_max(zend_long n,float *x,zend_long incX)
  {
      zend_long i;
      float a;
      a = x[0];
      for(i=1;i<n;i++) {
          if(a<x[i*incX]) {
              a = x[i*incX];
          }
      }
      return a;
  }
  
  static double d_max(zend_long n,double *x,zend_long incX)
  {
      zend_long i;
      double a;
      a = x[0];
      for(i=1;i<n;i++) {
          if(a<x[i*incX]) {
              a = x[i*incX];
          }
      }
      return a;
  }
  
  static zend_long s_argmax(zend_long n,float *x,zend_long incX)
  {
      zend_long i;
      zend_long idx;
      float a;
      idx = 0;
      a = x[0];
      for(i=1;i<n;i++) {
          if(a<x[i*incX]) {
              idx = i;
              a = x[i*incX];
          }
      }
      return idx;
  }
  
  static zend_long d_argmax(zend_long n,double *x,zend_long incX)
  {
      zend_long i;
      zend_long idx;
      double a;
      idx = 0;
      a = x[0];
      for(i=1;i<n;i++) {
          if(a<x[i*incX]) {
              idx = i;
              a = x[i*incX];
          }
      }
      return idx;
  }
  
  static float s_sum(zend_long n,float *x,zend_long incX)
  {
      zend_long i;
      float a=0;
      for(i=0; i<n; i++) {
          a += x[i*incX];
      }
      return a;
  }
  
  static double d_sum(zend_long n,double *x,zend_long incX)
  {
      zend_long i;
      double a=0;
      for(i=0; i<n; i++) {
          a += x[i*incX];
      }
      return a;
  }
  
  
  static zend_object_handlers rindow_openblas_math_object_handlers;
  
  // destractor
  static void php_rindow_openblas_math_free_object(zend_object* object)
  {
      zend_object_std_dtor(object);
  }
  
  // constructor
  static zend_object* php_rindow_openblas_math_create_object(zend_class_entry* class_type) /* {{{ */
  {
      zend_object* intern = NULL;
  
      intern = (zend_object*)ecalloc(1, sizeof(zend_object) + zend_object_properties_size(class_type));
  
      zend_object_std_init(intern, class_type);
      object_properties_init(intern, class_type);
  
      intern->handlers = &rindow_openblas_math_object_handlers;
  
      return intern;
  } /* }}} */
  
  #define PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(data_type) { \
      data_type  *pDataX; \
      pDataX = &(((data_type *)buffer->data)[offsetX]); \
      result = 0.0; \
      for (i=0; i<n; i++,pDataX+=incX) { \
          result += (data_type)*pDataX; \
      } \
  }
  
  int php_rindow_openblas_val2int(
      zval* val_value,
      zend_long* integer_value,
      char* message)
  {
  	switch(Z_TYPE_P(val_value)) {
  	    case IS_LONG:
  	        *integer_value = Z_LVAL_P(val_value);
  	        break;
  	    case IS_DOUBLE:
  	        *integer_value = (zend_long)Z_DVAL_P(val_value);
  	        break;
  		default:
              zend_throw_exception(spl_ce_InvalidArgumentException, message, 0);
  			return -1;
  	}
  	return 0;
  }
  
  int php_rindow_openblas_val2float(
      zval* val_value,
      double* float_value,
      char* message)
  {
  	switch(Z_TYPE_P(val_value)) {
  	    case IS_LONG:
  	        *float_value = (double)Z_LVAL_P(val_value);
  	        break;
  	    case IS_DOUBLE:
  	        *float_value = Z_DVAL_P(val_value);
  	        break;
  		default:
              zend_throw_exception(spl_ce_InvalidArgumentException, message, 0);
  			return -1;
  	}
  	return 0;
  }
  
  #define PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(data_type) { \
      data_type  *pDataX; \
      data_type  *pDataY; \
      pDataX = (data_type *)values; \
      pDataY = (data_type *)target; \
      for (i=0; i<n; i++) { \
          *pDataY += *pDataX; \
          pDataX+=incValue; \
          pDataY+=incTarget; \
      } \
  }
  int php_rindow_openblas_math_add(
      zend_long n,
      zend_long dtype,
      void* values,
      zend_long incValue,
      void* target,
      zend_long incTarget
      )
  {
      switch (dtype) {
          zend_long i;
          case php_interop_polite_math_matrix_dtype_float32:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(float)
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(double)
              break;
          case php_interop_polite_math_matrix_dtype_int8:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(int8_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint8:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(uint8_t)
              break;
          case php_interop_polite_math_matrix_dtype_int16:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(int16_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint16:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(uint16_t)
              break;
          case php_interop_polite_math_matrix_dtype_int32:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(int32_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint32:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(uint32_t)
              break;
          case php_interop_polite_math_matrix_dtype_int64:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(int64_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint64:
              PHP_RINDOW_OPENBLAS_MATH_ADD_TEMPLATE(uint64_t)
              break;
          default:
              zend_throw_exception(spl_ce_InvalidArgumentException, "Unsupported data type.", 0);
              return -1;
      }
      return 0;
  }
  
  #define PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(data_type) { \
      data_type  *pDataX; \
      data_type  *pDataY; \
      pDataX = (data_type *)source; \
      pDataY = (data_type *)dest; \
      for (i=0; i<n; i++) { \
          *pDataY += *pDataX; \
          pDataX+=incSource; \
          pDataY+=incDest; \
      } \
  }
  int php_rindow_openblas_math_copy(
      zend_long n,
      zend_long dtype,
      void* source,
      zend_long incSource,
      void* dest,
      zend_long incDest
      )
  {
      switch (dtype) {
          zend_long i;
          case php_interop_polite_math_matrix_dtype_float32:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(float)
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(double)
              break;
          case php_interop_polite_math_matrix_dtype_int8:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(int8_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint8:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(uint8_t)
              break;
          case php_interop_polite_math_matrix_dtype_int16:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(int16_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint16:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(uint16_t)
              break;
          case php_interop_polite_math_matrix_dtype_int32:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(int32_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint32:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(uint32_t)
              break;
          case php_interop_polite_math_matrix_dtype_int64:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(int64_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint64:
              PHP_RINDOW_OPENBLAS_MATH_COPY_TEMPLATE(uint64_t)
              break;
          default:
              zend_throw_exception(spl_ce_InvalidArgumentException, "Unsupported data type.", 0);
              return -1;
      }
      return 0;
  }
  
  /* Method Rindow\OpenBLAS\Math::
      public function sum(
          int $n,
          Buffer $X, int $offsetX, int $incX ) : float
   {{{ */
  static PHP_METHOD(Math, sum)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      double result;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          zend_long i;
          case php_interop_polite_math_matrix_dtype_float32:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(float)
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(double)
              break;
          case php_interop_polite_math_matrix_dtype_int8:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(int8_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint8:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(uint8_t)
              break;
          case php_interop_polite_math_matrix_dtype_int16:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(int16_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint16:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(uint16_t)
              break;
          case php_interop_polite_math_matrix_dtype_int32:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(int32_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint32:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(uint32_t)
              break;
          case php_interop_polite_math_matrix_dtype_int64:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(int64_t)
              break;
          case php_interop_polite_math_matrix_dtype_uint64:
              PHP_RINDOW_OPENBLAS_MATH_SUM_TEMPLATE(uint64_t)
              break;
          case php_interop_polite_math_matrix_dtype_bool:
              {
                  uint8_t *pBoolX;
                  pBoolX = &(((uint8_t *)buffer->data)[offsetX]);
                  result = 0.0;
                  for (i=0; i<n; i++,pBoolX+=incX) {
                      if(*pBoolX!=0) {
                          result += 1;
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_InvalidArgumentException, "Unsupported data type.", 0);
              return;
      }
      RETURN_DOUBLE(result);
  }
  /* }}} */
  
  /* Method Rindow\OpenBLAS\Math::
      public function imax(
          int $n,
          Buffer $X, int $offsetX, int $incX) : int
   {{{ */
  static PHP_METHOD(Math, imax)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      float  *pFloatX;
      double *pDoubleX;
      float  floatMax;
      double doubleMax;
      zend_long resultIdx;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          zend_long i;
          case php_interop_polite_math_matrix_dtype_float32:
              pFloatX = &(((float *)buffer->data)[offsetX]);
              floatMax = *pFloatX;
              pFloatX += incX;
              resultIdx = 0;
              for (i=1; i<n; i++,pFloatX+=incX) {
                  if(floatMax < *pFloatX) {
                      floatMax = *pFloatX;
                      resultIdx = i;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              pDoubleX = &(((double *)buffer->data)[offsetX]);
              doubleMax = *pDoubleX;
              pDoubleX += incX;
              resultIdx = 0;
              for (i=1; i<n; i++,pDoubleX+=incX) {
                  if(doubleMax < *pDoubleX) {
                      doubleMax = *pDoubleX;
                      resultIdx = i;
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
      RETURN_LONG(resultIdx);
  }
  /* }}} */
  
  /* Method Rindow\OpenBLAS\Math::
      public function imin(
          int $n,
          Buffer $X, int $offsetX, int $incX) : int
   {{{ */
  static PHP_METHOD(Math, imin)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      float  *pFloatX;
      double *pDoubleX;
      float  floatMin;
      double doubleMin;
      zend_long resultIdx;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          zend_long i;
          case php_interop_polite_math_matrix_dtype_float32:
              pFloatX = &(((float *)buffer->data)[offsetX]);
              floatMin = *pFloatX;
              pFloatX += incX;
              resultIdx = 0;
              for (i=1; i<n; i++,pFloatX+=incX) {
                  if(floatMin > *pFloatX) {
                      floatMin = *pFloatX;
                      resultIdx = i;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              pDoubleX = &(((double *)buffer->data)[offsetX]);
              doubleMin = *pDoubleX;
              pDoubleX += incX;
              resultIdx = 0;
              for (i=1; i<n; i++,pDoubleX+=incX) {
                  if(doubleMin > *pDoubleX) {
                      doubleMin = *pDoubleX;
                      resultIdx = i;
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
      RETURN_LONG(resultIdx);
  }
  /* }}} */
  
  /*
     X := a*X + b
  
     Method Rindow\OpenBLAS\Math::
      public function increment(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX,
          float $beta) : void
   {{{ */
  static PHP_METHOD(Math, increment)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      double beta;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 6, 6)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_DOUBLE(beta)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = (float)alpha * x[i*incX] + (float)beta;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = (double)alpha * x[i*incX] + (double)beta;
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := 1 / (a*X + b)
  
     Method Rindow\OpenBLAS\Math::
      public function reciprocal(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX,
          float $beta) : void
   {{{ */
  static PHP_METHOD(Math, reciprocal)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      double beta;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 6, 6)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_DOUBLE(beta)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      float t;
                      t = (float)alpha * x[i*incX] + (float)beta;
                      if(t==0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Zero divide.", 0);
                          return;
                      }
                      x[i*incX] = 1 / t;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      double t;
                      t = (double)alpha * x[i*incX] + (double)beta;
                      if(t==0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Zero divide.", 0);
                          return;
                      }
                      x[i*incX] = 1 / t;
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := X  (X > a)
     X := a  (X <= a)
  
     Method Rindow\OpenBLAS\Math::
      public function maximum(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, maximum)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 5, 5)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if((float)alpha > x[i*incX]) {
                          x[i*incX] = (float)alpha;
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if((double)alpha > x[i*incX]) {
                          x[i*incX] = (double)alpha;
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
      X := X  (X < a)
      X := a  (X >= a)
  
     Method Rindow\OpenBLAS\Math::
      public function minimum(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, minimum)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 5, 5)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if((float)alpha < x[i*incX]) {
                          x[i*incX] = (float)alpha;
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if((double)alpha < x[i*incX]) {
                          x[i*incX] = (double)alpha;
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  
  /*
        X := 1  (X > a)
        X := 0  (X <= a)
  
     Method Rindow\OpenBLAS\Math::
      public function greater(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, greater)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 5, 5)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if(x[i*incX] > (float)alpha) {
                          x[i*incX] = 1.0;
                      } else {
                          x[i*incX] = 0.0;
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if(x[i*incX] > (double)alpha) {
                          x[i*incX] = 1.0;
                      } else {
                          x[i*incX] = 0.0;
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
          X := 1  (X < a)
          X := 0  (X >= a)
  
     Method Rindow\OpenBLAS\Math::
      public function less(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, less)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 5, 5)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if(x[i*incX] < (float)alpha) {
                          x[i*incX] = 1.0;
                      } else {
                          x[i*incX] = 0.0;
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      if(x[i*incX] < (double)alpha) {
                          x[i*incX] = 1.0;
                      } else {
                          x[i*incX] = 0.0;
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     A(i) := X(i) * A(i)
  
     Method Rindow\OpenBLAS\Math::
      public function multiply(
          bool $trans,
          int $m,
          int $n,
          Buffer $X, int $offsetX, int $incX,
          Buffer $A, int $offsetA, int $ldA ) : void
   {{{ */
  static PHP_METHOD(Math, multiply)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      php_interop_polite_math_matrix_linear_buffer_t* bufferA;
      zend_bool trans;
      zend_long m;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zval* a=NULL;
      zend_long offsetA;
      zend_long ldA;
      zend_long rows,cols;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 9, 9)
          Z_PARAM_BOOL(trans)
          Z_PARAM_LONG(m)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_OBJECT(a) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetA)
          Z_PARAM_LONG(ldA)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_M, m)) {
          return;
      }
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      // Check Buffer X
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(!trans) {
          rows = m; cols = n;
      } else {
          rows = n; cols = m;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,cols,offsetX,incX)) {
          return;
      }
  
      // Check Buffer A
      bufferA = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(a);
      if(php_rindow_openblas_assert_buffer_type(bufferA,"a")) {
          return;
      }
      if(php_rindow_openblas_assert_matrix_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_A, bufferA,m,n,offsetA,ldA)) {
          return;
      }
  
      // Check Buffer X and A
      if(bufferX->dtype!=bufferA->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type for X and A", 0);
          return;
      }
  
      switch (bufferX->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)bufferX->data)[offsetX]);
                  float *a = &(((float *)bufferA->data)[offsetA]);
                  zend_long i,j,incAj,incAi;
                  if(!trans) { incAj = ldA; incAi = 1;}
                  else       { incAj = 1;   incAi = ldA;}
                  for(j=0; j<rows; j++) {
                      for(i=0; i<cols; i++) {
                          a[j*incAj+i*incAi] = x[i*incX] * a[j*incAj+i*incAi];
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)bufferX->data)[offsetX]);
                  double *a = &(((double *)bufferA->data)[offsetA]);
                  zend_long i,j,incAj,incAi;
                  if(!trans) { incAj = ldA; incAi = 1;}
                  else       { incAj = 1;   incAi = ldA;}
                  for(j=0; j<rows; j++) {
                      for(i=0; i<cols; i++) {
                          a[j*incAj+i*incAi] = x[i*incX] * a[j*incAj+i*incAi];
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     A(i) := alpha * X(i) + A(i)
  
     Method Rindow\OpenBLAS\Math::
      public function add(
          int $trans,
          int $m,
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX,
          Buffer $A, int $offsetA, int $ldA ) : void
   {{{ */
  static PHP_METHOD(Math, add)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      php_interop_polite_math_matrix_linear_buffer_t* bufferA;
      zend_bool trans;
      zend_long m;
      zend_long n;
      double alpha;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zval* a=NULL;
      zend_long offsetA;
      zend_long ldA;
      zend_long rows,cols;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 10, 10)
          Z_PARAM_BOOL(trans)
          Z_PARAM_LONG(m)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_OBJECT(a) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetA)
          Z_PARAM_LONG(ldA)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_M, m)) {
          return;
      }
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      // Check Buffer X
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(!trans) {
          rows = m; cols = n;
      } else {
          rows = n; cols = m;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,cols,offsetX,incX)) {
          return;
      }
  
      // Check Buffer A
      bufferA = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(a);
      if(php_rindow_openblas_assert_buffer_type(bufferA,"a")) {
          return;
      }
      if(php_rindow_openblas_assert_matrix_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_A, bufferA,m,n,offsetA,ldA)) {
          return;
      }
  
      // Check Buffer X and A
      if(bufferX->dtype!=bufferA->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type for X and A", 0);
          return;
      }
  
      switch (bufferX->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)bufferX->data)[offsetX]);
                  float *a = &(((float *)bufferA->data)[offsetA]);
                  zend_long j,incAj,incAi;
                  if(!trans) { incAj = ldA; incAi = 1;}
                  else       { incAj = 1;   incAi = ldA;}
                  for(j=0; j<rows; j++) {
                      cblas_saxpy((blasint)cols,(float)alpha,
                          (float*)x,(blasint)incX,
                          (float*)(&a[j*incAj]),(blasint)incAi);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)bufferX->data)[offsetX]);
                  double *a = &(((double *)bufferA->data)[offsetA]);
                  zend_long j,incAj,incAi;
                  if(!trans) { incAj = ldA; incAi = 1;}
                  else       { incAj = 1;   incAi = ldA;}
                  for(j=0; j<rows; j++) {
                      cblas_daxpy((blasint)cols,(double)alpha,
                          (double*)x,(blasint)incX,
                          (double*)(&a[j*incAj]),(blasint)incAi);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     A(m,n) := X(n)
  
     Method Rindow\OpenBLAS\Math::
      public function duplicate(
          bool $trans,
          int $m,
          int $n,
          Buffer $X, int $offsetX, int $incX,
          Buffer $A, int $offsetA, int $ldA ) : void
   {{{ */
  static PHP_METHOD(Math, duplicate)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      php_interop_polite_math_matrix_linear_buffer_t* bufferA;
      zend_bool trans;
      zend_long m;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zval* a=NULL;
      zend_long offsetA;
      zend_long ldA;
      zend_long rows,cols;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 9, 9)
          Z_PARAM_BOOL(trans)
          Z_PARAM_LONG(m)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_OBJECT(a) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetA)
          Z_PARAM_LONG(ldA)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_M, m)) {
          return;
      }
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      if(!trans) {
          rows = m; cols = n;
      } else {
          rows = n; cols = m;
      }
      // Check Buffer X
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,cols,offsetX,incX)) {
          return;
      }
  
      // Check Buffer A
      bufferA = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(a);
      if(php_rindow_openblas_assert_buffer_type(bufferA,"a")) {
          return;
      }
      if(php_rindow_openblas_assert_matrix_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_A, bufferA,m,n,offsetA,ldA)) {
          return;
      }
  
      // Check Buffer X and Y
      if(bufferX->dtype!=bufferA->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type for X and Y", 0);
          return;
      }
  
      switch (bufferX->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)bufferX->data)[offsetX]);
                  float *a = &(((float *)bufferA->data)[offsetA]);
                  zend_long j,incAj,incAi;
                  if(!trans) { incAj = ldA; incAi = 1;}
                  else       { incAj = 1;   incAi = ldA;}
                  for(j=0; j<rows; j++) {
                      cblas_scopy((blasint)cols,
                          x, (blasint)incX,
                          &(a[j*incAj]), (blasint)incAi);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)bufferX->data)[offsetX]);
                  double *a = &(((double *)bufferA->data)[offsetA]);
                  zend_long j,incAj,incAi;
                  if(!trans) { incAj = ldA; incAi = 1;}
                  else       { incAj = 1;   incAi = ldA;}
                  for(j=0; j<rows; j++) {
                      cblas_dcopy((blasint)n,
                          x, (blasint)incX,
                          &(a[j*incAj]), (blasint)incAi);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := X ^ 2
  
     Method Rindow\OpenBLAS\Math::
      public function square(
          int $n,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, square)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = x[i*incX] * x[i*incX];
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = x[i*incX] * x[i*incX];
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := sqrt(X)
  
     Method Rindow\OpenBLAS\Math::
      public function sqrt(
          int $n,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, sqrt)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      float t;
                      t = x[i*incX];
                      if(t<0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Invalid value in sqrt.", 0);
                          return;
                      }
                      x[i*incX] = sqrtf(t);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      double t;
                      t = x[i*incX];
                      if(t<0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Invalid value in sqrt.", 0);
                          return;
                      }
                      x[i*incX] = sqrt(t);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := 1 / (a * sqrt(X) + b)
  
     Method Rindow\OpenBLAS\Math::
      public function rsqrt(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX,
          float $beta) : void
   {{{ */
  static PHP_METHOD(Math, rsqrt)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      double beta;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 6, 6)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_DOUBLE(beta)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      float t;
                      if(x[i*incX]<0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Invalid value in sqrt.", 0);
                          return;
                      }
                      t = (float)alpha * sqrtf(x[i*incX]) + (float)beta;
                      if(t==0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Zero divide.", 0);
                          return;
                      }
                      x[i*incX] = 1 / t;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      double t;
                      if(x[i*incX]<0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Invalid value in sqrt.", 0);
                          return;
                      }
                      t = (double)alpha * sqrt(x[i*incX]) + (double)beta;
                      if(t==0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Zero divide.", 0);
                          return;
                      }
                      x[i*incX] = 1 / t;
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := X ^ a
  
     Method Rindow\OpenBLAS\Math::
      public function pow(
          int $n,
          float $alpha,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, pow)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      double alpha;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 5, 5)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = powf(x[i*incX], (float)alpha);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = pow(x[i*incX], (double)alpha);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X(i) := e ^ X(i)
  
     Method Rindow\OpenBLAS\Math::
      public function exp(
          int $n,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, exp)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = expf(x[i*incX]);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = exp(x[i*incX]);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := log(X)
  
     Method Rindow\OpenBLAS\Math::
      public function log(
          int $n,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, log)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      float t;
                      t = x[i*incX];
                      if(t<=0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Invalid value in log.", 0);
                          return;
                      }
                      x[i*incX] = logf(t);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      double t;
                      t = x[i*incX];
                      if(t<=0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Invalid value in log.", 0);
                          return;
                      }
                      x[i*incX] = log(t);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  /*
     X := tanh(X)
  
     Method Rindow\OpenBLAS\Math::
      public function tanh(
          int $n,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, tanh)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zend_long i;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      float t;
                      t = x[i*incX];
                      x[i*incX] = tanhf(t);
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      double t;
                      t = x[i*incX];
                      x[i*incX] = tanh(t);
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X := 0
  
     Method Rindow\OpenBLAS\Math::
      public function zeros(
          int $n,
          Buffer $X, int $offsetX, int $incX) : void
   {{{ */
  static PHP_METHOD(Math, zeros)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 4, 4)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(buffer,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, buffer,n,offsetX,incX)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  zend_long i;
                  float *x = &(((float *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = 0;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  zend_long i;
                  double *x = &(((double *)buffer->data)[offsetX]);
                  for(i=0;i<n;i++) {
                      x[i*incX] = 0;
                  }
              }
              break;
          default:
              {
                  zend_long i;
                  int valueSize;
                  uint8_t *x;
                  valueSize = php_rindow_openblas_common_dtype_to_valuesize(buffer->dtype);
                  x = php_rindow_openblas_get_address(buffer,offsetX,valueSize);
                  if(incX==1) {
                      memset(x,0,valueSize*n);
                  } else {
                      for(i=0;i<n;i++) {
                          memset(&x[i*incX],0,valueSize);
                      }
                  }
              }
              break;
      }
  }
  /* }}} */
  
  #define RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(data_type,get_type) { \
      data_type *x = &(((data_type *)buffer)[offset]); \
      *value = (get_type)(x[index*incWidth]);  \
      return 0; \
  }
  
  #define RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(data_type) { \
      data_type *x = &(((data_type *)buffer)[offset]); \
      x[index*incWidth] = (data_type)value;  \
      return 0; \
  }
  
  static int rindow_openblas_math_get_integer(
      zend_long dtype,void *buffer, zend_long offset,zend_long incWidth,
      zend_long index, zend_long *value)
  {
      switch (dtype) {
          case php_interop_polite_math_matrix_dtype_bool:
              {
                  uint8_t *x = &(((uint8_t *)buffer)[offset]);
                  if(x[index*incWidth]==0) { *value=0; return 0; }
                  else                     { *value=1; return 0; }
              }
          case php_interop_polite_math_matrix_dtype_int8:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int8_t,zend_long);
          case php_interop_polite_math_matrix_dtype_uint8:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint8_t,zend_long);
          case php_interop_polite_math_matrix_dtype_int16:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int16_t,zend_long);
          case php_interop_polite_math_matrix_dtype_uint16:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint16_t,zend_long);
          case php_interop_polite_math_matrix_dtype_int32:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int32_t,zend_long);
          case php_interop_polite_math_matrix_dtype_uint32:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint32_t,zend_long);
          case php_interop_polite_math_matrix_dtype_int64:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int64_t,zend_long);
          case php_interop_polite_math_matrix_dtype_uint64:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint64_t,zend_long);
          case php_interop_polite_math_matrix_dtype_float32:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(float,zend_long);
          case php_interop_polite_math_matrix_dtype_float64:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(double,zend_long);
          default:
              return -1;
      }
  }
  
  static int rindow_openblas_math_set_integer(
      zend_long dtype,void *buffer, zend_long offset,zend_long incWidth,
      zend_long index, zend_long value)
  {
      switch (dtype) {
          case php_interop_polite_math_matrix_dtype_bool:
          {
              uint8_t *x = &(((uint8_t *)buffer)[offset]);
              if(value==0) { x[index*incWidth]=0; return 0; }
              else         { x[index*incWidth]=1; return 0; }
          }
          case php_interop_polite_math_matrix_dtype_int8:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int8_t);
          case php_interop_polite_math_matrix_dtype_uint8:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint8_t);
          case php_interop_polite_math_matrix_dtype_int16:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int16_t);
          case php_interop_polite_math_matrix_dtype_uint16:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint16_t);
          case php_interop_polite_math_matrix_dtype_int32:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int32_t);
          case php_interop_polite_math_matrix_dtype_uint32:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint32_t);
          case php_interop_polite_math_matrix_dtype_int64:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int64_t);
          case php_interop_polite_math_matrix_dtype_uint64:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint64_t);
          case php_interop_polite_math_matrix_dtype_float32:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(float);
          case php_interop_polite_math_matrix_dtype_float64:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(double);
          default:
              return -1;
      }
  }
  
  static int rindow_openblas_math_get_float(
      zend_long dtype,void *buffer, zend_long offset,zend_long incWidth,
      zend_long index, double *value)
  {
      switch (dtype) {
          case php_interop_polite_math_matrix_dtype_bool:
              {
                  uint8_t *x = &(((uint8_t *)buffer)[offset]);
                  if(x[index*incWidth]==0) { *value=0; return 0; }
                  else                     { *value=1; return 0; }
              }
          case php_interop_polite_math_matrix_dtype_int8:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int8_t,double);
          case php_interop_polite_math_matrix_dtype_uint8:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint8_t,double);
          case php_interop_polite_math_matrix_dtype_int16:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int16_t,double);
          case php_interop_polite_math_matrix_dtype_uint16:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint16_t,double);
          case php_interop_polite_math_matrix_dtype_int32:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int32_t,double);
          case php_interop_polite_math_matrix_dtype_uint32:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint32_t,double);
          case php_interop_polite_math_matrix_dtype_int64:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(int64_t,double);
          case php_interop_polite_math_matrix_dtype_uint64:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(uint64_t,double);
          case php_interop_polite_math_matrix_dtype_float32:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(float,double);
          case php_interop_polite_math_matrix_dtype_float64:
              RINDOW_OPENBLAS_MATH_GET_CAST_TEMPLATE(double,double);
          default:
              return -1;
      }
  }
  
  static int rindow_openblas_math_set_float(
      zend_long dtype,void *buffer, zend_long offset,zend_long incWidth,
      zend_long index, double value)
  {
      switch (dtype) {
          case php_interop_polite_math_matrix_dtype_bool:
          {
              uint8_t *x = &(((uint8_t *)buffer)[offset]);
              if(value==0) { x[index*incWidth]=0; return 0; }
              else         { x[index*incWidth]=1; return 0; }
          }
          case php_interop_polite_math_matrix_dtype_int8:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int8_t);
          case php_interop_polite_math_matrix_dtype_uint8:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint8_t);
          case php_interop_polite_math_matrix_dtype_int16:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int16_t);
          case php_interop_polite_math_matrix_dtype_uint16:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint16_t);
          case php_interop_polite_math_matrix_dtype_int32:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int32_t);
          case php_interop_polite_math_matrix_dtype_uint32:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint32_t);
          case php_interop_polite_math_matrix_dtype_int64:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(int64_t);
          case php_interop_polite_math_matrix_dtype_uint64:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(uint64_t);
          case php_interop_polite_math_matrix_dtype_float32:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(float);
          case php_interop_polite_math_matrix_dtype_float64:
              RINDOW_OPENBLAS_MATH_SET_CAST_TEMPLATE(double);
          default:
              return -1;
      }
  }
  
  
  /*
     Y := a * onehot(X) + Y
  
     Method Rindow\OpenBLAS\Math::
      public function updateAddOnehot(
          int $m,
          int $n,
          float $a,
          Buffer $X, int $offsetX, int $incX,
          Buffer $Y, int $offsetY, int $ldY ) : void
   {{{ */
  static PHP_METHOD(Math, updateAddOnehot)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      php_interop_polite_math_matrix_linear_buffer_t* bufferY;
      zend_long m;
      zend_long n;
      double a;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zval* y=NULL;
      zend_long offsetY;
      zend_long ldY;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 9, 9)
          Z_PARAM_LONG(m)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(a)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_OBJECT(y) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetY)
          Z_PARAM_LONG(ldY)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_M, m)) {
          return;
      }
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      // Check Buffer X
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,m,offsetX,incX)) {
          return;
      }
  
      // Check Buffer Y
      bufferY = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(y);
      if(php_rindow_openblas_assert_buffer_type(bufferY,"y")) {
          return;
      }
      if(php_rindow_openblas_assert_matrix_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_Y, bufferY,m,n,offsetY,ldY)) {
          return;
      }
  
      // Check Buffer A and Y
      if(bufferX->dtype==php_interop_polite_math_matrix_dtype_bool) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Data type of BufferX must not be bool", 0);
          return;
      }
  
      switch (bufferY->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *y = &(((float *)bufferY->data)[offsetY]);
                  zend_long i,selector;
                  for(i=0; i<m; i++) {
                      if(rindow_openblas_math_get_integer(
                                  bufferX->dtype, bufferX->data, offsetX,incX,
                                  i, &selector)) {
                          zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type of label number.", 0);
                          return;
                      }
                      if(selector<0||selector>=n) {
                          zend_throw_exception(spl_ce_RuntimeException, "Label number is out of bounds.", 0);
                          return;
                      }
                      y[i*ldY+selector] += (float)a;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *y = &(((double *)bufferY->data)[offsetY]);
                  zend_long i,selector;
                  for(i=0; i<m; i++) {
                      if(rindow_openblas_math_get_integer(
                                  bufferX->dtype, bufferX->data, offsetX,incX,
                                  i, &selector)) {
                          zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type of label number.", 0);
                          return;
                      }
                      if(selector<0||selector>=n) {
                          zend_throw_exception(spl_ce_RuntimeException, "Label number is out of bounds.", 0);
                          return;
                      }
                      y[i*ldY+selector] += (double)a;
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     A := softmax(A)
  
     Method Rindow\OpenBLAS\Math::
      public function softmax(
          int $m,
          int $n,
          Buffer $A, int $offsetA, int $ldA) : void
   {{{ */
  static PHP_METHOD(Math, softmax)
  {
      php_interop_polite_math_matrix_linear_buffer_t* buffer;
      zend_long m;
      zend_long n;
      zval* a=NULL;
      zend_long offsetA;
      zend_long ldA;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 5, 5)
          Z_PARAM_LONG(m)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(a) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetA)
          Z_PARAM_LONG(ldA)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_M, m)) {
          return;
      }
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      buffer = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(a);
      if(php_rindow_openblas_assert_buffer_type(buffer,"a")) {
          return;
      }
      if(php_rindow_openblas_assert_matrix_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_A, buffer,m,n,offsetA,ldA)) {
          return;
      }
      switch (buffer->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *a = &(((float *)buffer->data)[offsetA]);
                  zend_long i,j;
                  for(i=0;i<m;i++,a+=ldA) {
                      float t,max_a,sum_exp;
                      max_a = s_max(n,a,1);
                      sum_exp = 0;
                      for(j=0;j<n;j++) {
                          t = expf(a[j]-max_a);
                          sum_exp += t;
                          a[j] = t;
                      }
                      if(sum_exp==0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Zero divide in softmax.", 0);
                          return;
                      }
                      for(j=0;j<n;j++) {
                          a[j] = a[j] / sum_exp;
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *a = &(((double *)buffer->data)[offsetA]);
                  zend_long i,j;
                  for(i=0;i<m;i++,a+=ldA) {
                      double t,max_a,sum_exp;
                      max_a = d_max(n,a,1);
                      sum_exp = 0;
                      for(j=0;j<n;j++) {
                          t = exp(a[j]-max_a);
                          sum_exp += t;
                          a[j] = t;
                      }
                      if(sum_exp==0.0) {
                          zend_throw_exception(spl_ce_RuntimeException, "Zero divide in softmax.", 0);
                          return;
                      }
                      for(j=0;j<n;j++) {
                          a[j] = a[j] / sum_exp;
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     Y(i) := 1  ( X(i) == Y(i) )
     Y(i) := 0  ( X(i) != Y(i) )
  
     Method Rindow\OpenBLAS\Math::
      public function equal(
          int $n,
          Buffer $X, int $offsetX, int $incX,
          Buffer $Y, int $offsetY, int $incY ) : void
   {{{ */
  static PHP_METHOD(Math, equal)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      php_interop_polite_math_matrix_linear_buffer_t* bufferY;
      zend_long n;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zval* y=NULL;
      zend_long offsetY;
      zend_long incY;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 7, 7)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_OBJECT(y) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetY)
          Z_PARAM_LONG(incY)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      // Check Buffer X
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,n,offsetX,incX)) {
          return;
      }
  
      // Check Buffer Y
      bufferY = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(y);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"y")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_Y, bufferY,n,offsetY,incY)) {
          return;
      }
  
      // Check Buffer X and Y
      if(bufferX->dtype!=bufferY->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type for X and Y", 0);
          return;
      }
  
      switch (bufferX->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *x = &(((float *)bufferX->data)[offsetX]);
                  float *y = &(((float *)bufferY->data)[offsetY]);
                  zend_long i;
                  for(i=0; i<n; i++) {
                      if(x[i*incX] == y[i*incY])
                          y[i*incY] = 1;
                      else
                          y[i*incY] = 0;
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *x = &(((double *)bufferX->data)[offsetX]);
                  double *y = &(((double *)bufferY->data)[offsetY]);
                  zend_long i;
                  for(i=0; i<n; i++) {
                      if(x[i*incX] == y[i*incY])
                          y[i*incY] = 1;
                      else
                          y[i*incY] = 0;
                  }
              }
              break;
          default:
              if(!php_rindow_openblas_common_dtype_is_int(bufferX->dtype)&&
                  !php_rindow_openblas_common_dtype_is_bool(bufferX->dtype)) {
                  zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
                  return;
              }
              {
                  int valueSize;
                  uint8_t *x, *y;
                  zend_long i,zero,one;
                  zero = 0;
                  one = 1;
                  valueSize = php_rindow_openblas_common_dtype_to_valuesize(bufferX->dtype);
                  x = php_rindow_openblas_get_address(bufferX,offsetX,valueSize);
                  y = php_rindow_openblas_get_address(bufferY,offsetY,valueSize);
                  for(i=0; i<n; i++) {
                      if(memcmp(&x[i*incX*valueSize],&y[i*incY*valueSize],valueSize)==0) {
                          memcpy(&y[i*incY*valueSize],&one,valueSize);
                      } else {
                          memcpy(&y[i*incY*valueSize],&zero,valueSize);
                      }
                  }
              }
              break;
      }
  }
  /* }}} */
  
  /*
     Y := cast<dtype> X
  
     Method Rindow\OpenBLAS\Math::
      public function astype(
          int $n,
          int $dtype,
          Buffer $X, int $offsetX, int $incX,
          Buffer $Y, int $offsetY, int $incY) : void
   {{{ */
  static PHP_METHOD(Math, astype)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      php_interop_polite_math_matrix_linear_buffer_t* bufferY;
      zend_long n;
      zend_long dtype;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
      zval* y=NULL;
      zend_long offsetY;
      zend_long incY;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 8, 8)
          Z_PARAM_LONG(n)
          Z_PARAM_LONG(dtype)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
          Z_PARAM_OBJECT(y) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetY)
          Z_PARAM_LONG(incY)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,n,offsetX,incX)) {
          return;
      }
      bufferY = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(y);
      if(php_rindow_openblas_assert_buffer_type(bufferY,"y")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_Y, bufferY,n,offsetY,incY)) {
          return;
      }
      // Check dtype and Buffer Y
      if(dtype!=bufferY->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type for Y", 0);
          return;
      }
  
      if(php_rindow_openblas_common_dtype_is_int(dtype) || php_rindow_openblas_common_dtype_is_bool(dtype)) {
          zend_long i,value;
          for(i=0;i<n;i++) {
              if(rindow_openblas_math_get_integer(
                          bufferX->dtype, bufferX->data, offsetX,incX,
                          i, &value)) {
                  zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type of X.", 0);
                  return;
              }
              rindow_openblas_math_set_integer(bufferY->dtype, bufferY->data, offsetY, incY, i, value);
          }
      } else if(php_rindow_openblas_common_dtype_is_float(dtype)) {
          zend_long i;
          double value;
          for(i=0;i<n;i++) {
              if(rindow_openblas_math_get_float(
                          bufferX->dtype, bufferX->data, offsetX,incX,
                          i, &value)) {
                  zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type of X.", 0);
                  return;
              }
              rindow_openblas_math_set_float(bufferY->dtype, bufferY->data, offsetY, incY, i, value);
          }
      } else {
          zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type.", 0);
          return;
      }
  }
  /* }}} */
  
  /*
     B(m,n) :=  A(m,n) : trans=false
     B(n,m) :=  A(m,n) : trans=true
  
     Method Rindow\OpenBLAS\Math::
      public function matrixcopy(
          bool $trans,
          int $m,
          int $n,
          float $alpha,
          Buffer $A, int $offsetA, int $ldA,
          Buffer $B, int $offsetB, int $ldB ) : void
   {{{ */
  static PHP_METHOD(Math, matrixcopy)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferA;
      php_interop_polite_math_matrix_linear_buffer_t* bufferB;
      zend_bool trans;
      zend_long m;
      zend_long n;
      double alpha;
      zval* a=NULL;
      zend_long offsetA;
      zend_long ldA;
      zval* b=NULL;
      zend_long offsetB;
      zend_long ldB;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 10, 10)
          Z_PARAM_BOOL(trans)
          Z_PARAM_LONG(m)
          Z_PARAM_LONG(n)
          Z_PARAM_DOUBLE(alpha)
          Z_PARAM_OBJECT(a) // Interop\Polite\Math\Matrix\LinearBuffer
  
          Z_PARAM_LONG(offsetA)
          Z_PARAM_LONG(ldA)
          Z_PARAM_OBJECT(b) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetB)
          Z_PARAM_LONG(ldB)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_M, m)) {
          return;
      }
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      // Check Buffer A
      bufferA = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(a);
      if(php_rindow_openblas_assert_buffer_type(bufferA,"a")) {
          return;
      }
      if(php_rindow_openblas_assert_matrix_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_A, bufferA,m,n,offsetA,ldA)) {
          return;
      }
  
      {
          zend_long rows,cols;
          if(!trans) {
              rows = m;
              cols = n;
          } else {
              rows = n;
              cols = m;
          }
          // Check Buffer B
          bufferB = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(b);
          if(php_rindow_openblas_assert_buffer_type(bufferB,"b")) {
              return;
          }
          if(php_rindow_openblas_assert_matrix_buffer_spec(
              PHP_RINDOW_OPENBLAS_ASSERT_B, bufferB,rows,cols,offsetB,ldB)) {
              return;
          }
      }
  
      if(bufferA->dtype!=bufferB->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type A and B", 0);
          return;
      }
  
      switch (bufferA->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *a = &(((float *)bufferA->data)[offsetA]);
                  float *b = &(((float *)bufferB->data)[offsetB]);
                  zend_long i,j;
                  if(!trans) {
                      for(i=0;i<m;i++) {
                          for(j=0;j<n;j++) {
                              b[i*ldB+j] = (float)alpha * a[i*ldA+j];
                          }
                      }
                  } else {
                      for(i=0;i<m;i++) {
                          for(j=0;j<n;j++) {
                              b[j*ldB+i] = (float)alpha * a[i*ldA+j];
                          }
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *a = &(((double *)bufferA->data)[offsetA]);
                  double *b = &(((double *)bufferB->data)[offsetB]);
                  zend_long i,j;
                  if(!trans) {
                      for(i=0;i<m;i++) {
                          for(j=0;j<n;j++) {
                              b[i*ldB+j] = (double)alpha * a[i*ldA+j];
                          }
                      }
                  } else {
                      for(i=0;i<m;i++) {
                          for(j=0;j<n;j++) {
                              b[j*ldB+i] = (double)alpha * a[i*ldA+j];
                          }
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type of A.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     Method Rindow\OpenBLAS\Math::
      public function imagecopy(
          int $height,
          int $width,
          int $channels,
          Buffer $A, int $offsetA,
          Buffer $B, int $offsetB,
          bool $channelsFirst,
          int $heightShift,
          int $widthShift,
          bool $verticalFlip,
          bool $horizontalFlip
      ) : void
   {{{ */
  static PHP_METHOD(Math, imagecopy)
  {
      zend_long height;
      zend_long width;
      zend_long channels;
      zval* a;
      zend_long offsetA;
      zval* b;
      zend_long offsetB;
      zend_bool channelsFirst;
      zend_long heightShift;
      zend_long widthShift;
      zend_bool verticalFlip;
      zend_bool horizontalFlip;
      php_interop_polite_math_matrix_linear_buffer_t* bufferA;
      php_interop_polite_math_matrix_linear_buffer_t* bufferB;
      zend_long ldC,ldY,ldX;
      zend_long directionY,directionX,biasY,biasX;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 12, 12)
          Z_PARAM_LONG(height)
          Z_PARAM_LONG(width)
          Z_PARAM_LONG(channels)
          Z_PARAM_OBJECT(a) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetA)
  
          Z_PARAM_OBJECT(b) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetB)
          Z_PARAM_BOOL(channelsFirst)
          Z_PARAM_LONG(heightShift)
          Z_PARAM_LONG(widthShift)
  
          Z_PARAM_BOOL(verticalFlip)
          Z_PARAM_BOOL(horizontalFlip)
      ZEND_PARSE_PARAMETERS_END();
  
      if(height<1) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "height must be greater then 0", 0);
          return;
      }
      if(width<1) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "width must be greater then 0", 0);
          return;
      }
      if(channels<1) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "channels must be greater then 0", 0);
          return;
      }
      // Check Buffer A
      bufferA = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(a);
      if(php_rindow_openblas_assert_buffer_type(bufferA,"a")) {
          return;
      }
      if(bufferA->size < height*width*channels+offsetA) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Matrix specification too large for bufferA", 0);
          return;
      }
      // Check Buffer B
      bufferB = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(b);
      if(php_rindow_openblas_assert_buffer_type(bufferA,"b")) {
          return;
      }
      if(bufferB->size < height*width*channels+offsetB) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Matrix specification too large for bufferB", 0);
          return;
      }
  
      if(bufferA->dtype!=bufferB->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type A and B", 0);
          return;
      }
  
      if(channelsFirst) {
          ldC = width*height;
          ldY = width;
          ldX = 1;
      } else {
          ldY = width*channels;
          ldX = channels;
          ldC = 1;
      }
      directionY = directionX = 1;
      biasY = biasX = 0;
      if(verticalFlip) {
          directionY = -directionY;
          biasY = height-1;
      }
      if(horizontalFlip) {
          directionX = -directionX;
          biasX = width-1;
      }
      biasY -= heightShift*directionY;
      biasX -= widthShift*directionX;
  
      switch (bufferA->dtype) {
          case php_interop_polite_math_matrix_dtype_float32:
              {
                  float *a = &(((float *)bufferA->data)[offsetA]);
                  float *b = &(((float *)bufferB->data)[offsetB]);
                  for(zend_long y=0;y<height;y++) {
                      for(zend_long x=0;x<width;x++) {
                          for(zend_long c=0;c<channels;c++) {
                              zend_long sy = y*directionY+biasY;
                              zend_long sx = x*directionX+biasX;
                              if(sy<0) {
                                  sy = 0;
                              } else if(sy>=height) {
                                  sy = height-1;
                              }
                              if(sx<0) {
                                  sx = 0;
                              } else if(sx>=width) {
                                  sx = width-1;
                              }
                              b[y*ldY+x*ldX+c*ldC] =
                                  a[sy*ldY+sx*ldX+c*ldC];
                          }
                      }
                  }
              }
              break;
          case php_interop_polite_math_matrix_dtype_float64:
              {
                  double *a = &(((double *)bufferA->data)[offsetA]);
                  double *b = &(((double *)bufferB->data)[offsetB]);
                  for(zend_long y=0;y<height;y++) {
                      for(zend_long x=0;x<width;x++) {
                          for(zend_long c=0;c<channels;c++) {
                              zend_long sy = y*directionY+biasY;
                              zend_long sx = x*directionX+biasX;
                              if(sy<0) {
                                  sy = 0;
                              } else if(sy>=height) {
                                  sy = height-1;
                              }
                              if(sx<0) {
                                  sx = 0;
                              } else if(sx>=width) {
                                  sx = width-1;
                              }
                              b[y*ldY+x*ldX+c*ldC] =
                                  a[sy*ldY+sx*ldX+c*ldC];
                          }
                      }
                  }
              }
              break;
          default:
              zend_throw_exception(spl_ce_RuntimeException, "Unsupported data type of A.", 0);
              return;
      }
  }
  /* }}} */
  
  /*
     X(n) :=  P
  
     Method Rindow\OpenBLAS\Math::
      public function fill(
          int $n,
          Buffer $value, int $offsetV,
          Buffer $X, int $offsetX, int $incX ) : void
   {{{ */
  static PHP_METHOD(Math, fill)
  {
      php_interop_polite_math_matrix_linear_buffer_t* bufferV;
      php_interop_polite_math_matrix_linear_buffer_t* bufferX;
      zend_long n;
      zval* value=NULL;
      zend_long offsetV;
      zval* x=NULL;
      zend_long offsetX;
      zend_long incX;
  
      ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 6, 6)
          Z_PARAM_LONG(n)
          Z_PARAM_OBJECT(value) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetV)
          Z_PARAM_OBJECT(x) // Interop\Polite\Math\Matrix\LinearBuffer
          Z_PARAM_LONG(offsetX)
          Z_PARAM_LONG(incX)
      ZEND_PARSE_PARAMETERS_END();
  
      if(php_rindow_openblas_assert_shape_parameter(
          PHP_RINDOW_OPENBLAS_ASSERT_N, n)) {
          return;
      }
      // Check Buffer V
      bufferV = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(value);
      if(php_rindow_openblas_assert_buffer_type(bufferV,"value")) {
          return;
      }
      if(offsetV >= bufferV->size) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "value buffer size is too small", 0);
          return;
      }
      // Check Buffer X
      bufferX = Z_INTEROP_POLITE_MATH_MATRIX_LINEAR_BUFFER_OBJ_P(x);
      if(php_rindow_openblas_assert_buffer_type(bufferX,"x")) {
          return;
      }
      if(php_rindow_openblas_assert_vector_buffer_spec(
          PHP_RINDOW_OPENBLAS_ASSERT_X, bufferX,n,offsetX,incX)) {
          return;
      }
  
      if(bufferV->dtype!=bufferX->dtype) {
          zend_throw_exception(spl_ce_InvalidArgumentException, "Unmatch data type X and value", 0);
          return;
      }
  
      {
          size_t value_size = php_rindow_openblas_common_dtype_to_valuesize(bufferV->dtype);
          char *value = &(((char *)(bufferV->data))[offsetV*value_size]);
          char *x = &(((char *)(bufferX->data))[offsetX*value_size]);
          zend_long i;
          size_t step = incX*value_size;
          for(i=0;i<n;i++,x+=step) {
              memcpy(x,value,value_size);
          }
      }
  }
  /* }}} */
  
  #include "Math_gather.c"
  #include "Math_repeat.c"
  #include "Math_slice.c"
  #include "Math_reduction.c"
  #include "Math_im2col1d.c"
  #include "Math_im2col2d.c"
  #include "Math_im2col3d.c"
  #include "Math_random.c"
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_sum, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_imax, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_imin, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_increment, 0, 0, 6)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_INFO(0, beta)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_reciprocal, 0, 0, 6)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_INFO(0, beta)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_maximum, 0, 0, 5)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_minimum, 0, 0, 5)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_greater, 0, 0, 5)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_less, 0, 0, 5)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_multiply, 0, 0, 9)
      ZEND_ARG_INFO(0, trans)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, incY)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_add, 0, 0, 10)
      ZEND_ARG_INFO(0, trans)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, incY)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_duplicate, 0, 0, 9)
      ZEND_ARG_INFO(0, trans)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, incY)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_square, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_sqrt, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_rsqrt, 0, 0, 6)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_INFO(0, beta)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_pow, 0, 0, 5)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_exp, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_log, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_tanh, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_zeros, 0, 0, 4)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_gather, 0, 0, 11)
      ZEND_ARG_INFO(0, reverse)
      ZEND_ARG_INFO(0, addMode)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, k)
      ZEND_ARG_INFO(0, numClass)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_reduceGather, 0, 0, 11)
      ZEND_ARG_INFO(0, reverse)
      ZEND_ARG_INFO(0, addMode)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, numClass)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_repeat, 0, 0, 7)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, k)
      ZEND_ARG_INFO(0, repeats)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_slice, 0, 0, 18)
      ZEND_ARG_INFO(0, reverse)
      ZEND_ARG_INFO(0, addMode)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, k)
      ZEND_ARG_INFO(0, size)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_INFO(0, incA)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, incY)
      ZEND_ARG_INFO(0, startAxis0)
      ZEND_ARG_INFO(0, sizeAxis0)
      ZEND_ARG_INFO(0, startAxis1)
      ZEND_ARG_INFO(0, sizeAxis1)
      ZEND_ARG_INFO(0, startAxis2)
      ZEND_ARG_INFO(0, sizeAxis2)
  ZEND_END_ARG_INFO()
  
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_updateAddOnehot, 0, 0, 9)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, a)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, ldY)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_softmax, 0, 0, 5)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_equal, 0, 0, 7)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, incY)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_reduceSum, 0, 0, 7)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, k)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_reduceMax, 0, 0, 7)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, k)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_reduceArgMax, 0, 0, 7)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, k)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_astype, 0, 0, 8)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, dtype)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_OBJ_INFO(0, y, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetY)
      ZEND_ARG_INFO(0, incY)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_matrixcopy, 0, 0, 10)
      ZEND_ARG_INFO(0, trans)
      ZEND_ARG_INFO(0, m)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, alpha)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
  
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_INFO(0, ldA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
      ZEND_ARG_INFO(0, ldB)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_imagecopy, 0, 0, 12)
      ZEND_ARG_INFO(0, height)
      ZEND_ARG_INFO(0, width)
      ZEND_ARG_INFO(0, channels)
      ZEND_ARG_OBJ_INFO(0, a, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetA)
      ZEND_ARG_OBJ_INFO(0, b, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetB)
      ZEND_ARG_INFO(0, channelsFirst)
      ZEND_ARG_INFO(0, heightShift)
      ZEND_ARG_INFO(0, widthShift)
      ZEND_ARG_INFO(0, verticalFlip)
      ZEND_ARG_INFO(0, horizontalFlip)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_fill, 0, 0, 6)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, value, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetV)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_im2col1d, 0, 0, 16)
      ZEND_ARG_INFO(0, reverse)
      ZEND_ARG_OBJ_INFO(0, images_obj, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, images_offset)
      ZEND_ARG_INFO(0, images_size)
      ZEND_ARG_INFO(0, batches)
  
      ZEND_ARG_INFO(0, im_w)
      ZEND_ARG_INFO(0, channels)
      ZEND_ARG_INFO(0, filter_w)
      ZEND_ARG_INFO(0, stride_w)
      ZEND_ARG_INFO(0, padding)
  
      ZEND_ARG_INFO(0, channels_first)
      ZEND_ARG_INFO(0, dilation_w)
      ZEND_ARG_INFO(0, cols_channels_first)
      ZEND_ARG_OBJ_INFO(0, cols_obj,Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, cols_offset)
  
      ZEND_ARG_INFO(0, cols_size)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_im2col2d, 0, 0, 18)
      ZEND_ARG_INFO(0, reverse)
      ZEND_ARG_OBJ_INFO(0, images_obj, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, images_offset)
      ZEND_ARG_INFO(0, images_size)
      ZEND_ARG_INFO(0, batches)
  
      ZEND_ARG_INFO(0, im_h)
      ZEND_ARG_INFO(0, im_w)
      ZEND_ARG_INFO(0, channels)
      ZEND_ARG_INFO(0, filter_h)
      ZEND_ARG_INFO(0, filter_w)
  
      ZEND_ARG_INFO(0, stride_h)
      ZEND_ARG_INFO(0, stride_w)
      ZEND_ARG_INFO(0, padding)
      ZEND_ARG_INFO(0, channels_first)
      ZEND_ARG_INFO(0, dilation_h)
  
      ZEND_ARG_INFO(0, dilation_w)
      ZEND_ARG_INFO(0, cols_channels_first)
      ZEND_ARG_OBJ_INFO(0, cols_obj,Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, cols_offset)
      ZEND_ARG_INFO(0, cols_size)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_im2col3d, 0, 0, 24)
      ZEND_ARG_INFO(0, reverse)
      ZEND_ARG_OBJ_INFO(0, images_obj, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, images_offset)
      ZEND_ARG_INFO(0, images_size)
      ZEND_ARG_INFO(0, batches)
  
      ZEND_ARG_INFO(0, im_d)
      ZEND_ARG_INFO(0, im_h)
      ZEND_ARG_INFO(0, im_w)
      ZEND_ARG_INFO(0, channels)
      ZEND_ARG_INFO(0, filter_d)
  
      ZEND_ARG_INFO(0, filter_h)
      ZEND_ARG_INFO(0, filter_w)
      ZEND_ARG_INFO(0, stride_d)
      ZEND_ARG_INFO(0, stride_h)
      ZEND_ARG_INFO(0, stride_w)
  
      ZEND_ARG_INFO(0, padding)
      ZEND_ARG_INFO(0, channels_first)
      ZEND_ARG_INFO(0, dilation_d)
      ZEND_ARG_INFO(0, dilation_h)
      ZEND_ARG_INFO(0, dilation_w)
  
      ZEND_ARG_INFO(0, cols_channels_first)
      ZEND_ARG_OBJ_INFO(0, cols_obj,Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, cols_offset)
      ZEND_ARG_INFO(0, cols_size)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_randomUniform, 0, 0, 7)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_INFO(0, low)
      ZEND_ARG_INFO(0, high)
      ZEND_ARG_INFO(0, seed)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_randomNormal, 0, 0, 7)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_INFO(0, mean)
      ZEND_ARG_INFO(0, scale)
      ZEND_ARG_INFO(0, seed)
  ZEND_END_ARG_INFO()
  
  ZEND_BEGIN_ARG_INFO_EX(ai_Math_randomSequence, 0, 0, 6)
      ZEND_ARG_INFO(0, n)
      ZEND_ARG_INFO(0, size)
      ZEND_ARG_OBJ_INFO(0, x, Interop\\Polite\\Math\\Matrix\\LinearBuffer, 0)
      ZEND_ARG_INFO(0, offsetX)
      ZEND_ARG_INFO(0, incX)
      ZEND_ARG_INFO(0, seed)
  ZEND_END_ARG_INFO()
  
  /* {{{ Rindow\OpenBLAS\Blas function entries */
  static zend_function_entry php_rindow_openblas_math_me[] = {
      /* clang-format off */
      PHP_ME(Math, sum,            ai_Math_sum,            ZEND_ACC_PUBLIC)
      PHP_ME(Math, imax,           ai_Math_imax,           ZEND_ACC_PUBLIC)
      PHP_ME(Math, imin,           ai_Math_imin,           ZEND_ACC_PUBLIC)
      PHP_ME(Math, increment,      ai_Math_increment,      ZEND_ACC_PUBLIC)
      PHP_ME(Math, reciprocal,     ai_Math_reciprocal,     ZEND_ACC_PUBLIC)
      PHP_ME(Math, maximum,        ai_Math_maximum,        ZEND_ACC_PUBLIC)
      PHP_ME(Math, minimum,        ai_Math_minimum,        ZEND_ACC_PUBLIC)
      PHP_ME(Math, greater,        ai_Math_greater,        ZEND_ACC_PUBLIC)
      PHP_ME(Math, less,           ai_Math_less,           ZEND_ACC_PUBLIC)
      PHP_ME(Math, multiply,       ai_Math_multiply,       ZEND_ACC_PUBLIC)
      PHP_ME(Math, add,            ai_Math_add,            ZEND_ACC_PUBLIC)
      PHP_ME(Math, duplicate,      ai_Math_duplicate,      ZEND_ACC_PUBLIC)
      PHP_ME(Math, square,         ai_Math_square,         ZEND_ACC_PUBLIC)
      PHP_ME(Math, sqrt,           ai_Math_sqrt,           ZEND_ACC_PUBLIC)
      PHP_ME(Math, rsqrt,          ai_Math_rsqrt,          ZEND_ACC_PUBLIC)
      PHP_ME(Math, pow,            ai_Math_pow,            ZEND_ACC_PUBLIC)
      PHP_ME(Math, exp,            ai_Math_exp,            ZEND_ACC_PUBLIC)
      PHP_ME(Math, log,            ai_Math_log,            ZEND_ACC_PUBLIC)
      PHP_ME(Math, tanh,           ai_Math_tanh,           ZEND_ACC_PUBLIC)
      PHP_ME(Math, zeros,          ai_Math_zeros,          ZEND_ACC_PUBLIC)
      PHP_ME(Math, gather,         ai_Math_gather,         ZEND_ACC_PUBLIC)
      PHP_ME(Math, reduceGather,   ai_Math_reduceGather,   ZEND_ACC_PUBLIC)
      PHP_ME(Math, repeat,         ai_Math_repeat,         ZEND_ACC_PUBLIC)
      PHP_ME(Math, slice,          ai_Math_slice,          ZEND_ACC_PUBLIC)
      PHP_ME(Math, updateAddOnehot,ai_Math_updateAddOnehot,ZEND_ACC_PUBLIC)
      PHP_ME(Math, softmax,        ai_Math_softmax,        ZEND_ACC_PUBLIC)
      PHP_ME(Math, equal,          ai_Math_equal,          ZEND_ACC_PUBLIC)
      PHP_ME(Math, astype,         ai_Math_astype,         ZEND_ACC_PUBLIC)
      PHP_ME(Math, matrixcopy,     ai_Math_matrixcopy,     ZEND_ACC_PUBLIC)
      PHP_ME(Math, imagecopy,      ai_Math_imagecopy,      ZEND_ACC_PUBLIC)
      PHP_ME(Math, fill,           ai_Math_fill,           ZEND_ACC_PUBLIC)
      PHP_ME(Math, reduceSum,      ai_Math_reduceSum,      ZEND_ACC_PUBLIC)
      PHP_ME(Math, reduceMax,      ai_Math_reduceMax,      ZEND_ACC_PUBLIC)
      PHP_ME(Math, reduceArgMax,   ai_Math_reduceArgMax,   ZEND_ACC_PUBLIC)
      PHP_ME(Math, im2col1d,       ai_Math_im2col1d,       ZEND_ACC_PUBLIC)
      PHP_ME(Math, im2col2d,       ai_Math_im2col2d,       ZEND_ACC_PUBLIC)
      PHP_ME(Math, im2col3d,       ai_Math_im2col3d,       ZEND_ACC_PUBLIC)
      PHP_ME(Math, randomUniform,  ai_Math_randomUniform,  ZEND_ACC_PUBLIC)
      PHP_ME(Math, randomNormal,   ai_Math_randomNormal,   ZEND_ACC_PUBLIC)
      PHP_ME(Math, randomSequence, ai_Math_randomSequence, ZEND_ACC_PUBLIC)
      PHP_FE_END
      /* clang-format on */
  };
  /* }}} */
  
  /* Class Rindow\OpenBLAS\Math {{{ */
  static zend_class_entry* rindow_openblas_math_ce;
  
  void php_rindow_openblas_math_init_ce(INIT_FUNC_ARGS)
  {
      zend_class_entry ce;
  
      INIT_NS_CLASS_ENTRY(ce, "Rindow\\OpenBLAS", "Math", php_rindow_openblas_math_me);
      rindow_openblas_math_ce = zend_register_internal_class(&ce);
      rindow_openblas_math_ce->create_object = php_rindow_openblas_math_create_object;
  
      memcpy(&rindow_openblas_math_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
      rindow_openblas_math_object_handlers.offset    = 0;
      rindow_openblas_math_object_handlers.free_obj  = php_rindow_openblas_math_free_object;
      rindow_openblas_math_object_handlers.clone_obj = NULL;
  
      //zend_class_implements(rindow_openblas_math_ce, 2, spl_ce_ArrayAccess, spl_ce_Countable);
  }
  /* }}} */
  