<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 "gtest/gtest.h"
#include "perfetto/base/build_config.h"
#include "src/base/test/test_task_runner.h"
#include "test/test_helper.h"

#include "src/profiling/memory/heapprofd_producer.h"
#include "src/tracing/ipc/default_socket.h"

#include <sys/system_properties.h>

// This test only works when run on Android using an Android Q version of
// Bionic.
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#error "This test can only be used on Android."
#endif

// If we're building on Android and starting the daemons ourselves,
// create the sockets in a world-writable location.
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
#define TEST_PRODUCER_SOCK_NAME "/data/local/tmp/traced_producer"
#else
#define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
#endif

namespace perfetto {
namespace profiling {
namespace {

void WaitForHeapprofd(uint64_t timeout_ms) {
  constexpr uint64_t kSleepMs = 10;
  std::vector<std::string> cmdlines{"heapprofd"};
  std::set<pid_t> pids;
  for (size_t i = 0; i < timeout_ms / kSleepMs && pids.empty(); ++i) {
    FindPidsForCmdlines(cmdlines, &pids);
    usleep(kSleepMs * 1000);
  }
}

class HeapprofdDelegate : public ThreadDelegate {
 public:
  HeapprofdDelegate(const std::string& producer_socket)
      : producer_socket_(producer_socket) {}
  ~HeapprofdDelegate() override = default;

  void Initialize(base::TaskRunner* task_runner) override {
    producer_.reset(
        new HeapprofdProducer(HeapprofdMode::kCentral, task_runner));
    producer_->ConnectWithRetries(producer_socket_.c_str());
  }

 private:
  std::string producer_socket_;
  std::unique_ptr<HeapprofdProducer> producer_;
};

constexpr const char* kEnableHeapprofdProperty = "persist.heapprofd.enable";

int __attribute__((unused)) SetProperty(std::string* value) {
  if (value) {
    __system_property_set(kEnableHeapprofdProperty, value->c_str());
    delete value;
  }
  return 0;
}

base::ScopedResource<std::string*, SetProperty, nullptr>
StartSystemHeapprofdIfRequired() {
  base::ignore_result(TEST_PRODUCER_SOCK_NAME);
  std::string prev_property_value = "0";
  const prop_info* pi = __system_property_find(kEnableHeapprofdProperty);
  if (pi) {
    __system_property_read_callback(
        pi,
        [](void* cookie, const char*, const char* value, uint32_t) {
          *reinterpret_cast<std::string*>(cookie) = value;
        },
        &prev_property_value);
  }
  __system_property_set(kEnableHeapprofdProperty, "1");
  WaitForHeapprofd(5000);
  return base::ScopedResource<std::string*, SetProperty, nullptr>(
      new std::string(prev_property_value));
}

pid_t ForkContinousMalloc(size_t bytes) {
  pid_t pid = fork();
  switch (pid) {
    case -1:
      PERFETTO_FATAL("Failed to fork.");
    case 0:
      for (;;) {
        // This volatile is needed to prevent the compiler from trying to be
        // helpful and compiling a "useless" malloc + free into a noop.
        volatile char* x = static_cast<char*>(malloc(bytes));
        if (x) {
          x[1] = 'x';
          free(const_cast<char*>(x));
        }
      }
    default:
      break;
  }
  return pid;
}

class HeapprofdEndToEnd : public ::testing::Test {
 public:
  HeapprofdEndToEnd() {
    // This is not needed for correctness, but works around a init behavior that
    // makes this test take much longer. If persist.heapprofd.enable is set to 0
    // and then set to 1 again too quickly, init decides that the service is
    // "restarting" and waits before restarting it.
    usleep(50000);
    helper.StartServiceIfRequired();
    unset_property = StartSystemHeapprofdIfRequired();

    helper.ConnectConsumer();
    helper.WaitForConsumerConnect();
  }

 protected:
  base::TestTaskRunner task_runner;
  TestHelper helper{&task_runner};

#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
  TaskRunnerThread producer_thread("perfetto.prd");
  producer_thread.Start(std::unique_ptr<HeapprofdDelegate>(
      new HeapprofdDelegate(TEST_PRODUCER_SOCK_NAME)));
#else
  base::ScopedResource<std::string*, SetProperty, nullptr> unset_property;
#endif
};

// TODO(b/121352331): deflake and re-enable this test.
TEST_F(HeapprofdEndToEnd, DISABLED_Smoke) {
  constexpr size_t kAllocSize = 1024;

  pid_t pid = ForkContinousMalloc(kAllocSize);

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(10 * 1024);
  trace_config.set_duration_ms(1000);

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.heapprofd");
  ds_config->set_target_buffer(0);

  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
  heapprofd_config->set_sampling_interval_bytes(1);
  *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
  heapprofd_config->set_all(false);
  heapprofd_config->mutable_continuous_dump_config()->set_dump_phase_ms(0);
  heapprofd_config->mutable_continuous_dump_config()->set_dump_interval_ms(100);

  helper.StartTracing(trace_config);
  helper.WaitForTracingDisabled(5000);

  helper.ReadData();
  helper.WaitForReadData();

  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
  PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);

  const auto& packets = helper.trace();
  ASSERT_GT(packets.size(), 0u);
  size_t profile_packets = 0;
  size_t samples = 0;
  uint64_t last_allocated = 0;
  uint64_t last_freed = 0;
  for (const protos::TracePacket& packet : packets) {
    if (packet.has_profile_packet() &&
        packet.profile_packet().process_dumps().size() > 0) {
      const auto& dumps = packet.profile_packet().process_dumps();
      ASSERT_EQ(dumps.size(), 1);
      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
      EXPECT_EQ(dump.pid(), pid);
      EXPECT_EQ(dump.samples().size(), 1);
      for (const auto& sample : dump.samples()) {
        samples++;
        EXPECT_EQ(sample.self_allocated() % kAllocSize, 0);
        EXPECT_EQ(sample.self_freed() % kAllocSize, 0);
        last_allocated = sample.self_allocated();
        last_freed = sample.self_freed();
      }
      profile_packets++;
    }
  }
  EXPECT_GT(profile_packets, 0);
  EXPECT_GT(samples, 0);
  EXPECT_GT(last_allocated, 0);
  EXPECT_GT(last_freed, 0);
}

// TODO(b/121352331): deflake and re-enable this test.
TEST_F(HeapprofdEndToEnd, DISABLED_FinalFlush) {
  constexpr size_t kAllocSize = 1024;

  pid_t pid = ForkContinousMalloc(kAllocSize);

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(10 * 1024);
  trace_config.set_duration_ms(1000);

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.heapprofd");
  ds_config->set_target_buffer(0);

  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
  heapprofd_config->set_sampling_interval_bytes(1);
  *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
  heapprofd_config->set_all(false);

  helper.StartTracing(trace_config);
  helper.WaitForTracingDisabled(5000);

  helper.ReadData();
  helper.WaitForReadData();

  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
  PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);

  const auto& packets = helper.trace();
  ASSERT_GT(packets.size(), 0u);
  size_t profile_packets = 0;
  size_t samples = 0;
  uint64_t last_allocated = 0;
  uint64_t last_freed = 0;
  for (const protos::TracePacket& packet : packets) {
    if (packet.has_profile_packet() &&
        packet.profile_packet().process_dumps().size() > 0) {
      const auto& dumps = packet.profile_packet().process_dumps();
      ASSERT_EQ(dumps.size(), 1);
      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
      EXPECT_EQ(dump.pid(), pid);
      EXPECT_EQ(dump.samples().size(), 1);
      for (const auto& sample : dump.samples()) {
        samples++;
        EXPECT_EQ(sample.self_allocated() % kAllocSize, 0);
        EXPECT_EQ(sample.self_freed() % kAllocSize, 0);
        last_allocated = sample.self_allocated();
        last_freed = sample.self_freed();
      }
      profile_packets++;
    }
  }
  EXPECT_EQ(profile_packets, 1);
  EXPECT_GT(samples, 0);
  EXPECT_GT(last_allocated, 0);
  EXPECT_GT(last_freed, 0);
}

// TODO(b/121352331): deflake and re-enable this test.
TEST_F(HeapprofdEndToEnd, DISABLED_NativeStartup) {
  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(10 * 1024);
  trace_config.set_duration_ms(5000);

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.heapprofd");

  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
  heapprofd_config->set_sampling_interval_bytes(1);
  *heapprofd_config->add_process_cmdline() = "find";
  heapprofd_config->set_all(false);

  helper.StartTracing(trace_config);

  // Wait to guarantee that the process forked below is hooked by the profiler
  // by virtue of the startup check, and not by virtue of being seen as a
  // runnning process. This sleep is here to prevent that, accidentally, the
  // test gets to the fork()+exec() too soon, before the heap profiling daemon
  // has received the trace config.
  sleep(1);

  pid_t pid = fork();
  switch (pid) {
    case -1:
      PERFETTO_FATAL("Failed to fork.");
    case 0: {
      int null = open("/dev/null", O_RDWR);
      dup2(null, STDIN_FILENO);
      dup2(null, STDOUT_FILENO);
      dup2(null, STDERR_FILENO);
      // TODO(fmayer): Use a dedicated test binary rather than relying on find
      // doing allocations.
      PERFETTO_CHECK(execl("/system/bin/find", "find", "/", nullptr) == 0);
      break;
    }
    default:
      break;
  }

  helper.WaitForTracingDisabled(10000);

  helper.ReadData();
  helper.WaitForReadData();

  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
  PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);

  const auto& packets = helper.trace();
  ASSERT_GT(packets.size(), 0u);
  size_t profile_packets = 0;
  size_t samples = 0;
  uint64_t total_allocated = 0;
  uint64_t total_freed = 0;
  for (const protos::TracePacket& packet : packets) {
    if (packet.has_profile_packet() &&
        packet.profile_packet().process_dumps().size() > 0) {
      const auto& dumps = packet.profile_packet().process_dumps();
      ASSERT_EQ(dumps.size(), 1);
      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
      EXPECT_EQ(dump.pid(), pid);
      profile_packets++;
      for (const auto& sample : dump.samples()) {
        samples++;
        total_allocated += sample.self_allocated();
        total_freed += sample.self_freed();
      }
    }
  }
  EXPECT_EQ(profile_packets, 1);
  EXPECT_GT(samples, 0);
  EXPECT_GT(total_allocated, 0);
  EXPECT_GT(total_freed, 0);
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto
<commit_msg>profiling: Re-enable end to end tests. am: b10161389f am: 6d1dea6861 am: 7427a01f21<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 "gtest/gtest.h"
#include "perfetto/base/build_config.h"
#include "src/base/test/test_task_runner.h"
#include "test/test_helper.h"

#include "src/profiling/memory/heapprofd_producer.h"
#include "src/tracing/ipc/default_socket.h"

#include <sys/system_properties.h>

// This test only works when run on Android using an Android Q version of
// Bionic.
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
#error "This test can only be used on Android."
#endif

// If we're building on Android and starting the daemons ourselves,
// create the sockets in a world-writable location.
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
#define TEST_PRODUCER_SOCK_NAME "/data/local/tmp/traced_producer"
#else
#define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
#endif

namespace perfetto {
namespace profiling {
namespace {

void WaitForHeapprofd(uint64_t timeout_ms) {
  constexpr uint64_t kSleepMs = 10;
  std::vector<std::string> cmdlines{"heapprofd"};
  std::set<pid_t> pids;
  for (size_t i = 0; i < timeout_ms / kSleepMs && pids.empty(); ++i) {
    FindPidsForCmdlines(cmdlines, &pids);
    usleep(kSleepMs * 1000);
  }
}

class HeapprofdDelegate : public ThreadDelegate {
 public:
  HeapprofdDelegate(const std::string& producer_socket)
      : producer_socket_(producer_socket) {}
  ~HeapprofdDelegate() override = default;

  void Initialize(base::TaskRunner* task_runner) override {
    producer_.reset(
        new HeapprofdProducer(HeapprofdMode::kCentral, task_runner));
    producer_->ConnectWithRetries(producer_socket_.c_str());
  }

 private:
  std::string producer_socket_;
  std::unique_ptr<HeapprofdProducer> producer_;
};

constexpr const char* kEnableHeapprofdProperty = "persist.heapprofd.enable";

int __attribute__((unused)) SetProperty(std::string* value) {
  if (value) {
    __system_property_set(kEnableHeapprofdProperty, value->c_str());
    delete value;
  }
  return 0;
}

base::ScopedResource<std::string*, SetProperty, nullptr>
StartSystemHeapprofdIfRequired() {
  base::ignore_result(TEST_PRODUCER_SOCK_NAME);
  std::string prev_property_value = "0";
  const prop_info* pi = __system_property_find(kEnableHeapprofdProperty);
  if (pi) {
    __system_property_read_callback(
        pi,
        [](void* cookie, const char*, const char* value, uint32_t) {
          *reinterpret_cast<std::string*>(cookie) = value;
        },
        &prev_property_value);
  }
  __system_property_set(kEnableHeapprofdProperty, "1");
  WaitForHeapprofd(5000);
  return base::ScopedResource<std::string*, SetProperty, nullptr>(
      new std::string(prev_property_value));
}

pid_t ForkContinousMalloc(size_t bytes) {
  pid_t pid = fork();
  switch (pid) {
    case -1:
      PERFETTO_FATAL("Failed to fork.");
    case 0:
      for (;;) {
        // This volatile is needed to prevent the compiler from trying to be
        // helpful and compiling a "useless" malloc + free into a noop.
        volatile char* x = static_cast<char*>(malloc(bytes));
        if (x) {
          x[1] = 'x';
          free(const_cast<char*>(x));
        }
      }
    default:
      break;
  }
  return pid;
}

class HeapprofdEndToEnd : public ::testing::Test {
 public:
  HeapprofdEndToEnd() {
    // This is not needed for correctness, but works around a init behavior that
    // makes this test take much longer. If persist.heapprofd.enable is set to 0
    // and then set to 1 again too quickly, init decides that the service is
    // "restarting" and waits before restarting it.
    usleep(50000);
    helper.StartServiceIfRequired();
    unset_property = StartSystemHeapprofdIfRequired();

    helper.ConnectConsumer();
    helper.WaitForConsumerConnect();
  }

 protected:
  base::TestTaskRunner task_runner;
  TestHelper helper{&task_runner};

#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
  TaskRunnerThread producer_thread("perfetto.prd");
  producer_thread.Start(std::unique_ptr<HeapprofdDelegate>(
      new HeapprofdDelegate(TEST_PRODUCER_SOCK_NAME)));
#else
  base::ScopedResource<std::string*, SetProperty, nullptr> unset_property;
#endif
};

// TODO(b/121352331): deflake and re-enable this test.
TEST_F(HeapprofdEndToEnd, Smoke) {
  constexpr size_t kAllocSize = 1024;

  pid_t pid = ForkContinousMalloc(kAllocSize);

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(10 * 1024);
  trace_config.set_duration_ms(1000);

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.heapprofd");
  ds_config->set_target_buffer(0);

  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
  heapprofd_config->set_sampling_interval_bytes(1);
  *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
  heapprofd_config->set_all(false);
  heapprofd_config->mutable_continuous_dump_config()->set_dump_phase_ms(0);
  heapprofd_config->mutable_continuous_dump_config()->set_dump_interval_ms(100);

  helper.StartTracing(trace_config);
  helper.WaitForTracingDisabled(10000);

  helper.ReadData();
  helper.WaitForReadData();

  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
  PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);

  const auto& packets = helper.trace();
  ASSERT_GT(packets.size(), 0u);
  size_t profile_packets = 0;
  size_t samples = 0;
  uint64_t last_allocated = 0;
  uint64_t last_freed = 0;
  for (const protos::TracePacket& packet : packets) {
    if (packet.has_profile_packet() &&
        packet.profile_packet().process_dumps().size() > 0) {
      const auto& dumps = packet.profile_packet().process_dumps();
      ASSERT_EQ(dumps.size(), 1);
      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
      EXPECT_EQ(dump.pid(), pid);
      for (const auto& sample : dump.samples()) {
        samples++;
        EXPECT_EQ(sample.self_allocated() % kAllocSize, 0);
        EXPECT_EQ(sample.self_freed() % kAllocSize, 0);
        last_allocated = sample.self_allocated();
        last_freed = sample.self_freed();
      }
      profile_packets++;
    }
  }
  EXPECT_GT(profile_packets, 0);
  EXPECT_GT(samples, 0);
  EXPECT_GT(last_allocated, 0);
  EXPECT_GT(last_freed, 0);
}

// TODO(b/121352331): deflake and re-enable this test.
TEST_F(HeapprofdEndToEnd, FinalFlush) {
  constexpr size_t kAllocSize = 1024;

  pid_t pid = ForkContinousMalloc(kAllocSize);

  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(10 * 1024);
  trace_config.set_duration_ms(1000);

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.heapprofd");
  ds_config->set_target_buffer(0);

  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
  heapprofd_config->set_sampling_interval_bytes(1);
  *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
  heapprofd_config->set_all(false);

  helper.StartTracing(trace_config);
  helper.WaitForTracingDisabled(10000);

  helper.ReadData();
  helper.WaitForReadData();

  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
  PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);

  const auto& packets = helper.trace();
  ASSERT_GT(packets.size(), 0u);
  size_t profile_packets = 0;
  size_t samples = 0;
  uint64_t last_allocated = 0;
  uint64_t last_freed = 0;
  for (const protos::TracePacket& packet : packets) {
    if (packet.has_profile_packet() &&
        packet.profile_packet().process_dumps().size() > 0) {
      const auto& dumps = packet.profile_packet().process_dumps();
      ASSERT_EQ(dumps.size(), 1);
      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
      EXPECT_EQ(dump.pid(), pid);
      EXPECT_EQ(dump.samples().size(), 1);
      for (const auto& sample : dump.samples()) {
        samples++;
        EXPECT_EQ(sample.self_allocated() % kAllocSize, 0);
        EXPECT_EQ(sample.self_freed() % kAllocSize, 0);
        last_allocated = sample.self_allocated();
        last_freed = sample.self_freed();
      }
      profile_packets++;
    }
  }
  EXPECT_EQ(profile_packets, 1);
  EXPECT_GT(samples, 0);
  EXPECT_GT(last_allocated, 0);
  EXPECT_GT(last_freed, 0);
}

// TODO(b/121352331): deflake and re-enable this test.
TEST_F(HeapprofdEndToEnd, NativeStartup) {
  TraceConfig trace_config;
  trace_config.add_buffers()->set_size_kb(10 * 1024);
  trace_config.set_duration_ms(5000);

  auto* ds_config = trace_config.add_data_sources()->mutable_config();
  ds_config->set_name("android.heapprofd");

  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
  heapprofd_config->set_sampling_interval_bytes(1);
  *heapprofd_config->add_process_cmdline() = "find";
  heapprofd_config->set_all(false);

  helper.StartTracing(trace_config);

  // Wait to guarantee that the process forked below is hooked by the profiler
  // by virtue of the startup check, and not by virtue of being seen as a
  // runnning process. This sleep is here to prevent that, accidentally, the
  // test gets to the fork()+exec() too soon, before the heap profiling daemon
  // has received the trace config.
  sleep(1);

  pid_t pid = fork();
  switch (pid) {
    case -1:
      PERFETTO_FATAL("Failed to fork.");
    case 0: {
      int null = open("/dev/null", O_RDWR);
      dup2(null, STDIN_FILENO);
      dup2(null, STDOUT_FILENO);
      dup2(null, STDERR_FILENO);
      // TODO(fmayer): Use a dedicated test binary rather than relying on find
      // doing allocations.
      PERFETTO_CHECK(execl("/system/bin/find", "find", "/", nullptr) == 0);
      break;
    }
    default:
      break;
  }

  helper.WaitForTracingDisabled(10000);

  helper.ReadData();
  helper.WaitForReadData();

  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
  PERFETTO_CHECK(waitpid(pid, nullptr, 0) == pid);

  const auto& packets = helper.trace();
  ASSERT_GT(packets.size(), 0u);
  size_t profile_packets = 0;
  size_t samples = 0;
  uint64_t total_allocated = 0;
  uint64_t total_freed = 0;
  for (const protos::TracePacket& packet : packets) {
    if (packet.has_profile_packet() &&
        packet.profile_packet().process_dumps().size() > 0) {
      const auto& dumps = packet.profile_packet().process_dumps();
      ASSERT_EQ(dumps.size(), 1);
      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
      EXPECT_EQ(dump.pid(), pid);
      profile_packets++;
      for (const auto& sample : dump.samples()) {
        samples++;
        total_allocated += sample.self_allocated();
        total_freed += sample.self_freed();
      }
    }
  }
  EXPECT_EQ(profile_packets, 1);
  EXPECT_GT(samples, 0);
  EXPECT_GT(total_allocated, 0);
  EXPECT_GT(total_freed, 0);
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto
<|endoftext|>


<commit_before>#include <yaml-cpp/yaml.h>

#include <iostream>
#include <fstream>
#include <map>

#include "Config.hh"
#include "Exception.hh"

namespace aegir {

  // PIN default configuration
  pinconfig_t g_pinconfig = pinconfig_t{
    {"swled", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"swon",  PinConfig(PinMode::IN, PinPull::DOWN)},
    {"swoff", PinConfig(PinMode::IN, PinPull::DOWN)},
    {"cs0", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"cs1", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"cs2", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"cs3", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"rimsheat", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"rimspump", PinConfig(PinMode::OUT, PinPull::NONE)}
  };

  static std::set<std::string> g_tcnames{"RIMS", "MashTun", "HLT", "BK"};

  // SPI ChipSelector string translations
  static std::map<ChipSelectors, std::string> g_spi_cs_to_string{
    {ChipSelectors::DirectSelect, "DirectSelect"}};
  static std::map<std::string, ChipSelectors> g_spi_string_to_cs{
    {"DirectSelect",ChipSelectors::DirectSelect}};
  // ThermoCouple type lookups
  std::map<std::string, MAX31856::TCType> g_string_to_tctype{
    {"B", MAX31856::TCType::B},
      {"E", MAX31856::TCType::E},
	{"J", MAX31856::TCType::J},
	  {"K", MAX31856::TCType::K},
	    {"N", MAX31856::TCType::N},
	      {"R", MAX31856::TCType::R},
		{"S", MAX31856::TCType::S},
		  {"T", MAX31856::TCType::T}
  };
  std::map<MAX31856::TCType, std::string> g_tctype_to_string{
    {MAX31856::TCType::B, "B"},
      {MAX31856::TCType::E, "E"},
	{MAX31856::TCType::J, "J"},
	  {MAX31856::TCType::K, "K"},
	    {MAX31856::TCType::N, "N"},
	      {MAX31856::TCType::R, "R"},
		{MAX31856::TCType::S, "S"},
		  {MAX31856::TCType::T, "T"}
  };
  // Noisefilter lookups
  std::map<std::string, NoiseFilters> g_string_to_noisefilter{
    {"50Hz", NoiseFilters::HZ50},
    {"60Hz", NoiseFilters::HZ60}
  };
  std::map<NoiseFilters, std::string> g_noisefilter_to_string{
    {NoiseFilters::HZ50, "50Hz"},
      {NoiseFilters::HZ60, "60Hz"}
  };

  // The singleton instance holder
  Config *Config::c_instance=0;

  Config::Config(const std::string &_cfgfile, bool _noload): c_cfgfile(_cfgfile) {
    setDefaults();
    if ( !_noload ) load();
  }

  Config::~Config() {
    save();
  }

  Config *Config::instantiate(const std::string &_cfgfile, bool _noload) {
    if ( !c_instance ) c_instance = new Config(_cfgfile, _noload);
    return c_instance;
  }

  // TODO: throw exception when !c_instance
  Config *Config::getInstance() {
    return c_instance;
  }

  void Config::setDefaults() {
    c_device = "/dev/gpioc0";

    // PIN layout
    c_pinlayout.clear();
    c_pinlayout["swled"] = 16;
    c_pinlayout["swon"]  = 20;
    c_pinlayout["swoff"] = 21;
    c_pinlayout["rimsheat"] = 23;
    c_pinlayout["rimspump"] = 24;

    // SPI config
    c_spidev = "/dev/spigen0";
    c_spi_chipselector = ChipSelectors::DirectSelect;
    c_pinlayout["cs0"] = 8;
    c_pinlayout["cs1"] = 7;
    c_pinlayout["cs2"] = 5;
    c_pinlayout["cs3"] = 6;
    // SPI / MAX31856
    c_spi_max31856_tctype = MAX31856::TCType::T;
    c_spi_max31856_noisefilter = NoiseFilters::HZ50;
    // SPI / chips
    c_spi_dschips = {{0, "cs0"}, {1, "cs1"}, {2, "cs2"}, {3, "cs3"}};

    // thermocouples
    c_thermocouples = {{"MashTun", 0}, {"RIMS", 1}, {"HLT", 2}, {"BK", 3}};

    // thermocouple reading interval
    c_thermoival = 1;

    // the PR ZMQ socket
    c_zmq_pr_port = 42069;

    // the heating element's power
    c_hepower = 3500;
  }

  void Config::load() {
    YAML::Node config;
    try {
      config = YAML::LoadFile(c_cfgfile);
    }
    catch (YAML::ParserException &e) {
      throw Exception("YAML::ParseException: %s", e.what());
    }
    catch (std::exception &e) {
      throw Exception("Unknown exception: %s", e.what());
    }
    catch (...) {
      throw Exception("Unknown exception");
    }

    // The config file is loaded into config, now put it into local variables
    try {
      // GPIO
      if ( config["gpio"] && config["gpio"].IsMap() ) {
	YAML::Node gpio = config["gpio"];
	// load the device
	if ( gpio["device"] ) c_device = gpio["device"].as<std::string>();

	// the PIN configuration
	if ( gpio["pins"] && gpio["pins"].IsMap() ) {
	  YAML::Node pins = gpio["pins"];
	  std::map<std::string, int> pinlayout(c_pinlayout);
	  for (const auto &it: g_pinconfig)
	    if ( pins[it.first] ) pinlayout[it.first] = pins[it.first].as<int>();

	  checkPinConfig(pinlayout);
	  c_pinlayout = pinlayout;
	} // PIN config
      } // GPIO section

      // SPI
      if ( config["spi"] && config["spi"].IsMap() ) {
	YAML::Node spi = config["spi"];

	// load the device
	if ( spi["device"] ) c_spidev = spi["device"].as<std::string>();
	// load the selector
	if ( spi["selector"] ) {
	  std::string csname(spi["selector"].as<std::string>());
	  auto it = g_spi_string_to_cs.find(csname);
	  if ( it == g_spi_string_to_cs.end() ) {
	    throw Exception("Unknown SPI chip selector: %s\n", csname.c_str());
	  }
	  c_spi_chipselector = it->second;
	}
	// MAX31856 config
	if ( spi["MAX31856"] && spi["MAX31856"].IsMap() ) {
	  auto max31856 = spi["MAX31856"];
	  // TC type
	  if ( max31856["tctype"] ) {
	    std::string tctype = max31856["tctype"].as<std::string>();
	    auto it = g_string_to_tctype.find(tctype);
	    if ( it == g_string_to_tctype.end() ) {
	      throw Exception("Unknown TC type: %s\n", tctype.c_str());
	    }
	    c_spi_max31856_tctype = it->second;
	  }// TC type
	  // Noise Filter, AKA 50/60Hz
	  if ( max31856["noisefilter"] ) {
	    std::string nf = max31856["noisefilter"].as<std::string>();
	    auto it = g_string_to_noisefilter.find(nf);
	    if ( it == g_string_to_noisefilter.end() ) {
	      throw Exception("Unknown Noise Filter mode: %s\n", nf.c_str());
	    }
	    c_spi_max31856_noisefilter = it->second;
	  }// Noise Filter
	} // MAX31856 config
	// DirectSelect Chip Selector
	// the PIN configuration
	if ( spi["DirectSelect"] && spi["DirectSelect"].IsMap() ) {
	  YAML::Node ds = spi["DirectSelect"];

	  // we have 3 hardcoded sensors at this level, for now
	  for (int i=0; i<3; ++i) {
	    if ( !ds[i] ) continue;
	    std::string pin = ds[i].as<std::string>();
	    auto it = g_pinconfig.find(pin);
	    if ( it == g_pinconfig.end() )
	      throw Exception("Unknown pin: %s", pin.c_str());
	    c_spi_dschips[i] = pin;
	  }

	  // Now we have to check for dups
	  std::set<std::string> tmp;
	  for ( auto &it: c_spi_dschips ) {
	    auto it2 = tmp.find(it.second);
	    if ( it2 != tmp.end() )
	      throw Exception("Duplicate pin for DirectSelect: %s", it.second.c_str());
	    tmp.insert(it.second);
	  }
	} // PIN config

	// Thermocouples
	if ( spi["thermocouples"] && spi["thermocouples"].IsMap() ) {
	  YAML::Node tc = spi["thermocouples"];

	  // We are going through only the valid ones, the rest are ignored
	  // also, not emptying the list, because that's how unset values default
	  for (auto &it: g_tcnames) {
	    if ( tc[it] ) {
	      int id = tc[it].as<int>();
	      if ( id < 0 || id > 3 )
		throw Exception("Thermocouple id out of range: %i", id);
	      c_thermocouples[it] = id;
	    }
	  }
	  // now verify whether any of them is on the same id
	  std::set<int> tmp;
	  for (auto &it: c_thermocouples) {
	    if ( tmp.find(it.second) != tmp.end() )
	      throw Exception("Duplicate thermocouple id: %i", it.second);
	    tmp.insert(it.second);
	  }
	} // thermocouples
	if ( spi["thermointerval"] && spi["thermointerval"].IsScalar() ) {
	  YAML::Node ti = spi["thermointerval"];
	  c_thermoival = ti.as<uint32_t>();
	if ( c_thermoival > 60 )
	  throw Exception("Thermocouple reading interval is too high: %lu", c_thermoival);
	}
      } // SPI section

      // ZMQ PR socket
      if ( config["prport"] && config["prport"].IsScalar() ) {
	YAML::Node prsock = config["prport"];
	c_zmq_pr_port = prsock.as<uint16_t>();
      }

      // Heating Element's Power
      if ( config["elementpower"] && config["elementpower"].IsScalar() ) {
	YAML::Node hep = config["elementpower"];
	c_hepower = hep.as<uint32_t>();
	if ( c_hepower < 1000 || c_hepower > 10000 )
	  throw Exception("Heating element's power is out of range");
      }

    }
    catch (std::exception &e) {
      throw Exception("Error during parsing config: %s", e.what());
    }
  }

  void Config::checkPinConfig(std::map<std::string, int> &_layout) {
    std::map<int, int> count;

    for ( const auto &it: _layout ) {
      if ( count.find(it.second) == count.end() ) {
	count[it.second] = 0;
      } else {
	count[it.second] += 1;
      }
    }

    for ( const auto &it: count ) {
      if ( it.second > 1 ) throw Exception("Conflict on Pin %i\n", it.first);
    }
  }

  Config &Config::save() {
    YAML::Emitter yout;

    yout << YAML::BeginMap;
    // GPIO config
    yout << YAML::Key << "gpio";
    yout << YAML::Value << YAML::BeginMap;
    yout << YAML::Key << "device" << YAML::Value << c_device;
    yout << YAML::Key << "pins" << YAML::Value << c_pinlayout;
    yout << YAML::EndMap;

    // SPI config
    yout << YAML::Key << "spi";
    yout << YAML::Value << YAML::BeginMap;
    yout << YAML::Key << "device" << YAML::Value << c_spidev;
    yout << YAML::Key << "selector" << YAML::Value << g_spi_cs_to_string[c_spi_chipselector];

    // SPI / MAX31856 config
    yout << YAML::Key << "MAX31856";
    yout << YAML::Value <<
      std::map<std::string, std::string>{
      {"tctype", g_tctype_to_string[c_spi_max31856_tctype]},
	{"noisefilter", g_noisefilter_to_string[c_spi_max31856_noisefilter]}};
    // end SPI / MAX31856

    // SPI / DirectSelect
    yout << YAML::Key << "DirectSelect";
    yout << YAML::Value << c_spi_dschips;

    // Thermocouple layout
    yout << YAML::Key << "thermocouples";
    yout << YAML::Value << c_thermocouples;

    // thermocouple reading interval
    yout << YAML::Key << "thermointerval";
    yout << YAML::Value << c_thermoival;

    yout << YAML::EndMap; // end of SPI

    // ZMQ PR port
    yout << YAML::Key << "prport" << YAML::Value << c_zmq_pr_port;

    // Heating element's power in watts
    yout << YAML::Key << "elementpower" << YAML::Value << c_hepower;

    // End the config
    yout << YAML::EndMap;

    std::ofstream outfile;

    outfile.open(c_cfgfile, std::ios::out | std::ios::trunc);
    outfile << yout.c_str() << std::endl;
    outfile.close();

    return *this;
  }

  const std::string &Config::getGPIODevice() const {
    return c_device;
  }

  Config &Config::getPinConfig(pinlayout_t &_layout) {
    _layout = c_pinlayout;
    return *this;
  }
}
<commit_msg>[brewd] Added the buzzer pin, and adjusted default heating element to 3kW<commit_after>#include <yaml-cpp/yaml.h>

#include <iostream>
#include <fstream>
#include <map>

#include "Config.hh"
#include "Exception.hh"

namespace aegir {

  // PIN default configuration
  pinconfig_t g_pinconfig = pinconfig_t{
    {"swled", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"swon",  PinConfig(PinMode::IN, PinPull::DOWN)},
    {"swoff", PinConfig(PinMode::IN, PinPull::DOWN)},
    {"cs0", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"cs1", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"cs2", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"cs3", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"rimsheat", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"rimspump", PinConfig(PinMode::OUT, PinPull::NONE)},
    {"buzzer", PinConfig(PinMode::OUT, PinPull::NONE)}
  };

  static std::set<std::string> g_tcnames{"RIMS", "MashTun", "HLT", "BK"};

  // SPI ChipSelector string translations
  static std::map<ChipSelectors, std::string> g_spi_cs_to_string{
    {ChipSelectors::DirectSelect, "DirectSelect"}};
  static std::map<std::string, ChipSelectors> g_spi_string_to_cs{
    {"DirectSelect",ChipSelectors::DirectSelect}};
  // ThermoCouple type lookups
  std::map<std::string, MAX31856::TCType> g_string_to_tctype{
    {"B", MAX31856::TCType::B},
      {"E", MAX31856::TCType::E},
	{"J", MAX31856::TCType::J},
	  {"K", MAX31856::TCType::K},
	    {"N", MAX31856::TCType::N},
	      {"R", MAX31856::TCType::R},
		{"S", MAX31856::TCType::S},
		  {"T", MAX31856::TCType::T}
  };
  std::map<MAX31856::TCType, std::string> g_tctype_to_string{
    {MAX31856::TCType::B, "B"},
      {MAX31856::TCType::E, "E"},
	{MAX31856::TCType::J, "J"},
	  {MAX31856::TCType::K, "K"},
	    {MAX31856::TCType::N, "N"},
	      {MAX31856::TCType::R, "R"},
		{MAX31856::TCType::S, "S"},
		  {MAX31856::TCType::T, "T"}
  };
  // Noisefilter lookups
  std::map<std::string, NoiseFilters> g_string_to_noisefilter{
    {"50Hz", NoiseFilters::HZ50},
    {"60Hz", NoiseFilters::HZ60}
  };
  std::map<NoiseFilters, std::string> g_noisefilter_to_string{
    {NoiseFilters::HZ50, "50Hz"},
      {NoiseFilters::HZ60, "60Hz"}
  };

  // The singleton instance holder
  Config *Config::c_instance=0;

  Config::Config(const std::string &_cfgfile, bool _noload): c_cfgfile(_cfgfile) {
    setDefaults();
    if ( !_noload ) load();
  }

  Config::~Config() {
    save();
  }

  Config *Config::instantiate(const std::string &_cfgfile, bool _noload) {
    if ( !c_instance ) c_instance = new Config(_cfgfile, _noload);
    return c_instance;
  }

  // TODO: throw exception when !c_instance
  Config *Config::getInstance() {
    return c_instance;
  }

  void Config::setDefaults() {
    c_device = "/dev/gpioc0";

    // PIN layout
    c_pinlayout.clear();
    c_pinlayout["swled"] = 16;
    c_pinlayout["swon"]  = 20;
    c_pinlayout["swoff"] = 21;
    c_pinlayout["rimsheat"] = 23;
    c_pinlayout["rimspump"] = 24;
    c_pinlayout["buzzer"] = 26;

    // SPI config
    c_spidev = "/dev/spigen0";
    c_spi_chipselector = ChipSelectors::DirectSelect;
    c_pinlayout["cs0"] = 8;
    c_pinlayout["cs1"] = 7;
    c_pinlayout["cs2"] = 5;
    c_pinlayout["cs3"] = 6;
    // SPI / MAX31856
    c_spi_max31856_tctype = MAX31856::TCType::T;
    c_spi_max31856_noisefilter = NoiseFilters::HZ50;
    // SPI / chips
    c_spi_dschips = {{0, "cs0"}, {1, "cs1"}, {2, "cs2"}, {3, "cs3"}};

    // thermocouples
    c_thermocouples = {{"MashTun", 0}, {"RIMS", 1}, {"HLT", 2}, {"BK", 3}};

    // thermocouple reading interval
    c_thermoival = 1;

    // the PR ZMQ socket
    c_zmq_pr_port = 42069;

    // the heating element's power
    c_hepower = 3000;
  }

  void Config::load() {
    YAML::Node config;
    try {
      config = YAML::LoadFile(c_cfgfile);
    }
    catch (YAML::ParserException &e) {
      throw Exception("YAML::ParseException: %s", e.what());
    }
    catch (std::exception &e) {
      throw Exception("Unknown exception: %s", e.what());
    }
    catch (...) {
      throw Exception("Unknown exception");
    }

    // The config file is loaded into config, now put it into local variables
    try {
      // GPIO
      if ( config["gpio"] && config["gpio"].IsMap() ) {
	YAML::Node gpio = config["gpio"];
	// load the device
	if ( gpio["device"] ) c_device = gpio["device"].as<std::string>();

	// the PIN configuration
	if ( gpio["pins"] && gpio["pins"].IsMap() ) {
	  YAML::Node pins = gpio["pins"];
	  std::map<std::string, int> pinlayout(c_pinlayout);
	  for (const auto &it: g_pinconfig)
	    if ( pins[it.first] ) pinlayout[it.first] = pins[it.first].as<int>();

	  checkPinConfig(pinlayout);
	  c_pinlayout = pinlayout;
	} // PIN config
      } // GPIO section

      // SPI
      if ( config["spi"] && config["spi"].IsMap() ) {
	YAML::Node spi = config["spi"];

	// load the device
	if ( spi["device"] ) c_spidev = spi["device"].as<std::string>();
	// load the selector
	if ( spi["selector"] ) {
	  std::string csname(spi["selector"].as<std::string>());
	  auto it = g_spi_string_to_cs.find(csname);
	  if ( it == g_spi_string_to_cs.end() ) {
	    throw Exception("Unknown SPI chip selector: %s\n", csname.c_str());
	  }
	  c_spi_chipselector = it->second;
	}
	// MAX31856 config
	if ( spi["MAX31856"] && spi["MAX31856"].IsMap() ) {
	  auto max31856 = spi["MAX31856"];
	  // TC type
	  if ( max31856["tctype"] ) {
	    std::string tctype = max31856["tctype"].as<std::string>();
	    auto it = g_string_to_tctype.find(tctype);
	    if ( it == g_string_to_tctype.end() ) {
	      throw Exception("Unknown TC type: %s\n", tctype.c_str());
	    }
	    c_spi_max31856_tctype = it->second;
	  }// TC type
	  // Noise Filter, AKA 50/60Hz
	  if ( max31856["noisefilter"] ) {
	    std::string nf = max31856["noisefilter"].as<std::string>();
	    auto it = g_string_to_noisefilter.find(nf);
	    if ( it == g_string_to_noisefilter.end() ) {
	      throw Exception("Unknown Noise Filter mode: %s\n", nf.c_str());
	    }
	    c_spi_max31856_noisefilter = it->second;
	  }// Noise Filter
	} // MAX31856 config
	// DirectSelect Chip Selector
	// the PIN configuration
	if ( spi["DirectSelect"] && spi["DirectSelect"].IsMap() ) {
	  YAML::Node ds = spi["DirectSelect"];

	  // we have 3 hardcoded sensors at this level, for now
	  for (int i=0; i<3; ++i) {
	    if ( !ds[i] ) continue;
	    std::string pin = ds[i].as<std::string>();
	    auto it = g_pinconfig.find(pin);
	    if ( it == g_pinconfig.end() )
	      throw Exception("Unknown pin: %s", pin.c_str());
	    c_spi_dschips[i] = pin;
	  }

	  // Now we have to check for dups
	  std::set<std::string> tmp;
	  for ( auto &it: c_spi_dschips ) {
	    auto it2 = tmp.find(it.second);
	    if ( it2 != tmp.end() )
	      throw Exception("Duplicate pin for DirectSelect: %s", it.second.c_str());
	    tmp.insert(it.second);
	  }
	} // PIN config

	// Thermocouples
	if ( spi["thermocouples"] && spi["thermocouples"].IsMap() ) {
	  YAML::Node tc = spi["thermocouples"];

	  // We are going through only the valid ones, the rest are ignored
	  // also, not emptying the list, because that's how unset values default
	  for (auto &it: g_tcnames) {
	    if ( tc[it] ) {
	      int id = tc[it].as<int>();
	      if ( id < 0 || id > 3 )
		throw Exception("Thermocouple id out of range: %i", id);
	      c_thermocouples[it] = id;
	    }
	  }
	  // now verify whether any of them is on the same id
	  std::set<int> tmp;
	  for (auto &it: c_thermocouples) {
	    if ( tmp.find(it.second) != tmp.end() )
	      throw Exception("Duplicate thermocouple id: %i", it.second);
	    tmp.insert(it.second);
	  }
	} // thermocouples
	if ( spi["thermointerval"] && spi["thermointerval"].IsScalar() ) {
	  YAML::Node ti = spi["thermointerval"];
	  c_thermoival = ti.as<uint32_t>();
	if ( c_thermoival > 60 )
	  throw Exception("Thermocouple reading interval is too high: %lu", c_thermoival);
	}
      } // SPI section

      // ZMQ PR socket
      if ( config["prport"] && config["prport"].IsScalar() ) {
	YAML::Node prsock = config["prport"];
	c_zmq_pr_port = prsock.as<uint16_t>();
      }

      // Heating Element's Power
      if ( config["elementpower"] && config["elementpower"].IsScalar() ) {
	YAML::Node hep = config["elementpower"];
	c_hepower = hep.as<uint32_t>();
	if ( c_hepower < 1000 || c_hepower > 10000 )
	  throw Exception("Heating element's power is out of range");
      }

    }
    catch (std::exception &e) {
      throw Exception("Error during parsing config: %s", e.what());
    }
  }

  void Config::checkPinConfig(std::map<std::string, int> &_layout) {
    std::map<int, int> count;

    for ( const auto &it: _layout ) {
      if ( count.find(it.second) == count.end() ) {
	count[it.second] = 0;
      } else {
	count[it.second] += 1;
      }
    }

    for ( const auto &it: count ) {
      if ( it.second > 1 ) throw Exception("Conflict on Pin %i\n", it.first);
    }
  }

  Config &Config::save() {
    YAML::Emitter yout;

    yout << YAML::BeginMap;
    // GPIO config
    yout << YAML::Key << "gpio";
    yout << YAML::Value << YAML::BeginMap;
    yout << YAML::Key << "device" << YAML::Value << c_device;
    yout << YAML::Key << "pins" << YAML::Value << c_pinlayout;
    yout << YAML::EndMap;

    // SPI config
    yout << YAML::Key << "spi";
    yout << YAML::Value << YAML::BeginMap;
    yout << YAML::Key << "device" << YAML::Value << c_spidev;
    yout << YAML::Key << "selector" << YAML::Value << g_spi_cs_to_string[c_spi_chipselector];

    // SPI / MAX31856 config
    yout << YAML::Key << "MAX31856";
    yout << YAML::Value <<
      std::map<std::string, std::string>{
      {"tctype", g_tctype_to_string[c_spi_max31856_tctype]},
	{"noisefilter", g_noisefilter_to_string[c_spi_max31856_noisefilter]}};
    // end SPI / MAX31856

    // SPI / DirectSelect
    yout << YAML::Key << "DirectSelect";
    yout << YAML::Value << c_spi_dschips;

    // Thermocouple layout
    yout << YAML::Key << "thermocouples";
    yout << YAML::Value << c_thermocouples;

    // thermocouple reading interval
    yout << YAML::Key << "thermointerval";
    yout << YAML::Value << c_thermoival;

    yout << YAML::EndMap; // end of SPI

    // ZMQ PR port
    yout << YAML::Key << "prport" << YAML::Value << c_zmq_pr_port;

    // Heating element's power in watts
    yout << YAML::Key << "elementpower" << YAML::Value << c_hepower;

    // End the config
    yout << YAML::EndMap;

    std::ofstream outfile;

    outfile.open(c_cfgfile, std::ios::out | std::ios::trunc);
    outfile << yout.c_str() << std::endl;
    outfile.close();

    return *this;
  }

  const std::string &Config::getGPIODevice() const {
    return c_device;
  }

  Config &Config::getPinConfig(pinlayout_t &_layout) {
    _layout = c_pinlayout;
    return *this;
  }
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 * $Log$
 * Revision 1.3  2002/11/21 15:45:34  gareth
 * gcc 3.2 now issues a warning for use of iostream.h. Removed the .h and prefixed cout with std::.
 *
 * Revision 1.2  2002/11/04 15:00:21  tng
 * C++ Namespace Support.
 *
 * Revision 1.1  2002/05/28 22:40:46  peiyongz
 * DOM3 Save Interface: DOMWriter/DOMWriterFilter
 *
 */

#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <iostream>

XERCES_CPP_NAMESPACE_BEGIN

StdOutFormatTarget::StdOutFormatTarget()
{}

StdOutFormatTarget::~StdOutFormatTarget()
{}

void StdOutFormatTarget::writeChars(const XMLByte* const  toWrite
                                  , const unsigned int    count
                                  , XMLFormatter* const   formatter)
{
        // Surprisingly, Solaris was the only platform on which
        // required the char* cast to print out the string correctly.
        // Without the cast, it was printing the pointer value in hex.
        // Quite annoying, considering every other platform printed
        // the string with the explicit cast to char* below.
	std::cout.write((char *) toWrite, (int) count);

}

XERCES_CPP_NAMESPACE_END

<commit_msg>Got a number of compilation erros for those non-ANSI C++ compliant compiler like xlC v3. Since the previous fix is just for fixing a "warning", I think it doesn't worth to break users who are not ANSI C++ ready yet.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 * $Log$
 * Revision 1.4  2002/11/22 14:25:59  tng
 * Got a number of compilation erros for those non-ANSI C++ compliant compiler like xlC v3.
 * Since the previous fix is just for fixing a "warning", I think it doesn't worth to break users who
 * are not ANSI C++ ready yet.
 *
 * Revision 1.3  2002/11/21 15:45:34  gareth
 * gcc 3.2 now issues a warning for use of iostream.h. Removed the .h and prefixed cout with std::.
 *
 * Revision 1.2  2002/11/04 15:00:21  tng
 * C++ Namespace Support.
 *
 * Revision 1.1  2002/05/28 22:40:46  peiyongz
 * DOM3 Save Interface: DOMWriter/DOMWriterFilter
 *
 */

#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <iostream.h>

XERCES_CPP_NAMESPACE_BEGIN

StdOutFormatTarget::StdOutFormatTarget()
{}

StdOutFormatTarget::~StdOutFormatTarget()
{}

void StdOutFormatTarget::writeChars(const XMLByte* const  toWrite
                                  , const unsigned int    count
                                  , XMLFormatter* const   formatter)
{
        // Surprisingly, Solaris was the only platform on which
        // required the char* cast to print out the string correctly.
        // Without the cast, it was printing the pointer value in hex.
        // Quite annoying, considering every other platform printed
        // the string with the explicit cast to char* below.
    cout.write((char *) toWrite, (int) count);

}

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>#ifndef STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#define STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/kernel_cl.hpp>

namespace stan {
namespace math {
namespace opencl_kernels {
// \cond
static const char* matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix multiplication on the OpenCL device
     *
     * @param[in] A the left matrix in matrix multiplication
     * @param[in] B the right matrix in matrix multiplication
     * @param[out] C the output matrix
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix B
     * @param[in] K Number of cols for matrix A and number of rows for matrix B
     * @param[in] lower_upper_A the triangularity of A (lower, upper or none)
     * @param[in] lower_upper_B the triangularity of B (lower, upper or none)
     */
    __kernel void matrix_multiply(
        const __global double* A, const __global double* B, __global double* C,
        const int M, const int N, const int K, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      // thread index inside the thread_block
      const int thread_block_row = get_local_id(0);
      const int thread_block_col = get_local_id(1);
      // global thread index
      const int i = THREAD_BLOCK_SIZE * get_group_id(0) + thread_block_row;
      const int j = THREAD_BLOCK_SIZE * get_group_id(1) + thread_block_col;

      // local memory
      __local double A_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];
      __local double B_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];

      double acc[WORK_PER_THREAD];
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        acc[w] = 0.0;
      }

      const int num_tiles = (K + THREAD_BLOCK_SIZE - 1) / THREAD_BLOCK_SIZE;

      // This kernel is based on the well known
      // general matrix multiplication kernels that
      // use tiling for shared memory
      // In cases where a matrix is lower triangular
      // its not necessary to multiply the elements
      // over the diagonal, therefore those tiles
      // in the matrix multiply can be skipped.
      // With upper triangular matrices we dont need
      // to multiply the elements under the diagonal,
      // so those tiles can be skipped.
      // The following code determines the start and
      // end tile based on triangularity of the input matrices
      // If no matrices are triangular the starting tile
      // is 0 and the end tile is num_tiles-1 which
      // is then a general matrix multiply
      const int end_tile_A
          = lower_upper_A == LOWER ? (i / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int end_tile_B
          = lower_upper_B == UPPER ? (j / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int start_tile_A
          = lower_upper_A == UPPER ? (i / THREAD_BLOCK_SIZE) : 0;
      const int start_tile_B
          = lower_upper_B == LOWER ? (j / THREAD_BLOCK_SIZE) : 0;
      const int start_tile = max(start_tile_A, start_tile_B);
      const int end_tile = min(end_tile_A, end_tile_B);  // NOLINT

      for (int tile_idx = start_tile; tile_idx <= end_tile; tile_idx++) {
        const int tiled_i = THREAD_BLOCK_SIZE * tile_idx + thread_block_row;
        const int tiled_j = THREAD_BLOCK_SIZE * tile_idx + thread_block_col;
        // each thread copies WORK_PER_THREAD values to the local
        // memory
        for (int w = 0; w < WORK_PER_THREAD; w++) {
          // For the tiles on the diagonal we can ignore the values over
          // the diagonal if the matrix is lower triangular or under
          // the diagonal if the matrix is upper triangular
          A_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                 [thread_block_row]
              = A[(tiled_j + w * THREAD_BLOCK_SIZE_COL) * M + i];
          B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                 [thread_block_row]
              = B[(j + w * THREAD_BLOCK_SIZE_COL) * K + tiled_i];
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        for (int block_idx = 0; block_idx < THREAD_BLOCK_SIZE; block_idx++) {
          for (int w = 0; w < WORK_PER_THREAD; w++) {
            acc[w] += A_local[block_idx][thread_block_row]
                      * B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                               [block_idx];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
      // save the values
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        // each thread saves WORK_PER_THREAD values
        C[(j + w * THREAD_BLOCK_SIZE_COL) * M + i] = acc[w];
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int, int,
                         TriangularViewCL, TriangularViewCL>
    matrix_multiply("matrix_multiply", matrix_multiply_kernel_code,
                    {{"THREAD_BLOCK_SIZE", 32}, {"WORK_PER_THREAD", 8}});

// \cond
static const char* matrix_vector_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix-vector multiplication R=A*B on the OpenCL device
     *
     * @param[in] A matrix in matrix-vector multiplication
     * @param[in] B vector in matrix-vector multiplication
     * @param[out] R the output vector
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix A and number of rows for vector B
     */
    __kernel void matrix_vector_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int M, const int N) {
      const int gid = get_global_id(0);

      double acc = 0;
      for (int i = 0, j = 0; i < N; i++, j += M) {
        acc += A[j + gid] * B[i];
      }
      R[gid] = acc;
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_vector_multiply()
 * \endlink
 */
const global_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int>
    matrix_vector_multiply("matrix_vector_multiply",
                           matrix_vector_multiply_kernel_code);

// \cond
static const char* row_vector_matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Row vector-matrix multiplication R=A*B on the OpenCL device
     *
     * @param[in] A row vector in row vector-matrix multiplication
     * @param[in] B matrix in row vector-matrix multiplication
     * @param[out] R the output vector
     * @param[in] N Number of cols for vector A and number of rows for matrix B
     * @param[in] K Number of cols for matrix B
     */
    __kernel void row_vector_matrix_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int N, const int K) {
      const int lid = get_local_id(0);
      const int gid = get_global_id(0);
      const int wgid = get_group_id(0);

      double acc = 0;
      for (int i = lid; i < N; i += 64) {
        acc += A[i] * B[i + wgid * N];
      }
      __local double res_loc[64];
      res_loc[lid] = acc;
      barrier(CLK_LOCAL_MEM_FENCE);
      if (lid < 16) {
        res_loc[lid]
            += res_loc[lid + 16] + res_loc[lid + 32] + res_loc[lid + 48];
      }
      barrier(CLK_LOCAL_MEM_FENCE);
      if (lid < 4) {
        res_loc[lid] += res_loc[lid + 4] + res_loc[lid + 8] + res_loc[lid + 12];
      }
      barrier(CLK_LOCAL_MEM_FENCE);
      if (lid == 0) {
        acc = res_loc[lid] + res_loc[lid + 1] + res_loc[lid + 2]
              + res_loc[lid + 3];
        R[wgid] = acc;
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp row_vector_matrix_multiply()
 * \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int>
    row_vector_matrix_multiply("row_vector_matrix_multiply",
                           row_vector_matrix_multiply_kernel_code);

}  // namespace opencl_kernels
}  // namespace math
}  // namespace stan
#endif
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 5.0.0-3~16.04.1 (tags/RELEASE_500/final)<commit_after>#ifndef STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#define STAN_MATH_OPENCL_KERNELS_MATRIX_MULTIPLY_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/kernel_cl.hpp>

namespace stan {
namespace math {
namespace opencl_kernels {
// \cond
static const char* matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix multiplication on the OpenCL device
     *
     * @param[in] A the left matrix in matrix multiplication
     * @param[in] B the right matrix in matrix multiplication
     * @param[out] C the output matrix
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix B
     * @param[in] K Number of cols for matrix A and number of rows for matrix B
     * @param[in] lower_upper_A the triangularity of A (lower, upper or none)
     * @param[in] lower_upper_B the triangularity of B (lower, upper or none)
     */
    __kernel void matrix_multiply(
        const __global double* A, const __global double* B, __global double* C,
        const int M, const int N, const int K, unsigned int lower_upper_A,
        unsigned int lower_upper_B) {
      // thread index inside the thread_block
      const int thread_block_row = get_local_id(0);
      const int thread_block_col = get_local_id(1);
      // global thread index
      const int i = THREAD_BLOCK_SIZE * get_group_id(0) + thread_block_row;
      const int j = THREAD_BLOCK_SIZE * get_group_id(1) + thread_block_col;

      // local memory
      __local double A_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];
      __local double B_local[THREAD_BLOCK_SIZE][THREAD_BLOCK_SIZE];

      double acc[WORK_PER_THREAD];
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        acc[w] = 0.0;
      }

      const int num_tiles = (K + THREAD_BLOCK_SIZE - 1) / THREAD_BLOCK_SIZE;

      // This kernel is based on the well known
      // general matrix multiplication kernels that
      // use tiling for shared memory
      // In cases where a matrix is lower triangular
      // its not necessary to multiply the elements
      // over the diagonal, therefore those tiles
      // in the matrix multiply can be skipped.
      // With upper triangular matrices we dont need
      // to multiply the elements under the diagonal,
      // so those tiles can be skipped.
      // The following code determines the start and
      // end tile based on triangularity of the input matrices
      // If no matrices are triangular the starting tile
      // is 0 and the end tile is num_tiles-1 which
      // is then a general matrix multiply
      const int end_tile_A
          = lower_upper_A == LOWER ? (i / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int end_tile_B
          = lower_upper_B == UPPER ? (j / THREAD_BLOCK_SIZE) : (num_tiles - 1);
      const int start_tile_A
          = lower_upper_A == UPPER ? (i / THREAD_BLOCK_SIZE) : 0;
      const int start_tile_B
          = lower_upper_B == LOWER ? (j / THREAD_BLOCK_SIZE) : 0;
      const int start_tile = max(start_tile_A, start_tile_B);
      const int end_tile = min(end_tile_A, end_tile_B);  // NOLINT

      for (int tile_idx = start_tile; tile_idx <= end_tile; tile_idx++) {
        const int tiled_i = THREAD_BLOCK_SIZE * tile_idx + thread_block_row;
        const int tiled_j = THREAD_BLOCK_SIZE * tile_idx + thread_block_col;
        // each thread copies WORK_PER_THREAD values to the local
        // memory
        for (int w = 0; w < WORK_PER_THREAD; w++) {
          // For the tiles on the diagonal we can ignore the values over
          // the diagonal if the matrix is lower triangular or under
          // the diagonal if the matrix is upper triangular
          A_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                 [thread_block_row]
              = A[(tiled_j + w * THREAD_BLOCK_SIZE_COL) * M + i];
          B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                 [thread_block_row]
              = B[(j + w * THREAD_BLOCK_SIZE_COL) * K + tiled_i];
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        for (int block_idx = 0; block_idx < THREAD_BLOCK_SIZE; block_idx++) {
          for (int w = 0; w < WORK_PER_THREAD; w++) {
            acc[w] += A_local[block_idx][thread_block_row]
                      * B_local[thread_block_col + w * THREAD_BLOCK_SIZE_COL]
                               [block_idx];
          }
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
      // save the values
      for (int w = 0; w < WORK_PER_THREAD; w++) {
        // each thread saves WORK_PER_THREAD values
        C[(j + w * THREAD_BLOCK_SIZE_COL) * M + i] = acc[w];
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int, int,
                         TriangularViewCL, TriangularViewCL>
    matrix_multiply("matrix_multiply", matrix_multiply_kernel_code,
                    {{"THREAD_BLOCK_SIZE", 32}, {"WORK_PER_THREAD", 8}});

// \cond
static const char* matrix_vector_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Matrix-vector multiplication R=A*B on the OpenCL device
     *
     * @param[in] A matrix in matrix-vector multiplication
     * @param[in] B vector in matrix-vector multiplication
     * @param[out] R the output vector
     * @param[in] M Number of rows for matrix A
     * @param[in] N Number of cols for matrix A and number of rows for vector B
     */
    __kernel void matrix_vector_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int M, const int N) {
      const int gid = get_global_id(0);

      double acc = 0;
      for (int i = 0, j = 0; i < N; i++, j += M) {
        acc += A[j + gid] * B[i];
      }
      R[gid] = acc;
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp matrix_vector_multiply()
 * \endlink
 */
const global_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int>
    matrix_vector_multiply("matrix_vector_multiply",
                           matrix_vector_multiply_kernel_code);

// \cond
static const char* row_vector_matrix_multiply_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Row vector-matrix multiplication R=A*B on the OpenCL device
     *
     * @param[in] A row vector in row vector-matrix multiplication
     * @param[in] B matrix in row vector-matrix multiplication
     * @param[out] R the output vector
     * @param[in] N Number of cols for vector A and number of rows for matrix B
     * @param[in] K Number of cols for matrix B
     */
    __kernel void row_vector_matrix_multiply(
        const __global double* A, const __global double* B, __global double* R,
        const int N, const int K) {
      const int lid = get_local_id(0);
      const int gid = get_global_id(0);
      const int wgid = get_group_id(0);

      double acc = 0;
      for (int i = lid; i < N; i += 64) {
        acc += A[i] * B[i + wgid * N];
      }
      __local double res_loc[64];
      res_loc[lid] = acc;
      barrier(CLK_LOCAL_MEM_FENCE);
      if (lid < 16) {
        res_loc[lid]
            += res_loc[lid + 16] + res_loc[lid + 32] + res_loc[lid + 48];
      }
      barrier(CLK_LOCAL_MEM_FENCE);
      if (lid < 4) {
        res_loc[lid] += res_loc[lid + 4] + res_loc[lid + 8] + res_loc[lid + 12];
      }
      barrier(CLK_LOCAL_MEM_FENCE);
      if (lid == 0) {
        acc = res_loc[lid] + res_loc[lid + 1] + res_loc[lid + 2]
              + res_loc[lid + 3];
        R[wgid] = acc;
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/matrix_multiply.hpp
 * row_vector_matrix_multiply() \endlink
 */
const local_range_kernel<cl::Buffer, cl::Buffer, cl::Buffer, int, int>
    row_vector_matrix_multiply("row_vector_matrix_multiply",
                               row_vector_matrix_multiply_kernel_code);

}  // namespace opencl_kernels
}  // namespace math
}  // namespace stan
#endif
#endif
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library 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 2 of the License, or (at your option) any later version.
//
//  This library 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 for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Player.h"

#include "../base/TestSuite.h"
#include "../base/Exception.h"
#include "../base/Logger.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>

using namespace avg;
using namespace std;

class PlayerTest: public Test {
public:
    PlayerTest()
        : Test("PlayerTest", 2)
    {
    }

    void runTests()
    {
        Player player;
        char * pszDir = getenv("srcdir");
        string sFName = string(pszDir)+ "/../test/empty.avg";
        player.loadFile(sFName);
    }
};

class PlayerTestSuite: public TestSuite {
public:
    PlayerTestSuite()
        : TestSuite("PlayerTestSuite")
    {
        addTest(TestPtr(new PlayerTest));
    }
};

int main(int nargs, char** args)
{
    PlayerTestSuite Suite;
    Suite.runTests();
    bool bOK = Suite.isOk();

    if (bOK) {
        return 0;
    } else {
        return 1;
    }
}

<commit_msg>Fixed testplayer if $srcdir is undefined.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library 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 2 of the License, or (at your option) any later version.
//
//  This library 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 for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Player.h"

#include "../base/TestSuite.h"
#include "../base/Exception.h"
#include "../base/Logger.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>

using namespace avg;
using namespace std;

class PlayerTest: public Test {
public:
    PlayerTest()
        : Test("PlayerTest", 2)
    {
    }

    void runTests()
    {
        Player player;
        char * pszDir = getenv("srcdir");
        string sFName;
        if (pszDir) {
            sFName = string(pszDir)+ "/../test/empty.avg";
        } else {
            sFName = "../test/empty.avg";
        }
        player.loadFile(sFName);
    }
};

class PlayerTestSuite: public TestSuite {
public:
    PlayerTestSuite()
        : TestSuite("PlayerTestSuite")
    {
        addTest(TestPtr(new PlayerTest));
    }
};

int main(int nargs, char** args)
{
    PlayerTestSuite Suite;
    Suite.runTests();
    bool bOK = Suite.isOk();

    if (bOK) {
        return 0;
    } else {
        return 1;
    }
}

<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef PCL_SURFACE_IMPL_POISSON_H_
#define PCL_SURFACE_IMPL_POISSON_H_

#include "pcl/surface/poisson.h"
#include <pcl/common/common.h>
#include <pcl/common/vector_average.h>
#include <pcl/Vertices.h>

#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include "pcl/surface/poisson/octree.h"
#include "pcl/surface/poisson/sparse_matrix.h"
#include "pcl/surface/poisson/function_data.h"
#include "pcl/surface/poisson/ppolynomial.h"
#include "pcl/surface/poisson/multi_grid_octree_data.h"

#define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12

#include <stdarg.h>
#include <string>

using namespace pcl::surface::poisson;

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::surface::Poisson<PointNT>::Poisson ()
  : no_reset_samples_(false),
    no_clip_tree_(false),
    confidence_(false),
    manifold_(false),
    depth_(10),
    solver_divide_(8),
    iso_divide_(8),
    refine_(3),
    kernel_depth_(8),
    degree_ (2),
    samples_per_node_(1.0),
    scale_(1.25)
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::surface::Poisson<PointNT>::~Poisson ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> template <int Degree> void
pcl::surface::Poisson<PointNT>::execute (CoredMeshData &mesh,
                                         Point3D<float> &center)
{
  float scale = 1;
  //////////////////////////////////
  // Fix courtesy of David Gallup //
  // TreeNodeData::UseIndex = 1;  //
  //////////////////////////////////
  Octree<Degree> tree;
  PPolynomial<Degree> ReconstructionFunction=PPolynomial<Degree>::GaussianApproximation();

  center.coords[0]=center.coords[1]=center.coords[2]=0;

  TreeOctNode::SetAllocator(MEMORY_ALLOCATOR_BLOCK_SIZE);

  int kernel_depth=depth_-2;
  if(kernel_depth_){kernel_depth=kernel_depth_;}

  tree.setFunctionData(ReconstructionFunction,depth_,0,float(1.0)/(1<<depth_));
  if (kernel_depth > depth_)
  {
    PCL_ERROR ("KernelDepth can't be greater than Depth: %d <= %d\n",kernel_depth,depth_);
    return;
  }

  tree.setTree (depth_, kernel_depth, float(samples_per_node_), scale_, center, scale, !no_reset_samples_, confidence_, input_);

  if(!no_clip_tree_)
    tree.ClipTree();

  tree.finalize1(refine_);

  tree.SetLaplacianWeights();

  tree.finalize2(refine_);

  tree.LaplacianMatrixIteration(solver_divide_);

  float isoValue=tree.GetIsoValue();

  if (iso_divide_)
    tree.GetMCIsoTriangles (isoValue, iso_divide_, &mesh, 0, 1, manifold_);
  else
    tree.GetMCIsoTriangles (isoValue, &mesh, 0, 1, manifold_);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::surface::Poisson<PointNT>::performReconstruction (PolygonMesh &output)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch(degree_)
  {
    case 1:
      execute<1> (mesh, center);
      break;
    case 2:
      execute<2> (mesh, center);
      break;
    case 3:
      execute<3> (mesh, center);
      break;
    case 4:
      execute<4> (mesh, center);
      break;
    case 5:
      execute<5> (mesh, center);
      break;
    default:
      PCL_ERROR (stderr,"Degree %d not supported\n", degree_);
  }

  /// Write output PolygonMesh
  float scale = 1;
   // write vertices
   pcl::PointCloud < pcl::PointXYZ > cloud;
   cloud.points.resize (int (mesh.outOfCorePointCount()+mesh.inCorePoints.size ()) );
   Point3D<float> p;
   for (int i = 0; i < int(mesh.inCorePoints.size()); i++)
   {
     p = mesh.inCorePoints[i];
     cloud.points[i].x = p.coords[0]*scale+center.coords[0];
     cloud.points[i].y = p.coords[1]*scale+center.coords[1];
     cloud.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   for (int i = int(mesh.inCorePoints.size()); i < int (mesh.outOfCorePointCount() + mesh.inCorePoints.size ()); i++)
   {
     mesh.nextOutOfCorePoint(p);
     cloud.points[i].x = p.coords[0]*scale+center.coords[0];
     cloud.points[i].y = p.coords[1]*scale+center.coords[1];
     cloud.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   pcl::toROSMsg (cloud, output.cloud);
   output.polygons.resize (mesh.triangleCount ());

   // write faces
   TriangleIndex tIndex;
   int inCoreFlag;
   for (int i = 0; i < mesh.triangleCount(); i++)
   {
     // create and fill a struct that the ply code can handle
     pcl::Vertices v;
     v.vertices.resize (3);

     mesh.nextTriangle(tIndex,inCoreFlag);
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0])) { tIndex.idx[0] += int(mesh.inCorePoints.size()); }
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1])) { tIndex.idx[1] += int(mesh.inCorePoints.size()); }
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2])) { tIndex.idx[2] += int(mesh.inCorePoints.size()); }
     for (int j = 0; j < 3; j++) {v.vertices[j] = tIndex.idx[j];}
     output.polygons[i] = v;
   }  // for, write faces
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::surface::Poisson<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points,
                                                       std::vector<pcl::Vertices> &polygons)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch(degree_)
  {
    case 1:
      execute<1> (mesh, center);
      break;
    case 2:
      execute<2> (mesh, center);
      break;
    case 3:
      execute<3> (mesh, center);
      break;
    case 4:
      execute<4> (mesh, center);
      break;
    case 5:
      execute<5> (mesh, center);
      break;
    default:
      PCL_ERROR (stderr,"Degree %d not supported\n", degree_);
  }

  /// Write output PolygonMesh
  float scale = 1;
   // write vertices
   points.points.resize (int (mesh.outOfCorePointCount()+mesh.inCorePoints.size ()) );
   Point3D<float> p;
   for (int i = 0; i < int(mesh.inCorePoints.size()); i++)
   {
     p = mesh.inCorePoints[i];
     points.points[i].x = p.coords[0]*scale+center.coords[0];
     points.points[i].y = p.coords[1]*scale+center.coords[1];
     points.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   for (int i = int(mesh.inCorePoints.size()); i < int (mesh.outOfCorePointCount() + mesh.inCorePoints.size ()); i++)
   {
     mesh.nextOutOfCorePoint(p);
     points.points[i].x = p.coords[0]*scale+center.coords[0];
     points.points[i].y = p.coords[1]*scale+center.coords[1];
     points.points[i].z = p.coords[2]*scale+center.coords[2];
   }

   polygons.resize (mesh.triangleCount ());

   // write faces
   TriangleIndex tIndex;
   int inCoreFlag;
   for (int i = 0; i < mesh.triangleCount(); i++)
   {
     // create and fill a struct that the ply code can handle
     pcl::Vertices v;
     v.vertices.resize (3);

     mesh.nextTriangle(tIndex,inCoreFlag);
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0])) { tIndex.idx[0] += int(mesh.inCorePoints.size()); }
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1])) { tIndex.idx[1] += int(mesh.inCorePoints.size()); }
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2])) { tIndex.idx[2] += int(mesh.inCorePoints.size()); }
     for (int j = 0; j < 3; j++) {v.vertices[j] = tIndex.idx[j];}
     polygons[i] = v;
   }  // for, write faces

}

#define PCL_INSTANTIATE_Poisson(T) template class PCL_EXPORTS pcl::surface::Poisson<T>;

#endif    // PCL_SURFACE_IMPL_POISSON_H_

<commit_msg>poisson beautification<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  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.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef PCL_SURFACE_IMPL_POISSON_H_
#define PCL_SURFACE_IMPL_POISSON_H_

#include "pcl/surface/poisson.h"
#include <pcl/common/common.h>
#include <pcl/common/vector_average.h>
#include <pcl/Vertices.h>

#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include "pcl/surface/poisson/octree.h"
#include "pcl/surface/poisson/sparse_matrix.h"
#include "pcl/surface/poisson/function_data.h"
#include "pcl/surface/poisson/ppolynomial.h"
#include "pcl/surface/poisson/multi_grid_octree_data.h"

#define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12

#include <stdarg.h>
#include <string>

using namespace pcl::surface::poisson;

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::surface::Poisson<PointNT>::Poisson ()
  : no_reset_samples_ (false),
    no_clip_tree_ (false),
    confidence_ (false),
    manifold_ (false),
    depth_ (10),
    solver_divide_ (8),
    iso_divide_ (8),
    refine_ (3),
    kernel_depth_ (8),
    degree_ (2),
    samples_per_node_ (1.0),
    scale_ (1.25)
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::surface::Poisson<PointNT>::~Poisson ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> template <int Degree> void
pcl::surface::Poisson<PointNT>::execute (CoredMeshData &mesh,
                                         Point3D<float> &center)
{
  float scale = 1;
  //////////////////////////////////
  // Fix courtesy of David Gallup //
  // TreeNodeData::UseIndex = 1;  //
  //////////////////////////////////
  Octree<Degree> tree;
  PPolynomial<Degree> ReconstructionFunction = PPolynomial<Degree>::GaussianApproximation ();

  center.coords[0] = center.coords[1] = center.coords[2] = 0;

  TreeOctNode::SetAllocator(MEMORY_ALLOCATOR_BLOCK_SIZE);

  int kernel_depth=depth_-2;
  if (kernel_depth_)
    kernel_depth=kernel_depth_;

  tree.setFunctionData (ReconstructionFunction,depth_, 0, float (1.0) / (1<<depth_));
  if (kernel_depth > depth_)
  {
    PCL_ERROR ("KernelDepth can't be greater than Depth: %d <= %d\n", kernel_depth, depth_);
    return;
  }

  tree.setTree (depth_, kernel_depth, float (samples_per_node_), scale_, center, scale, !no_reset_samples_, confidence_, input_);

  if(!no_clip_tree_)
    tree.ClipTree ();

  tree.finalize1 (refine_);
  tree.SetLaplacianWeights ();
  tree.finalize2 (refine_);

  tree.LaplacianMatrixIteration (solver_divide_);

  float isoValue=tree.GetIsoValue ();

  if (iso_divide_)
    tree.GetMCIsoTriangles (isoValue, iso_divide_, &mesh, 0, 1, manifold_);
  else
    tree.GetMCIsoTriangles (isoValue, &mesh, 0, 1, manifold_);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::surface::Poisson<PointNT>::performReconstruction (PolygonMesh &output)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  printf ("Before execution\n");
  switch (degree_)
  {
    case 1:
      execute<1> (mesh, center);
      break;
    case 2:
      execute<2> (mesh, center);
      break;
    case 3:
      execute<3> (mesh, center);
      break;
    case 4:
      execute<4> (mesh, center);
      break;
    case 5:
      execute<5> (mesh, center);
      break;
    default:
      PCL_ERROR (stderr,"Degree %d not supported\n", degree_);
  }

  printf ("Done execution \n");

  /// Write output PolygonMesh
  float scale = 1;
   // write vertices
   pcl::PointCloud < pcl::PointXYZ > cloud;
   cloud.points.resize (int (mesh.outOfCorePointCount()+mesh.inCorePoints.size ()));
   Point3D<float> p;
   for (int i = 0; i < int (mesh.inCorePoints.size()); i++)
   {
     p = mesh.inCorePoints[i];
     cloud.points[i].x = p.coords[0]*scale+center.coords[0];
     cloud.points[i].y = p.coords[1]*scale+center.coords[1];
     cloud.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   for (int i = int (mesh.inCorePoints.size ()); i < int (mesh.outOfCorePointCount () + mesh.inCorePoints.size ()); i++)
   {
     mesh.nextOutOfCorePoint (p);
     cloud.points[i].x = p.coords[0]*scale+center.coords[0];
     cloud.points[i].y = p.coords[1]*scale+center.coords[1];
     cloud.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   pcl::toROSMsg (cloud, output.cloud);
   output.polygons.resize (mesh.triangleCount ());

   // Write faces
   TriangleIndex tIndex;
   int inCoreFlag;
   for (int i = 0; i < mesh.triangleCount(); i++)
   {
     // Create and fill a struct that the ply code can handle
     pcl::Vertices v;
     v.vertices.resize (3);

     mesh.nextTriangle(tIndex,inCoreFlag);
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0]))
       tIndex.idx[0] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1]))
       tIndex.idx[1] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2]))
       tIndex.idx[2] += int(mesh.inCorePoints.size());

     for (int j = 0; j < 3; j++)
       v.vertices[j] = tIndex.idx[j];
     output.polygons[i] = v;
   }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::surface::Poisson<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points,
                                                       std::vector<pcl::Vertices> &polygons)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch(degree_)
  {
    case 1:
      execute<1> (mesh, center);
      break;
    case 2:
      execute<2> (mesh, center);
      break;
    case 3:
      execute<3> (mesh, center);
      break;
    case 4:
      execute<4> (mesh, center);
      break;
    case 5:
      execute<5> (mesh, center);
      break;
    default:
      PCL_ERROR (stderr,"Degree %d not supported\n", degree_);
  }

  /// Write output PolygonMesh
  float scale = 1;
   // write vertices
   points.points.resize (int (mesh.outOfCorePointCount ()+mesh.inCorePoints.size ()));
   Point3D<float> p;
   for (int i = 0; i < int(mesh.inCorePoints.size()); i++)
   {
     p = mesh.inCorePoints[i];
     points.points[i].x = p.coords[0]*scale+center.coords[0];
     points.points[i].y = p.coords[1]*scale+center.coords[1];
     points.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   for (int i = int(mesh.inCorePoints.size()); i < int (mesh.outOfCorePointCount() + mesh.inCorePoints.size ()); i++)
   {
     mesh.nextOutOfCorePoint(p);
     points.points[i].x = p.coords[0]*scale+center.coords[0];
     points.points[i].y = p.coords[1]*scale+center.coords[1];
     points.points[i].z = p.coords[2]*scale+center.coords[2];
   }

   polygons.resize (mesh.triangleCount ());

   // write faces
   TriangleIndex tIndex;
   int inCoreFlag;
   for (int i = 0; i < mesh.triangleCount (); i++)
   {
     // create and fill a struct that the ply code can handle
     pcl::Vertices v;
     v.vertices.resize (3);

     mesh.nextTriangle(tIndex,inCoreFlag);
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0]))
       tIndex.idx[0] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1]))
       tIndex.idx[1] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2]))
       tIndex.idx[2] += int(mesh.inCorePoints.size());
     for (int j = 0; j < 3; j++)
       v.vertices[j] = tIndex.idx[j];
     polygons[i] = v;
   }
}

#define PCL_INSTANTIATE_Poisson(T) template class PCL_EXPORTS pcl::surface::Poisson<T>;

#endif    // PCL_SURFACE_IMPL_POISSON_H_

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ChildrenManager.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:40:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#ifndef _SVX_ACCESSIBILITY_CHILDREN_MANAGER_HXX
#include <svx/ChildrenManager.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_CHILDREN_MANAGER_IMPL_HXX
#include "ChildrenManagerImpl.hxx"
#endif
#ifndef _SVX_ACCESSIBILITY_ACCESSIBLE_SHAPE_HXX
#include <svx/AccessibleShape.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::accessibility;
using ::com::sun::star::uno::Reference;

namespace accessibility {

//=====  AccessibleChildrenManager  ===========================================

ChildrenManager::ChildrenManager (
    const Reference<XAccessible>& rxParent,
    const Reference<drawing::XShapes>& rxShapeList,
    const AccessibleShapeTreeInfo& rShapeTreeInfo,
    AccessibleContextBase& rContext)
    : mpImpl (NULL)
{
    mpImpl = new ChildrenManagerImpl (rxParent, rxShapeList, rShapeTreeInfo, rContext);
    if (mpImpl != NULL)
        mpImpl->Init ();
    else
        throw uno::RuntimeException(
            ::rtl::OUString::createFromAscii(
                "ChildrenManager::ChildrenManager can't create implementation object"), NULL);
}

ChildrenManager::~ChildrenManager (void)
{
    if (mpImpl != NULL)
        mpImpl->dispose();

    // emtpy
    OSL_TRACE ("~ChildrenManager");
}

long ChildrenManager::GetChildCount (void) const throw ()
{
    OSL_ASSERT (mpImpl != NULL);
    return mpImpl->GetChildCount();
}

Reference<XAccessible> ChildrenManager::GetChild (long nIndex)
    throw (::com::sun::star::uno::RuntimeException)
{
    OSL_ASSERT (mpImpl != NULL);
    return mpImpl->GetChild (nIndex);
}

void ChildrenManager::Update (bool bCreateNewObjectsOnDemand)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->Update (bCreateNewObjectsOnDemand);
}

void ChildrenManager::SetShapeList (const ::com::sun::star::uno::Reference<
    ::com::sun::star::drawing::XShapes>& xShapeList)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->SetShapeList (xShapeList);
}

void ChildrenManager::AddAccessibleShape (std::auto_ptr<AccessibleShape> pShape)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->AddAccessibleShape (pShape);
}

void ChildrenManager::ClearAccessibleShapeList (void)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->ClearAccessibleShapeList ();
}

void ChildrenManager::SetInfo (AccessibleShapeTreeInfo& rShapeTreeInfo)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->SetInfo (rShapeTreeInfo);
}

void ChildrenManager::UpdateSelection (void)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->UpdateSelection ();
}

bool ChildrenManager::HasFocus (void)
{
    OSL_ASSERT (mpImpl != NULL);
    return mpImpl->HasFocus ();
}

void ChildrenManager::RemoveFocus (void)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->RemoveFocus ();
}

//=====  IAccessibleViewForwarderListener  ====================================
void ChildrenManager::ViewForwarderChanged (ChangeType aChangeType,
        const IAccessibleViewForwarder* pViewForwarder)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->ViewForwarderChanged (aChangeType, pViewForwarder);
}

} // end of namespace accessibility
<commit_msg>INTEGRATION: CWS atkbridge8_SRC680 (1.15.148); FILE MERGED 2007/10/12 11:38:50 obr 1.15.148.1: #b6581554# fixed incorrect exception specification for GetChild<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ChildrenManager.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-01 13:01:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#ifndef _SVX_ACCESSIBILITY_CHILDREN_MANAGER_HXX
#include <svx/ChildrenManager.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_CHILDREN_MANAGER_IMPL_HXX
#include "ChildrenManagerImpl.hxx"
#endif
#ifndef _SVX_ACCESSIBILITY_ACCESSIBLE_SHAPE_HXX
#include <svx/AccessibleShape.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::accessibility;
using ::com::sun::star::uno::Reference;

namespace accessibility {

//=====  AccessibleChildrenManager  ===========================================

ChildrenManager::ChildrenManager (
    const Reference<XAccessible>& rxParent,
    const Reference<drawing::XShapes>& rxShapeList,
    const AccessibleShapeTreeInfo& rShapeTreeInfo,
    AccessibleContextBase& rContext)
    : mpImpl (NULL)
{
    mpImpl = new ChildrenManagerImpl (rxParent, rxShapeList, rShapeTreeInfo, rContext);
    if (mpImpl != NULL)
        mpImpl->Init ();
    else
        throw uno::RuntimeException(
            ::rtl::OUString::createFromAscii(
                "ChildrenManager::ChildrenManager can't create implementation object"), NULL);
}

ChildrenManager::~ChildrenManager (void)
{
    if (mpImpl != NULL)
        mpImpl->dispose();

    // emtpy
    OSL_TRACE ("~ChildrenManager");
}

long ChildrenManager::GetChildCount (void) const throw ()
{
    OSL_ASSERT (mpImpl != NULL);
    return mpImpl->GetChildCount();
}

Reference<XAccessible> ChildrenManager::GetChild (long nIndex)
    throw (::com::sun::star::uno::RuntimeException,
           ::com::sun::star::lang::IndexOutOfBoundsException)
{
    OSL_ASSERT (mpImpl != NULL);
    return mpImpl->GetChild (nIndex);
}

void ChildrenManager::Update (bool bCreateNewObjectsOnDemand)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->Update (bCreateNewObjectsOnDemand);
}

void ChildrenManager::SetShapeList (const ::com::sun::star::uno::Reference<
    ::com::sun::star::drawing::XShapes>& xShapeList)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->SetShapeList (xShapeList);
}

void ChildrenManager::AddAccessibleShape (std::auto_ptr<AccessibleShape> pShape)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->AddAccessibleShape (pShape);
}

void ChildrenManager::ClearAccessibleShapeList (void)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->ClearAccessibleShapeList ();
}

void ChildrenManager::SetInfo (AccessibleShapeTreeInfo& rShapeTreeInfo)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->SetInfo (rShapeTreeInfo);
}

void ChildrenManager::UpdateSelection (void)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->UpdateSelection ();
}

bool ChildrenManager::HasFocus (void)
{
    OSL_ASSERT (mpImpl != NULL);
    return mpImpl->HasFocus ();
}

void ChildrenManager::RemoveFocus (void)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->RemoveFocus ();
}

//=====  IAccessibleViewForwarderListener  ====================================
void ChildrenManager::ViewForwarderChanged (ChangeType aChangeType,
        const IAccessibleViewForwarder* pViewForwarder)
{
    OSL_ASSERT (mpImpl != NULL);
    mpImpl->ViewForwarderChanged (aChangeType, pViewForwarder);
}

} // end of namespace accessibility
<|endoftext|>