////////////////////////////////////////////////////////////////////////////////
// 
// ConfData.hh 
//
//    produced: 08/08/25 jr
//
////////////////////////////////////////////////////////////////////////////////
#ifndef CONFDATA_HH
#define CONFDATA_HH

#include <iostream>
#include <string>
#include <sstream>

#include "CommandlineOptions.hh"

#include "Options.hh"

#include "Chirotope.hh"
#include "PointConfiguration.hh"
#include "Symmetry.hh"
#include "SimplicialComplex.hh"
#include "Circuits.hh"
#include "Cocircuits.hh"
#include "Vertices.hh"
#include "Facets.hh"
#include "Incidences.hh"
#include "Admissibles.hh"
#include "Volumes.hh"
#include "Field.hh"
#include "SwitchTable.hh"
#include "ClassifiedExtensionSymmetries.hh"
#include "ClassifiedSubsetSymmetries.hh"
#include "PlacingTriang.hh"
#include "FineTriang.hh"
#include "CheckTriang.hh"

namespace topcom {
  
  // the following class collects everything that one might want to know
  // about a configuration;
  // minimal information is always available,
  // some information can be generated on demand:
  class ConfData {
  private:
    static const std::string                    _dump_startline;
    static const std::string                    _dump_endline;
  private:
    
    // options including options for interpreting input data:
    const Options                               _options; // some options are relevant for what data is needed
    
    // minimal configuration information from input file (depending on client);
    const PointConfiguration*                   _pointsptr; // the coordinates (available if in input file)
    const Chirotope*                            _chiroptr; // the chirotope (from input file or generated from points)
    const SymmetryGroup*                        _symmetriesptr; // the symmetries of the configuration
    const SymmetryGroup*                        _required_symmetriesptr; // the symmetries required for the result
    const SimplicialComplex*                    _seedptr; // a triangulation used as a root for exploration

    // configuration information that may be generated as needed
    // (pointer = 0 => not yet available):
    const SimplicialComplex*                      _placingtriangptr;
    const Circuits*                               _circuitsptr;
    const Cocircuits*                             _cocircuitsptr;
    const Cocircuits*                             _poscocircuitsptr;
    const Vertices*                               _verticesptr;
    const Facets*                                 _facetsptr;
    const Incidences*                             _inctableptr;
    const Admissibles*                            _admtableptr;
    const Volumes*                                _voltableptr;
    const Field*                                  _volumeptr;
    const symmetryptr_datapair*                   _seed_symmetryptrsptr;
    const SymmetryGroup*                          _valid_symmetriesptr; // stabilizer of the valid simplices in case of restrictions
    const SymmetryGroup*                          _trivial_symmetriesptr; // holds a trivial symmetry group
    const SymmetryGroup*                          _simpidx_symmetriesptr; // valid symmetries represented as permutations of simplex indices
    const SwitchTable<IntegerSet, lexmin_mode>*   _extension_switchtableptr;
    const SwitchTable<IntegerSet, colexmax_mode>* _subset_switchtableptr;
    const points_simpidx_symmetries_type*         _points_simpidx_symmetriesptr; // all symmetries represented by pairs (pointer to point symmetry, corr. simpidx symmetry)
    const points_simpidx_symmetries_type*         _valid_points_simpidx_symmetriesptr; // valid symmetries represented by pairs of point/simpidx symmetries
    const points_simpidx_symmetries_type*         _trivial_points_simpidx_symmetriesptr; // no symmetries represented by pairs of point/simpidx symmetries
    const ClassifiedExtensionSymmetries*          _classified_extension_symmetriesptr;
    const ClassifiedSubsetSymmetries*             _classified_subset_symmetriesptr;

    // auxiliary data memebers:
    Symmetry*                                     _transformationptr;
  public:
    inline ConfData() = delete; // no default constructor since at least options are required

    // constructors:
    inline ConfData(const ConfData&);
    inline ConfData(ConfData&&);
    inline ConfData(const Options&);

    // destructor:
    inline ~ConfData();

    // assignments:
    inline ConfData& operator=(const ConfData&) = delete;
    inline ConfData& operator=(ConfData&&) = delete;

    // const check on availability of data:
    inline bool has_points() const;
    inline bool has_chiro() const;
    inline bool has_symmetries() const;
    inline bool has_required_symmetries() const;
    inline bool has_seed() const;
    inline bool has_placingtriang() const;
    inline bool has_circuits() const;
    inline bool has_cocircuits() const;
    inline bool has_poscocircuits() const;
    inline bool has_vertices() const;
    inline bool has_facets() const;
    inline bool has_inctable() const;
    inline bool has_admtable() const;
    inline bool has_voltable() const;
    inline bool has_volume() const;
    inline bool has_seed_symmetryptrs() const;
    inline bool has_valid_symmetries() const;
    inline bool has_trivial_symmetries() const;
    inline bool has_simpidx_symmetries() const;
    inline bool has_extension_switchtable() const;
    inline bool has_subset_switchtable() const;
    inline bool has_points_simpidx_symmetries() const;
    inline bool has_valid_points_simpidx_symmetries() const;
    inline bool has_trivial_points_simpidx_symmetries() const;
    inline bool has_classified_extension_symmetries() const;
    inline bool has_classified_subset_symmetries() const;

    // const accessors:
    inline const Options& options() const;
    inline const PointConfiguration& points() const;
    inline const Chirotope& chiro() const;
    inline const SymmetryGroup& symmetries() const;
    inline const SymmetryGroup& required_symmetries() const;
    inline const SimplicialComplex& seed() const;
    inline const SimplicialComplex& placingtriang() const;
    inline const Circuits& circuits() const;
    inline const Cocircuits& cocircuits() const;
    inline const Cocircuits& poscocircuits() const;
    inline const Vertices& vertices() const;
    inline const Facets& facets() const;
    inline const Incidences& inctable() const;
    inline const Admissibles& admtable() const;
    inline const Volumes& voltable() const;
    inline const Field& volume() const;
    inline const symmetryptr_datapair& seed_symmetryptrs() const;
    inline const SymmetryGroup& valid_symmetries() const;
    inline const SymmetryGroup& trivial_symmetries() const;
    inline const SymmetryGroup& simpidx_symmetries() const;
    inline const SwitchTable<IntegerSet, lexmin_mode>& extension_switchtable() const;
    inline const SwitchTable<IntegerSet, colexmax_mode>& subset_switchtable() const;
    inline const points_simpidx_symmetries_type& points_simpidx_symmetries() const;
    inline const points_simpidx_symmetries_type& valid_points_simpidx_symmetries() const;
    inline const points_simpidx_symmetries_type& trivial_points_simpidx_symmetries() const;
    inline const ClassifiedExtensionSymmetries& classified_extension_symmetries() const;
    inline const ClassifiedSubsetSymmetries& classified_subset_symmetries() const;

    // short-cut accessors:
    inline const parameter_type no() const;
    inline const parameter_type rank() const;

    // modifiers:
    // make data:
    inline const parameter_type make_no();
    inline const parameter_type make_rank();
    inline const Chirotope& make_chiro();
    inline const SimplicialComplex& make_seed();
    inline const SimplicialComplex& make_placingtriang();
    inline const Circuits& make_circuits();
    inline const Cocircuits& make_cocircuits();
    inline const Cocircuits& make_poscocircuits();
    inline const Vertices& make_vertices();
    inline const Facets& make_facets();
    inline const Incidences& make_inctable();
    inline const Admissibles& make_admtable();
    inline const Volumes& make_voltable();
    inline const Field& make_volume();
    inline const symmetryptr_datapair& make_seed_symmetryptrs();
    inline const SymmetryGroup& make_valid_symmetries();
    inline const SymmetryGroup& make_trivial_symmetries();
    inline const SymmetryGroup& make_simpidx_symmetries();
    inline const SwitchTable<IntegerSet, lexmin_mode>& make_extension_switchtable();
    inline const SwitchTable<IntegerSet, colexmax_mode>& make_subset_switchtable();
    inline const points_simpidx_symmetries_type& make_points_simpidx_symmetries();
    inline const points_simpidx_symmetries_type& make_valid_points_simpidx_symmetries();
    inline const points_simpidx_symmetries_type& make_trivial_points_simpidx_symmetries();
    inline const ClassifiedExtensionSymmetries& make_classified_extension_symmetries();
    inline const ClassifiedSubsetSymmetries& make_classified_subset_symmetries();

    // remove data (except for indispensable data points, chiro, symmetries, required_symmetries, seed):
    inline void remove_placingtriang();
    inline void remove_circuits();
    inline void remove_cocircuits();
    inline void remove_poscocircuits();
    inline void remove_vertices();
    inline void remove_facets();
    inline void remove_inctable();
    inline void remove_admtable();
    inline void remove_voltable();
    inline void remove_volume();
    inline void remove_seed_symmetryptrs();
    inline void remove_valid_symmetries();
    inline void remove_trivial_symmetries();
    inline void remove_simpidx_symmetries();
    inline void remove_extension_switchtable();
    inline void remove_subset_switchtable();
    inline void remove_points_simpidx_symmetries();
    inline void remove_valid_points_simpidx_symmetries();
    inline void remove_trivial_points_simpidx_symmetries();
    inline void remove_classified_extension_symmetries();
    inline void remove_classified_subset_symmetries();

    // comparison operators:
    inline bool operator==(const ConfData&) const;

    // functions of general interest:
    inline const Vector gkz(const SimplicialComplex& triang) const;

  public:
    
    // stream output/input:
    std::ostream& write(std::ostream&) const;
    std::istream& read(std::istream&); // read an input stream with some data written earlier by write
    std::istream& read_input(std::istream&); // read only the data from the TOPCOM input file
    friend inline std::ostream& operator<<(std::ostream&, const ConfData&);
    friend inline std::istream& operator>>(std::istream&, ConfData&);
  };
  
  inline ConfData::ConfData(const Options& options) :
    _options(options),
    _pointsptr(0),
    _chiroptr(0),
    _symmetriesptr(0),
    _required_symmetriesptr(0),
    _seedptr(0),
    _placingtriangptr(0),
    _circuitsptr(0),
    _cocircuitsptr(0),
    _poscocircuitsptr(0),
    _verticesptr(0),
    _facetsptr(0),
    _inctableptr(0),
    _admtableptr(0),
    _voltableptr(0),
    _volumeptr(0),
    _seed_symmetryptrsptr(0),
    _valid_symmetriesptr(0),
    _trivial_symmetriesptr(0),
    _simpidx_symmetriesptr(0),
    _extension_switchtableptr(0),
    _subset_switchtableptr(0),
    _points_simpidx_symmetriesptr(0),
    _valid_points_simpidx_symmetriesptr(0),
    _trivial_points_simpidx_symmetriesptr(0),
    _classified_extension_symmetriesptr(0),
    _classified_subset_symmetriesptr(0),
    _transformationptr(0) {

    // read the basic data from input stream:
  }

  // copy constructor means deep copy:
  inline ConfData::ConfData(const ConfData& cd) :
    _options(cd._options),
    _pointsptr(cd._pointsptr == 0 ? 0 : new PointConfiguration(*cd._pointsptr)),
    _chiroptr(cd._chiroptr == 0 ? 0 : new Chirotope(*cd._chiroptr)),
    _symmetriesptr(cd._symmetriesptr == 0 ? 0 : new SymmetryGroup(*cd._symmetriesptr)),
    _required_symmetriesptr(cd._required_symmetriesptr == 0 ? 0 : new SymmetryGroup(*cd._required_symmetriesptr)),
    _seedptr(cd._seedptr == 0 ? 0 : new SimplicialComplex(*cd._seedptr)),
    _placingtriangptr(cd._placingtriangptr == 0 ? 0 : new SimplicialComplex(*cd._placingtriangptr)),
    _circuitsptr(cd._circuitsptr == 0 ? 0 : new Circuits(*cd._circuitsptr)),
    _cocircuitsptr(cd._cocircuitsptr == 0 ? 0 : new Cocircuits(*cd._cocircuitsptr)),
    _poscocircuitsptr(cd._poscocircuitsptr == 0 ? 0 : new Cocircuits(*cd._poscocircuitsptr)),
    _verticesptr(cd._verticesptr == 0 ? 0 : new Vertices(*cd._verticesptr)),
    _facetsptr(cd._facetsptr == 0 ? 0 : new Facets(*cd._facetsptr)),
    _inctableptr(cd._inctableptr == 0 ? 0 : new Incidences(*cd._inctableptr)),
    _admtableptr(cd._admtableptr == 0 ? 0 : new Admissibles(*cd._admtableptr)),
    _voltableptr(cd._voltableptr == 0 ? 0 : new Volumes(*cd._voltableptr)),
    _volumeptr(cd._volumeptr == 0 ? 0 : new Field(*cd._volumeptr)),
    _seed_symmetryptrsptr(cd._seed_symmetryptrsptr == 0 ? 0 : new symmetryptr_datapair(*cd._seed_symmetryptrsptr)),
    _valid_symmetriesptr(cd._valid_symmetriesptr == 0 ? 0 : new SymmetryGroup(*cd._valid_symmetriesptr)),
    _trivial_symmetriesptr(cd._trivial_symmetriesptr == 0 ? 0 : new SymmetryGroup(*cd._trivial_symmetriesptr)),
    _simpidx_symmetriesptr(cd._simpidx_symmetriesptr == 0 ? 0 : new SymmetryGroup(*cd._simpidx_symmetriesptr)),
    _extension_switchtableptr(cd._extension_switchtableptr == 0 ? 0 : new SwitchTable(*cd._extension_switchtableptr)),
    _subset_switchtableptr(cd._subset_switchtableptr == 0 ? 0 : new SwitchTable(*cd._subset_switchtableptr)),
    _points_simpidx_symmetriesptr(cd._points_simpidx_symmetriesptr == 0 ? 0 : new points_simpidx_symmetries_type(*cd._points_simpidx_symmetriesptr)),
    _valid_points_simpidx_symmetriesptr(cd._valid_points_simpidx_symmetriesptr == 0 ? 0 : new points_simpidx_symmetries_type(*cd._valid_points_simpidx_symmetriesptr)),
    _trivial_points_simpidx_symmetriesptr(cd._trivial_points_simpidx_symmetriesptr == 0 ? 0 : new points_simpidx_symmetries_type(*cd._trivial_points_simpidx_symmetriesptr)),
    _classified_extension_symmetriesptr(cd._classified_extension_symmetriesptr == 0 ? 0 : new ClassifiedExtensionSymmetries(*cd._classified_extension_symmetriesptr)),
    _classified_subset_symmetriesptr(cd._classified_subset_symmetriesptr == 0 ? 0 : new ClassifiedSubsetSymmetries(*cd._classified_subset_symmetriesptr)),
    _transformationptr(0) {
  }

  // move constructor means shallow copy:
  inline ConfData::ConfData(ConfData&& cd) :
    _options(cd._options),
    _pointsptr(cd._pointsptr),
    _chiroptr(cd._chiroptr),
    _symmetriesptr(cd._symmetriesptr),
    _required_symmetriesptr(cd._required_symmetriesptr),
    _seedptr(cd._seedptr),
    _placingtriangptr(cd._placingtriangptr),
    _circuitsptr(cd._circuitsptr),
    _cocircuitsptr(cd._cocircuitsptr),
    _poscocircuitsptr(cd._poscocircuitsptr),
    _verticesptr(cd._verticesptr),
    _facetsptr(cd._facetsptr),
    _inctableptr(cd._inctableptr),
    _admtableptr(cd._admtableptr),
    _voltableptr(cd._voltableptr),
    _volumeptr(cd._volumeptr),
    _seed_symmetryptrsptr(cd._seed_symmetryptrsptr),
    _valid_symmetriesptr(cd._valid_symmetriesptr),
    _trivial_symmetriesptr(cd._trivial_symmetriesptr),
    _simpidx_symmetriesptr(cd._simpidx_symmetriesptr),
    _extension_switchtableptr(cd._extension_switchtableptr),
    _subset_switchtableptr(cd._subset_switchtableptr),
    _points_simpidx_symmetriesptr(cd._points_simpidx_symmetriesptr),
    _valid_points_simpidx_symmetriesptr(cd._valid_points_simpidx_symmetriesptr),
    _trivial_points_simpidx_symmetriesptr(cd._trivial_points_simpidx_symmetriesptr),
    _classified_extension_symmetriesptr(cd._classified_extension_symmetriesptr),
    _classified_subset_symmetriesptr(cd._classified_subset_symmetriesptr),
    _transformationptr(0) {
  }
  
  // destructor:
  inline ConfData::~ConfData() {
    if (_transformationptr) {
      delete _transformationptr;
    }
    if (_classified_subset_symmetriesptr) {
      delete _classified_subset_symmetriesptr;
    }
    if (_classified_extension_symmetriesptr) {
      delete _classified_extension_symmetriesptr;
    }
    if (_trivial_points_simpidx_symmetriesptr) {
      delete _trivial_points_simpidx_symmetriesptr;
    }
    if (_valid_points_simpidx_symmetriesptr) {
      delete _valid_points_simpidx_symmetriesptr;
    }
    if (_points_simpidx_symmetriesptr) {
      delete _points_simpidx_symmetriesptr;
    }
    if (_seed_symmetryptrsptr) {
      delete _seed_symmetryptrsptr;
    }
    if (_subset_switchtableptr) {
      delete _subset_switchtableptr;
    }
    if (_extension_switchtableptr) {
      delete _extension_switchtableptr;
    }
    if (_simpidx_symmetriesptr) {
      delete _simpidx_symmetriesptr;
    }
    if (_volumeptr) {
      delete _volumeptr;
    }
    if (_voltableptr) {
      delete _voltableptr;
    }
    if (_inctableptr) {
      delete _inctableptr;
    }
    if (_admtableptr) {
      delete _admtableptr;
    }
    if (_facetsptr) {
      delete _facetsptr;
    }
    if (_verticesptr) {
      delete _verticesptr;
    }
    if (_poscocircuitsptr) {
      delete _poscocircuitsptr;
    }
    if (_cocircuitsptr) {
      delete _cocircuitsptr;
    }
    if (_circuitsptr) {
      delete _circuitsptr;
    }
    if (_placingtriangptr) {
      delete _placingtriangptr;
    }
    if (_seedptr) {
      delete _seedptr;
    }
    if (_trivial_symmetriesptr) {
      delete _trivial_symmetriesptr;
    }

    // if no separate valid symmetries had to be generated,
    // the pointer points to _symmetriesptr and must not be deleted:
    if ((_valid_symmetriesptr) && (_valid_symmetriesptr != _symmetriesptr)) {
      delete _valid_symmetriesptr;
    }
    if (_required_symmetriesptr) {
      delete _required_symmetriesptr;
    }
    if (_symmetriesptr) {
      delete _symmetriesptr;
    }
    if (_chiroptr) {
      delete _chiroptr;
    }
    if (_pointsptr) {
      delete _pointsptr;
    }
  }

  
  // const check on availability of data:
  inline bool ConfData::has_points() const {
    return _pointsptr;
  }
  inline bool ConfData::has_chiro() const {
    return _chiroptr;
  }
  inline bool ConfData::has_symmetries() const {
    return _symmetriesptr;
  }
  inline bool ConfData::has_required_symmetries() const {
    return _required_symmetriesptr;
  }
  inline bool ConfData::has_seed() const {
    return _seedptr;
  }
  inline bool ConfData::has_placingtriang() const {
    return _placingtriangptr;
  }
  inline bool ConfData::has_circuits() const {
    return _circuitsptr;
  }
  inline bool ConfData::has_cocircuits() const {
    return _cocircuitsptr;
  }
  inline bool ConfData::has_poscocircuits() const {
    return _poscocircuitsptr;
  }
  inline bool ConfData::has_vertices() const {
    return _verticesptr;
  }
  inline bool ConfData::has_facets() const {
    return _facetsptr;
  }
  inline bool ConfData::has_inctable() const {
    return _inctableptr;
  }
  inline bool ConfData::has_admtable() const {
    return _admtableptr;
  }
  inline bool ConfData::has_voltable() const {
    return _voltableptr;
  }
  inline bool ConfData::has_volume() const {
    return _volumeptr;
  }
  inline bool ConfData::has_seed_symmetryptrs() const {
    return _seed_symmetryptrsptr;
  }
  inline bool ConfData::has_valid_symmetries() const {
    return _valid_symmetriesptr;
  }
  inline bool ConfData::has_trivial_symmetries() const {
    return _trivial_symmetriesptr;
  }
  inline bool ConfData::has_simpidx_symmetries() const {
    return _simpidx_symmetriesptr;
  }
  inline bool ConfData::has_extension_switchtable() const {
    return _extension_switchtableptr;
  }
  inline bool ConfData::has_subset_switchtable() const {
    return _subset_switchtableptr;
  }
  inline bool ConfData::has_points_simpidx_symmetries() const {
    return _points_simpidx_symmetriesptr;
  }
  inline bool ConfData::has_valid_points_simpidx_symmetries() const {
    return _valid_points_simpidx_symmetriesptr;
  }
  inline bool ConfData::has_trivial_points_simpidx_symmetries() const {
    return _trivial_points_simpidx_symmetriesptr;
  }
  inline bool ConfData::has_classified_extension_symmetries() const {
    return _classified_extension_symmetriesptr;
  }
  inline bool ConfData::has_classified_subset_symmetries() const {
    return _classified_subset_symmetriesptr;
  }

  // accessors:
  inline const Options& ConfData::options() const {
    return _options;
  }
  inline const PointConfiguration& ConfData::points() const {
    if (!_pointsptr) {
	MessageStreams::forced() << "ConfData::points(): no points present in data - exiting" << std::endl;
	exit(1);
    }
    return *_pointsptr;
  }
  inline const Chirotope& ConfData::chiro() const {
    if (!_chiroptr) {
      MessageStreams::forced() << "ConfData::symmetries(): no symmetries present in data - exiting" << std::endl;
      exit(1);
    }
    return *_chiroptr;
  }
  inline const SymmetryGroup& ConfData::symmetries() const {
    if (!_symmetriesptr) {
      MessageStreams::forced() << "ConfData::symmetries(): no symmetries present in data - exiting" << std::endl;
      exit(1);
    }
    return *_symmetriesptr;
  }
  inline const SymmetryGroup& ConfData::required_symmetries() const {
    if (!_required_symmetriesptr) {
      MessageStreams::forced() << "ConfData::chiro(): no required symmetries present in data - exiting" << std::endl;
      exit(1);
    }
    return *_required_symmetriesptr;
  }

  inline const SimplicialComplex& ConfData::seed() const {
    if (!_seedptr) {
      MessageStreams::forced() << "ConfData::seed(): no seed present in data - exiting" << std::endl;
      exit(1);
    }
    return *_seedptr;
  }
  
  inline const SimplicialComplex& ConfData::placingtriang() const {
    if (!_placingtriangptr) {
      MessageStreams::forced() << "ConfData::placingtriang(): no placingtriang present in data - exiting" << std::endl;
      exit(1);
    }
    return *_placingtriangptr;
  }

  inline const Circuits& ConfData::circuits() const {
    if (!_circuitsptr) {
      MessageStreams::forced() << "ConfData::circuits(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_circuitsptr;
  }
  inline const Cocircuits& ConfData::cocircuits() const {
    if (!_cocircuitsptr) {
      MessageStreams::forced() << "ConfData::cocircuits(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_cocircuitsptr;
  }
  inline const Cocircuits& ConfData::poscocircuits() const {
    if (!_cocircuitsptr) {
      MessageStreams::forced() << "ConfData::poscocircuits(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_poscocircuitsptr;
  }
  inline const Vertices& ConfData::vertices() const {
    if (!_verticesptr) {
      MessageStreams::forced() << "ConfData::vertices(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_verticesptr;
  }
  inline const Facets& ConfData::facets() const {
    if (!_facetsptr) {
      MessageStreams::forced() << "ConfData::facets(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_facetsptr;
  }
  inline const Incidences& ConfData::inctable() const {
    if (!_inctableptr) {
      MessageStreams::forced() << "ConfData::inctable(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_inctableptr;
  }
  inline const Admissibles& ConfData::admtable() const {
    if (!_admtableptr) {
      MessageStreams::forced() << "ConfData::admtable(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_admtableptr;
  }
  inline const Volumes& ConfData::voltable() const {
    if (!_voltableptr) {
      MessageStreams::forced() << "ConfData::voltable(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_voltableptr;
  }
  inline const Field& ConfData::volume() const {
    if (!_volumeptr) {
      MessageStreams::forced() << "ConfData::volume(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_volumeptr;
  }
  inline const symmetryptr_datapair& ConfData::seed_symmetryptrs() const {
    if (!_seed_symmetryptrsptr) {
      MessageStreams::forced() << "ConfData::seed_symmetryptrs(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_seed_symmetryptrsptr;
  }
  inline const SymmetryGroup& ConfData::valid_symmetries() const {
    if (!_valid_symmetriesptr) {
      MessageStreams::forced() << "ConfData::valid_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_valid_symmetriesptr;
  }
  inline const SymmetryGroup& ConfData::trivial_symmetries() const {
    if (!_trivial_symmetriesptr) {
      MessageStreams::forced() << "ConfData::trivial_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_trivial_symmetriesptr;
  }
  inline const SwitchTable<IntegerSet, lexmin_mode>& ConfData::extension_switchtable() const {
    if (!_extension_switchtableptr) {
      MessageStreams::forced() << "ConfData::extension_switchtable(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_extension_switchtableptr;
  }
  inline const SwitchTable<IntegerSet, colexmax_mode>& ConfData::subset_switchtable() const {
    if (!_subset_switchtableptr) {
      MessageStreams::forced() << "ConfData::subset_switchtable(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_subset_switchtableptr;
  }
  inline const SymmetryGroup& ConfData::simpidx_symmetries() const {
    if (!_simpidx_symmetriesptr) {
      MessageStreams::forced() << "ConfData::simpidx_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_simpidx_symmetriesptr;
  }
  inline const points_simpidx_symmetries_type& ConfData::points_simpidx_symmetries() const {
    if (!_points_simpidx_symmetriesptr) {
      MessageStreams::forced() << "ConfData::points_simpidx_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_points_simpidx_symmetriesptr;
  }
  inline const points_simpidx_symmetries_type& ConfData::valid_points_simpidx_symmetries() const {
    if (!_valid_points_simpidx_symmetriesptr) {
      MessageStreams::forced() << "ConfData::valid_points_simpidx_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_valid_points_simpidx_symmetriesptr;
  }
  inline const points_simpidx_symmetries_type& ConfData::trivial_points_simpidx_symmetries() const {
    if (!_trivial_points_simpidx_symmetriesptr) {
      MessageStreams::forced() << "ConfData::trivial_points_simpidx_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_trivial_points_simpidx_symmetriesptr;
  }
  inline const ClassifiedExtensionSymmetries& ConfData::classified_extension_symmetries() const {
    if (!_classified_extension_symmetriesptr) {
      MessageStreams::forced() << "ConfData::classified_extension_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_classified_extension_symmetriesptr;
  }
  inline const ClassifiedSubsetSymmetries& ConfData::classified_subset_symmetries() const {
    if (!_classified_subset_symmetriesptr) {
      MessageStreams::forced() << "ConfData::classified_subset_symmetries(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_classified_subset_symmetriesptr;
  }

  // short-cut accessors:
  inline const parameter_type ConfData::no() const {
    return chiro().no();
  }
  inline const parameter_type ConfData::rank() const {
    return chiro().rank();
  }
  
  // modifiers:
  // make data:
  inline const parameter_type ConfData::make_no() {
    return make_chiro().no();
  }
  
  inline const parameter_type ConfData::make_rank() {
    return make_chiro().rank();
  }
  
  inline const Chirotope& ConfData::make_chiro() {
    if (!_chiroptr) {
      if (!_pointsptr) {
	MessageStreams::forced() << "ConfData::make_chiro(): neither points nor chirotope present in data - exiting" << std::endl;
	exit(1);
      }
      MessageStreams::verbose() << "generating chiro ..." << std::endl;
      _chiroptr = new Chirotope(points(), _options.preprocess_chiro());
    }
    return *_chiroptr;
  }
  inline const SimplicialComplex& ConfData::make_seed() {
    if (!_seedptr) {
      MessageStreams::verbose() << "computing seed triangulation via placing and pushing ..." 
				<< std::endl;
      _seedptr = new SimplicialComplex(make_placingtriang());
    }
    return *_seedptr;
  }
  inline const SimplicialComplex& ConfData::make_placingtriang() {
    if (!_placingtriangptr) {
      MessageStreams::verbose() << "computing placing triangulation via placing and pushing ..." 
				<< std::endl;
      if (_options.full_only()) {
	_placingtriangptr = new FineTriang(make_chiro());
      }
      else {
	_placingtriangptr = new PlacingTriang(make_chiro());
      }
    }
    return *_placingtriangptr;
  }
  inline const Circuits& ConfData::make_circuits() {
    if (!_circuitsptr) {
      MessageStreams::verbose() << "generating circuits ..." << std::endl;
      _circuitsptr = new Circuits(make_chiro());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_circuitsptr;
  }
  inline const Cocircuits& ConfData::make_cocircuits() {
    if (!_cocircuitsptr) {
      MessageStreams::verbose() << "generating cocircuits ..." << std::endl;
      _cocircuitsptr = new Cocircuits(make_chiro());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_cocircuitsptr;
  }
  inline const Cocircuits& ConfData::make_poscocircuits() {
    if (!_poscocircuitsptr) {
      MessageStreams::verbose() << "generating positive cocircuits ..." << std::endl;
      _poscocircuitsptr = new Cocircuits(make_chiro(), true);
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_poscocircuitsptr;
  }
  inline const Vertices& ConfData::make_vertices() {
    if (!_verticesptr) {
      MessageStreams::verbose() << "generating vertices ..." << std::endl;
      _verticesptr = new Vertices(make_circuits());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_verticesptr;
  }
  inline const Facets& ConfData::make_facets() {
    if (!_facetsptr) {
      MessageStreams::verbose() << "generating facets ..." << std::endl;
      if (_seedptr) {
	_facetsptr = new Facets(make_chiro(), seed().pseudoboundary());
      }
      else {
	_facetsptr = new Facets(make_poscocircuits());
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_facetsptr;
  }
  inline const Incidences& ConfData::make_inctable() {
    if (!_inctableptr) {
      MessageStreams::verbose() << "generating incidences table ..." << std::endl;
      if (CommandlineOptions::full_inctable_needed()) {

	// all incidences are required:
	_inctableptr = new Incidences(make_chiro(), make_facets());
      }
      else if (
	       has_admtable() // if not, simplices have not been reduced to valid simplices
	       &&
	       !CommandlineOptions::orbit_traversal_needed() // no orbit needs traversal
	       &&
	       _options.compute_all() // in flip graph exploration, all incidences are needed at various places
	       ) {

	// only incidences for valid simplices from admtable are required:
	_inctableptr = new Incidences(make_chiro(), make_facets(), admtable().valid_simplices());
      }
      else {

	// it does not pay off to generate admissibles only to have a smaller incidences table;
	// for flip-graph exploration, all incidences are needed anyway,
	// since in orbit regularity checks all incidences are needed:
	_inctableptr = new Incidences(make_chiro(), make_facets());
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_inctableptr;
  }
  inline const Admissibles& ConfData::make_admtable() {
    if (!_admtableptr) {
      MessageStreams::verbose() << "generating admissibles table ..." << std::endl;
      _admtableptr = new Admissibles(make_circuits(), _pointsptr, make_chiro(), symmetries(), required_symmetries(), _options.full_only());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_admtableptr;
  }
  inline const Volumes& ConfData::make_voltable() {
    if (!_voltableptr) {
      MessageStreams::verbose() << "generating volumes table ..." << std::endl;
      _voltableptr = new Volumes(*this);
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_voltableptr;
  }
  inline const Field& ConfData::make_volume() {
    if (!_volumeptr) {
      MessageStreams::verbose() << "generating volume ..." << std::endl;
      _volumeptr = new Field(points().volume());
      MessageStreams::verbose() << "... done." << std::endl;
   }
    return *_volumeptr;
  }
  inline const symmetryptr_datapair& ConfData::make_seed_symmetryptrs() {
    if (!_seed_symmetryptrsptr) {
      MessageStreams::verbose() << "generating seed symmetry pointers ..." << std::endl;
      if (symmetries().complete()) {
	_seed_symmetryptrsptr = new symmetryptr_datapair(symmetries().stabilizer_ptrs(make_seed()));
      }
      else {
	SymmetryGroup init_symmetries(symmetries());
	init_symmetries.closure();
	_seed_symmetryptrsptr = new symmetryptr_datapair(init_symmetries.stabilizer_ptrs(make_seed()));
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_seed_symmetryptrsptr;
  }
  inline const SymmetryGroup& ConfData::make_valid_symmetries() {
    if (!_valid_symmetriesptr) {
      MessageStreams::verbose() << "generating valid symmetries ..." << std::endl;
      if (CommandlineOptions::admissibles_restricted()) {
	if (symmetries().fixes(make_admtable().valid_simplices())) {
	  MessageStreams::verbose() << "all symmetries fix the set of valid simplices - using all symmetries" << std::endl;
	  _valid_symmetriesptr = _symmetriesptr;
	}
	else {
	  MessageStreams::verbose() << "not all symmetries fix the set of valid simplices - reducing symmetries to stabilizer of valid simplices ..." << std::endl;
	  _valid_symmetriesptr = new SymmetryGroup(symmetries().stabilizer(make_admtable().valid_simplices()));
	  MessageStreams::verbose() << "... generated subgroup of valid symmetries of order " << _valid_symmetriesptr->size() + 1 << " - done." << std::endl;
	}
      }
      else {
	MessageStreams::verbose() << "no additional restriction on valid simplices - using all symmetries" << std::endl;
	_valid_symmetriesptr = _symmetriesptr;
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_valid_symmetriesptr;
  }
  inline const SymmetryGroup& ConfData::make_trivial_symmetries() {
    if (!_trivial_symmetriesptr) {
      MessageStreams::verbose() << "generating trivial symmetries ..." << std::endl;
      _trivial_symmetriesptr = new SymmetryGroup(make_chiro().no());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_trivial_symmetriesptr;
  }
  inline const SymmetryGroup& ConfData::make_simpidx_symmetries() {
    if (!_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "generating simplex-index symmetries ..." << std::endl;
      if (!CommandlineOptions::use_switch_tables() && !valid_symmetries().complete()) {
	SymmetryGroup init_symmetries(valid_symmetries());
	init_symmetries.closure();
	_simpidx_symmetriesptr = new SymmetryGroup(init_symmetries.simpidx_symmetries(rank()));
      }
      else {
	_simpidx_symmetriesptr = new SymmetryGroup(make_valid_symmetries().simpidx_symmetries(rank()));
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_simpidx_symmetriesptr;
  }
  inline const SwitchTable<IntegerSet,lexmin_mode>& ConfData::make_extension_switchtable() {
    if (!_extension_switchtableptr) {
      MessageStreams::verbose() << "generating extension switch table ..." << std::endl;
      _extension_switchtableptr = new SwitchTable<IntegerSet, lexmin_mode>(SimplicialComplex::no_of_simplices(make_chiro().rank()), make_simpidx_symmetries().generators());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_extension_switchtableptr;
  }
  inline const SwitchTable<IntegerSet,colexmax_mode>& ConfData::make_subset_switchtable() {
    if (!_subset_switchtableptr) {
      MessageStreams::verbose() << "generating subset switch table ..." << std::endl;
      _subset_switchtableptr = new SwitchTable<IntegerSet, colexmax_mode>(no(), symmetries().generators());
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_subset_switchtableptr;
  }
  inline const points_simpidx_symmetries_type& ConfData::make_points_simpidx_symmetries() {
    if (!_points_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "generating pairs of point and simplex-index symmetries of all symmetries ..." << std::endl;
      if (symmetries().complete()) {
	_points_simpidx_symmetriesptr = new points_simpidx_symmetries_type(symmetries().points_simpidx_symmetries(make_chiro().rank()));
      }
      else {
	SymmetryGroup init_symmetries(symmetries());
	init_symmetries.closure();
	_points_simpidx_symmetriesptr = new points_simpidx_symmetries_type(init_symmetries.points_simpidx_symmetries(make_chiro().rank()));
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_points_simpidx_symmetriesptr;
  }
  inline const points_simpidx_symmetries_type& ConfData::make_valid_points_simpidx_symmetries() {
    if (!_valid_points_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "generating pairs of point and simplex-index symmetries of valid symmetries ..." << std::endl;
      if (symmetries().complete()) {
	_valid_points_simpidx_symmetriesptr = new points_simpidx_symmetries_type(valid_symmetries().points_simpidx_symmetries(make_chiro().rank()));
      }
      else {
	SymmetryGroup init_symmetries(valid_symmetries());
	init_symmetries.closure();
	_valid_points_simpidx_symmetriesptr = new points_simpidx_symmetries_type(init_symmetries.points_simpidx_symmetries(make_chiro().rank()));
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_valid_points_simpidx_symmetriesptr;
  }
  inline const points_simpidx_symmetries_type& ConfData::make_trivial_points_simpidx_symmetries() {
    if (!_trivial_points_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "generating pairs of point and simplex-index symmetries for trivial group ..." << std::endl;
      _trivial_points_simpidx_symmetriesptr = new points_simpidx_symmetries_type();
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_trivial_points_simpidx_symmetriesptr;
  }
  inline const ClassifiedExtensionSymmetries& ConfData::make_classified_extension_symmetries() {
    if (!_classified_extension_symmetriesptr) {
      if (CommandlineOptions::parallel_symmetries()) {
	MessageStreams::verbose() << "generating classified extension symmetries ..." << std::endl;
	_classified_extension_symmetriesptr = new ClassifiedExtensionSymmetries(ClassifiedExtensionSymmetries::simpidx_mode,
										CommandlineOptions::no_of_threads(),
										admtable().valid_simplices(),
										simpidx_symmetries());
      }
      else {
	_classified_extension_symmetriesptr = new ClassifiedExtensionSymmetries(ClassifiedExtensionSymmetries::simpidx_mode,
										1,
										admtable().valid_simplices(),
										simpidx_symmetries());
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_classified_extension_symmetriesptr;
  }  
  inline const ClassifiedSubsetSymmetries& ConfData::make_classified_subset_symmetries() {
    if (!_classified_subset_symmetriesptr) {
      if (CommandlineOptions::parallel_symmetries()) {
	MessageStreams::verbose() << "generating classified subset symmetries ..." << std::endl;
	_classified_subset_symmetriesptr = new ClassifiedSubsetSymmetries(no(),
									  CommandlineOptions::no_of_symtables(),
									  CommandlineOptions::no_of_threads());
      }
      else {
	_classified_subset_symmetriesptr = new ClassifiedSubsetSymmetries(no(),
									  CommandlineOptions::no_of_symtables(),
									  1);
      }
      MessageStreams::verbose() << "... done." << std::endl;
    }
    return *_classified_subset_symmetriesptr;
  }
  
  // remove data:
  inline void ConfData::remove_placingtriang() {
    if (_placingtriangptr) {
      MessageStreams::verbose() << "removing placingtriang ..." << std::endl;
      delete _placingtriangptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_circuits() {
    if (_circuitsptr) {
      MessageStreams::verbose() << "removing circuits ..." << std::endl;
      delete _circuitsptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_cocircuits() {
    if (_cocircuitsptr) {
      MessageStreams::verbose() << "removing cocircuits ..." << std::endl;
      delete _cocircuitsptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_poscocircuits() {
    if (_poscocircuitsptr) {
      MessageStreams::verbose() << "removing positive cocircuits ..." << std::endl;
      delete _poscocircuitsptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_facets() {
    if (_facetsptr) {
      MessageStreams::verbose() << "removing facets ..." << std::endl;
      delete _facetsptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_inctable() {
    if (_inctableptr) {
      MessageStreams::verbose() << "removing incidences table ..." << std::endl;
      delete _inctableptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_admtable() {
    if (_admtableptr) {
      MessageStreams::verbose() << "removing admissibles table ..." << std::endl;
      delete _admtableptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_voltable() {
    if (_voltableptr) {
      MessageStreams::verbose() << "removing volumes table ..." << std::endl;
      delete _voltableptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_volume() {
    if (_volumeptr) {
      MessageStreams::verbose() << "removing volume ..." << std::endl;
      delete _volumeptr;
      MessageStreams::verbose() << "... done." << std::endl;
   }
  }
  inline void ConfData::remove_valid_symmetries() {
    if (_valid_symmetriesptr != _symmetriesptr) {
      MessageStreams::verbose() << "removing valid symmetries ..." << std::endl;
      delete _valid_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_trivial_symmetries() {
    if (_trivial_symmetriesptr) {
      MessageStreams::verbose() << "removing trivial symmetries ..." << std::endl;
      delete _trivial_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_simpidx_symmetries() {
    if (_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "removing simplex-index symmetries ..." << std::endl;
      delete _simpidx_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_extension_switchtable() {
    if (_extension_switchtableptr) {
      MessageStreams::verbose() << "removing extension switch table ..." << std::endl;
      delete _extension_switchtableptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_subset_switchtable() {
    if (_subset_switchtableptr) {
      MessageStreams::verbose() << "removing subset switch table ..." << std::endl;
      delete _subset_switchtableptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_points_simpidx_symmetries() {
    if (_points_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "removing pairs of point and simplex-index symmetries of all symmetries ..." << std::endl;
      delete _points_simpidx_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_valid_points_simpidx_symmetries() {
    if (_valid_points_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "removing pairs of point and simplex-index symmetries of valid symmetries ..." << std::endl;
      delete _valid_points_simpidx_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_trivial_points_simpidx_symmetries() {
    if (_trivial_points_simpidx_symmetriesptr) {
      MessageStreams::verbose() << "removing pairs of point and simplex-index symmetries of empty symmetries ..." << std::endl;
      delete _trivial_points_simpidx_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_classified_extension_symmetries() {
    if (_classified_extension_symmetriesptr) {
      MessageStreams::verbose() << "removing classified extension symmetries ..." << std::endl;
      delete _classified_extension_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }
  inline void ConfData::remove_classified_subset_symmetries() {
    if (_classified_subset_symmetriesptr) {
      MessageStreams::verbose() << "removing classified subset symmetries ..." << std::endl;
      delete _classified_subset_symmetriesptr;
      MessageStreams::verbose() << "... done." << std::endl;
    }
  }

  // comparison operator means identical pointers:
  inline bool ConfData::operator==(const ConfData& cd) const {
    return ((_pointsptr == cd._pointsptr)
	    && (_chiroptr == cd._chiroptr)
	    && (_symmetriesptr == cd._symmetriesptr)
	    && (_required_symmetriesptr == cd._required_symmetriesptr)
	    && (_seedptr == cd._seedptr)
	    && (_placingtriangptr == cd._placingtriangptr)
	    && (_circuitsptr == cd._circuitsptr)
	    && (_cocircuitsptr == cd._cocircuitsptr)
	    && (_poscocircuitsptr == cd._poscocircuitsptr)
	    && (_facetsptr == cd._facetsptr)
	    && (_inctableptr == cd._inctableptr)
	    && (_admtableptr == cd._admtableptr)
	    && (_voltableptr == cd._voltableptr)
	    && (_volumeptr == cd._volumeptr)
	    && (_seed_symmetryptrsptr == cd._seed_symmetryptrsptr)
	    && (_valid_symmetriesptr == cd._valid_symmetriesptr)
	    && (_trivial_symmetriesptr == cd._trivial_symmetriesptr)
	    && (_simpidx_symmetriesptr == cd._simpidx_symmetriesptr)
	    && (_extension_switchtableptr == cd._extension_switchtableptr)
	    && (_subset_switchtableptr == cd._subset_switchtableptr)
	    && (_points_simpidx_symmetriesptr == cd._points_simpidx_symmetriesptr)
	    && (_valid_points_simpidx_symmetriesptr == cd._valid_points_simpidx_symmetriesptr)
	    && (_trivial_points_simpidx_symmetriesptr == cd._trivial_points_simpidx_symmetriesptr)
	    && (_classified_extension_symmetriesptr == cd._classified_extension_symmetriesptr)
	    && (_classified_subset_symmetriesptr == cd._classified_subset_symmetriesptr));
  }

  inline const Vector ConfData::gkz(const SimplicialComplex& triang) const {
    if (!has_points()) {
      MessageStreams::forced() << message::lock
			       << "ConfData::gkz(const SimplicialComplex& triang): no points available for gkz computation - exiting." << std::endl
			       << message::unlock;
      exit(1);
    }
    Vector result(no(), FieldConstants::ZERO);
    if (has_voltable()) {

      // with voltable, the computation is faster:
      for (SimplicialComplex::const_iterator sciter = triang.begin();
	   sciter != triang.end();
	   ++sciter) {
	Field simpvol = voltable().find(*sciter)->second;
	for (Simplex::const_iterator simpiter = sciter->begin();
	     simpiter != sciter->end();
	     ++simpiter) {
	  result.at(*simpiter) += simpvol;
	}
      }
      return result;
    }
    else if (has_chiro()) {

      // first fall-back solution: compute each simplex volume from chirotope determinants:
      for (SimplicialComplex::const_iterator sciter = triang.begin();
	   sciter != triang.end();
	   ++sciter) {
	Field simpvol = abs(chiro().det(*sciter));
	for (Simplex::const_iterator simpiter = sciter->begin();
	     simpiter != sciter->end();
	     ++simpiter) {
	  result.at(*simpiter) += simpvol;
	}
      }
      return result;      
    }
    else {

      // fall-back solution: compute each simplex volume from scratch:
      for (SimplicialComplex::const_iterator sciter = triang.begin();
	   sciter != triang.end();
	   ++sciter) {
	Field simpvol = points().volume(*sciter);
	for (Simplex::const_iterator simpiter = sciter->begin();
	     simpiter != sciter->end();
	     ++simpiter) {
	  result.at(*simpiter) += simpvol;
	}
      }
      return result;      
    }
  }

  inline std::ostream& operator<<(std::ostream& ost, const ConfData& cd) {
    return cd.write(ost);
  }
  
  inline std::istream& operator>>(std::istream& ist, ConfData& cd) {
    return cd.read(ist);
  }

}; // namespace topcom

#endif

// eof ConfData.hh
