/***************************************************************************
                          kstvector.h  -  description
                             -------------------
    begin                : Fri Sep 22 2000
    copyright            : (C) 2000 by cbn
    email                :
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef KSTVECTOR_H
#define KSTVECTOR_H

#include <math.h>
#include <qdict.h>
#include <qguardedptr.h>
#include "kstscalar.h"

#define IS_POINT(x) (!isnan(x))
#define NOT_POINT(x) (isnan(x))

namespace KST {
  // Do not compare against this, only assign it and use the helpers above.
  extern double NOPOINT;
}

namespace Equation {
  class Node;
}

/**A class for handling data vectors for kst.
 *@author cbn
 */

class KstVector;
typedef KstSharedPtr<KstVector> KstVectorPtr;
  
class KstVector : public KstObject {
  Q_OBJECT
  public:
    /**
     * Vectors automatically add themselves to the global vector collection
     */
    KstVector(const QString& name = QString::null, int size = 0, bool bIsScalarList = false);

    virtual ~KstVector();

  public slots:
    virtual int length() const;
    
    /** Return V[i], interpolated/decimated to have ns_i total samples */
    double interpolate(int i, int ns_i);

    /** Return V[i] uninterpolated */
    double value(int i);

    /** Return Minimum value in Vector */
    double min() const;

    /** Return max value in Vector */
    double max() const;

    /** Return SpikeInsensitive max value in vector **/
    double ns_max() const { return _ns_max; }

    /** Return SpikeInsensitive min value in vector **/
    double ns_min() const { return _ns_min; }

    /** Return Mean value in Vector */
    double mean() const;

    /** Return Least Positive value in Vector */
    double minPos() const;

    /** Return number of samples in the vector */
    int sampleCount() const;

    /** Number of new samples in the vector since last newSync */
    int numNew() const;

    /** Number of samples  shifted since last newSync */
    int numShift() const;

    bool isRising() const { return _is_rising; }

    /** reset New Samples and Shifted samples */
    void newSync();

    /** return a sensible label for this vector */
    virtual QString label() const;

    /** return a sensible top label.... */
    virtual QString fileLabel() const;

    virtual bool resize(int sz, bool reinit = true);

    virtual void setNewAndShift(int inNew, int inShift);

    /** Clear out the vector */
    void zero();

    /* Generally you don't need to call this */
    void updateScalars();

    // Must not be a KstObjectPtr!
    virtual void setProvider(KstObject* obj);

  public:
    /** Save vector information */
    virtual void save(QTextStream &ts, const QString& indent = QString::null, bool saveAbsolutePosition = false);

    /** Update the vector.  Return true if there was new data. */
    virtual UpdateType update(int update_counter = -1);

    /** Generate a new vector [x0..x1] with n total points */
    static KstVectorPtr generateVector(double x0, double x1, int n, const QString& tag);

    virtual void setTagName(const QString& newTag);

    /** Return a pointer to the raw vector */
    double *const value() const;

    /** access functions for _isScalarList */
    bool isScalarList() const { return _isScalarList; }
    
    KstObjectPtr provider() const { return KstObjectPtr(_provider); }

    virtual bool deleteDependents();

  protected: // Protected attributes
    /** current number of samples */
    int _size;

    /** number of valid points */
    int _nsum;

    /** variables for SpikeInsensitiveAutoscale **/
    double _ns_max;
    double _ns_min;

    /** Where the vector is held */
    double *_v;

    /** number of samples shifted since last newSync */
    int NumShifted;

    /** number of new samples since last newSync */
    int NumNew;

    /** Statistics Scalars */
    QDict<KstScalar> _scalars;

    /** is the vector monotonically rising */
    bool _is_rising : 1;

    /** if true then we have a scalar list and do not want to be able to
    use it in a curve, display statistics for it, etc. */
    bool _isScalarList : 1;

    /** Possibly null.  Be careful, this is non-standard usage of a KstShared.
     * The purpose of this is to trigger hierarchical updates properly.
     */
    QGuardedPtr<KstObject> _provider;

    /** Scalar Maintenance methods */
    void CreateScalars();
    void RenameScalars();

  protected:
    friend class KstDataObject;
    virtual double* realloced(double *memptr, int newSize, bool bNew = false);
};

typedef KstObjectList<KstVectorPtr> KstVectorList;
typedef KstObjectMap<KstVectorPtr> KstVectorMap;

#endif
// vim: ts=2 sw=2 et
