Index: /branches/eam_branches/ipp-20191011/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- /branches/eam_branches/ipp-20191011/Ohana/src/libfits/include/gfitsio.h	(revision 41135)
+++ /branches/eam_branches/ipp-20191011/Ohana/src/libfits/include/gfitsio.h	(revision 41136)
@@ -259,5 +259,5 @@
 int     gfits_read_table               PROTO((char *filename, FTable *ftable)); 
 int     gfits_set_bintable_column      PROTO((Header *header, FTable *table, char *label, void *data, off_t Nrow));
-int     gfits_set_bintable_column_reformat PROTO((Header *header, FTable *table, char *label, char *intype, void *data, off_t Nrow, char nativeOrder));
+int     gfits_set_bintable_column_reformat PROTO((Header *header, FTable *table, char *label, char *intype, void *data, off_t Nrow, int element, char nativeOrder));
 int     gfits_set_table_column         PROTO((Header *header, FTable *table, char *label, void *data, off_t Nrow));
 int     gfits_table_column             PROTO((FTable *ftable, char *field, char *mode,...)) OHANA_FORMAT(printf, 3, 4);
Index: /branches/eam_branches/ipp-20191011/Ohana/src/libfits/table/F_define_column.c
===================================================================
--- /branches/eam_branches/ipp-20191011/Ohana/src/libfits/table/F_define_column.c	(revision 41135)
+++ /branches/eam_branches/ipp-20191011/Ohana/src/libfits/table/F_define_column.c	(revision 41136)
@@ -56,4 +56,5 @@
   char type[64], field[64];
   
+  // this call supported multiple columns per named field
   if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
   
Index: /branches/eam_branches/ipp-20191011/Ohana/src/libfits/table/F_set_column.c
===================================================================
--- /branches/eam_branches/ipp-20191011/Ohana/src/libfits/table/F_set_column.c	(revision 41135)
+++ /branches/eam_branches/ipp-20191011/Ohana/src/libfits/table/F_set_column.c	(revision 41136)
@@ -253,5 +253,5 @@
 /***********************/
 // convert the input data array (of the specified intype) to the desired table data type. swap unless nativeOrder is requested
-int gfits_set_bintable_column_reformat (Header *header, FTable *table, char *label, char *intype, void *data, off_t Nrow, char nativeOrder) {
+int gfits_set_bintable_column_reformat (Header *header, FTable *table, char *label, char *intype, void *data, off_t Nrow, int element, char nativeOrder) {
 
   off_t Nx, Ny;
@@ -288,4 +288,8 @@
 
   if (!gfits_bintable_format (format, outtype, &Nval, &NbytesOut)) return (FALSE);
+  if (element >= Nval) {
+    fprintf (stderr, "programming error: element >= Nval for field %s, format %s\n", label, format);
+    return FALSE;
+  }
   
   /* check existing table dimensions */
@@ -307,9 +311,13 @@
   }
 
+  // NOTE: we are inserting a single column into the output
+  // table.  If the output field is multi-value, the resulting
+  // array is inserted into the appropriate bytes in that output field
+
   /* make duplicate of data with correct type
      byte swap and Bzero/Bscale */
-  ALLOCATE (array, char, NbytesOut*Nval*Nrow);
+  ALLOCATE (array, char, NbytesOut*Nrow);
   Pin = data;
-  Pout = array;
+  Pout = array; // 
 
   // # define ASSIGN_DATA(ITYPE,INAME,ISIZE,OTYPE,ONAME)
@@ -321,5 +329,5 @@
   if (!strcmp (outtype, OUTNAME) && !strcmp (intype, INNAME)) {		\
     int NbytesIn = NBYTES_IN;						\
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) { \
+    for (i = 0; i < Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) { \
       if (directCopy) {							\
 	*(OUTTYPE *)Pout = *(INTYPE *)Pin;				\
@@ -385,425 +393,4 @@
   SET_VALUES("double",   double, "double", double, SWAP_DBLE, 8);
 
-# if (0)
-  /** input == char **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
-      if (directCopy) { *(char *)Pout = *(char *)Pin; } else {
-	*(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
-      }
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
-      if (directCopy) { *(char *)Pout = *(char *)Pin; } else {
-	*(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
-      }
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      if (directCopy) { *(short *)Pout = *(char *)Pin; } else {
-	*(short *)Pout = (*(char *)Pin - Bzero) / Bscale;
-      }
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "char")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-
-  /** input == byte **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
-      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin+=NbytesIn, Pout+=NbytesOut) {
-      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(short *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "byte")) {
-    int NbytesIn = 1;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(char *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-
-  /** input == short **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(short *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(short *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(short *)Pout = (*(short *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(short *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(short *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(short *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "short")) {
-    int NbytesIn = 2;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(short *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-
-  /** input == int **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(int *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(int *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(short *)Pout = (*(int *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(int *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(int *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(int *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "int")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(int *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-
-  /** input == int64_t **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(short *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "int64_t")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(int64_t *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-
-  /** input == float **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(float *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(float *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(short *)Pout = (*(float *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(float *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(float *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(float *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "float")) {
-    int NbytesIn = 4;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(float *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-
-  /** input == double **/
-  if (!strcmp (outtype, "char") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(double *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "byte") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(char *)Pout = (*(double *)Pin - Bzero) / Bscale;
-    }
-  }
-  if (!strcmp (outtype, "short") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(short *)Pout = (*(double *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_BYTE; }
-# endif
-    }  
-  }
-  if (!strcmp (outtype, "int") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int *)Pout = (*(double *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "int64_t") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(int64_t *)Pout = (*(double *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "float") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(float *)Pout = (*(double *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_WORD; }
-# endif
-    }
-  }
-  if (!strcmp (outtype, "double") && !strcmp (intype, "double")) {
-    int NbytesIn = 8;
-    for (i = 0; i < Nval*Nrow; i++, Pin += NbytesIn, Pout += NbytesOut) {
-      *(double *)Pout = (*(double *)Pin - Bzero) / Bscale;
-# ifdef BYTE_SWAP
-      if (!nativeOrder) { SWAP_DBLE; }
-# endif
-    }
-  }
-# endif
-
   /* check array space */
   if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*NbytesOut) {
@@ -813,8 +400,8 @@
 
   /* insert bytes from array into appropriate section of buffer */
-  Pout = table[0].buffer + Nstart;
+  Pout = table[0].buffer + Nstart + element*NbytesOut;
   Pin  = array;
-  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*NbytesOut) {
-    memcpy (Pout, Pin, Nval*NbytesOut);
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += NbytesOut) {
+    memcpy (Pout, Pin, NbytesOut);
   }
 
Index: /branches/eam_branches/ipp-20191011/Ohana/src/opihi/lib.data/SplineOps.c
===================================================================
--- /branches/eam_branches/ipp-20191011/Ohana/src/opihi/lib.data/SplineOps.c	(revision 41135)
+++ /branches/eam_branches/ipp-20191011/Ohana/src/opihi/lib.data/SplineOps.c	(revision 41136)
@@ -179,7 +179,7 @@
 
   // NOTE: if we want to compress the output table, use native byte order here (last element)
-  gfits_set_bintable_column_reformat (&theader, &ftable, "X_KNOT", "double", myspline->xk, myspline->Nknots, FALSE);
-  gfits_set_bintable_column_reformat (&theader, &ftable, "Y_KNOT", "double", myspline->yk, myspline->Nknots, FALSE);
-  gfits_set_bintable_column_reformat (&theader, &ftable, "DY2_DX", "double", myspline->y2, myspline->Nknots, FALSE);
+  gfits_set_bintable_column_reformat (&theader, &ftable, "X_KNOT", "double", myspline->xk, myspline->Nknots, 0, FALSE);
+  gfits_set_bintable_column_reformat (&theader, &ftable, "Y_KNOT", "double", myspline->yk, myspline->Nknots, 0, FALSE);
+  gfits_set_bintable_column_reformat (&theader, &ftable, "DY2_DX", "double", myspline->y2, myspline->Nknots, 0, FALSE);
 
   if (!append) {
Index: /branches/eam_branches/ipp-20191011/Ohana/src/opihi/lib.shell/VectorIO.c
===================================================================
--- /branches/eam_branches/ipp-20191011/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 41135)
+++ /branches/eam_branches/ipp-20191011/Ohana/src/opihi/lib.shell/VectorIO.c	(revision 41136)
@@ -7,17 +7,28 @@
   int j;
 
-  char *tformat = NULL;
-
   Header *theader = ftable->header;
   gfits_create_table_header (theader, "BINTABLE", extname);
 
-  ALLOCATE (tformat, char, 2*Nvec);
+  // allocate an array of strings to represent the format for each output field
+  // formats include single column formats (BIJKDE) and multi-column formats (e.g., 2I)
+  // we will have no more than Nvec fields (but we can have fewer)
+  int Nfield = 0;
+  ALLOCATE_PTR (tformat, char *, Nvec);
+  ALLOCATE_PTR (Nelement, int, Nvec);
+
   if (format) {
-    // the bintable format string can only define the byte-width of each field.  valid output columns are currently:
+    // the bintable format string can defines the byte-width of each field and number of elements (columns per field).
+    // valid output columns are currently:
     // B (char), I (16 bit short), J (32 bit int), E (32 bit float), D (64 bit double).
-    // the format string is just the sequence of types, eg: LIIJEED
-    // validate the format string
+    // the format string is just the sequence of types, eg: LIIJEED.
+    // it may have spaces or integer element counts:
+    // "2D 4I EEJ"
+
+    // *** validate the format string
+
+    // as I parse each elements, if it is a digit, I need parse that value
+
     char *ptr = format;
-    for (j = 0; j < Nvec; j++) {
+    for (j = 0; j < Nvec; ) {
       while (*ptr && OHANA_WHITESPACE (*ptr)) ptr++;
       if (*ptr == 0) {
@@ -25,11 +36,33 @@
 	goto escape;
       }
+
+      // is there a leading integer?
+      char *endptr;
+      Nelement[Nfield] = strtol (ptr, &endptr, 10);
+      if (endptr == ptr) {
+	Nelement[Nfield] = 1;
+      }
+      ptr = endptr; // this should now point at the letter that is the format type
       if ((*ptr != 'B') && (*ptr != 'I') && (*ptr != 'J') && (*ptr != 'K') && (*ptr != 'D') && (*ptr != 'E')) {
 	gprint (GP_ERR, "error in binary table format %s: invalid character %c\n", format, *ptr);
 	goto escape;
       }
-      tformat[2*j + 0] = *ptr;
-      tformat[2*j + 1] = 0; // a bit sleazy : use a 2xN string to store N 1-byte strings
+
+      int Nchar = snprintf (tformat[Nfield], 0, "%d%c", Nelement[Nfield], *ptr);
+      ALLOCATE (tformat[Nfield], char, Nchar + 1);
+      int Nout = snprintf (tformat[Nfield], Nchar + 1, "%d%c", Nelement[Nfield], *ptr);
+      myAssert (Nout <= Nchar, "oops");
+
+      // tformat[2*j + 0] = *ptr;
+      // tformat[2*j + 1] = 0; // a bit sleazy : use a 2xN string to store N 1-byte strings
+
+      j += Nelement[Nfield]; // advance past 
+      if (j > Nvec) {
+	gprint (GP_ERR, "error in binary table format %s (too few vectors for listed field)\n", format);
+	goto escape;
+      }
+
       ptr ++;
+      Nfield ++;
     }
     while (*ptr && OHANA_WHITESPACE (*ptr)) ptr++;
@@ -41,7 +74,10 @@
     for (j = 0; j < Nvec; j++) {
       // if the format is not defined, just use the native byte-widths
-      tformat[2*j + 0] = (vec[j][0].type == OPIHI_FLT) ? 'D' : 'K'; // this depends on opihi_int == int64_t for Int
-      tformat[2*j + 1] = 0;
-    }
+      ALLOCATE (tformat[j], char, 2);
+      tformat[j][0] = (vec[j][0].type == OPIHI_FLT) ? 'D' : 'K'; // this depends on opihi_int == int64_t for Int
+      tformat[j][1] = 0;
+      Nelement[j] = 1;
+    }
+    Nfield = Nvec;
   }
 
@@ -49,6 +85,15 @@
   // output table (because the data goes to the named column below).  need to enforce
   // this somehow
-  for (j = 0; j < Nvec; j++) {
-    gfits_define_bintable_column (theader, &tformat[2*j], vec[j][0].name, NULL, NULL, 1.0, 0.0);
+  int ivec = 0;
+  for (j = 0; j < Nfield; j++) {
+    // XX need to loop over fields, and skip the additional vectors that are part of a field
+    // this call supported multiple columns per named field
+    gfits_define_bintable_column (theader, tformat[j], vec[ivec][0].name, NULL, NULL, 1.0, 0.0);
+    ivec += Nelement[j];
+  }
+
+  // need to free the array 
+  for (j = 0; j < Nfield; j++) {
+    free (tformat[j]);
   }
   free (tformat);
@@ -57,11 +102,18 @@
   gfits_create_table (theader, ftable);
 
+  // I need to add each vector in order, but I need to
+  // track which field it corresponds to.
+
   // add the vectors to the output array
-  for (j = 0; j < Nvec; j++) {
-    if (vec[j][0].type == OPIHI_FLT) {
-      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "double",  vec[j][0].elements.Flt, vec[j][0].Nelements, nativeOrder);
-    } else {
-//    gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int",     vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder);
-      gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int64_t", vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder);
+  for (ivec = 0, j = 0; j < Nfield; j++) {
+    // the first vector provides the name for the field
+    char *fieldname = vec[ivec][0].name;
+    for (int k = 0; k < Nelement[j]; k++, ivec++) {
+      Vector *thisvec = vec[ivec];
+      if (thisvec->type == OPIHI_FLT) {
+	gfits_set_bintable_column_reformat (theader, ftable, fieldname, "double",  thisvec->elements.Flt, thisvec->Nelements, k, nativeOrder);
+      } else {
+	gfits_set_bintable_column_reformat (theader, ftable, fieldname, "int64_t", thisvec->elements.Int, thisvec->Nelements, k, nativeOrder);
+      }
     }
   }
