Skip to content
Snippets Groups Projects
Select Git revision
  • 39e1ffd645e18fbbd32cc33ab95406698ae29b0c
  • master default protected
  • tut_ring_allen
  • docs_furo
  • docs_reorder_cable_cell
  • docs_graphviz
  • docs_rtd_dev
  • ebrains_mirror
  • doc_recat
  • docs_spike_source
  • docs_sim_sample_clar
  • docs_pip_warn
  • github_template_updates
  • docs_fix_link
  • cv_default_and_doc_clarification
  • docs_add_numpy_req
  • readme_zenodo_05
  • install_python_fix
  • install_require_numpy
  • typofix_propetries
  • docs_recipe_lookup
  • v0.10.0
  • v0.10.1
  • v0.10.0-rc5
  • v0.10.0-rc4
  • v0.10.0-rc3
  • v0.10.0-rc2
  • v0.10.0-rc
  • v0.9.0
  • v0.9.0-rc
  • v0.8.1
  • v0.8
  • v0.8-rc
  • v0.7
  • v0.6
  • v0.5.2
  • v0.5.1
  • v0.5
  • v0.4
  • v0.3
  • v0.2.2
41 results

expressionclassifier.hpp

Blame
  • Ben Cumming's avatar
    Benjamin Cumming authored
    * update the out of date version of modparser was added to the repository
    * fix some warnings about unused static functions in a modcc test header
    * move modcc/src path contents to modcc, because there was little point having
      the additional sub directory.
    dfc43806
    History
    expressionclassifier.hpp 3.43 KiB
    #pragma once
    
    #include <mutex>
    
    #include "constantfolder.hpp"
    #include "scope.hpp"
    #include "visitor.hpp"
    
    enum class expressionClassification {
        constant,
        linear,
        nonlinear
    };
    
    class ExpressionClassifierVisitor : public Visitor {
    public:
        ExpressionClassifierVisitor(Symbol *s)
        : symbol_(s)
        {
            const_folder_ = new ConstantFolderVisitor();
        }
    
        void reset(Symbol* s) {
            reset();
            symbol_ = s;
        }
    
        void reset() {
            is_linear_    = true;
            found_symbol_ = false;
            configured_   = false;
            coefficient_  = nullptr;
            constant_     = nullptr;
        }
    
        void visit(Expression *e)           override;
        void visit(UnaryExpression *e)      override;
        void visit(BinaryExpression *e)     override;
        void visit(NumberExpression *e)     override;
        void visit(IdentifierExpression *e) override;
        void visit(CallExpression *e)       override;
    
        expressionClassification classify() const {
            if(!found_symbol_) {
                return expressionClassification::constant;
            }
            if(is_linear_) {
                return expressionClassification::linear;
            }
            return expressionClassification::nonlinear;
        }
    
        Expression *linear_coefficient() {
            set();
            return coefficient_.get();
        }
    
        Expression *constant_term() {
            set();
            return constant_.get();
        }
    
        ~ExpressionClassifierVisitor() {
            delete const_folder_;
        }
    
    private:
    
        void set() const {
            // a mutex is required because two threads might attempt to update
            // the cached constant_/coefficient_ values, which would violate the
            // condition that set() is const
            std::lock_guard<std::mutex> g(mutex_);
    
            // update the constant_ and coefficient_ terms if they have not already
            // been set
            if(!configured_) {
                if(classify() == expressionClassification::linear) {
                    // if constat_ was never set, it must be zero
                    if(!constant_) {
                        constant_ =
                            make_expression<NumberExpression>(Location(), 0.);
                    }
                    // perform constant folding on the coefficient term
                    coefficient_->accept(const_folder_);
                    if(const_folder_->is_number) {
                        // if the folding resulted in a constant, reset coefficient
                        // to be a NumberExpression
                        coefficient_.reset(new NumberExpression(
                                                Location(),
                                                const_folder_->value)
                                          );
                    }
                }
                else if(classify() == expressionClassification::constant) {
                    coefficient_.reset(new NumberExpression(
                                            Location(),
                                            0.)
                                      );
                }
                else { // nonlinear expression
                    coefficient_ = nullptr;
                    constant_    = nullptr;
                }
                configured_ = true;
            }
        }
    
        // assume linear until otherwise proven
        bool is_linear_     = true;
        bool found_symbol_  = false;
        mutable bool configured_    = false;
        mutable expression_ptr coefficient_;
        mutable expression_ptr constant_;
        Symbol* symbol_;
        ConstantFolderVisitor* const_folder_;
    
        mutable std::mutex mutex_;
    
    };