Пример #1
0
static PyObject *IIRsymorder2(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
  PyObject *sig=NULL;
  PyArrayObject *a_sig=NULL, *out=NULL;
  double r, omega;
  double precision = -1.0;
  int thetype, N, ret;
  npy_intp outstrides, instrides;

  if (!PyArg_ParseTuple(args, "Odd|d", &sig, &r, &omega, &precision))
    return NULL;

  thetype = PyArray_ObjectType(sig, PyArray_FLOAT);
  thetype = NPY_MIN(thetype, PyArray_DOUBLE);
  a_sig = (PyArrayObject *)PyArray_FromObject(sig, thetype, 1, 1);
  
  if ((a_sig == NULL)) goto fail;
  
  out = (PyArrayObject *)PyArray_SimpleNew(1,DIMS(a_sig),thetype);
  if (out == NULL) goto fail;
  N = DIMS(a_sig)[0];

  convert_strides(STRIDES(a_sig), &instrides, ELSIZE(a_sig), 1);
  outstrides = 1;

  switch (thetype) {
  case PyArray_FLOAT:
    if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-6;      
    ret = S_IIR_forback2 (r, omega, (float *)DATA(a_sig), 
			  (float *)DATA(out), N,
			  instrides, outstrides, precision);
    break;
  case PyArray_DOUBLE:
    if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-11;
    ret = D_IIR_forback2 (r, omega, (double *)DATA(a_sig), 
			  (double *)DATA(out), N,
			  instrides, outstrides, precision);
    break;
  default:
    PYERR("Incorrect type.");
  }
  
  if (ret < 0) PYERR("Problem occured inside routine.");

  Py_DECREF(a_sig);
  return PyArray_Return(out);
 
 fail:
  Py_XDECREF(a_sig);
  Py_XDECREF(out);
  return NULL;

}
Пример #2
0
  static void* convertible(PyObject *obj_ptr)
  {
    // Check for a null pointer.
    if(!obj_ptr)
      {
        //THROW_TYPE_ERROR("PyObject pointer was null");
        return 0;
      }

    // Make sure this is a numpy array.
    if (!PyArray_Check(obj_ptr))
      {
        //THROW_TYPE_ERROR("Conversion is only defined for numpy array and matrix types");
        return 0;
      }

    // Check the type of the array.
    int npyType = PyArray_ObjectType(obj_ptr, 0);
    
    if(!TypeToNumPy<scalar_t>::canConvert(npyType))
      {
        //THROW_TYPE_ERROR("Can not convert " << npyArrayTypeString(obj_ptr) << " to " << toString() 
        //                 << ". Mismatched types.");
        return 0;
      }

    

    // Check the array dimensions.
    int nd = PyArray_NDIM(obj_ptr);
    
    if(nd != 1 && nd != 2)
      {
	THROW_TYPE_ERROR("Conversion is only valid for arrays with 1 or 2 dimensions. Argument has " << nd << " dimensions");
      }

    if(nd == 1)
      {
	checkVectorSizes(obj_ptr);
      }
    else 
      {
	// Two-dimensional matrix type.
	checkMatrixSizes(obj_ptr);
      }


    return obj_ptr;
  }
Пример #3
0
static PyObject *qspline2d(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
  PyObject *image=NULL;
  PyArrayObject *a_image=NULL, *ck=NULL;
  double lambda = 0.0;
  double precision = -1.0;
  int thetype, M, N, retval=0;
  npy_intp outstrides[2], instrides[2];

  if (!PyArg_ParseTuple(args, "O|dd", &image, &lambda, &precision)) return NULL;

  if (lambda != 0.0) PYERR("Smoothing spline not yet implemented.");

  thetype = PyArray_ObjectType(image, PyArray_FLOAT);
  thetype = NPY_MIN(thetype, PyArray_DOUBLE);
  a_image = (PyArrayObject *)PyArray_FromObject(image, thetype, 2, 2);
  if (a_image == NULL) goto fail;
 
  ck = (PyArrayObject *)PyArray_SimpleNew(2,DIMS(a_image),thetype);
  if (ck == NULL) goto fail;
  M = DIMS(a_image)[0];
  N = DIMS(a_image)[1];

  convert_strides(STRIDES(a_image), instrides, ELSIZE(a_image), 2);
  outstrides[0] = N;
  outstrides[1] = 1;

  if (thetype == PyArray_FLOAT) {
    if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-3;
    retval = S_quadratic_spline2D((float *)DATA(a_image), (float *)DATA(ck), M, N, lambda, instrides, outstrides, precision);
  }
  else if (thetype == PyArray_DOUBLE) {
    if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-6;
    retval = D_quadratic_spline2D((double *)DATA(a_image), (double *)DATA(ck), M, N, lambda, instrides, outstrides, precision);
  }

  if (retval == -3) PYERR("Precision too high.  Error did not converge.");
  if (retval < 0) PYERR("Problem occured inside routine");

  Py_DECREF(a_image);
  return PyArray_Return(ck);
 
 fail:
  Py_XDECREF(a_image);
  Py_XDECREF(ck);
  return NULL;

}
Пример #4
0
inline std::string npyArrayTypeString(PyObject * obj_ptr)
{
  std::stringstream ss;
  int nd = PyArray_NDIM(obj_ptr);
  ss << "numpy.array<" << npyTypeToString(PyArray_ObjectType(obj_ptr, 0)) << ">[";
  if(nd > 0)
    {
      ss << PyArray_DIM(obj_ptr, 0);
      for(int i = 1; i < nd; i++)
	{
	  ss << ", " << PyArray_DIM(obj_ptr, i);
	}
    }
  ss << "]";
  return ss.str();
}
static PyObject*
test_neighborhood_iterator_oob(PyObject* NPY_UNUSED(self), PyObject* args)
{
    PyObject *x, *out, *b1, *b2;
    PyArrayObject *ax;
    PyArrayIterObject *itx;
    int i, typenum, mode1, mode2, st;
    npy_intp bounds[NPY_MAXDIMS*2];
    PyArrayNeighborhoodIterObject *niterx1, *niterx2;

    if (!PyArg_ParseTuple(args, "OOiOi", &x, &b1, &mode1, &b2, &mode2)) {
        return NULL;
    }

    if (!PySequence_Check(b1) || !PySequence_Check(b2)) {
        return NULL;
    }

    typenum = PyArray_ObjectType(x, 0);

    ax = (PyArrayObject*)PyArray_FromObject(x, typenum, 1, 10);
    if (ax == NULL) {
        return NULL;
    }
    if (PySequence_Size(b1) != 2 * PyArray_NDIM(ax)) {
        PyErr_SetString(PyExc_ValueError,
                "bounds sequence 1 size not compatible with x input");
        goto clean_ax;
    }
    if (PySequence_Size(b2) != 2 * PyArray_NDIM(ax)) {
        PyErr_SetString(PyExc_ValueError,
                "bounds sequence 2 size not compatible with x input");
        goto clean_ax;
    }

    out = PyList_New(0);
    if (out == NULL) {
        goto clean_ax;
    }

    itx = (PyArrayIterObject*)PyArray_IterNew(x);
    if (itx == NULL) {
        goto clean_out;
    }

    /* Compute boundaries for the neighborhood iterator */
    for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) {
        PyObject* bound;
        bound = PySequence_GetItem(b1, i);
        if (bounds == NULL) {
            goto clean_itx;
        }
        if (!PyInt_Check(bound)) {
            PyErr_SetString(PyExc_ValueError,
                    "bound not long");
            Py_DECREF(bound);
            goto clean_itx;
        }
        bounds[i] = PyInt_AsLong(bound);
        Py_DECREF(bound);
    }

    /* Create the neighborhood iterator */
    niterx1 = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew(
                    (PyArrayIterObject*)itx, bounds,
                    mode1, NULL);
    if (niterx1 == NULL) {
        goto clean_out;
    }

    for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) {
        PyObject* bound;
        bound = PySequence_GetItem(b2, i);
        if (bounds == NULL) {
            goto clean_itx;
        }
        if (!PyInt_Check(bound)) {
            PyErr_SetString(PyExc_ValueError,
                    "bound not long");
            Py_DECREF(bound);
            goto clean_itx;
        }
        bounds[i] = PyInt_AsLong(bound);
        Py_DECREF(bound);
    }

    niterx2 = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew(
                    (PyArrayIterObject*)niterx1, bounds,
                    mode2, NULL);
    if (niterx1 == NULL) {
        goto clean_niterx1;
    }

    switch (typenum) {
        case NPY_DOUBLE:
            st = copy_double_double(niterx1, niterx2, bounds, &out);
            break;
        default:
            PyErr_SetString(PyExc_ValueError,
                    "Type not supported");
            goto clean_niterx2;
    }

    if (st) {
        goto clean_niterx2;
    }

    Py_DECREF(niterx2);
    Py_DECREF(niterx1);
    Py_DECREF(itx);
    Py_DECREF(ax);
    return out;

clean_niterx2:
    Py_DECREF(niterx2);
clean_niterx1:
    Py_DECREF(niterx1);
clean_itx:
    Py_DECREF(itx);
clean_out:
    Py_DECREF(out);
clean_ax:
    Py_DECREF(ax);
    return NULL;
}
static PyObject*
test_neighborhood_iterator(PyObject* NPY_UNUSED(self), PyObject* args)
{
    PyObject *x, *fill, *out, *b;
    PyArrayObject *ax, *afill;
    PyArrayIterObject *itx;
    int i, typenum, mode, st;
    npy_intp bounds[NPY_MAXDIMS*2];
    PyArrayNeighborhoodIterObject *niterx;

    if (!PyArg_ParseTuple(args, "OOOi", &x, &b, &fill, &mode)) {
        return NULL;
    }

    if (!PySequence_Check(b)) {
        return NULL;
    }

    typenum = PyArray_ObjectType(x, 0);
    typenum = PyArray_ObjectType(fill, typenum);

    ax = (PyArrayObject*)PyArray_FromObject(x, typenum, 1, 10);
    if (ax == NULL) {
        return NULL;
    }
    if (PySequence_Size(b) != 2 * PyArray_NDIM(ax)) {
        PyErr_SetString(PyExc_ValueError,
                "bounds sequence size not compatible with x input");
        goto clean_ax;
    }

    out = PyList_New(0);
    if (out == NULL) {
        goto clean_ax;
    }

    itx = (PyArrayIterObject*)PyArray_IterNew(x);
    if (itx == NULL) {
        goto clean_out;
    }

    /* Compute boundaries for the neighborhood iterator */
    for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) {
        PyObject* bound;
        bound = PySequence_GetItem(b, i);
        if (bounds == NULL) {
            goto clean_itx;
        }
        if (!PyInt_Check(bound)) {
            PyErr_SetString(PyExc_ValueError,
                    "bound not long");
            Py_DECREF(bound);
            goto clean_itx;
        }
        bounds[i] = PyInt_AsLong(bound);
        Py_DECREF(bound);
    }

    /* Create the neighborhood iterator */
    afill = NULL;
    if (mode == NPY_NEIGHBORHOOD_ITER_CONSTANT_PADDING) {
            afill = (PyArrayObject *)PyArray_FromObject(fill, typenum, 0, 0);
            if (afill == NULL) {
            goto clean_itx;
        }
    }

    niterx = (PyArrayNeighborhoodIterObject*)PyArray_NeighborhoodIterNew(
                    (PyArrayIterObject*)itx, bounds, mode, afill);
    if (niterx == NULL) {
        goto clean_afill;
    }

    switch (typenum) {
        case NPY_OBJECT:
            st = copy_object(itx, niterx, bounds, &out);
            break;
        case NPY_INT:
            st = copy_int(itx, niterx, bounds, &out);
            break;
        case NPY_DOUBLE:
            st = copy_double(itx, niterx, bounds, &out);
            break;
        default:
            PyErr_SetString(PyExc_ValueError,
                    "Type not supported");
            goto clean_niterx;
    }

    if (st) {
        goto clean_niterx;
    }

    Py_DECREF(niterx);
    Py_XDECREF(afill);
    Py_DECREF(itx);

    Py_DECREF(ax);

    return out;

clean_niterx:
    Py_DECREF(niterx);
clean_afill:
    Py_XDECREF(afill);
clean_itx:
    Py_DECREF(itx);
clean_out:
    Py_DECREF(out);
clean_ax:
    Py_DECREF(ax);
    return NULL;
}
Пример #7
0
static PyObject *IIRsymorder1(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
  PyObject *sig=NULL;
  PyArrayObject *a_sig=NULL, *out=NULL;
  Py_complex c0, z1;
  double precision = -1.0;
  int thetype, N, ret;
  npy_intp outstrides, instrides;

  if (!PyArg_ParseTuple(args, "ODD|d", &sig, &c0, &z1, &precision))
    return NULL;

  thetype = PyArray_ObjectType(sig, PyArray_FLOAT);
  thetype = NPY_MIN(thetype, PyArray_CDOUBLE);
  a_sig = (PyArrayObject *)PyArray_FromObject(sig, thetype, 1, 1);
  
  if ((a_sig == NULL)) goto fail;
  
  out = (PyArrayObject *)PyArray_SimpleNew(1,DIMS(a_sig),thetype);
  if (out == NULL) goto fail;
  N = DIMS(a_sig)[0];

  convert_strides(STRIDES(a_sig), &instrides, ELSIZE(a_sig), 1);
  outstrides = 1;

  switch (thetype) {
  case PyArray_FLOAT:
    {
      float rc0 = c0.real;
      float rz1 = z1.real;

      if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-6;      
      ret = S_IIR_forback1 (rc0, rz1, (float *)DATA(a_sig), 
			    (float *)DATA(out), N,
			    instrides, outstrides, (float )precision);
    }
    break;
  case PyArray_DOUBLE:
    {
      double rc0 = c0.real;
      double rz1 = z1.real;

      if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-11;
      ret = D_IIR_forback1 (rc0, rz1, (double *)DATA(a_sig), 
			    (double *)DATA(out), N,
			    instrides, outstrides, precision);
    }
    break;
#ifdef __GNUC__
  case PyArray_CFLOAT:
    {
      __complex__ float zc0 = c0.real + 1.0i*c0.imag;
      __complex__ float zz1 = z1.real + 1.0i*z1.imag;      
      if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-6;
      ret = C_IIR_forback1 (zc0, zz1, (__complex__ float *)DATA(a_sig), 
			    (__complex__ float *)DATA(out), N,
			    instrides, outstrides, (float )precision);
    }
    break;
  case PyArray_CDOUBLE:
    {
      __complex__ double zc0 = c0.real + 1.0i*c0.imag;
      __complex__ double zz1 = z1.real + 1.0i*z1.imag;      
      if ((precision <= 0.0) || (precision > 1.0)) precision = 1e-11;
      ret = Z_IIR_forback1 (zc0, zz1, (__complex__ double *)DATA(a_sig), 
			    (__complex__ double *)DATA(out), N,
			    instrides, outstrides, precision);
    }
    break;
#endif
  default:
    PYERR("Incorrect type.");
  }

  if (ret == 0) {
    Py_DECREF(a_sig);
    return PyArray_Return(out);
  }

  if (ret == -1) PYERR("Could not allocate enough memory.");
  if (ret == -2) PYERR("|z1| must be less than 1.0");
  if (ret == -3) PYERR("Sum to find symmetric boundary conditions did not converge.");

  PYERR("Unknown error.");

 
 fail:
  Py_XDECREF(a_sig);
  Py_XDECREF(out);
  return NULL;

}
Пример #8
0
static PyObject *FIRsepsym2d(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
  PyObject *image=NULL, *hrow=NULL, *hcol=NULL;
  PyArrayObject *a_image=NULL, *a_hrow=NULL, *a_hcol=NULL, *out=NULL;
  int thetype, M, N, ret;
  npy_intp outstrides[2], instrides[2];

  if (!PyArg_ParseTuple(args, "OOO", &image, &hrow, &hcol)) return NULL;

  thetype = PyArray_ObjectType(image, PyArray_FLOAT);
  thetype = NPY_MIN(thetype, PyArray_CDOUBLE);
  a_image = (PyArrayObject *)PyArray_FromObject(image, thetype, 2, 2);
  a_hrow = (PyArrayObject *)PyArray_ContiguousFromObject(hrow, thetype, 1, 1);
  a_hcol = (PyArrayObject *)PyArray_ContiguousFromObject(hcol, thetype, 1, 1);
  
  if ((a_image == NULL) || (a_hrow == NULL) || (a_hcol==NULL)) goto fail;
  
  out = (PyArrayObject *)PyArray_SimpleNew(2,DIMS(a_image),thetype);
  if (out == NULL) goto fail;
  M = DIMS(a_image)[0];
  N = DIMS(a_image)[1];

  convert_strides(STRIDES(a_image), instrides, ELSIZE(a_image), 2);
  outstrides[0] = N;
  outstrides[1] = 1;

  switch (thetype) {
  case PyArray_FLOAT:
    ret = S_separable_2Dconvolve_mirror((float *)DATA(a_image), 
					(float *)DATA(out), M, N,
					(float *)DATA(a_hrow), 
					(float *)DATA(a_hcol),
					DIMS(a_hrow)[0], DIMS(a_hcol)[0], 
					instrides, outstrides);
    break;
  case PyArray_DOUBLE:
    ret = D_separable_2Dconvolve_mirror((double *)DATA(a_image), 
					(double *)DATA(out), M, N, 
					(double *)DATA(a_hrow), 
					(double *)DATA(a_hcol),
					DIMS(a_hrow)[0], DIMS(a_hcol)[0], 
					instrides, outstrides);
    break;
#ifdef __GNUC__
  case PyArray_CFLOAT:
    ret = C_separable_2Dconvolve_mirror((__complex__ float *)DATA(a_image), 
					(__complex__ float *)DATA(out), M, N, 
					(__complex__ float *)DATA(a_hrow), 
					(__complex__ float *)DATA(a_hcol),
					DIMS(a_hrow)[0], DIMS(a_hcol)[0], 
					instrides, outstrides);
    break;
  case PyArray_CDOUBLE:
    ret = Z_separable_2Dconvolve_mirror((__complex__ double *)DATA(a_image), 
					(__complex__ double *)DATA(out), M, N, 
					(__complex__ double *)DATA(a_hrow), 
					(__complex__ double *)DATA(a_hcol),
					DIMS(a_hrow)[0], DIMS(a_hcol)[0], 
					instrides, outstrides);
    break;
#endif
  default:
    PYERR("Incorrect type.");
  }
  
  if (ret < 0) PYERR("Problem occured inside routine.");

  Py_DECREF(a_image);
  Py_DECREF(a_hrow);
  Py_DECREF(a_hcol);
  return PyArray_Return(out);
 
 fail:
  Py_XDECREF(a_image);
  Py_XDECREF(a_hrow);
  Py_XDECREF(a_hcol);
  Py_XDECREF(out);
  return NULL;

}
Пример #9
0
static PyObject *
dotblas_matrixproduct(PyObject *dummy, PyObject *args)
{
    PyObject *op1, *op2;
    PyArrayObject *ap1=NULL, *ap2=NULL, *ret=NULL;
    int j, l, lda, ldb, ldc;
    int typenum, nd;
    intp ap1stride=0;
    intp dimensions[MAX_DIMS];
    intp numbytes;
    static const float oneF[2] = {1.0, 0.0};
    static const float zeroF[2] = {0.0, 0.0};
    static const double oneD[2] = {1.0, 0.0};
    static const double zeroD[2] = {0.0, 0.0};
    double prior1, prior2;
    PyTypeObject *subtype;
    PyArray_Descr *dtype;
    MatrixShape ap1shape, ap2shape;

    if (!PyArg_ParseTuple(args, "OO", &op1, &op2)) return NULL;

    /*
     * "Matrix product" using the BLAS.
     * Only works for float double and complex types.
     */

    typenum = PyArray_ObjectType(op1, 0);
    typenum = PyArray_ObjectType(op2, typenum);

    /* This function doesn't handle other types */
    if ((typenum != PyArray_DOUBLE && typenum != PyArray_CDOUBLE &&
            typenum != PyArray_FLOAT && typenum != PyArray_CFLOAT)) {
        return PyArray_Return((PyArrayObject *)PyArray_MatrixProduct(op1, op2));
    }

    dtype = PyArray_DescrFromType(typenum);
    ap1 = (PyArrayObject *)PyArray_FromAny(op1, dtype, 0, 0, ALIGNED, NULL);
    if (ap1 == NULL) return NULL;
    Py_INCREF(dtype);
    ap2 = (PyArrayObject *)PyArray_FromAny(op2, dtype, 0, 0, ALIGNED, NULL);
    if (ap2 == NULL) goto fail;


    if ((ap1->nd > 2) || (ap2->nd > 2)) {
        /* This function doesn't handle dimensions greater than 2
           (or negative striding)  -- other
           than to ensure the dot function is altered
        */
        if (!altered) {
            /* need to alter dot product */
            PyObject *tmp1, *tmp2;
            tmp1 = PyTuple_New(0);
            tmp2 = dotblas_alterdot(NULL, tmp1);
            Py_DECREF(tmp1);
            Py_DECREF(tmp2);
        }
        ret = (PyArrayObject *)PyArray_MatrixProduct((PyObject *)ap1,
                (PyObject *)ap2);
        Py_DECREF(ap1);
        Py_DECREF(ap2);
        return PyArray_Return(ret);
    }

    if (_bad_strides(ap1)) {
        op1 = PyArray_NewCopy(ap1, PyArray_ANYORDER);
        Py_DECREF(ap1);
        ap1 = (PyArrayObject *)op1;
        if (ap1 == NULL) goto fail;
    }
    if (_bad_strides(ap2)) {
        op2 = PyArray_NewCopy(ap2, PyArray_ANYORDER);
        Py_DECREF(ap2);
        ap2 = (PyArrayObject *)op2;
        if (ap2 == NULL) goto fail;
    }
    ap1shape = _select_matrix_shape(ap1);
    ap2shape = _select_matrix_shape(ap2);

    if (ap1shape == _scalar || ap2shape == _scalar) {
        PyArrayObject *oap1, *oap2;
        oap1 = ap1;
        oap2 = ap2;
        /* One of ap1 or ap2 is a scalar */
        if (ap1shape == _scalar) { 		/* Make ap2 the scalar */
            PyArrayObject *t = ap1;
            ap1 = ap2;
            ap2 = t;
            ap1shape = ap2shape;
            ap2shape = _scalar;
        }

        if (ap1shape == _row) ap1stride = ap1->strides[1];
        else if (ap1->nd > 0) ap1stride = ap1->strides[0];

        if (ap1->nd == 0 || ap2->nd == 0) {
            intp *thisdims;
            if (ap1->nd == 0) {
                nd = ap2->nd;
                thisdims = ap2->dimensions;
            }
            else {
                nd = ap1->nd;
                thisdims = ap1->dimensions;
            }
            l = 1;
            for (j=0; j<nd; j++) {
                dimensions[j] = thisdims[j];
                l *= dimensions[j];
            }
        }
        else {
            l = oap1->dimensions[oap1->nd-1];

            if (oap2->dimensions[0] != l) {
                PyErr_SetString(PyExc_ValueError, "matrices are not aligned");
                goto fail;
            }
            nd = ap1->nd + ap2->nd - 2;
            /* nd = 0 or 1 or 2 */
            /* If nd == 0 do nothing ... */
            if (nd == 1) {
                /* Either ap1->nd is 1 dim or ap2->nd is 1 dim
                   and the other is 2-dim */
                dimensions[0] = (oap1->nd == 2) ? oap1->dimensions[0] : oap2->dimensions[1];
                l = dimensions[0];
                /* Fix it so that dot(shape=(N,1), shape=(1,))
                   and dot(shape=(1,), shape=(1,N)) both return
                   an (N,) array (but use the fast scalar code)
                */
            }
            else if (nd == 2) {
                dimensions[0] = oap1->dimensions[0];
                dimensions[1] = oap2->dimensions[1];
                /* We need to make sure that dot(shape=(1,1), shape=(1,N))
                   and dot(shape=(N,1),shape=(1,1)) uses
                   scalar multiplication appropriately
                */
                if (ap1shape == _row) l = dimensions[1];
                else l = dimensions[0];
            }
        }
    }
    else { /* (ap1->nd <= 2 && ap2->nd <= 2) */
        /*  Both ap1 and ap2 are vectors or matrices */
        l = ap1->dimensions[ap1->nd-1];

        if (ap2->dimensions[0] != l) {
            PyErr_SetString(PyExc_ValueError, "matrices are not aligned");
            goto fail;
        }
        nd = ap1->nd+ap2->nd-2;

        if (nd == 1)
            dimensions[0] = (ap1->nd == 2) ? ap1->dimensions[0] : ap2->dimensions[1];
        else if (nd == 2) {
            dimensions[0] = ap1->dimensions[0];
            dimensions[1] = ap2->dimensions[1];
        }
    }

    /* Choose which subtype to return */
    if (ap1->ob_type != ap2->ob_type) {
        prior2 = PyArray_GetPriority((PyObject *)ap2, 0.0);
        prior1 = PyArray_GetPriority((PyObject *)ap1, 0.0);
        subtype = (prior2 > prior1 ? ap2->ob_type : ap1->ob_type);
    }
    else {
        prior1 = prior2 = 0.0;
        subtype = ap1->ob_type;
    }

    ret = (PyArrayObject *)PyArray_New(subtype, nd, dimensions,
                                       typenum, NULL, NULL, 0, 0,
                                       (PyObject *)
                                       (prior2 > prior1 ? ap2 : ap1));

    if (ret == NULL) goto fail;
    numbytes = PyArray_NBYTES(ret);
    memset(ret->data, 0, numbytes);
    if (numbytes==0 || l == 0) {
        Py_DECREF(ap1);
        Py_DECREF(ap2);
        return PyArray_Return(ret);
    }


    if (ap2shape == _scalar) {
        /* Multiplication by a scalar -- Level 1 BLAS */
        /* if ap1shape is a matrix and we are not contiguous, then we can't
           just blast through the entire array using a single
           striding factor */
        NPY_BEGIN_ALLOW_THREADS

        if (typenum == PyArray_DOUBLE) {
            if (l == 1) {
                *((double *)ret->data) = *((double *)ap2->data) * \
                                         *((double *)ap1->data);
            }
            else if (ap1shape != _matrix) {
                cblas_daxpy(l, *((double *)ap2->data), (double *)ap1->data,
                            ap1stride/sizeof(double), (double *)ret->data, 1);
            }
            else {
                int maxind, oind, i, a1s, rets;
                char *ptr, *rptr;
                double val;
                maxind = (ap1->dimensions[0] >= ap1->dimensions[1] ? 0 : 1);
                oind = 1-maxind;
                ptr = ap1->data;
                rptr = ret->data;
                l = ap1->dimensions[maxind];
                val = *((double *)ap2->data);
                a1s = ap1->strides[maxind] / sizeof(double);
                rets = ret->strides[maxind] / sizeof(double);
                for (i=0; i < ap1->dimensions[oind]; i++) {
                    cblas_daxpy(l, val, (double *)ptr, a1s,
                                (double *)rptr, rets);
                    ptr += ap1->strides[oind];
                    rptr += ret->strides[oind];
                }
            }
        }
        else if (typenum == PyArray_CDOUBLE) {
            if (l == 1) {
                cdouble *ptr1, *ptr2, *res;
                ptr1 = (cdouble *)ap2->data;
                ptr2 = (cdouble *)ap1->data;
                res = (cdouble *)ret->data;
                res->real = ptr1->real * ptr2->real - ptr1->imag * ptr2->imag;
                res->imag = ptr1->real * ptr2->imag + ptr1->imag * ptr2->real;
            }
            else if (ap1shape != _matrix) {
                cblas_zaxpy(l, (double *)ap2->data, (double *)ap1->data,
                            ap1stride/sizeof(cdouble), (double *)ret->data, 1);
            }
            else {
                int maxind, oind, i, a1s, rets;
                char *ptr, *rptr;
                double *pval;
                maxind = (ap1->dimensions[0] >= ap1->dimensions[1] ? 0 : 1);
                oind = 1-maxind;
                ptr = ap1->data;
                rptr = ret->data;
                l = ap1->dimensions[maxind];
                pval = (double *)ap2->data;
                a1s = ap1->strides[maxind] / sizeof(cdouble);
                rets = ret->strides[maxind] / sizeof(cdouble);
                for (i=0; i < ap1->dimensions[oind]; i++) {
                    cblas_zaxpy(l, pval, (double *)ptr, a1s,
                                (double *)rptr, rets);
                    ptr += ap1->strides[oind];
                    rptr += ret->strides[oind];
                }
            }
        }
        else if (typenum == PyArray_FLOAT) {
            if (l == 1) {
                *((float *)ret->data) = *((float *)ap2->data) * \
                                        *((float *)ap1->data);
            }
            else if (ap1shape != _matrix) {
                cblas_saxpy(l, *((float *)ap2->data), (float *)ap1->data,
                            ap1stride/sizeof(float), (float *)ret->data, 1);
            }
            else {
                int maxind, oind, i, a1s, rets;
                char *ptr, *rptr;
                float val;
                maxind = (ap1->dimensions[0] >= ap1->dimensions[1] ? 0 : 1);
                oind = 1-maxind;
                ptr = ap1->data;
                rptr = ret->data;
                l = ap1->dimensions[maxind];
                val = *((float *)ap2->data);
                a1s = ap1->strides[maxind] / sizeof(float);
                rets = ret->strides[maxind] / sizeof(float);
                for (i=0; i < ap1->dimensions[oind]; i++) {
                    cblas_saxpy(l, val, (float *)ptr, a1s,
                                (float *)rptr, rets);
                    ptr += ap1->strides[oind];
                    rptr += ret->strides[oind];
                }
            }
        }
        else if (typenum == PyArray_CFLOAT) {
            if (l == 1) {
                cfloat *ptr1, *ptr2, *res;
                ptr1 = (cfloat *)ap2->data;
                ptr2 = (cfloat *)ap1->data;
                res = (cfloat *)ret->data;
                res->real = ptr1->real * ptr2->real - ptr1->imag * ptr2->imag;
                res->imag = ptr1->real * ptr2->imag + ptr1->imag * ptr2->real;
            }
            else if (ap1shape != _matrix) {
                cblas_caxpy(l, (float *)ap2->data, (float *)ap1->data,
                            ap1stride/sizeof(cfloat), (float *)ret->data, 1);
            }
            else {
                int maxind, oind, i, a1s, rets;
                char *ptr, *rptr;
                float *pval;
                maxind = (ap1->dimensions[0] >= ap1->dimensions[1] ? 0 : 1);
                oind = 1-maxind;
                ptr = ap1->data;
                rptr = ret->data;
                l = ap1->dimensions[maxind];
                pval = (float *)ap2->data;
                a1s = ap1->strides[maxind] / sizeof(cfloat);
                rets = ret->strides[maxind] / sizeof(cfloat);
                for (i=0; i < ap1->dimensions[oind]; i++) {
                    cblas_caxpy(l, pval, (float *)ptr, a1s,
                                (float *)rptr, rets);
                    ptr += ap1->strides[oind];
                    rptr += ret->strides[oind];
                }
            }
        }
        NPY_END_ALLOW_THREADS
    }