diff --git a/pub/CMakeLists.txt b/pub/CMakeLists.txt
index 57e14de142598b85d74bf9d5260eb2572858ca6c..6742e6d07951075ccf156d034b9a56a1176c8dc4 100644
--- a/pub/CMakeLists.txt
+++ b/pub/CMakeLists.txt
@@ -19,7 +19,7 @@ enable_testing()
 #option(FRIDA_MAN "Build a user manual" OFF)
 #option(BUILD_DEBIAN "Build a debian package" OFF)
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O2 -pedantic -Wall -Wno-sign-compare -Wno-unused-result -Wno-parentheses  -Wno-unknown-pragmas -Werror")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -g -O2 -pedantic -Wall -Wno-sign-compare -Wno-unused-result -Wno-parentheses  -Wno-unknown-pragmas -Werror")
 # to use C99 _Complex, add -fext-numeric-literals to CXX_FLAGS
 
 find_package(Boost REQUIRED) # used header-only modules: format algorithm
diff --git a/pub/ftest/fit5restrict.f2t b/pub/ftest/disabled/fit5restrict.f2t
similarity index 100%
rename from pub/ftest/fit5restrict.f2t
rename to pub/ftest/disabled/fit5restrict.f2t
diff --git a/pub/lib/fit.cpp b/pub/lib/fit.cpp
index 97908d8043265788605ae89e36c31786fd133e5d..b054db787c3863e9f1d304a1697113d716935f66 100644
--- a/pub/lib/fit.cpp
+++ b/pub/lib/fit.cpp
@@ -30,8 +30,8 @@ using boost::format;
 bool allow_slow_conv = true;
 
 namespace NCurveFit {
-    string fit_one_spec( COlc *fc, POld fd, int k, int j, const lm_control_struct& control );
-    void fit_global( COlc *fc, POld fd, int k, const lm_control_struct& control );
+    string fit_one_spec( COlc *fc, const COld *fd, int k, int j, const lm_control_struct& control );
+    void fit_global( COlc *fc, const COld *fd, int k, const lm_control_struct& control );
 }
 
 void conditionally_parallel_for_with_report(
@@ -213,7 +213,8 @@ static void fit_evaluate( const double* par, int m_dat, const void *data,
 
 //! Fits one spectrum. Used when there are no global parameters. Returns an info line.
 
-string NCurveFit::fit_one_spec( COlc *fc, POld fd, int k, int j, const lm_control_struct& control )
+string NCurveFit::fit_one_spec( COlc *fc, const COld *fd, int k, int j,
+                                const lm_control_struct& control )
 {
     try {
         PSpec D = fd->VS(j);
@@ -222,7 +223,7 @@ string NCurveFit::fit_one_spec( COlc *fc, POld fd, int k, int j, const lm_contro
             throw S("frozen, no fit");
         FitDatTyp data;
         data.fc = fc;
-        data.fd = fd.get();
+        data.fd = fd;
         data.k = k;
         data.j = j;
         int nd = D->size();
@@ -383,11 +384,11 @@ static void fit_evaluate_glo( const double* par, int m_dat, const void *data,
 
 //! Fits all spectra simultaneously. Used when there are global parameters.
 
-void NCurveFit::fit_global( COlc *fc, POld fd, int k, const lm_control_struct& control )
+void NCurveFit::fit_global( COlc *fc, const COld *fd, int k, const lm_control_struct& control )
 {
     FitGloDatTyp data;
     data.fc = fc;
-    data.fd = fd.get();
+    data.fd = fd;
     data.k = k;
 
     // Set vector J2J to contain indices of non-frozen curves.
@@ -515,7 +516,7 @@ void NCurveFit::fit( bool _allow_slow_conv )
         for( int j=0; j<fc->nJ(); ++j )
             fc->VC(j)->assert_attr();
 
-        POld fd = NOlm::sp_mem_get_D(fc->kd); // TODO get rid of shared ptr
+        const COld *fd = NOlm::mem_get_D(fc->kd);
         if ( fc->nJ() != fd->nJ() )
             throw S("data file and curve file have different number of spectra");
         if ( !fc->nJ() )
@@ -524,6 +525,8 @@ void NCurveFit::fit( bool _allow_slow_conv )
             throw S("Data have no error bars, cannot apply chosen fit weights");
 
         if( fc->range_T ) {
+            throw S("TODO: restore range evaluation");
+            /*
             // overwrite fd with data that obye the range restriction:
             POld fdr( fd->new_old() );
             for ( int j=0; j<fc->nJ(); j++ ) {
@@ -543,7 +546,8 @@ void NCurveFit::fit( bool _allow_slow_conv )
                 }
                 fdr->V.push_back( eout );
             }
-            fd = fdr;
+            fd.swap( fdr ); // TODO can we simplify ?
+            */
         }
 
         control.epsilon = Epsilon;
diff --git a/pub/lib/loop.cpp b/pub/lib/loop.cpp
index 44746a0c35dd11d5b83c33a29a6cd242dbbd2bc0..47e539f6e13831c8454a6952b6183ca30c295dc8 100644
--- a/pub/lib/loop.cpp
+++ b/pub/lib/loop.cpp
@@ -27,35 +27,35 @@ FileIterator::FileIterator( const vector<int>& _Sel, bool tolerate_empty )
     reset();
 }
 
-POlo FileIterator::sp_next()
+COlo* FileIterator::next()
 {
     if ( iV>=Sel.size() )
-        return POlo();
+        return nullptr;
     int k=Sel[iV];
     if( k<0 )
         throw S("BUG: k<0 in file selection");
     if( k>=NOlm::mem_size() )
         throw "FileSelection["+S(iV)+"]="+S(k)+" exceeds online memory size "+S(NOlm::mem_size());
     ++iV;
-    return NOlm::sp_mem_get(k);
+    return NOlm::mem_get(k);
 }
 
-POld FileIterator::sp_nextD()
+COld* FileIterator::nextD()
 {
-    POlo f = sp_next();
+    COlo *f = next();
     if( !f )
-        return POld();
-    if( POld ret = P2D(f) )
+        return nullptr;
+    if( COld *ret = dynamic_cast<COld*>(f) )
         return ret;
     throw S("BUG: non-D file found by D iterator");
 }
 
-POlc FileIterator::sp_nextC()
+COlc* FileIterator::nextC()
 {
-    POlo f = sp_next();
+    COlo *f = next();
     if( !f )
-        return POlc();
-    if( POlc ret = P2C(f) )
+        return nullptr;
+    if( COlc *ret = dynamic_cast<COlc*>(f) )
         return ret;
     throw S("BUG: non-C file found by C iterator");
 }
diff --git a/pub/lib/loop.hpp b/pub/lib/loop.hpp
index 6d9aef31583907b290182ea85d8bb8b20b8ba3fb..9c80f6a1eb590d2bd52ce2ac79166355594062f3 100644
--- a/pub/lib/loop.hpp
+++ b/pub/lib/loop.hpp
@@ -21,10 +21,7 @@ public:
     int iteration() const { return iV-1; }
     int size() const { return Sel.size(); }
     // return current file, and advance iterator:
-    POlo sp_next();
-    POld sp_nextD();
-    POlc sp_nextC();
-    COlo* next()  { return sp_next().get(); }
-    COld* nextD() { return sp_nextD().get(); }
-    COlc* nextC() { return sp_nextC().get(); }
+    COlo* next();
+    COld* nextD();
+    COlc* nextC();
 };
diff --git a/pub/lib/manip.cpp b/pub/lib/manip.cpp
index a825f844055a9b20528d7bf238646152f4d560dd..fd5b24aa59c1898f99159e81efa666e318e6b700 100644
--- a/pub/lib/manip.cpp
+++ b/pub/lib/manip.cpp
@@ -29,7 +29,7 @@ using boost::format;
 
 // local routines:
 namespace NManip {
-    void ScaRemoveConstantZ( POlo f );
+    void ScaRemoveConstantZ( COlo *f );
 }
 
 
@@ -412,7 +412,7 @@ void NManip::points_remove_err()
 
 //! Remove z variable that does not genusy with j.
 
-void NManip::ScaRemoveConstantZ( POlo fio )
+void NManip::ScaRemoveConstantZ( COlo *fio )
 {
     for ( int iz=fio->nZ()-1; iz>=0; --iz ) {
         int nj = fio->nJ();
@@ -453,7 +453,7 @@ void NManip::slices_select( bool sel_del )
                 fout->V.push_back( fin->new_slice( j ) );
             }
         }
-        ScaRemoveConstantZ( fout );
+        ScaRemoveConstantZ( fout.get() );
         NOlm::mem_store( fout, fiter.k() );
     }
 }
@@ -569,7 +569,7 @@ void NManip::slices_rebin()
                 fout->V.push_back( cout );
             }
         }
-        ScaRemoveConstantZ( fout );
+        ScaRemoveConstantZ( fout.get() );
         NOlm::mem_store( fout, fiter.k() );
     }
 }
@@ -608,7 +608,7 @@ void NManip::slices_merge()
             }
             fout->V.push_back(sout);
         }
-        ScaRemoveConstantZ( fout );
+        ScaRemoveConstantZ( fout.get() );
         NOlm::mem_store( fout, fiter.k() );
     }
 }
@@ -1002,12 +1002,13 @@ void NManip::files_merge( const string& opts )
     fout->yco = fin->yco;
     fout->ZCo = fin->ZCo;
     if ( const COlc *fc = dynamic_cast<const COlc*>(fin) ) {
-        P2C(fout)->expr = fc->expr;
-        P2C(fout)->evaMode = fc->evaMode;
-        P2C(fout)->scrInpMode = fc->scrInpMode;
-        P2C(fout)->nP = fc->nP;
-        P2C(fout)->PCo = fc->PCo;
-        P2C(fout)->T = fc->T;
+        COlc *fcout = dynamic_cast<COlc*>(fout.get());
+        fcout->expr = fc->expr;
+        fcout->evaMode = fc->evaMode;
+        fcout->scrInpMode = fc->scrInpMode;
+        fcout->nP = fc->nP;
+        fcout->PCo = fc->PCo;
+        fcout->T = fc->T;
     }
     while ( fin = fiter.next() ) {
         if ( fin->xco != fout->xco )
@@ -1020,13 +1021,14 @@ void NManip::files_merge( const string& opts )
             if ( fin->ZCo[i] != fout->ZCo[i] )
                 throw "different z"+S(i)+" coordinate";
         if ( const COlc *fc = dynamic_cast<const COlc*>(fin) ) {
-            if ( dynamic_cast<const COlc*>(fin)->expr != fc->expr )
+            const COlc *fcout = dynamic_cast<const COlc*>(fout.get());
+            if ( fc->expr != fcout->expr  )
                 throw S("different curve definitions");
-            if ( fc->evaMode != P2C(fout)->evaMode )
+            if ( fc->evaMode != fcout->evaMode )
                 throw S("different curve evaluation mode");
-            if ( fc->nP != P2C(fout)->nP )
+            if ( fc->nP != fcout->nP )
                 throw S("different number of curve parameters");
-            if ( fc->PCo.size() != P2C(fout)->PCo.size() )
+            if ( fc->PCo.size() != fcout->PCo.size() )
                 throw S("inconsistent number of curve parameters");
         }
     }
@@ -1186,7 +1188,7 @@ void NManip::interpolate()
 
         CContext ctx( k );
         int k2 = T->tree_val_idx( ctx, "K" );
-        POld f2 = NOlm::sp_mem_get_D( k2 );
+        COld *f2 = NOlm::mem_get_D( k2 );
 
         fout->lDoc.push_back( "mi " + S(k2) );
 
diff --git a/pub/lib/mem.cpp b/pub/lib/mem.cpp
index 5a52173671605f9bbe243e6695cdfe3eb24ae026..0744dfc4b9ad1f7f64a3dc86d430bc4e1796816e 100644
--- a/pub/lib/mem.cpp
+++ b/pub/lib/mem.cpp
@@ -42,60 +42,67 @@ namespace NOlm {
     }
 
     //! Return pointer to file with index k.
-    POlo sp_mem_get( int k )
+    COlo* mem_get( int k )
     {
         if ( k<0 )
             throw "negative number " + S(k) + " cannot be a file index";
         if ( k>=MOM.size() )
             throw "file index " + S(k) + " not in online memory";
-        return MOM[k];
+        return MOM[k].get();
     }
 
-    const COlo* mem_get( int k ) { return sp_mem_get(k).get(); }
-
     //! Return pointer to file with index k, provided it contains data.
-    POld sp_mem_get_D( int k )
+    COld* mem_get_D( int k )
     {
-        POld ret = P2D( sp_mem_get( k ) );
+        COld *ret = dynamic_cast<COld*>( mem_get( k ) );
         if( !ret )
             throw "file " + S(k) + " is not a data file";
         return ret;
     }
 
-    const COld* mem_get_D( int k ) { return sp_mem_get_D(k).get(); }
-
     //! Return pointer to file with index k, provided it contains curves.
-    POlc sp_mem_get_C( int k )
+    COlc* mem_get_C( int k )
     {
-        POlc ret = P2C( sp_mem_get( k ) );
+        COlc *ret = dynamic_cast<COlc*>( mem_get( k ) );
         if( !ret )
             throw "file " + S(k) + " is not a curve file";
         return ret;
     }
 
-    const COlc* mem_get_C( int k ) { return sp_mem_get_C(k).get(); }
-
 
 //**************************************************************************************************
 //*  Modify online memory, and adapt file NSel::selection
 //**************************************************************************************************
 
     //! Store file f in online memory. If overwrite and k!=-1, overwrite file k.
-    void mem_store( POlo f, int k )
+    void mem_store( POlo& f, int k )
     {
         f->check_integrity();
         if( overwrite && k!=-1 ){
             // replace file k
             if( k>=MOM.size() )
                 throw S("BUG: cannot overwrite inexistent file");
-            MOM[k] = f;
+            f.swap( MOM[k] );
         } else {
             // append at end of online memory
-            MOM.push_back( f );
+            MOM.push_back( POlo() );
+            f.swap( MOM.back() );
             NSel::sel_push_back( MOM.size()-1 );
         }
     }
 
+    void mem_store( POld& f, int k )
+    {
+        POlo tmp( dynamic_cast<COlo*>(f.release()) );
+        mem_store( tmp, k );
+    }
+
+    void mem_store( POlc& f, int k )
+    {
+        POlo tmp( dynamic_cast<COlo*>(f.release()) );
+        mem_store( tmp, k );
+    }
+
     //! Remove file k from online memory.
     void mem_del( int k )
     {
@@ -138,7 +145,8 @@ namespace NOlm {
         while ( const COlo *fin=fiter.next() ){
             POlo fout( fin->new_olo( false ) );
             fout->copy_mainvec( fin );
-            BAK.push_back( fout );
+            BAK.push_back( POlo() );
+            BAK.back().swap( fout ); // TODO: simplify!
         }
     }
 
@@ -149,8 +157,11 @@ namespace NOlm {
         if( !BAK.size() )
             throw S("no files in backup");
         NSel::sel_collect_begin();
+        throw S("TODO: restore mem_backup_retrieve()");
+        /*
         for( auto b: BAK )
             mem_store( b, -1 );
+        */
         NSel::sel_collect_end();
         BAK.clear();
     }
diff --git a/pub/lib/mem.hpp b/pub/lib/mem.hpp
index e5ac8ac6ed9f2753048b4aefd0827ebc3cb19d22..c7691eaee6d3f43b2aac0e23a5fc4f0af17d2452 100644
--- a/pub/lib/mem.hpp
+++ b/pub/lib/mem.hpp
@@ -12,15 +12,15 @@
 namespace NOlm {
 
     // Read from online memory:
-    POlo sp_mem_get  ( int k ); // TODO wegdamit
-    const COlo* mem_get  ( int k );
-    const COld* mem_get_D( int k );
-    POld sp_mem_get_D( int k ); // TODO get rid of this workaround
-    const COlc* mem_get_C( int k );
+    COlo* mem_get  ( int k );
+    COld* mem_get_D( int k );
+    COlc* mem_get_C( int k );
     const int  mem_size();
 
     // Modify online memory (file selection is changed accordingly):
-    void mem_store( POlo olo, int k=-1 );
+    void mem_store( POlo& olo, int k=-1 );
+    void mem_store( POld& old, int k=-1 );
+    void mem_store( POlc& olc, int k=-1 );
     void mem_del( int k );
     void mem_xchange();
     void mem_copy();
diff --git a/pub/lib/olf.cpp b/pub/lib/olf.cpp
index 146816fd13e9da756e0d0351db1336ed258d8de4..4c4351d04561cf73f7dae5d05676d7cad37e217e 100644
--- a/pub/lib/olf.cpp
+++ b/pub/lib/olf.cpp
@@ -117,14 +117,14 @@ POlo COlc::new_olo( bool modified ) const
     return ret;
 }
 
-POld COld::new_old( bool modified ) const
+POld COld::new_old( bool modified ) const // TODO improve this scandalous workaround
 {
-    return P2D( new_olo( modified ) );
+    return POld( dynamic_cast<COld*>(new_olo( modified ).release() ) );
 }
 
-POlc COlc::new_olc( bool modified ) const
+POlc COlc::new_olc( bool modified ) const // TODO improve this scandalous workaround
 {
-    return P2C( new_olo( modified ) );
+    return POlc( dynamic_cast<COlc*>(new_olo( modified ).release() ) );
 }
 
 
diff --git a/pub/lib/olf.hpp b/pub/lib/olf.hpp
index f57777cf3821706d7db2e4679f47f21761fa9777..26c8b16b442989644d491589ad0d4e53630a4247 100644
--- a/pub/lib/olf.hpp
+++ b/pub/lib/olf.hpp
@@ -136,9 +136,3 @@ public:
     RObj eval_curve_scalar( double arg, int k, int j, bool want_error ) const;
     virtual string type() const { return "curve"; }
 };
-
-
-//! Casts.
-
-#define P2D(p) std::dynamic_pointer_cast<      class COld>(p)
-#define P2C(p) std::dynamic_pointer_cast<      class COlc>(p)
diff --git a/pub/lib/opr.cpp b/pub/lib/opr.cpp
index fb993ae598990fd72c5d20a2228161fe2bd1c908..4e2a54b59f49de8b6e1dbcb6f74763b93c6aeaea 100644
--- a/pub/lib/opr.cpp
+++ b/pub/lib/opr.cpp
@@ -200,7 +200,7 @@ void NOperate::Pointwise( string llabel )
             if( lref.num>=fc->nP )
                 throw S("no such parameter to operate on");
             NOlm::overwrite = 1;
-            P2C(fout)->clear_fits_outcome();
+            dynamic_cast<COlc*>(fout.get())->clear_fits_outcome();
         }
 
         if ( lref.categ==VCateg::R ) {
@@ -219,22 +219,23 @@ void NOperate::Pointwise( string llabel )
                 if ( lref.pointwise() ) {
                     PSpec eout( new CSpec( *(fd->VS(j)) ) );
                     vector<double> vout( fd->nPts(j) );
+                    COld* fdout = dynamic_cast<COld*>(fout.get());
                     if ( lref.categ==VCateg::X || lref.categ==VCateg::DY ) {
                         T->tree_vec_val( &vout, 0, k, j );
                         if      ( lref.categ==VCateg::X )
-                            (P2D(fout))->VS(j)->x = vout;
+                            fdout->VS(j)->x = vout;
                         else if ( lref.categ==VCateg::DY )
-                            (P2D(fout))->VS(j)->dy = vout;
+                            fdout->VS(j)->dy = vout;
                         else
                             throw S("BUG: unexpected lref");
                     } else if ( lref.categ==VCateg::Y ) {
                         vector<double> dvout( fd->nPts(j) );
                         T->tree_vec_val( &vout, &dvout, k, j );
-                        (P2D(fout))->VS(j)->y = vout;
+                        fdout->VS(j)->y = vout;
                         if( dvout.size() )
-                            (P2D(fout))->VS(j)->dy = dvout;
+                            fdout->VS(j)->dy = dvout;
                         else
-                            (P2D(fout))->VS(j)->dy.clear();
+                            fdout->VS(j)->dy.clear();
                     } else
                         throw S("BUG: unexpected lref");
                 } else if ( lref.categ==VCateg::Z ) {
@@ -244,7 +245,8 @@ void NOperate::Pointwise( string llabel )
                     else
                         fout->V[j]->z[lref.num] = pret;
                 } else if ( lref.categ==VCateg::CP ) {
-                    (P2C(fout))->VC(j)->P[lref.num] = T->tree_point_val( k, j )->to_r();
+                    COlc* fcout = dynamic_cast<COlc*>(fout.get());
+                    fcout->VC(j)->P[lref.num] = T->tree_point_val( k, j )->to_r();
                 } else {
                     throw S("BUG: invalid oxy");
                 }
diff --git a/pub/lib/ptr.hpp b/pub/lib/ptr.hpp
index ef038ec781b883d0cbc00276a24390ecf0d6bbce..0095d29131afdc24c81e10696062f4eae9958b7c 100644
--- a/pub/lib/ptr.hpp
+++ b/pub/lib/ptr.hpp
@@ -30,9 +30,9 @@ DEF_PTR( CObjVecEnu, PObjVecEnu, RObjVecEnu );
 
 #undef DEF_PTR
 
-using POlo   = std::shared_ptr<class COlo>;
-using POld   = std::shared_ptr<class COld>;
-using POlc   = std::shared_ptr<class COlc>;
+using POlo   = std::unique_ptr<class COlo>;
+using POld   = std::unique_ptr<class COld>;
+using POlc   = std::unique_ptr<class COlc>;
 using PSlice = std::shared_ptr<class CSlice>;
 using PSpec  = std::shared_ptr<class CSpec>;
 using PCurve = std::shared_ptr<class CCurve>;