<commit_before>#include "stdlibs_for_debugging.h"

#include "foobar.h"

// TODO (unit test):
// - reflection.h, REFLECTABLE(function), namespace::ClassTemplate, namespace::function(ClassTemplate), SmartRef
// - also make sure that no invalid free functions are added (e.g. push_back on a vector)

#include <smartref/smartref.h>

#include <iostream>
#include <vector>
#include <typeinfo>
#include <iterator>

using namespace std;
using namespace foobar;
using smartref::using_;

template<typename T>
class Property : public using_<T>
{
// TODO: Add proper reference-leaking control by allowing
//       the user-defined conversion functions to be private.
public:
  using using_<T>::operator=;

  Property() = default;
  Property(T value) : data{value} {}

  operator T &() &
  {
    return data;
  }

  operator T &&() &&
  {
    return move(data);
  }

  operator const T &() const &
  {
    return data;
  }

  operator const T &&() const &&
  {
    return move(data);
  }

public:
  T data;
};

/*
class JSONValue : public using_<JSONValue, double>,
          public using_<JSONValue, string>,
          public using_<JSONValue, vector<JSONValue>>,
          public using_<JSONValue, map<JSONValue, JSONValue>>
{
public:
  operator double &()
  {
    return get<double>(data);
  }

  operator double &()
  {
    return get<string>(data);
  }

  operator double &()
  {
    return get<vector<JSONValue>>(data);
  }

  operator double &()
  {
    return get<map<JSONValue, JSONValue>>(data);
  }

private:
  variant<
    double,
    string,
    vector<JSONValue>,
    map<JSONValue, JSONValue>
  > data;
};
*/

namespace foobar {

void asdf(Foo)              { cout << "asdf(Foo)"              << endl; }
void asdf(Derived)          { cout << "asdf(Derived)"          << endl; }

template<typename T>
void asdf(ClassTemplate<T>) { cout << "asdf(ClassTemplate<T>)" << endl; }

} // namespace foobar

namespace foobar2 {

struct A {};
struct B {};

template<typename>
void qwerty(A)
{
  cout << "foobar2::qwerty<T>(A)" << endl;
}

template<typename>
void qwerty(foobar::ClassTemplate<A>)
{
  cout << "foobar2::qwerty<T>(foobar::ClassTemplate<A>)" << endl;
}

template<typename, typename U>
void qwerty(foobar::ClassTemplate<U>)
{
  cout << "foobar2::qwerty<T>(foobar::ClassTemplate<U>)" << endl;
}

} // namespace foobar2

int main()
{
/*
  JSONValue json = {};

  json["asdf"] = 1.0;
  json[123456] = nullptr;
  json.DOT(qwerty) = "the other (third) operator dot proposal";
  json.qwerty = "__getattr__ for C++";
*/

  cout << "Hello, Wandbox!" << endl;

  Property<vector<int>> v;

  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  // The following statements should *not* compile
  // v.push_back(1, 2, 3);
  // push_back(v, 1);

  for (auto x : v)
  {
    cout << x << endl;
  }

  Property<vector<float>> v2;
  copy(begin(v), end(v), back_inserter(v2));
  copy(begin(v2), end(v2), ostream_iterator<double>(cout, " "));
  cout << endl;

  Property<int> x{};
  Property<int> y{};

  x = 5;

  cout << x.data << endl;
  cout << (x = 9) << endl;

  // TODO: Proper reference leaking control
  //       i.e. {x + y} -> Property<decltype(delegate(x)+delegate(y))>
  {
    auto u = x + 1;
    auto v = 1 + y;
    auto w = x + y;
    auto z = Property<int>{x + y};

    cout << u << endl;
    cout << typeid(u).name() << endl;
    cout << v << endl;
    cout << typeid(v).name() << endl;
    cout << w << endl;
    cout << typeid(w).name() << endl;
    cout << z << endl;
    cout << typeid(z).name() << endl;
  }

  Property<Foo> foo;
  foo.foo();

  Property<Bar> bar;
  bar.bar();
  bar.bar2();
  bar.bar3();

  Property<Baz> baz;
  baz.baz();
  baz.baz2();

  Property<Bat> bat;
  bat.bat();
  bat.bat2();

  {
    Bar bar;
    bar.bar();
    bar.bar2();
    bar.bar3();

    Baz baz;
    baz.baz();
    baz.baz2();

    Bat bat;
    bat.bat();
    bat.bat2();
  }

  {
    Property<Bla> bla;
    bla.foo();
    bla.bar();
    auto x = decltype(bla)::baz{1234};
    cout << typeid(x).name() << " " << x << endl;
    auto y = decltype(bla)::bla{};
    y.foo();
    y.bar();
  }

  {
    Property<Overloads> o;
    o.foo();
    o.foo(0);
    o.bar<int>();
  }

  {
    Property<GenericClassA> a;
    a.foobar();
    a.foobar(1);
    a.foobar(1.0);
    static_assert(is_same<decltype(a)::some_type, GenericClassA::some_type>::value);

    Property<GenericClassB> b;
    b.foobar();
    b.foobar(1);
    static_assert(is_same<decltype(b)::some_type, GenericClassB::some_type>::value);

    Property<ClassTemplate<int>> c;
    c.foobarbaz();
    static_assert(is_same<decltype(c)::some_foo_type, ClassTemplate<int>::some_foo_type>::value);

    Property<ClassTemplate<float>> d;
    d.foobarbaz();
    static_assert(is_same<decltype(d)::some_foo_type, ClassTemplate<float>::some_foo_type>::value);
  }

  {
    Property<ConstClass> non_const_obj;
    const Property<ConstClass> const_obj;

    non_const_obj.foo();  // Should compile
    non_const_obj.bar();  // Should compile
    const_obj.foo();      // Should compile
    // const_obj.bar();      // Should not compile
  }

  {
    Property<RefClass> obj;
    const Property<RefClass> cobj;

    obj.foo(); // "RefClass::foo() &"
    move(obj).foo(); // "RefClass::foo() &&"
    cobj.foo(); // "RefClass::foo() const &"
    move(cobj).foo(); // "RefClass::foo() const &&"
  }

  {
    Property<Foo> foo;
    Property<Derived> derived;
    Property<MoreDerived> moreDerived;
    Property<ClassTemplate<int>> tmpl;

    asdf(foo);          // "asdf(Foo)"
    asdf(derived);      // "asdf(Derived)"
    asdf(moreDerived);  // "asdf(Derived)"
    asdf(tmpl);         // "asdf(ClassTemplate<T>)"
  }

  {
                           foobar2::A   tmpl1;
             ClassTemplate<foobar2::A > tmpl2;
             ClassTemplate<foobar2::B > tmpl3;
    Property<              foobar2::A > tmpl4;
    Property<ClassTemplate<foobar2::A>> tmpl5;
    Property<ClassTemplate<foobar2::B>> tmpl6;

    using reflectable::qwerty;
    qwerty<int>(tmpl1);
    qwerty<int>(tmpl2);
    qwerty<int>(tmpl3);
    qwerty<int>(tmpl4);
    qwerty<int>(tmpl5);
    qwerty<int>(tmpl6);
  }
}
<commit_msg>Added comment<commit_after>#include "stdlibs_for_debugging.h"

#include "foobar.h"

// TODO (unit test):
// - reflection.h, REFLECTABLE(function), namespace::ClassTemplate, namespace::function(ClassTemplate), SmartRef
// - also make sure that no invalid free functions are added (e.g. push_back on a vector)

#include <smartref/smartref.h>

#include <iostream>
#include <vector>
#include <typeinfo>
#include <iterator>

using namespace std;
using namespace foobar;
using smartref::using_;

template<typename T>
class Property : public using_<T>
{
// TODO: Add proper reference-leaking control by allowing
//       the user-defined conversion functions to be private.
public:
  using using_<T>::operator=;

  Property() = default;
  Property(T value) : data{value} {}

  operator T &() &
  {
    return data;
  }

  operator T &&() &&
  {
    return move(data);
  }

  operator const T &() const &
  {
    return data;
  }

  operator const T &&() const &&
  {
    return move(data);
  }

public:
  T data;
};

/*
class JSONValue : public using_<JSONValue, double>,
          public using_<JSONValue, string>,
          public using_<JSONValue, vector<JSONValue>>,
          public using_<JSONValue, map<JSONValue, JSONValue>>
{
public:
  operator double &()
  {
    return get<double>(data);
  }

  operator double &()
  {
    return get<string>(data);
  }

  operator double &()
  {
    return get<vector<JSONValue>>(data);
  }

  operator double &()
  {
    return get<map<JSONValue, JSONValue>>(data);
  }

private:
  variant<
    double,
    string,
    vector<JSONValue>,
    map<JSONValue, JSONValue>
  > data;
};
*/

namespace foobar {

void asdf(Foo)              { cout << "asdf(Foo)"              << endl; }
void asdf(Derived)          { cout << "asdf(Derived)"          << endl; }

template<typename T>
void asdf(ClassTemplate<T>) { cout << "asdf(ClassTemplate<T>)" << endl; }

} // namespace foobar

namespace foobar2 {

struct A {};
struct B {};

template<typename>
void qwerty(A)
{
  cout << "foobar2::qwerty<T>(A)" << endl;
}

template<typename>
void qwerty(foobar::ClassTemplate<A>)
{
  cout << "foobar2::qwerty<T>(foobar::ClassTemplate<A>)" << endl;
}

template<typename, typename U>
void qwerty(foobar::ClassTemplate<U>)
{
  cout << "foobar2::qwerty<T>(foobar::ClassTemplate<U>)" << endl;
}

} // namespace foobar2

int main()
{
/*
  JSONValue json = {};

  json["asdf"] = 1.0;
  json[123456] = nullptr;
  json.DOT(qwerty) = "the other (third) operator dot proposal";
  json.qwerty = "__getattr__ for C++";
*/

  cout << "Hello, Wandbox!" << endl;

  Property<vector<int>> v;

  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  // The following statements should *not* compile
  // v.push_back(1, 2, 3);
  // push_back(v, 1);

  for (auto x : v)
  {
    cout << x << endl;
  }

  // This is a great example of a fully-encapsulated smart reference:
  // back_inserter requires:
  // - push_back() member function
  // - value_type member type
  //
  // Furthermore, because of the full encapsulation of Property<T>,
  // begin(v) returns a Property<vector<int>::iterator_type>
  // Which in turn requires the following:
  // - operator* for dereferencing
  // - operator++ for incrementing
  // - operator!= for comparing begin() and end()
  //
  // And after being referenced, it returns again a Property<vector<int>::iterator &>
  // which requires:
  // - operator= for assigning the value (via push_back())
  Property<vector<float>> v2;
  copy(begin(v), end(v), back_inserter(v2));
  copy(begin(v2), end(v2), ostream_iterator<double>(cout, " "));
  cout << endl;

  Property<int> x{};
  Property<int> y{};

  x = 5;

  cout << x.data << endl;
  cout << (x = 9) << endl;

  // TODO: Proper reference leaking control
  //       i.e. {x + y} -> Property<decltype(delegate(x)+delegate(y))>
  {
    auto u = x + 1;
    auto v = 1 + y;
    auto w = x + y;
    auto z = Property<int>{x + y};

    cout << u << endl;
    cout << typeid(u).name() << endl;
    cout << v << endl;
    cout << typeid(v).name() << endl;
    cout << w << endl;
    cout << typeid(w).name() << endl;
    cout << z << endl;
    cout << typeid(z).name() << endl;
  }

  Property<Foo> foo;
  foo.foo();

  Property<Bar> bar;
  bar.bar();
  bar.bar2();
  bar.bar3();

  Property<Baz> baz;
  baz.baz();
  baz.baz2();

  Property<Bat> bat;
  bat.bat();
  bat.bat2();

  {
    Bar bar;
    bar.bar();
    bar.bar2();
    bar.bar3();

    Baz baz;
    baz.baz();
    baz.baz2();

    Bat bat;
    bat.bat();
    bat.bat2();
  }

  {
    Property<Bla> bla;
    bla.foo();
    bla.bar();
    auto x = decltype(bla)::baz{1234};
    cout << typeid(x).name() << " " << x << endl;
    auto y = decltype(bla)::bla{};
    y.foo();
    y.bar();
  }

  {
    Property<Overloads> o;
    o.foo();
    o.foo(0);
    o.bar<int>();
  }

  {
    Property<GenericClassA> a;
    a.foobar();
    a.foobar(1);
    a.foobar(1.0);
    static_assert(is_same<decltype(a)::some_type, GenericClassA::some_type>::value);

    Property<GenericClassB> b;
    b.foobar();
    b.foobar(1);
    static_assert(is_same<decltype(b)::some_type, GenericClassB::some_type>::value);

    Property<ClassTemplate<int>> c;
    c.foobarbaz();
    static_assert(is_same<decltype(c)::some_foo_type, ClassTemplate<int>::some_foo_type>::value);

    Property<ClassTemplate<float>> d;
    d.foobarbaz();
    static_assert(is_same<decltype(d)::some_foo_type, ClassTemplate<float>::some_foo_type>::value);
  }

  {
    Property<ConstClass> non_const_obj;
    const Property<ConstClass> const_obj;

    non_const_obj.foo();  // Should compile
    non_const_obj.bar();  // Should compile
    const_obj.foo();      // Should compile
    // const_obj.bar();      // Should not compile
  }

  {
    Property<RefClass> obj;
    const Property<RefClass> cobj;

    obj.foo(); // "RefClass::foo() &"
    move(obj).foo(); // "RefClass::foo() &&"
    cobj.foo(); // "RefClass::foo() const &"
    move(cobj).foo(); // "RefClass::foo() const &&"
  }

  {
    Property<Foo> foo;
    Property<Derived> derived;
    Property<MoreDerived> moreDerived;
    Property<ClassTemplate<int>> tmpl;

    asdf(foo);          // "asdf(Foo)"
    asdf(derived);      // "asdf(Derived)"
    asdf(moreDerived);  // "asdf(Derived)"
    asdf(tmpl);         // "asdf(ClassTemplate<T>)"
  }

  {
                           foobar2::A   tmpl1;
             ClassTemplate<foobar2::A > tmpl2;
             ClassTemplate<foobar2::B > tmpl3;
    Property<              foobar2::A > tmpl4;
    Property<ClassTemplate<foobar2::A>> tmpl5;
    Property<ClassTemplate<foobar2::B>> tmpl6;

    using reflectable::qwerty;
    qwerty<int>(tmpl1);
    qwerty<int>(tmpl2);
    qwerty<int>(tmpl3);
    qwerty<int>(tmpl4);
    qwerty<int>(tmpl5);
    qwerty<int>(tmpl6);
  }
}
<|endoftext|>


<commit_before>// Copyright 2020 PAL Robotics SL
//
// 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.

#include <chrono>
#include <cstddef>
#include <memory>
#include <thread>

#include "control_toolbox/pid_ros.hpp"

#include "gtest/gtest.h"

#include "rclcpp/duration.hpp"
#include "rclcpp/executors.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "rclcpp/utilities.hpp"

using PidStateMsg = control_msgs::msg::PidState;
using rclcpp::executors::MultiThreadedExecutor;

TEST(PidPublihserTest, PublishTest)
{
  const size_t ATTEMPTS = 100;
  const std::chrono::milliseconds DELAY(250);

  auto node = std::make_shared<rclcpp::Node>("pid_publisher_test");

  control_toolbox::PidROS<rclcpp::Node> pid_ros(node);

  pid_ros.initPid(1.0, 1.0, 1.0, 5.0, -5.0, false);

  bool callback_called = false;
  control_msgs::msg::PidState::SharedPtr last_state_msg;
  auto state_callback = [&](const control_msgs::msg::PidState::SharedPtr)
    {
      callback_called = true;
    };

  auto state_sub = node->create_subscription<control_msgs::msg::PidState>(
    "/pid_state", rclcpp::SensorDataQoS(), state_callback);

  double command = pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
  EXPECT_EQ(-1.5, command);

  // wait for callback
  for (size_t i = 0; i < ATTEMPTS && !callback_called; ++i) {
    pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
    rclcpp::spin_some(node);
    std::this_thread::sleep_for(DELAY);
  }

  ASSERT_TRUE(callback_called);
}

TEST(PidPublihserTest, PublishTestLifecycle)
{
  const size_t ATTEMPTS = 100;
  const std::chrono::milliseconds DELAY(250);

  auto node = std::make_shared<rclcpp_lifecycle::LifecycleNode>("pid_publisher_test");

  control_toolbox::PidROS<rclcpp_lifecycle::LifecycleNode> pid_ros(node);

  auto state_pub_lifecycle_ =
      std::dynamic_pointer_cast<rclcpp_lifecycle::LifecyclePublisher<control_msgs::msg::PidState>>(
      pid_ros.getPidStatePublisher());
    state_pub_lifecycle_->on_activate();

  pid_ros.initPid(1.0, 1.0, 1.0, 5.0, -5.0, false);

  bool callback_called = false;
  control_msgs::msg::PidState::SharedPtr last_state_msg;
  auto state_callback = [&](const control_msgs::msg::PidState::SharedPtr)
    {
      callback_called = true;
    };

  auto state_sub = node->create_subscription<control_msgs::msg::PidState>(
    "/pid_state", rclcpp::SensorDataQoS(), state_callback);

  double command = pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
  EXPECT_EQ(-1.5, command);

  // wait for callback
  for (size_t i = 0; i < ATTEMPTS && !callback_called; ++i) {
    pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
    rclcpp::spin_some(node->get_node_base_interface());
    std::this_thread::sleep_for(DELAY);
  }

  ASSERT_TRUE(callback_called);
}

int main(int argc, char ** argv)
{
  testing::InitGoogleTest(&argc, argv);
  rclcpp::init(0, nullptr);
  return RUN_ALL_TESTS();
}
<commit_msg>minor spelling fix<commit_after>// Copyright 2020 PAL Robotics SL
//
// 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.

#include <chrono>
#include <cstddef>
#include <memory>
#include <thread>

#include "control_toolbox/pid_ros.hpp"

#include "gtest/gtest.h"

#include "rclcpp/duration.hpp"
#include "rclcpp/executors.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "rclcpp/utilities.hpp"

using PidStateMsg = control_msgs::msg::PidState;
using rclcpp::executors::MultiThreadedExecutor;

TEST(PidPublisherTest, PublishTest)
{
  const size_t ATTEMPTS = 100;
  const std::chrono::milliseconds DELAY(250);

  auto node = std::make_shared<rclcpp::Node>("pid_publisher_test");

  control_toolbox::PidROS<rclcpp::Node> pid_ros(node);

  pid_ros.initPid(1.0, 1.0, 1.0, 5.0, -5.0, false);

  bool callback_called = false;
  control_msgs::msg::PidState::SharedPtr last_state_msg;
  auto state_callback = [&](const control_msgs::msg::PidState::SharedPtr)
    {
      callback_called = true;
    };

  auto state_sub = node->create_subscription<control_msgs::msg::PidState>(
    "/pid_state", rclcpp::SensorDataQoS(), state_callback);

  double command = pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
  EXPECT_EQ(-1.5, command);

  // wait for callback
  for (size_t i = 0; i < ATTEMPTS && !callback_called; ++i) {
    pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
    rclcpp::spin_some(node);
    std::this_thread::sleep_for(DELAY);
  }

  ASSERT_TRUE(callback_called);
}

TEST(PidPublisherTest, PublishTestLifecycle)
{
  const size_t ATTEMPTS = 100;
  const std::chrono::milliseconds DELAY(250);

  auto node = std::make_shared<rclcpp_lifecycle::LifecycleNode>("pid_publisher_test");

  control_toolbox::PidROS<rclcpp_lifecycle::LifecycleNode> pid_ros(node);

  auto state_pub_lifecycle_ =
      std::dynamic_pointer_cast<rclcpp_lifecycle::LifecyclePublisher<control_msgs::msg::PidState>>(
      pid_ros.getPidStatePublisher());
    state_pub_lifecycle_->on_activate();

  pid_ros.initPid(1.0, 1.0, 1.0, 5.0, -5.0, false);

  bool callback_called = false;
  control_msgs::msg::PidState::SharedPtr last_state_msg;
  auto state_callback = [&](const control_msgs::msg::PidState::SharedPtr)
    {
      callback_called = true;
    };

  auto state_sub = node->create_subscription<control_msgs::msg::PidState>(
    "/pid_state", rclcpp::SensorDataQoS(), state_callback);

  double command = pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
  EXPECT_EQ(-1.5, command);

  // wait for callback
  for (size_t i = 0; i < ATTEMPTS && !callback_called; ++i) {
    pid_ros.computeCommand(-0.5, rclcpp::Duration(1, 0));
    rclcpp::spin_some(node->get_node_base_interface());
    std::this_thread::sleep_for(DELAY);
  }

  ASSERT_TRUE(callback_called);
}

int main(int argc, char ** argv)
{
  testing::InitGoogleTest(&argc, argv);
  rclcpp::init(0, nullptr);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    fltkGlWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * 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.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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 <itkWindows.h>
#include <fltkGlWindow.h>
#include <fstream>
#include <FL/fl_ask.H>
#include <FL/fl_file_chooser.H>

namespace fltk {

//--------------------------------------------------
//
//    Creator
//
//--------------------------------------------------
GlWindow::GlWindow(int x,int y,int w,int h, const char * label)
  :Fl_Gl_Window(x,y,w,h,label)
{
  m_RedrawCommand = RedrawCommandType::New();
  m_RedrawCommand->SetWidget( this );
  m_Notifier   = itk::LightObject::New();
}

//--------------------------------------------------
//
//    Destructor
//
//--------------------------------------------------
GlWindow::~GlWindow()
{

}

//--------------------------------------------------
//
//    Grab Image and Store in a PPM file
//    This is the user interface part.
//
//--------------------------------------------------
void GlWindow::SaveImage(void)
{

  const char * filename =
        fl_file_chooser("Please select a file name","*.ppm","");

  if( !filename ) return;

  SaveImage( filename );

}

//------------------------------------------
//
//    Return Redraw Command
//
//------------------------------------------
const GlWindow::RedrawCommandType::Pointer &
GlWindow
::GetRedrawCommand(  void )
{

  return m_RedrawCommand;

}

//------------------------------------------
//
//    Return Notifier Object
//    this is used by observers interested
//    in events generated by GlWindow
//
//------------------------------------------
itk::LightObject::Pointer &
GlWindow::GetNotifier(  void )
{
  return m_Notifier;
}

//--------------------------------------------------
//
//    Grab Image and Store in a PPM file
//
//--------------------------------------------------
void GlWindow::SaveImage(const char * filename)
{

  if( !filename )
  {
    return;
  }

  if( strlen(filename) == 0 )
  {
    return;
  }

  const int wnx = w();
  const int wny = h();

/*
  ::std::ofstream  of;
  of.open(filename);
  if( of.fail() )
  {
    fl_alert("Error opening file %s",filename);
    return;
  }

  unsigned char *image = new unsigned char[ wnx * wny * 8 ];

  if( !image )
  {
    fl_alert("Problem","Allocating memory for image grabbing buffer");
    of.close();
    return;
  }

  of << "P6" << std::endl;      // Magic number for PPM files
  of << wnx << " " << wny << std::endl;

  of << 255 << std::endl;

  make_current();
  draw();

  glReadBuffer(GL_FRONT);
  glReadPixels(0,0,wnx,wny,GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid *)image);

  bool firstPixel = true;

  for(int y=wny-1; y>=0; y--)
  {
    unsigned char *p = image + 4*y*wnx;
    for(int x=0; x<wnx; x++)
    {
      const unsigned char red   = *p++;
      const unsigned char green = *p++;
      const unsigned char blue  = *p++;
                                   p++; // alpha channel
      if( firstPixel )
      {
        of << green << blue;
        firstPixel = false;
      }
      else
      {
        of << red << green << blue;
      }
    }
  }

  of.close();

  delete [] image;

  */
}

} // end namespace fltk

<commit_msg>ENH: itkWindows include is now conditioned to _WIN32<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    fltkGlWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * 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.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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.

=========================================================================*/

#if    defined(_WIN32)
#include <itkWindows.h>
#endif

#include <fltkGlWindow.h>
#include <fstream>
#include <FL/fl_ask.H>
#include <FL/fl_file_chooser.H>

namespace fltk {

//--------------------------------------------------
//
//    Creator
//
//--------------------------------------------------
GlWindow::GlWindow(int x,int y,int w,int h, const char * label)
  :Fl_Gl_Window(x,y,w,h,label)
{
  m_RedrawCommand = RedrawCommandType::New();
  m_RedrawCommand->SetWidget( this );
  m_Notifier   = itk::LightObject::New();
}

//--------------------------------------------------
//
//    Destructor
//
//--------------------------------------------------
GlWindow::~GlWindow()
{

}

//--------------------------------------------------
//
//    Grab Image and Store in a PPM file
//    This is the user interface part.
//
//--------------------------------------------------
void GlWindow::SaveImage(void)
{

  const char * filename =
        fl_file_chooser("Please select a file name","*.ppm","");

  if( !filename ) return;

  SaveImage( filename );

}

//------------------------------------------
//
//    Return Redraw Command
//
//------------------------------------------
const GlWindow::RedrawCommandType::Pointer &
GlWindow
::GetRedrawCommand(  void )
{

  return m_RedrawCommand;

}

//------------------------------------------
//
//    Return Notifier Object
//    this is used by observers interested
//    in events generated by GlWindow
//
//------------------------------------------
itk::LightObject::Pointer &
GlWindow::GetNotifier(  void )
{
  return m_Notifier;
}

//--------------------------------------------------
//
//    Grab Image and Store in a PPM file
//
//--------------------------------------------------
void GlWindow::SaveImage(const char * filename)
{

  if( !filename )
  {
    return;
  }

  if( strlen(filename) == 0 )
  {
    return;
  }

  const int wnx = w();
  const int wny = h();

/*
  ::std::ofstream  of;
  of.open(filename);
  if( of.fail() )
  {
    fl_alert("Error opening file %s",filename);
    return;
  }

  unsigned char *image = new unsigned char[ wnx * wny * 8 ];

  if( !image )
  {
    fl_alert("Problem","Allocating memory for image grabbing buffer");
    of.close();
    return;
  }

  of << "P6" << std::endl;      // Magic number for PPM files
  of << wnx << " " << wny << std::endl;

  of << 255 << std::endl;

  make_current();
  draw();

  glReadBuffer(GL_FRONT);
  glReadPixels(0,0,wnx,wny,GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid *)image);

  bool firstPixel = true;

  for(int y=wny-1; y>=0; y--)
  {
    unsigned char *p = image + 4*y*wnx;
    for(int x=0; x<wnx; x++)
    {
      const unsigned char red   = *p++;
      const unsigned char green = *p++;
      const unsigned char blue  = *p++;
                                   p++; // alpha channel
      if( firstPixel )
      {
        of << green << blue;
        firstPixel = false;
      }
      else
      {
        of << red << green << blue;
      }
    }
  }

  of.close();

  delete [] image;

  */
}

} // end namespace fltk

<|endoftext|>


<commit_before>#include "Benchmark.h"
#include <iostream>
#include <stdlib.h>     /* srand, rand */
#include <cassert>

Benchmark::Benchmark(const unsigned int nOperations) {
    m_nOperations = nOperations;
}

void Benchmark::SingleAllocation(Allocator* allocator, const std::size_t size, const std::size_t alignment) {
    std::cout << "BENCHMARK: ALLOCATION" << std::endl;
    std::cout << "\tSize:     \t" << size << std::endl;
    std::cout << "\tAlignment\t" << alignment << std::endl;

    setTimer(m_start);

    allocator->Init();
    unsigned int operations = 0;
    while (operations < m_nOperations) {
        allocator->Allocate(size, alignment);
        ++operations;
    }
    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);
}

void Benchmark::SingleFree(Allocator* allocator, const std::size_t size, const std::size_t alignment) {
    std::cout << "BENCHMARK: ALLOCATION/FREE" << std::endl;
    std::cout << "\tSize:     \t" << size << std::endl;
    std::cout << "\tAlignment\t" << alignment << std::endl;

    void* addresses[m_nOperations];

    setTimer(m_start);

    allocator->Init();
    int operations = 0;
    while (operations < m_nOperations) {
        addresses[operations] = allocator->Allocate(size, alignment);
        ++operations;
    }
    --operations;
    while (operations >= 0) {
        allocator->Free(addresses[operations]);
        --operations;
    }

    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);
}

void Benchmark::MultipleAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    assert(allocationSizes.size() == alignments.size() && "Allocation sizes and Alignments must have same length");

    for (int i = 0; i < allocationSizes.size(); ++i) {
        SingleAllocation(allocator, allocationSizes[i], alignments[i]);
    }
}

void Benchmark::MultipleFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    assert(allocationSizes.size() == alignments.size() && "Allocation sizes and Alignments must have same length");

    for (int i = 0; i < allocationSizes.size(); ++i) {
        SingleFree(allocator, allocationSizes[i], alignments[i]);
    }
}

void Benchmark::RandomAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    srand(1);

    std::cout << "\tBENCHMARK: ALLOCATION" << std::endl;

    setTimer(m_start);
    std::size_t allocation_size;
    std::size_t alignment;

    allocator->Init();
    unsigned int operations = 0;
    while (operations < m_nOperations) {
        this->RandomAllocationAttr(allocationSizes, alignments, allocation_size, alignment);
        allocator->Allocate(allocation_size, alignment);
        ++operations;
    }
    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);

}

void Benchmark::RandomFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    srand(1);

    std::cout << "\tBENCHMARK: ALLOCATION/FREE" << std::endl;

    setTimer(m_start);

    void* addresses[m_nOperations];
    std::size_t allocation_size;
    std::size_t alignment;

    allocator->Init();
    int operations = 0;
    while (operations < m_nOperations) {
        this->RandomAllocationAttr(allocationSizes, alignments, allocation_size, alignment);
        addresses[operations] = allocator->Allocate(allocation_size, alignment);
        ++operations;
    }
    --operations;
    while (operations >= 0) {
        allocator->Free(addresses[operations]);
        --operations;
    }

    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);

}

void Benchmark::setTimer(timespec& timer) {
    clock_gettime(CLOCK_REALTIME, &timer);
}

const double Benchmark::calculateElapsedTime() const {
    timespec temp;
    if ((m_end.tv_nsec - m_start.tv_nsec) < 0) {
        temp.tv_sec = m_end.tv_sec - m_start.tv_sec - 1;
        temp.tv_nsec = 1e9 + m_end.tv_nsec - m_start.tv_nsec;
    } else {
        temp.tv_sec = m_end.tv_sec - m_start.tv_sec;
        temp.tv_nsec = m_end.tv_nsec - m_start.tv_nsec;
    }

    const double time_sec = (double) temp.tv_sec;
    const double time_nsec = (double) temp.tv_nsec;
    const double time_msec = (time_sec * 1e3) + (time_nsec / 1e6);

    return time_msec;
}

void Benchmark::printResults(const BenchmarkResults& results) const {
    std::cout << "\tRESULTS:" << std::endl;
    std::cout << "\t\tOperations:    \t" << results.nOperations << std::endl;
    std::cout << "\t\tTime elapsed:  \t" << results.elapsedTime << " ms" << std::endl;
    std::cout << "\t\tOp per sec:    \t" << results.operationsPerSec << " ops/ms" << std::endl;
    std::cout << "\t\tTimer per op:  \t" << results.timePerOperation << " ms/ops" << std::endl;
    std::cout << "\t\tMemory peak:   \t" << results.memoryPeak << " bytes" << std::endl;

    std::cout << std::endl;
}

const BenchmarkResults Benchmark::buildResults(const unsigned int nOperations, const double elapsedTime, const std::size_t memoryPeak) const {
    BenchmarkResults results;

    results.nOperations = nOperations;
    results.elapsedTime = elapsedTime;
    results.operationsPerSec = results.nOperations / results.elapsedTime;
    results.timePerOperation = results.elapsedTime / results.nOperations;
    results.memoryPeak = memoryPeak;

    return results;
}

void Benchmark::RandomAllocationAttr(const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments, std::size_t & size, std::size_t & alignment) {
    const int r = rand() % allocationSizes.size();
    size = allocationSizes[r];
    alignment = alignments[r];
}

<commit_msg>Commented benchmark info because its not used<commit_after>#include "Benchmark.h"
#include <iostream>
#include <stdlib.h>     /* srand, rand */
#include <cassert>

Benchmark::Benchmark(const unsigned int nOperations) {
    m_nOperations = nOperations;
}

void Benchmark::SingleAllocation(Allocator* allocator, const std::size_t size, const std::size_t alignment) {
    //std::cout << "BENCHMARK: ALLOCATION" << std::endl;
    //std::cout << "\tSize:     \t" << size << std::endl;
    //std::cout << "\tAlignment\t" << alignment << std::endl;

    setTimer(m_start);

    allocator->Init();
    unsigned int operations = 0;
    while (operations < m_nOperations) {
        allocator->Allocate(size, alignment);
        ++operations;
    }
    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);
}

void Benchmark::SingleFree(Allocator* allocator, const std::size_t size, const std::size_t alignment) {
    std::cout << "BENCHMARK: ALLOCATION/FREE" << std::endl;
    std::cout << "\tSize:     \t" << size << std::endl;
    std::cout << "\tAlignment\t" << alignment << std::endl;

    void* addresses[m_nOperations];

    setTimer(m_start);

    allocator->Init();
    int operations = 0;
    while (operations < m_nOperations) {
        addresses[operations] = allocator->Allocate(size, alignment);
        ++operations;
    }
    --operations;
    while (operations >= 0) {
        allocator->Free(addresses[operations]);
        --operations;
    }

    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);
}

void Benchmark::MultipleAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    assert(allocationSizes.size() == alignments.size() && "Allocation sizes and Alignments must have same length");

    for (int i = 0; i < allocationSizes.size(); ++i) {
        SingleAllocation(allocator, allocationSizes[i], alignments[i]);
    }
}

void Benchmark::MultipleFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    assert(allocationSizes.size() == alignments.size() && "Allocation sizes and Alignments must have same length");

    for (int i = 0; i < allocationSizes.size(); ++i) {
        SingleFree(allocator, allocationSizes[i], alignments[i]);
    }
}

void Benchmark::RandomAllocation(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    srand(1);

    std::cout << "\tBENCHMARK: ALLOCATION" << std::endl;

    setTimer(m_start);
    std::size_t allocation_size;
    std::size_t alignment;

    allocator->Init();
    unsigned int operations = 0;
    while (operations < m_nOperations) {
        this->RandomAllocationAttr(allocationSizes, alignments, allocation_size, alignment);
        allocator->Allocate(allocation_size, alignment);
        ++operations;
    }
    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);

}

void Benchmark::RandomFree(Allocator* allocator, const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments) {
    srand(1);

    std::cout << "\tBENCHMARK: ALLOCATION/FREE" << std::endl;

    setTimer(m_start);

    void* addresses[m_nOperations];
    std::size_t allocation_size;
    std::size_t alignment;

    allocator->Init();
    int operations = 0;
    while (operations < m_nOperations) {
        this->RandomAllocationAttr(allocationSizes, alignments, allocation_size, alignment);
        addresses[operations] = allocator->Allocate(allocation_size, alignment);
        ++operations;
    }
    --operations;
    while (operations >= 0) {
        allocator->Free(addresses[operations]);
        --operations;
    }

    setTimer(m_end);

    BenchmarkResults results = buildResults(m_nOperations, calculateElapsedTime(), allocator->m_peak);
    printResults(results);

}

void Benchmark::setTimer(timespec& timer) {
    clock_gettime(CLOCK_REALTIME, &timer);
}

const double Benchmark::calculateElapsedTime() const {
    timespec temp;
    if ((m_end.tv_nsec - m_start.tv_nsec) < 0) {
        temp.tv_sec = m_end.tv_sec - m_start.tv_sec - 1;
        temp.tv_nsec = 1e9 + m_end.tv_nsec - m_start.tv_nsec;
    } else {
        temp.tv_sec = m_end.tv_sec - m_start.tv_sec;
        temp.tv_nsec = m_end.tv_nsec - m_start.tv_nsec;
    }

    const double time_sec = (double) temp.tv_sec;
    const double time_nsec = (double) temp.tv_nsec;
    const double time_msec = (time_sec * 1e3) + (time_nsec / 1e6);

    return time_msec;
}

void Benchmark::printResults(const BenchmarkResults& results) const {
    //std::cout << "\tRESULTS:" << std::endl;
    std::cout << "\t\tOperations:    \t" << results.nOperations << std::endl;
    std::cout << "\t\tTime elapsed:  \t" << results.elapsedTime << " ms" << std::endl;
    //std::cout << "\t\tOp per sec:    \t" << results.operationsPerSec << " ops/ms" << std::endl;
    //std::cout << "\t\tTimer per op:  \t" << results.timePerOperation << " ms/ops" << std::endl;
    std::cout << "\t\tMemory peak:   \t" << results.memoryPeak << " bytes" << std::endl;

    std::cout << std::endl;
}

const BenchmarkResults Benchmark::buildResults(const unsigned int nOperations, const double elapsedTime, const std::size_t memoryPeak) const {
    BenchmarkResults results;

    results.nOperations = nOperations;
    results.elapsedTime = elapsedTime;
    results.operationsPerSec = results.nOperations / results.elapsedTime;
    results.timePerOperation = results.elapsedTime / results.nOperations;
    results.memoryPeak = memoryPeak;

    return results;
}

void Benchmark::RandomAllocationAttr(const std::vector<std::size_t>& allocationSizes, const std::vector<std::size_t>& alignments, std::size_t & size, std::size_t & alignment) {
    const int r = rand() % allocationSizes.size();
    size = allocationSizes[r];
    alignment = alignments[r];
}

<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include "expander.hpp"

using namespace std;

namespace bohrium {
namespace filter {
namespace composite {

int Expander::expand_sign(bh_ir& bhir, int pc)
{
    int start_pc = pc;
    bh_instruction& composite = bhir.instr_list[pc];
    composite.opcode = BH_NONE; // Easy choice... no re-use just NOOP it.

    bh_view out     = composite.operand[0];             // Grab operands
    bh_view input   = composite.operand[1];

    bh_type input_type = input.base->type;
                                                            // NON-COMPLEX input-type
    if (!((input_type == BH_COMPLEX64) || (input_type == BH_COMPLEX128))) {
                                                            // Construct temps
        bh_view t1_bool = input; t1_bool.base = make_base(BH_BOOL, input.base->nelem);
        bh_view t1 = input; t1.base = make_base(input.base->type, input.base->nelem);
        bh_view t2_bool = input; t2_bool.base = make_base(BH_BOOL, input.base->nelem);
        bh_view t2 = input; t2.base = make_base(input.base->type, input.base->nelem);

        inject(bhir, ++pc, BH_LESS, t1_bool, input, 0.0);   // Expand sequence
        inject(bhir, ++pc, BH_IDENTITY, t1, t1_bool);
        inject(bhir, ++pc, BH_FREE, t1_bool);
        inject(bhir, ++pc, BH_DISCARD, t1_bool);

        inject(bhir, ++pc, BH_GREATER, t2_bool, input, 0.0);
        inject(bhir, ++pc, BH_IDENTITY, t2, t2_bool);
        inject(bhir, ++pc, BH_FREE, t2_bool);
        inject(bhir, ++pc, BH_DISCARD, t2_bool);

        inject(bhir, ++pc, BH_SUBTRACT, out, t2, t1);
        inject(bhir, ++pc, BH_FREE, t1);
        inject(bhir, ++pc, BH_DISCARD, t1);
        inject(bhir, ++pc, BH_FREE, t2);
        inject(bhir, ++pc, BH_DISCARD, t2);
    } else {                                                // COMPLEX input-type
        bh_type real_type = (input_type == BH_COMPLEX64) ? BH_FLOAT32 : BH_FLOAT64;

        bh_view input_r = input; input_r.base = make_base(real_type, out.base->nelem);
        inject(bhir, ++pc, BH_REAL, input_r, input);
                                                            // Construct temps
        bh_view t1_bool = input_r; t1_bool.base = make_base(BH_BOOL, input.base->nelem);
        bh_view t1 = input_r; t1.base = make_base(real_type, input_r.base->nelem);
        bh_view t2_bool = input_r; t2_bool.base = make_base(BH_BOOL, input_r.base->nelem);
        bh_view t2 = input_r; t2.base = make_base(real_type, input_r.base->nelem);
        bh_view t3 = input_r; t3.base = make_base(real_type, input_r.base->nelem);

        inject(bhir, ++pc, BH_LESS, t1_bool, input_r, 0.0); // Expand sequence
        inject(bhir, ++pc, BH_IDENTITY, t1, t1_bool);
        inject(bhir, ++pc, BH_FREE, t1_bool);
        inject(bhir, ++pc, BH_DISCARD, t1_bool);

        inject(bhir, ++pc, BH_GREATER, t2_bool, input_r, 0.0);
        inject(bhir, ++pc, BH_IDENTITY, t2, t2_bool);
        inject(bhir, ++pc, BH_FREE, t2_bool);
        inject(bhir, ++pc, BH_DISCARD, t2_bool);

        inject(bhir, ++pc, BH_FREE, input_r);
        inject(bhir, ++pc, BH_DISCARD, input_r);

        inject(bhir, ++pc, BH_SUBTRACT, t3, t2, t1);
        inject(bhir, ++pc, BH_FREE, t1);
        inject(bhir, ++pc, BH_DISCARD, t1);
        inject(bhir, ++pc, BH_FREE, t2);
        inject(bhir, ++pc, BH_DISCARD, t2);

        inject(bhir, ++pc, BH_IDENTITY, out, t3);
        inject(bhir, ++pc, BH_FREE, t3);
        inject(bhir, ++pc, BH_DISCARD, t3);
    }

    return pc-start_pc;
}

}}}
<commit_msg>composite_expansion: Constructed contiguous meta for temps.<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include "expander.hpp"

using namespace std;

namespace bohrium {
namespace filter {
namespace composite {

int Expander::expand_sign(bh_ir& bhir, int pc)
{
    int start_pc = pc;
    bh_instruction& composite = bhir.instr_list[pc];
    composite.opcode = BH_NONE; // Lazy choice... no re-use just NOP it.

    bh_view out     = composite.operand[0];         // Grab operands
    bh_view input   = composite.operand[1];

    bh_type input_type = input.base->type;          // Grab the input-type

    bh_view meta = composite.operand[0];            // Inherit ndim and shape
    meta.start = 0;
    bh_intp nelements = 1;                          // Count number of elements
    for(bh_intp dim=meta.ndim-1; dim >= 0; --dim) { // Contiguous stride
        meta.stride[dim] = nelements;
        nelements *= meta.shape[dim];
    }
                                                            // NON-COMPLEX input-type
    if (!((input_type == BH_COMPLEX64) || (input_type == BH_COMPLEX128))) {
                                                            // Construct temps
        bh_view t1_bool = make_temp(meta, BH_BOOL, nelements);
        bh_view t1      = make_temp(meta, input_type, nelements);
        bh_view t2_bool = make_temp(meta, BH_BOOL, nelements);
        bh_view t2      = make_temp(meta, input_type, nelements);

        inject(bhir, ++pc, BH_LESS, t1_bool, input, 0.0);   // Expand sequence
        inject(bhir, ++pc, BH_IDENTITY, t1, t1_bool);
        inject(bhir, ++pc, BH_FREE, t1_bool);
        inject(bhir, ++pc, BH_DISCARD, t1_bool);

        inject(bhir, ++pc, BH_GREATER, t2_bool, input, 0.0);
        inject(bhir, ++pc, BH_IDENTITY, t2, t2_bool);
        inject(bhir, ++pc, BH_FREE, t2_bool);
        inject(bhir, ++pc, BH_DISCARD, t2_bool);

        inject(bhir, ++pc, BH_SUBTRACT, out, t2, t1);
        inject(bhir, ++pc, BH_FREE, t1);
        inject(bhir, ++pc, BH_DISCARD, t1);
        inject(bhir, ++pc, BH_FREE, t2);
        inject(bhir, ++pc, BH_DISCARD, t2);
    } else {                                                // COMPLEX input-type
        bh_type real_type = (input_type == BH_COMPLEX64) ? BH_FLOAT32 : BH_FLOAT64;

                                                            // Construct temps
        bh_view input_r = make_temp(meta, real_type, nelements);
        bh_view t1_bool = make_temp(meta, BH_BOOL, nelements);
        bh_view t1      = make_temp(meta, real_type, nelements);
        bh_view t2_bool = make_temp(meta, BH_BOOL, nelements);
        bh_view t2      = make_temp(meta, real_type, nelements);
        bh_view t3      = make_temp(meta, real_type, nelements);

        inject(bhir, ++pc, BH_REAL, input_r, input);

        inject(bhir, ++pc, BH_LESS, t1_bool, input_r, 0.0); // Expand sequence
        inject(bhir, ++pc, BH_IDENTITY, t1, t1_bool);
        inject(bhir, ++pc, BH_FREE, t1_bool);
        inject(bhir, ++pc, BH_DISCARD, t1_bool);

        inject(bhir, ++pc, BH_GREATER, t2_bool, input_r, 0.0);
        inject(bhir, ++pc, BH_FREE, input_r);
        inject(bhir, ++pc, BH_DISCARD, input_r);

        inject(bhir, ++pc, BH_IDENTITY, t2, t2_bool);
        inject(bhir, ++pc, BH_FREE, t2_bool);
        inject(bhir, ++pc, BH_DISCARD, t2_bool);

        inject(bhir, ++pc, BH_SUBTRACT, t3, t2, t1);
        inject(bhir, ++pc, BH_FREE, t1);
        inject(bhir, ++pc, BH_DISCARD, t1);
        inject(bhir, ++pc, BH_FREE, t2);
        inject(bhir, ++pc, BH_DISCARD, t2);

        inject(bhir, ++pc, BH_IDENTITY, out, t3);
        inject(bhir, ++pc, BH_FREE, t3);
        inject(bhir, ++pc, BH_DISCARD, t3);
    }

    return pc-start_pc;
}

}}}
<|endoftext|>


<commit_before>#include	"ActionBattle.hh"

Action::Battle::Battle()
  : _data(*Action::data)
{
  _state = NOT_STARTED;
  _tick = 0;
}

Action::Battle::~Battle()
{
}

void		Action::Battle::_releaseKeys()
{
  for (uint8_t i = KEY_LEFT; i <= KEY_BUTTON_AUTO_B; i++)
    sdlSetButton((EKey) i, false);
}

uint8_t		Action::Battle::_getBestMove()
{
  const BattleData	&p = _data.battlers()[0];
  const BattleData	&e = _data.battlers()[1];
  const Species	&sp = _data.species(p.getSpecies());
  uint8_t	best = 0;
  uint8_t	min = 0;

  for (int m = 0; m < 4; m++)
    {
      if (p.getMove(m) && p.getPP(m))
	{
	  const Move	&move = _data.move(p.getMove(m));
	  Range		dmg = _data.potentialDamage(p, e, move);

	  if (dmg.min > min)
	    {
	      best = m;
	      min = dmg.min;
	    }
	}
    }
  return (best);
}

void		Action::Battle::_selectMove(uint8_t move, uint8_t curr)
{
  if (curr <= 1 && move > 1)
    sdlSetButton(KEY_DOWN, true);
  else if (curr > 1 && move <= 1)
    sdlSetButton(KEY_UP, true);
  else if (curr < move)
    sdlSetButton(KEY_RIGHT, true);
  else if (curr > move)
    sdlSetButton(KEY_LEFT, true);
}

void		Action::Battle::update()
{
  BattleMenu	&bm = _data.battleMenu();

  _releaseKeys();
  if (_tick = !_tick)
    return;
  if (bm.isOpen())
    {
      if (bm.getMenu() == 0)
	{
	  if (bm.getCursor() == 0)
	    sdlSetButton(KEY_BUTTON_A, true);
	}
      else if (bm.getMenu() == 1)
	{
	  uint8_t	move = _getBestMove();

	  if (bm.getAttack() == move)
	    sdlSetButton(KEY_BUTTON_A, true);
	  else
	    _selectMove(move, bm.getAttack());
	}
    }
  else
    sdlSetButton(KEY_BUTTON_A, true);
}
<commit_msg>fix: uses the weakest possible move that will kill the opponent<commit_after>#include	"ActionBattle.hh"

Action::Battle::Battle()
  : _data(*Action::data)
{
  _state = NOT_STARTED;
  _tick = 0;
}

Action::Battle::~Battle()
{
}

void		Action::Battle::_releaseKeys()
{
  for (uint8_t i = KEY_LEFT; i <= KEY_BUTTON_AUTO_B; i++)
    sdlSetButton((EKey) i, false);
}

uint8_t		Action::Battle::_getBestMove()
{
  const BattleData	&p = _data.battlers()[0];
  const BattleData	&e = _data.battlers()[1];
  const Species	&sp = _data.species(p.getSpecies());
  uint8_t	best = 0;
  uint8_t	min = 0;

  for (int m = 0; m < 4; m++)
    {
      if (p.getMove(m) && p.getPP(m))
	{
	  const Move	&move = _data.move(p.getMove(m));
	  Range		dmg = _data.potentialDamage(p, e, move);

	  if ((min < e.getHP() && dmg.min > min) || (dmg.min > e.getHP() && dmg.min < min))
	    {
	      best = m;
	      min = dmg.min;
	    }
	}
    }
  return (best);
}

void		Action::Battle::_selectMove(uint8_t move, uint8_t curr)
{
  if (curr <= 1 && move > 1)
    sdlSetButton(KEY_DOWN, true);
  else if (curr > 1 && move <= 1)
    sdlSetButton(KEY_UP, true);
  else if (curr < move)
    sdlSetButton(KEY_RIGHT, true);
  else if (curr > move)
    sdlSetButton(KEY_LEFT, true);
}

void		Action::Battle::update()
{
  BattleMenu	&bm = _data.battleMenu();

  _releaseKeys();
  if (_tick = !_tick)
    return;
  if (bm.isOpen())
    {
      if (bm.getMenu() == 0)
	{
	  if (bm.getCursor() == 0)
	    sdlSetButton(KEY_BUTTON_A, true);
	}
      else if (bm.getMenu() == 1)
	{
	  uint8_t	move = _getBestMove();

	  if (bm.getAttack() == move)
	    sdlSetButton(KEY_BUTTON_A, true);
	  else
	    _selectMove(move, bm.getAttack());
	}
    }
  else
    sdlSetButton(KEY_BUTTON_A, true);
}
<|endoftext|>


<commit_before>#include <silicium/fast_variant.hpp>
#include <ctime>

int main()
{
	Si::fast_variant<int, std::time_t, double> r(std::time(nullptr));
	return Si::visit<int>(
		r,
		[](int v)
	{
		return v;
	},
		[](std::time_t t)
	{
		return t != 0;
	},
		[](double d)
	{
		return std::isnan(d);
	});
}
<commit_msg>fix indentation<commit_after>#include <silicium/fast_variant.hpp>
#include <ctime>

int main()
{
	Si::fast_variant<int, std::time_t, double> r(std::time(nullptr));
	return Si::visit<int>(
		r,
		[](int v)
		{
			return v;
		},
		[](std::time_t t)
		{
			return t != 0;
		},
		[](double d)
		{
			return std::isnan(d);
		}
	);
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

static int nb_temporaries;

#define EIGEN_DEBUG_MATRIX_CTOR { if(size!=0) nb_temporaries++; }

#include "main.h"

#define VERIFY_EVALUATION_COUNT(XPR,N) {\
    nb_temporaries = 0; \
    XPR; \
    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
    VERIFY( (#XPR) && nb_temporaries==N ); \
  }

template<typename MatrixType> void product_notemporary(const MatrixType& m)
{
  /* This test checks the number of temporaries created
   * during the evaluation of a complex expression */

  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::RealScalar RealScalar;
  typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
  typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
  typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType;

  int rows = m.rows();
  int cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows);
  ColVectorType vc2 = ColVectorType::Random(cols), cvres(cols);
  RowMajorMatrixType rm3(rows, cols);

  Scalar s1 = ei_random<Scalar>(),
         s2 = ei_random<Scalar>(),
         s3 = ei_random<Scalar>();

  int c0 = ei_random<int>(4,cols-8),
      c1 = ei_random<int>(8,cols-c0),
      r0 = ei_random<int>(4,cols-8),
      r1 = ei_random<int>(8,rows-r0);

  VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0);

  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0);
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0);

  // NOTE this is because the Block expression is not handled yet by our expression analyser
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() = s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1) ), 1);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<Lower>() * m2, 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m1.template triangularView<Lower>().solveInPlace(m3), 0);
  VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<Lower>().solveInPlace(m3.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<Upper>(), 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<Lower>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * (s1*m2.block(r0,c0,r1,c1)), 0);
  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * m2.block(r0,c0,r1,c1), 0);

  VERIFY_EVALUATION_COUNT( m3.template selfadjointView<Lower>().rankUpdate(m2.adjoint()), 0);

  // Here we will get 1 temporary for each resize operation of the lhs operator; resize(r1,c1) would lead to zero temporaries
  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Lower>() * m2.block(r0,c0,r1,c1), 1);
  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpper>()  * m2.block(r0,c0,r1,c1), 1);

  // Zero temporaries for lazy products ...
  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose().lazyProduct(m3)).diagonal().sum(), 0 );

  // ... and one temporary for even deeply (>=2) nested products
  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose() * m3).diagonal().sum(), 1 );
  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose() * m3).diagonal().array().abs().sum(), 1 );

  // Zero temporaries for ... CoeffBasedProductMode
  // - does not work with GCC because of the <..>, we'ld need variadic macros ...
  //VERIFY_EVALUATION_COUNT( m3.col(0).head<5>() * m3.col(0).transpose() + m3.col(0).head<5>() * m3.col(0).transpose(), 0 );
}

void test_product_notemporary()
{
  int s;
  for(int i = 0; i < g_repeat; i++) {
    s = ei_random<int>(16,320);
    CALL_SUBTEST_1( product_notemporary(MatrixXf(s, s)) );
    s = ei_random<int>(16,120);
    CALL_SUBTEST_2( product_notemporary(MatrixXcd(s,s)) );
  }
}
<commit_msg>Fixed notemporary unit test.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

static int nb_temporaries;

#define EIGEN_DEBUG_MATRIX_CTOR { if(size!=0) nb_temporaries++; }

#include "main.h"

#define VERIFY_EVALUATION_COUNT(XPR,N) {\
    nb_temporaries = 0; \
    XPR; \
    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
    VERIFY( (#XPR) && nb_temporaries==N ); \
  }

template<typename MatrixType> void product_notemporary(const MatrixType& m)
{
  /* This test checks the number of temporaries created
   * during the evaluation of a complex expression */

  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::RealScalar RealScalar;
  typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
  typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
  typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType;

  int rows = m.rows();
  int cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows);
  ColVectorType vc2 = ColVectorType::Random(cols), cvres(cols);
  RowMajorMatrixType rm3(rows, cols);

  Scalar s1 = ei_random<Scalar>(),
         s2 = ei_random<Scalar>(),
         s3 = ei_random<Scalar>();

  int c0 = ei_random<int>(4,cols-8),
      c1 = ei_random<int>(8,cols-c0),
      r0 = ei_random<int>(4,cols-8),
      r1 = ei_random<int>(8,rows-r0);

  VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0);

  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0);
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0);

  // NOTE this is because the Block expression is not handled yet by our expression analyser
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() = s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1) ), 1);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<Lower>() * m2, 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m1.template triangularView<Lower>().solveInPlace(m3), 0);
  VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<Lower>().solveInPlace(m3.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<Upper>(), 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<Lower>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * (s1*m2.block(r0,c0,r1,c1)), 0);
  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * m2.block(r0,c0,r1,c1), 0);

  VERIFY_EVALUATION_COUNT( m3.template selfadjointView<Lower>().rankUpdate(m2.adjoint()), 0);

  // Here we will get 1 temporary for each resize operation of the lhs operator; resize(r1,c1) would lead to zero temporaries
  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Lower>() * m2.block(r0,c0,r1,c1), 1);
  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpper>()  * m2.block(r0,c0,r1,c1), 1);

  // Zero temporaries for lazy products ...
  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose().lazyProduct(m3)).diagonal().sum(), 0 );

  // ... and even no temporary for even deeply (>=2) nested products
  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose() * m3).diagonal().sum(), 0 );
  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose() * m3).diagonal().array().abs().sum(), 0 );

  // Zero temporaries for ... CoeffBasedProductMode
  // - does not work with GCC because of the <..>, we'ld need variadic macros ...
  //VERIFY_EVALUATION_COUNT( m3.col(0).head<5>() * m3.col(0).transpose() + m3.col(0).head<5>() * m3.col(0).transpose(), 0 );
}

void test_product_notemporary()
{
  int s;
  for(int i = 0; i < g_repeat; i++) {
    s = ei_random<int>(16,320);
    CALL_SUBTEST_1( product_notemporary(MatrixXf(s, s)) );
    s = ei_random<int>(16,120);
    CALL_SUBTEST_2( product_notemporary(MatrixXcd(s,s)) );
  }
}
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "config.h"

#ifndef DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
# define DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING 0
#endif

#include <string>
#include <vector>
#include <map>
#include <random>
#include <fstream>
#include <limits>

#include <dune/common/float_cmp.hh>
#include <dune/common/fvector.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/parallel/mpihelper.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/misc/mpimanager.hh>
#endif

#include <dune/stuff/test/gtest/gtest.h>
#include <dune/stuff/aliases.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/timedlogging.hh>
#include <dune/stuff/common/convergence-study.hh>
#include <dune/stuff/common/parallel/threadmanager.hh>

#include "common.hh"

class
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
      errors_are_not_as_expected
  : public Dune::Exception
{};

std::vector< double >
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
                      truncate_vector(const std::vector< double >& in, const size_t size)
{
  assert(size <= in.size());
  if (size == in.size())
    return in;
  else {
    std::vector< double > ret(size);
    for (size_t ii = 0; ii < size; ++ii)
      ret[ii] = in[ii];
    return ret;
  }
} // ... truncate_vector(...)

unsigned int
  DUNE_DEPRECATED_MSG()
             dsc_grid_elements()
{
  return Dune::Stuff::Test::grid_elements();
}

int main(int argc, char** argv)
{
#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  try {
#endif

    testing::InitGoogleTest(&argc, argv);
    DSC_CONFIG.read_options(argc, argv);
#if HAVE_DUNE_FEM
    Dune::Fem::MPIManager::initialize(argc, argv);
#else
    Dune::MPIHelper::instance(argc, argv);
#endif

    DSC::Logger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_DEBUG | DSC::LOG_ERROR
#elif DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_ERROR
#else
                         DSC::LOG_CONSOLE | DSC::LOG_ERROR
#endif
                                                                                , "", "", "");

    DSC::TimedLogger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                              std::numeric_limits< ssize_t >::max(),
#else
                              -1,
#endif
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                                                                    std::numeric_limits< ssize_t >::max()
#else
                                                                    -1
#endif
                                                                                );
    const auto threads = DSC_CONFIG.has_key("threading.max_count")      // <- doing this so complicated to
                         ? DSC_CONFIG.get< int >("threading.max_count") //    silence the WARNING: ...
                         : std::thread::hardware_concurrency();
    DS::threadManager().set_max_threads(threads);

    return RUN_ALL_TESTS();

#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  } catch (Dune::Exception& e) {
    std::cerr << "\nDune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << "\n" << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
#endif // DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
} // ... main(...)
<commit_msg>[tests] don't init > 1 threads w/o tbb present<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "config.h"

#ifndef DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
# define DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING 0
#endif
#ifndef DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING
# define DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING 0
#endif

#include <string>
#include <vector>
#include <map>
#include <random>
#include <fstream>
#include <limits>

#include <dune/common/float_cmp.hh>
#include <dune/common/fvector.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/parallel/mpihelper.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/misc/mpimanager.hh>
#endif

#include <dune/stuff/test/gtest/gtest.h>
#include <dune/stuff/aliases.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/timedlogging.hh>
#include <dune/stuff/common/convergence-study.hh>
#include <dune/stuff/common/parallel/threadmanager.hh>

#include "common.hh"

class
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
      errors_are_not_as_expected
  : public Dune::Exception
{};

std::vector< double >
  DUNE_DEPRECATED_MSG("Use the expectation macros of the gtest test suite (20.08.2014)!")
                      truncate_vector(const std::vector< double >& in, const size_t size)
{
  assert(size <= in.size());
  if (size == in.size())
    return in;
  else {
    std::vector< double > ret(size);
    for (size_t ii = 0; ii < size; ++ii)
      ret[ii] = in[ii];
    return ret;
  }
} // ... truncate_vector(...)

unsigned int
  DUNE_DEPRECATED_MSG()
             dsc_grid_elements()
{
  return Dune::Stuff::Test::grid_elements();
}

int main(int argc, char** argv)
{
#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  try {
#endif

    testing::InitGoogleTest(&argc, argv);
    DSC_CONFIG.read_options(argc, argv);
#if HAVE_DUNE_FEM
    Dune::Fem::MPIManager::initialize(argc, argv);
#else
    Dune::MPIHelper::instance(argc, argv);
#endif

    DSC::Logger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_DEBUG | DSC::LOG_ERROR
#elif DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                         DSC::LOG_CONSOLE | DSC::LOG_INFO | DSC::LOG_ERROR
#else
                         DSC::LOG_CONSOLE | DSC::LOG_ERROR
#endif
                                                                                , "", "", "");

    DSC::TimedLogger().create(
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_INFO_LOGGING
                              std::numeric_limits< ssize_t >::max(),
#else
                              -1,
#endif
#if DUNE_STUFF_TEST_MAIN_ENABLE_TIMED_LOGGING && DUNE_STUFF_TEST_MAIN_ENABLE_DEBUG_LOGGING
                                                                    std::numeric_limits< ssize_t >::max()
#else
                                                                    -1
#endif
                                                                                );
    const size_t threads = DSC_CONFIG.has_key("threading.max_count")      // <- doing this so complicated to
                         ? DSC_CONFIG.get< size_t >("threading.max_count") //    silence the WARNING: ...
#if HAVE_TBB
                         : std::thread::hardware_concurrency();
#else
                         : 1u;
#endif
    DS::threadManager().set_max_threads(threads);

    return RUN_ALL_TESTS();

#if DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
  } catch (Dune::Exception& e) {
    std::cerr << "\nDune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << "\n" << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
#endif // DUNE_STUFF_TEST_MAIN_CATCH_EXCEPTIONS
} // ... main(...)
<|endoftext|>


<commit_before>#include <cassert>
#include "CodeGen_Bash.h"

using namespace Bish;

void CodeGen_Bash::indent() {
    for (unsigned i = 0; i < indent_level; i++) {
        stream << "    ";
    }
}

// Return true if the given node is a statement that should be
// emitted. This excludes side-effecting statements like 'import'.
bool CodeGen_Bash::should_emit_statement(const IRNode *node) const {
    return dynamic_cast<const ImportStatement*>(node) == NULL;
}

void CodeGen_Bash::visit(Module *n) {
    for (std::vector<Assignment *>::const_iterator I = n->global_variables.begin(),
             E = n->global_variables.end(); I != E; ++I) {
        (*I)->accept(this);
        stream << ";\n";
    }
    stream << "\n";
    for (std::vector<Function *>::const_iterator I = n->functions.begin(),
             E = n->functions.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    // Insert a call to bish_main().
    assert(n->main);
    FunctionCall *call_main = new FunctionCall(n->main);
    visit(call_main);
    stream << ";\n";
    delete call_main;
}

void CodeGen_Bash::visit(Block *n) {
    if (should_print_block_braces()) stream << "{\n";
    indent_level++;

    if (!function_args_insert.empty()) {
        Function *f = function_args_insert.top();
        function_args_insert.pop();
        unsigned i = 1;
        for (std::vector<Variable *>::const_iterator I = f->args.begin(), E = f->args.end(); I != E; ++I, ++i) {
            indent();
            stream << "local " << (*I)->name.str() << "=\"$" << i << "\";\n";
        }
    }

    for (std::vector<IRNode *>::const_iterator I = n->nodes.begin(), E = n->nodes.end();
         I != E; ++I) {
        if (should_emit_statement(*I)) {
            indent();
            (*I)->accept(this);
            stream << ";\n";
        }
    }
    indent_level--;
    if (should_print_block_braces()) stream << "}\n\n";
}

void CodeGen_Bash::visit(Variable *n) {
    if (should_quote_variable()) stream << "\"";
    stream << "$" << lookup_name(n);
    if (should_quote_variable()) stream << "\"";
}

void CodeGen_Bash::visit(ReturnStatement *n) {
    bool external = dynamic_cast<ExternCall*>(n->value) != NULL;
    stream << "echo ";
    enable_functioncall_wrap();
    // Defensively wrap external calls in quotes in case they return
    // space-separated strings. Not sure how to handle this yet in the
    // general case.
    if (external) stream << "\"";
    n->value->accept(this);
    if (external) stream << "\"";
    reset_functioncall_wrap();
    stream << "; exit";
}

void CodeGen_Bash::visit(LoopControlStatement *n) {
    switch (n->op) {
    case LoopControlStatement::Break:
        stream << "break";
        break;
    case LoopControlStatement::Continue:
        stream << "continue";
        break;
    }
}

void CodeGen_Bash::visit(IfStatement *n) {
    stream << "if [[ ";
    enable_functioncall_wrap();
    n->pblock->condition->accept(this);
    if (is_equals_op(n->pblock->condition) ||
        !dynamic_cast<BinOp*>(n->pblock->condition)) {
        stream << " -eq 1";
    }
    reset_functioncall_wrap();
    stream << " ]]; then\n";
    disable_block_braces();
    n->pblock->body->accept(this);

    for (std::vector<PredicatedBlock *>::const_iterator I = n->elses.begin(),
             E = n->elses.end(); I != E; ++I) {
        indent();
        stream << "elif [[ ";
        enable_functioncall_wrap();
        (*I)->condition->accept(this);
        reset_functioncall_wrap();
        stream << " ]]; then\n";
        (*I)->body->accept(this);
    }
    if (n->elseblock) {
        indent();
        stream << "else\n";
        n->elseblock->accept(this);
    }

    reset_block_braces();
    indent();
    stream << "fi";
}

void CodeGen_Bash::visit(ForLoop *n) {
    stream << "for " << lookup_name(n->variable) << " in ";
    if (n->upper) {
        stream << "$(seq ";
        n->lower->accept(this);
        stream << " ";
        n->upper->accept(this);
        stream << ")";
    } else {
        disable_quote_variable();
        n->lower->accept(this);
        reset_quote_variable();
    }
    stream << "; do\n";
    disable_block_braces();
    n->body->accept(this);
    reset_block_braces();
    indent();
    stream << "done";
}

void CodeGen_Bash::visit(Function *n) {
    if (n->body == NULL) return;
    stream << "function " << n->name.str() << " ";
    stream << "() ";
    push_function_args_insert(n);
    if (n->body) n->body->accept(this);
}

void CodeGen_Bash::visit(FunctionCall *n) {
    const int nargs = n->args.size();
    if (should_functioncall_wrap()) stream << "$(";
    stream << n->function->name.str();
    for (int i = 0; i < nargs; i++) {
        stream << " ";
        enable_functioncall_wrap();
        if (const FunctionCall *FC = dynamic_cast<const FunctionCall*>(n->args[i])) {
          if (should_quote_variable()) stream << "\"";
          n->args[i]->accept(this);
          if (should_quote_variable()) stream << "\"";
        } else {
            n->args[i]->accept(this);
        }
        reset_functioncall_wrap();
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(ExternCall *n) {
    if (should_functioncall_wrap()) stream << "$(";
    disable_quote_variable();
    output_interpolated_string(n->body);
    reset_quote_variable();
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::output_interpolated_string(InterpolatedString *n) {
    for (InterpolatedString::const_iterator I = n->begin(), E = n->end();
         I != E; ++I) {
        if ((*I).is_str()) {
            stream << (*I).str();
        } else {
            assert((*I).is_var());
            visit((*I).var());
        }
    }
}

void CodeGen_Bash::visit(IORedirection *n) {
    std::string bash_op;
    switch (n->op) {
    case IORedirection::Pipe:
        bash_op = "|";
        break;
    default:
        assert(false && "Unimplemented redirection.");
    }

    disable_functioncall_wrap();
    stream << "$(";
    n->a->accept(this);
    stream << " " << bash_op << " ";
    n->b->accept(this);
    stream << ")";
    reset_functioncall_wrap();
}

void CodeGen_Bash::visit(Assignment *n) {
    if (!n->variable->global) stream << "local ";
    stream << lookup_name(n->variable) << "=";
    enable_functioncall_wrap();
    n->value->accept(this);
    reset_functioncall_wrap();
}

void CodeGen_Bash::visit(BinOp *n) {
    std::string bash_op;
    bool comparison = false, equals = false, string = false;
    if (n->a->type() == StringTy || n->b->type() == StringTy) {
        string = true;
    }
    switch (n->op) {
    case BinOp::Eq:
        bash_op = string ? "==" : "-eq";
        equals = true;
        comparison = true;
        break;
    case BinOp::NotEq:
        bash_op = string ? "!=" : "-ne";
        equals = true;
        comparison = true;
        break;
    case BinOp::LT:
        bash_op = string ? "<" : "-lt";
        comparison = true;
        break;
    case BinOp::LTE:
        bash_op = "-le";
        comparison = true;
        break;
    case BinOp::GT:
        bash_op = string ? ">" : "-gt";
        comparison = true;
        break;
    case BinOp::GTE:
        bash_op = "-ge";
        comparison = true;
        break;
    case BinOp::And:
        bash_op = "&&";
        comparison = true;
        break;
    case BinOp::Or:
        bash_op = "||";
        comparison = true;
        break;
    case BinOp::Add:
        bash_op = "+";
        break;
    case BinOp::Sub:
        bash_op = "-";
        break;
    case BinOp::Mul:
        bash_op = "*";
        break;
    case BinOp::Div:
        bash_op = "/";
        break;
    case BinOp::Mod:
        bash_op = "%";
        break;
    }

    bool reset_wrap = false;
    if (should_comparison_wrap() && (n->op == BinOp::And || n->op == BinOp::Or)) {
        reset_wrap = true;
        // Disable wrapping comparisons in [[]] because we need to
        // wrap them all from the outside for And and Or operations.
        disable_comparison_wrap();
        stream << "$([[ ";
    }

    if (equals && should_comparison_wrap()) stream << "$([[ ";
    if (!comparison) stream << "$((";
    if (!string) disable_quote_variable();
    n->a->accept(this);
    stream << " " << bash_op << " ";
    n->b->accept(this);
    if (equals && should_comparison_wrap()) stream << " ]] && echo 1 || echo 0)";
    if (!comparison) stream << "))";
    if (!string) reset_quote_variable();

    if (reset_wrap && (n->op == BinOp::And || n->op == BinOp::Or)) {
        reset_comparison_wrap();
        stream << " ]] && echo 1 || echo 0)";
    }
}

void CodeGen_Bash::visit(UnaryOp *n) {
    bool negate_binop = dynamic_cast<BinOp*>(n->a);
    switch (n->op) {
    case UnaryOp::Negate:
        stream << "-";
        break;
    case UnaryOp::Not:
        stream << "$(! [[ ";
        disable_comparison_wrap();
        break;
    }
    n->a->accept(this);
    if (n->op == UnaryOp::Not) {
        // Don't need the '-eq 1' if the argument is a binary operator (like '==').
        if (!negate_binop) stream << " -eq 1";
        stream << " ]] && echo 1 || echo 0)";
        reset_comparison_wrap();
    }
}

void CodeGen_Bash::visit(Integer *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(Fractional *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(String *n) {
    stream << "\"";
    output_interpolated_string(n->value);
    stream << "\"";
}

void CodeGen_Bash::visit(Boolean *n) {
    stream << n->value;
}
<commit_msg>Fix codegen issue with global variables.<commit_after>#include <cassert>
#include "CodeGen_Bash.h"

using namespace Bish;

void CodeGen_Bash::indent() {
    for (unsigned i = 0; i < indent_level; i++) {
        stream << "    ";
    }
}

// Return true if the given node is a statement that should be
// emitted. This excludes side-effecting statements like 'import'.
bool CodeGen_Bash::should_emit_statement(const IRNode *node) const {
    return dynamic_cast<const ImportStatement*>(node) == NULL;
}

void CodeGen_Bash::visit(Module *n) {
    // Define the functions first.
    for (std::vector<Function *>::const_iterator I = n->functions.begin(),
             E = n->functions.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    // Global variables next.
    for (std::vector<Assignment *>::const_iterator I = n->global_variables.begin(),
             E = n->global_variables.end(); I != E; ++I) {
        (*I)->accept(this);
        stream << ";\n";
    }
    stream << "\n";
    // Insert a call to bish_main().
    assert(n->main);
    FunctionCall *call_main = new FunctionCall(n->main);
    visit(call_main);
    stream << ";\n";
    delete call_main;
}

void CodeGen_Bash::visit(Block *n) {
    if (should_print_block_braces()) stream << "{\n";
    indent_level++;

    if (!function_args_insert.empty()) {
        Function *f = function_args_insert.top();
        function_args_insert.pop();
        unsigned i = 1;
        for (std::vector<Variable *>::const_iterator I = f->args.begin(), E = f->args.end(); I != E; ++I, ++i) {
            indent();
            stream << "local " << (*I)->name.str() << "=\"$" << i << "\";\n";
        }
    }

    for (std::vector<IRNode *>::const_iterator I = n->nodes.begin(), E = n->nodes.end();
         I != E; ++I) {
        if (should_emit_statement(*I)) {
            indent();
            (*I)->accept(this);
            stream << ";\n";
        }
    }
    indent_level--;
    if (should_print_block_braces()) stream << "}\n\n";
}

void CodeGen_Bash::visit(Variable *n) {
    if (should_quote_variable()) stream << "\"";
    stream << "$" << lookup_name(n);
    if (should_quote_variable()) stream << "\"";
}

void CodeGen_Bash::visit(ReturnStatement *n) {
    bool external = dynamic_cast<ExternCall*>(n->value) != NULL;
    stream << "echo ";
    enable_functioncall_wrap();
    // Defensively wrap external calls in quotes in case they return
    // space-separated strings. Not sure how to handle this yet in the
    // general case.
    if (external) stream << "\"";
    n->value->accept(this);
    if (external) stream << "\"";
    reset_functioncall_wrap();
    stream << "; exit";
}

void CodeGen_Bash::visit(LoopControlStatement *n) {
    switch (n->op) {
    case LoopControlStatement::Break:
        stream << "break";
        break;
    case LoopControlStatement::Continue:
        stream << "continue";
        break;
    }
}

void CodeGen_Bash::visit(IfStatement *n) {
    stream << "if [[ ";
    enable_functioncall_wrap();
    n->pblock->condition->accept(this);
    if (is_equals_op(n->pblock->condition) ||
        !dynamic_cast<BinOp*>(n->pblock->condition)) {
        stream << " -eq 1";
    }
    reset_functioncall_wrap();
    stream << " ]]; then\n";
    disable_block_braces();
    n->pblock->body->accept(this);

    for (std::vector<PredicatedBlock *>::const_iterator I = n->elses.begin(),
             E = n->elses.end(); I != E; ++I) {
        indent();
        stream << "elif [[ ";
        enable_functioncall_wrap();
        (*I)->condition->accept(this);
        reset_functioncall_wrap();
        stream << " ]]; then\n";
        (*I)->body->accept(this);
    }
    if (n->elseblock) {
        indent();
        stream << "else\n";
        n->elseblock->accept(this);
    }

    reset_block_braces();
    indent();
    stream << "fi";
}

void CodeGen_Bash::visit(ForLoop *n) {
    stream << "for " << lookup_name(n->variable) << " in ";
    if (n->upper) {
        stream << "$(seq ";
        n->lower->accept(this);
        stream << " ";
        n->upper->accept(this);
        stream << ")";
    } else {
        disable_quote_variable();
        n->lower->accept(this);
        reset_quote_variable();
    }
    stream << "; do\n";
    disable_block_braces();
    n->body->accept(this);
    reset_block_braces();
    indent();
    stream << "done";
}

void CodeGen_Bash::visit(Function *n) {
    if (n->body == NULL) return;
    stream << "function " << n->name.str() << " ";
    stream << "() ";
    push_function_args_insert(n);
    if (n->body) n->body->accept(this);
}

void CodeGen_Bash::visit(FunctionCall *n) {
    const int nargs = n->args.size();
    if (should_functioncall_wrap()) stream << "$(";
    stream << n->function->name.str();
    for (int i = 0; i < nargs; i++) {
        stream << " ";
        enable_functioncall_wrap();
        if (const FunctionCall *FC = dynamic_cast<const FunctionCall*>(n->args[i])) {
          if (should_quote_variable()) stream << "\"";
          n->args[i]->accept(this);
          if (should_quote_variable()) stream << "\"";
        } else {
            n->args[i]->accept(this);
        }
        reset_functioncall_wrap();
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(ExternCall *n) {
    if (should_functioncall_wrap()) stream << "$(";
    disable_quote_variable();
    output_interpolated_string(n->body);
    reset_quote_variable();
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::output_interpolated_string(InterpolatedString *n) {
    for (InterpolatedString::const_iterator I = n->begin(), E = n->end();
         I != E; ++I) {
        if ((*I).is_str()) {
            stream << (*I).str();
        } else {
            assert((*I).is_var());
            visit((*I).var());
        }
    }
}

void CodeGen_Bash::visit(IORedirection *n) {
    std::string bash_op;
    switch (n->op) {
    case IORedirection::Pipe:
        bash_op = "|";
        break;
    default:
        assert(false && "Unimplemented redirection.");
    }

    disable_functioncall_wrap();
    stream << "$(";
    n->a->accept(this);
    stream << " " << bash_op << " ";
    n->b->accept(this);
    stream << ")";
    reset_functioncall_wrap();
}

void CodeGen_Bash::visit(Assignment *n) {
    if (!n->variable->global) stream << "local ";
    stream << lookup_name(n->variable) << "=";
    enable_functioncall_wrap();
    n->value->accept(this);
    reset_functioncall_wrap();
}

void CodeGen_Bash::visit(BinOp *n) {
    std::string bash_op;
    bool comparison = false, equals = false, string = false;
    if (n->a->type() == StringTy || n->b->type() == StringTy) {
        string = true;
    }
    switch (n->op) {
    case BinOp::Eq:
        bash_op = string ? "==" : "-eq";
        equals = true;
        comparison = true;
        break;
    case BinOp::NotEq:
        bash_op = string ? "!=" : "-ne";
        equals = true;
        comparison = true;
        break;
    case BinOp::LT:
        bash_op = string ? "<" : "-lt";
        comparison = true;
        break;
    case BinOp::LTE:
        bash_op = "-le";
        comparison = true;
        break;
    case BinOp::GT:
        bash_op = string ? ">" : "-gt";
        comparison = true;
        break;
    case BinOp::GTE:
        bash_op = "-ge";
        comparison = true;
        break;
    case BinOp::And:
        bash_op = "&&";
        comparison = true;
        break;
    case BinOp::Or:
        bash_op = "||";
        comparison = true;
        break;
    case BinOp::Add:
        bash_op = "+";
        break;
    case BinOp::Sub:
        bash_op = "-";
        break;
    case BinOp::Mul:
        bash_op = "*";
        break;
    case BinOp::Div:
        bash_op = "/";
        break;
    case BinOp::Mod:
        bash_op = "%";
        break;
    }

    bool reset_wrap = false;
    if (should_comparison_wrap() && (n->op == BinOp::And || n->op == BinOp::Or)) {
        reset_wrap = true;
        // Disable wrapping comparisons in [[]] because we need to
        // wrap them all from the outside for And and Or operations.
        disable_comparison_wrap();
        stream << "$([[ ";
    }

    if (equals && should_comparison_wrap()) stream << "$([[ ";
    if (!comparison) stream << "$((";
    if (!string) disable_quote_variable();
    n->a->accept(this);
    stream << " " << bash_op << " ";
    n->b->accept(this);
    if (equals && should_comparison_wrap()) stream << " ]] && echo 1 || echo 0)";
    if (!comparison) stream << "))";
    if (!string) reset_quote_variable();

    if (reset_wrap && (n->op == BinOp::And || n->op == BinOp::Or)) {
        reset_comparison_wrap();
        stream << " ]] && echo 1 || echo 0)";
    }
}

void CodeGen_Bash::visit(UnaryOp *n) {
    bool negate_binop = dynamic_cast<BinOp*>(n->a);
    switch (n->op) {
    case UnaryOp::Negate:
        stream << "-";
        break;
    case UnaryOp::Not:
        stream << "$(! [[ ";
        disable_comparison_wrap();
        break;
    }
    n->a->accept(this);
    if (n->op == UnaryOp::Not) {
        // Don't need the '-eq 1' if the argument is a binary operator (like '==').
        if (!negate_binop) stream << " -eq 1";
        stream << " ]] && echo 1 || echo 0)";
        reset_comparison_wrap();
    }
}

void CodeGen_Bash::visit(Integer *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(Fractional *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(String *n) {
    stream << "\"";
    output_interpolated_string(n->value);
    stream << "\"";
}

void CodeGen_Bash::visit(Boolean *n) {
    stream << n->value;
}
<|endoftext|>