Index: GenericIO.cxx
===================================================================
--- GenericIO.cxx	(revision 14e73bb67da7c88ed4a2e4c7ff1232656894be54)
+++ GenericIO.cxx	(revision 5d57155c2b8a63fdd26a994151e5a4bf08823f7c)
@@ -322,4 +322,5 @@
   endian_specific_value<uint64_t, IsBigEndian> Flags;
   endian_specific_value<uint64_t, IsBigEndian> Size;
+  endian_specific_value<uint64_t, IsBigEndian> ElementSize;
 };
 
@@ -583,4 +584,5 @@
       VH->Flags = VFlags;
       RecordSize += VH->Size = Vars[i].Size;
+      VH->ElementSize = Vars[i].ElementSize;
     }
 
@@ -1379,4 +1381,8 @@
       }
 
+      size_t ElementSize = VH->Size;
+      if (offsetof_safe(VH, ElementSize) < GH->VarsSize)
+        ElementSize = VH->ElementSize;
+
       VarFound = true;
       bool IsFloat = (bool) (VH->Flags & FloatValue),
@@ -1387,4 +1393,10 @@
               " in: " << OpenFileName << ": current: " << Vars[i].Size <<
               ", file: " << VH->Size;
+        throw runtime_error(ss.str());
+      } else if (ElementSize != Vars[i].ElementSize) {
+        stringstream ss;
+        ss << "Element size mismatch for variable " << Vars[i].Name <<
+              " in: " << OpenFileName << ": current: " << Vars[i].ElementSize <<
+              ", file: " << ElementSize;
         throw runtime_error(ss.str());
       } else if (IsFloat != Vars[i].IsFloat) {
@@ -1565,7 +1577,8 @@
       // Byte swap the data if necessary.
       if (IsBigEndian != isBigEndian())
-        for (size_t j = 0; j < RH->NElems; ++j) {
-          char *Offset = ((char *) VarData) + j*Vars[i].Size;
-          bswap(Offset, Vars[i].Size);
+        for (size_t j = 0;
+             j < RH->NElems*(Vars[i].Size/Vars[i].ElementSize); ++j) {
+          char *Offset = ((char *) VarData) + j*Vars[i].ElementSize;
+          bswap(Offset, Vars[i].ElementSize);
         }
 
@@ -1625,4 +1638,8 @@
     if (VNameNull < NameSize)
       VName.resize(VNameNull);
+
+    size_t ElementSize = VH->Size;
+    if (offsetof_safe(VH, ElementSize) < GH->VarsSize)
+      ElementSize = VH->ElementSize;
 
     bool IsFloat = (bool) (VH->Flags & FloatValue),
@@ -1634,5 +1651,5 @@
     VI.push_back(VariableInfo(VName, (size_t) VH->Size, IsFloat, IsSigned,
                               IsPhysCoordX, IsPhysCoordY, IsPhysCoordZ,
-                              MaybePhysGhost));
+                              MaybePhysGhost, ElementSize));
   }
 }
Index: GenericIO.h
===================================================================
--- GenericIO.h	(revision 14e73bb67da7c88ed4a2e4c7ff1232656894be54)
+++ GenericIO.h	(revision 5d57155c2b8a63fdd26a994151e5a4bf08823f7c)
@@ -117,4 +117,48 @@
   int FH;
 };
+
+namespace detail {
+// A standard enable_if idiom (we include our own here for pre-C++11 support).
+template <bool B, typename T = void>
+struct enable_if {};
+
+template <typename T>
+struct enable_if<true, T> { typedef T type; };
+
+// A SFINAE-based trait to detect whether a type has a member named x. This is
+// designed to work both with structs/classes and also with OpenCL-style vector
+// types.
+template <typename T>
+class has_x {
+  typedef char yes[1];
+  typedef char no[2];
+
+  template <typename C>
+  static yes &test(char(*)[sizeof((*((C *) 0)).x)]);
+
+  template <typename C>
+  static no &test(...);
+
+public:
+  enum { value = sizeof(test<T>(0)) == sizeof(yes) };
+};
+
+// A SFINAE-based trait to detect whether a type is array-like (i.e. supports
+// the [] operator).
+template <typename T>
+class is_array {
+  typedef char yes[1];
+  typedef char no[2];
+
+  template <typename C>
+  static yes &test(char(*)[sizeof((*((C *) 0))[0])]);
+
+  template <typename C>
+  static no &test(...);
+
+public:
+  enum { value = sizeof(test<T>(0)) == sizeof(yes) };
+};
+} // namespace detail
 
 class GenericIO {
@@ -133,8 +177,8 @@
   struct VariableInfo {
     VariableInfo(const std::string &N, std::size_t S, bool IF, bool IS,
-                 bool PCX, bool PCY, bool PCZ, bool PG)
+                 bool PCX, bool PCY, bool PCZ, bool PG, std::size_t ES = 0)
       : Name(N), Size(S), IsFloat(IF), IsSigned(IS),
         IsPhysCoordX(PCX), IsPhysCoordY(PCY), IsPhysCoordZ(PCZ),
-        MaybePhysGhost(PG) {}
+        MaybePhysGhost(PG), ElementSize(ES ? ES : S) {}
 
     std::string Name;
@@ -144,18 +188,68 @@
     bool IsPhysCoordX, IsPhysCoordY, IsPhysCoordZ;
     bool MaybePhysGhost;
+    std::size_t ElementSize;
   };
 
 public:
-  struct Variable {
+  class Variable {
+  private:
+    template <typename ET>
+    void deduceTypeInfoFromElement(ET *) {
+      ElementSize = sizeof(ET);
+      IsFloat = !std::numeric_limits<ET>::is_integer;
+      IsSigned = std::numeric_limits<ET>::is_signed;
+    }
+
+    // There are specializations here to handle array types
+    // (e.g. typedef float float4[4];), struct types
+    // (e.g. struct float4 { float x, y, z, w; };), and scalar types.
+    // Builtin vector types
+    // (e.g. typedef float float4 __attribute__((ext_vector_type(4)));) should
+    // also work.
+    template <typename T>
+    typename detail::enable_if<detail::is_array<T>::value, void>::type
+    deduceTypeInfo(T *D) {
+      Size = sizeof(T);
+      deduceTypeInfoFromElement(&(*D)[0]);
+    }
+
+    template <typename T>
+    typename detail::enable_if<detail::has_x<T>::value &&
+                               !detail::is_array<T>::value, void>::type
+    deduceTypeInfo(T *D) {
+      Size = sizeof(T);
+      deduceTypeInfoFromElement(&(*D).x);
+    }
+
+    template <typename T>
+    typename detail::enable_if<!detail::has_x<T>::value &&
+                               !detail::is_array<T>::value, void>::type
+    deduceTypeInfo(T *D) {
+      Size = sizeof(T);
+      deduceTypeInfoFromElement(D);
+    }
+
+  public:
     template <typename T>
     Variable(const std::string &N, T* D, unsigned Flags = 0)
-      : Name(N), Size(sizeof(T)),
-        IsFloat(!std::numeric_limits<T>::is_integer),
-        IsSigned(std::numeric_limits<T>::is_signed),
-        Data((void *) D), HasExtraSpace(Flags & VarHasExtraSpace),
+      : Name(N), Data((void *) D), HasExtraSpace(Flags & VarHasExtraSpace),
         IsPhysCoordX(Flags & VarIsPhysCoordX),
         IsPhysCoordY(Flags & VarIsPhysCoordY),
         IsPhysCoordZ(Flags & VarIsPhysCoordZ),
-        MaybePhysGhost(Flags & VarMaybePhysGhost) {}
+        MaybePhysGhost(Flags & VarMaybePhysGhost) {
+      deduceTypeInfo(D);
+    }
+
+    template <typename T>
+    Variable(const std::string &N, std::size_t NumElements, T* D,
+             unsigned Flags = 0)
+      : Name(N), Data((void *) D), HasExtraSpace(Flags & VarHasExtraSpace),
+        IsPhysCoordX(Flags & VarIsPhysCoordX),
+        IsPhysCoordY(Flags & VarIsPhysCoordY),
+        IsPhysCoordZ(Flags & VarIsPhysCoordZ),
+        MaybePhysGhost(Flags & VarMaybePhysGhost) {
+      deduceTypeInfoFromElement(D);
+      Size = ElementSize*NumElements;
+    }
 
     Variable(const VariableInfo &VI, void *D, unsigned Flags = 0)
@@ -166,5 +260,6 @@
         IsPhysCoordY((Flags & VarIsPhysCoordY) || VI.IsPhysCoordY),
         IsPhysCoordZ((Flags & VarIsPhysCoordZ) || VI.IsPhysCoordZ),
-        MaybePhysGhost((Flags & VarMaybePhysGhost) || VI.MaybePhysGhost) {}
+        MaybePhysGhost((Flags & VarMaybePhysGhost) || VI.MaybePhysGhost),
+        ElementSize(VI.ElementSize) {}
 
     std::string Name;
@@ -176,4 +271,5 @@
     bool IsPhysCoordX, IsPhysCoordY, IsPhysCoordZ;
     bool MaybePhysGhost;
+    std::size_t ElementSize;
   };
 
@@ -261,4 +357,17 @@
   }
 
+  template <typename T>
+  void addScalarizedVariable(const std::string &Name, T *Data,
+                             std::size_t NumElements, unsigned Flags = 0) {
+    Vars.push_back(Variable(Name, NumElements, Data, Flags));
+  }
+
+  template <typename T, typename A>
+  void addScalarizedVariable(const std::string &Name, std::vector<T, A> &Data,
+                             std::size_t NumElements, unsigned Flags = 0) {
+    T *D = Data.empty() ? 0 : &Data[0];
+    addScalarizedVariable(Name, D, NumElements, Flags);
+  }
+
 #ifndef GENERICIO_NO_MPI
   // Writing
Index: GenericIOBenchmarkRead.cxx
===================================================================
--- GenericIOBenchmarkRead.cxx	(revision 8f0a211de68fdaf18f8af21d8574c73197b28c5e)
+++ GenericIOBenchmarkRead.cxx	(revision 5d57155c2b8a63fdd26a994151e5a4bf08823f7c)
@@ -54,4 +54,8 @@
 #define MASK_T uint16_t
 
+struct pos_t {
+  POSVEL_T x, y, z, w;
+};
+
 using namespace std;
 using namespace gio;
@@ -64,14 +68,24 @@
   MPI_Comm_size(MPI_COMM_WORLD, &commRanks);
 
+  bool UseAOS = false;
+  int a = 1;
+  if (argc > 1 && string(argv[a]) == "-a") {
+    UseAOS = true;
+    --argc;
+    ++a;
+  }
+
   if(argc != 2) {
-    fprintf(stderr,"USAGE: %s <mpiioName>\n", argv[0]);
+    fprintf(stderr,"USAGE: %s [-a] <mpiioName>\n", argv[0]);
     exit(-1);
   }
 
-  char *mpiioName = argv[1];
+  char *mpiioName = argv[a];
 
   vector<POSVEL_T> xx, yy, zz, vx, vy, vz, phi;
   vector<ID_T> id;
   vector<MASK_T> mask;
+
+  vector<pos_t> pos, vel;
 
   assert(sizeof(ID_T) == 8);
@@ -93,34 +107,49 @@
   Np = GIO.readNumElems();
 
-  xx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  yy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  zz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  vx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  vy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  vz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  phi.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+  if (UseAOS) {
+    pos.resize(Np + (GIO.requestedExtraSpace() + sizeof(pos_t) - 1)/sizeof(pos_t));
+    vel.resize(Np + (GIO.requestedExtraSpace() + sizeof(pos_t) - 1)/sizeof(pos_t));
+  } else {
+    xx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    yy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    zz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    vx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    vy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    vz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    phi.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+  }
   id.resize(Np + GIO.requestedExtraSpace()/sizeof(ID_T));
   mask.resize(Np + GIO.requestedExtraSpace()/sizeof(MASK_T));
 
-  GIO.addVariable("x", xx, true);
-  GIO.addVariable("y", yy, true);
-  GIO.addVariable("z", zz, true);
-  GIO.addVariable("vx", vx, true);
-  GIO.addVariable("vy", vy, true);
-  GIO.addVariable("vz", vz, true);
-  GIO.addVariable("phi", phi, true);
-  GIO.addVariable("id", id, true);
-  GIO.addVariable("mask", mask, true);
+  if (UseAOS) {
+    GIO.addVariable("pos", pos, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vel", vel, GenericIO::VarHasExtraSpace);
+  } else {
+    GIO.addVariable("x", xx, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("y", yy, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("z", zz, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vx", vx, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vy", vy, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vz", vz, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("phi", phi, GenericIO::VarHasExtraSpace);
+  }
+  GIO.addVariable("id", id, GenericIO::VarHasExtraSpace);
+  GIO.addVariable("mask", mask, GenericIO::VarHasExtraSpace);
 
   GIO.readData();
   } // destroy GIO prior to calling MPI_Finalize
 
-  xx.resize(Np);
-  yy.resize(Np);
-  zz.resize(Np);
-  vx.resize(Np);
-  vy.resize(Np);
-  vz.resize(Np);
-  phi.resize(Np);
+  if (UseAOS) {
+    pos.resize(Np);
+    vel.resize(Np);
+  } else {
+    xx.resize(Np);
+    yy.resize(Np);
+    zz.resize(Np);
+    vx.resize(Np);
+    vy.resize(Np);
+    vz.resize(Np);
+    phi.resize(Np);
+  }
   id.resize(Np);
   mask.resize(Np);
Index: GenericIOBenchmarkWrite.cxx
===================================================================
--- GenericIOBenchmarkWrite.cxx	(revision cda87e9f70222875d8b16fb6cffdf0a04781acae)
+++ GenericIOBenchmarkWrite.cxx	(revision 5d57155c2b8a63fdd26a994151e5a4bf08823f7c)
@@ -70,4 +70,26 @@
 };
 
+struct pos_t {
+  POSVEL_T x, y, z, w;
+};
+
+template <>
+struct Generator<pos_t> {
+  Generator(POSVEL_T start, POSVEL_T inc) :
+    GenX(start, inc), GenY(start, inc), GenZ(start, inc), GenW(start, inc) {}
+
+  pos_t operator()() {
+    pos_t v;
+    v.x = GenX();
+    v.y = GenY();
+    v.z = GenZ();
+    v.w = GenW();
+
+    return v;
+  }
+
+  Generator<POSVEL_T> GenX, GenY, GenZ, GenW;
+};
+
 int main(int argc, char *argv[]) {
   MPI_Init(&argc, &argv);
@@ -77,5 +99,12 @@
   MPI_Comm_size(MPI_COMM_WORLD, &commRanks);
 
+  bool UseAOS = false;
   int a = 1;
+  if (argc > 1 && string(argv[a]) == "-a") {
+    UseAOS = true;
+    --argc;
+    ++a;
+  }
+
   if (argc > 1 && string(argv[a]) == "-c") {
     GenericIO::setDefaultShouldCompress(true);
@@ -85,5 +114,5 @@
 
   if(argc != 4) {
-    fprintf(stderr,"USAGE: %s [-c] <mpiioName> <NP> <seed>\n", argv[0]);
+    fprintf(stderr,"USAGE: %s [-a] [-c] <mpiioName> <NP> <seed>\n", argv[0]);
     exit(-1);
   }
@@ -103,4 +132,6 @@
   vector<ID_T> id;
   vector<MASK_T> mask;
+
+  vector<pos_t> pos, vel;
 
   assert(sizeof(ID_T) == 8);
@@ -123,31 +154,47 @@
   GIO.setPhysScale(256.0);
 
-  xx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  yy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  zz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  vx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  vy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  vz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
-  phi.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+  if (UseAOS) {
+    pos.resize(Np + (GIO.requestedExtraSpace() + sizeof(pos_t) - 1)/sizeof(pos_t));
+    vel.resize(Np + (GIO.requestedExtraSpace() + sizeof(pos_t) - 1)/sizeof(pos_t));
+  } else {
+    xx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    yy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    zz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    vx.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    vy.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    vz.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+    phi.resize(Np + GIO.requestedExtraSpace()/sizeof(POSVEL_T));
+  }
   id.resize(Np + GIO.requestedExtraSpace()/sizeof(ID_T));
   mask.resize(Np + GIO.requestedExtraSpace()/sizeof(MASK_T));
 
-  std::generate(xx.begin(), xx.end(), Generator<POSVEL_T>(25, 3));
-  std::generate(yy.begin(), yy.end(), Generator<POSVEL_T>(25, 3));
-  std::generate(zz.begin(), zz.end(), Generator<POSVEL_T>(25, 3));
-  std::generate(vx.begin(), vx.end(), Generator<POSVEL_T>(25, 3));
-  std::generate(vy.begin(), vy.end(), Generator<POSVEL_T>(25, 3));
-  std::generate(vz.begin(), vz.end(), Generator<POSVEL_T>(25, 3));
-  std::generate(phi.begin(), phi.end(), Generator<POSVEL_T>(25, 3));
+  if (UseAOS) {
+    std::generate(pos.begin(), pos.end(), Generator<pos_t>(25, 3));
+    std::generate(vel.begin(), vel.end(), Generator<pos_t>(25, 3));
+  } else {
+    std::generate(xx.begin(), xx.end(), Generator<POSVEL_T>(25, 3));
+    std::generate(yy.begin(), yy.end(), Generator<POSVEL_T>(25, 3));
+    std::generate(zz.begin(), zz.end(), Generator<POSVEL_T>(25, 3));
+    std::generate(vx.begin(), vx.end(), Generator<POSVEL_T>(25, 3));
+    std::generate(vy.begin(), vy.end(), Generator<POSVEL_T>(25, 3));
+    std::generate(vz.begin(), vz.end(), Generator<POSVEL_T>(25, 3));
+    std::generate(phi.begin(), phi.end(), Generator<POSVEL_T>(25, 3));
+  }
   std::generate(id.begin(), id.end(), Generator<ID_T>(25, 3));
   std::fill(mask.begin(), mask.end(), 25);
 
-  GIO.addVariable("x", xx, CoordFlagsX | GenericIO::VarHasExtraSpace);
-  GIO.addVariable("y", yy, CoordFlagsY | GenericIO::VarHasExtraSpace);
-  GIO.addVariable("z", zz, CoordFlagsZ | GenericIO::VarHasExtraSpace);
-  GIO.addVariable("vx", vx, GenericIO::VarHasExtraSpace);
-  GIO.addVariable("vy", vy, GenericIO::VarHasExtraSpace);
-  GIO.addVariable("vz", vz, GenericIO::VarHasExtraSpace);
-  GIO.addVariable("phi", phi, GenericIO::VarHasExtraSpace);
+  if (UseAOS) {
+    GIO.addVariable("pos", pos, CoordFlagsX | CoordFlagsY | CoordFlagsZ |
+                                GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vel", vel, GenericIO::VarHasExtraSpace);
+  } else {
+    GIO.addVariable("x", xx, CoordFlagsX | GenericIO::VarHasExtraSpace);
+    GIO.addVariable("y", yy, CoordFlagsY | GenericIO::VarHasExtraSpace);
+    GIO.addVariable("z", zz, CoordFlagsZ | GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vx", vx, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vy", vy, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("vz", vz, GenericIO::VarHasExtraSpace);
+    GIO.addVariable("phi", phi, GenericIO::VarHasExtraSpace);
+  }
   GIO.addVariable("id", id, GenericIO::VarHasExtraSpace);
   GIO.addVariable("mask", mask, GenericIO::VarHasExtraSpace);
@@ -156,11 +203,16 @@
   } // destroy GIO prior to calling MPI_Finalize
 
-  xx.resize(Np);
-  yy.resize(Np);
-  zz.resize(Np);
-  vx.resize(Np);
-  vy.resize(Np);
-  vz.resize(Np);
-  phi.resize(Np);
+  if (UseAOS) {
+    pos.resize(Np);
+    vel.resize(Np);
+  } else {
+    xx.resize(Np);
+    yy.resize(Np);
+    zz.resize(Np);
+    vx.resize(Np);
+    vy.resize(Np);
+    vz.resize(Np);
+    phi.resize(Np);
+  }
   id.resize(Np);
   mask.resize(Np);
Index: GenericIOPrint.cxx
===================================================================
--- GenericIOPrint.cxx	(revision 8f0a211de68fdaf18f8af21d8574c73197b28c5e)
+++ GenericIOPrint.cxx	(revision 5d57155c2b8a63fdd26a994151e5a4bf08823f7c)
@@ -63,14 +63,21 @@
 class Printer : public PrinterBase {
 public:
-  Printer(GenericIO &G, size_t MNE, const string &N)
-    : Data(MNE + G.requestedExtraSpace()/sizeof(T)) {
-    G.addVariable(N, Data, true);
+  Printer(GenericIO &G, size_t MNE, size_t NE, const string &N)
+    : NumElements(NE), Data(MNE*NE + G.requestedExtraSpace()/sizeof(T)) {
+    G.addScalarizedVariable(N, Data, NE, GenericIO::VarHasExtraSpace);
   }
 
   virtual void print(ostream &os, size_t i) {
-    os << scientific << setprecision(numeric_limits<T>::digits10) << Data[i];
+    for (size_t j = 0; j < NumElements; ++j) {
+      os << scientific << setprecision(numeric_limits<T>::digits10) <<
+            Data[i*NumElements + j];
+
+      if (j != NumElements - 1)
+        os << "\t";
+    }
   }
 
 protected:
+  size_t NumElements;
   vector<T> Data;
 };
@@ -79,5 +86,5 @@
 PrinterBase *addPrinter(GenericIO::VariableInfo &V,
                 GenericIO &GIO, size_t MNE) {
-  if (sizeof(T) != V.Size)
+  if (sizeof(T) != V.ElementSize)
     return 0;
 
@@ -87,5 +94,5 @@
     return 0;
 
-  return new Printer<T>(GIO, MNE, V.Name);
+  return new Printer<T>(GIO, MNE, V.Size/V.ElementSize, V.Name);
 }
 
@@ -241,5 +248,27 @@
     cout << "# ";
     for (size_t i = 0; i < VI.size(); ++i) {
-      cout << VI[i].Name;
+      if (VI[i].Size == VI[i].ElementSize) {
+        cout << VI[i].Name;
+      } else {
+        size_t NumElements = VI[i].Size/VI[i].ElementSize;
+        for (size_t j = 0; j < NumElements; ++j) {
+          cout << VI[i].Name;
+          if (j == 0) {
+            cout << ".x";
+          } else if (j == 1) {
+            cout << ".y";
+          } else if (j == 2) {
+            cout << ".z";
+          } else if (j == 3) {
+            cout << ".w";
+          } else {
+            cout << ".w" << (j - 3);
+          }
+
+          if (j != NumElements - 1)
+            cout << "\t";
+        }
+      }
+
       if (i != VI.size() - 1)
         cout << "\t";
