#include "preact/fwrap.h"
#include <sstream>

// ----------- frwap_att ------------
string fwrap_att::despace(string s) {
  bool ok=true ;
  for (string::size_type j=0 ; j<s.length() ; j++) {
    if (isspace(s[j])) {
      ok=false ; break ;
    } ;
  } ;
  if (ok) {
    // cout << "returning the original = " << s << endl ;
    return s ;
  } ;
  string t ;
  for (string::size_type j=0 ; j<s.length() ; j++) {
    if (isspace(s[j])) continue ;
    t.push_back(s[j]) ;
  } ;
  // cout << "returning a new one = " << t << endl ;
  return t ;
} ;

string fwrap_att::despace0(string s) {
  string t = despace(s) ;
  if (t.size()==0) throw fwrap_att_error("?fwrap_att:despace0(): attempted to use an empty string as a name") ;
  return t ;
}

string fwrap_att::att_name(fwrap_att::att_type t) {
  switch(t) {
  case fwrap_att::itype:
    return "int" ;
  case fwrap_att::dtype:
    return "double" ;
  case fwrap_att::stype:
    return "string" ;
  default:
    return "unknown" ;
  }
} ;


fwrap_att::fwrap_att_error& fwrap_att::fwrap_att_error::operator=(const fwrap_att::fwrap_att_error& q) throw() {
  if (&q!=this) {
    std::exception::operator=(q) ;
    errmsg = q.errmsg ;
  } ;
  return *this ;
} ;

fwrap_att::fwrap_att_error::~fwrap_att_error() throw() {} ;

const char* fwrap_att::fwrap_att_error::what() const throw() { 
  return errmsg.c_str() ; 
} ;

fwrap_att::fwrap_att_error fwrap_att::fwrap_att_error::notScalar(string stype, size_t psize) {
  ostringstream s ;
  s << stype << ": attribute is not a scalar, size = " << psize ;
  return fwrap_att_error(s.str()) ;
} ;

fwrap_att::fwrap_att_error fwrap_att::fwrap_att_error::badIndex(string stype, size_t psize, size_t ix) {
  ostringstream s ;
  s << stype << ": index out of range for attribute, size = " << psize << ", index = "<< ix ;
  return fwrap_att_error(s.str()) ;
} ;

fwrap_att::fwrap_att_error fwrap_att::fwrap_att_error::tooSmall(string stype, size_t psize, size_t asize)  {
  ostringstream s ;
  s << stype << ": argument array is too small for attribute, attribute size = " << psize << ", argument size = "<< asize ;
  return fwrap_att_error(s.str()) ;
} ;

// ------------ fwrap_int_att ---------------
fwrap_int_att::~fwrap_int_att() {
  delete[] ptr ;
} ;

fwrap_int_att::fwrap_int_att(int i) : fwrap_att(), psize(0), ptr(0) {
  ptr = new int[1] ;
  psize = 1 ;
  *ptr = i ;
}

fwrap_int_att::fwrap_int_att(const int* iptr, size_t isize) : fwrap_att(), psize(0), ptr(0) {
  ptr   = new int[isize] ;
  psize = isize ;
  int* p = ptr ;
  for (int i=0 ; i<isize ; i++) *p++=*iptr++ ;
}

fwrap_att::att_type fwrap_int_att::get_type() const { 
  return fwrap_att::itype ; 
} ;

fwrap_att::attInfo fwrap_int_att::get_info() const {
  return attInfo(fwrap_att::itype,psize) ;
} ;  
  
fwrap_att* fwrap_int_att::clone() const { 
  return new fwrap_int_att(ptr, psize) ; 
} ;

int fwrap_int_att::get_int() const { 
  if (psize!=1) throw fwrap_att::fwrap_att_error::notScalar("?fwrap_att_int::get_int()", psize) ;
  return *ptr ; 
} ;

void  fwrap_int_att::set_int(int i) { 
  if (psize!=1) {
    delete[] ptr ;
    ptr = new int[1] ;
    psize=1 ;
  }
  *ptr = i ; 
} ;

void fwrap_int_att::set_int(const int* iptr, size_t isize) { 
  if (psize!=isize) {
    delete[] ptr ;
    ptr = new int[isize] ;
    psize = isize ;
  }
  int* p = ptr ;
  for (int i=0 ; i<isize ; i++) *p++=*iptr++ ;
} ;

size_t fwrap_int_att::fill_int(int* iptr, size_t isize) const {
  if (isize<psize) throw fwrap_att::fwrap_att_error::tooSmall("?fwrap_att_int::getx_int()", psize, isize) ;
  int* p = ptr ;
  for (int i=0 ; i<psize ; i++) *iptr++=*p++ ;
  return psize ;
} ;

int fwrap_int_att::getx_int(size_t ix) const {
  if (ix>=psize) throw fwrap_att::fwrap_att_error::badIndex("?fwrap_att_int::getx_int()", psize, ix) ;
  return ptr[ix] ; 
} ;

void fwrap_int_att::setx_int(size_t ix, int i) {
  if (ix>=psize) throw fwrap_att::fwrap_att_error::badIndex("?fwrap_att_int::setx_int()", psize, ix) ;
  ptr[ix] = i ; 
} ;

ostream& fwrap_int_att::put(ostream& s) const {
  if (psize==1) {
    s << *ptr ;
  }
  else {
    s << '[' ;
    for (int i=0 ; i<psize ; i++) {
      if (i!=0) s<< ',' ;
      s << ptr[i] ;
      if (i!=(psize-1)) s<<' ' ;
    }
    s << ']' ;
  }
  return s ;
} ;

// ------------ fwrap_double_att ---------------

fwrap_double_att::~fwrap_double_att() {
  delete[] ptr ;
} ;

fwrap_double_att::fwrap_double_att(double i) : fwrap_att(), psize(0), ptr(0) {
  ptr = new double[1] ;
  psize = 1 ;
  *ptr = i ;
}

fwrap_double_att::fwrap_double_att(const double* iptr, size_t isize) : fwrap_att(), psize(0), ptr(0) {
  ptr   = new double[isize] ;
  psize = isize ;
  double* p = ptr ;
  for (int i=0 ; i<isize ; i++) *p++=*iptr++ ;
}

fwrap_att::att_type fwrap_double_att::get_type() const { 
  return fwrap_att::dtype ; 
} ;

fwrap_att::attInfo fwrap_double_att::get_info() const {
  return attInfo(fwrap_att::dtype,psize) ;
} ;  
  
fwrap_att* fwrap_double_att::clone() const { 
  return new fwrap_double_att(ptr, psize) ; 
} ;

double fwrap_double_att::get_double() const { 
  if (psize!=1) throw fwrap_att::fwrap_att_error::notScalar("?fwrap_att_double::get_double()", psize) ;
  return *ptr ; 
} ;

void  fwrap_double_att::set_double(double i) { 
  if (psize!=1) {
    delete[] ptr ;
    ptr = new double[1] ;
    psize=1 ;
  }
  *ptr = i ; 
} ;

void fwrap_double_att::set_double(const double* iptr, size_t isize) { 
  if (psize!=isize) {
    delete[] ptr ;
    ptr = new double[isize] ;
    psize = isize ;
  }
  double* p = ptr ;
  for (int i=0 ; i<isize ; i++) *p++=*iptr++ ;
} ;

size_t fwrap_double_att::fill_double(double* iptr, size_t isize) const {
  if (isize<psize) throw fwrap_att::fwrap_att_error::tooSmall("?fwrap_att_double::getx_double()", psize, isize) ;
  double* p = ptr ;
  for (int i=0 ; i<psize ; i++) *iptr++=*p++ ;
  return psize ;
} ;

double fwrap_double_att::getx_double(size_t ix) const {
  if (ix>=psize) throw fwrap_att::fwrap_att_error::badIndex("?fwrap_att_double::getx_double()", psize, ix) ;
  return ptr[ix] ; 
} ;

void fwrap_double_att::setx_double(size_t ix, double i) {
  if (ix>=psize) throw fwrap_att::fwrap_att_error::badIndex("?fwrap_att_double::setx_double()", psize, ix) ;
  ptr[ix] = i ; 
} ;

ostream& fwrap_double_att::put(ostream& s) const {
  if (psize==1) {
    s << *ptr ;
  }
  else {
    s << '[' ;
    for (int i=0 ; i<psize ; i++) {
      if (i!=0) s<< ',' ;
      s << ptr[i] ;
      if (i!=(psize-1)) s<<' ' ;
    }
    s << ']' ;
  }
  return s ;
} ;

// ------------ fwrap_string_att ----------------

fwrap_string_att::~fwrap_string_att() {
  delete[] ptr ;
} ;

fwrap_string_att::fwrap_string_att(string i) : fwrap_att(), psize(0), ptr(0) {
  ptr = new string[1] ;
  psize = 1 ;
  *ptr = i ;
}

fwrap_string_att::fwrap_string_att(const string* iptr, size_t isize) : fwrap_att(), psize(0), ptr(0) {
  ptr   = new string[isize] ;
  psize = isize ;
  string* p = ptr ;
  for (size_t i=0 ; i<isize ; i++) *p++=*iptr++ ;
}

fwrap_att::att_type fwrap_string_att::get_type() const { 
  return fwrap_att::stype ; 
} ;

fwrap_att::attInfo fwrap_string_att::get_info() const {
  return attInfo(fwrap_att::stype,psize) ;
} ;  

size_t  fwrap_string_att::get_maxLength() const {
  size_t kmax = 0 ;
  for (size_t i=0 ; i<psize ; i++) {
    size_t k = ptr[i].length() ;
    kmax = (k>kmax) ? k : kmax ;
  }
  return kmax ;
}
  
fwrap_att* fwrap_string_att::clone() const { 
  return new fwrap_string_att(ptr, psize) ; 
} ;

string fwrap_string_att::get_string() const { 
  if (psize!=1) throw fwrap_att::fwrap_att_error::notScalar("?fwrap_att_string::get_string()", psize) ;
  return *ptr ; 
} ;

void  fwrap_string_att::set_string(string i) { 
  if (psize!=1) {
    delete[] ptr ;
    ptr = new string[1] ;
    psize=1 ;
  }
  *ptr = i ; 
} ;

void fwrap_string_att::set_string(const string* iptr, size_t isize) { 
  if (psize!=isize) {
    delete[] ptr ;
    ptr = new string[isize] ;
    psize = isize ;
  }
  string* p = ptr ;
  for (int i=0 ; i<isize ; i++) *p++=*iptr++ ;
} ;

size_t fwrap_string_att::fill_string(string* iptr, size_t isize) const {
  if (isize<psize) throw fwrap_att::fwrap_att_error::tooSmall("?fwrap_att_string::getx_string()", psize, isize) ;
  string* p = ptr ;
  for (int i=0 ; i<psize ; i++) *iptr++=*p++ ;
  return psize ;
} ;

string fwrap_string_att::getx_string(size_t ix) const {
  if (ix>=psize) throw fwrap_att::fwrap_att_error::badIndex("?fwrap_att_string::getx_string()", psize, ix) ;
  return ptr[ix] ; 
} ;

void fwrap_string_att::setx_string(size_t ix, string i) {
  if (ix>=psize) throw fwrap_att::fwrap_att_error::badIndex("?fwrap_att_string::setx_string()", psize, ix) ;
  ptr[ix] = i ; 
} ;

ostream& fwrap_string_att::put(ostream& s) const {
  if (psize==1) {
    s << '\'' << *ptr << '\'' ;
  }
  else {
    s << '[' ;
    for (int i=0 ; i<psize ; i++) {
      if (i!=0) s<< ',' ;
      s << '\'' << ptr[i] << '\'' ;
      if (i!=(psize-1)) s<<' ' ;
    }
    s << ']' ;
  }
  return s ;
} ;

// ----------- frwap_map_att ------------
fwrap_map_att::fwrap_map_att() : atts() {
} ;

fwrap_map_att::~fwrap_map_att() {
  for ( map<string,fwrap_att*>::iterator p=atts.begin() ; p!=atts.end() ; ++p) {
    delete p->second ;
  } ;
} ;

fwrap_map_att::fwrap_map_att(const fwrap_map_att& t) : atts() {
  for ( map<string,fwrap_att*>::const_iterator p=t.atts.begin() ; p!=t.atts.end() ; ++p) {
    atts[p->first] = p->second->clone() ;
  } ; 
} ;

fwrap_map_att& fwrap_map_att::operator=(const fwrap_map_att& t) {
  if (&t != this) {
    clear() ;
    for ( map<string,fwrap_att*>::const_iterator p=t.atts.begin() ; p!=t.atts.end() ; ++p) {
      atts[p->first] = p->second->clone() ;
    } ; 
  }
  return *this ;
} ;

void fwrap_map_att::clear() {
  for ( map<string,fwrap_att*>::iterator p=atts.begin() ; p!=atts.end() ; ++p) {
    delete p->second ;
  } ;
  atts.clear() ;
} ;

list<string> fwrap_map_att::keys() const {
  list<string> s(0) ;
  for ( map<string,fwrap_att*>::const_iterator p=atts.begin() ; p!=atts.end() ; ++p) {
    s.push_back(p->first) ;
  } ;
  return s ;
} ;

fwrap_att* fwrap_map_att::get(string aname) {
  string name = fwrap_att::despace0(aname) ;
  map<string,fwrap_att*>::iterator p = atts.find(name) ;
  return p==atts.end() ? 0 : p->second ;
} ;  
  
const fwrap_att* fwrap_map_att::get(string aname) const {
  string name = fwrap_att::despace0(aname) ;
  map<string,fwrap_att*>::const_iterator p = atts.find(name) ;
  return p==atts.end() ? 0 : p->second ;
} ;   

void fwrap_map_att::set(string aname, int value) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att*     q = get(name) ;
  fwrap_int_att* p = q!=0 ? dynamic_cast<fwrap_int_att*>(q) : 0 ;

  if (p==0) {
    if (q!=0) remove(name) ;
    atts[name] = new fwrap_int_att(value) ;
  }
  else {
    p->set_int(value) ;
  } ;
} ;
   
void fwrap_map_att::set(string aname, double value) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att*        q = get(name) ;
  fwrap_double_att* p = q!=0 ? dynamic_cast<fwrap_double_att*>(q) : 0 ;

  if (p==0) {
    if (q!=0) remove(name) ;
    atts[name] = new fwrap_double_att(value) ;
  }
  else {
    p->set_double(value) ;
  } ;
};

void fwrap_map_att::set(string aname, string value) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att*        q = get(name) ;
  fwrap_string_att* p = q!=0 ? dynamic_cast<fwrap_string_att*>(q) : 0 ;

  if (p==0) {
    if (q!=0) remove(name) ;
    atts[name] = new fwrap_string_att(value) ;
  }
  else {
    p->set_string(value) ;
  } ;
} ;

void fwrap_map_att::remove(string aname) {
  string name = fwrap_att::despace0(aname) ;
  map<string,fwrap_att*>::iterator p = atts.find(name) ;
  if (p != atts.end()) {
    delete p->second ;
    atts.erase(p) ;
  } ;
} ;

int fwrap_map_att::get_int(string aname) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* p = get(name) ;
  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: unknown attribute called '")+name+"'") ;

  size_t psize = p->get_size() ;
  if (psize!=1) throw fwrap_map_att::fwrap_map_error::notScalar(name, "?fwrap_map_att::get_int()", psize) ; 

  const fwrap_int_att* q = dynamic_cast<const fwrap_int_att*>(p) ;
  if (q==0) throw fwrap_map_error(string("?fwrap_map_att: this attribute is not an integer, '")+name+"'") ;
  return q->get_int() ;
} ;          
  
double fwrap_map_att::get_double(string aname) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* p = get(name) ;
  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: unknown attribute called '")+name+"'") ;

  size_t psize = p->get_size() ;
  if (psize!=1) throw fwrap_map_att::fwrap_map_error::notScalar(name, "?fwrap_map_att::get_double()", psize) ; 

  const fwrap_double_att* q = dynamic_cast<const fwrap_double_att*>(p) ;
  if (q==0) throw fwrap_map_error(string("?fwrap_map_att: this attribute is not a double, '")+name+"'") ;
  return q->get_double() ;

}; 

string fwrap_map_att::get_string(string aname) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* p = get(name) ;
  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: unknown attribute called '")+name+"'") ;

  size_t psize = p->get_size() ;
  if (psize!=1) throw fwrap_map_att::fwrap_map_error::notScalar(name, "?fwrap_map_att::get_string()", psize) ; 

  const fwrap_string_att* q = dynamic_cast<const fwrap_string_att*>(p) ;
  if (q==0) throw fwrap_map_error(string("?fwrap_map_att: this attribute is not a string, '")+name+"'") ;
  return q->get_string() ;
}; 

int fwrap_map_att::get_int(string aname, int def) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* p = get(name) ;
  if (p==0) return def ;
  if (p->get_size()!=1) return def ;
  const fwrap_int_att* q = dynamic_cast<const fwrap_int_att*>(p) ;
  if (q==0) return def ;
  return q->get_int() ;
} ;          
  
double fwrap_map_att::get_double(string aname, double def) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* p = get(name) ;
  if (p==0) return def ;
  if (p->get_size()!=1) return def ;
  const fwrap_double_att* q = dynamic_cast<const fwrap_double_att*>(p) ;
  if (q==0) return def ;
  return q->get_double() ;

}; 

string fwrap_map_att::get_string(string aname, string def) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* p = get(name) ;
  if (p==0) return def ;
  if (p->get_size()!=1) return def ;
  const fwrap_string_att* q = dynamic_cast<const fwrap_string_att*>(p) ;
  if (q==0) return def ;
  return q->get_string() ;
}; 

void fwrap_map_att::set(string aname, const int* value, size_t vsize) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att* q = get(name) ;
  fwrap_int_att* p = q!=0 ? dynamic_cast<fwrap_int_att*>(q) : 0 ;

  if (p==0) {
    if (q!=0) remove(name) ;
    atts[name] = new fwrap_int_att(value,vsize) ;
  }
  else {
    p->set_int(value,vsize) ;
  } ;
} ;

void fwrap_map_att::set(string aname, const double* value, size_t vsize) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att* q = get(name) ;
  fwrap_double_att* p = q!=0 ? dynamic_cast<fwrap_double_att*>(q) : 0 ;

  if (p==0) {
    if (q!=0) remove(name) ;
    atts[name] = new fwrap_double_att(value,vsize) ;
  }
  else {
    p->set_double(value,vsize) ;
  } ;
} ;

void fwrap_map_att::set(string aname, const string* value, size_t vsize) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att* q = get(name) ;
  fwrap_string_att* p = q!=0 ? dynamic_cast<fwrap_string_att*>(q) : 0 ;

  if (p==0) {
    if (q!=0) remove(name) ;
    atts[name] = new fwrap_string_att(value,vsize) ;
  }
  else {
    p->set_string(value,vsize) ;
  } ;
} ;

void fwrap_map_att::setx(string aname, size_t ix, int value) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att* q = get(name) ;
  fwrap_int_att* p = q!=0 ? dynamic_cast<fwrap_int_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as an int attribute") ;

  size_t psize = p->get_size() ;
  if (ix>=psize) throw fwrap_map_att::fwrap_map_error::badIndex(name, "?fwrap_map_att::setx()", psize, ix) ;

  p->setx_int(ix,value) ;
} ;

void fwrap_map_att::setx(string aname, size_t ix, double value) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att* q = get(name) ;
  fwrap_double_att* p = q!=0 ? dynamic_cast<fwrap_double_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as a double attribute") ;

  size_t psize = p->get_size() ;
  if (ix>=psize) throw fwrap_map_att::fwrap_map_error::badIndex(name, "?fwrap_map_att::setx()", psize, ix) ;

  p->setx_double(ix,value) ;
} ;

void fwrap_map_att::setx(string aname, size_t ix, string value) {
  string name = fwrap_att::despace0(aname) ;
  fwrap_att* q = get(name) ;
  fwrap_string_att* p = q!=0 ? dynamic_cast<fwrap_string_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as a string attribute") ;

  size_t psize = p->get_size() ;
  if (ix>=psize) throw fwrap_map_att::fwrap_map_error::badIndex(name, "?fwrap_map_att::setx()", psize, ix) ;

  p->setx_string(ix,value) ;
} ;

int fwrap_map_att::getx_int(string aname, size_t ix) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_int_att* p = q!=0 ? dynamic_cast<const fwrap_int_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as an int attribute") ;

  size_t psize = p->get_size() ;
  if (ix>=psize) throw fwrap_map_att::fwrap_map_error::badIndex(name, "?fwrap_map_att::getx_int()", psize, ix) ;

  return p->getx_int(ix) ;
} ;          

double fwrap_map_att::getx_double(string aname, size_t ix) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_double_att* p = q!=0 ? dynamic_cast<const fwrap_double_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as a double attribute") ;

  size_t psize = p->get_size() ;
  if (ix>=psize) throw fwrap_map_att::fwrap_map_error::badIndex(name, "?fwrap_map_att::getx_double()", psize, ix) ;

  return p->getx_double(ix) ;
} ;          

string fwrap_map_att::getx_string(string aname, size_t ix) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_string_att* p = q!=0 ? dynamic_cast<const fwrap_string_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as a string attribute") ;

  size_t psize = p->get_size() ;
  if (ix>=psize) throw fwrap_map_att::fwrap_map_error::badIndex(name, "?fwrap_map_att::getx_string()", psize, ix) ;

  return p->getx_string(ix) ;
} ;          

size_t fwrap_map_att::fill(string aname, int* value, size_t vsize) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_int_att* p = q!=0 ? dynamic_cast<const fwrap_int_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as an int attribute") ;

  size_t psize = p->get_size() ;
  if (vsize<psize) throw fwrap_map_att::fwrap_map_error::tooSmall(name, "?fwrap_map_att::fill()", psize, vsize) ;

  return p->fill_int(value, vsize) ;
} ;

size_t fwrap_map_att::fill(string aname, double* value, size_t vsize) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_double_att* p = q!=0 ? dynamic_cast<const fwrap_double_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as a double attribute") ;

  size_t psize = p->get_size() ;
  if (vsize<psize) throw fwrap_map_att::fwrap_map_error::tooSmall(name, "?fwrap_map_att::fill()", psize, vsize) ;

  return p->fill_double(value, vsize) ;
} ;

size_t fwrap_map_att::fill(string aname, string* value, size_t vsize) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_string_att* p = q!=0 ? dynamic_cast<const fwrap_string_att*>(q) : 0 ;

  if (p==0) throw fwrap_map_error(string("?fwrap_map_att: attribute called '")+name+"' does not exist as a string attribute") ;

  size_t psize = p->get_size() ;
  if (vsize<psize) throw fwrap_map_att::fwrap_map_error::tooSmall(name, "?fwrap_map_att::fill()", psize, vsize) ;

  return p->fill_string(value, vsize) ;
} ;

size_t fwrap_map_att::fill(string aname, int* value, size_t vsize, const int* def, size_t dsize) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_int_att* p = q!=0 ? dynamic_cast<const fwrap_int_att*>(q) : 0 ;

  if (p!=0) {
    size_t psize = p->get_size() ;
    if (vsize>=psize) {
      return p->fill_int(value, vsize) ;
    }
  }
  // copy the default
  if (vsize<dsize) throw fwrap_map_att::fwrap_map_error(string("?fwrap_map_att::fill(): argument array with attribute '")+name+"' too small for default array") ;
  int* a = value ;
  const int* b = def ;
  for (int k=0 ; k<dsize ; k++) *a++=*b++ ;
  return dsize ;
} ;

size_t fwrap_map_att::fill(string aname, double* value, size_t vsize, const double* def, size_t dsize) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_double_att* p = q!=0 ? dynamic_cast<const fwrap_double_att*>(q) : 0 ;

  if (p!=0) {
    size_t psize = p->get_size() ;
    if (vsize>=psize) {
      return p->fill_double(value, vsize) ;
    }
  }
  // copy the default
  if (vsize<dsize) throw fwrap_map_att::fwrap_map_error(string("?fwrap_map_att::fill(): argument array with attribute '")+name+"' too small for default array") ;
  double* a = value ;
  const double* b = def ;
  for (int k=0 ; k<dsize ; k++) *a++=*b++ ;
  return dsize ;
} ;

size_t fwrap_map_att::fill(string aname, string* value, size_t vsize, const string* def, size_t dsize) const {
  string name = fwrap_att::despace0(aname) ;
  const fwrap_att* q = get(name) ;
  const fwrap_string_att* p = q!=0 ? dynamic_cast<const fwrap_string_att*>(q) : 0 ;

  if (p!=0) {
    size_t psize = p->get_size() ;
    if (vsize>=psize) {
      return p->fill_string(value, vsize) ;
    }
  }
  // copy the default
  if (vsize<dsize) throw fwrap_map_att::fwrap_map_error(string("?fwrap_map_att::fill(): argument array with attribute '")+name+"' too small for default array") ;
  string* a = value ;
  const string* b = def ;
  for (int k=0 ; k<dsize ; k++) *a++=*b++ ;
  return dsize ;
} ;

ostream& fwrap_map_att::write(ostream& s, string lead) const {
  for (map<string,fwrap_att*>::const_iterator p = atts.begin() ; p!=atts.end() ; ++p) {
    s << lead ;
    s.width(10) ; s.setf(ios_base::left,ios_base::adjustfield) ; s << p->first ;
    s.setf(ios_base::right,ios_base::adjustfield) ; s << " " ;
    s << *(p->second) << '\n' ;
  } ;
  return s ;
} ;    
   
ostream& operator<<(ostream& s, const fwrap_map_att& f) {
  return f.write(s,string("& ")) ;
} ;

fwrap_map_att::fwrap_map_error& fwrap_map_att::fwrap_map_error::operator=(const fwrap_map_att::fwrap_map_error& q) throw() {
  if (&q!=this) {
    std::exception::operator=(q) ;
    errmsg = q.errmsg ;
  } ;
  return *this ;
} ;

fwrap_map_att::fwrap_map_error::~fwrap_map_error() throw() {} ;

const char* fwrap_map_att::fwrap_map_error::what() const throw() { 
  return errmsg.c_str() ; 
} ;


fwrap_map_att::fwrap_map_error fwrap_map_att::fwrap_map_error::notScalar(string name, string stype, size_t psize) {
  ostringstream s ;
  s << stype << ": attribute '" << name << "' is not a scalar, size = " << psize ;
  return fwrap_map_error(s.str()) ;
} ;

fwrap_map_att::fwrap_map_error fwrap_map_att::fwrap_map_error::badIndex(string name, string stype, size_t psize, size_t ix) {
  ostringstream s ;
  s << stype << ": index out of range for attribute '" << name << "', size = " << psize << ", index = "<< ix ;
  return fwrap_map_error(s.str()) ;
} ;

fwrap_map_att::fwrap_map_error fwrap_map_att::fwrap_map_error::tooSmall(string name, string stype, size_t psize, size_t asize)  {
  ostringstream s ;
  s << stype << ": argument array is too small for attribute'" << name << "', map attribute size = " << psize << ", argument size = "<< asize ;
  return fwrap_map_error(s.str()) ;
} ;


// ----------- frwapPtrNull -------------
fwrapPtrNull& fwrapPtrNull::operator=(const fwrapPtrNull& q) throw() {
  if (&q!=this) std::exception::operator=(q) ;
  return *this ;
} ;

fwrapPtrNull::~fwrapPtrNull() throw() {} ;

const char* fwrapPtrNull::what()  const throw() { 
  return errmsg ; 
} ;

const char* fwrapPtrNull::errmsg="Attempt to dereference a null fwrapPtr" ;

// ----------- fwrapChar*** --------------
template<> Shape fwrapCharShape(const fwrap<cp_char>& f){
  size_t rank = f.rank();
  if (rank==0) return Shape() ;  // length 1, rank 0

  rank -= 1 ;
  Shape r(rank) ;
  for (size_t i=0 ; i<rank ; i++) r[i]=f.size(i+1) ;
  return r ;
}

template<> size_t fwrapCharLength(const fwrap<cp_char>& f) {
  size_t rank = f.rank() ;
  return rank>0 ? f.size(0) : 1 ;  // possibility of length 0 if the first dimension has zero size
}

template<> size_t fwrapCharMaxLength(const fwrap<cp_char>& f) {
  return fwrapCharLength(f) ;
} ;

template<> size_t fwrapCharMaxLength(const fwrap<string>& f) {
  size_t s = f.pstore() ;
  size_t m = 0 ;
  const string* p = f.fptr() ;
  for (size_t i=0 ; i<s ; i++) {
    size_t n = (p++)->size() ;
    m = n>m ? n : m ;
  }
  return m ;
} ;


//
// mimic fortran -> fortran character copy
//
template<> void fwrapCharCopy(const fwrap<cp_char>& f, fwrap<cp_char>& g, const Shape& s) {
  size_t flen, glen ;      // length of character strings

  const char* pf = f.fptr() ;
  char*       pg = g.fptr() ;

  bool ok = true ;         // index error flag

  if (f.rank()==0) {
    flen = 1 ;
  }
  else {
    if (f.rank()!=(s.size()+1)) TRANSP_THROW("?fwrapCharCopy: mismatched f rank and shape arguments") ;

    flen = f.size(0) ;

    const Shape& dim   = f.shape() ;
    const Shape& store = f.pshape() ;

    size_t i = f.rank()-1 ;   // dimension of char array being operated on, start from back
    size_t k = 0 ;            // accumulated offset

    while(ok&&i>0) {            
      ok = s[i-1]<dim[i] ;
      k += s[i-1] ;
      k *= store[--i] ;
    } ;
    pf += k ;
  }

  if (g.rank()==0) {
    glen = 1 ;
  }
  else {
    if (g.rank()!=(s.size()+1)) TRANSP_THROW("?fwrapCharCopy: mismatched g rank and shape arguments") ;

    glen = g.size(0) ;

    const Shape& dim   = g.shape() ;
    const Shape& store = g.pshape() ;

    size_t i = g.rank()-1 ;   // dimension of char array being operated on, start from back
    size_t k = 0 ;            // accumulated offset

    while(ok&&i>0) {            
      ok = s[i-1]<dim[i] ;
      k += s[i-1] ;
      k *= store[--i] ;
    } ;
    pg += k ;
  }

  if (!ok) TRANSP_THROW("?fwrapCharCopy: bad indexing into fwrap<char> arrays") ;

  size_t tlen = flen<glen ? flen : glen ;
  
  for (size_t i=0    ; i<tlen ; i++) *(pg++) = *(pf++) ;
  for (size_t i=tlen ; i<glen ; i++) *(pg++) = ' ' ;     // fill rest with spaces
}

//
// fortran -> c++ string,  respect zero termination in fortran string otherwise copy the whole thing
//
template<> void fwrapCharCopy(const fwrap<cp_char>& f, fwrap<string>& g, const Shape& s) {
  size_t flen ;

  const char* pf = f.fptr() ;

  bool ok = true ;         // index error flag

  if (f.rank()==0) {
    flen = 1 ;
  }
  else {
    if (f.rank()!=(s.size()+1)) TRANSP_THROW("?fwrapCharCopy: mismatched f rank and shape arguments") ;

    flen = f.size(0) ;

    const Shape& dim   = f.shape() ;
    const Shape& store = f.pshape() ;

    size_t i = f.rank()-1 ;   // dimension of char array being operated on, start from back
    size_t k = 0 ;            // accumulated offset

    while(ok&&i>0) {            
      ok = s[i-1]<dim[i] ;
      k += s[i-1] ;
      k *= store[--i] ;
    } ;
    pf += k ;
  }

  if (!ok) TRANSP_THROW("?fwrapCharCopy: bad indexing into fwrap<char> array") ;

  size_t tlen=0 ;                    // a 0 in the char[] string will terminate it
  for (size_t i=0 ; i<flen ; i++) {
    if (pf[tlen]==0) break ;
    tlen++ ;
  }

  g[s] = string(pf,tlen) ;
}

//
// c++ string --> fortran
//
template<> void fwrapCharCopy(const fwrap<string>& f, fwrap<cp_char>& g, const Shape& s) {
  size_t glen ;

  char* pg = g.fptr() ;

  bool ok = true ;         // index error flag

  const string& fs = f[s] ;

  size_t flen = fs.size() ;   // size of source string

  if (g.rank()==0) {
    glen = 1 ;
  }
  else {
    if (g.rank()!=(s.size()+1)) TRANSP_THROW("?fwrapCharCopy: mismatched g rank and shape arguments") ;

    glen = g.size(0) ;

    const Shape& dim   = g.shape() ;
    const Shape& store = g.pshape() ;

    size_t i = g.rank()-1 ;   // dimension of char array being operated on, start from back
    size_t k = 0 ;            // accumulated offset

    while(ok&&i>0) {            
      ok = s[i-1]<dim[i] ;
      k += s[i-1] ;
      k *= store[--i] ;
    } ;
    pg += k ;
  }

  if (!ok) TRANSP_THROW("?fwrapCharCopy: bad indexing into fwrap<char> array") ;

  size_t tlen = flen<glen ? flen : glen ;
  
  for (size_t i=0    ; i<tlen ; i++) *(pg++) = fs.at(i) ;
  for (size_t i=tlen ; i<glen ; i++) *(pg++) = ' ' ;     // fill rest with spaces
}

template<> ostream& operator<<(ostream& s, const fwrap<cp_char>& f) {
  // -- write rank and indices ---
  size_t rank = f.rank() ;
  s << "rank: " << rank << endl ;
  for (size_t i=0 ; i<rank ; i++) s << "dim[" << setw(2) << i << "]:   " << setw(6) << f.size(i) 
				    << "  " << setw(6) << f.pstore(i) << endl ;
  if (rank==0) {
    s.put('"') ; s.put(f()) ; s.put('"') ; s << endl ;
  }
  else {
    Shape loop(rank) ;     // initialize to zero -- represents loop index
#ifndef NO_GOT_VALARRAY
    loop = 0 ;
#else
    set_vector_int(loop,0) ;
#endif
    size_t k= f.size()>0 ? 0 : rank  ;   // dimension being incremented
    while(k<rank) {                      // terminate when try to increment nonexistent k=rank dimension
      // -- loop body --
      if (loop[0]==0) {
	for (size_t i=0 ; i<rank ; i++) s << setw(2) << loop[i] << "  " ; // indices
	s.put('"') ; s.put(f[loop]) ;
	if (f.size(0)==1) {
	  s.put('"') ; s << endl ;
	}
      }
      else if (loop[0]==(f.size(0)-1)) {
	s.put(f[loop]) ; s.put('"') ; s << endl ;
      }
      else {
	s.put(f[loop]) ;
      }

      // -- loop management --
      // increment loop index -- when hit the dimension limit
      // for dimension k, that dimension is set to zero and
      // the next dimension needs incrementing.  Store f.size(*)
      // in a Shape for time critical loops.
      //
      k = 0 ;  // start out incrementing smallest dimension
      while (k<rank && (++loop[k] >= f.size(k))) loop[k++]=0 ;
    } ;
  } ;
  
  if (f.att_size()>0) f.att()->write(s, string(" & ")) ;
  return s ;
} ;

template<> ostream& operator<<(ostream& s, const fwrap<Bytes>& f) {
  // -- write rank and indices ---
  size_t rank = f.rank() ;
  s << "rank: " << rank << endl ;
  for (size_t i=0 ; i<rank ; i++) s << "dim[" << setw(2) << i << "]:   " << setw(6) << f.size(i) 
				    << "  " << setw(6) << f.pstore(i) << endl ;
  if (rank==0) {
    const Bytes& v = f() ;
    s << "  " << " {" << v.size() << "} " ; s.put('"') ;

    for (size_t i=0 ; i<v.size() ; i++) s.put(v[i]) ;
    s.put('"') ; s << endl ;
  }
  else {
    Shape loop(rank) ;     // initialize to zero -- represents loop index
#ifndef NO_GOT_VALARRAY
    loop = 0 ;
#else
    set_vector_int(loop,0) ;
#endif
    size_t k= f.size()>0 ? 0 : rank  ;   // dimension being incremented
    while(k<rank) {                      // terminate when try to increment nonexistent k=rank dimension
      // -- loop body --
      for (size_t i=0 ; i<rank ; i++) s << setw(2) << loop[i] << "  " ; // indices
       
      const Bytes& v = f[loop] ;
      s << "  " << " {" << v.size() << "} " ; s.put('"') ;

      for (size_t i=0 ; i<v.size() ; i++) s.put(v[i]) ;
      s.put('"') ; s << endl ;
      
      // -- loop management --
      // increment loop index -- when hit the dimension limit
      // for dimension k, that dimension is set to zero and
      // the next dimension needs incrementing.  Store f.size(*)
      // in a Shape for time critical loops.
      //
      k = 0 ;  // start out incrementing smallest dimension
      while (k<rank && (++loop[k] >= f.size(k))) loop[k++]=0 ;
    } ;
  } ;
  
  if (f.att_size()>0) f.att()->write(s, string(" & ")) ;
  return s ;
} ;


//
// ---------- fwrap instantiate ----------
//template class fwrap<lp_32> ;   // same as ip_32
template class fwrap<ip_32> ;
template class fwrap<fp_64> ;
template class fwrap<fp_32> ;
template class fwrap<cp_char> ;

template class fwrap<bool> ;
template class fwrap<Bytes> ;
template class fwrap<string> ;

//template class fwrapPtr<lp_32> ;  // same as ip_32
template class fwrapPtr<ip_32> ;
template class fwrapPtr<fp_64> ;
template class fwrapPtr<fp_32> ;
template class fwrapPtr<cp_char> ;

template class fwrapPtr<bool> ;
template class fwrapPtr<Bytes> ;
template class fwrapPtr<string> ;

//template ostream& operator<<(ostream&, const fwrap<lp_32>&) ;  // same as ip_32
template ostream& operator<<(ostream&, const fwrap<ip_32>&) ;
template ostream& operator<<(ostream&, const fwrap<fp_64>&) ;
template ostream& operator<<(ostream&, const fwrap<fp_32>&) ;
template ostream& operator<<(ostream&, const fwrap<cp_char>&) ; 

template ostream& operator<<(ostream&, const fwrap<bool>&) ;
template ostream& operator<<(ostream&, const fwrap<Bytes>&) ;  
template ostream& operator<<(ostream&, const fwrap<string>&) ;


//
// ---------------- opaque C access -----------------
// these are raw unchecked operations, indexing as before as fortran starting from zero
//
extern "C" int   F77NAME(fw_ip32rank)(aip_32** self) {
  return static_cast<int>((*self)->rank()) ;
} ;                           

extern "C" void  F77NAME(fw_ip32shape)(aip_32** self, int* ishape) {
  aip_32* a = *self ;
  size_t r = a->rank() ;
  for (size_t i=0 ; i<r ; i++) ishape[i] = static_cast<int>(a->size(i)) ;
} ; 

extern "C" ip_32 F77NAME(cw_ip32get0)(aip_32** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" ip_32 F77NAME(cw_ip32get1)(aip_32** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i))) ; 
};
extern "C" ip_32 F77NAME(cw_ip32get2)(aip_32** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) ; 
};               
extern "C" ip_32 F77NAME(cw_ip32get3)(aip_32** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) ; 
};         
extern "C" ip_32 F77NAME(cw_ip32get4)(aip_32** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) ; 
};   
extern "C" void  F77NAME(cw_ip32set0)(aip_32** self, ip_32* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(cw_ip32set1)(aip_32** self, int* i, ip_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i))) = *v ;
} ;
extern "C" void  F77NAME(cw_ip32set2)(aip_32** self, int* i, int* j, ip_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) = *v  ;
} ;
extern "C" void  F77NAME(cw_ip32set3)(aip_32** self, int* i, int* j, int* k, ip_32* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) = *v ; 
} ;
extern "C" void  F77NAME(cw_ip32set4)(aip_32** self, int* i, int* j, int* k, int* m, ip_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) = *v ;
} ; 

extern "C" ip_32 F77NAME(fw_ip32get0)(aip_32** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" ip_32 F77NAME(fw_ip32get1)(aip_32** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1))) ; 
};
extern "C" ip_32 F77NAME(fw_ip32get2)(aip_32** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) ; 
};               
extern "C" ip_32 F77NAME(fw_ip32get3)(aip_32** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) ; 
};         
extern "C" ip_32 F77NAME(fw_ip32get4)(aip_32** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) ; 
};   
extern "C" void  F77NAME(fw_ip32set0)(aip_32** self, ip_32* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(fw_ip32set1)(aip_32** self, int* i, ip_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1))) = *v ;
} ;
extern "C" void  F77NAME(fw_ip32set2)(aip_32** self, int* i, int* j, ip_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) = *v  ;
} ;
extern "C" void  F77NAME(fw_ip32set3)(aip_32** self, int* i, int* j, int* k, ip_32* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) = *v ; 
} ;
extern "C" void  F77NAME(fw_ip32set4)(aip_32** self, int* i, int* j, int* k, int* m, ip_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) = *v ;
} ; 



extern "C" int   F77NAME(fw_fp32rank)(afp_32** self) {
  return static_cast<int>((*self)->rank()) ;
} ;                           

extern "C" void  F77NAME(fw_fp32shape)(afp_32** self, int* ishape) {
  afp_32* a = *self ;
  size_t  r = a->rank() ;
  for (size_t i=0 ; i<r ; i++) ishape[i] = static_cast<int>(a->size(i)) ;
} ; 

extern "C" fp_32 F77NAME(cw_fp32get0)(afp_32** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" fp_32 F77NAME(cw_fp32get1)(afp_32** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i))) ; 
};
extern "C" fp_32 F77NAME(cw_fp32get2)(afp_32** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) ; 
};               
extern "C" fp_32 F77NAME(cw_fp32get3)(afp_32** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) ; 
};         
extern "C" fp_32 F77NAME(cw_fp32get4)(afp_32** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) ; 
};   
extern "C" fp_32 F77NAME(cw_fp32get5)(afp_32** self, int* i, int* j, int* k, int* m, int* n) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m),static_cast<size_t>(*n))) ; 
};   
extern "C" void  F77NAME(cw_fp32set0)(afp_32** self, fp_32* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(cw_fp32set1)(afp_32** self, int* i, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i))) = *v ;
} ;
extern "C" void  F77NAME(cw_fp32set2)(afp_32** self, int* i, int* j, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) = *v  ;
} ;
extern "C" void  F77NAME(cw_fp32set3)(afp_32** self, int* i, int* j, int* k, fp_32* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) = *v ; 
} ;
extern "C" void  F77NAME(cw_fp32set4)(afp_32** self, int* i, int* j, int* k, int* m, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) = *v ;
} ; 
extern "C" void  F77NAME(cw_fp32set5)(afp_32** self, int* i, int* j, int* k, int* m, int* n, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m),static_cast<size_t>(*n))) = *v ;
} ; 

extern "C" fp_32 F77NAME(fw_fp32get0)(afp_32** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" fp_32 F77NAME(fw_fp32get1)(afp_32** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1))) ; 
};
extern "C" fp_32 F77NAME(fw_fp32get2)(afp_32** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) ; 
};               
extern "C" fp_32 F77NAME(fw_fp32get3)(afp_32** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) ; 
};         
extern "C" fp_32 F77NAME(fw_fp32get4)(afp_32** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) ; 
};   
extern "C" fp_32 F77NAME(fw_fp32get5)(afp_32** self, int* i, int* j, int* k, int* m, int* n) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1),static_cast<size_t>(*n-1))) ; 
};   
extern "C" void  F77NAME(fw_fp32set0)(afp_32** self, fp_32* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(fw_fp32set1)(afp_32** self, int* i, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1))) = *v ;
} ;
extern "C" void  F77NAME(fw_fp32set2)(afp_32** self, int* i, int* j, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) = *v  ;
} ;
extern "C" void  F77NAME(fw_fp32set3)(afp_32** self, int* i, int* j, int* k, fp_32* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) = *v ; 
} ;
extern "C" void  F77NAME(fw_fp32set4)(afp_32** self, int* i, int* j, int* k, int* m, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) = *v ;
} ; 
extern "C" void  F77NAME(fw_fp32set5)(afp_32** self, int* i, int* j, int* k, int* m, int* n, fp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1),static_cast<size_t>(*n-1))) = *v ;
} ; 



extern "C" int   F77NAME(fw_fp64rank)(afp_64** self) {
  return static_cast<int>((*self)->rank()) ;
} ;                           

extern "C" void  F77NAME(fw_fp64shape)(afp_64** self, int* ishape) {
  afp_64* a = *self ;
  size_t  r = a->rank() ;
  for (size_t i=0 ; i<r ; i++) ishape[i] = static_cast<int>(a->size(i)) ;
} ; 

extern "C" fp_64 F77NAME(cw_fp64get0)(afp_64** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" fp_64 F77NAME(cw_fp64get1)(afp_64** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i))) ; 
};
extern "C" fp_64 F77NAME(cw_fp64get2)(afp_64** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) ; 
};               
extern "C" fp_64 F77NAME(cw_fp64get3)(afp_64** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) ; 
};         
extern "C" fp_64 F77NAME(cw_fp64get4)(afp_64** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) ; 
};   
extern "C" fp_64 F77NAME(cw_fp64get5)(afp_64** self, int* i, int* j, int* k, int* m, int* n) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m),static_cast<size_t>(*n))) ; 
};   
extern "C" void  F77NAME(cw_fp64set0)(afp_64** self, fp_64* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(cw_fp64set1)(afp_64** self, int* i, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i))) = *v ;
} ;
extern "C" void  F77NAME(cw_fp64set2)(afp_64** self, int* i, int* j, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) = *v  ;
} ;
extern "C" void  F77NAME(cw_fp64set3)(afp_64** self, int* i, int* j, int* k, fp_64* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) = *v ; 
} ;
extern "C" void  F77NAME(cw_fp64set4)(afp_64** self, int* i, int* j, int* k, int* m, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) = *v ;
} ; 
extern "C" void  F77NAME(cw_fp64set5)(afp_64** self, int* i, int* j, int* k, int* m, int* n, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m),static_cast<size_t>(*n))) = *v ;
} ; 

extern "C" fp_64 F77NAME(fw_fp64get0)(afp_64** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" fp_64 F77NAME(fw_fp64get1)(afp_64** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1))) ; 
};
extern "C" fp_64 F77NAME(fw_fp64get2)(afp_64** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) ; 
};               
extern "C" fp_64 F77NAME(fw_fp64get3)(afp_64** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) ; 
};         
extern "C" fp_64 F77NAME(fw_fp64get4)(afp_64** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) ; 
};   
extern "C" fp_64 F77NAME(fw_fp64get5)(afp_64** self, int* i, int* j, int* k, int* m, int* n) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1),static_cast<size_t>(*n-1))) ; 
};   
extern "C" void  F77NAME(fw_fp64set0)(afp_64** self, fp_64* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(fw_fp64set1)(afp_64** self, int* i, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1))) = *v ;
} ;
extern "C" void  F77NAME(fw_fp64set2)(afp_64** self, int* i, int* j, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) = *v  ;
} ;
extern "C" void  F77NAME(fw_fp64set3)(afp_64** self, int* i, int* j, int* k, fp_64* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) = *v ; 
} ;
extern "C" void  F77NAME(fw_fp64set4)(afp_64** self, int* i, int* j, int* k, int* m, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) = *v ;
} ; 
extern "C" void  F77NAME(fw_fp64set5)(afp_64** self, int* i, int* j, int* k, int* m, int* n, fp_64* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1),static_cast<size_t>(*n-1))) = *v ;
} ; 



extern "C" int   F77NAME(fw_lp32rank)(alp_32** self) {
  return static_cast<int>((*self)->rank()) ;
} ;                           

extern "C" void  F77NAME(fw_lp32shape)(alp_32** self, int* ishape) {
  alp_32* a = *self ;
  size_t  r = a->rank() ;
  for (size_t i=0 ; i<r ; i++) ishape[i] = static_cast<int>(a->size(i)) ;
} ; 

extern "C" lp_32 F77NAME(cw_lp32get0)(alp_32** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" lp_32 F77NAME(cw_lp32get1)(alp_32** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i))) ; 
};
extern "C" lp_32 F77NAME(cw_lp32get2)(alp_32** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) ; 
};               
extern "C" lp_32 F77NAME(cw_lp32get3)(alp_32** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) ; 
};         
extern "C" lp_32 F77NAME(cw_lp32get4)(alp_32** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) ; 
};   
extern "C" void  F77NAME(cw_lp32set0)(alp_32** self, lp_32* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(cw_lp32set1)(alp_32** self, int* i, lp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i))) = *v ;
} ;
extern "C" void  F77NAME(cw_lp32set2)(alp_32** self, int* i, int* j, lp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j))) = *v  ;
} ;
extern "C" void  F77NAME(cw_lp32set3)(alp_32** self, int* i, int* j, int* k, lp_32* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k))) = *v ; 
} ;
extern "C" void  F77NAME(cw_lp32set4)(alp_32** self, int* i, int* j, int* k, int* m, lp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i),static_cast<size_t>(*j),static_cast<size_t>(*k),static_cast<size_t>(*m))) = *v ;
} ; 

extern "C" lp_32 F77NAME(fw_lp32get0)(alp_32** self) { 
  return ((*self)->operator()())        ; 
}; 
extern "C" lp_32 F77NAME(fw_lp32get1)(alp_32** self, int* i) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1))) ; 
};
extern "C" lp_32 F77NAME(fw_lp32get2)(alp_32** self, int* i, int* j) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) ; 
};               
extern "C" lp_32 F77NAME(fw_lp32get3)(alp_32** self, int* i, int* j, int* k) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) ; 
};         
extern "C" lp_32 F77NAME(fw_lp32get4)(alp_32** self, int* i, int* j, int* k, int* m) { 
  return ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) ; 
};   
extern "C" void  F77NAME(fw_lp32set0)(alp_32** self, lp_32* v) { 
  ((*self)->operator()()) = *v ;
} ;
extern "C" void  F77NAME(fw_lp32set1)(alp_32** self, int* i, lp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1))) = *v ;
} ;
extern "C" void  F77NAME(fw_lp32set2)(alp_32** self, int* i, int* j, lp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1))) = *v  ;
} ;
extern "C" void  F77NAME(fw_lp32set3)(alp_32** self, int* i, int* j, int* k, lp_32* v)  { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1))) = *v ; 
} ;
extern "C" void  F77NAME(fw_lp32set4)(alp_32** self, int* i, int* j, int* k, int* m, lp_32* v) { 
  ((*self)->operator()(static_cast<size_t>(*i-1),static_cast<size_t>(*j-1),static_cast<size_t>(*k-1),static_cast<size_t>(*m-1))) = *v ;
} ; 

extern "C" int   F77NAME(fw_charrank)(acp_char** self) {
  return static_cast<int>((*self)->rank()) ;
} 
                  
extern "C" void  F77NAME(fw_charshape)(acp_char** self, int* ishape) {
  acp_char* a = *self ;
  size_t r = a->rank() ;
  for (size_t i=0 ; i<r ; i++) ishape[i] = static_cast<int>(a->size(i)) ;
}

void fwrapCharCharCopy(size_t lsrc, const cp_char* src, size_t ldest, cp_char* dest) {
  size_t icp = lsrc>ldest ? ldest : lsrc ;
  const cp_char* s = src ;
  cp_char*       d = dest ;
  for (size_t i=0 ;   i<icp ;   i++) *d++=*s++ ;
  for (size_t i=icp ; i<ldest ; i++) *d++=' ';      // back fill with spaces
}

extern "C" void  F77NAME(cw_charget0)(acp_char** self, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->rank()>0 ? a->xsize(0) : 1 ;
  cp_char* src  = a->fptr() ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}

extern "C" void  F77NAME(cw_charget1)(acp_char** self, int* i, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(cw_charget2)(acp_char** self, int* i, int* j, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i), static_cast<size_t>(*j))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(cw_charget3)(acp_char** self, int* i, int* j, int* k, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i), static_cast<size_t>(*j), static_cast<size_t>(*k))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(cw_charget4)(acp_char** self, int* i, int* j, int* k, int*m, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i), static_cast<size_t>(*j), static_cast<size_t>(*k), static_cast<size_t>(*m))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(cw_charset0)(acp_char** self, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->rank()>0 ? a->xsize(0) : 1 ;
  cp_char* src  = a->fptr() ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(cw_charset1)(acp_char** self, int* i, const int* ilen, cp_char* c){
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(cw_charset2)(acp_char** self, int* i, int* j, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i), static_cast<size_t>(*j))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(cw_charset3)(acp_char** self, int* i, int* j, int* k, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i), static_cast<size_t>(*j), static_cast<size_t>(*k))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(cw_charset4)(acp_char** self, int* i, int* j, int* k, int* m, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i), static_cast<size_t>(*j), static_cast<size_t>(*k), static_cast<size_t>(*m))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(fw_charget0)(acp_char** self, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->rank()>0 ? a->xsize(0) : 1 ;
  cp_char* src  = a->fptr() ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(fw_charget1)(acp_char** self, int* i, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(fw_charget2)(acp_char** self, int* i, int* j, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1), static_cast<size_t>(*j-1))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(fw_charget3)(acp_char** self, int* i, int* j, int* k, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1), static_cast<size_t>(*j-1), static_cast<size_t>(*k-1))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(fw_charget4)(acp_char** self, int* i, int* j, int* k, int* m, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1), static_cast<size_t>(*j-1), static_cast<size_t>(*k-1), static_cast<size_t>(*m-1))) ;
  
  fwrapCharCharCopy(lsrc, src, static_cast<size_t>(*ilen), c) ;
}
extern "C" void  F77NAME(fw_charset0)(acp_char** self, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->rank()>0 ? a->xsize(0) : 1 ;
  cp_char* src  = a->fptr() ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(fw_charset1)(acp_char** self, int* i, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(fw_charset2)(acp_char** self, int* i, int* j, const int* ilen, cp_char* c){
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1), static_cast<size_t>(*j-1))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(fw_charset3)(acp_char** self, int* i, int* j, int* k, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1), static_cast<size_t>(*j-1), static_cast<size_t>(*k-1))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
extern "C" void  F77NAME(fw_charset4)(acp_char** self, int* i, int* j, int* k, int* m, const int* ilen, cp_char* c) {
  acp_char* a = *self ;
  
  size_t   lsrc = a->xsize(0) ;
  cp_char* src  = &(a->operator()(0, static_cast<size_t>(*i-1), static_cast<size_t>(*j-1), static_cast<size_t>(*k-1), static_cast<size_t>(*m-1))) ;
  
  fwrapCharCharCopy(static_cast<size_t>(*ilen), c, lsrc, src) ;
}
