/* $Id: numarray.h,v 1.24 2003/11/25 16:59:18 jaytmiller Exp $ */ 

#if !defined(_numarray)
#define _numarray

#include "numconfig.h"

#define PY_BOOL_CHAR "b"
#define PY_INT8_CHAR "b"
#define PY_INT16_CHAR "h"
#define PY_INT32_CHAR "i"
#define PY_FLOAT32_CHAR "f"
#define PY_FLOAT64_CHAR "d"
#define PY_UINT8_CHAR "h"
#define PY_UINT16_CHAR "i"
#define PY_UINT32_CHAR "i" /* Unless longer int available */
#define PY_COMPLEX64_CHAR "D"
#define PY_COMPLEX128_CHAR "D"

#define PY_LONG_CHAR "l"
#define PY_LONG_LONG_CHAR "L"

#define pyFPE_DIVIDE_BY_ZERO  1
#define pyFPE_OVERFLOW        2
#define pyFPE_UNDERFLOW       4
#define pyFPE_INVALID         8

#define MAXARGS 20

#define MAXDIM  40
#define SZ_BUF  79

#define isNonZERO(x) (x != 0) /* to convert values to boolean 1's or 0's */

typedef signed char Bool;

typedef signed char Int8;
typedef short int Int16;
typedef int Int32;

typedef unsigned char UInt8;
typedef unsigned short int UInt16;
typedef unsigned int UInt32;

#if LP64
typedef long int Int64;
typedef unsigned long int UInt64;
typedef Int64 Long;
#else                  /* 32-bit platforms */
typedef Int32 Long;
#if defined(_MSC_VER)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#else
typedef long long Int64;
typedef unsigned long long UInt64;
#endif
#endif

typedef float Float32;
typedef double Float64;

#if HAS_FLOAT128
typedef long double Float128;
#endif

/* From Numeric lapack_litemodule, from f2c */
typedef struct { Float32 r, i; } Complex32;
typedef struct { Float64 r, i; } Complex64;

#define MAX_ALIGN sizeof(double)

typedef enum 
{
  tAny,

  tBool,

  tInt8, 
  tUInt8,

  tInt16, 
  tUInt16,

  tInt32, 
  tUInt32, 

  tInt64, 
  tUInt64,

  tFloat32, 
  tFloat64,

  tComplex32, 
  tComplex64,
  
  tObject,

  tDefault = tFloat64,
#if LP64
  tLong = tInt64,
#else
  tLong = tInt32,
#endif
  tMaxType  
} NumarrayType;
#define nNumarrayType (tObject+1)

typedef enum 
{
	NUM_LITTLE_ENDIAN=0,
	NUM_BIG_ENDIAN = 1
} NumarrayByteOrder;

typedef enum
{
	NUM_CONTIGUOUS=1,
	NUM_NOTSWAPPED=2,
	NUM_ALIGNED=4,
	NUM_WRITABLE=8,

	NUM_C_ARRAY  = (NUM_CONTIGUOUS | NUM_ALIGNED | NUM_NOTSWAPPED),
	NUM_UNCONVERTED = 0
} NumRequirements;

#define UNCONVERTED 0
#define C_ARRAY     (NUM_CONTIGUOUS | NUM_NOTSWAPPED | NUM_ALIGNED)

#define MUST_BE_COMPUTED 2   

enum PyArray_TYPES { 
 #if defined(USE_SIGNED_CHAR)
	PyArray_CHAR=tInt8, 
 #else
	PyArray_CHAR=tUInt8,
 #endif
	PyArray_UBYTE=tUInt8, 
	PyArray_SBYTE=tInt8,
	PyArray_SHORT=tInt16, 
	PyArray_INT=tInt32, 
	PyArray_LONG=tLong,
	PyArray_FLOAT=tFloat32, 
	PyArray_DOUBLE=tFloat64, 
	PyArray_CFLOAT=tComplex32, 
	PyArray_CDOUBLE=tComplex64,
	PyArray_NOTYPE=tAny,
	PyArray_OBJECT=tObject
};

/* Array flags */
#define CONTIGUOUS       1          /* compatible, depends */
#define OWN_DIMENSIONS   2          /* always false */
#define OWN_STRIDES      4          /* always false */
#define OWN_DATA         8          /* always false */
#define SAVESPACE     0x10

#define ALIGNED         0x100       /* roughly: data % itemsize == 0 */
#define NOTSWAPPED      0x200       /* byteorder == sys.byteorder    */
#define WRITABLE        0x400       /* data buffer is writable       */
#define CHECKOVERFLOW   0x800       /* Check overflows on value assignments */

#define IS_CARRAY (CONTIGUOUS | ALIGNED | NOTSWAPPED)

/* type bit */
#define SAVESPACEBIT 0  /* From Numeric: 128,  but not needed in numarray */ 

/* Original Numeric Descr
typedef struct {
  PyArray_VectorUnaryFunc *cast[PyArray_NTYPES]; 
  PyArray_GetItemFunc *getitem;
  PyArray_SetItemFunc *setitem;
  int type_num, elsize;
  char *one, *zero;
  char type;
} PyArray_Descr;
*/

/* PyArrayObject is compilation-compatible with Numeric,  but includes 
additional fields required to implement numarray.

This is a source compatible (not binary compatible) version of the Numeric
array object.  dimensions and strides are "pre-allocated" in numarray and
inlined to avoid a multi-step malloc process.

Array type descriptors, "descr", are statically allocated. 

*/
typedef struct s_PyArrayObject PyArrayObject;

#if 0 
typedef long maybelong;  
#define ML_DEC "%ld"
#define ML_HEX "%016lx"
#else 
typedef int maybelong;
#define ML_DEC "%d"
#define ML_HEX "%08x"
#endif

typedef struct s_Array_Descr PyArray_Descr;

struct s_PyArrayObject {
	/* Numeric compatible stuff */

	PyObject_HEAD
	char *data;
	int nd;
	maybelong dimensions[MAXDIM];
	maybelong strides[MAXDIM];
	PyObject *base;
	PyArray_Descr *descr;
	int flags;

	/* numarray extras */

	PyObject *_data;       /* object must meet buffer API */
	PyObject *_shadows;    /* ill-behaved original array. */
	int      nstrides;     /* elements in strides array */
	long     byteoffset;   /* offset into buffer where array data begins */
	long     bytestride;   /* basic seperation of elements in bytes */
	long     itemsize;     /* length of 1 element in bytes */

	char      byteorder;   /* NUM_BIG_ENDIAN, NUM_LITTLE_ENDIAN */

	char      _aligned;    /* test override flag */      
	char      _contiguous; /* test override flag */

	Complex64      temp;   /* temporary for gettitem/setitem MACROS */
	char *         wptr;   /* working pointer for getitem/setitem MACROS */
};       


/* PyArray_Descr is compilation-compatible with Numeric,  but implements
only a subset of the Numeric struct so not all Numeric code will compile.
*/
typedef PyObject * (*_getfunc)(PyArrayObject *, long offset);
typedef int        (*_setfunc)(PyArrayObject *, long offset, PyObject *);

struct s_Array_Descr {
	int  type_num;  /* PyArray_TYPES */
	int  elsize;    /* bytes for 1 element */
	char type;      /* One of "cb1silfdFD "  Object numarray not supported. */
	_getfunc _get;
	_setfunc _set;
};

typedef struct {
	PyObject_HEAD
	PyObject *(*compute)(PyObject*,PyObject*,PyObject*);   /* Must match PyOperatorObject */
	PyObject *(*rebuffer)(PyObject*,PyObject*,PyObject*);
	int       arr_position;
	int       inb_position;
	int       direction;
	int       generated;
	int       conversion_required;
	PyObject  *buffers[4];
	PyObject  *bytestrides[2];
	PyObject  *convfunction;
	PyObject  *stridefunction;
	PyObject  *result_buff;
} PyConverterObject;


typedef struct {
	PyObject_HEAD
	PyObject *(*compute)(PyObject*,PyObject*,PyObject*);   /* Must match PyConverterObject */
	PyObject *inputs;
	PyObject *outputs;
	PyObject *cfunc;
	int      striding;
} PyOperatorObject;
 
/* ====================================================================================== */

#endif  /* _numarray */
