From c1d8f01ee3e93811f1867c6679c2df65495aad5d Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Mon, 19 Jan 2015 16:51:21 +0100
Subject: [PATCH] z has become an Obj. Bug fixes for previous commit.

---
 pub/lib/dualplot.cpp |  4 +--
 pub/lib/dualplot.hpp |  4 +--
 pub/lib/edif.cpp     |  5 ++--
 pub/lib/expr.cpp     |  3 +++
 pub/lib/file_in.cpp  |  8 +++---
 pub/lib/file_out.cpp | 16 ++++++++----
 pub/lib/fit.cpp      |  2 +-
 pub/lib/import.cpp   | 13 +++++-----
 pub/lib/manip.cpp    | 61 +++++++++++++++++++++++++-------------------
 pub/lib/node.cpp     |  2 +-
 pub/lib/obj.cpp      | 12 ++++-----
 pub/lib/obj.hpp      | 30 ++++++++++++++--------
 pub/lib/olf.cpp      |  6 ++---
 pub/lib/olf.hpp      |  2 +-
 pub/lib/opr.cpp      | 20 +++++++--------
 pub/lib/plot.cpp     | 19 +++++++-------
 pub/lib/rssm.cpp     | 21 +++++++--------
 pub/lib/slice.cpp    | 29 ++++++++++++++-------
 pub/lib/slice.hpp    |  8 +++---
 pub/lib/special.cpp  |  5 ++--
 pub/test/oz.f2t      |  5 ++++
 21 files changed, 159 insertions(+), 116 deletions(-)
 create mode 100755 pub/test/oz.f2t

diff --git a/pub/lib/dualplot.cpp b/pub/lib/dualplot.cpp
index 47b1e594..9e06a683 100644
--- a/pub/lib/dualplot.cpp
+++ b/pub/lib/dualplot.cpp
@@ -183,7 +183,7 @@ void CPlot::plotFrame( const string& xlabel, const string& ylabel )
 void CPlot::addSpec( bool as_line, bool new_style, int style_no,
                      const vector<double>& xp,
                      const vector<double>& yp, const vector<double>& dyp,
-                     const vector<double>& z,
+                     const vector<string>& z,
                      const string& xco,
                      const string& yco,
                      const string& info
@@ -245,7 +245,7 @@ void CPlot::addSpec( bool as_line, bool new_style, int style_no,
         snprintf( outlin, mLin, "\n%3u [", ++ps_snum );
         ps_accu.push_back( outlin );
         for (int i=0; i<z.size(); i++){
-            snprintf( outlin, mLin, " %12g", z[i]);
+            snprintf( outlin, mLin, " %s", z[i].c_str() );
             ps_accu.push_back( outlin );
         }
         snprintf( outlin, mLin, " ] zValues\n" );
diff --git a/pub/lib/dualplot.hpp b/pub/lib/dualplot.hpp
index b05d4149..f1074940 100644
--- a/pub/lib/dualplot.hpp
+++ b/pub/lib/dualplot.hpp
@@ -33,7 +33,7 @@ class CPlot {
                   const vector<double>& xp,
                   const vector<double>& yp,
                   const vector<double>& dyp,
-                  const vector<double>& z,
+                  const vector<string>& z,
                   const string& xco,
                   const string& yco,
                   const string& info );
@@ -73,4 +73,4 @@ namespace NPloWin {
     extern int iPlot;            //!< Index of currently active plot window.
 
     void initialize();
-}
\ No newline at end of file
+}
diff --git a/pub/lib/edif.cpp b/pub/lib/edif.cpp
index ab330baf..ae38bea8 100644
--- a/pub/lib/edif.cpp
+++ b/pub/lib/edif.cpp
@@ -20,6 +20,7 @@
 #include "mem.hpp"
 #include "slice.hpp"
 #include "var.hpp"
+#include "obj.hpp"
 #include "edif.hpp"
 
 using boost::format;
@@ -100,8 +101,8 @@ void NEdif::showSpectra()
             for ( int j=0; j<f->nJ(); j++ ) {
                 printf( "%3u%c", j,
                         f->V[j]->frozen ? '/' : ' ' );
-                for ( double z: f->V[j]->z )
-                    printf( " %12.6g", z );
+                for ( RObj z: f->V[j]->z )
+                    printf( " %s", z->to_cc(12,12,6) );
                 printf( " %12.6g (%4u) %12.6g\n", 
                         fd->VS(j)->x[0], fd->nPts(j),
                         fd->VS(j)->x[fd->nPts(j)-1] );
diff --git a/pub/lib/expr.cpp b/pub/lib/expr.cpp
index 351147d5..0907105d 100644
--- a/pub/lib/expr.cpp
+++ b/pub/lib/expr.cpp
@@ -263,6 +263,9 @@ void CNode::tree_vec_val( vector<double> *ret, vector<double> *dret, int k, int
         if( dret && pr->has_err() )
             dret->assign( nret, pr->to_dr() );
 
+    } else if ( RObjVecInt pv = PCAST<const CObjVecInt>(val) ) {
+        for( int i=0; i<nret; ++i )
+            (*ret)[i] = pv->to_r(i);
     } else if ( RObjVecDbl pv = PCAST<const CObjVecDbl>(val) ) {
         *ret = pv->v;
         if( dret )
diff --git a/pub/lib/file_in.cpp b/pub/lib/file_in.cpp
index 8548cd4f..6d2924e3 100644
--- a/pub/lib/file_in.cpp
+++ b/pub/lib/file_in.cpp
@@ -215,12 +215,12 @@ void NFileIn::Load_08( ifstream& FS, string flong )
     for (int iTable = 0; iTable < (doc["Tables"].size()); iTable++) {
         if ( doc["Tables"][iTable].Type() != YAML::NodeType::Map )
             throw "Tables " + S(iTable) + " is not a MAP type";
-        vector<double> z;
+        vector<PObj> z;
         for(iz=0; iz<fout->ZCo.size(); ++iz ){
             doc["Tables"][iTable]["z" + S(iz)] >> val;
             if( !triv::any2dbl( val, &num ) )
                 throw "z" + S(iz) + ": invalid value " + val;
-            z.push_back( num );
+            z.push_back( PObjDbl( new CObjDbl( num ) ) );
         }
 
         if( isdata ) {
@@ -383,7 +383,7 @@ void NFileIn::LoadSpec_01( FILE *F_in, PSpec& sout, int nz )
     for ( i=0; i<nz; ++i ) {
         if ((err=fscanf(F_in, "%lg\n", &v))!=1)
             throw "expecting z value, found " + S(err) + " entries";
-        sout->z.push_back( v );
+        sout->z.push_back( PObjDbl( new CObjDbl( v ) ) );
     }
 
     // get xy values:
@@ -533,7 +533,7 @@ void NFileIn::Load_96( FILE *F_in, string flong )
         if ( triv::freadln(F_in, &lin)<0 ||
              sscanf( lin.c_str(), "%i %lg", &n, &r0 )!=2 )
             throw "no valid header in spectrum";
-        sout->z.push_back( r0 );
+        sout->z.push_back( PObjDbl( new CObjDbl( r0 ) ) );
 
         for( int i=0; i<n; ++i ){
             if ( !F_in || triv::freadln(F_in, &lin)<=0 )
diff --git a/pub/lib/file_out.cpp b/pub/lib/file_out.cpp
index c7179a11..aa474a78 100644
--- a/pub/lib/file_out.cpp
+++ b/pub/lib/file_out.cpp
@@ -16,6 +16,7 @@
 #include "defs.hpp"
 #include "olf.hpp"
 #include "mem.hpp"
+#include "obj.hpp"
 #include "slice.hpp"
 #include "file_out.hpp"
 
@@ -109,10 +110,17 @@ void NFileOut::save_y08( FILE *file, POlo f )
 
     for( int j=0; j<f->nJ(); j++ ){
         fprintf( file, "  - # table %i\n", j );
+        PSlice s = f->V[j];
+        for ( int i=0; i<f->nZ(); i++ ) {
+            if( PObjNum pz = PCAST<CObjNum>(s->z[i]) ) {
+                fprintf( file, "    z%i: %18.10g\n", i, pz->to_r() );
+                if( PObjNum pdz = PCAST<CObjEnu>(s->z[i]) )
+                    fprintf( file, "    dz%i: %18.10g\n", i, pdz->to_dr() );
+            } else
+                fprintf( file, "    z%i: %s\n", i, s->z[i]->to_cc() );
+        }
         if   ( fd ) {
             PSpec s = fd->VS(j);
-            for ( int i=0; i<f->nZ(); i++ ) 
-                fprintf( file, "    z%i: %18.10g\n", i, s->z[i] );
             if( s->dy.size() ) {
                 fprintf( file, "    xyd: |2 # %i entries\n", (int)s->size() );
                 for( int i=0; i<s->size(); i++ ) 
@@ -126,8 +134,6 @@ void NFileOut::save_y08( FILE *file, POlo f )
             }
         } else {
             PCurve s = fc->VC(j);
-            for ( int i=0; i<f->nZ(); i++ ) 
-                fprintf( file, "    z%i: %18.10g\n", i, s->z[i] );
             for ( int i=0; i<fc->nP; i++ ) 
                 fprintf( file, "    p%i: %18.10g\n", i, s->P[i] );
         }
@@ -163,7 +169,7 @@ void NFileOut::save_tab( FILE *file, POlo f )
     for( int j=0; j<f->nJ(); j++ ){
         for( int iz=0; iz<f->ZCo.size(); ++iz ){
             if( iz>0 )  fprintf( file, "\t" );
-            fprintf( file, "%g", fd->VS(j)->z[iz] );
+            fprintf( file, "%g", PCAST<CObjNum>(fd->VS(j)->z[iz])->to_r() );
         }
         fprintf( file, "\n" );
         for( int i=0; i<fd->VS(j)->size(); ++i ){
diff --git a/pub/lib/fit.cpp b/pub/lib/fit.cpp
index fdf837f0..2075ef00 100644
--- a/pub/lib/fit.cpp
+++ b/pub/lib/fit.cpp
@@ -183,7 +183,7 @@ void NCurveFit::fit( bool _allow_slow_conv )
             for ( int j=0; j<fc->nJ(); j++ ) {
                 RSpec ein = fd->VS(j);
                 PSpec eout = PSpec( new CSpec );
-                eout->copy_z_base( ein );
+                eout->z = ein->clone_z();
                 vector<double> range( ein->size() );
                 fc->range_T->tree_vec_val( &range, 0, fc->kd, j );
                 bool with_dy = ein->dy.size();
diff --git a/pub/lib/import.cpp b/pub/lib/import.cpp
index 2d773b3b..b4a289d1 100644
--- a/pub/lib/import.cpp
+++ b/pub/lib/import.cpp
@@ -18,6 +18,7 @@
 #include "defs.hpp"
 #include "olf.hpp"
 #include "mem.hpp"
+#include "obj.hpp"
 #include "slice.hpp"
 #include "import.hpp"
 
@@ -185,7 +186,7 @@ void NImport::readIn()
             break;
         }
         if (mInpZ<=2)
-            s->z.push_back(val);
+            s->z.push_back( PObjDbl( new CObjDbl(val) ) );
 
         switch(mInpX) {
         case 1:
@@ -224,13 +225,13 @@ void NImport::readIn()
                 }
                 if( mInpZ==3 ){
                     if( n==0 ){
-                        s->z.push_back(linv[imcz]);
+                        s->z.push_back( PObjDbl( new CObjDbl(linv[imcz]) ) );
                         zold = linv[imcz];
                     } else if( linv[imcz]!=zold ){
                         fout->V.push_back(s);
                         ns++;
                         s->z.clear();
-                        s->z.push_back(linv[imcz]);
+                        s->z.push_back( PObjDbl( new CObjDbl(linv[imcz]) ) );
                         zold = linv[imcz];
                     }
                 }
@@ -421,7 +422,7 @@ void NImport::readTab( string qualif )
                     s = PSpec( new CSpec );
                     s->z.resize( nz );
                     for( int iz=0; iz<nzdat; ++iz )
-                        s->z[iz] = zdat[iz];
+                        s->z[iz] = PObjDbl( new CObjDbl( zdat[iz] ) );
                 }
                 nline = 0;
                 ++nblock;
@@ -447,7 +448,7 @@ void NImport::readTab( string qualif )
                 s = PSpec( new CSpec );
                 s->z.resize( nz );
                 for( int iz=0; iz<nzdat; ++iz )
-                    s->z[iz] = zdat[iz];
+                    s->z[iz] = PObjDbl( new CObjDbl( zdat[iz] ) );
 // reactivate this in future z-y mode
 //                s->z[nz-1] = nline;
                 for( int i=0; i<dat.size(); ++i )
@@ -531,7 +532,7 @@ void NImport::makeGrid()
         s->y.clear();
         s->y.resize( ni, 0. );
 
-        if (nj>1) s->z.push_back( (double)j );
+        if (nj>1) s->z.push_back( PObjInt( new CObjInt(j) ) );
 
         fout->V.push_back(s);
     }
diff --git a/pub/lib/manip.cpp b/pub/lib/manip.cpp
index 0e01f968..021fd6cc 100644
--- a/pub/lib/manip.cpp
+++ b/pub/lib/manip.cpp
@@ -74,7 +74,7 @@ void NManip::PtsSelect( bool sel_del )
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
             pLis.evaluate( 0, sin->size()-1 );
             for ( int i=0; i<sin->size(); i++ ) {
                 if ( sel_del ^ pLis.contains(i) ) {
@@ -112,7 +112,7 @@ void NManip::PtsAvge()
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec() );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
 
             CList groups( sel, 0, sin->size()-1 );
             if ( !groups.size() )
@@ -162,7 +162,7 @@ void NManip::PtsAvgeFixed()
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec() );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
 
             if ( sin->size()<ng )
                 throw "not enough points in spectrum " + S(j);
@@ -209,7 +209,7 @@ void NManip::PtsAvgeByErr( const string& subcmd )
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec() );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
             if ( !sin->dy.size() )
                 throw "no errors available";
             double xg = 0, yg = 0, vg = 0;
@@ -266,7 +266,7 @@ void NManip::PtsSort()
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
 
             n = sin->size();
             vector<double> v(n);
@@ -299,7 +299,7 @@ void NManip::PtsAvgeEq(void)
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
 
             int n = sin->size();
             int ii=0;
@@ -348,7 +348,7 @@ void NManip::PtsSymmetrize()
         for (int j=0; j<fin->nJ(); j++) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
             if ( !triv::is_ascending( sin->x ) )
                 throw "not ascending";
             double step;
@@ -404,10 +404,10 @@ void NManip::ScaRemoveConstantZ( POlo fio )
         int nj = fio->nJ();
         if ( nj<1 )
             throw "file contains no spectrum";
-        double z = fio->z(0,iz);
+        double z = fio->z(0,iz)->to_r();
         bool z_is_const = true;
         for ( int j=1; j<nj; ++j ) {
-            if ( fio->z(j,iz) != z ) {
+            if ( fio->z(j,iz)->to_r() != z ) {
                 z_is_const = false;
             }
         }
@@ -469,7 +469,10 @@ void NManip::ScaAvge()
                 int mz = 0;
                 double z = 0;
                 for ( int jj=ji; jj<jf; jj++ ) {
-                    z += fin->z(jj,iz);
+                    auto pz = PCAST<CObjNum>(fin->z(jj,iz));
+                    if( !pz )
+                        throw "z"+S(iz)+" is not a number";
+                    z += pz->to_r();
                     ++mz;
                 }
                 zout[iz] = z/mz;
@@ -506,7 +509,8 @@ void NManip::ScaAvge()
                     if ( with_dy )
                         sout->dy[i] = mj==0 ? 0 : sqrt(vm)/mj;
                 }
-                sout->z = zout;
+                for ( int iz=0; iz<nz; ++iz )
+                    sout->z[iz] = PObjDbl( new CObjDbl(zout[iz]) );
                 fout->V.push_back( sout );
             } else if ( fc ) {
                 PCurve cout( new CCurve );
@@ -522,7 +526,8 @@ void NManip::ScaAvge()
                     p[ip] = mj==0 ? 0 : pm/mj;
                 }
                 cout->P = p;
-                cout->z = zout;
+                for ( int iz=0; iz<nz; ++iz )
+                    cout->z[iz] = PObjDbl( new CObjDbl(zout[iz]) );
                 cout->fixed.resize( np, false );
                 fout->V.push_back( cout );
             }
@@ -589,7 +594,7 @@ void NManip::ScaSpawn()
         for ( int jj=0; jj<njj; ++jj ) {
             for ( int j=0; j<fin->nJ(); j++ ) {
                 PSlice eout = fin->new_slice( j );
-                eout->z.insert( eout->z.begin(), jj );
+                eout->z.insert( eout->z.begin(), PObjInt( new CObjInt( jj ) ) );
                 fout->V.push_back( eout );
             }
         }
@@ -624,11 +629,11 @@ void NManip::ScaExch()
         for ( ji=0; ji<fin->nJ(); ) {
             zcommon.clear();
             for ( int i=0; i<izco; ++i)
-                zcommon.push_back(fin->V[ji]->z[i]);
+                zcommon.push_back(fin->V[ji]->z[i]->to_r());
 
             for ( jf=ji+1; jf<fin->nJ(); jf++ )
                 for ( int i=0; i<izco; ++i)
-                    if (fin->V[jf]->z[i] != zcommon[i])
+                    if (fin->V[jf]->z[i]->to_r() != zcommon[i])
                         goto end_group;
         end_group:
 
@@ -646,9 +651,10 @@ void NManip::ScaExch()
             int ii = 0; // a guess
             for ( int i=0; i<xcommon.size(); ++i ) {
                 PSpec sout( new CSpec );
-                
-                sout->z = zcommon;
-                sout->z.push_back(xcommon[i]);
+
+                for( double z: zcommon )
+                    sout->z.push_back( PObjDbl( new CObjDbl(z) ) );
+                sout->z.push_back( PObjDbl( new CObjDbl(xcommon[i]) ) );
 
                 for ( int j=ji; j<jf; ++j ) {
                     PSpec sin = fin->VS( j );
@@ -660,9 +666,9 @@ void NManip::ScaExch()
                     }
                     if ( ii<sin->size() ) {
                         if ( with_dy )
-                            sout->push_xyd( sin->z[izco], sin->y[ii], sin->dy[ii] );
+                            sout->push_xyd( sin->z[izco]->to_r(), sin->y[ii], sin->dy[ii] );
                         else
-                            sout->push_xy( sin->z[izco], sin->y[ii] );
+                            sout->push_xy( sin->z[izco]->to_r(), sin->y[ii] );
                     }
                 }
                 fout->V.push_back( sout );
@@ -848,7 +854,10 @@ void NManip::ZDelete()
             fout->ZCo.erase( fout->ZCo.begin()+iz );
             double zval = 0;
             for ( int j=0; j<fin->nJ(); j++ ) {
-                zval += fout->V[j]->z[iz];
+                auto pz = PCAST<CObjNum>(fin->z(j,iz));
+                if( !pz )
+                    throw "z"+S(iz)+" is not a number";
+                zval += pz->to_r();
                 fout->V[j]->z.erase( fout->V[j]->z.begin()+iz );
             }
             fout->RPar[nRPar].val = zval / fin->nJ();
@@ -877,13 +886,13 @@ void NManip::ScaBreak()
 
         for ( int j=0; j<fin->nJ(); ) {
             POlo fout( ftmp->new_olo() );
-            double zval = ftmp->z(j,0);
+            double zval = ftmp->z(j,0)->to_r();
             fout->RPar.push_back( CParam( zco, zval ) );
             do {
                 PSlice eout( fin->new_slice(j) );
                 eout->z.erase( eout->z.begin() );
                 fout->V.push_back( eout );
-            } while ( ++j<fin->nJ() && fin->z(j,0)==zval );
+            } while ( ++j<fin->nJ() && fin->z(j,0)->to_r()==zval );
             fout->name += "_" + S(jout++);
             NOlm::mem_store( fout );
         }
@@ -1036,9 +1045,9 @@ void NManip::FilMerge( const string& opts )
             auto zinsert=eout->z.begin();
             for ( int i=0; i<nR; ++i )
                 if ( RParDiff[i] )
-                    eout->z.insert( zinsert++, fin->RPar[i].val );
+                    eout->z.insert( zinsert++, PObjDbl( new CObjDbl( fin->RPar[i].val ) ) );
             if ( add_zk )
-                eout->z.insert( eout->z.begin(), fiter.iteration() );
+                eout->z.insert( eout->z.begin(), PObjInt( new CObjInt( fiter.iteration() ) ) );
             fout->V.push_back( eout );
         }
     }
@@ -1206,7 +1215,7 @@ void NManip::HistoMake()
         for ( int j=0; j<fin->nJ(); j++ ) {
             RSpec sin = fin->VS(j);
             PSpec sout( new CSpec() );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
             sout->x = xout;
             sout->y = vector<double>(nbin, 0.);
             for ( int i=0; i<sin->size(); ++i ) {
diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp
index 38d93bf6..d256d99a 100644
--- a/pub/lib/node.cpp
+++ b/pub/lib/node.cpp
@@ -602,7 +602,7 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
             if ( var->num>= f->nZ() )
                 throw string("invalid reference ") + var->var_info();
             int j = ref->get_j( ctx, f->nJ() );
-            return RObjDbl( new CObjDbl( f->V[j]->z[var->num] ) ); // TODO: z -> Enu
+            return f->V[j]->z[var->num];
         }
 
         // References for data file
diff --git a/pub/lib/obj.cpp b/pub/lib/obj.cpp
index 3f0531b9..7fef8b49 100644
--- a/pub/lib/obj.cpp
+++ b/pub/lib/obj.cpp
@@ -29,7 +29,7 @@ PObj CObj::objectify( string val ) { return PObjStr( new CObjStr(val) ); }
 
 //! Returns string representation.
 
-string CObjInt::to_s() const
+string CObjInt::to_s( int maxlen, int minlen, int prec ) const
 {
     return S(val);
 }
@@ -41,7 +41,7 @@ string CObjInt::to_s() const
 
 //! Returns string representation.
 
-string CObjDbl::to_s() const
+string CObjDbl::to_s( int maxlen, int minlen, int prec ) const
 {
     return S(val);
 }
@@ -63,7 +63,7 @@ string CObjDbl::result_info() const
 
 //! Returns string representation.
 
-string CObjEnu::to_s() const
+string CObjEnu::to_s( int maxlen, int minlen, int prec ) const
 {
     return S(val) + "+-" + S(err);
 }
@@ -86,7 +86,7 @@ string CObjEnu::result_info() const
 
 //! Returns string representation.
 
-string CObjVecInt::to_s() const
+string CObjVecInt::to_s( int maxlen, int minlen, int prec ) const
 {
     return "["+S(size())+" integer entries]";
 }
@@ -105,7 +105,7 @@ string CObjVecInt::result_info() const
 
 //! Returns string representation.
 
-string CObjVecDbl::to_s() const
+string CObjVecDbl::to_s( int maxlen, int minlen, int prec ) const
 {
     return "["+S(size())+" floating-point entries]";
 }
@@ -124,7 +124,7 @@ string CObjVecDbl::result_info() const
 
 //! Returns string representation.
 
-string CObjVecEnu::to_s() const
+string CObjVecEnu::to_s( int maxlen, int minlen, int prec ) const
 {
     return "["+S(size())+" floating-point entries with errors]";
 }
diff --git a/pub/lib/obj.hpp b/pub/lib/obj.hpp
index d2b6d580..f7940664 100644
--- a/pub/lib/obj.hpp
+++ b/pub/lib/obj.hpp
@@ -11,8 +11,8 @@
 
 class CObj {
  public:
-    virtual ~CObj() {};
-
+    virtual ~CObj() {}
+    virtual PObj clone() const =0;
     virtual bool is_vec() const =0;
     virtual bool has_err() const =0;
     virtual char base_type() const =0;
@@ -24,7 +24,9 @@ class CObj {
     virtual double to_r() const { throw "to_r() not available"; };
     virtual double to_dr() const { throw "to_dr() not available"; };
     virtual bool to_b() const =0;
-    virtual string to_s() const =0;
+    const char* to_cc( int maxlen=12, int minlen=1, int prec=6 ) const
+        { return to_s( maxlen, minlen, prec ).c_str(); };
+    virtual string to_s( int maxlen=12, int minlen=1, int prec=6 ) const =0;
     virtual int size() const { return 1; }
 
     static PObj objectify( int val );
@@ -46,8 +48,10 @@ class CObjNum : public CObj {
 
 class CObjInt : public CObjNum {
  public:
+    
     int val;         //!< Scalar value.
     CObjInt( int _val ) : CObjNum(), val(_val) {};
+    PObj clone() const { return PObjInt( new CObjInt( *this ) ); };
     bool has_err() const { return false; };
     char base_type() const { return 'i'; };
     string result_info() const { return "CObjInt("+S(val)+")"; };
@@ -56,7 +60,7 @@ class CObjInt : public CObjNum {
     double to_dr( int i ) const { return 0. ; };
     int to_i() const { return val; };
     double to_r() const { return val; };
-    string to_s() const;
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const;
     bool to_b() const { return val; };
 };
 
@@ -66,13 +70,14 @@ class CObjDbl : public CObjNum {
  public:
     double val;         //!< Scalar value.
     CObjDbl( double _val=NAN ) : CObjNum(), val(_val) {};
+    PObj clone() const { return PObjDbl( new CObjDbl( *this ) ); };
     bool has_err() const { return false; };
     char base_type() const { return 'd'; };
     string result_info() const;
     double to_r( int i ) const { return val; };
     double to_dr( int i ) const { return 0.; } ;
     double to_r() const { return val; };
-    string to_s() const;
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const;
     bool to_b() const { return val; };
 };
 
@@ -83,6 +88,7 @@ class CObjEnu : public CObjDbl {
  public:
     double err;         //!< Error of scalar value.
     CObjEnu( double _val=NAN, double _err=NAN ) : CObjDbl(_val), err(_err) {};
+    PObj clone() const { return PObjEnu( new CObjEnu( *this ) ); };
     bool has_err() const { return true; };
     char base_type() const { return 'e'; };
     string result_info() const;
@@ -90,7 +96,7 @@ class CObjEnu : public CObjDbl {
     double to_dr( int i ) const { return err; } ;
     double to_r() const { return val; };
     double to_dr() const { return err; } ;
-    string to_s() const;
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const;
     bool to_b() const { return val; };
 };
 
@@ -100,11 +106,12 @@ class CObjStr : public CObj {
  public:
     string val;
     CObjStr( string _val ) : CObj(), val(_val) {};
+    PObj clone() const { return PObjStr( new CObjStr( *this ) ); };
     bool is_vec() const { return false; };
     bool has_err() const { return false; };
     char base_type() const { return 's'; };
     string result_info() const { return "CObjStr("+val+")"; };
-    string to_s() const { return val; };
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const { return val; };
     bool to_b() const { return val.size(); };
     int size() const { return val.size(); };
 };
@@ -133,12 +140,13 @@ class CObjVecInt : public CObjVecNum {
     vector<int> v;  //!< The data.
     CObjVecInt( int n=0 ) : CObjVecNum(), v(n,-1) {};
     CObjVecInt( const vector<int>& _v ) : CObjVecNum(), v(_v) {};
+    PObj clone() const { return PObjVecInt( new CObjVecInt( *this ) ); };
     bool has_err() const { return false; };
     char base_type() const { return 'i'; };
     string result_info() const;
     int to_i( int i ) const { return v[i]; };
     double to_r( int i ) const { return v[i]; };
-    string to_s() const;
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const;
     bool to_b() const { return v.size(); };
     int size() const { return v.size(); };
 };
@@ -150,11 +158,12 @@ class CObjVecDbl : public CObjVecNum {
     vector<double> v;  //!< Resulting vector.
     CObjVecDbl( int n=0 ) : CObjVecNum(), v(n,NAN) {};
     CObjVecDbl( const vector<double>& _v ) : CObjVecNum(), v(_v) {};
+    PObj clone() const { return PObjVecDbl( new CObjVecDbl( *this ) ); };
     bool has_err() const { return false; };
     char base_type() const { return 'd'; };
     string result_info() const;
     double to_r( int i ) const { return v[i]; };
-    string to_s() const;
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const;
     bool to_b() const { return v.size(); };
     int size() const { return v.size(); };
 };
@@ -166,11 +175,12 @@ class CObjVecEnu : public CObjVecDbl {
     vector<double> dv; //!< Errors.
     CObjVecEnu( int n=0 ) : CObjVecDbl( n ), dv(n,NAN) {};
     CObjVecEnu( const vector<double>& _v, const vector<double>& _dv ) : CObjVecDbl(_v), dv(_dv) {};
+    PObj clone() const { return PObjVecEnu( new CObjVecEnu( *this ) ); };
     bool has_err() const { return true; };
     char base_type() const { return 'e'; };
     string result_info() const;
     double to_dr( int i ) const { return dv[i]; } ;
-    string to_s() const;
+    string to_s( int maxlen=12, int minlen=1, int prec=6 ) const;
     bool to_b() const { return v.size(); };
     int size() const { return v.size(); };
 };
diff --git a/pub/lib/olf.cpp b/pub/lib/olf.cpp
index 91596283..630e28ce 100644
--- a/pub/lib/olf.cpp
+++ b/pub/lib/olf.cpp
@@ -55,7 +55,7 @@ string COlo::infoLine( int j ) const
 
 //! Return value of iz-th z-variable for slice j.
 
-double COlo::z( int j, int iz ) const
+PObj COlo::z( int j, int iz ) const
 {
     return V[j]->z[iz];
 }
@@ -375,7 +375,7 @@ void COlc::curve_val_vec_expr( vector<double>* v, vector<double>* dv,
                     (*dv)[i] = pr->to_dr();
             }
         } else
-            throw "BUG: tree_curve_val did not get scalar result";
+            throw "BUG: val_curve_vec_expr did not get scalar result";
     } else {
         ctx.request_VT( &vt );
         val = T->tree_val( ctx );
@@ -384,7 +384,7 @@ void COlc::curve_val_vec_expr( vector<double>* v, vector<double>* dv,
             if( dv )
                 *dv = PCAST<const CObjVecEnu>(val)->dv;
         } else
-            throw "BUG: tree_curve_val did not get vectorial result";
+            throw "BUG: curve_val_vec_expr did not get vectorial result";
     }
 }
 
diff --git a/pub/lib/olf.hpp b/pub/lib/olf.hpp
index ce3d1f30..187f9606 100644
--- a/pub/lib/olf.hpp
+++ b/pub/lib/olf.hpp
@@ -38,7 +38,7 @@ class COlo {
 
     int nJ() const { return V.size(); }
     int nZ() const { return ZCo.size(); }
-    double z( int j, int iz ) const;
+    PObj z( int j, int iz ) const;
     virtual PSlice new_slice( int j ) const = 0;
     virtual POlo new_olo( bool modified=true ) const = 0;
     virtual CCoord coord( class CVar* var ) const = 0;
diff --git a/pub/lib/opr.cpp b/pub/lib/opr.cpp
index b46fde24..3be21991 100644
--- a/pub/lib/opr.cpp
+++ b/pub/lib/opr.cpp
@@ -114,7 +114,7 @@ void NOperate::select( bool sel_del )
             if ( fd ) {
                 PSpec ein = fd->VS(j);
                 PSpec eout = PSpec( new CSpec );
-                eout->copy_z_base( ein );
+                eout->z = ein->clone_z();
                 vector<double> lvec( ein->size() );
                 T->tree_vec_val( &lvec, 0, fiter.k(), j );
                 bool with_dy = ein->dy.size();
@@ -234,11 +234,11 @@ void NOperate::Pointwise( string llabel )
                     } else
                         throw "BUG: unexpected lref";
                 } else if ( lref.typ==CVar::_Z ) {
-                    double val = T->tree_point_val( k, j )->to_r();
+                    PObj pret = T->tree_point_val( k, j )->clone();
                     if ( lref.num==-1 )
-                        fout->V[j]->z.push_back( val );
+                        fout->V[j]->z.push_back( pret );
                     else
-                        fout->V[j]->z[lref.num] = val;
+                        fout->V[j]->z[lref.num] = pret;
                 } else if ( lref.typ==CVar::_CP ) {
                     (P2C(fout))->VC(j)->P[lref.num] = T->tree_point_val( k, j )->to_r();
                 } else {
@@ -280,7 +280,7 @@ void NOperate::Integral(void)
             fout->xco = fin->ZCo.back();
             T->set_coord( fout->yco, k );
             sout = PSpec( new CSpec );
-            sout->z = fin->V[0]->z;
+            sout->z = fin->V[0]->clone_z();
             sout->z.pop_back();
         }
 
@@ -291,14 +291,14 @@ void NOperate::Integral(void)
                 cout << "result: " << res->to_s() << "\n";
                 continue;
             }
-            xval = fin->V[j]->z[nz-1];
+            xval = fin->V[j]->z[nz-1]->to_r();
             sout->push_xyd( xval, res->to_r(), res->to_dr() );
             if (nz>=2) { // new spectrum if jump in other z values
-                zval = fin->V[j]->z[nz-2];
-                if ( j+1 < fin->nJ() && fin->V[j+1]->z[nz-2] != zval ) {
+                zval = fin->V[j]->z[nz-2]->to_r();
+                if ( j+1 < fin->nJ() && fin->V[j+1]->z[nz-2]->to_r() != zval ) {
                     fout->V.push_back( sout );
                     sout = PSpec( new CSpec );
-                    sout->z = fin->V[j+1]->z;
+                    sout->z = fin->V[j+1]->clone_z();
                     sout->z.pop_back();
                 }
             }
@@ -413,7 +413,7 @@ void NOperate::Functional( const string& subcmd )
         for ( int j=0; j<fin->nJ(); j++ ) {
             PSpec sin = fin->VS(j);
             PSpec sout( new CSpec );
-            sout->copy_z_base( sin );
+            sout->z = sin->clone_z();
             int n = sin->size();
 
             if        ( subcmd=="i" ) { // integrate
diff --git a/pub/lib/plot.cpp b/pub/lib/plot.cpp
index a42ec968..9c84affb 100644
--- a/pub/lib/plot.cpp
+++ b/pub/lib/plot.cpp
@@ -169,10 +169,9 @@ int plot_data( CPlot* plot, POld fd, int k, int j, int pstyle )
         if ( nyh )
             cout << "  " << nyh << " points > ymax\n";
     } else {
-        plot->addSpec(
-            false, true, pstyle, xp, yp, dyp, fd->V[j]->z,
-            fd->xco.str_std(), fd->yco.str_std(),
-            "data file " + S(k) + " spectrum "+S(j) );
+        plot->addSpec( false, true, pstyle, xp, yp, dyp, fd->V[j]->z_str(),
+                       fd->xco.str_std(), fd->yco.str_std(),
+                       "data file " + S(k) + " spectrum "+S(j) );
     }
     return np;
 }
@@ -205,7 +204,7 @@ int plot_curve_convolved( CPlot* plot, POlc fc, int k, int j, int cstyle )
         cout << "curve k="<<S(k)<<", j="<<S(j)<<
             " has no points in plot window\n";
     }
-    plot->addSpec( true, true, cstyle, xo, yo, novec, fc->V[j]->z,
+    plot->addSpec( true, true, cstyle, xo, yo, novec, fc->V[j]->z_str(),
                    fc->xco.str_std(), fc->yco.str_std(),
                    "curve file "+S(k)+" spectrum "+S(j) );
     return xo.size();
@@ -231,7 +230,7 @@ int plot_curve_to_grid( CPlot* plot, POlc fc, int k, int j, int cstyle )
             yp.push_back( yc[i] );
         }
     }
-    plot->addSpec( true, true, cstyle, xp, yp, novec, fc->V[j]->z,
+    plot->addSpec( true, true, cstyle, xp, yp, novec, fc->V[j]->z_str(),
                    fc->xco.str_std(), fc->yco.str_std(),
                    "curve file "+S(k)+" spectrum "+S(j) );
     return xp.size();
@@ -255,7 +254,7 @@ int plot_curve_equidist( CPlot* plot, POlc fc, int k, int j, int cstyle )
             yp.push_back( yc[i] );
         }
     }
-    plot->addSpec( true, true, cstyle, xp, yp, novec, fc->V[j]->z,
+    plot->addSpec( true, true, cstyle, xp, yp, novec, fc->V[j]->z_str(),
                    fc->xco.str_std(), fc->yco.str_std(),
                    "curve file "+S(k)+" spectrum "+S(j) );
     return xp.size();
@@ -408,8 +407,8 @@ int plot_curve_refine( CPlot* plot, POlc fc, int k, int j, int cstyle )
             if ( xa.size() ){
                 // cout << "DEB segment -> " << xa.size() << "\n";
                 plot->addSpec(
-                    true, first_seg, cstyle, xa, ya,
-                    novec, fc->V[j]->z, fc->xco.str_std(), fc->yco.str_std(),
+                    true, first_seg, cstyle, xa, ya, novec, fc->V[j]->z_str(),
+                    fc->xco.str_std(), fc->yco.str_std(),
                     "curve file "+S(k)+ " spectrum "+S(j) );
                 xa.clear();
                 ya.clear();
@@ -517,4 +516,4 @@ void NPlot::Plot( class CPlot *plot, bool add, const string& mode )
         }
     }
     plot->showSpecs();
-}
\ No newline at end of file
+}
diff --git a/pub/lib/rssm.cpp b/pub/lib/rssm.cpp
index 4dd3472d..ed1020cc 100644
--- a/pub/lib/rssm.cpp
+++ b/pub/lib/rssm.cpp
@@ -19,6 +19,7 @@
 
 #include "defs.hpp"
 #include "olf.hpp"
+#include "obj.hpp"
 #include "mem.hpp"
 #include "slice.hpp"
 #include "rssm.hpp"
@@ -269,7 +270,7 @@ void NRSSM::ReadSpec( int flag )
         for( int j=0; j<ndet; ++j ){
             PSpec s( new CSpec );
             s->z.resize( 1 );
-            s->z[0] = j;
+            s->z[0] = PObjInt( new CObjInt( j ) );
             olf[iolf]->V.push_back(s);
         }
     }
@@ -455,8 +456,8 @@ void NRSSM::ReadSeries( int flag )
         for( j=0; j<ndet; ++j ){
             PSpec s( new CSpec );
             s->z.resize( 2 );
-            s->z[0] = isub;
-            s->z[1] = j;
+            s->z[0] = PObjInt( new CObjInt (isub) );
+            s->z[1] = PObjInt( new CObjInt (j) );
             for( iolf=0; iolf<2; ++iolf )
                 olf[iolf]->V.push_back( s );
         }
@@ -490,8 +491,7 @@ void NRSSM::ReadSeries( int flag )
                 int iolf0 = ichop*2;
                 int iolf1 = ichop*2+1;
                 if( raw[iolf1].size()/(1+ndet*2)!=nE ){
-                    printf( "inconsistent raw array sizes:\n"
-                        "  chop %i raw1 %i nE %i\n",
+                    printf( "inconsistent raw array sizes:\n  chop %i raw1 %i nE %i\n",
                             ichop, (int)raw[iolf1].size(), nE );
                     return;
                 }
@@ -499,12 +499,10 @@ void NRSSM::ReadSeries( int flag )
                     iraw = iE*(1+ndet*2);
                     x = raw[iolf0][iraw];
                     for( j=0; j<ndet; ++j ){
-                        tmeas = raw[iolf0][iraw+ndet+1+j] +
-                            raw[iolf1][iraw+ndet+1+j];
+                        tmeas = raw[iolf0][iraw+ndet+1+j] + raw[iolf1][iraw+ndet+1+j];
                         if( tmeas<1 ) continue;
                         count = raw[iolf0][iraw+1+j] + raw[iolf1][iraw+1+j];
-                        olf[ichop]->VS( isub*ndet+j )->push_xy( 
-                            x, count/tmeas/tstep );
+                        olf[ichop]->VS( isub*ndet+j )->push_xy( x, count/tmeas/tstep );
                     }
                 }
             }
@@ -520,7 +518,7 @@ void NRSSM::ReadSeries( int flag )
                 for( int iarr=0; iarr<4; ++iarr ){
                     for( int iE=0; iE<nE; ++iE ){
                         for( j=1; j<ndet+2; ++j ){
-                            RR[isub].rawdata[iarr][iE*(ndet+2)+j] -= 
+                            RR[isub].rawdata[iarr][iE*(ndet+2)+j] -=
                                 RR[isub-1].rawdata[iarr][iE*(ndet+2)+j];
                         }
                     }
@@ -548,8 +546,7 @@ void NRSSM::ReadSeries( int flag )
                     if( tmeas<1 ) continue;
                     for( j=0; j<ndet; ++j ){
                         count = raw[iolf0][iraw+1+j] + raw[iolf1][iraw+1+j];
-                        olf[ichop]->VS( isub*ndet+j )->push_xy( 
-                            x, count/tmeas/tstep );
+                        olf[ichop]->VS( isub*ndet+j )->push_xy( x, count/tmeas/tstep );
                     }
                 }
             }
diff --git a/pub/lib/slice.cpp b/pub/lib/slice.cpp
index 640402ed..4130845b 100644
--- a/pub/lib/slice.cpp
+++ b/pub/lib/slice.cpp
@@ -17,6 +17,7 @@
 
 #include "defs.hpp"
 #include "ptr.hpp"
+#include "obj.hpp"
 #include "slice.hpp"
 
 
@@ -32,14 +33,25 @@ CSlice::CSlice() :
 {}
 
 
-//! Sets z and dz to values from other CSlice.
+//! Returns a copy of the z vector.
 
-void CSlice::copy_z_base( const RSlice& other )
+vector<PObj> CSlice::clone_z() const
 {
-    z = other->z;
-    dz = other->dz;
+    vector<PObj> ret;
+    for( PObj zi: z )
+        ret.push_back( zi );
+    return ret;
 }
 
+//! Returns a vector of strings describing the z entries.
+
+vector<string> CSlice::z_str() const
+{
+    vector<string> ret;
+    for( PObj zi: z )
+        ret.push_back( zi->to_s() );
+    return ret;
+}
 
 //! Compares z vectors of two CSlice', for use in sort routine.
 
@@ -49,9 +61,9 @@ bool CompareZ( const RSlice& E1, const RSlice& E2 )
         throw "BUG: inconsistent z.size in CompareZ";
     int nz = E1->z.size();
     for( int iz=0; iz<nz; ++iz ){
-        if    ( E1->z[iz] > E2->z[iz] )
+        if    ( E1->z[iz]->to_r() > E2->z[iz]->to_r() )
             return false;
-        if    ( E1->z[iz] < E2->z[iz] )
+        if    ( E1->z[iz]->to_r() < E2->z[iz]->to_r() )
             return true;
     }
     return false;
@@ -114,7 +126,6 @@ void CSpec::clear()
     y.clear();
     dy.clear();
     z.clear();
-    dz.clear();
 }
 
 
@@ -262,7 +273,7 @@ string CSpec::infoLine() const
     char wrd[LEN];
     string out = "";
     for ( int iz=0; iz<z.size(); iz++ ) {
-        snprintf( wrd, LEN, "%-12.7g", z[iz] );
+        snprintf( wrd, LEN, "%-12.7g", z[iz]->to_r() );
         out += wrd;
         if( iz<z.size()-1 )
             out += " ";
@@ -296,7 +307,7 @@ string CCurve::infoLine() const
     char wrd[LEN];
     string out = "";
     for ( int iz=0; iz<z.size(); iz++ ) {
-        snprintf( wrd, LEN, "%-12.7g", z[iz] );
+        snprintf( wrd, LEN, "%-12.7g", z[iz]->to_r() );
         out += wrd;
         out += " ";
     }
diff --git a/pub/lib/slice.hpp b/pub/lib/slice.hpp
index 372962e7..9b509a1b 100644
--- a/pub/lib/slice.hpp
+++ b/pub/lib/slice.hpp
@@ -12,13 +12,14 @@
 
 class CSlice {
  public:
-    vector<double> z, dz;
+    vector<PObj> z;
     bool frozen;
 
     CSlice();
     virtual ~CSlice() {}; // magic: makes dynamic_cast possible
 
-    void copy_z_base( const RSlice& ein );
+    vector<PObj> clone_z() const;
+    vector<string> z_str() const;
     virtual string infoLine() const = 0;
 };
 
@@ -54,8 +55,7 @@ class CSpec: public CSlice {
 
     // extract data:
     int size() const;
-    void intpol( const vector<double>& in_x,
-                 vector<double>* out_y, vector<double>* out_dy ) const;
+    void intpol( const vector<double>& in_x, vector<double>* out_y, vector<double>* out_dy ) const;
     double intpol( double x ) const;
     double norm( string info ) const;
     bool has_step( double step ) const;
diff --git a/pub/lib/special.cpp b/pub/lib/special.cpp
index eb2b62bc..551bdb80 100644
--- a/pub/lib/special.cpp
+++ b/pub/lib/special.cpp
@@ -17,6 +17,7 @@
 #include "defs.hpp"
 #include "olf.hpp"
 #include "mem.hpp"
+#include "obj.hpp"
 #include "slice.hpp"
 #include "special.hpp"
 
@@ -86,7 +87,7 @@ void NSpecial::Test()
     for ( int p=0; p<N; ++p ){ 
         PSpec s( new CSpec );
 
-        s->z.push_back( p );
+        s->z.push_back( PObjInt( new CObjInt (p) ) );
 
         s->resize(N,false);
         for( int n=0; n<N; ++n )
@@ -107,7 +108,7 @@ void NSpecial::Test()
             nor += s->y[n] * s->y[n];
         printf( "p=%i => check sum = %g, norm = %g\n",
                 p, s->y[N-2]-(1+lambda)*s->y[N-1], nor );
-        s->z.push_back( nor );
+        s->z.push_back( PObjDbl( new CObjDbl( nor ) ) );
         for( int n=0; n<N; ++n )
             s->y[n] /= sqrt(nor);
 
diff --git a/pub/test/oz.f2t b/pub/test/oz.f2t
new file mode 100755
index 00000000..41207107
--- /dev/null
+++ b/pub/test/oz.f2t
@@ -0,0 +1,5 @@
+#!/usr/bin/env frida
+fm 7 3 h
+oz+ 100*j
+mz- 0
+exit(z0[,2]==200)
\ No newline at end of file
-- 
GitLab