Indexer.h 3.08 KB
Newer Older
gsell's avatar
gsell committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
#ifndef OPAL_Indexer_HH
#define OPAL_Indexer_HH

// ------------------------------------------------------------------------
// $RCSfile: Indexer.h,v $
// ------------------------------------------------------------------------
// $Revision: 1.3 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
//
// Template class: Indexer<T>
//
// ------------------------------------------------------------------------
//
// $Date: 2002/01/17 22:18:36 $
// $Author: jsberg $
//
// ------------------------------------------------------------------------

#include "AbstractObjects/Expressions.h"
#include "Utilities/CLRangeError.h"
#include "Utilities/OpalException.h"
#include "Utilities/Round.h"
#include <cerrno>
#include <iosfwd>
#include <vector>


namespace Expressions {

    // Template class Indexer
    // ----------------------------------------------------------------------
    /// A scalar expression to retrieve an indexed component from an array.
    //  This expression first evaluates the array operand expression and the
    //  scalar index expression.  Then it applies the index to the array and
    //  returns the selected component.

    template <class T>
    class Indexer: public Scalar<T> {

    public:

        /// Constructor.
        //  Use array expression and index into the array.
        Indexer(PtrToArray<T> array, PtrToScalar<double> index);

        Indexer(const Indexer<T> &);
        virtual ~Indexer();

        /// Make clone.
        virtual Scalar<T> *clone() const;

        /// Evaluate.
        virtual T evaluate() const;

        /// Print expression.
        virtual void print(std::ostream &str, int precedence = 99) const;

    private:

        // Not implemented.
        Indexer();
        void operator=(const Indexer &);

        // The two operands.
        PtrToArray<T> lft;
        PtrToScalar<double> rgt;
    };


    // Implementation
    // ----------------------------------------------------------------------

    template <class T> inline
    Indexer<T>::Indexer(const Indexer &rhs):
        lft(rhs.lft->clone()), rgt(rhs.rgt->clone())
    {}


    template <class T> inline
    Indexer<T>::Indexer(PtrToArray<T> left, PtrToScalar<double> right):
        lft(left), rgt(right)
    {}


    template <class T> inline
    Indexer<T>::~Indexer()
    {}


    template <class T> inline
    Scalar<T> *Indexer<T>::clone() const {
        return new Indexer<T>(*this);
    }


    template <class T> inline
    T Indexer<T>::evaluate() const {
        std::vector<T> op1 = lft->evaluate();
        int op2 = int(Round(rgt->evaluate()));

        if(op2 <= 0 || static_cast<unsigned>(op2) > op1.size()) {
            throw CLRangeError("Expressions::Indexer()", "Index out of range.");
        }

        return op1[op2-1];
    }


    template <class T> inline
    void Indexer<T>::print(std::ostream &os, int precedence) const {
        lft->print(os, 0);
        os << '[';
        rgt->print(os, 0);
        os << ']';
    }

}

#endif // OPAL_Indexer_HH