<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

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 <algorithm>
#include <memory>
#include <string>

#include "tensorflow/compiler/xla/array2d.h"
#include "tensorflow/compiler/xla/client/computation.h"
#include "tensorflow/compiler/xla/client/computation_builder.h"
#include "tensorflow/compiler/xla/client/local_client.h"
#include "tensorflow/compiler/xla/legacy_flags/cpu_compiler_flags.h"
#include "tensorflow/compiler/xla/literal_util.h"
#include "tensorflow/compiler/xla/ptr_util.h"
#include "tensorflow/compiler/xla/reference_util.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/test_helpers.h"
#include "tensorflow/compiler/xla/tests/client_library_test_base.h"
#include "tensorflow/compiler/xla/tests/literal_test_util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/lib/strings/stringprintf.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/types.h"

namespace xla {
namespace {

class MatOpsSimpleTest : public ClientLibraryTestBase {
 protected:
  Computation BuildSum() {
    // sum(x, y) = x + y
    ComputationBuilder builder(client_, "sum");
    auto x_value =
        builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "x_value");
    auto y_value =
        builder.Parameter(1, ShapeUtil::MakeShape(F32, {}), "y_value");
    builder.Add(x_value, y_value);
    auto computation_status = builder.Build();
    TF_CHECK_OK(computation_status.status());
    return computation_status.ConsumeValueOrDie();
  }

  void TestLinspaceMax(int64 rows, int64 cols) {
    float from = -128.0, to = 256.0;
    std::unique_ptr<Array2D<float>> alhs =
        MakeLinspaceArray2D(from, to, rows, cols);
    auto arhs = MakeUnique<Array2D<float>>(rows, cols, 1.0);

    ComputationBuilder builder(
        client_,
        tensorflow::strings::Printf("max_%lldx%lld_linspace", rows, cols));
    auto lhs = builder.ConstantR2FromArray2D<float>(*alhs);
    auto rhs = builder.ConstantR2FromArray2D<float>(*arhs);
    auto max = builder.Max(lhs, rhs);

    Array2D<float> aexpected(rows, cols);
    for (int row = 0; row < rows; ++row) {
      for (int col = 0; col < cols; ++col) {
        aexpected(row, col) = std::max((*alhs)(row, col), (*arhs)(row, col));
      }
    }

    ComputeAndCompareR2<float>(&builder, aexpected, {}, ErrorSpec(1e-6));
  }
};

TEST_F(MatOpsSimpleTest, ExpTwoByTwoValues) {
  ComputationBuilder builder(client_, "exp_2x2");
  auto data = builder.ConstantR2<float>({
      {1.0, 0.0},   // row 0
      {-1.0, 0.5},  // row 1
  });
  builder.Exp(data);

  std::unique_ptr<Literal> expected =
      LiteralUtil::CreateR2<float>({{2.71828, 1.00000},    // row 0
                                    {0.36788, 1.64872}});  // row 1

  ComputeAndCompareLiteral(&builder, *expected, {}, ErrorSpec(1e-5));
}

TEST_F(MatOpsSimpleTest, MapTwoByTwo) {
  Computation add_half;
  {
    // add_half(x) = x + 0.5
    ComputationBuilder builder(client_, "add_half");
    auto x_value =
        builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "x_value");
    auto half = builder.ConstantR0<float>(0.5);
    builder.Add(x_value, half);
    auto computation_status = builder.Build();
    ASSERT_IS_OK(computation_status.status());
    add_half = computation_status.ConsumeValueOrDie();
  }

  ComputationBuilder builder(client_, "map_2x2");
  auto data = builder.ConstantR2<float>({
      {1.0, 0.0},   // row 0
      {-1.0, 0.5},  // row 1
  });
  auto map = builder.Map({data}, add_half);

  std::unique_ptr<Literal> expected =
      LiteralUtil::CreateR2<float>({{1.5, 0.5},     // row 0
                                    {-0.5, 1.0}});  // row 1
  ComputeAndCompareLiteral(&builder, *expected, {}, ErrorSpec(1e-5));
}

TEST_F(MatOpsSimpleTest, MaxTwoByTwoValues) {
  ComputationBuilder builder(client_, "max_2x2");
  auto lhs = builder.ConstantR2<float>({
      {7.0, 2.0},   // row 0
      {3.0, -4.0},  // row 1
  });
  auto rhs = builder.ConstantR2<float>({
      {5.0, 6.0},   // row 0
      {1.0, -8.0},  // row 1
  });
  auto max = builder.Max(lhs, rhs);

  std::unique_ptr<Literal> expected =
      LiteralUtil::CreateR2<float>({{7.0, 6.0},     // row 0
                                    {3.0, -4.0}});  // row 1
  ComputeAndCompareLiteral(&builder, *expected, {}, ErrorSpec(1e-6));
}

TEST_F(MatOpsSimpleTest, Max1x1Linspace) { TestLinspaceMax(1, 1); }

TEST_F(MatOpsSimpleTest, Max2x2Linspace) { TestLinspaceMax(2, 2); }

TEST_F(MatOpsSimpleTest, Max3x3Linspace) { TestLinspaceMax(3, 3); }

TEST_F(MatOpsSimpleTest, Max4x4Linspace) { TestLinspaceMax(4, 4); }

TEST_F(MatOpsSimpleTest, Max6x6Linspace) { TestLinspaceMax(6, 6); }

TEST_F(MatOpsSimpleTest, Max8x8Linspace) { TestLinspaceMax(8, 8); }

TEST_F(MatOpsSimpleTest, Max12x12Linspace) { TestLinspaceMax(12, 12); }

TEST_F(MatOpsSimpleTest, Max16x16Linspace) { TestLinspaceMax(16, 16); }

TEST_F(MatOpsSimpleTest, Max32x8Linspace) { TestLinspaceMax(32, 8); }

TEST_F(MatOpsSimpleTest, Max64x8Linspace) { TestLinspaceMax(64, 8); }

}  // namespace
}  // namespace xla

int main(int argc, char** argv) {
  std::vector<tensorflow::Flag> flag_list;
  xla::legacy_flags::AppendCpuCompilerFlags(&flag_list);
  xla::string usage = tensorflow::Flags::Usage(argv[0], flag_list);
  const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list);
  if (!parse_result) {
    LOG(ERROR) << "\n" << usage;
    return 2;
  }
  testing::InitGoogleTest(&argc, argv);
  if (argc > 1) {
    LOG(ERROR) << "Unknown argument " << argv[1] << "\n" << usage;
    return 2;
  }
  return RUN_ALL_TESTS();
}
<commit_msg>[XLA] Small test that performs A*B+A and A*B+B.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

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 <algorithm>
#include <memory>
#include <string>

#include "tensorflow/compiler/xla/array2d.h"
#include "tensorflow/compiler/xla/client/computation.h"
#include "tensorflow/compiler/xla/client/computation_builder.h"
#include "tensorflow/compiler/xla/client/local_client.h"
#include "tensorflow/compiler/xla/legacy_flags/cpu_compiler_flags.h"
#include "tensorflow/compiler/xla/literal_util.h"
#include "tensorflow/compiler/xla/ptr_util.h"
#include "tensorflow/compiler/xla/reference_util.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/test_helpers.h"
#include "tensorflow/compiler/xla/tests/client_library_test_base.h"
#include "tensorflow/compiler/xla/tests/literal_test_util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/lib/strings/stringprintf.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/types.h"

namespace xla {
namespace {

class MatOpsSimpleTest : public ClientLibraryTestBase {
 protected:
  Computation BuildSum() {
    // sum(x, y) = x + y
    ComputationBuilder builder(client_, "sum");
    auto x_value =
        builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "x_value");
    auto y_value =
        builder.Parameter(1, ShapeUtil::MakeShape(F32, {}), "y_value");
    builder.Add(x_value, y_value);
    auto computation_status = builder.Build();
    TF_CHECK_OK(computation_status.status());
    return computation_status.ConsumeValueOrDie();
  }

  void TestLinspaceMax(int64 rows, int64 cols) {
    float from = -128.0, to = 256.0;
    std::unique_ptr<Array2D<float>> alhs =
        MakeLinspaceArray2D(from, to, rows, cols);
    auto arhs = MakeUnique<Array2D<float>>(rows, cols, 1.0);

    ComputationBuilder builder(
        client_,
        tensorflow::strings::Printf("max_%lldx%lld_linspace", rows, cols));
    auto lhs = builder.ConstantR2FromArray2D<float>(*alhs);
    auto rhs = builder.ConstantR2FromArray2D<float>(*arhs);
    auto max = builder.Max(lhs, rhs);

    Array2D<float> aexpected(rows, cols);
    for (int row = 0; row < rows; ++row) {
      for (int col = 0; col < cols; ++col) {
        aexpected(row, col) = std::max((*alhs)(row, col), (*arhs)(row, col));
      }
    }

    ComputeAndCompareR2<float>(&builder, aexpected, {}, ErrorSpec(1e-6));
  }
};

TEST_F(MatOpsSimpleTest, ExpTwoByTwoValues) {
  ComputationBuilder builder(client_, "exp_2x2");
  auto data = builder.ConstantR2<float>({
      {1.0, 0.0},   // row 0
      {-1.0, 0.5},  // row 1
  });
  builder.Exp(data);

  std::unique_ptr<Literal> expected =
      LiteralUtil::CreateR2<float>({{2.71828, 1.00000},    // row 0
                                    {0.36788, 1.64872}});  // row 1

  ComputeAndCompareLiteral(&builder, *expected, {}, ErrorSpec(1e-5));
}

TEST_F(MatOpsSimpleTest, MapTwoByTwo) {
  Computation add_half;
  {
    // add_half(x) = x + 0.5
    ComputationBuilder builder(client_, "add_half");
    auto x_value =
        builder.Parameter(0, ShapeUtil::MakeShape(F32, {}), "x_value");
    auto half = builder.ConstantR0<float>(0.5);
    builder.Add(x_value, half);
    auto computation_status = builder.Build();
    ASSERT_IS_OK(computation_status.status());
    add_half = computation_status.ConsumeValueOrDie();
  }

  ComputationBuilder builder(client_, "map_2x2");
  auto data = builder.ConstantR2<float>({
      {1.0, 0.0},   // row 0
      {-1.0, 0.5},  // row 1
  });
  auto map = builder.Map({data}, add_half);

  std::unique_ptr<Literal> expected =
      LiteralUtil::CreateR2<float>({{1.5, 0.5},     // row 0
                                    {-0.5, 1.0}});  // row 1
  ComputeAndCompareLiteral(&builder, *expected, {}, ErrorSpec(1e-5));
}

TEST_F(MatOpsSimpleTest, MaxTwoByTwoValues) {
  ComputationBuilder builder(client_, "max_2x2");
  auto lhs = builder.ConstantR2<float>({
      {7.0, 2.0},   // row 0
      {3.0, -4.0},  // row 1
  });
  auto rhs = builder.ConstantR2<float>({
      {5.0, 6.0},   // row 0
      {1.0, -8.0},  // row 1
  });
  auto max = builder.Max(lhs, rhs);

  std::unique_ptr<Literal> expected =
      LiteralUtil::CreateR2<float>({{7.0, 6.0},     // row 0
                                    {3.0, -4.0}});  // row 1
  ComputeAndCompareLiteral(&builder, *expected, {}, ErrorSpec(1e-6));
}

TEST_F(MatOpsSimpleTest, Max1x1Linspace) { TestLinspaceMax(1, 1); }

TEST_F(MatOpsSimpleTest, Max2x2Linspace) { TestLinspaceMax(2, 2); }

TEST_F(MatOpsSimpleTest, Max3x3Linspace) { TestLinspaceMax(3, 3); }

TEST_F(MatOpsSimpleTest, Max4x4Linspace) { TestLinspaceMax(4, 4); }

TEST_F(MatOpsSimpleTest, Max6x6Linspace) { TestLinspaceMax(6, 6); }

TEST_F(MatOpsSimpleTest, Max8x8Linspace) { TestLinspaceMax(8, 8); }

TEST_F(MatOpsSimpleTest, Max12x12Linspace) { TestLinspaceMax(12, 12); }

TEST_F(MatOpsSimpleTest, Max16x16Linspace) { TestLinspaceMax(16, 16); }

TEST_F(MatOpsSimpleTest, Max32x8Linspace) { TestLinspaceMax(32, 8); }

TEST_F(MatOpsSimpleTest, Max64x8Linspace) { TestLinspaceMax(64, 8); }

class MatOpsDotAddTest
    : public ClientLibraryTestBase,
      public ::testing::WithParamInterface<std::tuple<bool, bool>> {};

TEST_P(MatOpsDotAddTest, Dot_Add_2x2_2x2) {
  bool row_major = std::get<0>(GetParam());
  bool add_lhs = std::get<1>(GetParam());
  Array2D<float> lhs({{1.0, 2.0}, {3.0, 4.0}});
  Array2D<float> rhs({{10.0, 11.0}, {12.0, 13.0}});

  auto minor_to_major = [](bool row_major) -> std::vector<int64> {
    return {row_major ? 1 : 0, row_major ? 0 : 1};
  };

  auto prim_type = primitive_util::NativeToPrimitiveType<float>();
  Shape lhs_shape =
      ShapeUtil::MakeShape(prim_type, {lhs.height(), lhs.width()});
  Shape rhs_shape =
      ShapeUtil::MakeShape(prim_type, {rhs.height(), rhs.width()});

  TF_ASSIGN_OR_ASSERT_OK(
      auto lhs_handle,
      client_->TransferToServer(
          *LiteralUtil::CreateR2FromArray2DWithLayout<float>(
              lhs, LayoutUtil::MakeLayout(minor_to_major(row_major)))));
  TF_ASSIGN_OR_ASSERT_OK(
      auto rhs_handle,
      client_->TransferToServer(
          *LiteralUtil::CreateR2FromArray2DWithLayout<float>(
              rhs, LayoutUtil::MakeLayout(minor_to_major(row_major)))));

  ComputationBuilder builder(client_, TestName());
  auto lhs_arg = builder.Parameter(0, lhs_shape, "lhs");
  auto rhs_arg = builder.Parameter(1, rhs_shape, "rhs");
  auto result = builder.Dot(lhs_arg, rhs_arg);
  Array2D<float> expected;
  if (add_lhs) {
    result = builder.Add(result, lhs_arg);
    expected = Array2D<float>({{35, 39}, {81, 89}});
  } else {
    result = builder.Add(result, rhs_arg);
    expected = Array2D<float>({{44, 48}, {90, 98}});
  }

  ComputeAndCompareR2<float>(&builder, expected,
                             {lhs_handle.get(), rhs_handle.get()},
                             ErrorSpec(1e-6));
}

INSTANTIATE_TEST_CASE_P(MatOpsDotAddTestInstances, MatOpsDotAddTest,
                        ::testing::Combine(::testing::Bool(),
                                           ::testing::Bool()));

}  // namespace
}  // namespace xla

int main(int argc, char** argv) {
  std::vector<tensorflow::Flag> flag_list;
  xla::legacy_flags::AppendCpuCompilerFlags(&flag_list);
  xla::string usage = tensorflow::Flags::Usage(argv[0], flag_list);
  const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list);
  if (!parse_result) {
    LOG(ERROR) << "\n" << usage;
    return 2;
  }
  testing::InitGoogleTest(&argc, argv);
  if (argc > 1) {
    LOG(ERROR) << "Unknown argument " << argv[1] << "\n" << usage;
    return 2;
  }
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// #include "stdafx.h"

// int _tmain(int argc, _TCHAR* argv[])
// {
//	return 0;
// }

#include <tbb/task_group.h>
#include <tbb/tbb_thread.h> // for sleep functionality
// An alternative can be taken from
// https://repo.anl-external.org/repos/BlueTBB/tbb30_104oss/src/rml/perfor/tbb_simple.cpp
//void MilliSleep(unsigned milliseconds) {
//#if ( _WIN32 || _WIN64 )
//    Sleep(milliseconds); // accepts DWORD: 32-bit unsigned integer
//#else
//    usleep(milliseconds * 1000); // accepts mysterious useconds_t
//#endif
//}

#include <iostream>
#include <stdio.h> //// MOVE TO iostreams TODO
#include <stdlib.h>

using namespace tbb;

// No matter which main function we use,
// we want to disable buffering on stdout before we do anything
// TODO this is nasty
struct Dummy { Dummy() { setbuf(stdout, NULL); } };
static Dummy d;

#if 0 // just spin up and run four simple tasks, using lambdas
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

int main(int argc, char *argv[]) {
    puts("Starting...");

    task_group g;

    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 1] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 2] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 3] started"); } );

    g.run_and_wait( [&]{ this_tbb_thread::sleep(oneSecond); puts("A message from the main thread"); } );

    return EXIT_SUCCESS;
}
#endif

#if 1 // fun with the idea of futures

// #include "tbb/atomic.h"

// Faking/implementing futures with TBB tasks

// Note that mutable state is held in its own struct,
// as TBB's run(1) function accepts its arg by const reference,
// forcing us to handle mutation via a pointer to a mutable value
// and not within the MyFuture class itself.

// We use TBB's sleep functionality, to avoid C++14 dependency
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds
const tbb::tick_count::interval_t threeSeconds(3.0);
const tbb::tick_count::interval_t tenSeconds(10.0);

int main(int argc, char *argv[]) {
    puts("Starting...");

    class MyFuture {
      struct MutableState {
        MutableState() : result(0) { }
        int result;
      };

      class Executor {
        /*not const*/ MutableState * const msPtr;
      public:
        Executor(MutableState *m) : msPtr(m) { };

        void operator()() const {
          puts("[from task] Task is running. Now for the pause...");
//        this_tbb_thread::sleep( threeSeconds );
          this_tbb_thread::sleep( tenSeconds );
          puts("[from task] Task pause complete, assigning output...");
          msPtr->result = 3;
          return;
        }
      };

      task_group   tg;
      MutableState ms;
      const Executor e; // must be const in order to call run(1)

    public:
      MyFuture() : e(&ms) // just invoke default constructor of tg and ms
      { }

      void begin() {
        tg.run( this->e );
      }

      int force() /*const*/ {
        tg.wait();
        return ms.result;
      }
    };

    MyFuture f; // not const: we mutate internally

    puts("Now to run");
    f.begin();
    puts("Running. Now to do a couple of prints with a pause between each.");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after a second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    puts("And now to wait...");

    printf( "%d\n", f.force() );

    return EXIT_SUCCESS;
}
#endif

#if 0 // the fib example from the web
int fib(int n) {
    int ret;
    if (n < 2) {
        ret = n;
    }
    else {
        int x, y;
        task_group g;

        x = y = 9;

        // g.run( [&]{my_mutex.lock();/* x=fib(n-1); */ puts("Now:\n"); getchar(); my_mutex.unlock();} ); // spawn a task

        g.run([&] {
            tbb::mutex::scoped_lock lock(my_mutex);
            /* x=fib(n-1); */ puts("Now:\n"); getchar();
        }); // spawn a task

            // g.run( [&]{my_mutex.lock();/* y=fib(n-2); */ puts("Now:\n"); getchar(); my_mutex.unlock();} ); // spawn another task
        g.run([&] {
            tbb::mutex::scoped_lock lock(my_mutex);/* y=fib(n-2); */ puts("Now:\n"); getchar();
        }); // spawn another task

        g.wait();                // wait for both tasks to complete

        ret = x + y;
    }

    return ret;
} // - See more at: https://www.threadingbuildingblocks.org/tutorial-intel-tbb-task-based-programming#sthash.EzgRXzaB.dpuf

int main(int argc, char *argv[]) {
    std::cout << fib(33);

    // getchar();
    return EXIT_SUCCESS;
}

#endif
<commit_msg>Remove cruft: another old uninteresting example<commit_after>// #include "stdafx.h"

// int _tmain(int argc, _TCHAR* argv[])
// {
//	return 0;
// }

#include <tbb/task_group.h>
#include <tbb/tbb_thread.h> // for sleep functionality
// An alternative can be taken from
// https://repo.anl-external.org/repos/BlueTBB/tbb30_104oss/src/rml/perfor/tbb_simple.cpp
//void MilliSleep(unsigned milliseconds) {
//#if ( _WIN32 || _WIN64 )
//    Sleep(milliseconds); // accepts DWORD: 32-bit unsigned integer
//#else
//    usleep(milliseconds * 1000); // accepts mysterious useconds_t
//#endif
//}

#include <iostream>
#include <stdio.h> //// MOVE TO iostreams TODO
#include <stdlib.h>

using namespace tbb;

// No matter which main function we use,
// we want to disable buffering on stdout before we do anything
// TODO this is nasty
struct Dummy { Dummy() { setbuf(stdout, NULL); } };
static Dummy d;

#if 0 // just spin up and run four simple tasks, using lambdas
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds

int main(int argc, char *argv[]) {
    puts("Starting...");

    task_group g;

    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 1] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 2] started"); } );
    g.run( [&]{ this_tbb_thread::sleep(oneSecond); puts("[Task 3] started"); } );

    g.run_and_wait( [&]{ this_tbb_thread::sleep(oneSecond); puts("A message from the main thread"); } );

    return EXIT_SUCCESS;
}
#endif

#if 1 // fun with the idea of futures

// #include "tbb/atomic.h"

// Faking/implementing futures with TBB tasks

// Note that mutable state is held in its own struct,
// as TBB's run(1) function accepts its arg by const reference,
// forcing us to handle mutation via a pointer to a mutable value
// and not within the MyFuture class itself.

// We use TBB's sleep functionality, to avoid C++14 dependency
const tbb::tick_count::interval_t oneSecond(1.0);    // double holds the number of seconds
const tbb::tick_count::interval_t threeSeconds(3.0);
const tbb::tick_count::interval_t tenSeconds(10.0);

int main(int argc, char *argv[]) {
    puts("Starting...");

    class MyFuture {
      struct MutableState {
        MutableState() : result(0) { }
        int result;
      };

      class Executor {
        /*not const*/ MutableState * const msPtr;
      public:
        Executor(MutableState *m) : msPtr(m) { };

        void operator()() const {
          puts("[from task] Task is running. Now for the pause...");
//        this_tbb_thread::sleep( threeSeconds );
          this_tbb_thread::sleep( tenSeconds );
          puts("[from task] Task pause complete, assigning output...");
          msPtr->result = 3;
          return;
        }
      };

      task_group   tg;
      MutableState ms;
      const Executor e; // must be const in order to call run(1)

    public:
      MyFuture() : e(&ms) // just invoke default constructor of tg and ms
      { }

      void begin() {
        tg.run( this->e );
      }

      int force() /*const*/ {
        tg.wait();
        return ms.result;
      }
    };

    MyFuture f; // not const: we mutate internally

    puts("Now to run");
    f.begin();
    puts("Running. Now to do a couple of prints with a pause between each.");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after a second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    this_tbb_thread::sleep( oneSecond );
    puts("And here we are after yet another second");
    puts("And now to wait...");

    printf( "%d\n", f.force() );

    return EXIT_SUCCESS;
}
#endif
<|endoftext|>


<commit_before>#include "patricia.hpp"
#include <cstring>
#include <memory>

extern "C" {
#include "indexed_ewah.h"
}

#define LARGE_LIST_THRESOLD 100000

typedef uint32_t Ipv4Ip;
typedef uint64_t Ipv4ListId;

typedef PatriciaKey<Ipv4Ip> Ipv4Mask;
typedef Patricia<Ipv4Ip, Ipv4ListId> Ipv4Tree;
typedef PatriciaElem<Ipv4Ip, Ipv4ListId> Ipv4TreeElem;

struct Ipv4List {
    Ipv4List(uint64_t i, unsigned l, const unsigned char *d) {
        id = i;
        length = l;
        data = d;
    }

    uint64_t id;
    unsigned length;
    const unsigned char *data;
};

struct free_delete
{
    void operator()(void* x) { ewah_free(static_cast<ewah_bitmap *>(x)); }
};

class Ipv4Map {
public:
    Ipv4ListId id;

    Ipv4Map(Ipv4ListId i) : id(i), internal_map(ewah_new()), finalized(false) {
        memset(&bitmap, 0, sizeof(indexed_ewah_map));
        bitmap.map = internal_map.get();
    }

    void add_ip(Ipv4Ip ip) {
        if (!finalized) {
            ewah_set(bitmap.map, ip);
        }
    }

    void finalize(void) {
        finalized = true;
        ewah_build_index(&bitmap);
    }

    bool lookup(Ipv4Ip ip) {
        return indexed_ewah_get(&bitmap, ip);
    }

private:
    indexed_ewah_map bitmap;
    std::unique_ptr<ewah_bitmap, free_delete> internal_map;
    bool finalized;
};

class Ipv4Index {
public:
    Ipv4Index(std::vector<Ipv4List>& lists) {
        std::vector<Ipv4TreeElem> tree_elems;

        for (Ipv4List &list : lists) {
            bool large_list = list.length >= LARGE_LIST_THRESOLD;

            if (large_list) {
                maps.emplace_back(Ipv4Map(list.id));
            }
            else {
                tree_elems.reserve(tree_elems.size() + list.length / 5);
            }

            for (unsigned i = 0; i < list.length; i += 5) {
                uint32_t ip = (list.data[i+0] << 24) + (list.data[i+1] << 16) + (list.data[i+2] << 8) + list.data[i+3];
                uint8_t mask = list.data[i+4];

                if (large_list && mask == 32) {
                    maps[maps.size()-1].add_ip(ip);
                }
                else {
                    uint8_t offset = 32 - mask;
                    tree_elems.emplace_back(Ipv4TreeElem(offset, ip, list.id));
                }
            }

            if (large_list) {
                maps[maps.size()-1].finalize();
            }
        }

        tree = Ipv4Tree(tree_elems);
    }

    std::vector<Ipv4ListId> lookup(Ipv4Ip ip, uint8_t mask) {
        std::vector<Ipv4ListId> result = tree.lookup(ip, 32 - mask);

        if (mask == 32) {
            for (Ipv4Map &map : maps) {
                if (map.lookup(ip)) {
                    result.emplace_back(map.id);
                }
            }
        }

        return result;
    }

private:

    Ipv4Tree tree;
    std::vector<Ipv4Map> maps;

};
<commit_msg>Wrap indexed_ewah_map in a unique_ptr<commit_after>#include "patricia.hpp"
#include <cassert>
#include <cstring>
#include <memory>

extern "C" {
#include "indexed_ewah.h"
}

#define LARGE_LIST_THRESOLD 100000

typedef uint32_t Ipv4Ip;
typedef uint64_t Ipv4ListId;

typedef PatriciaKey<Ipv4Ip> Ipv4Mask;
typedef Patricia<Ipv4Ip, Ipv4ListId> Ipv4Tree;
typedef PatriciaElem<Ipv4Ip, Ipv4ListId> Ipv4TreeElem;

struct Ipv4List {
    Ipv4List(uint64_t i, unsigned l, const unsigned char *d) {
        id = i;
        length = l;
        data = d;
    }

    uint64_t id;
    unsigned length;
    const unsigned char *data;
};

struct free_delete
{
    void operator()(void* x) {
	indexed_ewah_map *map = static_cast<indexed_ewah_map *>(x);
	ewah_free(map->map);
	delete map;
    }
};

class Ipv4Map {
public:
    Ipv4ListId id;

    Ipv4Map(Ipv4ListId i) : id(i), bitmap(new indexed_ewah_map()), finalized(false) {
	assert(0 == bitmap.get()->map);
	bitmap.get()->map = ewah_new();
    }

    void add_ip(Ipv4Ip ip) {
        if (!finalized) {
            ewah_set(bitmap.get()->map, ip);
        }
    }

    void finalize(void) {
        finalized = true;
        ewah_build_index(bitmap.get());
    }

    bool lookup(Ipv4Ip ip) {
        return indexed_ewah_get(bitmap.get(), ip);
    }

private:
    std::unique_ptr<indexed_ewah_map, free_delete> bitmap;
    bool finalized;
};

class Ipv4Index {
public:
    Ipv4Index(std::vector<Ipv4List>& lists) {
        std::vector<Ipv4TreeElem> tree_elems;

        for (Ipv4List &list : lists) {
            bool large_list = list.length >= LARGE_LIST_THRESOLD;

            if (large_list) {
                maps.emplace_back(Ipv4Map(list.id));
            }
            else {
                tree_elems.reserve(tree_elems.size() + list.length / 5);
            }

            for (unsigned i = 0; i < list.length; i += 5) {
                uint32_t ip = (list.data[i+0] << 24) + (list.data[i+1] << 16) + (list.data[i+2] << 8) + list.data[i+3];
                uint8_t mask = list.data[i+4];

                if (large_list && mask == 32) {
                    maps[maps.size()-1].add_ip(ip);
                }
                else {
                    uint8_t offset = 32 - mask;
                    tree_elems.emplace_back(Ipv4TreeElem(offset, ip, list.id));
                }
            }

            if (large_list) {
                maps[maps.size()-1].finalize();
            }
        }

        tree = Ipv4Tree(tree_elems);
    }

    std::vector<Ipv4ListId> lookup(Ipv4Ip ip, uint8_t mask) {
        std::vector<Ipv4ListId> result = tree.lookup(ip, 32 - mask);

        if (mask == 32) {
            for (Ipv4Map &map : maps) {
                if (map.lookup(ip)) {
                    result.emplace_back(map.id);
                }
            }
        }

        return result;
    }

private:

    Ipv4Tree tree;
    std::vector<Ipv4Map> maps;

};
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012, 2013 Aldebaran Robotics
**  See COPYING for the license
*/
#include <iostream>

#include <qitype/anyobject.hpp>
#include "staticobjecttype.hpp"
#include "anyobject_p.hpp"

#ifdef _MSC_VER
#  pragma warning( push )
#  pragma warning( disable: 4355 )
#endif

qiLogCategory("qitype.object");

namespace qi {

  GenericObject::GenericObject(ObjectTypeInterface *type, void *value)
  : type(type)
  , value(value)
  {
  }

  GenericObject::~GenericObject() {
  }

  ManageablePrivate::ManageablePrivate()
  : objectMutex(new boost::recursive_timed_mutex)
  , statsEnabled(false)
  , traceEnabled(false)
  {
  }

  Manageable::Manageable()
  : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
  {
    _p = new ManageablePrivate();
    _p->eventLoop = 0;
    _p->dying = false;
  }

  Manageable::Manageable(const Manageable& b)
  : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
  {
    _p = new ManageablePrivate();
    _p->eventLoop = b._p->eventLoop;
    _p->dying = false;
  }

  void Manageable::operator = (const Manageable& b)
  {
    this->~Manageable();
    _p = new ManageablePrivate();
    _p->eventLoop = b._p->eventLoop;
    _p->dying = false;
  }

  Manageable::~Manageable()
  {
    _p->dying = true;
    std::vector<SignalSubscriber> copy;
    {
      boost::mutex::scoped_lock sl(_p->registrationsMutex);
      copy = _p->registrations;
    }
    for (unsigned i = 0; i < copy.size(); ++i)
    {
      copy[i].source->disconnect(copy[i].linkId);
    }
    delete _p;
  }

  void Manageable::forceEventLoop(EventLoop* el)
  {
    _p->eventLoop = el;
  }

  EventLoop* Manageable::eventLoop() const
  {
    return _p->eventLoop;
  }

  Manageable::TimedMutexPtr Manageable::mutex()
  {
    return _p->objectMutex;
  }

  bool Manageable::isStatsEnabled() const
  {
    return _p->statsEnabled;
  }

  void Manageable::enableStats(bool state)
  {
    _p->statsEnabled = state;
  }

  void Manageable::pushStats(int slotId, float wallTime, float userTime, float systemTime)
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    MethodStatistics& ms = _p->stats[slotId];
    ms.push(wallTime, userTime, systemTime);
  }

  ObjectStatistics Manageable::stats() const
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    return _p->stats;
  }

  void Manageable::clearStats()
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    _p->stats.clear();
  }

  bool Manageable::isTraceEnabled() const
  {
    return _p->traceEnabled;
  }

  void Manageable::enableTrace(bool state)
  {
    _p->traceEnabled = state;
  }

  int Manageable::_nextTraceId()
  {
    return ++_p->traceId;
  }

  const MetaObject &GenericObject::metaObject() {
    if (!type || !value) {
      static qi::MetaObject fail;
      qiLogWarning() << "Operating on invalid GenericObject..";
      return fail;
    }
    return type->metaObject(value);
  }

  qi::Future<AnyReference>
  GenericObject::metaCall(unsigned int method, const GenericFunctionParameters& params, MetaCallType callType)
  {
    FutureCallbackType futureType = (callType == MetaCallType_Direct) ? FutureCallbackType_Sync: FutureCallbackType_Async;
    if (!type || !value) {
      const std::string s = "Operating on invalid GenericObject..";
      qiLogWarning() << s;
      return qi::makeFutureError<AnyReference>(s, futureType);
    }
    try {
      return type->metaCall(value, shared_from_this(), method, params, callType);
    } catch (const std::exception &e) {
      return qi::makeFutureError<AnyReference>(e.what(), futureType);
    }
    catch (...)
    {
      return qi::makeFutureError<AnyReference>("Unknown exception caught", futureType);
    }
  }

  void GenericObject::metaPost(unsigned int event, const GenericFunctionParameters& args)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return;
    }
    type->metaPost(value, shared_from_this(), event, args);
  }

  static std::string generateErrorString(const std::string &signature,
                                         const std::vector<MetaObject::CompatibleMethod> &candidates,
                                         bool logError = true)
  {
    std::stringstream                           ss;
    std::vector<MetaObject::CompatibleMethod>::const_iterator it;

    if (candidates.size() == 0) {
      ss << "Can't find method: " << signature << std::endl;
      return ss.str();
    }

    if (candidates.size() == 1) {
      ss << "Arguments types did not match for " << signature << ":" << std::endl
         << "  Candidate:" << std::endl;
    } else {
      ss << "Ambiguous overload for " << signature << ":" << std::endl
         << "  Candidate(s):" << std::endl;
    }
    for (it = candidates.begin(); it != candidates.end(); ++it) {
      const qi::MetaMethod       &mm = it->first;
      ss << "  " << mm.toString() << " (" << it->second << ')' << std::endl;
    }
    if (logError)
      qiLogError() << ss.str();
    return ss.str();
  }

  struct less_pair_second
  {
    template<typename T> bool operator()(const T& a, const T& b) const
    {
      return a.second < b.second;
    }
  };

  unsigned int GenericObject::findMethod(const std::string& nameWithOptionalSignature, const GenericFunctionParameters& args)
  {
    typedef std::vector<MetaObject::CompatibleMethod> Methods;
    const MetaObject& mo = metaObject();
    if (nameWithOptionalSignature.find(':') != nameWithOptionalSignature.npos)
      return mo.methodId(nameWithOptionalSignature);
    for (unsigned dyn = 0; dyn<2; ++dyn)
    {
      std::string resolvedSig = args.signature(dyn==1).toString();
      std::string fullSig = nameWithOptionalSignature + "::" + resolvedSig;
      qiLogDebug() << "Finding method for resolved signature " << fullSig;
      // First try an exact match, which is much faster if we're lucky.
      int methodId = mo.methodId(fullSig);
      if (methodId >= 0)
        return methodId;
      Methods mml = mo.findCompatibleMethod(fullSig);
      if (mml.empty())
        continue;
      if (mml.size() == 1)
        return mml.front().first.uid();
      // get best match
      Methods::iterator it = std::max_element(mml.begin(), mml.end(), less_pair_second());
      int count = 0;
      for (unsigned i=0; i<mml.size(); ++i)
      {
        if (mml[i].second == it->second)
          ++count;
      }
      assert(count);
      if (count > 1)
        qiLogVerbose() << generateErrorString(fullSig, mml, false);
      else
        return it->first.uid();
    }
    return -1;
  }

  qi::Future<AnyReference>
  GenericObject::metaCall(const std::string &nameWithOptionalSignature, const GenericFunctionParameters& args, MetaCallType callType)
  {
    if (!type || !value) {
      const std::string s = "Invalid object";
      qiLogError() << s;
      return qi::makeFutureError<AnyReference>(s);
    }
    int methodId = findMethod(nameWithOptionalSignature, args);
    if (methodId < 0) {
      std::string resolvedSig = args.signature(true).toString();
      std::string fullSig = nameWithOptionalSignature + "::" + resolvedSig;
      return makeFutureError<AnyReference>(generateErrorString(fullSig, metaObject().findCompatibleMethod(nameWithOptionalSignature), false));
    }
    return metaCall(methodId, args, callType);
  }

  /// Resolve signature and bounce
  void GenericObject::metaPost(const std::string &nameWithOptionalSignature, const GenericFunctionParameters &in) {
    if (!value || !type) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return;
    }

    int eventId = metaObject().signalId(qi::signatureSplit(nameWithOptionalSignature)[1]);
    if (eventId < 0)
      eventId = findMethod(nameWithOptionalSignature, in);
    if (eventId < 0) {
      std::stringstream ss;
      std::string name = qi::signatureSplit(nameWithOptionalSignature)[1];
      ss << "Can't find method or signal: " << nameWithOptionalSignature << std::endl;
      ss << "  Method Candidate(s):" << std::endl;
      std::vector<MetaMethod>           mml2 = metaObject().findMethod(name);
      std::vector<MetaMethod>::const_iterator it2;
      for (it2 = mml2.begin(); it2 != mml2.end(); ++it2) {
        ss << "  " << it2->toString() << std::endl;
      }
      qiLogError() << ss.str();
      return;
    }
    metaPost(eventId, in);
  }

  //TODO: use functor.signature instead of nameWithSignature.
  /// Resolve signature and bounce
  qi::FutureSync<SignalLink> GenericObject::connect(const std::string &name, const SignalSubscriber& functor)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return qi::makeFutureError<SignalLink>("Operating on invalid GenericObject..");
    }
    int eventId = metaObject().signalId(name);

    if (eventId < 0) {
      std::stringstream ss;
      ss << "Can't find signal: " << name;
      qiLogError() << ss.str();
      return qi::makeFutureError<SignalLink>(ss.str());
    }
    return connect(eventId, functor);
  }

  qi::FutureSync<SignalLink> GenericObject::connect(unsigned int event, const SignalSubscriber& sub)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return qi::makeFutureError<SignalLink>("Operating on invalid GenericObject..");
    }
    return type->connect(value, shared_from_this(), event, sub);
  }

  qi::FutureSync<void> GenericObject::disconnect(SignalLink linkId)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return qi::makeFutureError<void>("Operating on invalid GenericObject");
    }
    return type->disconnect(value, shared_from_this(), linkId);
  }

  qi::FutureSync<AnyValue> GenericObject::property(unsigned int id) {
    return type->property(value, id);
  }

  qi::FutureSync<void> GenericObject::setProperty(unsigned int id, const AnyValue& val) {
    return type->setProperty(value, id, val);
  }

  qi::FutureSync<SignalLink> GenericObject::connect(unsigned int signal, AnyObject target, unsigned int slot)
  {
    return connect(signal, SignalSubscriber(target, slot));
  }

  /*
  std::vector<SignalSubscriber> GenericObject::subscribers(int eventId) const
  {
    std::vector<SignalSubscriber> res;
    if (!_p) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return res;
    }
    return _p->subscribers(eventId);
  }*/

  void GenericObject::post(const std::string& nameWithOptionalSignature,
                         qi::AutoAnyReference p1,
                         qi::AutoAnyReference p2,
                         qi::AutoAnyReference p3,
                         qi::AutoAnyReference p4,
                         qi::AutoAnyReference p5,
                         qi::AutoAnyReference p6,
                         qi::AutoAnyReference p7,
                         qi::AutoAnyReference p8)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return;
    }
    qi::AutoAnyReference* vals[8]= {&p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8};
    std::vector<qi::AnyReference> params;
    for (unsigned i=0; i<8; ++i)
      if (vals[i]->type)
        params.push_back(*vals[i]);
    metaPost(nameWithOptionalSignature, GenericFunctionParameters(params));
  }

  int ObjectTypeInterface::inherits(TypeInterface* other)
  {
    /* A registered class C can have to TypeInterface* around:
    * - TypeImpl<C*>
    * - The staticObjectTypeInterface that was created by the builder.
    * So assume that any of them can be in the parentTypes list.
    */
    if (this == other)
      return 0;
    const std::vector<std::pair<TypeInterface*, int> >& parents = parentTypes();
    qiLogDebug() << infoString() <<" has " << parents.size() <<" parents";
    for (unsigned i=0; i<parents.size(); ++i)
    {
      if (parents[i].first->info() == other->info())
        return parents[i].second;
      ObjectTypeInterface* op = dynamic_cast<ObjectTypeInterface*>(parents[i].first);
      if (op)
      {
        int offset = op->inherits(other);
        if (offset != -1)
        {
          qiLogDebug() << "Inheritance offsets " << parents[i].second
           << " " << offset;
          return parents[i].second + offset;
        }
      }
      qiLogDebug() << parents[i].first->infoString() << " does not match " << other->infoString()
      <<" " << ((op != 0) == (dynamic_cast<ObjectTypeInterface*>(other) != 0));
    }
    return -1;
  }
  namespace manageable
  {
    static Manageable::MethodMap* methodMap = 0;
    static Manageable::SignalMap* signalMap = 0;
    static MetaObject* metaObject = 0;
  }
  void Manageable::_build()
  {
    if (manageable::methodMap)
      return;
    manageable::methodMap = new MethodMap();
    manageable::signalMap = new SignalMap();
    manageable::metaObject = new MetaObject();
    ObjectTypeBuilder<Manageable> builder;
    unsigned int id = startId;
    builder.advertiseMethod("isStatsEnabled", &Manageable::isStatsEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableStats", &Manageable::enableStats,       MetaCallType_Auto, id++);
    builder.advertiseMethod("stats", &Manageable::stats,                   MetaCallType_Auto, id++);
    builder.advertiseMethod("clearStats", &Manageable::clearStats,         MetaCallType_Auto, id++);
    builder.advertiseMethod("isTraceEnabled", &Manageable::isTraceEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableTrace", &Manageable::enableTrace,       MetaCallType_Auto, id++);
    builder.advertiseSignal("traceObject", &Manageable::traceObject, id++);
    assert(id <= endId);
    const ObjectTypeData& typeData = builder.typeData();
    *manageable::methodMap = typeData.methodMap;
    *manageable::signalMap = typeData.signalGetterMap;
    *manageable::metaObject = builder.metaObject();
  }

  Manageable::MethodMap& Manageable::manageableMmethodMap()
  {
    _build();
    return *manageable::methodMap;
  }

  Manageable::SignalMap& Manageable::manageableSignalMap()
  {
    _build();
    return *manageable::signalMap;
  }

  MetaObject& Manageable::manageableMetaObject()
  {
    _build();
    return *manageable::metaObject;
  }

  namespace detail
  {
    ProxyGeneratorMap& proxyGeneratorMap()
    {
      static ProxyGeneratorMap* map = 0;
      if (!map)
        map = new ProxyGeneratorMap();
      return *map;
    }
  }
}

#ifdef _MSC_VER
#  pragma warning( pop )
#endif

<commit_msg>GenericObject::metaPost: Optimize method resolution.<commit_after>/*
**  Copyright (C) 2012, 2013 Aldebaran Robotics
**  See COPYING for the license
*/
#include <iostream>

#include <qitype/anyobject.hpp>
#include "staticobjecttype.hpp"
#include "anyobject_p.hpp"

#ifdef _MSC_VER
#  pragma warning( push )
#  pragma warning( disable: 4355 )
#endif

qiLogCategory("qitype.object");

namespace qi {

  GenericObject::GenericObject(ObjectTypeInterface *type, void *value)
  : type(type)
  , value(value)
  {
  }

  GenericObject::~GenericObject() {
  }

  ManageablePrivate::ManageablePrivate()
  : objectMutex(new boost::recursive_timed_mutex)
  , statsEnabled(false)
  , traceEnabled(false)
  {
  }

  Manageable::Manageable()
  : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
  {
    _p = new ManageablePrivate();
    _p->eventLoop = 0;
    _p->dying = false;
  }

  Manageable::Manageable(const Manageable& b)
  : traceObject(boost::bind(&Manageable::enableTrace, this, _1))
  {
    _p = new ManageablePrivate();
    _p->eventLoop = b._p->eventLoop;
    _p->dying = false;
  }

  void Manageable::operator = (const Manageable& b)
  {
    this->~Manageable();
    _p = new ManageablePrivate();
    _p->eventLoop = b._p->eventLoop;
    _p->dying = false;
  }

  Manageable::~Manageable()
  {
    _p->dying = true;
    std::vector<SignalSubscriber> copy;
    {
      boost::mutex::scoped_lock sl(_p->registrationsMutex);
      copy = _p->registrations;
    }
    for (unsigned i = 0; i < copy.size(); ++i)
    {
      copy[i].source->disconnect(copy[i].linkId);
    }
    delete _p;
  }

  void Manageable::forceEventLoop(EventLoop* el)
  {
    _p->eventLoop = el;
  }

  EventLoop* Manageable::eventLoop() const
  {
    return _p->eventLoop;
  }

  Manageable::TimedMutexPtr Manageable::mutex()
  {
    return _p->objectMutex;
  }

  bool Manageable::isStatsEnabled() const
  {
    return _p->statsEnabled;
  }

  void Manageable::enableStats(bool state)
  {
    _p->statsEnabled = state;
  }

  void Manageable::pushStats(int slotId, float wallTime, float userTime, float systemTime)
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    MethodStatistics& ms = _p->stats[slotId];
    ms.push(wallTime, userTime, systemTime);
  }

  ObjectStatistics Manageable::stats() const
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    return _p->stats;
  }

  void Manageable::clearStats()
  {
    boost::mutex::scoped_lock(_p->registrationsMutex);
    _p->stats.clear();
  }

  bool Manageable::isTraceEnabled() const
  {
    return _p->traceEnabled;
  }

  void Manageable::enableTrace(bool state)
  {
    _p->traceEnabled = state;
  }

  int Manageable::_nextTraceId()
  {
    return ++_p->traceId;
  }

  const MetaObject &GenericObject::metaObject() {
    if (!type || !value) {
      static qi::MetaObject fail;
      qiLogWarning() << "Operating on invalid GenericObject..";
      return fail;
    }
    return type->metaObject(value);
  }

  qi::Future<AnyReference>
  GenericObject::metaCall(unsigned int method, const GenericFunctionParameters& params, MetaCallType callType)
  {
    FutureCallbackType futureType = (callType == MetaCallType_Direct) ? FutureCallbackType_Sync: FutureCallbackType_Async;
    if (!type || !value) {
      const std::string s = "Operating on invalid GenericObject..";
      qiLogWarning() << s;
      return qi::makeFutureError<AnyReference>(s, futureType);
    }
    try {
      return type->metaCall(value, shared_from_this(), method, params, callType);
    } catch (const std::exception &e) {
      return qi::makeFutureError<AnyReference>(e.what(), futureType);
    }
    catch (...)
    {
      return qi::makeFutureError<AnyReference>("Unknown exception caught", futureType);
    }
  }

  void GenericObject::metaPost(unsigned int event, const GenericFunctionParameters& args)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return;
    }
    type->metaPost(value, shared_from_this(), event, args);
  }

  static std::string generateErrorString(const std::string &signature,
                                         const std::vector<MetaObject::CompatibleMethod> &candidates,
                                         bool logError = true)
  {
    std::stringstream                           ss;
    std::vector<MetaObject::CompatibleMethod>::const_iterator it;

    if (candidates.size() == 0) {
      ss << "Can't find method: " << signature << std::endl;
      return ss.str();
    }

    if (candidates.size() == 1) {
      ss << "Arguments types did not match for " << signature << ":" << std::endl
         << "  Candidate:" << std::endl;
    } else {
      ss << "Ambiguous overload for " << signature << ":" << std::endl
         << "  Candidate(s):" << std::endl;
    }
    for (it = candidates.begin(); it != candidates.end(); ++it) {
      const qi::MetaMethod       &mm = it->first;
      ss << "  " << mm.toString() << " (" << it->second << ')' << std::endl;
    }
    if (logError)
      qiLogError() << ss.str();
    return ss.str();
  }

  struct less_pair_second
  {
    template<typename T> bool operator()(const T& a, const T& b) const
    {
      return a.second < b.second;
    }
  };

  unsigned int GenericObject::findMethod(const std::string& nameWithOptionalSignature, const GenericFunctionParameters& args)
  {
    typedef std::vector<MetaObject::CompatibleMethod> Methods;
    const MetaObject& mo = metaObject();
    if (nameWithOptionalSignature.find(':') != nameWithOptionalSignature.npos)
      return mo.methodId(nameWithOptionalSignature);
    for (unsigned dyn = 0; dyn<2; ++dyn)
    {
      std::string resolvedSig = args.signature(dyn==1).toString();
      std::string fullSig = nameWithOptionalSignature + "::" + resolvedSig;
      qiLogDebug() << "Finding method for resolved signature " << fullSig;
      // First try an exact match, which is much faster if we're lucky.
      int methodId = mo.methodId(fullSig);
      if (methodId >= 0)
        return methodId;
      Methods mml = mo.findCompatibleMethod(fullSig);
      if (mml.empty())
        continue;
      if (mml.size() == 1)
        return mml.front().first.uid();
      // get best match
      Methods::iterator it = std::max_element(mml.begin(), mml.end(), less_pair_second());
      int count = 0;
      for (unsigned i=0; i<mml.size(); ++i)
      {
        if (mml[i].second == it->second)
          ++count;
      }
      assert(count);
      if (count > 1)
        qiLogVerbose() << generateErrorString(fullSig, mml, false);
      else
        return it->first.uid();
    }
    return -1;
  }

  qi::Future<AnyReference>
  GenericObject::metaCall(const std::string &nameWithOptionalSignature, const GenericFunctionParameters& args, MetaCallType callType)
  {
    if (!type || !value) {
      const std::string s = "Invalid object";
      qiLogError() << s;
      return qi::makeFutureError<AnyReference>(s);
    }
    int methodId = findMethod(nameWithOptionalSignature, args);
    if (methodId < 0) {
      std::string resolvedSig = args.signature(true).toString();
      std::string fullSig = nameWithOptionalSignature + "::" + resolvedSig;
      return makeFutureError<AnyReference>(generateErrorString(fullSig, metaObject().findCompatibleMethod(nameWithOptionalSignature), false));
    }
    return metaCall(methodId, args, callType);
  }

  /// Resolve signature and bounce
  void GenericObject::metaPost(const std::string &nameWithOptionalSignature, const GenericFunctionParameters &in) {
    if (!value || !type) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return;
    }

    bool hasSig = (nameWithOptionalSignature.find(':') != std::string::npos);
    int eventId = metaObject().signalId(
      hasSig ? qi::signatureSplit(nameWithOptionalSignature)[1] : nameWithOptionalSignature);
    if (eventId < 0)
      eventId = findMethod(nameWithOptionalSignature, in);
    if (eventId < 0) {
      std::stringstream ss;
      std::string name = qi::signatureSplit(nameWithOptionalSignature)[1];
      ss << "Can't find method or signal: " << nameWithOptionalSignature << std::endl;
      ss << "  Method Candidate(s):" << std::endl;
      std::vector<MetaMethod>           mml2 = metaObject().findMethod(name);
      std::vector<MetaMethod>::const_iterator it2;
      for (it2 = mml2.begin(); it2 != mml2.end(); ++it2) {
        ss << "  " << it2->toString() << std::endl;
      }
      qiLogError() << ss.str();
      return;
    }
    metaPost(eventId, in);
  }

  //TODO: use functor.signature instead of nameWithSignature.
  /// Resolve signature and bounce
  qi::FutureSync<SignalLink> GenericObject::connect(const std::string &name, const SignalSubscriber& functor)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return qi::makeFutureError<SignalLink>("Operating on invalid GenericObject..");
    }
    int eventId = metaObject().signalId(name);

    if (eventId < 0) {
      std::stringstream ss;
      ss << "Can't find signal: " << name;
      qiLogError() << ss.str();
      return qi::makeFutureError<SignalLink>(ss.str());
    }
    return connect(eventId, functor);
  }

  qi::FutureSync<SignalLink> GenericObject::connect(unsigned int event, const SignalSubscriber& sub)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return qi::makeFutureError<SignalLink>("Operating on invalid GenericObject..");
    }
    return type->connect(value, shared_from_this(), event, sub);
  }

  qi::FutureSync<void> GenericObject::disconnect(SignalLink linkId)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return qi::makeFutureError<void>("Operating on invalid GenericObject");
    }
    return type->disconnect(value, shared_from_this(), linkId);
  }

  qi::FutureSync<AnyValue> GenericObject::property(unsigned int id) {
    return type->property(value, id);
  }

  qi::FutureSync<void> GenericObject::setProperty(unsigned int id, const AnyValue& val) {
    return type->setProperty(value, id, val);
  }

  qi::FutureSync<SignalLink> GenericObject::connect(unsigned int signal, AnyObject target, unsigned int slot)
  {
    return connect(signal, SignalSubscriber(target, slot));
  }

  /*
  std::vector<SignalSubscriber> GenericObject::subscribers(int eventId) const
  {
    std::vector<SignalSubscriber> res;
    if (!_p) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return res;
    }
    return _p->subscribers(eventId);
  }*/

  void GenericObject::post(const std::string& nameWithOptionalSignature,
                         qi::AutoAnyReference p1,
                         qi::AutoAnyReference p2,
                         qi::AutoAnyReference p3,
                         qi::AutoAnyReference p4,
                         qi::AutoAnyReference p5,
                         qi::AutoAnyReference p6,
                         qi::AutoAnyReference p7,
                         qi::AutoAnyReference p8)
  {
    if (!type || !value) {
      qiLogWarning() << "Operating on invalid GenericObject..";
      return;
    }
    qi::AutoAnyReference* vals[8]= {&p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8};
    std::vector<qi::AnyReference> params;
    for (unsigned i=0; i<8; ++i)
      if (vals[i]->type)
        params.push_back(*vals[i]);
    metaPost(nameWithOptionalSignature, GenericFunctionParameters(params));
  }

  int ObjectTypeInterface::inherits(TypeInterface* other)
  {
    /* A registered class C can have to TypeInterface* around:
    * - TypeImpl<C*>
    * - The staticObjectTypeInterface that was created by the builder.
    * So assume that any of them can be in the parentTypes list.
    */
    if (this == other)
      return 0;
    const std::vector<std::pair<TypeInterface*, int> >& parents = parentTypes();
    qiLogDebug() << infoString() <<" has " << parents.size() <<" parents";
    for (unsigned i=0; i<parents.size(); ++i)
    {
      if (parents[i].first->info() == other->info())
        return parents[i].second;
      ObjectTypeInterface* op = dynamic_cast<ObjectTypeInterface*>(parents[i].first);
      if (op)
      {
        int offset = op->inherits(other);
        if (offset != -1)
        {
          qiLogDebug() << "Inheritance offsets " << parents[i].second
           << " " << offset;
          return parents[i].second + offset;
        }
      }
      qiLogDebug() << parents[i].first->infoString() << " does not match " << other->infoString()
      <<" " << ((op != 0) == (dynamic_cast<ObjectTypeInterface*>(other) != 0));
    }
    return -1;
  }
  namespace manageable
  {
    static Manageable::MethodMap* methodMap = 0;
    static Manageable::SignalMap* signalMap = 0;
    static MetaObject* metaObject = 0;
  }
  void Manageable::_build()
  {
    if (manageable::methodMap)
      return;
    manageable::methodMap = new MethodMap();
    manageable::signalMap = new SignalMap();
    manageable::metaObject = new MetaObject();
    ObjectTypeBuilder<Manageable> builder;
    unsigned int id = startId;
    builder.advertiseMethod("isStatsEnabled", &Manageable::isStatsEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableStats", &Manageable::enableStats,       MetaCallType_Auto, id++);
    builder.advertiseMethod("stats", &Manageable::stats,                   MetaCallType_Auto, id++);
    builder.advertiseMethod("clearStats", &Manageable::clearStats,         MetaCallType_Auto, id++);
    builder.advertiseMethod("isTraceEnabled", &Manageable::isTraceEnabled, MetaCallType_Auto, id++);
    builder.advertiseMethod("enableTrace", &Manageable::enableTrace,       MetaCallType_Auto, id++);
    builder.advertiseSignal("traceObject", &Manageable::traceObject, id++);
    assert(id <= endId);
    const ObjectTypeData& typeData = builder.typeData();
    *manageable::methodMap = typeData.methodMap;
    *manageable::signalMap = typeData.signalGetterMap;
    *manageable::metaObject = builder.metaObject();
  }

  Manageable::MethodMap& Manageable::manageableMmethodMap()
  {
    _build();
    return *manageable::methodMap;
  }

  Manageable::SignalMap& Manageable::manageableSignalMap()
  {
    _build();
    return *manageable::signalMap;
  }

  MetaObject& Manageable::manageableMetaObject()
  {
    _build();
    return *manageable::metaObject;
  }

  namespace detail
  {
    ProxyGeneratorMap& proxyGeneratorMap()
    {
      static ProxyGeneratorMap* map = 0;
      if (!map)
        map = new ProxyGeneratorMap();
      return *map;
    }
  }
}

#ifdef _MSC_VER
#  pragma warning( pop )
#endif

<|endoftext|>


<commit_before>#include <GLFW/glfw3.h>
#include <algorithm>

const int width = 640;
const int height = 480;

float* pixels = new float[width*height * 3];

void drawPixel(const int& i, const int& j, const float& red, const float& green, const float& blue)
{
	pixels[(i + width* j) * 3 + 0] = red;
	pixels[(i + width* j) * 3 + 1] = green;
	pixels[(i + width* j) * 3 + 2] = blue;
}

void drawLine(const int& i0, const int& j0, const int& i1, const int& j1, const float& red, const float& green, const float& blue)
{
	for (int i = i0; i <= i1; i++)
	{
		const int j = (j1 - j0)*(i - i0) / (i1 - i0) + j0;
		drawPixel(i, j, red, green, blue);
	}
}

void draw()
{
	drawLine(10, 10, 150, 150, 0.0f, 0.0f, 0.0f);//ʺ
	drawLine(10, 10, 300, 10, 0.0f, 0.0f, 0.0f);//غ
	drawLine(150, 150, 300, 10, 0.0f, 0.0f, 0.0f);//
}

int main(void)
{
	GLFWwindow* window;

	/* Initialize the library */
	if (!glfwInit())
		return -1;

	/* Create a windowed mode window and its OpenGL context */
	window = glfwCreateWindow(width, height, "Hello World", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	/* Make the window's context current */
	glfwMakeContextCurrent(window);

	/* Loop until the user closes the window */
	while (!glfwWindowShouldClose(window))
	{
		/* Render here */
		glClear(GL_COLOR_BUFFER_BIT);

		std::fill_n(pixels, width*height * 3, 1.0f);	// white background

		draw();//׸ κ. ׸ ٲٷ void draw()Լ   ߰

		glDrawPixels(width, height, GL_RGB, GL_FLOAT, pixels);

		/* Swap front and back buffers */
		glfwSwapBuffers(window);

		/* Poll for and process events */
		glfwPollEvents();
	}

	delete[] pixels;

	glfwTerminate();
	return 0;
}<commit_msg>Delete triangle.cpp<commit_after><|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "hit.h"
#include "Parser.h"

#include "gtest_include.h"

#include <iostream>
#include <vector>

// TODO:
//
// * don't include trailing newlines in tokens (e.g. unquoted strings, strings, numbers, etc.)
// * build proper nesting structure
// * throw errors for bad/invalid number formats - both during parsing and retrieval (i.e. param
// func)
// * "${}" expressions get tokenized into strings correctly (including nesting, with spaces, etc.)
// * Lots of tests for tree merging
//
//     - existing param gets overridden in dst
//     - non-existing param gets duplicated into dst (not moved)
//     - existing tree gets overridden correctly
//     - non-existing tree gets duplicated into dst (not moved)

struct PassFailCase
{
  std::string name;
  std::string input;
};

TEST(HitTests, BraceExpressions)
{
  ValCase cases[] = {
      {"substitute string", "foo=bar boo=${foo}", "boo", "bar", hit::Field::Kind::String},
      {"substitute string explicit",
       "foo=bar boo=${replace foo}",
       "boo",
       "bar",
       hit::Field::Kind::String},
      {"trailing space", "foo=bar boo=${foo} ", "boo", "bar", hit::Field::Kind::String},
      {"substute number", "foo=42 boo=${foo}", "boo", "42", hit::Field::Kind::Int},
      {"multiple replacements",
       "foo=42 boo='${foo} ${foo}'",
       "boo",
       "42 42",
       hit::Field::Kind::String},
      {"nested", "foo=bar [hello] boo='${foo}' []", "hello/boo", "bar", hit::Field::Kind::String},
      {"repl-header-before",
       "src=foo [src] bar='${src}' []",
       "src/bar",
       "foo",
       hit::Field::Kind::String},
      {"repl-header-missing", "[src] bar='${src}' []", "src/bar", "${src}", hit::Field::Kind::None},
      {"repl-header-shadow",
       "[src] bar='${src}' [] src=foo",
       "src/bar",
       "${src}",
       hit::Field::Kind::None},
      {"nested shadow",
       "foo=bar [hello] foo=baz boo='${foo}' []",
       "hello/boo",
       "baz",
       hit::Field::Kind::String},
      {"multi-line brace expression",
       "foo=${raw 4\n"
       "          2\n"
       "     }",
       "foo",
       "42",
       hit::Field::Kind::String},
      {"fparse", "foo=${fparse 40 + 2}\n", "foo", "42", hit::Field::Kind::Float},
      {"fparse-dep-chain",
       "foo=${fparse 42} bar=${fparse foo}",
       "bar",
       "42",
       hit::Field::Kind::Float},
      {"fparse-dep-chain-quoted",
       "foo='${fparse 42}' bar=${fparse foo}",
       "bar",
       "42",
       hit::Field::Kind::Float},
      {"fparse-with-pi", "foo=${fparse cos(pi)}\n", "foo", "-1", hit::Field::Kind::Float},
      {"fparse-with-e", "foo=${fparse log(e)}\n", "foo", "1", hit::Field::Kind::Float},
      {"fparse-with-var", "var=39 foo=${fparse var + 3}", "foo", "42", hit::Field::Kind::Float},
      {"brace-expression-ends-before-newline",
       "foo=${raw 42} bar=23",
       "bar",
       "23",
       hit::Field::Kind::Int},
      {"super-complicated",
       "foo1 = 42\n"
       "foo2 = 43\n"
       "[section1]\n"
       "  num = 1\n"
       "  bar = ${${raw foo ${num}}} # becomes 42\n"
       "[]\n"
       "[section2]\n"
       "  num = 2\n"
       "  bar = ${${raw foo ${num}}}  # becomes 43\n"
       "[]\n"
       "\n"
       "a = ${fparse\n"
       "      ${section1/bar} + foo1 / foo2\n"
       "     }\n",
       "a",
       "42.97674418604651",
       hit::Field::Kind::Float},
  };

  for (size_t i = 0; i < sizeof(cases) / sizeof(ValCase); i++)
  {
    auto test = cases[i];
    hit::Node * root = nullptr;
    try
    {
      root = hit::parse("TEST", test.input);
      hit::BraceExpander exw("TEST");
      hit::RawEvaler raw;
      hit::ReplaceEvaler repl;
      FuncParseEvaler fparse_ev;
      exw.registerEvaler("fparse", fparse_ev);
      exw.registerEvaler("raw", raw);
      exw.registerEvaler("replace", repl);
      root->walk(&exw);
      if (exw.errors.size() > 0 && test.kind != hit::Field::Kind::None)
      {
        for (auto & err : exw.errors)
          FAIL() << "case " << i + 1 << " unexpected error: " << err << "\n";
        continue;
      }
      else if (exw.errors.size() == 0 && test.kind == hit::Field::Kind::None)
      {
        FAIL() << "case " << i + 1 << " missing expected error\n";
        continue;
      }
    }
    catch (std::exception & err)
    {
      FAIL() << "case " << i + 1 << " unexpected error: " << err.what() << "\n";
      continue;
    }

    auto n = root->find(test.key);
    if (!n)
    {
      FAIL() << "case " << i + 1 << " failed to find key '" << test.key << "'\n";
      continue;
    }
    if (n->strVal() != test.val)
    {
      FAIL() << "case " << i + 1 << " wrong value (key=" << test.key << "): got '" << n->strVal()
             << "', want '" << test.val << "'\n";
      continue;
    }

    auto f = dynamic_cast<hit::Field *>(n);
    if (!f)
      FAIL() << "case " << i + 1 << " node type is not NodeType::Field";
    else if (test.kind != hit::Field::Kind::None && f->kind() != test.kind)
      FAIL() << "case " << i + 1 << " wrong kind (key=" << test.key << "): got '"
             << strkind(f->kind()) << "', want '" << strkind(test.kind) << "'\n";
  }
}
<commit_msg>Fixup unit tests (missing structs)<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "hit.h"
#include "Parser.h"

#include "gtest_include.h"

#include <iostream>
#include <vector>

// TODO:
//
// * don't include trailing newlines in tokens (e.g. unquoted strings, strings, numbers, etc.)
// * build proper nesting structure
// * throw errors for bad/invalid number formats - both during parsing and retrieval (i.e. param
// func)
// * "${}" expressions get tokenized into strings correctly (including nesting, with spaces, etc.)
// * Lots of tests for tree merging
//
//     - existing param gets overridden in dst
//     - non-existing param gets duplicated into dst (not moved)
//     - existing tree gets overridden correctly
//     - non-existing tree gets duplicated into dst (not moved)

struct ValCase
{
  std::string name;
  std::string input;
  std::string key;
  std::string val;
  hit::Field::Kind kind;
};

std::string
strkind(hit::Field::Kind k)
{
  if (k == hit::Field::Kind::String)
    return "String";
  else if (k == hit::Field::Kind::Bool)
    return "Bool";
  else if (k == hit::Field::Kind::Int)
    return "Int";
  else if (k == hit::Field::Kind::Float)
    return "Float";
  else if (k == hit::Field::Kind::None)
    return "None";
  else
    return "Unknown";
}

TEST(HitTests, BraceExpressions)
{
  ValCase cases[] = {
      {"substitute string", "foo=bar boo=${foo}", "boo", "bar", hit::Field::Kind::String},
      {"substitute string explicit",
       "foo=bar boo=${replace foo}",
       "boo",
       "bar",
       hit::Field::Kind::String},
      {"trailing space", "foo=bar boo=${foo} ", "boo", "bar", hit::Field::Kind::String},
      {"substute number", "foo=42 boo=${foo}", "boo", "42", hit::Field::Kind::Int},
      {"multiple replacements",
       "foo=42 boo='${foo} ${foo}'",
       "boo",
       "42 42",
       hit::Field::Kind::String},
      {"nested", "foo=bar [hello] boo='${foo}' []", "hello/boo", "bar", hit::Field::Kind::String},
      {"repl-header-before",
       "src=foo [src] bar='${src}' []",
       "src/bar",
       "foo",
       hit::Field::Kind::String},
      {"repl-header-missing", "[src] bar='${src}' []", "src/bar", "${src}", hit::Field::Kind::None},
      {"repl-header-shadow",
       "[src] bar='${src}' [] src=foo",
       "src/bar",
       "${src}",
       hit::Field::Kind::None},
      {"nested shadow",
       "foo=bar [hello] foo=baz boo='${foo}' []",
       "hello/boo",
       "baz",
       hit::Field::Kind::String},
      {"multi-line brace expression",
       "foo=${raw 4\n"
       "          2\n"
       "     }",
       "foo",
       "42",
       hit::Field::Kind::String},
      {"fparse", "foo=${fparse 40 + 2}\n", "foo", "42", hit::Field::Kind::Float},
      {"fparse-dep-chain",
       "foo=${fparse 42} bar=${fparse foo}",
       "bar",
       "42",
       hit::Field::Kind::Float},
      {"fparse-dep-chain-quoted",
       "foo='${fparse 42}' bar=${fparse foo}",
       "bar",
       "42",
       hit::Field::Kind::Float},
      {"fparse-with-pi", "foo=${fparse cos(pi)}\n", "foo", "-1", hit::Field::Kind::Float},
      {"fparse-with-e", "foo=${fparse log(e)}\n", "foo", "1", hit::Field::Kind::Float},
      {"fparse-with-var", "var=39 foo=${fparse var + 3}", "foo", "42", hit::Field::Kind::Float},
      {"brace-expression-ends-before-newline",
       "foo=${raw 42} bar=23",
       "bar",
       "23",
       hit::Field::Kind::Int},
      {"super-complicated",
       "foo1 = 42\n"
       "foo2 = 43\n"
       "[section1]\n"
       "  num = 1\n"
       "  bar = ${${raw foo ${num}}} # becomes 42\n"
       "[]\n"
       "[section2]\n"
       "  num = 2\n"
       "  bar = ${${raw foo ${num}}}  # becomes 43\n"
       "[]\n"
       "\n"
       "a = ${fparse\n"
       "      ${section1/bar} + foo1 / foo2\n"
       "     }\n",
       "a",
       "42.97674418604651",
       hit::Field::Kind::Float},
  };

  for (size_t i = 0; i < sizeof(cases) / sizeof(ValCase); i++)
  {
    auto test = cases[i];
    hit::Node * root = nullptr;
    try
    {
      root = hit::parse("TEST", test.input);
      hit::BraceExpander exw("TEST");
      hit::RawEvaler raw;
      hit::ReplaceEvaler repl;
      FuncParseEvaler fparse_ev;
      exw.registerEvaler("fparse", fparse_ev);
      exw.registerEvaler("raw", raw);
      exw.registerEvaler("replace", repl);
      root->walk(&exw);
      if (exw.errors.size() > 0 && test.kind != hit::Field::Kind::None)
      {
        for (auto & err : exw.errors)
          FAIL() << "case " << i + 1 << " unexpected error: " << err << "\n";
        continue;
      }
      else if (exw.errors.size() == 0 && test.kind == hit::Field::Kind::None)
      {
        FAIL() << "case " << i + 1 << " missing expected error\n";
        continue;
      }
    }
    catch (std::exception & err)
    {
      FAIL() << "case " << i + 1 << " unexpected error: " << err.what() << "\n";
      continue;
    }

    auto n = root->find(test.key);
    if (!n)
    {
      FAIL() << "case " << i + 1 << " failed to find key '" << test.key << "'\n";
      continue;
    }
    if (n->strVal() != test.val)
    {
      FAIL() << "case " << i + 1 << " wrong value (key=" << test.key << "): got '" << n->strVal()
             << "', want '" << test.val << "'\n";
      continue;
    }

    auto f = dynamic_cast<hit::Field *>(n);
    if (!f)
      FAIL() << "case " << i + 1 << " node type is not NodeType::Field";
    else if (test.kind != hit::Field::Kind::None && f->kind() != test.kind)
      FAIL() << "case " << i + 1 << " wrong kind (key=" << test.key << "): got '"
             << strkind(f->kind()) << "', want '" << strkind(test.kind) << "'\n";
  }
}
<|endoftext|>


<commit_before>/**
 *  \file   stuff.hh
 *  \brief  contains some stuff
 **/
#ifndef STUFF_MISC_HH_INCLUDED
#define STUFF_MISC_HH_INCLUDED

#define SEGFAULT {int*J=0;*J=9;}

template <typename T>
bool isnan( T x ) { return !(x==x); }

#ifndef NDEBUG
    #ifndef LOGIC_ERROR
        #include <stdexcept>
        #include <sstream>
        #define LOGIC_ERROR \
            {\
                std::stringstream ss; ss << __FILE__ << ":" << __LINE__ << " should never be called"; \
                throw std::logic_error(ss.str());\
            }
    #endif
#else
    #define LOGIC_ERROR
#endif

#include <fstream>
#include <ostream>
#include <sstream>
#include <vector>
#include <assert.h>
#include <cmath>

namespace Stuff
{

/**
 *  \todo doc me
 **/
template < class ReturnType >
ReturnType fromString(const std::string& s)
{
    std::stringstream ss;
    ss << s;
    ReturnType r;
    ss >> r;
    return r;
}

/**
 *  \todo doc
 **/
template < class ReturnType >
std::string toString(const ReturnType& s)
{
    std::stringstream ss;
    ss << s;
    std::string r;
    ss >> r;
    return r;
}

template < class Info >
class TexOutput
{
    typedef std::vector< std::string >
        Strings;

    Info info_;
    double current_h_;
    Strings headers_;

    public:
        TexOutput( const Info& info, Strings& headers )
            : info_(info),
            current_h_(1.0),
            headers_(headers)
        {}

        TexOutput( Strings& headers )
            : info_(Info()),
            current_h_(1.0),
            headers_(headers)
        {}

        void setInfo( const Info& info )
        {
            info_ = info;
        }

        void putLineEnd( std::ofstream& outputFile_ )
        {
            outputFile_ << "\n"
                << "\\tabularnewline\n"
	              << "\\hline \n";
            outputFile_.flush();
        }

        void putErrorCol( std::ofstream& outputFile_, const double prevError_, const double error_, const double prevh_,  const bool /*initial*/  )
        {
            current_h_ = info_.grid_width;
            double factor = current_h_/prevh_;
            double eoc = std::log(error_/prevError_)/std::log(factor);
            outputFile_ << " & " << error_ << " & " << eoc;
        }

        void putHeader( std::ofstream& outputFile_ )
        {
            const unsigned int dynColSize = 2;
            const unsigned int statColSize = headers_.size() - 2;
            outputFile_ << "\\begin{longtable}{";
            for (unsigned int i=0;i<statColSize;i++) {
                outputFile_ << "|c|";
            }
            for (unsigned int i=0;i<dynColSize;i++) {
                outputFile_ << "|cc|";
            }
            outputFile_ << "}\n"
                << "\\caption{"
                << " Grid: " << info_.gridname
                << " BFG: " << ( info_.bfg ? std::string("yes") : std::string("no") )
                << " Polorder: " << info_.polorder
                << "}\\\\  \n"
                << "\\hline \n";

            for (unsigned int i=0;i<statColSize;i++) {
                outputFile_ << headers_[i];
                if ( i <  statColSize - 1 )
                    outputFile_ << " & ";
            }
            for (unsigned int i=0;i<dynColSize;i++) {
                outputFile_ << " & " << headers_[i+statColSize]
                    << " & EOC ";
            }
            outputFile_ << "\n \\endhead\n"
                        << "\\hline\n"
                        << "\\hline\n";
        }

        void putStaticCols( std::ofstream& outputFile_ )
        {
            outputFile_ << std::setw( 4 )
                << info_.grid_width << " & "
                << info_.codim0 << " & "
                << info_.run_time << " & "
                << info_.c11 << " & "
                << info_.d11 << " & "
                << info_.c12 << " & "
                << info_.d12 ;

        }

        void endTable( std::ofstream& outputFile_ )
        {
            outputFile_ << "\\end{longtable}";
            outputFile_.flush();
        }

        double get_h ()
        {
            return current_h_;
        }
};

/**
 *  \brief Only free mem pointed to by valid pointer, log warning otherwise
 *
 **/

template < class T >
void safe_delete ( T t )
{
    if (t){
        delete t;
        t=0;
    }
    //else log warning
}

template < class Container, class Element >
int getIdx( const Container& ct, Element e )
{
    int idx = 0;
    for ( typename Container::const_iterator it = ct.begin(); it != ct.end(); ++it, ++idx )
    {
        if ( *it == e )
            return idx;
    }
    return -1;
}

} // end namepspace stuff

#endif // end of stuff.hh
<commit_msg>even more info in table header<commit_after>/**
 *  \file   stuff.hh
 *  \brief  contains some stuff
 **/
#ifndef STUFF_MISC_HH_INCLUDED
#define STUFF_MISC_HH_INCLUDED

#define SEGFAULT {int*J=0;*J=9;}

template <typename T>
bool isnan( T x ) { return !(x==x); }

#ifndef NDEBUG
    #ifndef LOGIC_ERROR
        #include <stdexcept>
        #include <sstream>
        #define LOGIC_ERROR \
            {\
                std::stringstream ss; ss << __FILE__ << ":" << __LINE__ << " should never be called"; \
                throw std::logic_error(ss.str());\
            }
    #endif
#else
    #define LOGIC_ERROR
#endif

#include <fstream>
#include <ostream>
#include <sstream>
#include <vector>
#include <assert.h>
#include <cmath>

namespace Stuff
{

/**
 *  \todo doc me
 **/
template < class ReturnType >
ReturnType fromString(const std::string& s)
{
    std::stringstream ss;
    ss << s;
    ReturnType r;
    ss >> r;
    return r;
}

/**
 *  \todo doc
 **/
template < class ReturnType >
std::string toString(const ReturnType& s)
{
    std::stringstream ss;
    ss << s;
    std::string r;
    ss >> r;
    return r;
}

template < class Info >
class TexOutput
{
    typedef std::vector< std::string >
        Strings;

    Info info_;
    double current_h_;
    Strings headers_;

    public:
        TexOutput( const Info& info, Strings& headers )
            : info_(info),
            current_h_(1.0),
            headers_(headers)
        {}

        TexOutput( Strings& headers )
            : info_(Info()),
            current_h_(1.0),
            headers_(headers)
        {}

        void setInfo( const Info& info )
        {
            info_ = info;
        }

        void putLineEnd( std::ofstream& outputFile_ )
        {
            outputFile_ << "\n"
                << "\\tabularnewline\n"
	              << "\\hline \n";
            outputFile_.flush();
        }

        void putErrorCol( std::ofstream& outputFile_, const double prevError_, const double error_, const double prevh_,  const bool /*initial*/  )
        {
            current_h_ = info_.grid_width;
            double factor = current_h_/prevh_;
            double eoc = std::log(error_/prevError_)/std::log(factor);
            outputFile_ << " & " << error_ << " & " << eoc;
        }

        void putHeader( std::ofstream& outputFile_ )
        {
            const unsigned int dynColSize = 2;
            const unsigned int statColSize = headers_.size() - 2;
            outputFile_ << "\\begin{longtable}{";
            for (unsigned int i=0;i<statColSize;i++) {
                outputFile_ << "|c|";
            }
            for (unsigned int i=0;i<dynColSize;i++) {
                outputFile_ << "|cc|";
            }
            outputFile_ << "}\n"
                << "\\caption{"
                << " Grid: " << info_.gridname
                << " BFG: " << ( info_.bfg ? std::string("yes") : std::string("no") )
                << " Polorder (u,p,$\\sigma$): (" << info_.polorder_velocity << ", "<< info_.polorder_pressure << ", "<< info_.polorder_sigma << " ) "
                << "}\\\\  \n"
                << "\\hline \n";

            for (unsigned int i=0;i<statColSize;i++) {
                outputFile_ << headers_[i];
                if ( i <  statColSize - 1 )
                    outputFile_ << " & ";
            }
            for (unsigned int i=0;i<dynColSize;i++) {
                outputFile_ << " & " << headers_[i+statColSize]
                    << " & EOC ";
            }
            outputFile_ << "\n \\endhead\n"
                        << "\\hline\n"
                        << "\\hline\n";
        }

        void putStaticCols( std::ofstream& outputFile_ )
        {
            outputFile_ << std::setw( 4 )
                << info_.grid_width << " & "
                << info_.codim0 << " & "
                << info_.run_time << " & "
                << info_.c11 << " & "
                << info_.d11 << " & "
                << info_.c12 << " & "
                << info_.d12 ;

        }

        void endTable( std::ofstream& outputFile_ )
        {
            outputFile_ << "\\end{longtable}";
            outputFile_.flush();
        }

        double get_h ()
        {
            return current_h_;
        }
};

/**
 *  \brief Only free mem pointed to by valid pointer, log warning otherwise
 *
 **/

template < class T >
void safe_delete ( T t )
{
    if (t){
        delete t;
        t=0;
    }
    //else log warning
}

template < class Container, class Element >
int getIdx( const Container& ct, Element e )
{
    int idx = 0;
    for ( typename Container::const_iterator it = ct.begin(); it != ct.end(); ++it, ++idx )
    {
        if ( *it == e )
            return idx;
    }
    return -1;
}

} // end namepspace stuff

#endif // end of stuff.hh
<|endoftext|>