<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/util/timer.h>

namespace inviwo {

Timer::Timer(duration_t interval, std::function<void()> callback)
    : callback_{std::make_shared<std::function<void()>>(std::move(callback))}
    , interval_{interval}
    , enabled_{false} {}

Timer::Timer(size_t interval, std::function<void()> callback)
    : Timer(std::chrono::milliseconds(interval), std::move(callback)) {}

Timer::~Timer() { stop(); }

void Timer::start(size_t interval) {
    start(std::chrono::milliseconds(interval));
}

void Timer::start(duration_t interval) {
    interval_ = interval;
    start();
}

void Timer::start() {
    if (!enabled_) {
        enabled_ = true;
        thread_ = std::thread(&Timer::timer, this);
    }
}

void Timer::stop() {
    if (enabled_) {
        {
            std::lock_guard<std::mutex> _{mutex_};
            enabled_ = false;
        }
        cvar_.notify_one();
        thread_.join();
    }
}

void Timer::timer() {
    auto deadline = std::chrono::steady_clock::now() + interval_;
    std::unique_lock<std::mutex> lock{mutex_};
    while (enabled_) {
        if (cvar_.wait_until(lock, deadline) == std::cv_status::timeout) {
            lock.unlock();

            // skip if previous not done.
            if (!result_.valid() ||
                result_.wait_for(std::chrono::duration<int, std::milli>(0)) ==
                    std::future_status::ready) {
                auto tmp = callback_;
                result_ = dispatchFront([tmp]() { (*tmp)(); });
            }
            deadline += interval_;
            lock.lock();
        }
    }
}

Delay::Delay(duration_t interval, std::function<void()> callback)
    : callback_{std::make_shared<std::function<void()>>(std::move(callback))}
    , interval_{interval}
    , enabled_{false} {}

Delay::Delay(size_t interval, std::function<void()> callback)
    : Delay(std::chrono::milliseconds(interval), std::move(callback)) {}

Delay::~Delay() { stop(); }

void Delay::start() {
    if (!enabled_) {
        enabled_ = true;
        thread_ = std::thread(&Delay::delay, this);
    }
}

void Delay::stop() {
    if (enabled_) {
        {
            std::lock_guard<std::mutex> _{mutex_};
            enabled_ = false;
        }
        cvar_.notify_one();
        thread_.join();
    }
}

void Delay::delay() {
    auto deadline = std::chrono::steady_clock::now() + interval_;
    std::unique_lock<std::mutex> lock{mutex_};
    while (enabled_) {
        if (cvar_.wait_until(lock, deadline) == std::cv_status::timeout) {
            lock.unlock();
            auto tmp = callback_;
            dispatchFront([tmp]() { (*tmp)(); });

            lock.lock();
            enabled_ = false;
        }
    }
}

}  // namespace inviwo
<commit_msg>Core: Make sure that callbacks are not executed after calling stop() on a Timer. Flushes the cue, temporary solution for ticket inviwo/inviwo-dev#927.<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/util/timer.h>

namespace inviwo {

Timer::Timer(duration_t interval, std::function<void()> callback)
    : callback_{std::make_shared<std::function<void()>>(std::move(callback))}
    , interval_{interval}
    , enabled_{false} {}

Timer::Timer(size_t interval, std::function<void()> callback)
    : Timer(std::chrono::milliseconds(interval), std::move(callback)) {}

Timer::~Timer() { stop(); }

void Timer::start(size_t interval) {
    start(std::chrono::milliseconds(interval));
}

void Timer::start(duration_t interval) {
    interval_ = interval;
    start();
}

void Timer::start() {
    if (!enabled_) {
        enabled_ = true;
        thread_ = std::thread(&Timer::timer, this);
    }
}

void Timer::stop() {
    if (enabled_) {
        {
            std::lock_guard<std::mutex> _{mutex_};
            enabled_ = false;
        }
        cvar_.notify_one();
        thread_.join();
        // FIXME: Temporary solution for ticket #927
        // Flush the cue so that callbacks in the cue are not called after stop() has been called.
        // A better solution would be to remove cued callbacks.
        InviwoApplication::getPtr()->processFront();
    }
}

void Timer::timer() {
    auto deadline = std::chrono::steady_clock::now() + interval_;
    std::unique_lock<std::mutex> lock{mutex_};
    while (enabled_) {
        if (cvar_.wait_until(lock, deadline) == std::cv_status::timeout) {
            lock.unlock();

            // skip if previous not done.
            if (!result_.valid() ||
                result_.wait_for(std::chrono::duration<int, std::milli>(0)) ==
                    std::future_status::ready) {
                auto tmp = callback_;
                result_ = dispatchFront([tmp]() { (*tmp)(); });
            }
            deadline += interval_;
            lock.lock();
        }
    }
}

Delay::Delay(duration_t interval, std::function<void()> callback)
    : callback_{std::make_shared<std::function<void()>>(std::move(callback))}
    , interval_{interval}
    , enabled_{false} {}

Delay::Delay(size_t interval, std::function<void()> callback)
    : Delay(std::chrono::milliseconds(interval), std::move(callback)) {}

Delay::~Delay() { stop(); }

void Delay::start() {
    if (!enabled_) {
        enabled_ = true;
        thread_ = std::thread(&Delay::delay, this);
    }
}

void Delay::stop() {
    if (enabled_) {
        {
            std::lock_guard<std::mutex> _{mutex_};
            enabled_ = false;
        }
        cvar_.notify_one();
        thread_.join();
    }
}

void Delay::delay() {
    auto deadline = std::chrono::steady_clock::now() + interval_;
    std::unique_lock<std::mutex> lock{mutex_};
    while (enabled_) {
        if (cvar_.wait_until(lock, deadline) == std::cv_status::timeout) {
            lock.unlock();
            auto tmp = callback_;
            dispatchFront([tmp]() { (*tmp)(); });

            lock.lock();
            enabled_ = false;
        }
    }
}

}  // namespace inviwo
<|endoftext|>


<commit_before>
#pragma once

#include <vector>

#include "nifty/graph/optimization/common/proposal_generators/proposal_generator_base.hxx"
#include "nifty/graph/edge_weighted_watersheds.hxx"

namespace nifty{
namespace graph{
namespace optimization{
namespace common{

    /**
     * @brief      Watershed proposal generator for lifted_multicut::FusionMoveBased
     *
     * @tparam     OBJECTIVE  { description }
     */
    template<class OBJECTIVE>
    class WatershedProposalGenerator :
        public ProposalGeneratorBase<OBJECTIVE>{
    public:
        typedef OBJECTIVE ObjectiveType;
        typedef typename ObjectiveType::GraphType GraphType;
        typedef typename GraphType:: template NodeMap<uint64_t>  ProposalType;
        typedef typename GraphType:: template EdgeMap<float>       EdgeWeights;

        struct Settings{

            enum SeedingStrategie{
                SEED_FROM_NEGATIVE,
                SEED_FROM_ALL
            };

            SeedingStrategie seedingStrategie{SEED_FROM_NEGATIVE};
            double sigma{1.0};
            double numberOfSeeds{0.1};
        };

        WatershedProposalGenerator(
            const ObjectiveType & objective,
            const size_t numberOfThreads,
            const Settings & settings  = Settings()
        )
        :   objective_(objective),
            numberOfThreads_(numberOfThreads),
            settings_(settings),
            negativeEdges_(),
            seeds_(objective.graph()),
            noisyEdgeWeights_(objective.graph()),
            gens_(numberOfThreads_),
            dist_(0.0, settings.sigma),
            intDist_()
        {
            // use thread index as seed
            for(auto i=0; i<numberOfThreads_; ++i)
                gens_[i] = std::mt19937(i);

            this->reset();
        }

        void reset(){
            const auto & weights = objective_.weights();

            if(settings_.seedingStrategie == Settings::SEED_FROM_NEGATIVE){
                objective_.graph().forEachEdge([&](const uint64_t edge){
                    if(weights[edge] < 0.0){
                        negativeEdges_.push_back(edge);
                    }
                });
            }

            if(!negativeEdges_.empty())
                intDist_ = std::uniform_int_distribution<> (0, negativeEdges_.size()-1);
            else{
                // fallback to not crash, but meaningless since there are no negative edges
                intDist_ = std::uniform_int_distribution<> (0, 1);
            }
        }

        virtual ~WatershedProposalGenerator(){}

        virtual void generateProposal(
            const ProposalType & currentBest,
            ProposalType & proposal,
            const size_t tid
        ){

            if(negativeEdges_.empty()){
                // do nothing
            }
            else{

                const auto & graph = objective_.graph();

                auto & gen = gens_[tid];

                for(const auto node: graph.nodes()){
                    seeds_[node] = 0;
                }

                auto nSeeds = settings_.numberOfSeeds <=1.0 ?
                    size_t(float(graph.numberOfNodes())*settings_.numberOfSeeds+0.5f) :
                    size_t(settings_.numberOfSeeds + 0.5);

                nSeeds = std::max(size_t(1),nSeeds);
                nSeeds = std::min(size_t(negativeEdges_.size()-1), nSeeds);

                const auto & weights = objective_.weights();
                graph.forEachEdge([&](const uint64_t edge){
                    noisyEdgeWeights_[edge] = weights[edge] + dist_(gen);
                });

                for(size_t i=0; i <  (nSeeds == 1 ? 1 : nSeeds/2); ++i){
                    const auto randIndex = intDist_(gen);
                    const auto edge  = negativeEdges_[randIndex];
                    const auto uv = graph.uv(edge);

                    seeds_[uv.first] = (2*i)+1;
                    seeds_[uv.second] = (2*i+1)+1;
                }

                edgeWeightedWatershedsSegmentation(graph, noisyEdgeWeights_, seeds_, proposal);

            }

        }
    private:
        const ObjectiveType & objective_;
        size_t numberOfThreads_;
        Settings settings_;
        std::vector<uint64_t> negativeEdges_;
        EdgeWeights noisyEdgeWeights_;
        ProposalType  seeds_;

        std::vector<std::mt19937> gens_;
        std::normal_distribution<> dist_;
        std::uniform_int_distribution<>  intDist_;

    };

}
}
}
}

<commit_msg>fixed missing header<commit_after>
#pragma once

#include <string>
#include <random>
#include <vector>

#include "nifty/graph/optimization/common/proposal_generators/proposal_generator_base.hxx"
#include "nifty/graph/edge_weighted_watersheds.hxx"

namespace nifty{
namespace graph{
namespace optimization{
namespace common{

    /**
     * @brief      Watershed proposal generator for lifted_multicut::FusionMoveBased
     *
     * @tparam     OBJECTIVE  { description }
     */
    template<class OBJECTIVE>
    class WatershedProposalGenerator :
        public ProposalGeneratorBase<OBJECTIVE>{
    public:
        typedef OBJECTIVE ObjectiveType;
        typedef typename ObjectiveType::GraphType GraphType;
        typedef typename GraphType:: template NodeMap<uint64_t>  ProposalType;
        typedef typename GraphType:: template EdgeMap<float>       EdgeWeights;

        struct Settings{

            enum SeedingStrategie{
                SEED_FROM_NEGATIVE,
                SEED_FROM_ALL
            };

            SeedingStrategie seedingStrategie{SEED_FROM_NEGATIVE};
            double sigma{1.0};
            double numberOfSeeds{0.1};
        };

        WatershedProposalGenerator(
            const ObjectiveType & objective,
            const size_t numberOfThreads,
            const Settings & settings  = Settings()
        )
        :   objective_(objective),
            numberOfThreads_(numberOfThreads),
            settings_(settings),
            negativeEdges_(),
            seeds_(objective.graph()),
            noisyEdgeWeights_(objective.graph()),
            gens_(numberOfThreads_),
            dist_(0.0, settings.sigma),
            intDist_()
        {
            // use thread index as seed
            for(auto i=0; i<numberOfThreads_; ++i)
                gens_[i] = std::mt19937(i);

            this->reset();
        }

        void reset(){
            const auto & weights = objective_.weights();

            if(settings_.seedingStrategie == Settings::SEED_FROM_NEGATIVE){
                objective_.graph().forEachEdge([&](const uint64_t edge){
                    if(weights[edge] < 0.0){
                        negativeEdges_.push_back(edge);
                    }
                });
            }

            if(!negativeEdges_.empty())
                intDist_ = std::uniform_int_distribution<> (0, negativeEdges_.size()-1);
            else{
                // fallback to not crash, but meaningless since there are no negative edges
                intDist_ = std::uniform_int_distribution<> (0, 1);
            }
        }

        virtual ~WatershedProposalGenerator(){}

        virtual void generateProposal(
            const ProposalType & currentBest,
            ProposalType & proposal,
            const size_t tid
        ){

            if(negativeEdges_.empty()){
                // do nothing
            }
            else{

                const auto & graph = objective_.graph();

                auto & gen = gens_[tid];

                for(const auto node: graph.nodes()){
                    seeds_[node] = 0;
                }

                auto nSeeds = settings_.numberOfSeeds <=1.0 ?
                    size_t(float(graph.numberOfNodes())*settings_.numberOfSeeds+0.5f) :
                    size_t(settings_.numberOfSeeds + 0.5);

                nSeeds = std::max(size_t(1),nSeeds);
                nSeeds = std::min(size_t(negativeEdges_.size()-1), nSeeds);

                const auto & weights = objective_.weights();
                graph.forEachEdge([&](const uint64_t edge){
                    noisyEdgeWeights_[edge] = weights[edge] + dist_(gen);
                });

                for(size_t i=0; i <  (nSeeds == 1 ? 1 : nSeeds/2); ++i){
                    const auto randIndex = intDist_(gen);
                    const auto edge  = negativeEdges_[randIndex];
                    const auto uv = graph.uv(edge);

                    seeds_[uv.first] = (2*i)+1;
                    seeds_[uv.second] = (2*i+1)+1;
                }

                edgeWeightedWatershedsSegmentation(graph, noisyEdgeWeights_, seeds_, proposal);

            }

        }
    private:
        const ObjectiveType & objective_;
        size_t numberOfThreads_;
        Settings settings_;
        std::vector<uint64_t> negativeEdges_;
        EdgeWeights noisyEdgeWeights_;
        ProposalType  seeds_;

        std::vector<std::mt19937> gens_;
        std::normal_distribution<> dist_;
        std::uniform_int_distribution<>  intDist_;

    };

}
}
}
}

<|endoftext|>


<commit_before>// @(#)root/gui:$Name:  $:$Id: TGToolBar.cxx,v 1.9 2003/11/28 12:09:51 brun Exp $
// Author: Fons Rademakers   25/02/98

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.

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

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGToolBar                                                            //
//                                                                      //
// A toolbar is a composite frame that contains TGPictureButtons.       //
// Often used in combination with a TGHorizontal3DLine.                 //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGToolBar.h"
#include "TList.h"
#include "TGButton.h"
#include "TGPicture.h"
#include "TGPicture.h"
#include "TGToolTip.h"
#include "TSystem.h"
#include "TROOT.h"
#include "Riostream.h"

ClassImp(TGToolBar)

//______________________________________________________________________________
TGToolBar::TGToolBar(const TGWindow *p, UInt_t w, UInt_t h,
                     UInt_t options, ULong_t back) :
   TGCompositeFrame(p, w, h, options, back)
{
   // Create toolbar widget.

   fPictures = new TList;
   fTrash    = new TList;
}

//______________________________________________________________________________
TGToolBar::~TGToolBar()
{
   // Delete toolbar and its buttons and layout hints.

   if (fTrash) fTrash->Delete();
   delete fTrash;

   TIter next(fPictures);
   const TGPicture *p;
   while ((p = (const TGPicture *) next()))
      fClient->FreePicture(p);

   delete fPictures;
}

//______________________________________________________________________________
void TGToolBar::AddButton(const TGWindow *w, ToolBarData_t *button, Int_t spacing)
{
   // Add button to toolbar. All buttons added via this method will be
   // deleted by the toolbar. On return the TGButton field of the
   // ToolBarData_t struct is filled in (iff fPixmap was valid).
   // Window w is the window to which the button messages will be send.

   const TGPicture *pic = fClient->GetPicture(button->fPixmap);
   if (!pic) {
      Error("AddButton", "pixmap not found: %s", button->fPixmap);
      return;
   }
   fPictures->Add((TObject*)pic);

   TGPictureButton *pbut;
   TGLayoutHints   *layout;

   pbut = new TGPictureButton(this, pic, button->fId);
   pbut->SetToolTipText(button->fTipText);

   layout = new TGLayoutHints(kLHintsTop | kLHintsLeft, spacing, 0, 2, 2);
   AddFrame(pbut, layout);
   pbut->AllowStayDown(button->fStayDown);
   pbut->Associate(w);
   button->fButton = pbut;

   fTrash->Add(pbut);
   fTrash->Add(layout);
}

//______________________________________________________________________________
void TGToolBar::ChangeIcon(ToolBarData_t *button, const char *new_icon)
{
   // Change the icon of a toolbar button.

   const TGPicture *pic = fClient->GetPicture(new_icon);
   if (!pic) {
      Error("ChangeIcon", "pixmap not found: %s", new_icon);
      return;
   }
   fPictures->Add((TObject*)pic);

   ((TGPictureButton *)button->fButton)->SetPicture(pic);
}

//______________________________________________________________________________
void TGToolBar::Cleanup()
{
   // Cleanup and delete all objects contained in this composite frame.
   // This will delete all objects added via AddFrame().
   // CAUTION: all objects (frames and layout hints) must be unique, i.e.
   // cannot be shared.

   // avoid double deletion of objects in trash
   delete fTrash;
   fTrash = 0;

   TGCompositeFrame::Cleanup();
}

//______________________________________________________________________________
void TGToolBar::SavePrimitive(ofstream &out, Option_t *option)
{
   // Save an horizontal slider as a C++ statement(s) on output stream out.

   if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);

   out << endl;
   out << "   // tool bar" << endl;

   out << "   TGToolBar *";
   out << GetName() << " = new TGToolBar(" << fParent->GetName()
       << "," << GetWidth() << "," << GetHeight();

   if (fBackground == GetDefaultFrameBackground()) {
      if (!GetOptions()) {
         out <<");" << endl;
      } else {
         out << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << GetOptionString() << ",ucolor);" << endl;
   }

   char quote = '"';

   int i = 0;
   const char *picname;

   TGFrameElement *f;
   TIter next(GetList());

   while ((f = (TGFrameElement *) next())) {
      if (f->fFrame->InheritsFrom(TGPictureButton::Class())) {
         if (!gROOT->ClassSaved(TGPictureButton::Class())) {
            //  declare a structure used for pictute buttons
            out << endl << "   ToolBarData_t t;" << endl;
         }

         TGPictureButton *pb = (TGPictureButton *)f->fFrame;
         picname = pb->GetPicture()->GetName();

         out << "   t.fPixmap = " << quote
             << gSystem->ExpandPathName(gSystem->UnixPathName(picname))
             << quote << ";" << endl;
         out << "   t.fTipText = " << quote
             << pb->GetToolTip()->GetText()->GetString() << quote << ";" << endl;
         if (pb->GetState() == kButtonDown) {
            out << "   t.fStayDown = kTRUE;" << endl;
         } else {
            out << "   t.fStayDown = kFALSE;" << endl;
         }
         out << "   t.fId = " << i+1 << ";" << endl;
         out << "   t.fButton = 0;" << endl;
         out << "   " << GetName() << "->AddButton(" << GetParent()->GetName()
             << ",&t," << f->fLayout->GetPadLeft() << ");" << endl;
         if (pb->GetState() == kButtonDown) {
            out << "   TGButton *" << pb->GetName() <<  " = t.fButton;" << endl;
            out << "   " << pb->GetName() << "->SetState(kButtonDown);"  << endl;
         }
         if (pb->GetState() == kButtonDisabled) {
            out << "   TGButton *" << pb->GetName() <<  " = t.fButton;" << endl;
            out << "   " << pb->GetName() << "->SetState(kButtonDisabled);" << endl;
         }
         if (pb->GetState() == kButtonEngaged) {
            out << "   TGButton *" << pb->GetName() <<  " = t.fButton;" << endl;
            out << "   " << pb->GetName() << "->SetState(kButtonEngaged);"  << endl;
         }
         i++;
      } else {
         f->fFrame->SavePrimitive(out, option);
		       out << "   " << GetName()<<"->AddFrame(" << f->fFrame->GetName();
         f->fLayout->SavePrimitive(out, option);
         out << ");"<< endl;
      }
   }
}
<commit_msg>From Philippe: avoid access in the dtor to objects that have (potentially) already been deleted.<commit_after>// @(#)root/gui:$Name:  $:$Id: TGToolBar.cxx,v 1.10 2003/12/12 18:21:07 rdm Exp $
// Author: Fons Rademakers   25/02/98

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.

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

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGToolBar                                                            //
//                                                                      //
// A toolbar is a composite frame that contains TGPictureButtons.       //
// Often used in combination with a TGHorizontal3DLine.                 //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGToolBar.h"
#include "TList.h"
#include "TGButton.h"
#include "TGPicture.h"
#include "TGPicture.h"
#include "TGToolTip.h"
#include "TSystem.h"
#include "TROOT.h"
#include "Riostream.h"

ClassImp(TGToolBar)

//______________________________________________________________________________
TGToolBar::TGToolBar(const TGWindow *p, UInt_t w, UInt_t h,
                     UInt_t options, ULong_t back) :
   TGCompositeFrame(p, w, h, options, back)
{
   // Create toolbar widget.

   fPictures = new TList;
   fTrash    = new TList;
}

//______________________________________________________________________________
TGToolBar::~TGToolBar()
{
   // Delete toolbar and its buttons and layout hints.

   if (fTrash) fTrash->Delete();
   delete fTrash;

   TIter next(fPictures);
   const TGPicture *p;
   while ((p = (const TGPicture *) next()))
      fClient->FreePicture(p);

   // pictures might already have been deleted above, so avoid access
   // to these objects
   fPictures->Clear("nodelete");

   delete fPictures;
}

//______________________________________________________________________________
void TGToolBar::AddButton(const TGWindow *w, ToolBarData_t *button, Int_t spacing)
{
   // Add button to toolbar. All buttons added via this method will be
   // deleted by the toolbar. On return the TGButton field of the
   // ToolBarData_t struct is filled in (iff fPixmap was valid).
   // Window w is the window to which the button messages will be send.

   const TGPicture *pic = fClient->GetPicture(button->fPixmap);
   if (!pic) {
      Error("AddButton", "pixmap not found: %s", button->fPixmap);
      return;
   }
   fPictures->Add((TObject*)pic);

   TGPictureButton *pbut;
   TGLayoutHints   *layout;

   pbut = new TGPictureButton(this, pic, button->fId);
   pbut->SetToolTipText(button->fTipText);

   layout = new TGLayoutHints(kLHintsTop | kLHintsLeft, spacing, 0, 2, 2);
   AddFrame(pbut, layout);
   pbut->AllowStayDown(button->fStayDown);
   pbut->Associate(w);
   button->fButton = pbut;

   fTrash->Add(pbut);
   fTrash->Add(layout);
}

//______________________________________________________________________________
void TGToolBar::ChangeIcon(ToolBarData_t *button, const char *new_icon)
{
   // Change the icon of a toolbar button.

   const TGPicture *pic = fClient->GetPicture(new_icon);
   if (!pic) {
      Error("ChangeIcon", "pixmap not found: %s", new_icon);
      return;
   }
   fPictures->Add((TObject*)pic);

   ((TGPictureButton *)button->fButton)->SetPicture(pic);
}

//______________________________________________________________________________
void TGToolBar::Cleanup()
{
   // Cleanup and delete all objects contained in this composite frame.
   // This will delete all objects added via AddFrame().
   // CAUTION: all objects (frames and layout hints) must be unique, i.e.
   // cannot be shared.

   // avoid double deletion of objects in trash
   delete fTrash;
   fTrash = 0;

   TGCompositeFrame::Cleanup();
}

//______________________________________________________________________________
void TGToolBar::SavePrimitive(ofstream &out, Option_t *option)
{
   // Save an horizontal slider as a C++ statement(s) on output stream out.

   if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);

   out << endl;
   out << "   // tool bar" << endl;

   out << "   TGToolBar *";
   out << GetName() << " = new TGToolBar(" << fParent->GetName()
       << "," << GetWidth() << "," << GetHeight();

   if (fBackground == GetDefaultFrameBackground()) {
      if (!GetOptions()) {
         out <<");" << endl;
      } else {
         out << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << GetOptionString() << ",ucolor);" << endl;
   }

   char quote = '"';

   int i = 0;
   const char *picname;

   TGFrameElement *f;
   TIter next(GetList());

   while ((f = (TGFrameElement *) next())) {
      if (f->fFrame->InheritsFrom(TGPictureButton::Class())) {
         if (!gROOT->ClassSaved(TGPictureButton::Class())) {
            //  declare a structure used for pictute buttons
            out << endl << "   ToolBarData_t t;" << endl;
         }

         TGPictureButton *pb = (TGPictureButton *)f->fFrame;
         picname = pb->GetPicture()->GetName();

         out << "   t.fPixmap = " << quote
             << gSystem->ExpandPathName(gSystem->UnixPathName(picname))
             << quote << ";" << endl;
         out << "   t.fTipText = " << quote
             << pb->GetToolTip()->GetText()->GetString() << quote << ";" << endl;
         if (pb->GetState() == kButtonDown) {
            out << "   t.fStayDown = kTRUE;" << endl;
         } else {
            out << "   t.fStayDown = kFALSE;" << endl;
         }
         out << "   t.fId = " << i+1 << ";" << endl;
         out << "   t.fButton = 0;" << endl;
         out << "   " << GetName() << "->AddButton(" << GetParent()->GetName()
             << ",&t," << f->fLayout->GetPadLeft() << ");" << endl;
         if (pb->GetState() == kButtonDown) {
            out << "   TGButton *" << pb->GetName() <<  " = t.fButton;" << endl;
            out << "   " << pb->GetName() << "->SetState(kButtonDown);"  << endl;
         }
         if (pb->GetState() == kButtonDisabled) {
            out << "   TGButton *" << pb->GetName() <<  " = t.fButton;" << endl;
            out << "   " << pb->GetName() << "->SetState(kButtonDisabled);" << endl;
         }
         if (pb->GetState() == kButtonEngaged) {
            out << "   TGButton *" << pb->GetName() <<  " = t.fButton;" << endl;
            out << "   " << pb->GetName() << "->SetState(kButtonEngaged);"  << endl;
         }
         i++;
      } else {
         f->fFrame->SavePrimitive(out, option);
		       out << "   " << GetName()<<"->AddFrame(" << f->fFrame->GetName();
         f->fLayout->SavePrimitive(out, option);
         out << ");"<< endl;
      }
   }
}
<|endoftext|>


<commit_before>#include "classificator.hpp"
#include "tree_structure.hpp"

#include "../base/macros.hpp"
#include "../base/logging.hpp"

#include "../std/bind.hpp"
#include "../std/algorithm.hpp"
#include "../std/iterator.hpp"

/////////////////////////////////////////////////////////////////////////////////////////
// ClassifObject implementation
/////////////////////////////////////////////////////////////////////////////////////////

ClassifObject * ClassifObject::AddImpl(string const & s)
{
  if (m_objs.empty()) m_objs.reserve(30);

  m_objs.push_back(ClassifObject(s));
  return &(m_objs.back());
}

ClassifObject * ClassifObject::Add(string const & s)
{
  ClassifObject * p = Find(s);
  return (p ? p : AddImpl(s));
}

ClassifObject * ClassifObject::Find(string const & s)
{
  for (iter_t i = m_objs.begin(); i != m_objs.end(); ++i)
    if ((*i).m_name == s)
      return &(*i);

  return 0;
}

void ClassifObject::AddDrawRule(drule::Key const & k)
{
  for (size_t i = 0; i < m_drawRule.size(); ++i)
    if (k == m_drawRule[i]) return;

  m_drawRule.push_back(k);
}

ClassifObjectPtr ClassifObject::BinaryFind(string const & s) const
{
  const_iter_t i = lower_bound(m_objs.begin(), m_objs.end(), s, less_name_t());
  if ((i == m_objs.end()) || ((*i).m_name != s))
    return ClassifObjectPtr(0, 0);
  else
    return ClassifObjectPtr(&(*i), distance(m_objs.begin(), i));
}

void ClassifObject::LoadPolicy::Start(size_t i)
{
  ClassifObject * p = Current();
  p->m_objs.push_back(ClassifObject());

  base_type::Start(i);
}

namespace
{
  struct less_scales
  {
    bool operator() (drule::Key const & l, int r) const { return l.m_scale < r; }
    bool operator() (int l, drule::Key const & r) const { return l < r.m_scale; }
    bool operator() (drule::Key const & l, drule::Key const & r) const { return l.m_scale < r.m_scale; }
  };
}

void ClassifObject::LoadPolicy::EndChilds()
{
  ClassifObject * p = Current();
  ASSERT ( p->m_objs.back().m_name.empty(), () );
  p->m_objs.pop_back();
}

void ClassifObject::Sort()
{
  sort(m_drawRule.begin(), m_drawRule.end(), less_scales());
  sort(m_objs.begin(), m_objs.end(), less_name_t());
  for_each(m_objs.begin(), m_objs.end(), bind(&ClassifObject::Sort, _1));
}

void ClassifObject::Swap(ClassifObject & r)
{
  swap(m_name, r.m_name);
  swap(m_drawRule, r.m_drawRule);
  swap(m_objs, r.m_objs);
  swap(m_visibility, r.m_visibility);
}

ClassifObject const * ClassifObject::GetObject(size_t i) const
{
  if (i < m_objs.size())
    return &(m_objs[i]);
  else
  {
    LOG(LINFO, ("Map contains object that has no classificator entry", i, m_name));
    return 0;
  }
}

void ClassifObject::ConcatChildNames(string & s) const
{
  s.clear();
  size_t const count = m_objs.size();
  for (size_t i = 0; i < count; ++i)
  {
    s += m_objs[i].GetName();
    if (i != count-1) s += '|';
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
// Classificator implementation
/////////////////////////////////////////////////////////////////////////////////////////

Classificator & classif()
{
  static Classificator c;
  return c;
}

namespace ftype
{
  uint8_t const bits_count = 6;
  uint8_t const levels_count = 5;
  uint8_t const max_value = (1 << bits_count) - 1;

  void set_value(uint32_t & type, uint8_t level, uint8_t value)
  {
    level *= bits_count;  // level to bits

    uint32_t const m1 = uint32_t(max_value) << level;
    type &= (~m1);        // zero bits

    uint32_t const m2 = uint32_t(value) << level;
    type |= m2;           // set bits
  }

  uint8_t get_value(uint32_t type, uint8_t level)
  {
    level *= bits_count;     // level to bits;

    uint32_t const m = uint32_t(max_value) << level;
    type &= m;              // leave only our bits

    type = type >> level;   // move to start
    ASSERT ( type <= max_value, ("invalid output value", type) );

    return uint8_t(type);   // conversion
  }

  uint8_t get_control_level(uint32_t type)
  {
    uint8_t count = 0;
    while (type > 1)
    {
      type = type >> bits_count;
      ++count;
    }

    return count;
  }

  void PushValue(uint32_t & type, uint8_t value)
  {
    ASSERT ( value <= max_value, ("invalid input value", value) );

    uint8_t const cl = get_control_level(type);
    ASSERT ( cl < levels_count, (cl) );

    set_value(type, cl, value);

    // set control level
    set_value(type, cl+1, 1);
  }

  bool GetValue(uint32_t type, uint8_t level, uint8_t & value)
  {
    ASSERT ( level < levels_count, ("invalid input level", level) );

    if (level < get_control_level(type))
    {
      value = get_value(type, level);
      return true;
    }
    return false;
  }

  void PopValue(uint32_t & type)
  {
    uint8_t const cl = get_control_level(type);
    ASSERT_GREATER ( cl, 0, () );

    // remove control level
    set_value(type, cl, 0);

    // set control level
    set_value(type, cl-1, 1);
  }

  void TruncValue(uint32_t & type, uint8_t level)
  {
    ASSERT_GREATER ( level, 0, () );
    uint8_t cl = get_control_level(type);

    while (cl > level)
    {
      // remove control level
      set_value(type, cl, 0);

      --cl;

      // set control level
      set_value(type, cl, 1);
    }
  }

  uint8_t GetLevel(uint32_t type)
  {
    return get_control_level(type);
  }
}

namespace
{
  class suitable_getter
  {
    typedef vector<drule::Key> vec_t;
    typedef vec_t::const_iterator iter_t;

    vec_t const & m_rules;
    drule::KeysT & m_keys;

    bool m_added;

    void add_rule(int ft, iter_t i)
    {
      static const int visible[3][drule::count_of_rules] = {
        { 0, 0, 1, 1, 1, 0, 0 },   // fpoint
        { 1, 0, 0, 0, 0, 1, 0 },   // fline
        { 1, 1, 1, 1, 0, 0, 0 }    // farea
      };

      if (visible[ft][i->m_type] == 1)
      {
        m_keys.push_back(*i);
        m_added = true;
      }
    }

  public:
    suitable_getter(vec_t const & rules, drule::KeysT & keys)
      : m_rules(rules), m_keys(keys)
    {
    }

    void find(int ft, int scale)
    {
      iter_t i = lower_bound(m_rules.begin(), m_rules.end(), scale, less_scales());
      while (i != m_rules.end() && i->m_scale == scale)
        add_rule(ft, i++);
    }
  };
}

void ClassifObject::GetSuitable(int scale, FeatureGeoType ft, drule::KeysT & keys) const
{
  ASSERT ( ft <= FEATURE_TYPE_AREA, () );

  // 2. Check visibility criterion for scale first.
  if (!m_visibility[scale])
    return;

  // find rules for 'scale'
  suitable_getter rulesGetter(m_drawRule, keys);
  rulesGetter.find(ft, scale);
}

bool ClassifObject::IsDrawable(int scale) const
{
  return (m_visibility[scale] && IsDrawableAny());
}

bool ClassifObject::IsDrawableAny() const
{
  return (m_visibility != visible_mask_t() && !m_drawRule.empty());
}

bool ClassifObject::IsDrawableLike(FeatureGeoType ft) const
{
  // check the very common criterion first
  if (!IsDrawableAny())
    return false;

  ASSERT ( ft <= FEATURE_TYPE_AREA, () );

  static const int visible[3][drule::count_of_rules] = {
    {0, 0, 1, 1, 1, 0, 0},   // fpoint
    {1, 0, 0, 0, 0, 1, 0},   // fline
    {0, 1, 0, 0, 0, 0, 0}    // farea (!!! key difference with GetSuitable !!!)
  };

  for (size_t i = 0; i < m_drawRule.size(); ++i)
  {
    ASSERT ( m_drawRule[i].m_type < drule::count_of_rules, () );
    if (visible[ft][m_drawRule[i].m_type] == 1)
    {
      /// @todo Check if rule's scale is reachable according to m_visibility (see GetSuitable algorithm).
      return true;
    }
  }

  return false;
}

pair<int, int> ClassifObject::GetDrawScaleRange() const
{
  if (!IsDrawableAny())
    return make_pair(-1, -1);

  size_t const count = m_visibility.size();

  int left = -1;
  for (int i = 0; i < count; ++i)
    if (m_visibility[i])
    {
      left = i;
      break;
    }

  ASSERT_NOT_EQUAL ( left, -1, () );

  int right = left;
  for (int i = count-1; i > left; --i)
    if (m_visibility[i])
    {
      right = i;
      break;
    }

  return make_pair(left, right);
}

void Classificator::ReadClassificator(istream & s)
{
  ClassifObject::LoadPolicy policy(&m_root);
  tree::LoadTreeAsText(s, policy);

  m_root.Sort();

  char const * path[] = { "natural", "coastline" };
  m_coastType = GetTypeByPath(vector<string>(path, path + 2));
}

void Classificator::SortClassificator()
{
  GetMutableRoot()->Sort();
}

uint32_t Classificator::GetTypeByPath(vector<string> const & path) const
{
  ClassifObject const * p = GetRoot();

  size_t i = 0;
  uint32_t type = ftype::GetEmptyValue();

  while (i < path.size())
  {
    ClassifObjectPtr ptr = p->BinaryFind(path[i]);
    ASSERT ( ptr, ("Invalid path in Classificator::GetTypeByPath", path) );

    ftype::PushValue(type, ptr.GetIndex());

    ++i;
    p = ptr.get();
  }

  return type;
}

void Classificator::ReadTypesMapping(istream & s)
{
  m_mapping.Load(s);
}

void Classificator::Clear()
{
  ClassifObject("world").Swap(m_root);
  m_mapping.Clear();
}

string Classificator::GetReadableObjectName(uint32_t type) const
{
  string s = classif().GetFullObjectName(type);

  // remove ending dummy symbol
  ASSERT ( !s.empty(), () );
  s.resize(s.size()-1);

  // replace separator
  replace(s.begin(), s.end(), '|', '-');
  return s;
}
<commit_msg>[indexer] allow circles for polygons<commit_after>#include "classificator.hpp"
#include "tree_structure.hpp"

#include "../base/macros.hpp"
#include "../base/logging.hpp"

#include "../std/bind.hpp"
#include "../std/algorithm.hpp"
#include "../std/iterator.hpp"

/////////////////////////////////////////////////////////////////////////////////////////
// ClassifObject implementation
/////////////////////////////////////////////////////////////////////////////////////////

ClassifObject * ClassifObject::AddImpl(string const & s)
{
  if (m_objs.empty()) m_objs.reserve(30);

  m_objs.push_back(ClassifObject(s));
  return &(m_objs.back());
}

ClassifObject * ClassifObject::Add(string const & s)
{
  ClassifObject * p = Find(s);
  return (p ? p : AddImpl(s));
}

ClassifObject * ClassifObject::Find(string const & s)
{
  for (iter_t i = m_objs.begin(); i != m_objs.end(); ++i)
    if ((*i).m_name == s)
      return &(*i);

  return 0;
}

void ClassifObject::AddDrawRule(drule::Key const & k)
{
  for (size_t i = 0; i < m_drawRule.size(); ++i)
    if (k == m_drawRule[i]) return;

  m_drawRule.push_back(k);
}

ClassifObjectPtr ClassifObject::BinaryFind(string const & s) const
{
  const_iter_t i = lower_bound(m_objs.begin(), m_objs.end(), s, less_name_t());
  if ((i == m_objs.end()) || ((*i).m_name != s))
    return ClassifObjectPtr(0, 0);
  else
    return ClassifObjectPtr(&(*i), distance(m_objs.begin(), i));
}

void ClassifObject::LoadPolicy::Start(size_t i)
{
  ClassifObject * p = Current();
  p->m_objs.push_back(ClassifObject());

  base_type::Start(i);
}

namespace
{
  struct less_scales
  {
    bool operator() (drule::Key const & l, int r) const { return l.m_scale < r; }
    bool operator() (int l, drule::Key const & r) const { return l < r.m_scale; }
    bool operator() (drule::Key const & l, drule::Key const & r) const { return l.m_scale < r.m_scale; }
  };
}

void ClassifObject::LoadPolicy::EndChilds()
{
  ClassifObject * p = Current();
  ASSERT ( p->m_objs.back().m_name.empty(), () );
  p->m_objs.pop_back();
}

void ClassifObject::Sort()
{
  sort(m_drawRule.begin(), m_drawRule.end(), less_scales());
  sort(m_objs.begin(), m_objs.end(), less_name_t());
  for_each(m_objs.begin(), m_objs.end(), bind(&ClassifObject::Sort, _1));
}

void ClassifObject::Swap(ClassifObject & r)
{
  swap(m_name, r.m_name);
  swap(m_drawRule, r.m_drawRule);
  swap(m_objs, r.m_objs);
  swap(m_visibility, r.m_visibility);
}

ClassifObject const * ClassifObject::GetObject(size_t i) const
{
  if (i < m_objs.size())
    return &(m_objs[i]);
  else
  {
    LOG(LINFO, ("Map contains object that has no classificator entry", i, m_name));
    return 0;
  }
}

void ClassifObject::ConcatChildNames(string & s) const
{
  s.clear();
  size_t const count = m_objs.size();
  for (size_t i = 0; i < count; ++i)
  {
    s += m_objs[i].GetName();
    if (i != count-1) s += '|';
  }
}

/////////////////////////////////////////////////////////////////////////////////////////
// Classificator implementation
/////////////////////////////////////////////////////////////////////////////////////////

Classificator & classif()
{
  static Classificator c;
  return c;
}

namespace ftype
{
  uint8_t const bits_count = 6;
  uint8_t const levels_count = 5;
  uint8_t const max_value = (1 << bits_count) - 1;

  void set_value(uint32_t & type, uint8_t level, uint8_t value)
  {
    level *= bits_count;  // level to bits

    uint32_t const m1 = uint32_t(max_value) << level;
    type &= (~m1);        // zero bits

    uint32_t const m2 = uint32_t(value) << level;
    type |= m2;           // set bits
  }

  uint8_t get_value(uint32_t type, uint8_t level)
  {
    level *= bits_count;     // level to bits;

    uint32_t const m = uint32_t(max_value) << level;
    type &= m;              // leave only our bits

    type = type >> level;   // move to start
    ASSERT ( type <= max_value, ("invalid output value", type) );

    return uint8_t(type);   // conversion
  }

  uint8_t get_control_level(uint32_t type)
  {
    uint8_t count = 0;
    while (type > 1)
    {
      type = type >> bits_count;
      ++count;
    }

    return count;
  }

  void PushValue(uint32_t & type, uint8_t value)
  {
    ASSERT ( value <= max_value, ("invalid input value", value) );

    uint8_t const cl = get_control_level(type);
    ASSERT ( cl < levels_count, (cl) );

    set_value(type, cl, value);

    // set control level
    set_value(type, cl+1, 1);
  }

  bool GetValue(uint32_t type, uint8_t level, uint8_t & value)
  {
    ASSERT ( level < levels_count, ("invalid input level", level) );

    if (level < get_control_level(type))
    {
      value = get_value(type, level);
      return true;
    }
    return false;
  }

  void PopValue(uint32_t & type)
  {
    uint8_t const cl = get_control_level(type);
    ASSERT_GREATER ( cl, 0, () );

    // remove control level
    set_value(type, cl, 0);

    // set control level
    set_value(type, cl-1, 1);
  }

  void TruncValue(uint32_t & type, uint8_t level)
  {
    ASSERT_GREATER ( level, 0, () );
    uint8_t cl = get_control_level(type);

    while (cl > level)
    {
      // remove control level
      set_value(type, cl, 0);

      --cl;

      // set control level
      set_value(type, cl, 1);
    }
  }

  uint8_t GetLevel(uint32_t type)
  {
    return get_control_level(type);
  }
}

namespace
{
  class suitable_getter
  {
    typedef vector<drule::Key> vec_t;
    typedef vec_t::const_iterator iter_t;

    vec_t const & m_rules;
    drule::KeysT & m_keys;

    bool m_added;

    void add_rule(int ft, iter_t i)
    {
      static const int visible[3][drule::count_of_rules] = {
        { 0, 0, 1, 1, 1, 0, 0 },   // fpoint
        { 1, 0, 0, 0, 0, 1, 0 },   // fline
        { 1, 1, 1, 1, 1, 0, 0 }    // farea
      };

      if (visible[ft][i->m_type] == 1)
      {
        m_keys.push_back(*i);
        m_added = true;
      }
    }

  public:
    suitable_getter(vec_t const & rules, drule::KeysT & keys)
      : m_rules(rules), m_keys(keys)
    {
    }

    void find(int ft, int scale)
    {
      iter_t i = lower_bound(m_rules.begin(), m_rules.end(), scale, less_scales());
      while (i != m_rules.end() && i->m_scale == scale)
        add_rule(ft, i++);
    }
  };
}

void ClassifObject::GetSuitable(int scale, FeatureGeoType ft, drule::KeysT & keys) const
{
  ASSERT ( ft <= FEATURE_TYPE_AREA, () );

  // 2. Check visibility criterion for scale first.
  if (!m_visibility[scale])
    return;

  // find rules for 'scale'
  suitable_getter rulesGetter(m_drawRule, keys);
  rulesGetter.find(ft, scale);
}

bool ClassifObject::IsDrawable(int scale) const
{
  return (m_visibility[scale] && IsDrawableAny());
}

bool ClassifObject::IsDrawableAny() const
{
  return (m_visibility != visible_mask_t() && !m_drawRule.empty());
}

bool ClassifObject::IsDrawableLike(FeatureGeoType ft) const
{
  // check the very common criterion first
  if (!IsDrawableAny())
    return false;

  ASSERT ( ft <= FEATURE_TYPE_AREA, () );

  static const int visible[3][drule::count_of_rules] = {
    {0, 0, 1, 1, 1, 0, 0},   // fpoint
    {1, 0, 0, 0, 0, 1, 0},   // fline
    {0, 1, 0, 0, 0, 0, 0}    // farea (!!! key difference with GetSuitable !!!)
  };

  for (size_t i = 0; i < m_drawRule.size(); ++i)
  {
    ASSERT ( m_drawRule[i].m_type < drule::count_of_rules, () );
    if (visible[ft][m_drawRule[i].m_type] == 1)
    {
      /// @todo Check if rule's scale is reachable according to m_visibility (see GetSuitable algorithm).
      return true;
    }
  }

  return false;
}

pair<int, int> ClassifObject::GetDrawScaleRange() const
{
  if (!IsDrawableAny())
    return make_pair(-1, -1);

  size_t const count = m_visibility.size();

  int left = -1;
  for (int i = 0; i < count; ++i)
    if (m_visibility[i])
    {
      left = i;
      break;
    }

  ASSERT_NOT_EQUAL ( left, -1, () );

  int right = left;
  for (int i = count-1; i > left; --i)
    if (m_visibility[i])
    {
      right = i;
      break;
    }

  return make_pair(left, right);
}

void Classificator::ReadClassificator(istream & s)
{
  ClassifObject::LoadPolicy policy(&m_root);
  tree::LoadTreeAsText(s, policy);

  m_root.Sort();

  char const * path[] = { "natural", "coastline" };
  m_coastType = GetTypeByPath(vector<string>(path, path + 2));
}

void Classificator::SortClassificator()
{
  GetMutableRoot()->Sort();
}

uint32_t Classificator::GetTypeByPath(vector<string> const & path) const
{
  ClassifObject const * p = GetRoot();

  size_t i = 0;
  uint32_t type = ftype::GetEmptyValue();

  while (i < path.size())
  {
    ClassifObjectPtr ptr = p->BinaryFind(path[i]);
    ASSERT ( ptr, ("Invalid path in Classificator::GetTypeByPath", path) );

    ftype::PushValue(type, ptr.GetIndex());

    ++i;
    p = ptr.get();
  }

  return type;
}

void Classificator::ReadTypesMapping(istream & s)
{
  m_mapping.Load(s);
}

void Classificator::Clear()
{
  ClassifObject("world").Swap(m_root);
  m_mapping.Clear();
}

string Classificator::GetReadableObjectName(uint32_t type) const
{
  string s = classif().GetFullObjectName(type);

  // remove ending dummy symbol
  ASSERT ( !s.empty(), () );
  s.resize(s.size()-1);

  // replace separator
  replace(s.begin(), s.end(), '|', '-');
  return s;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkDashPathEffect.h"

static void drawline(SkCanvas* canvas, int on, int off, const SkPaint& paint) {
    SkPaint p(paint);

    const SkScalar intervals[] = {
        SkIntToScalar(on),
        SkIntToScalar(off),
    };

    p.setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
    canvas->drawLine(0, 0, SkIntToScalar(600), 0, p);
}

namespace skiagm {

class DashingGM : public GM {
public:
    DashingGM() {}

protected:
    SkString onShortName() {
        return SkString("dashing");
    }

    SkISize onISize() { return make_isize(640, 300); }

    virtual void onDraw(SkCanvas* canvas) {
        static const struct {
            int fOnInterval;
            int fOffInterval;
        } gData[] = {
            { 1, 1 },
            { 4, 1 },
        };

        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);

        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        canvas->translate(0, SK_ScalarHalf);

        for (int width = 0; width <= 2; ++width) {
            for (size_t data = 0; data < SK_ARRAY_COUNT(gData); ++data) {
                for (int aa = 0; aa <= 1; ++aa) {
                    int w = width * width * width;
                    paint.setAntiAlias(SkToBool(aa));
                    paint.setStrokeWidth(SkIntToScalar(w));

                    int scale = w ? w : 1;

                    drawline(canvas, gData[data].fOnInterval * scale,
                             gData[data].fOffInterval * scale,
                             paint);
                    canvas->translate(0, SkIntToScalar(20));
                }
            }
        }
    }

private:
    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static GM* gF(void*) { return new DashingGM; }
static GMRegistry gR(gF);

}
<commit_msg>add dashing2 gm to exercise dashing on curves and polygons<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkDashPathEffect.h"

static void drawline(SkCanvas* canvas, int on, int off, const SkPaint& paint) {
    SkPaint p(paint);

    const SkScalar intervals[] = {
        SkIntToScalar(on),
        SkIntToScalar(off),
    };

    p.setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
    canvas->drawLine(0, 0, SkIntToScalar(600), 0, p);
}

class DashingGM : public skiagm::GM {
public:
    DashingGM() {}

protected:
    SkString onShortName() {
        return SkString("dashing");
    }

    SkISize onISize() { return skiagm::make_isize(640, 300); }

    virtual void onDraw(SkCanvas* canvas) {
        static const struct {
            int fOnInterval;
            int fOffInterval;
        } gData[] = {
            { 1, 1 },
            { 4, 1 },
        };

        SkPaint paint;
        paint.setStyle(SkPaint::kStroke_Style);

        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        canvas->translate(0, SK_ScalarHalf);

        for (int width = 0; width <= 2; ++width) {
            for (size_t data = 0; data < SK_ARRAY_COUNT(gData); ++data) {
                for (int aa = 0; aa <= 1; ++aa) {
                    int w = width * width * width;
                    paint.setAntiAlias(SkToBool(aa));
                    paint.setStrokeWidth(SkIntToScalar(w));

                    int scale = w ? w : 1;

                    drawline(canvas, gData[data].fOnInterval * scale,
                             gData[data].fOffInterval * scale,
                             paint);
                    canvas->translate(0, SkIntToScalar(20));
                }
            }
        }
    }
};

///////////////////////////////////////////////////////////////////////////////

static void make_unit_star(SkPath* path, int n) {
    SkScalar rad = -SK_ScalarPI / 2;
    const SkScalar drad = (n >> 1) * SK_ScalarPI * 2 / n;

    path->moveTo(0, -SK_Scalar1);
    for (int i = 1; i < n; i++) {
        rad += drad;
        SkScalar cosV, sinV = SkScalarSinCos(rad, &cosV);
        path->lineTo(cosV, sinV);
    }
    path->close();
}

static void make_path_line(SkPath* path, const SkRect& bounds) {
    path->moveTo(bounds.left(), bounds.top());
    path->lineTo(bounds.right(), bounds.bottom());
}

static void make_path_rect(SkPath* path, const SkRect& bounds) {
    path->addRect(bounds);
}

static void make_path_oval(SkPath* path, const SkRect& bounds) {
    path->addOval(bounds);
}

static void make_path_star(SkPath* path, const SkRect& bounds) {
    make_unit_star(path, 5);
    SkMatrix matrix;
    matrix.setRectToRect(path->getBounds(), bounds, SkMatrix::kCenter_ScaleToFit);
    path->transform(matrix);
}

class Dashing2GM : public skiagm::GM {
public:
    Dashing2GM() {}

protected:
    SkString onShortName() {
        return SkString("dashing2");
    }

    SkISize onISize() { return skiagm::make_isize(640, 480); }

    virtual void onDraw(SkCanvas* canvas) {
        static const int gIntervals[] = {
            3,  // 3 dashes: each count [0] followed by intervals [1..count]
            2,  10, 10,
            4,  20, 5, 5, 5,
            2,  2, 2
        };

        void (*gProc[])(SkPath*, const SkRect&) = {
            make_path_line, make_path_rect, make_path_oval, make_path_star,
        };

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SkIntToScalar(6));

        SkRect bounds = SkRect::MakeWH(SkIntToScalar(120), SkIntToScalar(120));
        bounds.offset(SkIntToScalar(20), SkIntToScalar(20));
        SkScalar dx = bounds.width() * 4 / 3;
        SkScalar dy = bounds.height() * 4 / 3;

        const int* intervals = &gIntervals[1];
        for (int y = 0; y < gIntervals[0]; ++y) {
            SkScalar vals[SK_ARRAY_COUNT(gIntervals)];  // more than enough
            int count = *intervals++;
            for (int i = 0; i < count; ++i) {
                vals[i] = SkIntToScalar(*intervals++);
            }
            SkScalar phase = vals[0] / 2;
            paint.setPathEffect(new SkDashPathEffect(vals, count, phase))->unref();

            for (size_t x = 0; x < SK_ARRAY_COUNT(gProc); ++x) {
                SkPath path;
                SkRect r = bounds;
                r.offset(x * dx, y * dy);
                gProc[x](&path, r);

                canvas->drawPath(path, paint);
            }
        }
    }
};

//////////////////////////////////////////////////////////////////////////////

static skiagm::GM* F0(void*) { return new DashingGM; }
static skiagm::GM* F1(void*) { return new Dashing2GM; }

static skiagm::GMRegistry gR0(F0);
static skiagm::GMRegistry gR1(F1);

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/workarounds/draminit_workarounds.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file workarounds/draminit_workarounds.C
/// @brief Workarounds for the draminit code
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <mss.H>
#include <lib/dimm/rcd_load_ddr4.H>
#include <lib/dimm/ddr4/control_word_ddr4.H>
#include <lib/workarounds/draminit_workarounds.H>

namespace mss
{

namespace workarounds
{

///
/// @brief Runs the DRAM reset workaround to fix training bugs
/// @param[in] i_target - the target on which to operate
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode rcw_reset_dram( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
                                  std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // Note: we're always going to run this guy
    FAPI_INF("%s running the DRAM RCW DRAM reset workaround", mss::c_str(i_target));

    // Declares constexpr's
    constexpr uint64_t RESET_CW = 6;
    constexpr uint64_t RESET_DRAM = 0x02;
    constexpr uint64_t CLEAR_RESET = 0x03;
    // Note: the minimum for a FORC06 soft reset is 32 cycles, but we empirically tested it at 8k cycles
    constexpr uint64_t DELAY = 8000;
    // Function space 0
    constexpr uint8_t FS0 = 0;

    // Reset, then clear the data
    static const std::vector< cw_data > l_rcd_reset_data =
    {
        { FS0, RESET_CW, RESET_DRAM,  DELAY },
        { FS0, RESET_CW, CLEAR_RESET, DELAY },
    };

    // Load the data into the CCS array
    return control_word_engine<RCW_4BIT>(i_target, l_rcd_reset_data, io_inst);
}

} // namespace workarounds

} // namespace mss
<commit_msg>Fixes CKE levels during RCD initialization<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/workarounds/draminit_workarounds.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file workarounds/draminit_workarounds.C
/// @brief Workarounds for the draminit code
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <mss.H>
#include <lib/dimm/rcd_load_ddr4.H>
#include <lib/dimm/ddr4/control_word_ddr4.H>
#include <lib/workarounds/draminit_workarounds.H>

namespace mss
{

namespace workarounds
{

///
/// @brief Runs the DRAM reset workaround to fix training bugs
/// @param[in] i_target - the target on which to operate
/// @param[in] i_sim - true IFF simulation mode is on
/// @param[in,out] a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode rcw_reset_dram( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
                                  const bool i_sim,
                                  std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
{
    // Note: we're always going to run this guy
    FAPI_INF("%s running the DRAM RCW DRAM reset workaround", mss::c_str(i_target));

    // Declares constexpr's
    constexpr uint64_t RESET_CW = 6;
    constexpr uint64_t RESET_DRAM = 0x02;
    constexpr uint64_t CLEAR_RESET = 0x03;
    // Note: the minimum for a FORC06 soft reset is 32 cycles, but we empirically tested it at 8k cycles
    constexpr uint64_t DELAY = 8000;
    // Function space 0
    constexpr uint8_t FS0 = 0;

    // Reset, then clear the data
    static const std::vector< cw_data > l_rcd_reset_data =
    {
        { FS0, RESET_CW, RESET_DRAM,  DELAY },
        { FS0, RESET_CW, CLEAR_RESET, DELAY },
    };

    // Load the data into the CCS array
    FAPI_TRY(control_word_engine<RCW_4BIT>(i_target, l_rcd_reset_data, i_sim, io_inst));

fapi_try_exit:
    return fapi2::current_err;
}

} // namespace workarounds

} // namespace mss
<|endoftext|>


<commit_before>#pragma clang diagnostic ignored "-Wunused-parameter"

#include "stdafx.h"
#include <asdf_multiplat/main/asdf_multiplat.h>
#include <asdf_multiplat/utilities/utilities.h>

#include "hexmap.h"
#include "editor/main/editor.h"

using namespace asdf;
using namespace hexmap;

int main(int argc, char* argv[])
{
    //todo: make sure argv is actually the full exec path in UNIX
    std::string exec_dir(argv[0]);
    size_t new_size = exec_dir.length();
    for (;exec_dir[new_size] != '\\' && exec_dir[new_size] != '/' && --new_size != 0;);
    exec_dir.resize(new_size);

app.settings.resolution_width = 1024;
app.settings.resolution_height =  568;

    app.init(std::move(exec_dir));

    // hexmap_t hexmap;
    // app.specific = &hexmap;
    // hexmap.init();

    editor::editor_t editor;
    app.specific = &editor;
    editor.init();

	SDL_Event event;

    while (app.running) {
        while (SDL_PollEvent(&event)) {
            app.on_event(&event);
        }

        app.update();
        app.render();
    }

    LOG("--- Another Successful Procedure ---");

	return 0;
}<commit_msg>diagnostics<commit_after>#include "stdafx.h"
#include <asdf_multiplat/main/asdf_multiplat.h>
#include <asdf_multiplat/utilities/utilities.h>

#include "hexmap.h"
#include "editor/main/editor.h"

DIAGNOSTIC_IGNORE(-Wunused-parameter);

using namespace asdf;
using namespace hexmap;

int main(int argc, char* argv[])
{
    //todo: make sure argv is actually the full exec path in UNIX
    std::string exec_dir(argv[0]);
    size_t new_size = exec_dir.length();
    for (;exec_dir[new_size] != '\\' && exec_dir[new_size] != '/' && --new_size != 0;);
    exec_dir.resize(new_size);

app.settings.resolution_width = 1024;
app.settings.resolution_height =  568;

    app.init(std::move(exec_dir));

    // hexmap_t hexmap;
    // app.specific = &hexmap;
    // hexmap.init();

    editor::editor_t editor;
    app.specific = &editor;
    editor.init();

	SDL_Event event;

    while (app.running) {
        while (SDL_PollEvent(&event)) {
            app.on_event(&event);
        }

        app.update();
        app.render();
    }

    LOG("--- Another Successful Procedure ---");

	return 0;
}<|endoftext|>


<commit_before>// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "mfem.hpp"
#include "unit_tests.hpp"
#include <functional>
#include <ctime>

using namespace mfem;

struct LinearFormExtTest
{
   enum { DLFEval, BLFEval, QLFEval, DLFGrad, VDLFEval, VQLFEval, VDLFGrad };
   const double abs_tol = 1e-14, rel_tol = 1e-14;
   const char *mesh_filename;
   Mesh mesh;
   const int dim, vdim, ordering, gll, problem, p, q, SEED = 0x100001b3;
   H1_FECollection fec;
   FiniteElementSpace vfes;
   const Geometry::Type geom_type;
   IntegrationRules IntRulesGLL;
   const IntegrationRule *irGLL, *ir;
   Array<int> elem_marker;
   Vector one_vec, dim_vec, vdim_vec, vdim_dim_vec;
   ConstantCoefficient cst_coeff;
   VectorConstantCoefficient dim_cst_coeff, vdim_cst_coeff, vdim_dim_cst_coeff;
   QuadratureSpace qspace;
   QuadratureFunction q_function, q_vdim_function;
   QuadratureFunctionCoefficient qfc;
   VectorQuadratureFunctionCoefficient qfvc;
   LinearForm lf_dev, lf_std;
   LinearFormIntegrator *lfi_dev, *lfi_std;

   LinearFormExtTest(const char *mesh_filename,
                     int vdim, int ordering, bool gll, int problem, int p):
      mesh_filename(mesh_filename),
      mesh(Mesh::LoadFromFile(mesh_filename)),
      dim(mesh.Dimension()), vdim(vdim), ordering(ordering), gll(gll),
      problem(problem), p(p), q(2*p + (gll?-1:3)), fec(p, dim),
      vfes(&mesh, &fec, vdim, ordering),
      geom_type(vfes.GetFE(0)->GetGeomType()),
      IntRulesGLL(0, Quadrature1D::GaussLobatto),
      irGLL(&IntRulesGLL.Get(geom_type, q)), ir(&IntRules.Get(geom_type, q)),
      elem_marker(), one_vec(1), dim_vec(dim), vdim_vec(vdim), vdim_dim_vec(vdim*dim),
      cst_coeff(M_PI), dim_cst_coeff((dim_vec.Randomize(SEED), dim_vec)),
      vdim_cst_coeff((vdim_vec.Randomize(SEED), vdim_vec)),
      vdim_dim_cst_coeff((vdim_dim_vec.Randomize(SEED), vdim_dim_vec)),
      qspace(&mesh, q),
      q_function(&qspace, 1),
      q_vdim_function(&qspace, vdim),
      qfc((q_function.Randomize(SEED), q_function)),
      qfvc((q_vdim_function.Randomize(SEED), q_vdim_function)),
      lf_dev(&vfes), lf_std(&vfes), lfi_dev(nullptr), lfi_std(nullptr)
   {
      for (int e = 0; e < mesh.GetNE(); e++) { mesh.SetAttribute(e, e%2?1:2); }
      mesh.SetAttributes();
      MFEM_VERIFY(mesh.attributes.Size() == 2, "mesh attributes size error!");
      elem_marker.SetSize(2);
      elem_marker[0] = 0;
      elem_marker[1] = 1;

      if (problem == DLFEval)
      {
         lfi_dev = new DomainLFIntegrator(cst_coeff);
         lfi_std = new DomainLFIntegrator(cst_coeff);
      }
      else if (problem == BLFEval)
      {
         lfi_dev = new BoundaryLFIntegrator(cst_coeff);
         lfi_std = new BoundaryLFIntegrator(cst_coeff);
      }
      else if (problem == QLFEval)
      {
         lfi_dev = new QuadratureLFIntegrator(qfc,NULL);
         lfi_std = new QuadratureLFIntegrator(qfc,NULL);
      }
      else if (problem == DLFGrad)
      {
         lfi_dev = new DomainLFGradIntegrator(dim_cst_coeff);
         lfi_std = new DomainLFGradIntegrator(dim_cst_coeff);
      }
      else if (problem == VDLFEval)
      {
         lfi_dev = new VectorDomainLFIntegrator(vdim_cst_coeff);
         lfi_std = new VectorDomainLFIntegrator(vdim_cst_coeff);
      }
      else if (problem == VQLFEval)
      {
         lfi_dev = new VectorQuadratureLFIntegrator(qfvc,NULL);
         lfi_std = new VectorQuadratureLFIntegrator(qfvc,NULL);
      }
      else if (problem == VDLFGrad)
      {
         lfi_dev = new VectorDomainLFGradIntegrator(vdim_dim_cst_coeff);
         lfi_std = new VectorDomainLFGradIntegrator(vdim_dim_cst_coeff);
      }
      else { REQUIRE(false); }

      if (problem != QLFEval && problem != VQLFEval && problem != BLFEval)
      {
         lfi_dev->SetIntRule(gll ? irGLL : ir);
         lfi_std->SetIntRule(gll ? irGLL : ir);
      }

      if (problem != BLFEval)
      {
         lf_dev.AddDomainIntegrator(lfi_dev, elem_marker);
         lf_std.AddDomainIntegrator(lfi_std, elem_marker);
      }
      else
      {
         lf_dev.AddBoundaryIntegrator(lfi_dev);
         lf_std.AddBoundaryIntegrator(lfi_std);
      }
   }

   void Run()
   {
      const bool scalar = problem == LinearFormExtTest::DLFEval ||
                          problem == LinearFormExtTest::QLFEval ||
                          problem == LinearFormExtTest::DLFGrad;
      REQUIRE((!scalar || vdim == 1));

      const bool grad = problem == LinearFormExtTest::DLFGrad ||
                        problem == LinearFormExtTest::VDLFGrad;

      CAPTURE(mesh_filename, dim, p, q, ordering, vdim, scalar, grad);

      const bool use_device = true;
      lf_dev.Assemble(use_device);

      const bool dont_use_device = false;
      lf_std.Assemble(dont_use_device);

      lf_std -= lf_dev;
      REQUIRE(0.0 == MFEM_Approx(lf_std*lf_std, abs_tol, rel_tol));
   }
};

TEST_CASE("Linear Form Extension", "[LinearFormExtension], [CUDA]")
{
   const bool all = launch_all_non_regression_tests;

   const auto mesh_file =
      all ? GENERATE("../../data/star.mesh", "../../data/star-q3.mesh",
                     "../../data/fichera.mesh", "../../data/fichera-q3.mesh") :
      GENERATE("../../data/star-q3.mesh", "../../data/fichera-q3.mesh");
   const auto p = all ? GENERATE(1,2,3,4,5,6) : GENERATE(1,3);

   SECTION("Scalar")
   {
      const auto gll = GENERATE(false, true);
      const auto problem = GENERATE(LinearFormExtTest::DLFEval,
                                    LinearFormExtTest::QLFEval,
                                    LinearFormExtTest::DLFGrad,
                                    LinearFormExtTest::BLFEval);
      LinearFormExtTest(mesh_file, 1, Ordering::byNODES, gll, problem, p).Run();
   }

   SECTION("Vector")
   {
      const auto gll = GENERATE(false, true);
      const auto vdim = all ? GENERATE(1,5,7) : GENERATE(1,5);
      const auto ordering = GENERATE(Ordering::byVDIM, Ordering::byNODES);
      const auto problem = GENERATE(LinearFormExtTest::VDLFEval,
                                    LinearFormExtTest::VQLFEval,
                                    LinearFormExtTest::VDLFGrad);
      LinearFormExtTest(mesh_file, vdim, ordering, gll, problem, p).Run();
   }

   SECTION("SetIntPoint")
   {
      Mesh mesh(mesh_file);
      const int dim = mesh.Dimension();
      CAPTURE(mesh_file, dim, p);

      H1_FECollection H1(p, dim);
      FiniteElementSpace H1fes(&mesh, &H1);

      FunctionCoefficient f([](const Vector& x)
      { return std::sin(M_PI*x(0)) * std::sin(M_PI*x(1)); });

      GridFunction x(&H1fes);
      x.ProjectCoefficient(f);
      GradientGridFunctionCoefficient grad_x(&x);
      InnerProductCoefficient norm2_grad_x(grad_x,grad_x);

      L2_FECollection L2(p-1, dim);
      FiniteElementSpace L2fes(&mesh, &L2);

      LinearForm d1(&L2fes);
      d1.AddDomainIntegrator(new DomainLFIntegrator(norm2_grad_x));
      d1.Assemble();

      LinearForm d2(&L2fes);
      d2.AddDomainIntegrator(new DomainLFIntegrator(norm2_grad_x));
      d2.Assemble(false);

      d1 -= d2;

      REQUIRE(d1.Norml2() == MFEM_Approx(0.0));
   }

   SECTION("L2 MapType")
   {
      auto map_type = GENERATE(FiniteElement::VALUE, FiniteElement::INTEGRAL);
      Mesh mesh(mesh_file);
      const int dim = mesh.Dimension();

      CAPTURE(mesh_file, dim, p, map_type);

      L2_FECollection fec(p, dim, BasisType::GaussLegendre, map_type);
      FiniteElementSpace fes(&mesh, &fec);

      ConstantCoefficient coeff(1.0);

      LinearForm d1(&fes);
      d1.AddDomainIntegrator(new DomainLFIntegrator(coeff));
      d1.Assemble();

      LinearForm d2(&fes);
      d2.AddDomainIntegrator(new DomainLFIntegrator(coeff));
      d2.Assemble(false);

      CAPTURE(d1.Norml2(), d2.Norml2());

      d1 -= d2;

      REQUIRE(d1.Norml2() == MFEM_Approx(0.0));
   }
}
<commit_msg>Add unit test for BoundaryNormalLFIntegrator on device<commit_after>// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "mfem.hpp"
#include "unit_tests.hpp"
#include <functional>
#include <ctime>

using namespace mfem;

struct LinearFormExtTest
{
   enum { DLFEval, QLFEval, DLFGrad, // scalar domain
          VDLFEval, VQLFEval, VDLFGrad, // vector domain
          BLFEval, BNLFEval // boundary
        };
   const double abs_tol = 1e-14, rel_tol = 1e-14;
   const char *mesh_filename;
   Mesh mesh;
   const int dim, vdim, ordering, gll, problem, p, q, SEED = 0x100001b3;
   H1_FECollection fec;
   FiniteElementSpace vfes;
   const Geometry::Type geom_type;
   IntegrationRules IntRulesGLL;
   const IntegrationRule *irGLL, *ir;
   Array<int> elem_marker;
   Vector one_vec, dim_vec, vdim_vec, vdim_dim_vec;
   ConstantCoefficient cst_coeff;
   VectorConstantCoefficient dim_cst_coeff, vdim_cst_coeff, vdim_dim_cst_coeff;
   QuadratureSpace qspace;
   QuadratureFunction q_function, q_vdim_function;
   QuadratureFunctionCoefficient qfc;
   VectorQuadratureFunctionCoefficient qfvc;
   LinearForm lf_dev, lf_std;
   LinearFormIntegrator *lfi_dev, *lfi_std;

   LinearFormExtTest(const char *mesh_filename,
                     int vdim, int ordering, bool gll, int problem, int p):
      mesh_filename(mesh_filename),
      mesh(Mesh::LoadFromFile(mesh_filename)),
      dim(mesh.Dimension()), vdim(vdim), ordering(ordering), gll(gll),
      problem(problem), p(p), q(2*p + (gll?-1:3)), fec(p, dim),
      vfes(&mesh, &fec, vdim, ordering),
      geom_type(vfes.GetFE(0)->GetGeomType()),
      IntRulesGLL(0, Quadrature1D::GaussLobatto),
      irGLL(&IntRulesGLL.Get(geom_type, q)), ir(&IntRules.Get(geom_type, q)),
      elem_marker(), one_vec(1), dim_vec(dim), vdim_vec(vdim), vdim_dim_vec(vdim*dim),
      cst_coeff(M_PI), dim_cst_coeff((dim_vec.Randomize(SEED), dim_vec)),
      vdim_cst_coeff((vdim_vec.Randomize(SEED), vdim_vec)),
      vdim_dim_cst_coeff((vdim_dim_vec.Randomize(SEED), vdim_dim_vec)),
      qspace(&mesh, q),
      q_function(&qspace, 1),
      q_vdim_function(&qspace, vdim),
      qfc((q_function.Randomize(SEED), q_function)),
      qfvc((q_vdim_function.Randomize(SEED), q_vdim_function)),
      lf_dev(&vfes), lf_std(&vfes), lfi_dev(nullptr), lfi_std(nullptr)
   {
      for (int e = 0; e < mesh.GetNE(); e++) { mesh.SetAttribute(e, e%2?1:2); }
      mesh.SetAttributes();
      MFEM_VERIFY(mesh.attributes.Size() == 2, "mesh attributes size error!");
      elem_marker.SetSize(2);
      elem_marker[0] = 0;
      elem_marker[1] = 1;

      if (problem == DLFEval)
      {
         lfi_dev = new DomainLFIntegrator(cst_coeff);
         lfi_std = new DomainLFIntegrator(cst_coeff);
      }
      else if (problem == QLFEval)
      {
         lfi_dev = new QuadratureLFIntegrator(qfc,NULL);
         lfi_std = new QuadratureLFIntegrator(qfc,NULL);
      }
      else if (problem == DLFGrad)
      {
         lfi_dev = new DomainLFGradIntegrator(dim_cst_coeff);
         lfi_std = new DomainLFGradIntegrator(dim_cst_coeff);
      }
      else if (problem == VDLFEval)
      {
         lfi_dev = new VectorDomainLFIntegrator(vdim_cst_coeff);
         lfi_std = new VectorDomainLFIntegrator(vdim_cst_coeff);
      }
      else if (problem == VQLFEval)
      {
         lfi_dev = new VectorQuadratureLFIntegrator(qfvc,NULL);
         lfi_std = new VectorQuadratureLFIntegrator(qfvc,NULL);
      }
      else if (problem == VDLFGrad)
      {
         lfi_dev = new VectorDomainLFGradIntegrator(vdim_dim_cst_coeff);
         lfi_std = new VectorDomainLFGradIntegrator(vdim_dim_cst_coeff);
      }
      else if (problem == BLFEval)
      {
         lfi_dev = new BoundaryLFIntegrator(cst_coeff);
         lfi_std = new BoundaryLFIntegrator(cst_coeff);
      }
      else if (problem == BNLFEval)
      {
         lfi_dev = new BoundaryNormalLFIntegrator(dim_cst_coeff);
         lfi_std = new BoundaryNormalLFIntegrator(dim_cst_coeff);
      }
      else { REQUIRE(false); }

      if (problem != QLFEval && problem != VQLFEval && problem != BLFEval &&
          problem != BNLFEval)
      {
         lfi_dev->SetIntRule(gll ? irGLL : ir);
         lfi_std->SetIntRule(gll ? irGLL : ir);
      }

      if (problem != BLFEval && problem != BNLFEval)
      {
         lf_dev.AddDomainIntegrator(lfi_dev, elem_marker);
         lf_std.AddDomainIntegrator(lfi_std, elem_marker);
      }
      else
      {
         lf_dev.AddBoundaryIntegrator(lfi_dev);
         lf_std.AddBoundaryIntegrator(lfi_std);
      }
   }

   void Run()
   {
      const bool scalar = problem == LinearFormExtTest::DLFEval ||
                          problem == LinearFormExtTest::QLFEval ||
                          problem == LinearFormExtTest::DLFGrad;
      REQUIRE((!scalar || vdim == 1));

      const bool grad = problem == LinearFormExtTest::DLFGrad ||
                        problem == LinearFormExtTest::VDLFGrad;

      CAPTURE(mesh_filename, dim, p, q, ordering, vdim, scalar, grad);

      const bool use_device = true;
      lf_dev.Assemble(use_device);

      const bool dont_use_device = false;
      lf_std.Assemble(dont_use_device);

      lf_std -= lf_dev;
      REQUIRE(0.0 == MFEM_Approx(lf_std*lf_std, abs_tol, rel_tol));
   }
};

TEST_CASE("Linear Form Extension", "[LinearFormExtension], [CUDA]")
{
   const bool all = launch_all_non_regression_tests;

   const auto mesh_file =
      all ? GENERATE("../../data/star.mesh", "../../data/star-q3.mesh",
                     "../../data/fichera.mesh", "../../data/fichera-q3.mesh") :
      GENERATE("../../data/star-q3.mesh", "../../data/fichera-q3.mesh");
   const auto p = all ? GENERATE(1,2,3,4,5,6) : GENERATE(1,3);

   SECTION("Scalar")
   {
      const auto gll = GENERATE(false, true);
      const auto problem = GENERATE(LinearFormExtTest::DLFEval,
                                    LinearFormExtTest::QLFEval,
                                    LinearFormExtTest::DLFGrad,
                                    LinearFormExtTest::BLFEval,
                                    LinearFormExtTest::BNLFEval);
      LinearFormExtTest(mesh_file, 1, Ordering::byNODES, gll, problem, p).Run();
   }

   SECTION("Vector")
   {
      const auto gll = GENERATE(false, true);
      const auto vdim = all ? GENERATE(1,5,7) : GENERATE(1,5);
      const auto ordering = GENERATE(Ordering::byVDIM, Ordering::byNODES);
      const auto problem = GENERATE(LinearFormExtTest::VDLFEval,
                                    LinearFormExtTest::VQLFEval,
                                    LinearFormExtTest::VDLFGrad);
      LinearFormExtTest(mesh_file, vdim, ordering, gll, problem, p).Run();
   }

   SECTION("SetIntPoint")
   {
      Mesh mesh(mesh_file);
      const int dim = mesh.Dimension();
      CAPTURE(mesh_file, dim, p);

      H1_FECollection H1(p, dim);
      FiniteElementSpace H1fes(&mesh, &H1);

      FunctionCoefficient f([](const Vector& x)
      { return std::sin(M_PI*x(0)) * std::sin(M_PI*x(1)); });

      GridFunction x(&H1fes);
      x.ProjectCoefficient(f);
      GradientGridFunctionCoefficient grad_x(&x);
      InnerProductCoefficient norm2_grad_x(grad_x,grad_x);

      L2_FECollection L2(p-1, dim);
      FiniteElementSpace L2fes(&mesh, &L2);

      LinearForm d1(&L2fes);
      d1.AddDomainIntegrator(new DomainLFIntegrator(norm2_grad_x));
      d1.Assemble();

      LinearForm d2(&L2fes);
      d2.AddDomainIntegrator(new DomainLFIntegrator(norm2_grad_x));
      d2.Assemble(false);

      d1 -= d2;

      REQUIRE(d1.Norml2() == MFEM_Approx(0.0));
   }

   SECTION("L2 MapType")
   {
      auto map_type = GENERATE(FiniteElement::VALUE, FiniteElement::INTEGRAL);
      Mesh mesh(mesh_file);
      const int dim = mesh.Dimension();

      CAPTURE(mesh_file, dim, p, map_type);

      L2_FECollection fec(p, dim, BasisType::GaussLegendre, map_type);
      FiniteElementSpace fes(&mesh, &fec);

      ConstantCoefficient coeff(1.0);

      LinearForm d1(&fes);
      d1.AddDomainIntegrator(new DomainLFIntegrator(coeff));
      d1.Assemble();

      LinearForm d2(&fes);
      d2.AddDomainIntegrator(new DomainLFIntegrator(coeff));
      d2.Assemble(false);

      CAPTURE(d1.Norml2(), d2.Norml2());

      d1 -= d2;

      REQUIRE(d1.Norml2() == MFEM_Approx(0.0));
   }
}
<|endoftext|>