ASUnary.h 4.74 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
#ifndef OPAL_ASUnary_HH
#define OPAL_ASUnary_HH 1

// ------------------------------------------------------------------------
// $RCSfile: ASUnary.h,v $
// ------------------------------------------------------------------------
// $Revision: 1.1.1.1 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
//
// Template class: ASUnary<T>
//
// ------------------------------------------------------------------------
//
// $Date: 2000/03/27 09:33:41 $
// $Author: Andreas Adelmann $
//
// ------------------------------------------------------------------------

#include "AbstractObjects/Expressions.h"
#include "Expressions/SConstant.h"
#include "Expressions/TFunction1.h"
#include "Utilities/DomainError.h"
#include "Utilities/OverflowError.h"
#include <cerrno>
#include <iosfwd>
#include <vector>


namespace Expressions {

    // Template Class ASUnary
    // ----------------------------------------------------------------------
    /// A scalar expression with one array operand.
    //  This expression first evaluates its operand to get an array.
    //  The scalar result is computed then by applying a scalar-valued
    //  function to this array (e. g. minimum or maximum).

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

    public:

        /// Constructor.
        //  Use a function which maps a std::vector<T> to a T and an array
        //  expression.
        ASUnary(const TFunction1<T, const std::vector<T>&> &function,
                PtrToArray<T> &oper);

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

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

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

        /// Make new expression.
        //  If all component of the argument are constant, then evaluate
        //  and store the result as a constant.
        static PtrToScalar<T> make
        (const TFunction1<T, const std::vector<T>&> &function, PtrToArray<T> &oper);

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

    private:

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

        // The operation object.
        const TFunction1<T, const std::vector<T>&> &fun;

        // The operand.
        PtrToArray<T> opr;
    };


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

    template <class T> inline
    ASUnary<T>::ASUnary(const ASUnary<T> &rhs):
88
        Scalar<T>(rhs),
gsell's avatar
gsell committed
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
        fun(rhs.fun), opr(rhs.opr->clone())
    {}


    template <class T> inline
    ASUnary<T>::ASUnary(const TFunction1<T, const std::vector<T>&> &function,
                        PtrToArray<T> &oper):
        fun(function), opr(oper)
    {}


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


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


    template <class T> inline
    T ASUnary<T>::evaluate() const {
        errno = 0;
        const std::vector<T> arg = opr->evaluate();
        T result = (*fun.function)(arg);

        // Test for run-time evaluation errors.
        switch(errno) {

            case EDOM:
                throw DomainError("ASUnary::evaluate()");

            case ERANGE:
                // Ignore underflow.
                if(result == T(0)) return result;
                throw OverflowError("ASUnary::evaluate()");

            default:
                ;
        }

        return result;
    }


    template <class T> inline
    PtrToScalar<T> ASUnary<T>::make
    (const TFunction1<T, const std::vector<T>&> &function, PtrToArray<T> &oper) {
        // We must pick up the constant flag before the ownership of "oper"
        // is transferred to "result".
        bool isConst = oper->isConstant();
        PtrToScalar<T> result = new ASUnary<T>(function, oper);

        if(function.precedence != -2) {
            // Not a random expression.
            if(isConst) {
                // Replace constant expression by its value.
                result = new SConstant<T>(result->evaluate());
            }
        }

        // Other expression.
        return result.release();
    }


    template <class T> inline
    void ASUnary<T>::print(std::ostream &os, int precedence) const {
        if(fun.precedence >= 0) {
            if(fun.precedence <= precedence) os << "(";
            os << fun.name;
            opr->print(os, fun.precedence);
            if(fun.precedence <= precedence) os << ")";
        } else {
            os << fun.name << "(";
            opr->print(os, 0);
            os << ")";
        }
    }

}

#endif // OPAL_ASUnary_HH