Exemplo n.º 1
0
  // copy construct into state 1, always.
  // This is a choice, even if X is state 2 (a numpy).
  // We copy a numpy into a regular C++ array, which can then be used at max speed.
  mem_block (mem_block const & X): size_(X.size()), py_numpy(nullptr), py_guard(nullptr) {
  try { p = new ValueType[X.size()];}
   catch (std::bad_alloc& ba) { TRIQS_RUNTIME_ERROR<< "Memory allocation error in memblock copy construction. Size :"<<X.size() << "  bad_alloc error : "<< ba.what();}
   TRACE_MEM_DEBUG("Allocating from C++ a block of size "<< X.size() << " at address " <<p);
   TRIQS_MEMORY_USED_INC(X.size());
   ref_count=1;
   weak_ref_count =0;
   // now we copy the data
#ifndef TRIQS_WITH_PYTHON_SUPPORT
   copy_from(X);
#else
   // if X is in state 1 or 3
   if (X.py_numpy==nullptr) { copy_from(X); }
   else { // X was in state 2
    // else make a new copy of the numpy ...
    import_numpy_array();
    if (!is_scalar_or_pod<ValueType>::value) TRIQS_RUNTIME_ERROR << "Internal Error : memcpy on non-scalar";
#ifdef TRIQS_NUMPY_VERSION_LT_17
    PyObject * arr3 = X.py_numpy;
#else
    // STRANGE : uncommenting this leads to a segfault on mac ???
    // TO BE INVESTIGATED, IT IS NOT NORMAL
    //if (!PyArray_Check(X.py_numpy)) TRIQS_RUNTIME_ERROR<<"Internal error : is not an array";
    PyArrayObject * arr3 = (PyArrayObject *)(X.py_numpy);
#endif
    // if we can make a memcpy, do it.
    if ( ( PyArray_ISFORTRAN(arr3)) || (PyArray_ISCONTIGUOUS(arr3)))  {
     memcpy (p,PyArray_DATA(arr3),size_ * sizeof(ValueType));
    }
    else { // if the X.py_numpy is not contiguous, first let numpy copy it properly, then memcpy
     PyObject * na = PyObject_CallMethod(X.py_numpy,(char *)"copy",nullptr);
     assert(na);
#ifdef TRIQS_NUMPY_VERSION_LT_17
     PyObject * arr = na;
#else
     if (!PyArray_Check(na)) TRIQS_RUNTIME_ERROR<<"Internal error : is not an array";
     PyArrayObject * arr = (PyArrayObject *)(na);
#endif
     assert( ( PyArray_ISFORTRAN(arr)) || (PyArray_ISCONTIGUOUS(arr)));
     memcpy (p,PyArray_DATA(arr),size_ * sizeof(ValueType));
     Py_DECREF(na);
    }
   }
#endif
  }
Exemplo n.º 2
0
static mxArray *makeMxFromNumeric(const PyArrayObject *pSrc)
{
  npy_intp lRows=0, lCols=0;
  bool lIsComplex;
  bool lIsNotAMatrix = false;
  double *lR = NULL;
  double *lI = NULL;
  mxArray *lRetval = NULL;
  mwSize dims[NPY_MAXDIMS];
  mwSize nDims = pSrc->nd;
  const PyArrayObject *ap=NULL;

  switch (pSrc->nd) {
  case 0:                       // XXX the evil 0D
    lRows = 1;
    lCols = 1;
    lIsNotAMatrix = true;
    break;
  case 1:
    lRows = pSrc->dimensions[0];
    lCols = min(1, lRows); // for array([]): to avoid zeros((0,1)) !
    lIsNotAMatrix = true;
    break;
  default:
      for (mwSize i = 0;i != nDims; i++) {
        dims[i]=(mwSize)pSrc->dimensions[i];
      }
    break;
  }
  switch (pSrc->descr->type_num) {
  case PyArray_OBJECT:
    PyErr_SetString(PyExc_TypeError, "Non-numeric array types not supported");
    return NULL;
  case PyArray_CFLOAT:
  case PyArray_CDOUBLE:
    lIsComplex = true;
    break;
  default:
    lIsComplex = false;
  }

  // converts to fortran order if not already
  if(!PyArray_ISFORTRAN(pSrc)){ 
    ap = (PyArrayObject * const)PyArray_FromArray((PyArrayObject*)pSrc,NULL,NPY_ALIGNED|NPY_F_CONTIGUOUS);
  }
  else{
    ap = pSrc;
  }

  if(lIsNotAMatrix)
    lRetval = mxCreateDoubleMatrix(lRows, lCols, lIsComplex ? mxCOMPLEX : mxREAL);
  else
    lRetval = mxCreateNumericArray(nDims,dims,mxDOUBLE_CLASS,lIsComplex ? mxCOMPLEX : mxREAL);

  if (lRetval == NULL) return NULL;
  lR = mxGetPr(lRetval);
  lI = mxGetPi(lRetval);
  if (lIsNotAMatrix) {
    void *p = PyArray_DATA(ap);
    switch (ap->descr->type_num) {
    case PyArray_CHAR:
      copyNumericVector2Mx((char *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_UBYTE:
      copyNumericVector2Mx((unsigned char *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_SBYTE:
      copyNumericVector2Mx((signed char *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_SHORT:
      copyNumericVector2Mx((short *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_INT:
      copyNumericVector2Mx((int *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_LONG:
      copyNumericVector2Mx((long *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_FLOAT:
      copyNumericVector2Mx((float *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_DOUBLE:
      copyNumericVector2Mx((double *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_CFLOAT:
      copyCplxNumericVector2Mx((float *)(p), lRows, lR, lI, pSrc->strides);
      break;

    case PyArray_CDOUBLE:
      copyCplxNumericVector2Mx((double *)(p), lRows, lR, lI, pSrc->strides);
      break;
    }
  } else {
    void *p = PyArray_DATA(ap);
    npy_intp size = PyArray_SIZE(pSrc);

    switch (pSrc->descr->type_num) {
    case PyArray_CHAR:
      copyNumeric2Mx((char *)p,size,lR);
      break;

    case PyArray_UBYTE:
      copyNumeric2Mx((unsigned char *)p,size,lR);
      break;

    case PyArray_SBYTE:
      copyNumeric2Mx((signed char *)p,size,lR);
      break;

    case PyArray_SHORT:
      copyNumeric2Mx((short *)p,size,lR);
      break;

    case PyArray_INT:
      copyNumeric2Mx((int *)p,size,lR);
      break;

    case PyArray_LONG:
      copyNumeric2Mx((long *)p,size,lR);
      break;

    case PyArray_FLOAT:
      copyNumeric2Mx((float *)p,size,lR);
      break;

    case PyArray_DOUBLE:
      copyNumeric2Mx((double *)p,size,lR);
      break;

    case PyArray_CFLOAT:
      copyCplxNumeric2Mx((float *)p,size,lR,lI);
      break;

    case PyArray_CDOUBLE:
      copyCplxNumeric2Mx((double *)p,size,lR,lI);
      break;
    }
  }
  
  if(ap != pSrc){
    Py_DECREF(const_cast<PyArrayObject *>(ap));
  }
  return lRetval;
}
Exemplo n.º 3
0
  numpy_extractor ( PyObject * X, bool allow_copy) {
   if (X==NULL) TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is NULL !";
   if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy";

   // make sure IndexMap is cuboid ?s
   static const char Order = IndexMapType::index_order_type::C_or_F;
   static_assert( ((Order=='F')||(Order=='C')), "Ordering must be C or Fortran");

   if ((!PyArray_Check(X)) && (Order=='D'))
    TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is not a numpy and you ask me to deduce the ordering in memory !";

   const int elementsType (numpy_to_C_type<typename boost::remove_const<ValueType>::type>::arraytype);
   int rank = IndexMapType::rank;
   static const char * error_msg = "   A deep copy of the object would be necessary while views are supposed to guarantee to present a *view* of the python data.\n";

   if (!allow_copy) {
    // in case of a view, we decide ourselves if we can do it...
    // a previous uses PyArray_FromAny, but behaviour changes between different version of numpy, so it is not portable...
    if (!PyArray_Check(X)) 
     throw copy_exception () << error_msg<<"   Indeed the object was not even an array !\n";  

    if ( elementsType != PyArray_TYPE((PyArrayObject*)X)) 
     throw copy_exception () << error_msg<<"   The deep copy is caused by a type mismatch of the elements. \n";

    PyArrayObject *arr = (PyArrayObject *)X;    
    if ( arr->nd != rank)
     throw copy_exception () << error_msg<<"   Rank mismatch . numpy array is of rank "<< arr->nd << "while you ask for rank "<< rank<<". \n";

    if ((Order == 'C') && (PyArray_ISFORTRAN(arr))) 
     throw copy_exception () << error_msg<<"     The numpy is in Fortran order while it is expected in C order. \n";

    if ((Order == 'F') && (!PyArray_ISFORTRAN(arr))) 
     throw copy_exception () << error_msg<<"     The numpy is not in Fortran order as it is expected. \n";

    numpy_obj = X; Py_INCREF(X); 
   }
   else { 
    // From X, we ask the numpy library to make a numpy, and of the correct type.
    // This handles automatically the cases where : 
    //   - we have list, or list of list/tuple
    //   - the numpy type is not the one we want.
    //   - adjust the dimension if needed
    // If X is an array : 
    //   - if Order is same, don't change it
    //   - else impose it (may provoque a copy).
    // if X is not array : 
    //   - Order = FortranOrder or SameOrder - > Fortran order otherwise C
    bool ForceCast = false;// Unless FORCECAST is present in flags, this call will generate an error if the data type cannot be safely obtained from the object.
    int flags = (ForceCast ? NPY_FORCECAST : 0) ;// do NOT force a copy | (make_copy ?  NPY_ENSURECOPY : 0);
    if (!(PyArray_Check(X) && (Order=='D'))) flags |= (Order =='F' ? NPY_F_CONTIGUOUS : NPY_C_CONTIGUOUS); //impose mem order
    //if (!(PyArray_Check(X) && (Order=='D'))) flags |= (Order =='F' ? NPY_FARRAY : NPY_CARRAY); //impose mem order
    numpy_obj= PyArray_FromAny(X,PyArray_DescrFromType(elementsType), rank,rank, flags , NULL );

    // do several checks
    if (!numpy_obj) {// The convertion of X to a numpy has failed !
     if (PyErr_Occurred()) {PyErr_Print();PyErr_Clear();}
     TRIQS_RUNTIME_ERROR<<"numpy interface : the python object  is not convertible to a numpy. ";
    }
    assert (PyArray_Check(numpy_obj)); assert((numpy_obj->ob_refcnt==1) || ((numpy_obj ==X)));

    arr_obj = (PyArrayObject *)numpy_obj;
    try {
     if (arr_obj->nd!=rank)  TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
     if (arr_obj->descr->type_num != elementsType) 
      TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<arr_obj->descr->type_num <<" vs "<<elementsType;
     if (Order == 'F') { if (!PyArray_ISFORTRAN(numpy_obj)) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : should be Fortran array";}
     else {if (!PyArray_ISCONTIGUOUS(numpy_obj)) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : should be contiguous";}
    }
    catch(...) { Py_DECREF(numpy_obj); throw;} // make sure that in case of problem, the reference counting of python is still ok...
   }

   arr_obj = (PyArrayObject *)numpy_obj;
  } 
Exemplo n.º 4
0
static PyObject *product_matrix_vector_(PyObject *self, PyObject *args)
{
  PyArrayObject *matrix, *vector, *result;
  double alpha = 1.;
  double beta = 0.;
  int int_one = 1;
  int m, n;
  char trans[2] = "T";

  extern void dgemv_(char *trans, int *m, int *n,
                     double *alpha, double *a, int *lda,
                     double *x, int *incx,
                     double *beta, double *Y, int *incy);
 
  if (!PyArg_ParseTuple(args, "O!O!O!", 
                        &PyArray_Type, &matrix, 
                        &PyArray_Type, &vector, 
                        &PyArray_Type, &result)) return NULL;

  if ( (NULL == matrix) || (NULL == vector) || (NULL == result) ) return NULL;

  if ( (matrix->descr->type_num != NPY_DOUBLE) || 
       (vector->descr->type_num != NPY_DOUBLE) ||
       (result->descr->type_num != NPY_DOUBLE) ||
       !PyArray_CHKFLAGS(matrix,NPY_ALIGNED) ||
       !(PyArray_CHKFLAGS(matrix,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix,NPY_F_CONTIGUOUS)) ||
       !PyArray_CHKFLAGS(vector,NPY_C_CONTIGUOUS|NPY_ALIGNED) ||
       !PyArray_CHKFLAGS(result,NPY_C_CONTIGUOUS|NPY_ALIGNED|NPY_WRITEABLE) ) {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_vector: all arguments must be of type double, contiguous and aligned, and targets should be writeable");
    return NULL;
  }

  if ( (matrix->nd != 2) || (vector->nd != 1) || (result->nd != 1) )
  {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_vector: not all arguments have the right dimensionality");
    return NULL;
  }

  /* Figure out correct values for args to blas*/
  if (PyArray_ISFORTRAN(matrix)) {
    m = matrix->dimensions[0];
    n = matrix->dimensions[1];
    trans[0] = 'N';
  }
  else /*if (PyArray_ISCONTIGUOUS(matrix))*/ {
    /* Equivalent to matrix being the transposed of a Fortran matrix*/
    m = matrix->dimensions[1];
    n = matrix->dimensions[0];
  }

  /* Check if dimensions are compatible */
  if (matrix->dimensions[1] != vector->dimensions[0]) {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_vector: input dimensions are not compatible");
    return NULL;
  }

  if (result->dimensions[0] != matrix->dimensions[0]) {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_vector: target dimension is not compatible");
    return NULL;
  }
 
  dgemv_(trans, &m, &n, &alpha, (double *)matrix->data, &m,
         (double *)vector->data, &int_one,
         &beta, (double *)result->data, &int_one);
  Py_RETURN_NONE;
}
Exemplo n.º 5
0
static mxArray *makeMxFromNumeric(const PyArrayObject *pSrc, bool &is_reference)
{
  npy_intp lRows=0, lCols=0;
  bool lIsComplex;
  bool lIsNotAMatrix = false;
  double *lR = NULL;
  double *lI = NULL;
  mxArray *lRetval = NULL;
  mwSize dims[NPY_MAXDIMS];
  mwSize dimsEmpty [2];
  memset(&dimsEmpty, 0, 2 * sizeof(mwSize));
  mwSize nDims = pSrc->nd;
  const PyArrayObject *ap=NULL;
  mxClassID classID = mxUNKNOWN_CLASS;

  switch (pSrc->nd) {
  case 0:                       // XXX the evil 0D
    lRows = 1;
    lCols = 1;
    lIsNotAMatrix = true;
    break;
  case 1:
    lRows = pSrc->dimensions[0];
    lCols = min(1, lRows); // for array([]): to avoid zeros((0,1)) !
    lIsNotAMatrix = true;
    break;
  default:
      for (mwSize i = 0;i != nDims; i++) {
        dims[i]=(mwSize)pSrc->dimensions[i];
      }
    break;
  }
  switch (pSrc->descr->type_num) {
  case PyArray_OBJECT:
    PyErr_SetString(PyExc_TypeError, "Non-numeric array types not supported");
    return NULL;
  case PyArray_CFLOAT:
  case PyArray_CDOUBLE:
    lIsComplex = true;
    break;
  default:
    lIsComplex = false;
  }

  // converts to fortran order if not already
  if(!PyArray_ISFORTRAN(pSrc)){ 
    ap = (PyArrayObject * const)PyArray_FromArray((PyArrayObject*)pSrc,NULL,NPY_ALIGNED|NPY_F_CONTIGUOUS);
  }
  else{
    ap = pSrc;
  }

  if(lIsNotAMatrix)
    lRetval = mxCreateDoubleMatrix(lRows, lCols, lIsComplex ? mxCOMPLEX : mxREAL);
  else {
    switch (ap->descr->type_num) {
      case PyArray_CFLOAT:
      case PyArray_CDOUBLE:
        classID = mxDOUBLE_CLASS;
        is_reference = false;
        break;
      case PyArray_BOOL:
        classID = mxLOGICAL_CLASS;
        is_reference = true;
        break;
      case PyArray_CHAR:
        classID = mxCHAR_CLASS;
        is_reference = true;
        break;
      case PyArray_DOUBLE:
        classID = mxDOUBLE_CLASS;
        is_reference = true;
        break;
      case PyArray_FLOAT:
        classID = mxSINGLE_CLASS;
        is_reference = true;
        break;
      case PyArray_INT8:
        classID = mxINT8_CLASS;
        is_reference = true;
        break;
      case PyArray_UINT8:
        classID = mxUINT8_CLASS;
        is_reference = true;
        break;
      case PyArray_INT16:
        classID = mxINT16_CLASS;
        is_reference = true;
        break;
      case PyArray_UINT16:
        classID = mxUINT16_CLASS;
        is_reference = true;
        break;
      case PyArray_INT32:
        classID = mxINT32_CLASS;
        is_reference = true;
        break;
      case PyArray_UINT32:
        classID = mxUINT32_CLASS;
        is_reference = true;
        break;
#ifdef NPY_INT64
      case PyArray_INT64:
        classID = mxINT64_CLASS;
        is_reference = true;
        break;
      case PyArray_UINT64:
        classID = mxUINT64_CLASS;
        is_reference = true;
        break;
#endif
    }
    if (!is_reference) {
      lRetval = mxCreateNumericArray(nDims,dims,classID,lIsComplex ? mxCOMPLEX : mxREAL);
    } else {
/*
      // code for create and mxArray ref on the numpy object
      lRetval = mxCreateNumericArray(2, dimsEmpty, classID, lIsComplex ? mxCOMPLEX : mxREAL);
      if (mxSetDimensions(lRetval, dims, nDims) == 1) {
        // failed to reset the dimensions
        mxDestroyArray(lRetval);
        lRetval = NULL;
      } else {
        mxSetData(lRetval, PyArray_DATA(ap));
      }
*/
      // uses memcopy for faster copying
      is_reference = false;
      lRetval = mxCreateNumericArray(nDims, dims, classID, lIsComplex ? mxCOMPLEX : mxREAL);
      // this is a sanity check, it should not fail
      int matlab_nbytes = mxGetNumberOfElements(lRetval) * mxGetElementSize(lRetval);
      if (matlab_nbytes == PyArray_NBYTES(pSrc)) {
        memcpy(mxGetData(lRetval), PyArray_DATA(ap), PyArray_NBYTES(pSrc));
      } else {
        PyErr_SetString(PyExc_TypeError, "Number of bytes do not match");
      }
    }
  }

  if (lRetval == NULL) return NULL;
  lR = mxGetPr(lRetval);
  lI = mxGetPi(lRetval);
  if (lIsNotAMatrix) {
    void *p = PyArray_DATA(ap);
    switch (ap->descr->type_num) {
    case PyArray_CHAR:
      copyNumericVector2Mx((char *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_UBYTE:
      copyNumericVector2Mx((unsigned char *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_SBYTE:
      copyNumericVector2Mx((signed char *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_SHORT:
      copyNumericVector2Mx((short *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_INT:
      copyNumericVector2Mx((int *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_LONG:
      copyNumericVector2Mx((long *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_FLOAT:
      copyNumericVector2Mx((float *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_DOUBLE:
      copyNumericVector2Mx((double *)(p), lRows, lR, pSrc->strides);
      break;

    case PyArray_CFLOAT:
      copyCplxNumericVector2Mx((float *)(p), lRows, lR, lI, pSrc->strides);
      break;

    case PyArray_CDOUBLE:
      copyCplxNumericVector2Mx((double *)(p), lRows, lR, lI, pSrc->strides);
      break;
    }
  } else {
    void *p = PyArray_DATA(ap);
    npy_intp size = PyArray_SIZE(pSrc);

    switch (pSrc->descr->type_num) {
    case PyArray_CFLOAT:
      copyCplxNumeric2Mx((float *)p,size,lR,lI);
      break;

    case PyArray_CDOUBLE:
      copyCplxNumeric2Mx((double *)p,size,lR,lI);
      break;
    }
  }
  
  if(ap != pSrc){
    Py_DECREF(const_cast<PyArrayObject *>(ap));
  }
  return lRetval;
}
Exemplo n.º 6
0
static PyObject *product_matrix_matrix_(PyObject *self, PyObject *args)
{
  PyArrayObject *matrix1, *matrix2, *result, *A, *B;
  double alpha = 1.;
  double beta = 0.;
  int m, n, k; /* Watch out: m and n have a different meaning from that for dgemv, where
                             it is the dimensionality BEFORE the transpose, whereas
                             dgemm requires the dimensionality AFTER. */
  int lda, ldb, ldc;
  char transa[2] = "T";
  char transb[2] = "T";
 
  extern void dgemm_(char* transa, char* transb, int* m, 
                     int* n, int* k, double *alpha, 
                     double *a, int* lda, double *b, 
                     int *ldb, double *beta, double *c, int* ldc);

  if (!PyArg_ParseTuple(args, "O!O!O!", 
                        &PyArray_Type, &matrix1,
                        &PyArray_Type, &matrix2, 
                        &PyArray_Type, &result)) return NULL;

  if ( (NULL == matrix1) || (NULL == matrix2) || (NULL == result) ) return NULL;

  if ( (matrix1->descr->type_num != NPY_DOUBLE) || 
       (matrix2->descr->type_num != NPY_DOUBLE) ||
       (result->descr->type_num != NPY_DOUBLE) ||
       !PyArray_CHKFLAGS(matrix1,NPY_ALIGNED) ||
       !(PyArray_CHKFLAGS(matrix1,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix1,NPY_F_CONTIGUOUS)) ||
       !PyArray_CHKFLAGS(matrix2,NPY_ALIGNED) ||
       !(PyArray_CHKFLAGS(matrix2,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(matrix2,NPY_F_CONTIGUOUS)) ||
       !PyArray_CHKFLAGS(result,NPY_ALIGNED|NPY_WRITEABLE) ||
       !(PyArray_CHKFLAGS(result,NPY_C_CONTIGUOUS) || PyArray_CHKFLAGS(result,NPY_F_CONTIGUOUS)) ) {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_matrix: all arguments must be of type double, contiguous and aligned, and targets should be writeable");
    return NULL;
  }

  if ( (matrix1->nd != 2) || (matrix2->nd != 2) || (result->nd != 2) )
  {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_matrix: not all arguments have the right dimensionality");
    return NULL;
  }
  
  /* Figure out correct values for args to blas*/
  if (PyArray_ISFORTRAN(result)) {
    /* Matrix result has Fortran order */
    A = matrix1;
    B = matrix2;

    m = matrix1->dimensions[0];
    k = matrix1->dimensions[1];
    if (PyArray_ISFORTRAN(matrix1)) {
      transa[0] = 'N';
      lda = m;
    }
    else /*if (PyArray_ISCONTIGUOUS(matrix1))*/ {
      /* Equivalent to matrix being the transposed of a Fortran matrix*/
      lda = k;
    }
    
    n = matrix2->dimensions[1];
    k = matrix2->dimensions[0];
    if (PyArray_ISFORTRAN(matrix2)) {
      transb[0] = 'N';
      ldb = k;
    }
    else /*if (PyArray_ISCONTIGUOUS(matrix2))*/ {
      /* Equivalent to matrix being the transposed of a Fortran matrix*/
      ldb = n;
    }
  }
  else /*if (PyArray_ISCONTIGUOUS(result))*/ {
    /* Matrix result has C order! Must be careful how blas is called!
       Must interchange matrix1 with matrix2, and interchange 
       how the C and Fortran matrices are processed. */
    A = matrix2;
    B = matrix1;

    m = matrix2->dimensions[1];
    k = matrix2->dimensions[0];
    if (PyArray_ISFORTRAN(matrix2)) {
      lda = k;
    }
    else /*if (PyArray_ISCONTIGUOUS(matrix2))*/ {
      /* Equivalent to matrix being the transposed of a Fortran matrix*/
      transa[0] = 'N';
      lda = m;
    }

    n = matrix1->dimensions[0];
    k = matrix1->dimensions[1];
    if (PyArray_ISFORTRAN(matrix1)) {
      ldb = n;
    }
    else /*if (PyArray_ISCONTIGUOUS(matrix1))*/ {
      /* Equivalent to matrix being the transposed of a Fortran matrix*/
      transb[0] = 'N';
      ldb = k;
    }
  }
  ldc = m;

  if ( matrix1->dimensions[1] != matrix2->dimensions[0] ) {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_matrix: input matrices dimensions are not compatible");
    return NULL;
  }

  if ( (matrix1->dimensions[0] != result->dimensions[0]) || 
       (matrix2->dimensions[1] != result->dimensions[1]) ) {
    PyErr_SetString(PyExc_ValueError,
                    "In product_matrix_matrix: target dimensions are not compatible");
    return NULL;
  }

  dgemm_(transa, transb, &m, &n, &k, &alpha, (double *)A->data, &lda,
         (double *)B->data, &ldb, &beta,
         (double *)result->data, &ldc );
  
  Py_RETURN_NONE;
}
Exemplo n.º 7
0
/*
 * optimize float array or complex array to a scalar power
 * returns 0 on success, -1 if no optimization is possible
 * the result is in value (can be NULL if an error occurred)
 */
static int
fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace,
                  PyObject **value)
{
    double exponent;
    NPY_SCALARKIND kind;   /* NPY_NOSCALAR is not scalar */

    if (PyArray_Check(a1) &&
            !PyArray_ISOBJECT(a1) &&
            ((kind=is_scalar_with_conversion(o2, &exponent))>0)) {
        PyObject *fastop = NULL;
        if (PyArray_ISFLOAT(a1) || PyArray_ISCOMPLEX(a1)) {
            if (exponent == 1.0) {
                fastop = n_ops.positive;
            }
            else if (exponent == -1.0) {
                fastop = n_ops.reciprocal;
            }
            else if (exponent ==  0.0) {
                fastop = n_ops._ones_like;
            }
            else if (exponent ==  0.5) {
                fastop = n_ops.sqrt;
            }
            else if (exponent ==  2.0) {
                fastop = n_ops.square;
            }
            else {
                return -1;
            }

            if (inplace || can_elide_temp_unary(a1)) {
                *value = PyArray_GenericInplaceUnaryFunction(a1, fastop);
            }
            else {
                *value = PyArray_GenericUnaryFunction(a1, fastop);
            }
            return 0;
        }
        /* Because this is called with all arrays, we need to
         *  change the output if the kind of the scalar is different
         *  than that of the input and inplace is not on ---
         *  (thus, the input should be up-cast)
         */
        else if (exponent == 2.0) {
            fastop = n_ops.square;
            if (inplace) {
                *value = PyArray_GenericInplaceUnaryFunction(a1, fastop);
            }
            else {
                /* We only special-case the FLOAT_SCALAR and integer types */
                if (kind == NPY_FLOAT_SCALAR && PyArray_ISINTEGER(a1)) {
                    PyArray_Descr *dtype = PyArray_DescrFromType(NPY_DOUBLE);
                    a1 = (PyArrayObject *)PyArray_CastToType(a1, dtype,
                            PyArray_ISFORTRAN(a1));
                    if (a1 != NULL) {
                        /* cast always creates a new array */
                        *value = PyArray_GenericInplaceUnaryFunction(a1, fastop);
                        Py_DECREF(a1);
                    }
                }
                else {
                    *value = PyArray_GenericUnaryFunction(a1, fastop);
                }
            }
            return 0;
        }
    }
    /* no fast operation found */
    return -1;
}
Exemplo n.º 8
0
/* optimize float array or complex array to a scalar power */
static PyObject *
fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace)
{
    double exponent;
    NPY_SCALARKIND kind;   /* NPY_NOSCALAR is not scalar */

    if (PyArray_Check(a1) && ((kind=is_scalar_with_conversion(o2, &exponent))>0)) {
        PyObject *fastop = NULL;
        if (PyArray_ISFLOAT(a1) || PyArray_ISCOMPLEX(a1)) {
            if (exponent == 1.0) {
                /* we have to do this one special, as the
                   "copy" method of array objects isn't set
                   up early enough to be added
                   by PyArray_SetNumericOps.
                */
                if (inplace) {
                    Py_INCREF(a1);
                    return (PyObject *)a1;
                } else {
                    return PyArray_Copy(a1);
                }
            }
            else if (exponent == -1.0) {
                fastop = n_ops.reciprocal;
            }
            else if (exponent ==  0.0) {
                fastop = n_ops._ones_like;
            }
            else if (exponent ==  0.5) {
                fastop = n_ops.sqrt;
            }
            else if (exponent ==  2.0) {
                fastop = n_ops.square;
            }
            else {
                return NULL;
            }

            if (inplace) {
                return PyArray_GenericInplaceUnaryFunction(a1, fastop);
            } else {
                return PyArray_GenericUnaryFunction(a1, fastop);
            }
        }
        /* Because this is called with all arrays, we need to
         *  change the output if the kind of the scalar is different
         *  than that of the input and inplace is not on ---
         *  (thus, the input should be up-cast)
         */
        else if (exponent == 2.0) {
            fastop = n_ops.multiply;
            if (inplace) {
                return PyArray_GenericInplaceBinaryFunction
                    (a1, (PyObject *)a1, fastop);
            }
            else {
                PyArray_Descr *dtype = NULL;
                PyObject *res;

                /* We only special-case the FLOAT_SCALAR and integer types */
                if (kind == NPY_FLOAT_SCALAR && PyArray_ISINTEGER(a1)) {
                    dtype = PyArray_DescrFromType(NPY_DOUBLE);
                    a1 = (PyArrayObject *)PyArray_CastToType(a1, dtype,
                            PyArray_ISFORTRAN(a1));
                    if (a1 == NULL) {
                        return NULL;
                    }
                }
                else {
                    Py_INCREF(a1);
                }
                res = PyArray_GenericBinaryFunction(a1, (PyObject *)a1, fastop);
                Py_DECREF(a1);
                return res;
            }
        }
    }
    return NULL;
}
Exemplo n.º 9
0
/*NUMPY_API
 * Clip
 */
NPY_NO_EXPORT PyObject *
PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *out)
{
    PyArray_FastClipFunc *func;
    int outgood = 0, ingood = 0;
    PyArrayObject *maxa = NULL;
    PyArrayObject *mina = NULL;
    PyArrayObject *newout = NULL, *newin = NULL;
    PyArray_Descr *indescr = NULL, *newdescr = NULL;
    char *max_data, *min_data;
    PyObject *zero;

    /* Treat None the same as NULL */
    if (min == Py_None) {
        min = NULL;
    }
    if (max == Py_None) {
        max = NULL;
    }

    if ((max == NULL) && (min == NULL)) {
        PyErr_SetString(PyExc_ValueError,
                        "array_clip: must set either max or min");
        return NULL;
    }

    func = PyArray_DESCR(self)->f->fastclip;
    if (func == NULL
        || (min != NULL && !PyArray_CheckAnyScalar(min))
        || (max != NULL && !PyArray_CheckAnyScalar(max))
        || PyArray_ISBYTESWAPPED(self)
        || (out && PyArray_ISBYTESWAPPED(out))) {
        return _slow_array_clip(self, min, max, out);
    }
    /* Use the fast scalar clip function */

    /* First we need to figure out the correct type */
    if (min != NULL) {
        indescr = PyArray_DescrFromObject(min, NULL);
        if (indescr == NULL) {
            goto fail;
        }
    }
    if (max != NULL) {
        newdescr = PyArray_DescrFromObject(max, indescr);
        Py_XDECREF(indescr);
        indescr = NULL;
        if (newdescr == NULL) {
            goto fail;
        }
    }
    else {
        /* Steal the reference */
        newdescr = indescr;
        indescr = NULL;
    }


    /*
     * Use the scalar descriptor only if it is of a bigger
     * KIND than the input array (and then find the
     * type that matches both).
     */
    if (PyArray_ScalarKind(newdescr->type_num, NULL) >
        PyArray_ScalarKind(PyArray_DESCR(self)->type_num, NULL)) {
        indescr = PyArray_PromoteTypes(newdescr, PyArray_DESCR(self));
        if (indescr == NULL) {
            goto fail;
        }
        func = indescr->f->fastclip;
        if (func == NULL) {
            Py_DECREF(indescr);
            return _slow_array_clip(self, min, max, out);
        }
    }
    else {
        indescr = PyArray_DESCR(self);
        Py_INCREF(indescr);
    }
    Py_DECREF(newdescr);
    newdescr = NULL;

    if (!PyDataType_ISNOTSWAPPED(indescr)) {
        PyArray_Descr *descr2;
        descr2 = PyArray_DescrNewByteorder(indescr, '=');
        Py_DECREF(indescr);
        indescr = NULL;
        if (descr2 == NULL) {
            goto fail;
        }
        indescr = descr2;
    }

    /* Convert max to an array */
    if (max != NULL) {
        Py_INCREF(indescr);
        maxa = (PyArrayObject *)PyArray_FromAny(max, indescr, 0, 0,
                                 NPY_ARRAY_DEFAULT, NULL);
        if (maxa == NULL) {
            goto fail;
        }
    }

    /*
     * If we are unsigned, then make sure min is not < 0
     * This is to match the behavior of _slow_array_clip
     *
     * We allow min and max to go beyond the limits
     * for other data-types in which case they
     * are interpreted as their modular counterparts.
    */
    if (min != NULL) {
        if (PyArray_ISUNSIGNED(self)) {
            int cmp;
            zero = PyInt_FromLong(0);
            cmp = PyObject_RichCompareBool(min, zero, Py_LT);
            if (cmp == -1) {
                Py_DECREF(zero);
                goto fail;
            }
            if (cmp == 1) {
                min = zero;
            }
            else {
                Py_DECREF(zero);
                Py_INCREF(min);
            }
        }
        else {
            Py_INCREF(min);
        }

        /* Convert min to an array */
        Py_INCREF(indescr);
        mina = (PyArrayObject *)PyArray_FromAny(min, indescr, 0, 0,
                                 NPY_ARRAY_DEFAULT, NULL);
        Py_DECREF(min);
        if (mina == NULL) {
            goto fail;
        }
    }

    /*
     * Check to see if input is single-segment, aligned,
     * and in native byteorder
     */
    if (PyArray_ISONESEGMENT(self) &&
                            PyArray_CHKFLAGS(self, NPY_ARRAY_ALIGNED) &&
                            PyArray_ISNOTSWAPPED(self) &&
                            (PyArray_DESCR(self) == indescr)) {
        ingood = 1;
    }
    if (!ingood) {
        int flags;

        if (PyArray_ISFORTRAN(self)) {
            flags = NPY_ARRAY_FARRAY;
        }
        else {
            flags = NPY_ARRAY_CARRAY;
        }
        Py_INCREF(indescr);
        newin = (PyArrayObject *)PyArray_FromArray(self, indescr, flags);
        if (newin == NULL) {
            goto fail;
        }
    }
    else {
        newin = self;
        Py_INCREF(newin);
    }

    /*
     * At this point, newin is a single-segment, aligned, and correct
     * byte-order array of the correct type
     *
     * if ingood == 0, then it is a copy, otherwise,
     * it is the original input.
     */

    /*
     * If we have already made a copy of the data, then use
     * that as the output array
     */
    if (out == NULL && !ingood) {
        out = newin;
    }

    /*
     * Now, we know newin is a usable array for fastclip,
     * we need to make sure the output array is available
     * and usable
     */
    if (out == NULL) {
        Py_INCREF(indescr);
        out = (PyArrayObject*)PyArray_NewFromDescr(Py_TYPE(self),
                                            indescr, PyArray_NDIM(self),
                                            PyArray_DIMS(self),
                                            NULL, NULL,
                                            PyArray_ISFORTRAN(self),
                                            (PyObject *)self);
        if (out == NULL) {
            goto fail;
        }

        outgood = 1;
    }
    else Py_INCREF(out);
    /* Input is good at this point */
    if (out == newin) {
        outgood = 1;
    }


    /* make sure the shape of the output array is the same */
    if (!PyArray_SAMESHAPE(newin, out)) {
        PyErr_SetString(PyExc_ValueError, "clip: Output array must have the"
                        "same shape as the input.");
        goto fail;
    }

    if (!outgood && PyArray_EQUIVALENTLY_ITERABLE(
                            self, out, PyArray_TRIVIALLY_ITERABLE_OP_READ,
                            PyArray_TRIVIALLY_ITERABLE_OP_NOREAD) &&
                        PyArray_CHKFLAGS(out, NPY_ARRAY_ALIGNED) &&
                        PyArray_ISNOTSWAPPED(out) &&
                        PyArray_EquivTypes(PyArray_DESCR(out), indescr)) {
        outgood = 1;
    }

    /*
     * Do we still not have a suitable output array?
     * Create one, now. No matter why the array is not suitable a copy has
     * to be made. This may be just to avoid memory overlap though.
     */
    if (!outgood) {
        int oflags;
        if (PyArray_ISFORTRAN(self)) {
            oflags = NPY_ARRAY_FARRAY;
        }
        else {
            oflags = NPY_ARRAY_CARRAY;
        }
        oflags |= (NPY_ARRAY_WRITEBACKIFCOPY | NPY_ARRAY_FORCECAST |
                   NPY_ARRAY_ENSURECOPY);
        Py_INCREF(indescr);
        newout = (PyArrayObject*)PyArray_FromArray(out, indescr, oflags);
        if (newout == NULL) {
            goto fail;
        }
    }
    else {
        newout = out;
        Py_INCREF(newout);
    }

    /* Now we can call the fast-clip function */
    min_data = max_data = NULL;
    if (mina != NULL) {
        min_data = PyArray_DATA(mina);
    }
    if (maxa != NULL) {
        max_data = PyArray_DATA(maxa);
    }
    func(PyArray_DATA(newin), PyArray_SIZE(newin), min_data, max_data, PyArray_DATA(newout));

    /* Clean up temporary variables */
    Py_XDECREF(indescr);
    Py_XDECREF(newdescr);
    Py_XDECREF(mina);
    Py_XDECREF(maxa);
    Py_DECREF(newin);
    /* Copy back into out if out was not already a nice array. */
    PyArray_ResolveWritebackIfCopy(newout);
    Py_DECREF(newout);
    return (PyObject *)out;

 fail:
    Py_XDECREF(indescr);
    Py_XDECREF(newdescr);
    Py_XDECREF(maxa);
    Py_XDECREF(mina);
    Py_XDECREF(newin);
    PyArray_DiscardWritebackIfCopy(newout);
    Py_XDECREF(newout);
    return NULL;
}
Exemplo n.º 10
0
/*NUMPY_API
 * Round
 */
NPY_NO_EXPORT PyObject *
PyArray_Round(PyArrayObject *a, int decimals, PyArrayObject *out)
{
    PyObject *f, *ret = NULL, *tmp, *op1, *op2;
    int ret_int=0;
    PyArray_Descr *my_descr;
    if (out && (PyArray_SIZE(out) != PyArray_SIZE(a))) {
        PyErr_SetString(PyExc_ValueError,
                        "invalid output shape");
        return NULL;
    }
    if (PyArray_ISCOMPLEX(a)) {
        PyObject *part;
        PyObject *round_part;
        PyObject *arr;
        int res;

        if (out) {
            arr = (PyObject *)out;
            Py_INCREF(arr);
        }
        else {
            arr = PyArray_Copy(a);
            if (arr == NULL) {
                return NULL;
            }
        }

        /* arr.real = a.real.round(decimals) */
        part = PyObject_GetAttrString((PyObject *)a, "real");
        if (part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        part = PyArray_EnsureAnyArray(part);
        round_part = PyArray_Round((PyArrayObject *)part,
                                   decimals, NULL);
        Py_DECREF(part);
        if (round_part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        res = PyObject_SetAttrString(arr, "real", round_part);
        Py_DECREF(round_part);
        if (res < 0) {
            Py_DECREF(arr);
            return NULL;
        }

        /* arr.imag = a.imag.round(decimals) */
        part = PyObject_GetAttrString((PyObject *)a, "imag");
        if (part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        part = PyArray_EnsureAnyArray(part);
        round_part = PyArray_Round((PyArrayObject *)part,
                                   decimals, NULL);
        Py_DECREF(part);
        if (round_part == NULL) {
            Py_DECREF(arr);
            return NULL;
        }
        res = PyObject_SetAttrString(arr, "imag", round_part);
        Py_DECREF(round_part);
        if (res < 0) {
            Py_DECREF(arr);
            return NULL;
        }
        return arr;
    }
    /* do the most common case first */
    if (decimals >= 0) {
        if (PyArray_ISINTEGER(a)) {
            if (out) {
                if (PyArray_AssignArray(out, a,
                            NULL, NPY_DEFAULT_ASSIGN_CASTING) < 0) {
                    return NULL;
                }
                Py_INCREF(out);
                return (PyObject *)out;
            }
            else {
                Py_INCREF(a);
                return (PyObject *)a;
            }
        }
        if (decimals == 0) {
            if (out) {
                return PyObject_CallFunction(n_ops.rint, "OO", a, out);
            }
            return PyObject_CallFunction(n_ops.rint, "O", a);
        }
        op1 = n_ops.multiply;
        op2 = n_ops.true_divide;
    }
    else {
        op1 = n_ops.true_divide;
        op2 = n_ops.multiply;
        decimals = -decimals;
    }
    if (!out) {
        if (PyArray_ISINTEGER(a)) {
            ret_int = 1;
            my_descr = PyArray_DescrFromType(NPY_DOUBLE);
        }
        else {
            Py_INCREF(PyArray_DESCR(a));
            my_descr = PyArray_DESCR(a);
        }
        out = (PyArrayObject *)PyArray_Empty(PyArray_NDIM(a), PyArray_DIMS(a),
                                             my_descr,
                                             PyArray_ISFORTRAN(a));
        if (out == NULL) {
            return NULL;
        }
    }
    else {
        Py_INCREF(out);
    }
    f = PyFloat_FromDouble(power_of_ten(decimals));
    if (f == NULL) {
        return NULL;
    }
    ret = PyObject_CallFunction(op1, "OOO", a, f, out);
    if (ret == NULL) {
        goto finish;
    }
    tmp = PyObject_CallFunction(n_ops.rint, "OO", ret, ret);
    if (tmp == NULL) {
        Py_DECREF(ret);
        ret = NULL;
        goto finish;
    }
    Py_DECREF(tmp);
    tmp = PyObject_CallFunction(op2, "OOO", ret, f, ret);
    if (tmp == NULL) {
        Py_DECREF(ret);
        ret = NULL;
        goto finish;
    }
    Py_DECREF(tmp);

 finish:
    Py_DECREF(f);
    Py_DECREF(out);
    if (ret_int) {
        Py_INCREF(PyArray_DESCR(a));
        tmp = PyArray_CastToType((PyArrayObject *)ret,
                                 PyArray_DESCR(a), PyArray_ISFORTRAN(a));
        Py_DECREF(ret);
        return tmp;
    }
    return ret;
}
Exemplo n.º 11
0
/*NUMPY_API*/
NPY_NO_EXPORT int
PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
{
    int ret;
    PyArrayObject *src;
    PyArray_Descr *dtype = NULL;
    int ndim = 0;
    npy_intp dims[NPY_MAXDIMS];

    Py_INCREF(src_object);
    /*
     * Special code to mimic Numeric behavior for
     * character arrays.
     */
    if (dest->descr->type == PyArray_CHARLTR && dest->nd > 0 \
        && PyString_Check(src_object)) {
        npy_intp n_new, n_old;
        char *new_string;
        PyObject *tmp;

        n_new = dest->dimensions[dest->nd-1];
        n_old = PyString_Size(src_object);
        if (n_new > n_old) {
            new_string = (char *)malloc(n_new);
            memmove(new_string, PyString_AS_STRING(src_object), n_old);
            memset(new_string + n_old, ' ', n_new - n_old);
            tmp = PyString_FromStringAndSize(new_string, n_new);
            free(new_string);
            Py_DECREF(src_object);
            src_object = tmp;
        }
    }

    /*
     * Get either an array object we can copy from, or its parameters
     * if there isn't a convenient array available.
     */
    if (PyArray_GetArrayParamsFromObject(src_object, PyArray_DESCR(dest),
                0, &dtype, &ndim, dims, &src, NULL) < 0) {
        Py_DECREF(src_object);
        return -1;
    }

    /* If it's not an array, either assign from a sequence or as a scalar */
    if (src == NULL) {
        /* If the input is scalar */
        if (ndim == 0) {
            /* If there's one dest element and src is a Python scalar */
            if (PyArray_IsScalar(src_object, Generic)) {
                src = (PyArrayObject *)PyArray_FromScalar(src_object, dtype);
                if (src == NULL) {
                    Py_DECREF(src_object);
                    return -1;
                }
            }
            else {
                if (PyArray_SIZE(dest) == 1) {
                    Py_DECREF(dtype);
                    return PyArray_DESCR(dest)->f->setitem(src_object,
                                                    PyArray_DATA(dest), dest);
                }
                else {
                    src = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
                                                        dtype, 0, NULL, NULL,
                                                        NULL, 0, NULL);
                    if (src == NULL) {
                        Py_DECREF(src_object);
                        return -1;
                    }
                    if (PyArray_DESCR(src)->f->setitem(src_object,
                                                PyArray_DATA(src), src) < 0) {
                        Py_DECREF(src_object);
                        Py_DECREF(src);
                        return -1;
                    }
                }
            }
        }
        else {
            /*
             * If there are more than enough dims, use AssignFromSequence
             * because it can handle this style of broadcasting.
             */
            if (ndim >= PyArray_NDIM(dest)) {
                int res;
                Py_DECREF(dtype);
                res = PyArray_AssignFromSequence(dest, src_object);
                Py_DECREF(src_object);
                return res;
            }
            /* Otherwise convert to an array and do an array-based copy */
            src = (PyArrayObject *)PyArray_NewFromDescr(&PyArray_Type,
                                        dtype, ndim, dims, NULL, NULL,
                                        PyArray_ISFORTRAN(dest), NULL);
            if (src == NULL) {
                Py_DECREF(src_object);
                return -1;
            }
            if (PyArray_AssignFromSequence(src, src_object) < 0) {
                Py_DECREF(src);
                Py_DECREF(src_object);
                return -1;
            }
        }
    }

    /* If it's an array, do a move (handling possible overlapping data) */
    ret = PyArray_MoveInto(dest, src);
    Py_DECREF(src);
    Py_DECREF(src_object);
    return ret;
}