
/*
  Native entries for the Native interface library class

  @author Jeff Schoen / Neon Ngo
  @version $Id: Native.c,v 1.52 2014/08/05 19:41:46 jgs Exp $
*/

#include <stdlib.h>
#include "cdefs.h"
#include "native.h"
#include "nxm_sys_lib_Native.h"
#define ROUND_DOWN        nxm_sys_lib_Native_ROUND_DOWN
#define ROUND_CEILING     nxm_sys_lib_Native_ROUND_CEILING
#define ROUND_FLOOR       nxm_sys_lib_Native_ROUND_FLOOR
#define ROUND_HALF_UP     nxm_sys_lib_Native_ROUND_HALF_UP
#define ROUND_HALF_EVEN   nxm_sys_lib_Native_ROUND_HALF_EVEN
#define ROUND_UNNECESSARY nxm_sys_lib_Native_ROUND_UNNECESSARY
#define ROUND_ROUND       nxm_sys_lib_Native_ROUND_ROUND

/* On Windows Java emits a Native.h that uses the VisualC++ suffix of "i64" on this value
   that is not supported by GCC. GCC uses the Unix-standard (specified in C99) suffix of
   "LL" (long long). See Java Bug 5085132 for details.

   Note: This section must come AFTER the include for nxm_sys_lib_Native.h.
 */
#if defined(__GNUC__) && defined(_WIN)
#undef nxm_sys_lib_Native_XMAX
#define nxm_sys_lib_Native_XMAX  9223372036854775807LL
#endif


/* In C the '-' is an operator (not part of a numeric constant) which is limits the
   operand to _MAX. To trick the compiler to use the minimum value for integer types,
   we need to use (-_MAX-1) and hope that it will compute the value at compile time.
 */
#define DMAX              nxm_sys_lib_Native_DMAX
#define DMIN              (-DMAX)
#define FMAX              nxm_sys_lib_Native_FMAX
#define FMIN              (-FMAX)
#define XMAX              nxm_sys_lib_Native_XMAX
#define XMIN              (-XMAX-1)
#define LMAX              nxm_sys_lib_Native_LMAX
#define LMIN              (-LMAX-1)
#define IMAX              nxm_sys_lib_Native_IMAX
#define IMIN              (-IMAX-1)
#define BMAX              nxm_sys_lib_Native_BMAX
#define BMIN              (-BMAX-1)
#define NMAX              nxm_sys_lib_Native_NMAX
#define NMIN              (-NMAX-1)

#define IEEE              nxm_sys_lib_Native_IEEE
#define EEEI              nxm_sys_lib_Native_EEEI
#define VAX               nxm_sys_lib_Native_VAX

/* positive and negative INFINITY constants for float and double */
#if defined(_OSF)
  /* On OSF we can not get Inf via a division by zero since the complier errors
     out if we try to do this the same as we do on the rest of the platforms.
     This violates the IEEE 754 specs that state that +N/0.0 is +Inf for all
     values of N other than 0 (0.0/0.0 = NaN).
   */
  static jlong DPOSINF_LONG = 0x7ff0000000000000LL; /* Hex value of +Inf as double */
  static jint  FPOSINF_INT  = 0x7f800000;           /* Hex value of +Inf as float */
# define DPOSINF (*((double*)&DPOSINF_LONG))
# define DNEGINF (-DPOSINF)
# define FPOSINF (*((float*)&FPOSINF_INT))
# define FNEGINF (-FPOSINF)
#else
/* This "should" be faster than what we are doing on OSF since the compiler
   can evaluate this at compile time.
 */
# define DPOSINF           ((jdouble)(+1.0/0.0))  /* +Inf as a double */
# define DNEGINF           ((jdouble)(-1.0/0.0))  /* -Inf as a double */
# define FPOSINF           ((jfloat)(+1.0f/0.0f)) /* +Inf as a float */
# define FNEGINF           ((jfloat)(-1.0f/0.0f)) /* -Inf as a float */
#endif

#if _UNIX
#include <unistd.h>
#endif
#if _LINX
#include <sys/statvfs.h>
#include <asm/mman.h>
#endif

#ifndef O_NONBLOCK
#define O_NONBLOCK 04000 /* JC4: This is for Windows users... value copied from Linux */
#endif


#include <fcntl.h>
#include <errno.h>
/* extern int errno;  // This should be defined in <errno.h> */

#define MPOS 6
jint FPOS=0, SPOS=0, SELEM=0;
jint flagF,flagD,flagB,flagI,flagL;

typedef struct {
  union { jint l[4]; jshort i[8]; } val;
} ArrayClass;

#define JAFLAG(A) (A)->val.l[FPOS]
#define JASIZE(A) (A)->val.l[SPOS]
#if _OSF
#define O2A(X) (ArrayClass *)X
#else
#define O2A(X) *(ArrayClass **)X
#endif

void dumpClass (char *prefix, jint *data, jint size) {
  int i;
  printf("%s at %p   ",prefix,data);
  for (i=0; i<size; i++) printf("%08x ",data[i]);
  printf("\n");
}

JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_castF (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagB) return array;
  JAFLAG(ja)=flagF;
  if (SELEM) JASIZE(ja)>>=2; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_castD (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagB) return array;
  JAFLAG(ja)=flagD;
  if (SELEM) JASIZE(ja)>>=3; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_castI (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagB) return array;
  JAFLAG(ja)=flagI;
  if (SELEM) JASIZE(ja)>>=1; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_castL (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagB) return array;
  JAFLAG(ja)=flagL;
  if (SELEM) JASIZE(ja)>>=2; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_uncastF (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagF) return array;
  JAFLAG(ja)=flagB;
  if (SELEM) JASIZE(ja)<<=2; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_uncastD (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagD) return array;
  JAFLAG(ja)=flagB;
  if (SELEM) JASIZE(ja)<<=3; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_uncastI (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagI) return array;
  JAFLAG(ja)=flagB;
  if (SELEM) JASIZE(ja)<<=1; return array;
}
JNIEXPORT jobject JNICALL Java_nxm_sys_lib_Native_uncastL (JNIEnv *env, jclass clazz, jobject array) {
  ArrayClass *ja = O2A(array);
  if (JAFLAG(ja)!=flagL) return array;
  JAFLAG(ja)=flagB;
  if (SELEM) JASIZE(ja)<<=2; return array;
}
JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_dumpClass (JNIEnv *env, jclass clazz,
  jobject obj, jint words) {
  dumpClass("class",*(jint **)obj,words);
}
JNIEXPORT jlong JNICALL Java_nxm_sys_lib_Native_getAddress (JNIEnv *env, jclass clazz,
  jobject obj, jint item) {
/*  dumpClass("class",*(jint **)obj,8); */
  return (jlong)(jpointer)(*(jint **)obj);
}
JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_castInit (JNIEnv *env, jclass clazz,
		 jobject F, jobject D, jobject B, jobject I, jobject L,
		 jobject f, jobject d, jobject b, jobject i, jobject l) {
  ArrayClass *jaF=O2A(F),*jaD=O2A(D),*jaB=O2A(B),*jaI=O2A(I),*jaL=O2A(L);
  ArrayClass *jaf=O2A(f),*jad=O2A(d),*jab=O2A(b),*jai=O2A(i),*jal=O2A(l);
  for (SPOS=0; SPOS<MPOS; SPOS++) {
    if (JASIZE(jaF)==10 && JASIZE(jaD)==11 && JASIZE(jaB)==12 &&
	JASIZE(jaI)==13 && JASIZE(jaL)==14) { SELEM=1; break; }
    if (JASIZE(jaF)==10*4 && JASIZE(jaD)==11*8 && JASIZE(jaB)==12*1 &&
	JASIZE(jaI)==13*2 && JASIZE(jaL)==14*4) { SELEM=0; break; }
  }
  for (FPOS=0; FPOS<MPOS; FPOS++) {
    if (FPOS==SPOS) continue;
    flagF=JAFLAG(jaF); if (JAFLAG(jaf)!=flagF) continue;
    flagD=JAFLAG(jaD); if (JAFLAG(jad)!=flagD) continue;
    flagB=JAFLAG(jaB); if (JAFLAG(jab)!=flagB) continue;
    flagI=JAFLAG(jaI); if (JAFLAG(jai)!=flagI) continue;
    flagL=JAFLAG(jaL); if (JAFLAG(jal)!=flagL) continue;
    if (flagF==0||flagD==0||flagB==0||flagI==0||flagL==0) continue;
    if (flagF==flagD||flagF==flagB||flagF==flagI||flagF==flagL) continue;
    if (flagD==flagB||flagD==flagI||flagD==flagL) continue;
    if (flagB==flagI||flagB==flagL) continue;
    if (flagI==flagL) continue;
    break;
  }
  if (FPOS==MPOS || SPOS==MPOS) {
    printf("CastInit Problem FPOS=%d SPOS=%d\n",FPOS,SPOS);
    dumpClass("CastF",jaF->val.l,MPOS);
    dumpClass("CastD",jaD->val.l,MPOS);
    dumpClass("CastB",jaB->val.l,MPOS);
    dumpClass("CastI",jaI->val.l,MPOS);
    dumpClass("CastL",jaL->val.l,MPOS);
    return 0;
  }
  return 1;
}

JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_copy (JNIEnv *env, jclass clazz,
        jobject array1, jobject array2, jint size) {
  jbyte *buf1,*buf2;
  buf1 = GetArray(array1);
  buf2 = GetArray(array2);
  memcpy (buf2,buf1,size);
  ReleaseArray(array1,buf1);
  ReleaseArray(array2,buf2);
}

JNIEXPORT jlong JNICALL Java_nxm_sys_lib_Native_alloc (JNIEnv *env, jclass clazz, jlong bytes) {
  return (jlong)(jpointer) malloc((size_t)bytes);
}
JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_free (JNIEnv *env, jclass clazz, jlong handle) {
  if ( handle == 0 ) return -1;
  free((void *)(jpointer)handle);
  return 0;
}
JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_p2ja (JNIEnv *env, jclass clazz,
        jlong pointer1, jint off1, jobject array2, jint off2, jint size) {
  jbyte *buf1,*buf2;
  buf1 = (jbyte *)(jpointer)pointer1;
  buf2 = GetArray(array2);
  memcpy (buf2+off2,buf1+off1,size);
  ReleaseArray(array2,buf2);
}

JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_ja2p (JNIEnv *env, jclass clazz,
        jobject array1, jint off1, jlong pointer2, jint off2, jint size) {
  jbyte *buf1,*buf2;
  buf1 = GetArray(array1);
  buf2 = (jbyte *)(jpointer)pointer2;
  memcpy (buf2+off2,buf1+off1,size);
  ReleaseArray(array1,buf1);
}

JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_p2p (JNIEnv *env, jclass clazz,
        jlong pointer1, jint off1, jlong pointer2, jint off2, jint size) {
  jbyte *buf1,*buf2;
  buf1 = (jbyte *)(jpointer)pointer1;
  buf2 = (jbyte *)(jpointer)pointer2;
  memcpy (buf2+off2,buf1+off1,size);
}

JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_p2ps (JNIEnv *env, jclass clazz,
        jlong pointer1, jint off1, jint stride1,
        jlong pointer2, jint off2, jint stride2,
        jint csize, jint tsize) {
  jbyte *buf1,*buf2;
  jint m;
  buf1 = (jbyte *)(jpointer)pointer1;
  buf2 = (jbyte *)(jpointer)pointer2;
  for ( m=0; m<tsize; m+=csize, off1+=stride1, off2+=stride2) {
    memcpy (buf2+off2,buf1+off1,csize);
  }
}

#define LROUND(N) ((N)>0.0)? (N)+0.5: (N)-0.5

/* Unpacks a nibble from a byte buffer */
#define UNPACK_N(buf,off) ((jbyte)((((off)&1)==0)? (((buf[(off)>>1])<<4)&0xF0) : ((buf[(off)>>1])&0xF0)))

void cast_F2D (jfloat  *a, jdouble *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jdouble)a[i]; } }
void cast_X2D (jlong   *a, jdouble *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jdouble)a[i]; i++; } }
void cast_L2D (jint    *a, jdouble *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jdouble)a[i]; } }
void cast_I2D (jshort  *a, jdouble *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jdouble)a[i]; } }
void cast_B2D (jbyte   *a, jdouble *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jdouble)a[i]; } }
void cast_N2D (jbyte   *a, jdouble *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jdouble)UNPACK_N(a,i); } }

void cast_D2F (jdouble *a, jfloat *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jfloat)a[i]; i++; } }
void cast_X2F (jlong   *a, jfloat *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jfloat)a[i]; i++; } }
void cast_L2F (jint    *a, jfloat *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jfloat)a[i]; i++; } }
void cast_I2F (jshort  *a, jfloat *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jfloat)a[i]; } }
void cast_B2F (jbyte   *a, jfloat *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jfloat)a[i]; } }
void cast_N2F (jbyte   *a, jfloat *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jfloat)UNPACK_N(a,i); } }

void cast_D2X (jdouble *a, jlong *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jlong)LROUND(a[i]); i++; } }
void cast_F2X (jfloat  *a, jlong *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jlong)LROUND(a[i]); i++; } }
void cast_L2X (jint    *a, jlong *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jlong)a[i]; } }
void cast_I2X (jshort  *a, jlong *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jlong)a[i]; } }
void cast_B2X (jbyte   *a, jlong *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jlong)a[i]; } }
void cast_N2X (jbyte   *a, jlong *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jlong)UNPACK_N(a,i); } }

void cast_D2L (jdouble *a, jint *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jint)LROUND(a[i]); i++; } }
void cast_F2L (jfloat  *a, jint *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jint)LROUND(a[i]); i++; } }
void cast_X2L (jlong   *a, jint *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jlong)a[i]; i++; } }
void cast_I2L (jshort  *a, jint *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jint)a[i]; } }
void cast_B2L (jbyte   *a, jint *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jint)a[i]; } }
void cast_N2L (jbyte   *a, jint *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jint)UNPACK_N(a,i); } }

void cast_D2I (jdouble *a, jshort *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jshort)max(IMIN,min(IMAX,LROUND(a[i]))); i++; } }
void cast_F2I (jfloat  *a, jshort *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jshort)max(IMIN,min(IMAX,LROUND(a[i]))); i++; } }
void cast_X2I (jlong   *a, jshort *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jshort)max(IMIN,min(IMAX,a[i])); i++; } }
void cast_L2I (jint    *a, jshort *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jshort)max(IMIN,min(IMAX,a[i])); i++; } }
void cast_B2I (jbyte   *a, jshort *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jshort)a[i]; } }
void cast_N2I (jbyte   *a, jshort *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jshort)UNPACK_N(a,i); } }

void cast_D2B (jdouble *a, jbyte *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jbyte)max(BMIN,min(BMAX,LROUND(a[i]))); i++; } }
void cast_F2B (jfloat  *a, jbyte *b, jint n) { jint i=0; for (;i<n;) { b[i]=(jbyte)max(BMIN,min(BMAX,LROUND(a[i]))); i++; } }
void cast_X2B (jlong   *a, jbyte *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jbyte)a[i]; } }
void cast_L2B (jint    *a, jbyte *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jbyte)a[i]; } }
void cast_I2B (jshort  *a, jbyte *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jbyte)a[i]; } }
void cast_N2B (jbyte   *a, jbyte *b, jint n) { jint i=n; for (;i>0;) { i--; b[i]=(jbyte)UNPACK_N(a,i); } }

void cast_D2N (jdouble  *a, jbyte *b, jint n) {
  jint i=0,j=0; for (;i<n;i+=2) b[j++] = (jbyte)((((jint)a[i]>>4)&0xF) | ((jint)a[i+1]&0xF0));
}
void cast_F2N (jfloat  *a, jbyte *b, jint n) {
  jint i=0,j=0; for (;i<n;i+=2) b[j++] = (jbyte)((((jint)a[i]>>4)&0xF) | ((jint)a[i+1]&0xF0));
}
void cast_X2N (jlong  *a, jbyte *b, jint n) {
  jint i=0,j=0; for (;i<n;i+=2) b[j++] = (jbyte)((((jint)a[i]>>4)&0xF) | ((jint)a[i+1]&0xF0));
}
void cast_L2N (jint  *a, jbyte *b, jint n) {
  jint i=0,j=0; for (;i<n;i+=2) b[j++] = (jbyte)((((jint)a[i]>>4)&0xF) | ((jint)a[i+1]&0xF0));
}
void cast_I2N (jshort  *a, jbyte *b, jint n) {
  jint i=0,j=0; for (;i<n;i+=2) b[j++] = (jbyte)((((jint)a[i]>>4)&0xF) | ((jint)a[i+1]&0xF0));
}
void cast_B2N (jbyte  *a, jbyte *b, jint n) {
  jint i=0,j=0; for (;i<n;i+=2) b[j++] = (jbyte)((((jint)a[i]>>4)&0xF) | ((jint)a[i+1]&0xF0));
}

void cast_P2D (jbyte *a, jdouble *b, jint n) {
  jint i=n, j=i/8, k=i-j*8, c; if (k==0) { j--; k=8; }
  for (;i>0;) { c=a[j--]; for (;--k>=0;) b[--i]=(jbyte)((c>>k)&0x1); k=8; }
}
void cast_P2F (jbyte *a, jfloat *b, jint n) {
  jint i=n, j=i/8, k=i-j*8, c; if (k==0) { j--; k=8; }
  for (;i>0;) { c=a[j--]; for (;--k>=0;) b[--i]=(jbyte)((c>>k)&0x1); k=8; }
}
void cast_P2X (jbyte *a, jlong *b, jint n) {
  jint i=n, j=i/8, k=i-j*8, c; if (k==0) { j--; k=8; }
  for (;i>0;) { c=a[j--]; for (;--k>=0;) b[--i]=(jbyte)((c>>k)&0x1); k=8; }
}
void cast_P2L (jbyte *a, jint *b, jint n) {
  jint i=n, j=i/8, k=i-j*8, c; if (k==0) { j--; k=8; }
  for (;i>0;) { c=a[j--]; for (;--k>=0;) b[--i]=(jbyte)((c>>k)&0x1); k=8; }
}
void cast_P2I (jbyte *a, jshort *b, jint n) {
  jint i=n, j=i/8, k=i-j*8, c; if (k==0) { j--; k=8; }
  for (;i>0;) { c=a[j--]; for (;--k>=0;) b[--i]=(jbyte)((c>>k)&0x1); k=8; }
}
void cast_P2B (jbyte *a, jbyte *b, jint n) {
  jint i=n, j=i/8, k=i-j*8, c; if (k==0) { j--; k=8; }
  for (;i>0;) { c=a[j--]; for (;--k>=0;) b[--i]=(jbyte)((c>>k)&0x1); k=8; }
}

void cast_D2P (jdouble  *a, jbyte *b, jint n) {
  jint i=0, j=0, sp,sb,k;
  for (;i<n; b[j++]=(jbyte)sp) for (sp=0,sb=1,k=0; k<8; k++,sb<<=1) if (a[i++]>0) sp|=sb;
}
void cast_F2P (jfloat  *a, jbyte *b, jint n) {
  jint i=0, j=0, sp,sb,k;
  for (;i<n; b[j++]=(jbyte)sp) for (sp=0,sb=1,k=0; k<8; k++,sb<<=1) if (a[i++]>0) sp|=sb;
}
void cast_X2P (jlong  *a, jbyte *b, jint n) {
  jint i=0, j=0, sp,sb,k;
  for (;i<n; b[j++]=(jbyte)sp) for (sp=0,sb=1,k=0; k<8; k++,sb<<=1) if (a[i++]>0) sp|=sb;
}
void cast_L2P (jint  *a, jbyte *b, jint n) {
  jint i=0, j=0, sp,sb,k;
  for (;i<n; b[j++]=(jbyte)sp) for (sp=0,sb=1,k=0; k<8; k++,sb<<=1) if (a[i++]>0) sp|=sb;
}
void cast_I2P (jshort  *a, jbyte *b, jint n) {
  jint i=0, j=0, sp,sb,k;
  for (;i<n; b[j++]=(jbyte)sp) for (sp=0,sb=1,k=0; k<8; k++,sb<<=1) if (a[i++]>0) sp|=sb;
}
void cast_B2P (jbyte  *a, jbyte *b, jint n) {
  jint i=0, j=0, sp,sb,k;
  for (;i<n; b[j++]=(jbyte)sp) for (sp=0,sb=1,k=0; k<8; k++,sb<<=1) if (a[i++]>0) sp|=sb;
}
void cast_P2P (jbyte   *a, jbyte *b, jint n) { if (a!=b) memcpy (b,a,n/8); }

typedef union {
  jdouble *dbuf;
  jfloat  *fbuf;
  jlong   *xbuf;
  jint    *lbuf;
  jshort  *ibuf;
  jbyte   *bbuf;
} buffer_t;

/** Convert method for floating point types (DOUBLE, FLOAT) */
#define CONVERTF(name,t1,t2,max,min,pinf,ninf) \
static t2 name (t1 val) { \
  if (val != val) return (jfloat)val; /* NaN */ \
  if ((double)val >= (double)max) return (t2)pinf; \
  if ((double)val <= (double)min) return (t2)ninf; \
  return (t2)val; \
}

/** Convert method for integer types (XLONG, LONG, INT, BYTE) */
#define CONVERTI(name,t1,t2,max,min) \
static t2 name (t1 val) { \
  if (val != val) return 0; /* NaN */ \
  if ((double)val >= (double)max) return (t2)max; \
  if ((double)val <= (double)min) return (t2)min; \
  return (t2)val; \
}

#define d2d_sat(val) ((jdouble)(val))
CONVERTF(d2f_sat, jdouble, jfloat, FMAX, FMIN, FPOSINF, FNEGINF)
CONVERTI(d2x_sat, jdouble, jlong,  XMAX, XMIN)
CONVERTI(d2l_sat, jdouble, jint,   LMAX, LMIN)
CONVERTI(d2i_sat, jdouble, jshort, IMAX, IMIN)
CONVERTI(d2b_sat, jdouble, jbyte,  BMAX, BMIN)
CONVERTI(d2n_sat, jdouble, jbyte,  NMAX, NMIN)

#define f2d_sat(val) ((jdouble)(val))
#define f2f_sat(val) ((jfloat)(val))
CONVERTI(f2x_sat, jfloat, jlong,  XMAX, XMIN)
CONVERTI(f2l_sat, jfloat, jint,   LMAX, LMIN)
CONVERTI(f2i_sat, jfloat, jshort, IMAX, IMIN)
CONVERTI(f2b_sat, jfloat, jbyte,  BMAX, BMIN)
CONVERTI(f2n_sat, jfloat, jbyte,  NMAX, NMIN)

#define x2d_sat(val) ((jdouble)(val))
#define x2f_sat(val) ((jfloat)(val))
#define x2x_sat(val) ((jlong)(val))
CONVERTI(x2l_sat, jlong, jint,   LMAX, LMIN)
CONVERTI(x2i_sat, jlong, jshort, IMAX, IMIN)
CONVERTI(x2b_sat, jlong, jbyte,  BMAX, BMIN)
CONVERTI(x2n_sat, jlong, jbyte,  NMAX, NMIN)

#define l2d_sat(val) ((jdouble)(val))
#define l2f_sat(val) ((jfloat)(val))
#define l2x_sat(val) ((jlong)(val))
#define l2l_sat(val) ((jint)(val))
CONVERTI(l2i_sat, jint, jshort, IMAX, IMIN)
CONVERTI(l2b_sat, jint, jbyte,  BMAX, BMIN)
CONVERTI(l2n_sat, jint, jbyte,  NMAX, NMIN)

#define i2d_sat(val) ((jdouble)(val))
#define i2f_sat(val) ((jfloat)(val))
#define i2x_sat(val) ((jlong)(val))
#define i2l_sat(val) ((jint)(val))
#define i2i_sat(val) ((jshort)(val))
CONVERTI(i2b_sat, jshort, jbyte,  BMAX, BMIN)
CONVERTI(i2n_sat, jshort, jbyte,  NMAX, NMIN)

#define b2d_sat(val) ((jdouble)(val))
#define b2f_sat(val) ((jfloat)(val))
#define b2x_sat(val) ((jlong)(val))
#define b2l_sat(val) ((jint)(val))
#define b2i_sat(val) ((jshort)(val))
#define b2b_sat(val) ((jbyte)(val))
CONVERTI(b2n_sat, jbyte, jbyte,  NMAX, NMIN)

#define d2d_cast(val) ((jdouble)(val))
#define d2f_cast(val) ((jfloat)(val))
#define d2x_cast(val) ((jlong)(val))
#define d2l_cast(val) ((jint)(val))
#define d2i_cast(val) ((jshort)(val))
#define d2b_cast(val) ((jbyte)(val))

#define f2d_cast(val) ((jdouble)(val))
#define f2f_cast(val) ((jfloat)(val))
#define f2x_cast(val) ((jlong)(val))
#define f2l_cast(val) ((jint)(val))
#define f2i_cast(val) ((jshort)(val))
#define f2b_cast(val) ((jbyte)(val))

#define x2d_cast(val) ((jdouble)(val))
#define x2f_cast(val) ((jfloat)(val))
#define x2x_cast(val) ((jlong)(val))
#define x2l_cast(val) ((jint)(val))
#define x2i_cast(val) ((jshort)(val))
#define x2b_cast(val) ((jbyte)(val))

#define l2d_cast(val) ((jdouble)(val))
#define l2f_cast(val) ((jfloat)(val))
#define l2x_cast(val) ((jlong)(val))
#define l2l_cast(val) ((jint)(val))
#define l2i_cast(val) ((jshort)(val))
#define l2b_cast(val) ((jbyte)(val))

#define i2d_cast(val) ((jdouble)(val))
#define i2f_cast(val) ((jfloat)(val))
#define i2x_cast(val) ((jlong)(val))
#define i2l_cast(val) ((jint)(val))
#define i2i_cast(val) ((jshort)(val))
#define i2b_cast(val) ((jbyte)(val))

#define b2d_cast(val) ((jdouble)(val))
#define b2f_cast(val) ((jfloat)(val))
#define b2x_cast(val) ((jlong)(val))
#define b2l_cast(val) ((jint)(val))
#define b2i_cast(val) ((jshort)(val))
#define b2b_cast(val) ((jbyte)(val))

/** These #define's mimic the methods in Convert.java */
#define packD(buf,off,val) buf.dbuf[off] = val
#define packF(buf,off,val) buf.fbuf[off] = val
#define packX(buf,off,val) buf.xbuf[off] = val
#define packL(buf,off,val) buf.lbuf[off] = val
#define packI(buf,off,val) buf.ibuf[off] = val
#define packB(buf,off,val) buf.bbuf[off] = val
#define packN(buf,off,val) { \
  jint boff=off>>1, bn=buf.bbuf[boff]; \
  bn = (((off)&1)!=0)? (bn&0x0F) | ((val<<4)&0xF0) : (bn&0xF0) | (val&0x0F); \
  buf.bbuf[boff] = (jbyte)bn; \
}
#define packP(buf,off,val) { \
  if (val==0) buf.bbuf[(off)>>3] &= ~(0x1<<((off)&0x7)); \
  else        buf.bbuf[(off)>>3] |=  (0x1<<((off)&0x7)); \
}
#define unpackD(buf,off)   buf.dbuf[off]
#define unpackF(buf,off)   buf.fbuf[off]
#define unpackX(buf,off)   buf.xbuf[off]
#define unpackL(buf,off)   buf.lbuf[off]
#define unpackI(buf,off)   buf.ibuf[off]
#define unpackB(buf,off)   buf.bbuf[off]
#define unpackN(buf,off)   (jbyte)((buf.bbuf[(off)>>1]<<((((off)&1)==0)?28:24))>>28)
#define unpackP(buf,off)   (jbyte)((buf.bbuf[(off)>>3]>>((off)&0x7))&0x1)

#define getBPS(type)  ((type=='D')||(type=='X'))? 8 : \
                      ((type=='F')||(type=='L'))? 4 : (type=='I')? 2 : (type=='B')? 1 : 0

jshort unpackJ (jbyte *buf, int off) {
  int boff = (off/2)*3;
  if ((off&1)==0) {
    return ((jshort)buf[boff+1]&0xFF)<<12 | ((jshort)buf[boff+0]&0xFF)<<4; // EEEI
  } else {
    return ((jshort)buf[boff+2]&0xFF)<<8  | ((jshort)buf[boff+1]&0xF0); // EEEI
  }
}
void packJs (jbyte *b16, jbyte *b12, int size) {
  int i;
  size = size>>1;
  for (i=0; i<size; i++,b16+=4,b12+=3) {
    b12[0] = (b16[1]<<4)|((b16[0]>>4)&0x0F);
    b12[1] = (b16[2]&0xF0)|((b16[1]>>4)&0x0F);
    b12[2] =  b16[3];
  }
}


JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_type (JNIEnv *env, jclass clazz,
        jobject array1, jint off1, jbyte type1,
        jobject array2, jint off2, jbyte type2, jint size, jint round, jboolean saturating) {
  buffer_t buf1;
  buffer_t buf2;
  jint  status = 0; /* 0=NoError, -1=UnknownType, -2=OutOfMemory, -3=NPCopy, -4=Unaligned64, -5=UnsupportedRounding */
  jint  bps1   = getBPS(type1);
  jint  bps2   = getBPS(type2);
  jint  i      = off1;
  jint  j      = off2;
  jint  ii     = i+size;
  jint  jj     = j+size;
  jbyte type2s = type2;

  buf1.bbuf = GetArray(array1);
  buf2.bbuf = GetArray(array2);

  if (buf1.bbuf==NULL || buf2.bbuf==NULL) {
    status = -2;
    goto DONE;
  }
  if (type2 == type1) {
    if (buf2.bbuf == buf1.bbuf && off1 == off2) { status =  0; goto DONE; } /* Nothing to do */
    if (bps1 == 0)                              { status = -3; goto DONE; } /* Not handled here ('N' and 'P') */
    memcpy(&buf2.bbuf[off2*bps2], &buf1.bbuf[off1*bps1], size*bps1);
    goto DONE;
  }

#ifdef _ALLOW_64BIT_UNALIGNED
  /* Unaligned access to 64-bit values is ok (i386). */
#else
  /* Unaligned access to 64-bit values will cause core dump (Sun/SPARC). Newer versions of Java
     on the SPARC (e.g. Java 6) appear to automatically align all fields (i.e. these should always
     be false on those systems). Older versions of Java (e.g. Java 1.4.2) only appear to do 4-byte
     alignment. Either way, 8-byte alignment on a SPARC is effectively MANDATORY (this can be
     turned off, but it is a HUGE performance penalty that applies to the entire application), so
     we should keep these checks in place even with newer versions of Java.
   */
  if ((type1 == 'D') || (type1 == 'X')) {
    if ((((intptr_t)buf1.bbuf) % 8) != 0) { status = -4; goto DONE; }
  }
  if ((type2 == 'D') || (type2 == 'X')) {
    if ((((intptr_t)buf2.bbuf) % 8) != 0) { status = -4; goto DONE; }
  }
#endif

#if (__INTEL_COMPILER >= 1000)
  /* JC4/NTN: This bit "tricks" the Intel 10.x/11.x C/C++ compiler to not vectorize the loops in
              the rest of this method when using -O2 or higher optimization (which enables
              vectorization). Intel's C vectorizer's for the loops below causes problems when the
              input and output arrays are the same. (See BUG 2143 or DR 526686-3 for details). */
  if (buf1.bbuf == buf2.bbuf) {
    buf2.bbuf = buf1.bbuf;
    buf2.ibuf = buf1.ibuf;
    buf2.lbuf = buf1.lbuf;
    buf2.xbuf = buf1.xbuf;
    buf2.fbuf = buf1.fbuf;
    buf2.dbuf = buf1.dbuf;
  }
#endif
  if (type2=='J') {
    if (type1=='I') {
      memcpy(&buf2.bbuf[off2/2*3], &buf1.bbuf[off1*bps1], size*bps1);
      goto DONE;	/* bypass first statge */
    }
    type2 = 'I';	/* use first stage pre */
  }

  if ((round == ROUND_UNNECESSARY) && ((type2 != 'F') || (type2 == 'D'))) {
    round = ROUND_DOWN; /* Rounding not necessary. */
  }
  if (saturating) {
    switch (type1) {
      case 'D':
        switch (round) {
          case ROUND_DOWN:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_sat(unpackD(buf1,i))); j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_sat(unpackD(buf1,i))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_sat(unpackD(buf1,i))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_sat(unpackD(buf1,i))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_sat(unpackD(buf1,i))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2n_sat(unpackD(buf1,i))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_sat(unpackD(buf1,i))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_CEILING:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_sat(     unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_sat(ceil(unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_sat(ceil(unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_sat(ceil(unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_sat(ceil(unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2n_sat(ceil(unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_sat(ceil(unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_FLOOR:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_sat(      unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_sat(floor(unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_sat(floor(unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_sat(floor(unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_sat(floor(unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2n_sat(floor(unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_sat(floor(unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_ROUND: /* Math.round(n) is implemented as Math.floor(0.5+n). */
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_sat(          unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_sat(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_sat(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_sat(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_sat(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2n_sat(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_sat(floor(0.5+unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_HALF_UP:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_sat(       unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_sat(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_sat(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_sat(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_sat(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2n_sat(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_sat(LROUND(unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          default:
            status=-5;
            break;
        } break;
      case 'F':
        switch (round) {
          case ROUND_DOWN:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_sat(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_sat(unpackF(buf1,ii))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_sat(unpackF(buf1,i))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_sat(unpackF(buf1,i))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_sat(unpackF(buf1,i))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2n_sat(unpackF(buf1,i))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_sat(unpackF(buf1,i))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_CEILING:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_sat(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_sat(ceil(unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_sat(ceil(unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_sat(ceil(unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_sat(ceil(unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2n_sat(ceil(unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_sat(ceil(unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_FLOOR:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_sat(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_sat(floor(unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_sat(floor(unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_sat(floor(unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_sat(floor(unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2n_sat(floor(unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_sat(floor(unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_ROUND: /* Math.round(n) is implemented as Math.floor(0.5+n). */
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_sat(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_sat(floor(0.5+unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_sat(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_sat(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_sat(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2n_sat(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_sat(floor(0.5+unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_HALF_UP:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_sat(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_sat(LROUND((jdouble)unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_sat(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_sat(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_sat(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2n_sat(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_sat(LROUND(unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          default:
            status=-5;
            break;
        } break;
      case 'X':
        switch (type2) {
          case 'D': for (;i<ii;i++) { packD(buf2,j, x2d_sat(unpackX(buf1,i))); j++; } break;
          case 'F': for (;i<ii;i++) { packF(buf2,j, x2f_sat(unpackX(buf1,i))); j++; } break;
          case 'L': for (;i<ii;i++) { packL(buf2,j, x2l_sat(unpackX(buf1,i))); j++; } break;
          case 'I': for (;i<ii;i++) { packI(buf2,j, x2i_sat(unpackX(buf1,i))); j++; } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, x2b_sat(unpackX(buf1,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, x2n_sat(unpackX(buf1,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, x2b_sat(unpackX(buf1,i))); j++; } break;
          default: status=-1;
        } break;
      case 'L':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, l2d_sat(unpackL(buf1,ii))); } break;
          case 'F': for (;i<ii;i++) { packF(buf2,j, l2f_sat(unpackL(buf1,i))); j++; } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, l2x_sat(unpackL(buf1,ii))); } break;
          case 'I': for (;i<ii;i++) { packI(buf2,j, l2i_sat(unpackL(buf1,i))); j++; } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, l2b_sat(unpackL(buf1,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, l2n_sat(unpackL(buf1,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, l2b_sat(unpackL(buf1,i))); j++; } break;
          default: status=-1;
        } break;
      case 'I':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, i2d_sat(unpackI(buf1,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, i2f_sat(unpackI(buf1,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, i2x_sat(unpackI(buf1,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, i2l_sat(unpackI(buf1,ii))); } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, i2b_sat(unpackI(buf1,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, i2n_sat(unpackI(buf1,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, i2b_sat(unpackI(buf1,i))); j++; } break;
          default: status=-1;
        } break;
      case 'J':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, i2d_sat(unpackJ(buf1.bbuf,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, i2f_sat(unpackJ(buf1.bbuf,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, i2x_sat(unpackJ(buf1.bbuf,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, i2l_sat(unpackJ(buf1.bbuf,ii))); } break;
          case 'I': for (;ii>i;) { ii--; jj--; packI(buf2,jj,         unpackJ(buf1.bbuf,ii)) ; } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, i2b_sat(unpackJ(buf1.bbuf,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, i2n_sat(unpackJ(buf1.bbuf,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, i2b_sat(unpackJ(buf1.bbuf,i))); j++; } break;
          default: status=-1;
        } break;
      case 'B':
        switch (type2) {
          case 'D': for (;ii>i;) { jj--; packD(buf2,jj, b2d_sat(buf1.bbuf[--ii])); } break;
          case 'F': for (;ii>i;) { jj--; packF(buf2,jj, b2f_sat(buf1.bbuf[--ii])); } break;
          case 'X': for (;ii>i;) { jj--; packX(buf2,jj, b2x_sat(buf1.bbuf[--ii])); } break;
          case 'L': for (;ii>i;) { jj--; packL(buf2,jj, b2l_sat(buf1.bbuf[--ii])); } break;
          case 'I': for (;ii>i;) { jj--; packI(buf2,jj, b2i_sat(buf1.bbuf[--ii])); } break;
          case 'N': for (;i<ii;) { packN(buf2,j,b2n_sat(buf1.bbuf[i++])); j++; } break;
          case 'P': for (;i<ii;) { packP(buf2,j,b2b_sat(buf1.bbuf[i++])); j++; } break;
          default: status=-1;
        } break;
      case 'N':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, b2d_sat(unpackN(buf1,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, b2f_sat(unpackN(buf1,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, b2x_sat(unpackN(buf1,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, b2l_sat(unpackN(buf1,ii))); } break;
          case 'I': for (;ii>i;) { ii--; jj--; packI(buf2,jj, b2i_sat(unpackN(buf1,ii))); } break;
          case 'B': for (;ii>i;) { ii--; jj--; packB(buf2,jj, b2b_sat(unpackN(buf1,ii))); } break;
          case 'P': for (;ii>i;) { ii--; jj--; packP(buf2,jj, b2b_sat(unpackN(buf1,ii))); } break;
          default: status=-1;
        } break;
      case 'P': //ii--;
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, b2d_sat(unpackP(buf1,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, b2f_sat(unpackP(buf1,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, b2x_sat(unpackP(buf1,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, b2l_sat(unpackP(buf1,ii))); } break;
          case 'I': for (;ii>i;) { ii--; jj--; packI(buf2,jj, b2i_sat(unpackP(buf1,ii))); } break;
          case 'B': for (;ii>i;) { ii--; jj--; packB(buf2,jj, b2b_sat(unpackP(buf1,ii))); } break;
          case 'N': for (;ii>i;) { ii--; jj--; packN(buf2,jj, b2n_sat(unpackP(buf1,ii))); } break;
          default: status=-1;
        } break;
      default: status=-1;
    }
  } else {
    switch (type1) {
      case 'D':
        switch (round) {
          case ROUND_DOWN:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_cast(unpackD(buf1,i))); j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_cast(unpackD(buf1,i))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_cast(unpackD(buf1,i))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_cast(unpackD(buf1,i))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_cast(unpackD(buf1,i))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2b_cast(unpackD(buf1,i))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_cast(unpackD(buf1,i))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_CEILING:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_cast(     unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_cast(ceil(unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_cast(ceil(unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_cast(ceil(unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_cast(ceil(unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2b_cast(ceil(unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_cast(ceil(unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_FLOOR:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_cast(      unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_cast(floor(unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_cast(floor(unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_cast(floor(unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_cast(floor(unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2b_cast(floor(unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_cast(floor(unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_ROUND: /* Math.round(n) is implemented as Math.floor(0.5+n). */
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_cast(          unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_cast(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_cast(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_cast(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_cast(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2b_cast(floor(0.5+unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_cast(floor(0.5+unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_HALF_UP:
            switch (type2) {
              case 'F': for (;i<ii;i++) { packF(buf2,j, d2f_cast(       unpackD(buf1,i)));  j++; } break;
              case 'X': for (;i<ii;i++) { packX(buf2,j, d2x_cast(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, d2l_cast(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, d2i_cast(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, d2b_cast(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, d2b_cast(LROUND(unpackD(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, d2b_cast(LROUND(unpackD(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          default:
            status=-5;
            break;
        } break;
      case 'F':
        switch (round) {
          case ROUND_DOWN:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_cast(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_cast(unpackF(buf1,ii))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_cast(unpackF(buf1,i))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_cast(unpackF(buf1,i))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_cast(unpackF(buf1,i))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2b_cast(unpackF(buf1,i))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_cast(unpackF(buf1,i))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_CEILING:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_cast(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_cast(ceil(unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_cast(ceil(unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_cast(ceil(unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_cast(ceil(unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2b_cast(ceil(unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_cast(ceil(unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_FLOOR:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_cast(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_cast(floor(unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_cast(floor(unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_cast(floor(unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_cast(floor(unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2b_cast(floor(unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_cast(floor(unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_ROUND: /* Math.round(n) is implemented as Math.floor(0.5+n). */
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_cast(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_cast(floor(0.5+unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_cast(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_cast(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_cast(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2b_cast(floor(0.5+unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_cast(floor(0.5+unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          case ROUND_HALF_UP:
            switch (type2) {
              case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, f2d_cast(unpackF(buf1,ii))); } break;
              case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, f2x_cast(LROUND((jdouble)unpackF(buf1,ii)))); } break;
              case 'L': for (;i<ii;i++) { packL(buf2,j, f2l_cast(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'I': for (;i<ii;i++) { packI(buf2,j, f2i_cast(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'B': for (;i<ii;i++) { packB(buf2,j, f2b_cast(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'N': for (;i<ii;i++) { packN(buf2,j, f2b_cast(LROUND(unpackF(buf1,i)))); j++; } break;
              case 'P': for (;i<ii;i++) { packP(buf2,j, f2b_cast(LROUND(unpackF(buf1,i)))); j++; } break;
              default: status=-1;
            } break;
          default:
            status=-5;
            break;
        } break;
      case 'X':
        switch (type2) {
          case 'D': for (;i<ii;i++) { packD(buf2,j, x2d_cast(unpackX(buf1,i))); j++; } break;
          case 'F': for (;i<ii;i++) { packF(buf2,j, x2f_cast(unpackX(buf1,i))); j++; } break;
          case 'L': for (;i<ii;i++) { packL(buf2,j, x2l_cast(unpackX(buf1,i))); j++; } break;
          case 'I': for (;i<ii;i++) { packI(buf2,j, x2i_cast(unpackX(buf1,i))); j++; } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, x2b_cast(unpackX(buf1,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, x2b_cast(unpackX(buf1,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, x2b_cast(unpackX(buf1,i))); j++; } break;
          default: status=-1;
        } break;
      case 'L':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, l2d_cast(unpackL(buf1,ii))); } break;
          case 'F': for (;i<ii;i++) { packF(buf2,j, l2f_cast(unpackL(buf1,i))); j++; } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, l2x_cast(unpackL(buf1,ii))); } break;
          case 'I': for (;i<ii;i++) { packI(buf2,j, l2i_cast(unpackL(buf1,i))); j++; } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, l2b_cast(unpackL(buf1,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, l2b_cast(unpackL(buf1,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, l2b_cast(unpackL(buf1,i))); j++; } break;
          default: status=-1;
        } break;
      case 'I':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, i2d_cast(unpackI(buf1,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, i2f_cast(unpackI(buf1,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, i2x_cast(unpackI(buf1,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, i2l_cast(unpackI(buf1,ii))); } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, i2b_cast(unpackI(buf1,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, i2b_cast(unpackI(buf1,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, i2b_cast(unpackI(buf1,i))); j++; } break;
          default: status=-1;
        } break;
      case 'J':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, i2d_cast(unpackJ(buf1.bbuf,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, i2f_cast(unpackJ(buf1.bbuf,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, i2x_cast(unpackJ(buf1.bbuf,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, i2l_cast(unpackJ(buf1.bbuf,ii))); } break;
          case 'I': for (;ii>i;) { ii--; jj--; packI(buf2,jj,          unpackJ(buf1.bbuf,ii)) ; } break;
          case 'B': for (;i<ii;i++) { packB(buf2,j, i2b_cast(unpackJ(buf1.bbuf,i))); j++; } break;
          case 'N': for (;i<ii;i++) { packN(buf2,j, i2b_cast(unpackJ(buf1.bbuf,i))); j++; } break;
          case 'P': for (;i<ii;i++) { packP(buf2,j, i2b_cast(unpackJ(buf1.bbuf,i))); j++; } break;
          default: status=-1;
        } break;
      case 'B':
        switch (type2) {
          case 'D': for (;ii>i;) { jj--; packD(buf2,jj, b2d_cast(buf1.bbuf[--ii])); } break;
          case 'F': for (;ii>i;) { jj--; packF(buf2,jj, b2f_cast(buf1.bbuf[--ii])); } break;
          case 'X': for (;ii>i;) { jj--; packX(buf2,jj, b2x_cast(buf1.bbuf[--ii])); } break;
          case 'L': for (;ii>i;) { jj--; packL(buf2,jj, b2l_cast(buf1.bbuf[--ii])); } break;
          case 'I': for (;ii>i;) { jj--; packI(buf2,jj, b2i_cast(buf1.bbuf[--ii])); } break;
          case 'N': for (;i<ii;) { packN(buf2,j,b2b_cast(buf1.bbuf[i++])); j++; } break;
          case 'P': for (;i<ii;) { packP(buf2,j,b2b_cast(buf1.bbuf[i++])); j++; } break;
          default: status=-1;
        } break;
      case 'N':
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, b2d_cast(unpackN(buf1,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, b2f_cast(unpackN(buf1,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, b2x_cast(unpackN(buf1,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, b2l_cast(unpackN(buf1,ii))); } break;
          case 'I': for (;ii>i;) { ii--; jj--; packI(buf2,jj, b2i_cast(unpackN(buf1,ii))); } break;
          case 'B': for (;ii>i;) { ii--; jj--; packB(buf2,jj, b2b_cast(unpackN(buf1,ii))); } break;
          case 'P': for (;ii>i;) { ii--; jj--; packP(buf2,jj, b2b_cast(unpackN(buf1,ii))); } break;
          default: status=-1;
        } break;
      case 'P': //ii--;
        switch (type2) {
          case 'D': for (;ii>i;) { ii--; jj--; packD(buf2,jj, b2d_cast(unpackP(buf1,ii))); } break;
          case 'F': for (;ii>i;) { ii--; jj--; packF(buf2,jj, b2f_cast(unpackP(buf1,ii))); } break;
          case 'X': for (;ii>i;) { ii--; jj--; packX(buf2,jj, b2x_cast(unpackP(buf1,ii))); } break;
          case 'L': for (;ii>i;) { ii--; jj--; packL(buf2,jj, b2l_cast(unpackP(buf1,ii))); } break;
          case 'I': for (;ii>i;) { ii--; jj--; packI(buf2,jj, b2i_cast(unpackP(buf1,ii))); } break;
          case 'B': for (;ii>i;) { ii--; jj--; packB(buf2,jj, b2b_cast(unpackP(buf1,ii))); } break;
          case 'P': for (;ii>i;) { ii--; jj--; packP(buf2,jj, b2b_cast(unpackP(buf1,ii))); } break;
          default: status=-1;
        } break;
      default: status=-1;
    }
  }
  DONE:
  if (type2s=='J') packJs (buf2.bbuf+off2*3/2,buf2.bbuf+off2*3/2,size);
  if (buf1.bbuf!=NULL) ReleaseArray(array1, buf1.bbuf);
  if (buf2.bbuf!=NULL) ReleaseArray(array2, buf2.bbuf);
  if (status == -1) fprintf(stderr, "Native.c: ERROR: Can not convert %c->%c, unknown type.\n", type1,type2);
  if (status == -2) fprintf(stderr, "Native.c: ERROR: Out of memory in native code.\n");
  return status;
}


#if _IEEE
#define SOFF 0
#else
#define SOFF 1
#endif

JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_dbf (JNIEnv *env, jclass clazz,
	jobject array, jint size, jint flags) {
  jfloat scale = 3.0/128, *buf = GetArray(array);
  jshort offset = 16384-128, *sbuf = (jshort *)buf;
  int i,j; for (i=0,j=SOFF; i<size; i++, j+=2) buf[i]=scale*(float)(sbuf[j]-offset);
  ReleaseArray(array,buf);
}

JNIEXPORT jfloat JNICALL Java_nxm_sys_lib_Native_sqrtf (JNIEnv *env, jclass clazz,
	jfloat value) {
  return sqrtf(value);
}

JNIEXPORT jfloat JNICALL Java_nxm_sys_lib_Native_logf (JNIEnv *env, jclass clazz,
	jfloat value) {
  return logf(value);
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_fopen (JNIEnv *env, jclass clazz, jstring fname, jint dir) {
  jint fd, iofunc; const char *cfname;
  cfname = (*env)->GetStringUTFChars(env, fname, 0);
  if (dir>0) iofunc = O_RDWR|O_CREAT;
  else if (dir<0) iofunc = O_RDONLY;
  else iofunc = O_RDWR;
  if (dir==2) iofunc = O_RDWR|O_NONBLOCK;
#if defined(_WIN)
  iofunc |= O_BINARY; /* O_BINARY required to read/write binary data under Windows Platform */
#endif
  fd = (jint)open (cfname,iofunc,0666);
  (*env)->ReleaseStringUTFChars(env, fname, cfname);
  return fd;
}

JNIEXPORT void JNICALL Java_nxm_sys_lib_Native_fclose (JNIEnv *env, jclass clazz, jint fd) {
  close ((int)fd);
}

JNIEXPORT jlong JNICALL Java_nxm_sys_lib_Native_fseek (JNIEnv *env, jclass clazz, jint fd, jlong offset) {
  return (jlong) lseek ((int)fd, (off_t)offset, SEEK_SET);
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_fread (JNIEnv *env, jclass clazz, jint fd, jlong lbuf, jint boff, jint bytes) {
  jpointer buf = (jpointer)lbuf;
  jint status = (jint) read ((int)fd, (void *)(buf+boff), (size_t)bytes);
  if (status == -1 && errno == EAGAIN) status = 0;  /* Non-blocking I/O and no data immediately available for reading */
  return status;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_fwrite (JNIEnv *env, jclass clazz, jint fd, jlong lbuf, jint boff, jint bytes) {
  jpointer buf = (jpointer)lbuf;
  jint status = (jint) write ((int)fd, (void *)(buf+boff), (size_t)bytes);
  return status;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_freadb (JNIEnv *env, jclass clazz, jint fd, jobject obuf, jint boff, jint bytes) {
  jbyte *buf = GetArray(obuf);
  jint status = (jint) read ((int)fd, (void *)(buf+boff), (size_t)bytes);
  if (status == -1 && errno == EAGAIN) status = 0;  /* Non-blocking I/O and no data immediately available for reading */
  ReleaseArray(obuf,buf);
  return status;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_fwriteb (JNIEnv *env, jclass clazz, jint fd, jobject obuf, jint boff, jint bytes) {
  jbyte *buf = GetArray(obuf);
  jint status = (jint) write ((int)fd, (void *)(buf+boff), (size_t)bytes);
  ReleaseArray(obuf,buf);
  return status;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_chdir (JNIEnv *env, jclass clazz, jstring path) {
  int stat; const char *cpath;
  cpath = (*env)->GetStringUTFChars(env, path, 0);
  stat = chdir(cpath);
  (*env)->ReleaseStringUTFChars(env, path, cpath);
  return stat;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_statfs (JNIEnv *env, jclass clazz, jstring path, jobject obuf) {
  int stat=-1;
#if _LINX
  const char *cpath; jlong *buf; struct statvfs stats;
  cpath = (*env)->GetStringUTFChars(env, path, 0);
  buf = (jlong *)GetArray(obuf);
  stat = statvfs (cpath,&stats);
  buf[0] = stats.f_bsize; 		/* block size */
  buf[1] = stats.f_blocks;
  buf[2] = stats.f_bavail;
  buf[3] = stats.f_files;
  buf[4] = stats.f_favail;
  ReleaseArray(obuf,buf);
  (*env)->ReleaseStringUTFChars(env, path, cpath);
#endif
  return stat;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_top (JNIEnv *env, jclass clazz, jint flags, jobject obuf, jint boff, jint bytes) {
  jint status=0;
  jbyte *buf = GetArray(obuf);
  ReleaseArray(obuf,buf);
  return status;
}

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_jstr2fstr (JNIEnv *env, jclass clazz, jstring jstr, jlong fstr, jint lfstr) {
  jint i,ls; char *fs = (char *)(jpointer)fstr; const char *cjstr;
  cjstr = (*env)->GetStringUTFChars(env, jstr, 0);
  ls = strlen(cjstr);
  if (ls>lfstr) ls=lfstr;
  for (i=0; i<lfstr; i++) {
    if (i<ls) fs[i]=cjstr[i];
    else fs[i]=' ';
  }
  (*env)->ReleaseStringUTFChars(env, jstr, cjstr);
  return ls;
}

#ifdef _CUDA
#include <cuda.h>
#include <driver_types.h>
#endif

JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_cudaInit (JNIEnv *env, jclass clazz) {
  int deviceCount=0;
#ifdef _CUDA
  struct cudaDeviceProp deviceProp;
  cudaGetDeviceCount(&deviceCount);
  if (deviceCount<=0) return 0;
  cudaGetDeviceProperties(&deviceProp,0);
  if (deviceProp.major==9999 && deviceProp.major==9999) deviceCount=-1;
#endif
  return deviceCount;
}

/* Prototypes for detailed conversion routines */
/* The 'swap' routines are used by the rep and repsoi functions */
void swap1 (int_1* buf, const int_4 n);
void swap2 (int_1* buf, const int_4 n);
void swap4 (int_1* buf, const int_4 n);
void swap8 (int_1* buf, const int_4 n);
void swapJ (int_1* buf, const int_4 n, int_1 repa, int_1 repb);

void f_vax2ieee (int_1* buf, const int_4 n);
void f_ieee2vax (int_1* buf, const int_4 n);

void d_vax2ieee (int_1* buf, const int_4 n);
void d_ieee2vax (int_1* buf, const int_4 n);

void f_vax2eeei (int_1* buf, const int_4 n);
void f_eeei2vax (int_1* buf, const int_4 n);

void d_vax2eeei (int_1* buf, const int_4 n);
void d_eeei2vax (int_1* buf, const int_4 n);

/* ============================= Single Precision IEEE/VAX Conversions ===== */

union FOURBYTEDATA
{
  int_u1 int1[4];
  int_u2 int2[2];
  int_u4 int4;
  real_4 real4;
};
typedef union FOURBYTEDATA FOURBYTEDATA;

union EIGHTBYTEDATA
{
  int_u1 int1[8];
  int_u2 int2[4];
  int_u4 int4[2];
  real_4 real4[2];
  real_8 real8;
};
typedef union EIGHTBYTEDATA EIGHTBYTEDATA;


const int_u8 vax_exp_msk = 0x7f80000000000000LL;
const int_u8 vax_man_msk = 0x007fffffffffffffLL;
const int_u8 ieee_exp_msk = 0x7ff0000000000000LL;
const int_u8 ieee_man_msk = 0x000fffffffffffffLL;
const int_u8 exp_msk = (0xff << 7);


/* Mirrors java code in Convert.rep() to convert data representation (endian),
   on a native pointer (lbuf). Since NeXtMidas 2.7.0 */
JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_rep (JNIEnv *env, jclass clazz,
    jlong lbuf, jint off, jbyte type, jint n, jbyte repa, jbyte repb) {

    int_1 *buf = (int_1 *)(jpointer)lbuf;
    if (repa!=repb)
    switch (type) {
      case 'B': break;
      case 'A': break;
      case 'S': break;
      case 'J': if ( (repa==IEEE) != (repb==IEEE)) swapJ (buf+off,n,repa,repb); break;
      case 'I': if ( (repa==IEEE) != (repb==IEEE)) swap2 (buf+off,n); break;
      case 'L': if ( (repa==IEEE) != (repb==IEEE)) swap4 (buf+off,n); break;
      case 'X': if ( (repa==IEEE) != (repb==IEEE)) swap8 (buf+off,n); break;
      case 'P': if ( (repa==IEEE) != (repb==IEEE)) swap1 (buf+off,n); break;
      case 'F': switch (repa) {
        case VAX: switch (repb) {
          case EEEI: f_vax2eeei (buf+off,n); break;
          case IEEE: f_vax2ieee (buf+off,n); break;
        } break;
        case IEEE: switch (repb) {
          case VAX:  f_ieee2vax (buf+off,n); break;
          case EEEI:      swap4 (buf+off,n); break;
        } break;
        case EEEI: switch (repb) {
          case VAX:  f_eeei2vax (buf+off,n); break;
          case IEEE:      swap4 (buf+off,n); break;
        } break;
      } break;
      case 'D': switch (repa) {
        case VAX: switch (repb) {
          case EEEI: d_vax2eeei (buf+off,n); break;
          case IEEE: d_vax2ieee (buf+off,n); break;
        } break;
        case IEEE: switch (repb) {
          case VAX:  d_ieee2vax (buf+off,n); break;
          case EEEI:      swap8 (buf+off,n); break;
        } break;
        case EEEI: switch (repb) {
          case VAX:  d_eeei2vax (buf+off,n); break;
          case IEEE:      swap8 (buf+off,n); break;
        } break;
      } break;
    }
    return n;
}

/* Mirrors java code in Convert.repsoi() to convert data representation (endian),
   on a native pointer (lbuf). Since NeXtMidas 2.7.0 */
JNIEXPORT jint JNICALL Java_nxm_sys_lib_Native_repsoi (JNIEnv *env, jclass clazz,
    jlong lbuf, jint off, jbyte type, jint n, jbyte repa, jbyte repb, jint nn, jint inc) {

    int_1 *buf = (int_1*)(jpointer)lbuf;
    if (repa!=repb)
    switch (type) {
      case 'B': break;
      case 'A': break;
      case 'S': break;
      case 'I': if ( (repa==IEEE) != (repb==IEEE)) for (;--nn>=0;off+=inc) swap2 (buf+off,n); break;
      case 'L': if ( (repa==IEEE) != (repb==IEEE)) for (;--nn>=0;off+=inc) swap4 (buf+off,n); break;
      case 'X': if ( (repa==IEEE) != (repb==IEEE)) for (;--nn>=0;off+=inc) swap8 (buf+off,n); break;
      case 'P': if ( (repa==IEEE) != (repb==IEEE)) for (;--nn>=0;off+=inc) swap1 (buf+off,n); break;
      case 'F': switch (repa) {
	case VAX: switch (repb) {
	  case EEEI: for (;--nn>=0;off+=inc) f_vax2eeei (buf+off,n); break;
	  case IEEE: for (;--nn>=0;off+=inc) f_vax2ieee (buf+off,n); break;
	} break;
	case IEEE: switch (repb) {
	  case VAX:  for (;--nn>=0;off+=inc) f_ieee2vax (buf+off,n); break;
	  case EEEI: for (;--nn>=0;off+=inc)      swap4 (buf+off,n); break;
	} break;
	case EEEI: switch (repb) {
	  case VAX:  for (;--nn>=0;off+=inc) f_eeei2vax (buf+off,n); break;
	  case IEEE: for (;--nn>=0;off+=inc)      swap4 (buf+off,n); break;
	} break;
      } break;
      case 'D': switch (repa) {
	case VAX: switch (repb) {
	  case EEEI: for (;--nn>=0;off+=inc) d_vax2eeei (buf+off,n); break;
	  case IEEE: for (;--nn>=0;off+=inc) d_vax2ieee (buf+off,n); break;
	} break;
	case IEEE: switch (repb) {
	  case VAX:  for (;--nn>=0;off+=inc) d_ieee2vax (buf+off,n); break;
	  case EEEI: for (;--nn>=0;off+=inc)      swap8 (buf+off,n); break;
	} break;
	case EEEI: switch (repb) {
	  case VAX:  for (;--nn>=0;off+=inc) d_eeei2vax (buf+off,n); break;
	  case IEEE: for (;--nn>=0;off+=inc)      swap8 (buf+off,n); break;
	} break;
      } break;
    }
    return n;
}

/**************************** Byte Swap Routines **************************/

/* This is the same as Convert.bitrev[] - e.g. Bit reversed LUT buffer for
   Big/Little Endian Packet conversions used in swap1() method to reverse
   the bit order within a byte. */
static const unsigned char bitrev[] = {
  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
  0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
  0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
  0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
  0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
  0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
  0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
  0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
  0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
  0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
  0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
  0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
  0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
  0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
  0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
  0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};

/** This should be the same as Convert.swap1 (byte[] buf, int off, int n). */
void swap1 (int_1* buf, const int_4 n) {
  int i, off;
  /* (n>>3 )is same as dividing n by 8 (for number of bits per byte) */
  for (i=0, off=0; i<(n>>3); i++,off++) buf[off] = bitrev[ buf[off]&0xFF ];
}

/* quick way of swapping two values without temp storage! */
#define SWAB(a,b) {if(a!=b){a ^= b; b ^= a; a ^= b;}}

void swap2 (int_1 *buf, const int_4 n) {
  register int    i;
  register int    j = n * 2;
  register int_1   b;

  for (i = 0; i < j; i += 2) {
    b = buf[i];
    buf[i] = buf[i + 1];
    buf[i + 1] = b;
  }
}	/* swap2 */

void swap4 (int_1 *buf, const int_4 n) {
  register int    i;
  register int_1   b;
  register int    j = n * 4;

  for (i = 0; i < j; i += 4) {
    b = buf[i];
    buf[i] = buf[i + 3];
    buf[i + 3] = b;
    b = buf[i + 1];
    buf[i + 1] = buf[i + 2];
    buf[i + 2] = b;
  }
}	/* swap4 */

void swap8 (int_1 *buf, const int_4 n) {
  register int    i;
  register int_1   b;
  register int    j = n * 8;

  for (i = 0; i < j; i += 8) {
    b = buf[i];
    buf[i] = buf[i + 7];
    buf[i + 7] = b;
    b = buf[i + 1];
    buf[i + 1] = buf[i + 6];
    buf[i + 6] = b;
    b = buf[i + 2];
    buf[i + 2] = buf[i + 5];
    buf[i + 5] = b;
    b = buf[i + 3];
    buf[i + 3] = buf[i + 4];
    buf[i + 4] = b;
  }
}	/* swap8 */

void swapJ (int_1 *buf, const int_4 n, int_1 repa, int_1 repb) {
  register int i, m=n/2*3;
  register int_1 b;
  if (repa==IEEE && repb!=IEEE) for (i=0; i<m; i+=3) {
    b = buf[i+1];
    buf[i+1] = (buf[i+2]<<4) | ((buf[i]>>4)&0xF);
    buf[i+2] = (b<<4) | ((buf[i+2]>>4)&0xF);
    buf[i] = (buf[i]<<4) | ((b>>4)&0xF);
  }
  if (repa!=IEEE && repb==IEEE) for (i=0; i<m; i+=3) {
    b = buf[i+1];
    buf[i+1] = (buf[i]<<4) | ((buf[i+2]>>4)&0xF);
    buf[i] = (b<<4) | ((buf[i]>>4)&0xF);
    buf[i+2] = (buf[i+2]<<4) | ((b>>4)&0xF);
  }
}	/* swapJ */

/******************** Floating Point Conversion Routines ********************/
/*============================= Single Precision EEEI<->VAX Conversions ====*/
void f_vax2eeei (int_1 *buf_in, const int_4 n) {
  real_4 *buf = (real_4 *)buf_in;
#if _OSF
  int             i, flag;

  flag = 0;
  for (i = 0; i < n; i++)
    cvt_vax_f_to_ieee_single(buf + i, flag, buf + i);

#else
  int             i;
  int		  j = n;
  FOURBYTEDATA    ptr,tmp;

  for (i = 0; i < j; i++) {
    tmp.real4=buf[i];
    ptr.int2[0]=tmp.int2[1];
    ptr.int2[1]=tmp.int2[0];
    ptr.real4/=4;
    buf[i]=ptr.real4;
  }
#  endif
}	/* f_vax2eeei */

void f_eeei2vax (int_1 *buf_in, const int_4 n) {
  real_4 *buf = (real_4 *)buf_in;
#if _OSF
  int             i, flag;

  flag = 0;
  for (i = 0; i < n; i++)
    cvt_ieee_single_to_vax_f(buf + i, flag, buf + i);

#else
  int              i;
  int		   j = n;
  FOURBYTEDATA     ptr,tmp;

  for (i = 0; i < j; i++) {
    tmp.real4=buf[i]*4;
    ptr.int2[0]=tmp.int2[1];
    ptr.int2[1]=tmp.int2[0];
    buf[i]=ptr.real4;
  }
#  endif
}	/* f_eeei2vax2 */

/*============================= Double Precision EEEI<->VAX Conversions ====*/
void d_vax2eeei (int_1 *buf_in, const int_4 n) {
  real_8 *buf = (real_8 *)buf_in;
#if _OSF
  int             i, flag;

  flag = 0;
  for (i = 0; i < n; i++)
    cvt_vax_d_to_ieee_double(buf + i, flag, buf + i);

#else
  int              i;
  int		   j = n;
  int_u4   	   bias;
  EIGHTBYTEDATA   ptr,tmp;
  int_u1	signbit;

  bias = 1023 - 129;
  bias = bias << (52 - 32);
  for (i = 0; i < j; i++) {
    tmp.real8=buf[i];
    ptr.int2[0]=tmp.int2[3];
    ptr.int2[1]=tmp.int2[2];
    ptr.int2[2]=tmp.int2[1];
    ptr.int2[3]=tmp.int2[0];
    signbit=ptr.int1[7]&0x80;
    ptr.int1[7]&=0x7F;

    if (ptr.int4[0] != 0 || ptr.int4[1] != 0) {
      ptr.int4[0] = (ptr.int4[0] >> 3) | (ptr.int4[1] << 29);
      ptr.int4[1] = (ptr.int4[1] >> 3) + bias;
      ptr.int1[7]|=signbit;
      buf[i] = ptr.real8;
    }
  }
#endif
}	/* d_vax2eeei */

void d_eeei2vax (int_1 *buf_in, const int_4 n) {
  real_8 *buf = (real_8 *)buf_in;
#if _OSF
  int             i, flag;

  flag = 0;
  for (i = 0; i < n; i++)
    cvt_ieee_double_to_vax_d(buf + i, flag, buf + i);

#  elif _LINX|_IRIX
  int              i;
  int		   j = n;
  int_u4  	    bias;
  EIGHTBYTEDATA   ptr,tmp;
  int_u1	signbit;

  bias = 1023 - 129;
  bias = bias << (52 - 32);
  for (i = 0; i < j; i++) {
    ptr.real8 = buf[i];
    signbit=ptr.int1[7]&0x80;
    ptr.int1[7]&=0x7F;
    if (ptr.int4[0] != 0 || ptr.int4[1] != 0) {
      ptr.int4[1] = ((ptr.int4[1] - bias) << 3) | (ptr.int4[0] >> 29);
      ptr.int4[0] = (ptr.int4[0] << 3);
      ptr.int1[7] |= signbit;
      tmp.int2[0]=ptr.int2[3];
      tmp.int2[1]=ptr.int2[2];
      tmp.int2[2]=ptr.int2[1];
      tmp.int2[3]=ptr.int2[0];
      buf[i]=tmp.real8;
    }
  }
#endif
}	/* d_eeei2vax */

/*============================= Single Precision IEEE<->VAX Conversions ====*/
void f_vax2ieee (int_1 *buf, const int_4 n) {
  int		i, exp, man;
  int_4 	j = n;
  int_u4	*word;
  int_u2	*bufU2;

  /* swap the bytes */
  swap4(buf, j);

  word =(int_u4 *)buf;
  for (i = 0; i < j; i++) {
    man = word[i] & 0x7f;
    man = man << 16;
    man = man | (word[i] & 0xffff0000) >> 16;
    exp = word[i] & exp_msk;
    exp = exp >> 7;

    /* check for special cases */
    if (((exp == 0) && (man == 0)) || (exp <=3)) {
      word[i] = 0;	/* kill the sign bit */
      continue;
    }
    exp -= 2;

    /* put the exponent back */
    word[i] &= ~exp_msk;
    word[i] |= exp << 7;
  }

  /* swap the bytes */
  bufU2 = (int_u2 *)buf;
  for (i = 0; i < 2 * j; i += 2) {
    SWAB(bufU2[i],bufU2[i+1]);
  }
}	/* f_vax2ieee */

void f_ieee2vax (int_1 *buf, const int_4 n) {
  int		i, exp, man;
  int		j = n;
  int_u2	*bufU2;
  int_u4	*word;

  /* swap bytes */
  bufU2 = (int_u2 *)buf;
  for (i = 0; i < 2 * j; i += 2) {
    SWAB(bufU2[i],bufU2[i+1]);
  }

  word = (int_u4 *)buf;
  for (i = 0; i < j; i++) {
    man   = word[i] & 0x7f;
    man <<= 16;
    man  |= (word[i] & 0xffff0000) >> 16;
    exp   = word[i] & exp_msk;
    exp >>= 7;

    /* check for special cases */
    if (((exp == 0) && (man == 0)) || (exp == 1)) {
      word[i] = 0; /* kill the sign bit */
      continue;
    }
    if (exp >= 254) {
      word[i] |= exp_msk;		/* exp = 255   */
      word[i] |= 0xffff007f;	/* man = all 1 */
      continue;
    }

    exp += 2;

    /* put the exponent back */
    word[i] &= ~exp_msk;
    word[i] |= (exp << 7);
  }

  /* convert to VAX word order */
  swap4(buf, j);
}	/* f_ieee2vax */

/*============================= Double Precision IEEE<->VAX Conversions ====*/
void d_vax2ieee (int_1 *buf, const int_4 n) {
  int		i;
  int		j = n, k = n * 4;
  int_u8	*word, exp, man;

  /* swap bytes */
  swap2(buf, k);

  word = (int_u8 *)buf;
  for (i = 0; i < j; i++) {
    man = word[i] & vax_man_msk;
    exp = word[i] & vax_exp_msk;

    /* check for special cases */
    if ((exp == 0) && (man == 0)) {
      word[i] = 0;
      continue;
    }

    man >>= 3;
    exp >>= 55;
    exp  += (1023 - 2 - 127);
    exp <<= 52;

    /* put the mantissa back */
    word[i] &= ~ieee_man_msk;
    word[i] |= man;

    /* put the exponent back */
    word[i] &= ~ieee_exp_msk;
    word[i] |= exp;
  }
}	/* d_vax2ieee */

void d_ieee2vax (int_1 *buf, const int_4 n) {
  int		i;
  int		j = n, k = n * 4;
  int_u8	*word, man;
  int_8 	exp;

  word = (int_u8 *)buf;
  for (i = 0; i < j; i++) {
    man = word[i] & ieee_man_msk;
    exp = word[i] & ieee_exp_msk;

    /* check for special cases */
    if ((exp == 0) && (man == 0)) {
      word[i] = 0; /* kill the sign bit */
      continue;
    }

    exp >>= 52;
    exp  -= 1023;

    /* check bounds */
    if (exp >= 127) {
      word[i] |= (vax_exp_msk | vax_man_msk);
      continue;
    }
    if (exp <= -129) {
      word[i] = 0;
      continue;
    }

    exp  += (2 + 127);
    exp <<= 55;
    man <<= 3;

    /* put the mantissa back */
    word[i] &= ~vax_man_msk;
    word[i] |= man;

    /* put the exponent back */
    word[i] &= ~vax_exp_msk;
    word[i] |= exp;
  }

  /* convert to VAX word order */
  swap2(buf, k);
} /* d_ieee2vax */
