<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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.
 */
#if !MBED_TICKLESS
#error [NOT_SUPPORTED] Tickless mode not supported for this target.
#endif

#if !DEVICE_LOWPOWERTIMER
#error [NOT_SUPPORTED] Current SysTimer implementation requires lp ticker support.
#endif

#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "ticker_api.h"

extern "C" {
#include "rtx_lib.h"
}
#include "rtos/TARGET_CORTEX/SysTimer.h"

#define TEST_TICKS 42UL
#define DELAY_DELTA_US 2500ULL

using namespace utest::v1;

const us_timestamp_t DELAY_US = 1000000ULL * TEST_TICKS / OS_TICK_FREQ;

// Override the handler() -- the SysTick interrupt must not be set as pending by the test code.
class SysTimerTest: public rtos::internal::SysTimer {
private:
    Semaphore _sem;
    virtual void handler()
    {
        core_util_critical_section_enter();
        _increment_tick();
        core_util_critical_section_exit();
        _sem.release();
    }

public:
    SysTimerTest() :
            SysTimer(), _sem(0, 1)
    {
    }

    SysTimerTest(const ticker_data_t *data) :
            SysTimer(data), _sem(0, 1)
    {
    }

    virtual ~SysTimerTest()
    {
    }

    int32_t sem_wait(uint32_t millisec)
    {
        return _sem.wait(millisec);
    }
};

timestamp_t mock_ticker_timestamp;

void mock_ticker_init()
{
}

uint32_t mock_ticker_read()
{
    return mock_ticker_timestamp;
}

void mock_ticker_disable_interrupt()
{
}

void mock_ticker_clear_interrupt()
{
}

void mock_ticker_set_interrupt(timestamp_t timestamp)
{
}

void mock_ticker_fire_interrupt()
{
}

const ticker_info_t *mock_ticker_get_info()
{
    static const ticker_info_t mock_ticker_info = {
        .frequency = 1000000,
        .bits = 32
    };
    return &mock_ticker_info;
}

ticker_interface_t mock_ticker_interface = {
    .init = mock_ticker_init,
    .read = mock_ticker_read,
    .disable_interrupt = mock_ticker_disable_interrupt,
    .clear_interrupt = mock_ticker_clear_interrupt,
    .set_interrupt = mock_ticker_set_interrupt,
    .fire_interrupt = mock_ticker_fire_interrupt,
    .get_info = mock_ticker_get_info,
};

ticker_event_queue_t mock_ticker_event_queue;

const ticker_data_t mock_ticker_data = {
    .interface = &mock_ticker_interface,
    .queue = &mock_ticker_event_queue
};

void mock_ticker_reset()
{
    mock_ticker_timestamp = 0;
    memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue);
}

/** Test tick count is zero upon creation
 *
 * Given a SysTimer
 * When the timer is created
 * Then tick count is zero
 */
void test_created_with_zero_tick_count(void)
{
    SysTimerTest st;
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
}

/** Test tick count is updated correctly
 *
 * Given a SysTimer
 * When the @a suspend and @a resume methods are called immediately after creation
 * Then the tick count is not updated
 * When @a suspend and @a resume methods are called again after a delay
 * Then the tick count is updated
 *     and the number of ticks incremented is equal TEST_TICKS - 1
 * When @a suspend and @a resume methods are called again without a delay
 * Then the tick count is not updated
 */
void test_update_tick(void)
{
    mock_ticker_reset();
    SysTimerTest st(&mock_ticker_data);
    st.suspend(TEST_TICKS * 2);
    TEST_ASSERT_EQUAL_UINT32(0, st.resume());
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());

    st.suspend(TEST_TICKS * 2);
    mock_ticker_timestamp = DELAY_US;
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume());
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());

    st.suspend(TEST_TICKS * 2);
    TEST_ASSERT_EQUAL_UINT32(0, st.resume());
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
}

/** Test get_time returns correct time
 *
 * Given a SysTimer
 * When @a get_time method is called before and after a delay
 * Then time difference is equal the delay
 */
void test_get_time(void)
{
    mock_ticker_reset();
    SysTimerTest st(&mock_ticker_data);
    us_timestamp_t t1 = st.get_time();

    mock_ticker_timestamp = DELAY_US;
    us_timestamp_t t2 = st.get_time();
    TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1);
}

/** Test cancel_tick
 *
 * Given a SysTimer with a scheduled tick
 * When @a cancel_tick is called before the given number of ticks elapse
 * Then the handler is never called
 *     and the tick count is not incremented
 */
void test_cancel_tick(void)
{
    SysTimerTest st;
    st.cancel_tick();
    st.schedule_tick(TEST_TICKS);

    st.cancel_tick();
    int32_t sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
    TEST_ASSERT_EQUAL_INT32(0, sem_slots);
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
}

/** Test schedule zero
 *
 * Given a SysTimer
 * When a tick is scheduled with delta = 0 ticks
 * Then the handler is called instantly
 */
void test_schedule_zero(void)
{
    SysTimerTest st;

    st.schedule_tick(0UL);
    int32_t sem_slots = st.sem_wait(0UL);
    TEST_ASSERT_EQUAL_INT32(1, sem_slots);
}

/** Test handler called once
 *
 * Given a SysTimer with a tick scheduled with delta = TEST_TICKS
 * When the handler is called
 * Then the tick count is incremented by 1
 *     and elapsed time is equal 1000000ULL * TEST_TICKS / OS_TICK_FREQ;
 * When more time elapses
 * Then the handler is not called again
 */
void test_handler_called_once(void)
{
    SysTimerTest st;
    st.schedule_tick(TEST_TICKS);
    us_timestamp_t t1 = st.get_time();
    int32_t sem_slots = st.sem_wait(0);
    TEST_ASSERT_EQUAL_INT32(0, sem_slots);

    sem_slots = st.sem_wait(osWaitForever);
    us_timestamp_t t2 = st.get_time();
    TEST_ASSERT_EQUAL_INT32(1, sem_slots);
    TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);

    sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
    TEST_ASSERT_EQUAL_INT32(0, sem_slots);
    TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
}

/** Test wake up from sleep
 *
 * Given a SysTimer with a tick scheduled in the future
 *     and a core in sleep mode
 * When given time elapses
 * Then the uC is woken up from sleep
 *     and the tick handler is called
 *     and measured time matches requested delay
 */
void test_sleep(void)
{
    Timer timer;
    SysTimerTest st;

    sleep_manager_lock_deep_sleep();
    timer.start();
    st.schedule_tick(TEST_TICKS);

    TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be disallowed");
    while (st.sem_wait(0) != 1) {
        sleep();
    }
    timer.stop();
    sleep_manager_unlock_deep_sleep();

    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us());
}

#if DEVICE_LOWPOWERTIMER
/** Test wake up from deepsleep
 *
 * Given a SysTimer with a tick scheduled in the future
 *     and a core in deepsleep mode
 * When given time elapses
 * Then the uC is woken up from deepsleep
 *     and the tick handler is called
 *     and measured time matches requested delay
 */
void test_deepsleep(void)
{
    /*
     * Since deepsleep() may shut down the UART peripheral, we wait for 10ms
     * to allow for hardware serial buffers to completely flush.

     * This should be replaced with a better function that checks if the
     * hardware buffers are empty. However, such an API does not exist now,
     * so we'll use the wait_ms() function for now.
     */
    wait_ms(10);

    // Regular Timer might be disabled during deepsleep.
    LowPowerTimer lptimer;
    SysTimerTest st;

    lptimer.start();
    st.schedule_tick(TEST_TICKS);
    TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be allowed");
    while (st.sem_wait(0) != 1) {
        sleep();
    }
    lptimer.stop();

    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us());
}
#endif

utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(5, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("Tick count is zero upon creation", test_created_with_zero_tick_count),
    Case("Tick count is updated correctly", test_update_tick),
    Case("Time is updated correctly", test_get_time),
    Case("Tick can be cancelled", test_cancel_tick),
    Case("Schedule zero ticks", test_schedule_zero),
    Case("Handler called once", test_handler_called_once),
    Case("Wake up from sleep", test_sleep),
#if DEVICE_LOWPOWERTIMER
    Case("Wake up from deep sleep", test_deepsleep),
#endif

};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<commit_msg>tests-mbedmicro-rtos-mbed-systimer: execute sleep/deepsleep test cases only when SLEEP support is enabled.<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * 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.
 */
#if !MBED_TICKLESS
#error [NOT_SUPPORTED] Tickless mode not supported for this target.
#endif

#if !DEVICE_LOWPOWERTIMER
#error [NOT_SUPPORTED] Current SysTimer implementation requires lp ticker support.
#endif

#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "ticker_api.h"

extern "C" {
#include "rtx_lib.h"
}
#include "rtos/TARGET_CORTEX/SysTimer.h"

#define TEST_TICKS 42UL
#define DELAY_DELTA_US 2500ULL

using namespace utest::v1;

const us_timestamp_t DELAY_US = 1000000ULL * TEST_TICKS / OS_TICK_FREQ;

// Override the handler() -- the SysTick interrupt must not be set as pending by the test code.
class SysTimerTest: public rtos::internal::SysTimer {
private:
    Semaphore _sem;
    virtual void handler()
    {
        core_util_critical_section_enter();
        _increment_tick();
        core_util_critical_section_exit();
        _sem.release();
    }

public:
    SysTimerTest() :
            SysTimer(), _sem(0, 1)
    {
    }

    SysTimerTest(const ticker_data_t *data) :
            SysTimer(data), _sem(0, 1)
    {
    }

    virtual ~SysTimerTest()
    {
    }

    int32_t sem_wait(uint32_t millisec)
    {
        return _sem.wait(millisec);
    }
};

timestamp_t mock_ticker_timestamp;

void mock_ticker_init()
{
}

uint32_t mock_ticker_read()
{
    return mock_ticker_timestamp;
}

void mock_ticker_disable_interrupt()
{
}

void mock_ticker_clear_interrupt()
{
}

void mock_ticker_set_interrupt(timestamp_t timestamp)
{
}

void mock_ticker_fire_interrupt()
{
}

const ticker_info_t *mock_ticker_get_info()
{
    static const ticker_info_t mock_ticker_info = {
        .frequency = 1000000,
        .bits = 32
    };
    return &mock_ticker_info;
}

ticker_interface_t mock_ticker_interface = {
    .init = mock_ticker_init,
    .read = mock_ticker_read,
    .disable_interrupt = mock_ticker_disable_interrupt,
    .clear_interrupt = mock_ticker_clear_interrupt,
    .set_interrupt = mock_ticker_set_interrupt,
    .fire_interrupt = mock_ticker_fire_interrupt,
    .get_info = mock_ticker_get_info,
};

ticker_event_queue_t mock_ticker_event_queue;

const ticker_data_t mock_ticker_data = {
    .interface = &mock_ticker_interface,
    .queue = &mock_ticker_event_queue
};

void mock_ticker_reset()
{
    mock_ticker_timestamp = 0;
    memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue);
}

/** Test tick count is zero upon creation
 *
 * Given a SysTimer
 * When the timer is created
 * Then tick count is zero
 */
void test_created_with_zero_tick_count(void)
{
    SysTimerTest st;
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
}

/** Test tick count is updated correctly
 *
 * Given a SysTimer
 * When the @a suspend and @a resume methods are called immediately after creation
 * Then the tick count is not updated
 * When @a suspend and @a resume methods are called again after a delay
 * Then the tick count is updated
 *     and the number of ticks incremented is equal TEST_TICKS - 1
 * When @a suspend and @a resume methods are called again without a delay
 * Then the tick count is not updated
 */
void test_update_tick(void)
{
    mock_ticker_reset();
    SysTimerTest st(&mock_ticker_data);
    st.suspend(TEST_TICKS * 2);
    TEST_ASSERT_EQUAL_UINT32(0, st.resume());
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());

    st.suspend(TEST_TICKS * 2);
    mock_ticker_timestamp = DELAY_US;
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume());
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());

    st.suspend(TEST_TICKS * 2);
    TEST_ASSERT_EQUAL_UINT32(0, st.resume());
    TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
}

/** Test get_time returns correct time
 *
 * Given a SysTimer
 * When @a get_time method is called before and after a delay
 * Then time difference is equal the delay
 */
void test_get_time(void)
{
    mock_ticker_reset();
    SysTimerTest st(&mock_ticker_data);
    us_timestamp_t t1 = st.get_time();

    mock_ticker_timestamp = DELAY_US;
    us_timestamp_t t2 = st.get_time();
    TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1);
}

/** Test cancel_tick
 *
 * Given a SysTimer with a scheduled tick
 * When @a cancel_tick is called before the given number of ticks elapse
 * Then the handler is never called
 *     and the tick count is not incremented
 */
void test_cancel_tick(void)
{
    SysTimerTest st;
    st.cancel_tick();
    st.schedule_tick(TEST_TICKS);

    st.cancel_tick();
    int32_t sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
    TEST_ASSERT_EQUAL_INT32(0, sem_slots);
    TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
}

/** Test schedule zero
 *
 * Given a SysTimer
 * When a tick is scheduled with delta = 0 ticks
 * Then the handler is called instantly
 */
void test_schedule_zero(void)
{
    SysTimerTest st;

    st.schedule_tick(0UL);
    int32_t sem_slots = st.sem_wait(0UL);
    TEST_ASSERT_EQUAL_INT32(1, sem_slots);
}

/** Test handler called once
 *
 * Given a SysTimer with a tick scheduled with delta = TEST_TICKS
 * When the handler is called
 * Then the tick count is incremented by 1
 *     and elapsed time is equal 1000000ULL * TEST_TICKS / OS_TICK_FREQ;
 * When more time elapses
 * Then the handler is not called again
 */
void test_handler_called_once(void)
{
    SysTimerTest st;
    st.schedule_tick(TEST_TICKS);
    us_timestamp_t t1 = st.get_time();
    int32_t sem_slots = st.sem_wait(0);
    TEST_ASSERT_EQUAL_INT32(0, sem_slots);

    sem_slots = st.sem_wait(osWaitForever);
    us_timestamp_t t2 = st.get_time();
    TEST_ASSERT_EQUAL_INT32(1, sem_slots);
    TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);

    sem_slots = st.sem_wait((DELAY_US + DELAY_DELTA_US) / 1000ULL);
    TEST_ASSERT_EQUAL_INT32(0, sem_slots);
    TEST_ASSERT_EQUAL_UINT32(1, st.get_tick());
}

#if DEVICE_SLEEP
/** Test wake up from sleep
 *
 * Given a SysTimer with a tick scheduled in the future
 *     and a core in sleep mode
 * When given time elapses
 * Then the uC is woken up from sleep
 *     and the tick handler is called
 *     and measured time matches requested delay
 */
void test_sleep(void)
{
    Timer timer;
    SysTimerTest st;

    sleep_manager_lock_deep_sleep();
    timer.start();
    st.schedule_tick(TEST_TICKS);

    TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be disallowed");
    while (st.sem_wait(0) != 1) {
        sleep();
    }
    timer.stop();
    sleep_manager_unlock_deep_sleep();

    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us());
}

#if DEVICE_LOWPOWERTIMER
/** Test wake up from deepsleep
 *
 * Given a SysTimer with a tick scheduled in the future
 *     and a core in deepsleep mode
 * When given time elapses
 * Then the uC is woken up from deepsleep
 *     and the tick handler is called
 *     and measured time matches requested delay
 */
void test_deepsleep(void)
{
    /*
     * Since deepsleep() may shut down the UART peripheral, we wait for 10ms
     * to allow for hardware serial buffers to completely flush.

     * This should be replaced with a better function that checks if the
     * hardware buffers are empty. However, such an API does not exist now,
     * so we'll use the wait_ms() function for now.
     */
    wait_ms(10);

    // Regular Timer might be disabled during deepsleep.
    LowPowerTimer lptimer;
    SysTimerTest st;

    lptimer.start();
    st.schedule_tick(TEST_TICKS);
    TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "Deep sleep should be allowed");
    while (st.sem_wait(0) != 1) {
        sleep();
    }
    lptimer.stop();

    TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us());
}
#endif
#endif

utest::v1::status_t test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(5, "default_auto");
    return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
    Case("Tick count is zero upon creation", test_created_with_zero_tick_count),
    Case("Tick count is updated correctly", test_update_tick),
    Case("Time is updated correctly", test_get_time),
    Case("Tick can be cancelled", test_cancel_tick),
    Case("Schedule zero ticks", test_schedule_zero),
    Case("Handler called once", test_handler_called_once),
#if DEVICE_SLEEP
    Case("Wake up from sleep", test_sleep),
#if DEVICE_LOWPOWERTIMER
    Case("Wake up from deep sleep", test_deepsleep),
#endif
#endif

};

Specification specification(test_setup, cases);

int main()
{
    return !Harness::run(specification);
}
<|endoftext|>


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

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/common/model_builder.h"

#include <cstdlib>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/builtin_ops.h"
#include "tensorflow/lite/c/c_api_internal.h"
#include "tensorflow/lite/core/subgraph.h"
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/stderr_reporter.h"

namespace tflite {
namespace gpu {
namespace {

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank0) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteFloat32;
  tflite_tensor.dims = TfLiteIntArrayCreate(1);
  tflite_tensor.dims->data[0] = 4;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::FLOAT32);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 1, 1, 1));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank1) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteInt32;
  tflite_tensor.dims = TfLiteIntArrayCreate(2);
  tflite_tensor.dims->data[0] = 4;
  tflite_tensor.dims->data[1] = 5;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::INT32);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 1, 1, 5));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank2) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteInt64;
  tflite_tensor.dims = TfLiteIntArrayCreate(3);
  tflite_tensor.dims->data[0] = 4;
  tflite_tensor.dims->data[1] = 5;
  tflite_tensor.dims->data[2] = 6;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::INT64);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 1, 5, 6));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank3) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteUInt8;
  tflite_tensor.dims = TfLiteIntArrayCreate(4);
  tflite_tensor.dims->data[0] = 4;
  tflite_tensor.dims->data[1] = 5;
  tflite_tensor.dims->data[2] = 6;
  tflite_tensor.dims->data[3] = 7;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::UINT8);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 5, 6, 7));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefFailsForRankLT0) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteFloat32;
  tflite_tensor.dims = TfLiteIntArrayCreate(0);
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  // TODO(b/130054481): Cover scalar.
  EXPECT_FALSE(status.ok());
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefFailsForRankGT3) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteFloat32;
  tflite_tensor.dims = TfLiteIntArrayCreate(5);
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  EXPECT_FALSE(status.ok());
}

class InterpreterFp16 {
 public:
  InterpreterFp16() {
    void* builtin_data = malloc(sizeof(int));
    EXPECT_EQ(interpreter_.AddTensors(5), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetInputs({0, 1}), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetOutputs({4}), kTfLiteOk);

    // Add a Dequantize Node.
    const TfLiteRegistration reg_dequant0 = {
        nullptr, nullptr, nullptr, nullptr, nullptr, kTfLiteBuiltinDequantize};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{0}, /*outputs=*/{1}, /*init_data=*/nullptr,
                  /*init_data_size=*/0, /*builtin_data=*/nullptr,
                  /*registration=*/&reg_dequant0),
              kTfLiteOk);

    // Add a Dequantize Node.
    const TfLiteRegistration reg_dequant1 = {
        nullptr, nullptr, nullptr, nullptr, nullptr, kTfLiteBuiltinDequantize};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{2}, /*outputs=*/{3}, /*init_data=*/nullptr,
                  /*init_data_size=*/0, /*builtin_data=*/nullptr,
                  /*registration=*/&reg_dequant1),
              kTfLiteOk);

    // Add a node that GPU delegate can parse.
    const TfLiteRegistration reg_add0 = {
        [](TfLiteContext* context, const char* buffer, size_t length) {
          return reinterpret_cast<void*>(new int(1));
        },
        [](TfLiteContext* context, void* buffer) {
          delete reinterpret_cast<int*>(buffer);
        },
        nullptr,
        nullptr,
        nullptr,
        kTfLiteBuiltinAdd};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{1, 3}, /*outputs=*/{4}, /*init_data=*/nullptr,
                  /*init_data_size=*/0,
                  /*builtin_data=*/builtin_data,
                  /*registration=*/&reg_add0),
              kTfLiteOk);

    // Set inputs to Dequantize node to the specified type.
    const std::vector<int> dims = {1};
    TfLiteQuantization quantization;
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            0, TfLiteType::kTfLiteFloat16, "t0", dims, quantization, false),
        kTfLiteOk);
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            2, TfLiteType::kTfLiteFloat16, "t2", dims, quantization, false),
        kTfLiteOk);
    exec_plan_ = TfLiteIntArrayCreate(3);
    exec_plan_->data[0] = 0;
    exec_plan_->data[1] = 1;
    exec_plan_->data[2] = 2;
  }

  ~InterpreterFp16() { TfLiteIntArrayFree(exec_plan_); }

  Subgraph* GetSubgraph() { return interpreter_.subgraph(0); }
  TfLiteIntArray* exec_plan() const { return exec_plan_; }

 private:
  Interpreter interpreter_;
  TfLiteIntArray* exec_plan_;
};

InterpreterFp16* interpreter_fp16 = new InterpreterFp16();

TEST(ModelBuilderTest, GetOpsToReplacePrunesFp16DequantizeNodes) {
  // Before pruning, the graph has three nodes:
  //
  //   t0 (FP16) -> DequantNode -> t1 (FP32) -> Add -> t4
  //   t2 (FP16) -> DequantNode -> t3 (FP32) --/
  //
  // After pruning, the graph has one node:
  //
  //   t0 (FP16) --> Add -> t4
  //   t2 (FP16) --/
  //
  TfLiteContext* context = interpreter_fp16->GetSubgraph()->context();
  // These functions are meant to be called inside delegates. Swap out
  // for similar functions to permit direct calling of GetOpsToReplace.
  context->GetExecutionPlan = [](struct TfLiteContext* context,
                                 TfLiteIntArray** execution_plan) {
    *execution_plan = interpreter_fp16->exec_plan();
    return kTfLiteOk;
  };
  context->GetNodeAndRegistration = [](struct TfLiteContext*, int node_index,
                                       TfLiteNode** node,
                                       TfLiteRegistration** registration) {
    auto& node_and_reg =
        interpreter_fp16->GetSubgraph()->nodes_and_registration()[node_index];
    *node = &node_and_reg.first;
    *registration = &node_and_reg.second;
    return kTfLiteOk;
  };

  TfLiteIntArray* ops_to_replace = GetOpsToReplace(context);

  // Just one node left.
  EXPECT_EQ(ops_to_replace->size, 1);
  TfLiteNode* node = nullptr;
  TfLiteRegistration* registration = nullptr;
  context->GetNodeAndRegistration(context, ops_to_replace->data[0], &node,
                                  &registration);
  EXPECT_EQ(context->tensors[node->inputs->data[0]].type,
            TfLiteType::kTfLiteFloat16);
  EXPECT_EQ(context->tensors[node->inputs->data[1]].type,
            TfLiteType::kTfLiteFloat16);
  TfLiteIntArrayFree(ops_to_replace);
}

class InterpreterFp32 {
 public:
  InterpreterFp32() {
    void* builtin_data = malloc(sizeof(int));
    EXPECT_EQ(interpreter_.AddTensors(3), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetInputs({0, 1}), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetOutputs({2}), kTfLiteOk);

    // Add a node that GPU delegate can parse.
    const TfLiteRegistration reg_add0 = {
        [](TfLiteContext* context, const char* buffer, size_t length) {
          return reinterpret_cast<void*>(new int(1));
        },
        [](TfLiteContext* context, void* buffer) {
          delete reinterpret_cast<int*>(buffer);
        },
        nullptr,
        nullptr,
        nullptr,
        kTfLiteBuiltinAdd};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{0, 1}, /*outputs=*/{2}, /*init_data=*/nullptr,
                  /*init_data_size=*/0,
                  /*builtin_data=*/builtin_data,
                  /*registration=*/&reg_add0),
              kTfLiteOk);

    const std::vector<int> dims = {1};
    TfLiteQuantization quantization;
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            0, TfLiteType::kTfLiteFloat32, "t0", dims, quantization, false),
        kTfLiteOk);
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            1, TfLiteType::kTfLiteFloat32, "t1", dims, quantization, false),
        kTfLiteOk);
    exec_plan_ = TfLiteIntArrayCreate(1);
    exec_plan_->data[0] = 0;
  }

  ~InterpreterFp32() { TfLiteIntArrayFree(exec_plan_); }

  Subgraph* GetSubgraph() { return interpreter_.subgraph(0); }
  TfLiteIntArray* exec_plan() const { return exec_plan_; }

 private:
  Interpreter interpreter_;
  TfLiteIntArray* exec_plan_;
};

InterpreterFp32* interpreter_fp32 = new InterpreterFp32();

TEST(ModelBuilderTest, GetOpsToReplaceDoesNotPruneFp32) {
  // A FP32 graph is not affected and is same before and after:
  //
  //   t0 (FP32) --> Add -> t2
  //   t1 (FP32) --/
  //
  TfLiteContext* context = interpreter_fp32->GetSubgraph()->context();

  // These functions are meant to be called inside delegates. Swap out
  // for similar functions to permit direct calling of GetOpsToReplace.
  context->GetExecutionPlan = [](struct TfLiteContext* context,
                                 TfLiteIntArray** execution_plan) {
    *execution_plan = interpreter_fp32->exec_plan();
    return kTfLiteOk;
  };
  context->GetNodeAndRegistration = [](struct TfLiteContext*, int node_index,
                                       TfLiteNode** node,
                                       TfLiteRegistration** registration) {
    auto& node_and_reg =
        interpreter_fp32->GetSubgraph()->nodes_and_registration()[node_index];
    *node = &node_and_reg.first;
    *registration = &node_and_reg.second;
    return kTfLiteOk;
  };

  TfLiteIntArray* ops_to_replace = GetOpsToReplace(context);

  // Just one node left.
  EXPECT_EQ(ops_to_replace->size, 1);
  TfLiteNode* node = nullptr;
  TfLiteRegistration* registration = nullptr;
  context->GetNodeAndRegistration(context, ops_to_replace->data[0], &node,
                                  &registration);
  EXPECT_EQ(context->tensors[node->inputs->data[0]].type,
            TfLiteType::kTfLiteFloat32);
  EXPECT_EQ(context->tensors[node->inputs->data[1]].type,
            TfLiteType::kTfLiteFloat32);
  TfLiteIntArrayFree(ops_to_replace);
}

}  // namespace
}  // namespace gpu
}  // namespace tflite
<commit_msg>Fix uninintialized variable.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/common/model_builder.h"

#include <cstdlib>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/builtin_ops.h"
#include "tensorflow/lite/c/c_api_internal.h"
#include "tensorflow/lite/core/subgraph.h"
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/stderr_reporter.h"

namespace tflite {
namespace gpu {
namespace {

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank0) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteFloat32;
  tflite_tensor.dims = TfLiteIntArrayCreate(1);
  tflite_tensor.dims->data[0] = 4;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::FLOAT32);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 1, 1, 1));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank1) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteInt32;
  tflite_tensor.dims = TfLiteIntArrayCreate(2);
  tflite_tensor.dims->data[0] = 4;
  tflite_tensor.dims->data[1] = 5;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::INT32);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 1, 1, 5));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank2) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteInt64;
  tflite_tensor.dims = TfLiteIntArrayCreate(3);
  tflite_tensor.dims->data[0] = 4;
  tflite_tensor.dims->data[1] = 5;
  tflite_tensor.dims->data[2] = 6;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::INT64);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 1, 5, 6));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefSucceedsForRank3) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteUInt8;
  tflite_tensor.dims = TfLiteIntArrayCreate(4);
  tflite_tensor.dims->data[0] = 4;
  tflite_tensor.dims->data[1] = 5;
  tflite_tensor.dims->data[2] = 6;
  tflite_tensor.dims->data[3] = 7;
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  ASSERT_TRUE(status.ok());
  EXPECT_EQ(tensor_ref.type, DataType::UINT8);
  EXPECT_EQ(tensor_ref.shape, BHWC(4, 5, 6, 7));
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefFailsForRankLT0) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteFloat32;
  tflite_tensor.dims = TfLiteIntArrayCreate(0);
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  // TODO(b/130054481): Cover scalar.
  EXPECT_FALSE(status.ok());
}

TEST(ModelBuilderTest, ConvertTfLiteTensorToTensorRefFailsForRankGT3) {
  TfLiteTensor tflite_tensor;
  tflite_tensor.type = TfLiteType::kTfLiteFloat32;
  tflite_tensor.dims = TfLiteIntArrayCreate(5);
  TensorRefFloat32 tensor_ref;
  const auto status =
      ConvertTfLiteTensorToTensorRef(tflite_tensor, &tensor_ref);
  TfLiteIntArrayFree(tflite_tensor.dims);
  EXPECT_FALSE(status.ok());
}

class InterpreterFp16 {
 public:
  InterpreterFp16() {
    void* builtin_data = malloc(sizeof(int));
    EXPECT_EQ(interpreter_.AddTensors(5), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetInputs({0, 1}), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetOutputs({4}), kTfLiteOk);

    // Add a Dequantize Node.
    const TfLiteRegistration reg_dequant0 = {
        nullptr, nullptr, nullptr, nullptr, nullptr, kTfLiteBuiltinDequantize};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{0}, /*outputs=*/{1}, /*init_data=*/nullptr,
                  /*init_data_size=*/0, /*builtin_data=*/nullptr,
                  /*registration=*/&reg_dequant0),
              kTfLiteOk);

    // Add a Dequantize Node.
    const TfLiteRegistration reg_dequant1 = {
        nullptr, nullptr, nullptr, nullptr, nullptr, kTfLiteBuiltinDequantize};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{2}, /*outputs=*/{3}, /*init_data=*/nullptr,
                  /*init_data_size=*/0, /*builtin_data=*/nullptr,
                  /*registration=*/&reg_dequant1),
              kTfLiteOk);

    // Add a node that GPU delegate can parse.
    const TfLiteRegistration reg_add0 = {
        [](TfLiteContext* context, const char* buffer, size_t length) {
          return reinterpret_cast<void*>(new int(1));
        },
        [](TfLiteContext* context, void* buffer) {
          delete reinterpret_cast<int*>(buffer);
        },
        nullptr,
        nullptr,
        nullptr,
        kTfLiteBuiltinAdd};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{1, 3}, /*outputs=*/{4}, /*init_data=*/nullptr,
                  /*init_data_size=*/0,
                  /*builtin_data=*/builtin_data,
                  /*registration=*/&reg_add0),
              kTfLiteOk);

    // Set inputs to Dequantize node to the specified type.
    const std::vector<int> dims = {1};
    TfLiteQuantization quantization;
    quantization.type = kTfLiteNoQuantization;
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            0, TfLiteType::kTfLiteFloat16, "t0", dims, quantization, false),
        kTfLiteOk);
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            2, TfLiteType::kTfLiteFloat16, "t2", dims, quantization, false),
        kTfLiteOk);
    exec_plan_ = TfLiteIntArrayCreate(3);
    exec_plan_->data[0] = 0;
    exec_plan_->data[1] = 1;
    exec_plan_->data[2] = 2;
  }

  ~InterpreterFp16() { TfLiteIntArrayFree(exec_plan_); }

  Subgraph* GetSubgraph() { return interpreter_.subgraph(0); }
  TfLiteIntArray* exec_plan() const { return exec_plan_; }

 private:
  Interpreter interpreter_;
  TfLiteIntArray* exec_plan_;
};

InterpreterFp16* interpreter_fp16 = new InterpreterFp16();

TEST(ModelBuilderTest, GetOpsToReplacePrunesFp16DequantizeNodes) {
  // Before pruning, the graph has three nodes:
  //
  //   t0 (FP16) -> DequantNode -> t1 (FP32) -> Add -> t4
  //   t2 (FP16) -> DequantNode -> t3 (FP32) --/
  //
  // After pruning, the graph has one node:
  //
  //   t0 (FP16) --> Add -> t4
  //   t2 (FP16) --/
  //
  TfLiteContext* context = interpreter_fp16->GetSubgraph()->context();
  // These functions are meant to be called inside delegates. Swap out
  // for similar functions to permit direct calling of GetOpsToReplace.
  context->GetExecutionPlan = [](struct TfLiteContext* context,
                                 TfLiteIntArray** execution_plan) {
    *execution_plan = interpreter_fp16->exec_plan();
    return kTfLiteOk;
  };
  context->GetNodeAndRegistration = [](struct TfLiteContext*, int node_index,
                                       TfLiteNode** node,
                                       TfLiteRegistration** registration) {
    auto& node_and_reg =
        interpreter_fp16->GetSubgraph()->nodes_and_registration()[node_index];
    *node = &node_and_reg.first;
    *registration = &node_and_reg.second;
    return kTfLiteOk;
  };

  TfLiteIntArray* ops_to_replace = GetOpsToReplace(context);

  // Just one node left.
  EXPECT_EQ(ops_to_replace->size, 1);
  TfLiteNode* node = nullptr;
  TfLiteRegistration* registration = nullptr;
  context->GetNodeAndRegistration(context, ops_to_replace->data[0], &node,
                                  &registration);
  EXPECT_EQ(context->tensors[node->inputs->data[0]].type,
            TfLiteType::kTfLiteFloat16);
  EXPECT_EQ(context->tensors[node->inputs->data[1]].type,
            TfLiteType::kTfLiteFloat16);
  TfLiteIntArrayFree(ops_to_replace);
}

class InterpreterFp32 {
 public:
  InterpreterFp32() {
    void* builtin_data = malloc(sizeof(int));
    EXPECT_EQ(interpreter_.AddTensors(3), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetInputs({0, 1}), kTfLiteOk);
    EXPECT_EQ(interpreter_.SetOutputs({2}), kTfLiteOk);

    // Add a node that GPU delegate can parse.
    const TfLiteRegistration reg_add0 = {
        [](TfLiteContext* context, const char* buffer, size_t length) {
          return reinterpret_cast<void*>(new int(1));
        },
        [](TfLiteContext* context, void* buffer) {
          delete reinterpret_cast<int*>(buffer);
        },
        nullptr,
        nullptr,
        nullptr,
        kTfLiteBuiltinAdd};
    EXPECT_EQ(interpreter_.AddNodeWithParameters(
                  /*inputs=*/{0, 1}, /*outputs=*/{2}, /*init_data=*/nullptr,
                  /*init_data_size=*/0,
                  /*builtin_data=*/builtin_data,
                  /*registration=*/&reg_add0),
              kTfLiteOk);

    const std::vector<int> dims = {1};
    TfLiteQuantization quantization;
    quantization.type = kTfLiteNoQuantization;
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            0, TfLiteType::kTfLiteFloat32, "t0", dims, quantization, false),
        kTfLiteOk);
    EXPECT_EQ(
        interpreter_.SetTensorParametersReadWrite(
            1, TfLiteType::kTfLiteFloat32, "t1", dims, quantization, false),
        kTfLiteOk);
    exec_plan_ = TfLiteIntArrayCreate(1);
    exec_plan_->data[0] = 0;
  }

  ~InterpreterFp32() { TfLiteIntArrayFree(exec_plan_); }

  Subgraph* GetSubgraph() { return interpreter_.subgraph(0); }
  TfLiteIntArray* exec_plan() const { return exec_plan_; }

 private:
  Interpreter interpreter_;
  TfLiteIntArray* exec_plan_;
};

InterpreterFp32* interpreter_fp32 = new InterpreterFp32();

TEST(ModelBuilderTest, GetOpsToReplaceDoesNotPruneFp32) {
  // A FP32 graph is not affected and is same before and after:
  //
  //   t0 (FP32) --> Add -> t2
  //   t1 (FP32) --/
  //
  TfLiteContext* context = interpreter_fp32->GetSubgraph()->context();

  // These functions are meant to be called inside delegates. Swap out
  // for similar functions to permit direct calling of GetOpsToReplace.
  context->GetExecutionPlan = [](struct TfLiteContext* context,
                                 TfLiteIntArray** execution_plan) {
    *execution_plan = interpreter_fp32->exec_plan();
    return kTfLiteOk;
  };
  context->GetNodeAndRegistration = [](struct TfLiteContext*, int node_index,
                                       TfLiteNode** node,
                                       TfLiteRegistration** registration) {
    auto& node_and_reg =
        interpreter_fp32->GetSubgraph()->nodes_and_registration()[node_index];
    *node = &node_and_reg.first;
    *registration = &node_and_reg.second;
    return kTfLiteOk;
  };

  TfLiteIntArray* ops_to_replace = GetOpsToReplace(context);

  // Just one node left.
  EXPECT_EQ(ops_to_replace->size, 1);
  TfLiteNode* node = nullptr;
  TfLiteRegistration* registration = nullptr;
  context->GetNodeAndRegistration(context, ops_to_replace->data[0], &node,
                                  &registration);
  EXPECT_EQ(context->tensors[node->inputs->data[0]].type,
            TfLiteType::kTfLiteFloat32);
  EXPECT_EQ(context->tensors[node->inputs->data[1]].type,
            TfLiteType::kTfLiteFloat32);
  TfLiteIntArrayFree(ops_to_replace);
}

}  // namespace
}  // namespace gpu
}  // namespace tflite
<|endoftext|>


<commit_before>//===--- Allocator.cpp - Simple memory allocation abstraction -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the BumpPtrAllocator interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Recycler.h"
#include "llvm/Support/Streams.h"
#include <cstring>

namespace llvm {

BumpPtrAllocator::BumpPtrAllocator(size_t size, size_t threshold,
                                   SlabAllocator &allocator)
    : SlabSize(size), SizeThreshold(threshold), Allocator(allocator),
      CurSlab(0), BytesAllocated(0) {
  StartNewSlab();
}

BumpPtrAllocator::~BumpPtrAllocator() {
  DeallocateSlabs(CurSlab);
}

/// AlignPtr - Align Ptr to Alignment bytes, rounding up.  Alignment should
/// be a power of two.  This method rounds up, so AlignPtr(7, 4) == 8 and
/// AlignPtr(8, 4) == 8.
char *BumpPtrAllocator::AlignPtr(char *Ptr, size_t Alignment) {
  assert(Alignment && (Alignment & (Alignment - 1)) == 0 &&
         "Alignment is not a power of two!");

  // Do the alignment.
  return (char*)(((uintptr_t)Ptr + Alignment - 1) &
                 ~(uintptr_t)(Alignment - 1));
}

/// StartNewSlab - Allocate a new slab and move the bump pointers over into
/// the new slab.  Modifies CurPtr and End.
void BumpPtrAllocator::StartNewSlab() {
  MemSlab *NewSlab = Allocator.Allocate(SlabSize);
  NewSlab->NextPtr = CurSlab;
  CurSlab = NewSlab;
  CurPtr = (char*)(CurSlab + 1);
  End = ((char*)CurSlab) + CurSlab->Size;
}

/// DeallocateSlabs - Deallocate all memory slabs after and including this
/// one.
void BumpPtrAllocator::DeallocateSlabs(MemSlab *Slab) {
  while (Slab) {
    MemSlab *NextSlab = Slab->NextPtr;
#ifndef NDEBUG
    // Poison the memory so stale pointers crash sooner.  Note we must
    // preserve the Size and NextPtr fields at the beginning.
    memset(Slab + 1, 0xCD, Slab->Size - sizeof(MemSlab));
#endif
    Allocator.Deallocate(Slab);
    Slab = NextSlab;
  }
}

/// Reset - Deallocate all but the current slab and reset the current pointer
/// to the beginning of it, freeing all memory allocated so far.
void BumpPtrAllocator::Reset() {
  DeallocateSlabs(CurSlab->NextPtr);
  CurSlab->NextPtr = 0;
  CurPtr = (char*)(CurSlab + 1);
  End = ((char*)CurSlab) + CurSlab->Size;
}

/// Allocate - Allocate space at the specified alignment.
///
void *BumpPtrAllocator::Allocate(size_t Size, size_t Alignment) {
  // Keep track of how many bytes we've allocated.
  BytesAllocated += Size;

  // 0-byte alignment means 1-byte alignment.
  if (Alignment == 0) Alignment = 1;

  // Allocate the aligned space, going forwards from CurPtr.
  char *Ptr = AlignPtr(CurPtr, Alignment);

  // Check if we can hold it.
  if (Ptr + Size <= End) {
    CurPtr = Ptr + Size;
    return Ptr;
  }

  // If Size is really big, allocate a separate slab for it.
  if (Size > SizeThreshold) {
    size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1;
    MemSlab *NewSlab = Allocator.Allocate(PaddedSize);

    // Put the new slab after the current slab, since we are not allocating
    // into it.
    NewSlab->NextPtr = CurSlab->NextPtr;
    CurSlab->NextPtr = NewSlab;

    Ptr = AlignPtr((char*)(NewSlab + 1), Alignment);
    assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + NewSlab->Size);
    return Ptr;
  }

  // Otherwise, start a new slab and try again.
  StartNewSlab();
  Ptr = AlignPtr(CurPtr, Alignment);
  CurPtr = Ptr + Size;
  assert(CurPtr <= End && "Unable to allocate memory!");
  return Ptr;
}

unsigned BumpPtrAllocator::GetNumSlabs() const {
  unsigned NumSlabs = 0;
  for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) {
    ++NumSlabs;
  }
  return NumSlabs;
}

void BumpPtrAllocator::PrintStats() const {
  unsigned NumSlabs = 0;
  size_t TotalMemory = 0;
  for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) {
    TotalMemory += Slab->Size;
    ++NumSlabs;
  }

  cerr << "\nNumber of memory regions: " << NumSlabs << '\n'
       << "Bytes used: " << BytesAllocated << '\n'
       << "Bytes allocated: " << TotalMemory << '\n'
       << "Bytes wasted: " << (TotalMemory - BytesAllocated)
       << " (includes alignment, etc)\n";
}

MallocSlabAllocator BumpPtrAllocator::DefaultSlabAllocator =
  MallocSlabAllocator();

SlabAllocator::~SlabAllocator() { }

MallocSlabAllocator::~MallocSlabAllocator() { }

MemSlab *MallocSlabAllocator::Allocate(size_t Size) {
  MemSlab *Slab = (MemSlab*)Allocator.Allocate(Size, 0);
  Slab->Size = Size;
  Slab->NextPtr = 0;
  return Slab;
}

void MallocSlabAllocator::Deallocate(MemSlab *Slab) {
  Allocator.Deallocate(Slab);
}

void PrintRecyclerStats(size_t Size,
                        size_t Align,
                        size_t FreeListSize) {
  cerr << "Recycler element size: " << Size << '\n'
       << "Recycler element alignment: " << Align << '\n'
       << "Number of elements free for recycling: " << FreeListSize << '\n';
}

}
<commit_msg>Switch to raw_ostream.<commit_after>//===--- Allocator.cpp - Simple memory allocation abstraction -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the BumpPtrAllocator interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Recycler.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>

namespace llvm {

BumpPtrAllocator::BumpPtrAllocator(size_t size, size_t threshold,
                                   SlabAllocator &allocator)
    : SlabSize(size), SizeThreshold(threshold), Allocator(allocator),
      CurSlab(0), BytesAllocated(0) {
  StartNewSlab();
}

BumpPtrAllocator::~BumpPtrAllocator() {
  DeallocateSlabs(CurSlab);
}

/// AlignPtr - Align Ptr to Alignment bytes, rounding up.  Alignment should
/// be a power of two.  This method rounds up, so AlignPtr(7, 4) == 8 and
/// AlignPtr(8, 4) == 8.
char *BumpPtrAllocator::AlignPtr(char *Ptr, size_t Alignment) {
  assert(Alignment && (Alignment & (Alignment - 1)) == 0 &&
         "Alignment is not a power of two!");

  // Do the alignment.
  return (char*)(((uintptr_t)Ptr + Alignment - 1) &
                 ~(uintptr_t)(Alignment - 1));
}

/// StartNewSlab - Allocate a new slab and move the bump pointers over into
/// the new slab.  Modifies CurPtr and End.
void BumpPtrAllocator::StartNewSlab() {
  MemSlab *NewSlab = Allocator.Allocate(SlabSize);
  NewSlab->NextPtr = CurSlab;
  CurSlab = NewSlab;
  CurPtr = (char*)(CurSlab + 1);
  End = ((char*)CurSlab) + CurSlab->Size;
}

/// DeallocateSlabs - Deallocate all memory slabs after and including this
/// one.
void BumpPtrAllocator::DeallocateSlabs(MemSlab *Slab) {
  while (Slab) {
    MemSlab *NextSlab = Slab->NextPtr;
#ifndef NDEBUG
    // Poison the memory so stale pointers crash sooner.  Note we must
    // preserve the Size and NextPtr fields at the beginning.
    memset(Slab + 1, 0xCD, Slab->Size - sizeof(MemSlab));
#endif
    Allocator.Deallocate(Slab);
    Slab = NextSlab;
  }
}

/// Reset - Deallocate all but the current slab and reset the current pointer
/// to the beginning of it, freeing all memory allocated so far.
void BumpPtrAllocator::Reset() {
  DeallocateSlabs(CurSlab->NextPtr);
  CurSlab->NextPtr = 0;
  CurPtr = (char*)(CurSlab + 1);
  End = ((char*)CurSlab) + CurSlab->Size;
}

/// Allocate - Allocate space at the specified alignment.
///
void *BumpPtrAllocator::Allocate(size_t Size, size_t Alignment) {
  // Keep track of how many bytes we've allocated.
  BytesAllocated += Size;

  // 0-byte alignment means 1-byte alignment.
  if (Alignment == 0) Alignment = 1;

  // Allocate the aligned space, going forwards from CurPtr.
  char *Ptr = AlignPtr(CurPtr, Alignment);

  // Check if we can hold it.
  if (Ptr + Size <= End) {
    CurPtr = Ptr + Size;
    return Ptr;
  }

  // If Size is really big, allocate a separate slab for it.
  if (Size > SizeThreshold) {
    size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1;
    MemSlab *NewSlab = Allocator.Allocate(PaddedSize);

    // Put the new slab after the current slab, since we are not allocating
    // into it.
    NewSlab->NextPtr = CurSlab->NextPtr;
    CurSlab->NextPtr = NewSlab;

    Ptr = AlignPtr((char*)(NewSlab + 1), Alignment);
    assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + NewSlab->Size);
    return Ptr;
  }

  // Otherwise, start a new slab and try again.
  StartNewSlab();
  Ptr = AlignPtr(CurPtr, Alignment);
  CurPtr = Ptr + Size;
  assert(CurPtr <= End && "Unable to allocate memory!");
  return Ptr;
}

unsigned BumpPtrAllocator::GetNumSlabs() const {
  unsigned NumSlabs = 0;
  for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) {
    ++NumSlabs;
  }
  return NumSlabs;
}

void BumpPtrAllocator::PrintStats() const {
  unsigned NumSlabs = 0;
  size_t TotalMemory = 0;
  for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) {
    TotalMemory += Slab->Size;
    ++NumSlabs;
  }

  errs() << "\nNumber of memory regions: " << NumSlabs << '\n'
         << "Bytes used: " << BytesAllocated << '\n'
         << "Bytes allocated: " << TotalMemory << '\n'
         << "Bytes wasted: " << (TotalMemory - BytesAllocated)
         << " (includes alignment, etc)\n";
}

MallocSlabAllocator BumpPtrAllocator::DefaultSlabAllocator =
  MallocSlabAllocator();

SlabAllocator::~SlabAllocator() { }

MallocSlabAllocator::~MallocSlabAllocator() { }

MemSlab *MallocSlabAllocator::Allocate(size_t Size) {
  MemSlab *Slab = (MemSlab*)Allocator.Allocate(Size, 0);
  Slab->Size = Size;
  Slab->NextPtr = 0;
  return Slab;
}

void MallocSlabAllocator::Deallocate(MemSlab *Slab) {
  Allocator.Deallocate(Slab);
}

void PrintRecyclerStats(size_t Size,
                        size_t Align,
                        size_t FreeListSize) {
  errs() << "Recycler element size: " << Size << '\n'
         << "Recycler element alignment: " << Align << '\n'
         << "Number of elements free for recycling: " << FreeListSize << '\n';
}

}
<|endoftext|>


<commit_before>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/slobrok/server/mock_map_listener.h>
#include <vespa/slobrok/server/service_map_mirror.h>
#include <vespa/vespalib/gtest/gtest.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <map>

using namespace vespalib;
using namespace slobrok;
using vespalib::make_string_short::fmt;

using Map = std::map<vespalib::string, vespalib::string>;

Map dump(const ServiceMapMirror &history) {
    Map result;
    for (const auto & entry : history.allMappings()) {
        result[entry.name] = entry.spec;
    }
    return result;
}

void addTo(ServiceMapMirror &target, const ServiceMapping &mapping) {
    auto cur = target.currentGeneration();
    std::vector<vespalib::string> removes = {};
    ServiceMappingList updates = { mapping };
    auto nxt = cur;
    nxt.add();
    MapDiff diff{cur, removes, updates, nxt};
    target.apply(diff);
}

void removeFrom(ServiceMapMirror &target, const ServiceMapping &mapping) {
    auto cur = target.currentGeneration();
    std::vector<vespalib::string> removes = { mapping.name };
    ServiceMappingList updates = { };
    auto nxt = cur;
    nxt.add();
    MapDiff diff{cur, removes, updates, nxt};
    target.apply(diff);
}

TEST(ServiceMapMirrorTest, empty_inspection) {
    ServiceMapMirror mirror;
    auto bar = dump(mirror);
    EXPECT_TRUE(bar.empty());

    MockMapListener observer;
    mirror.registerListener(observer);
    mirror.unregisterListener(observer);
    EXPECT_EQ(observer.last_event, MockEvent::NONE);
}

TEST(ServiceMapMirrorTest, full_inspection) {
    ServiceMapMirror mirror;
    MockMapListener observer;
    mirror.registerListener(observer);
    for (int i = 0; i < 1984; ++i) {
        EXPECT_EQ(mirror.currentGeneration(), GenCnt(i));
        auto name = fmt("key/%d/name", i);
        auto spec = fmt("tcp/host%d.domain.tld:19099", 10000+i);
        ServiceMapping toAdd{name, spec};
        addTo(mirror, toAdd);
        EXPECT_EQ(observer.last_event, MockEvent::ADD);
        EXPECT_EQ(observer.last_add, toAdd);
    }
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1984));
    ServiceMapping toRemove{"key/666/name", "tcp/host10666.domain.tld:19099"};
    removeFrom(mirror, toRemove);
    EXPECT_EQ(observer.last_event, MockEvent::REMOVE);
    EXPECT_EQ(observer.last_remove, toRemove);
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1985));

    ServiceMapping oldMapping{"key/1969/name", "tcp/host11969.domain.tld:19099"};
    ServiceMapping toUpdate{"key/1969/name", "tcp/woodstock:19069"};
    addTo(mirror, toUpdate);
    EXPECT_EQ(observer.last_event, MockEvent::UPDATE);
    EXPECT_EQ(observer.last_remove, oldMapping);
    EXPECT_EQ(observer.last_add, toUpdate);
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1986));

    auto map = dump(mirror);
    EXPECT_FALSE(map.contains("foo"));
    EXPECT_TRUE(map.contains("key/0/name"));
    EXPECT_FALSE(map.contains("key/666/name"));
    EXPECT_TRUE(map.contains("key/1983/name"));
    EXPECT_FALSE(map.contains("key/1984/name"));
    EXPECT_TRUE(map.contains("key/1969/name"));
    EXPECT_EQ(map["key/0/name"], "tcp/host10000.domain.tld:19099");
    EXPECT_EQ(map["key/123/name"], "tcp/host10123.domain.tld:19099");
    EXPECT_EQ(map["key/1983/name"], "tcp/host11983.domain.tld:19099");
    EXPECT_EQ(map["key/1969/name"], "tcp/woodstock:19069");
    EXPECT_EQ(map.size(), 1983ul);

    mirror.unregisterListener(observer);
}

GTEST_MAIN_RUN_ALL_TESTS()

<commit_msg>some minor test improvements<commit_after>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/slobrok/server/mock_map_listener.h>
#include <vespa/slobrok/server/service_map_mirror.h>
#include <vespa/vespalib/gtest/gtest.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <map>

using namespace vespalib;
using namespace slobrok;
using vespalib::make_string_short::fmt;

using Map = std::map<vespalib::string, vespalib::string>;

Map dump(const ServiceMapMirror &mirror) {
    Map result;
    for (const auto & entry : mirror.allMappings()) {
        result[entry.name] = entry.spec;
    }
    return result;
}

void addTo(ServiceMapMirror &target, const ServiceMapping &mapping) {
    auto cur = target.currentGeneration();
    std::vector<vespalib::string> removes = {};
    ServiceMappingList updates = { mapping };
    auto nxt = cur;
    nxt.add();
    MapDiff diff{cur, removes, updates, nxt};
    target.apply(diff);
}

void removeFrom(ServiceMapMirror &target, const ServiceMapping &mapping) {
    auto cur = target.currentGeneration();
    std::vector<vespalib::string> removes = { mapping.name };
    ServiceMappingList updates = { };
    auto nxt = cur;
    nxt.add();
    MapDiff diff{cur, removes, updates, nxt};
    target.apply(diff);
}

TEST(ServiceMapMirrorTest, empty_inspection) {
    ServiceMapMirror mirror;
    auto bar = dump(mirror);
    EXPECT_TRUE(bar.empty());

    MockMapListener observer;
    mirror.registerListener(observer);
    mirror.unregisterListener(observer);
    EXPECT_EQ(observer.last_event, MockEvent::NONE);
}

TEST(ServiceMapMirrorTest, full_inspection) {
    ServiceMapMirror mirror;
    MockMapListener observer;
    mirror.registerListener(observer);
    for (int i = 0; i < 1984; ++i) {
        EXPECT_EQ(mirror.currentGeneration(), GenCnt(i));
        auto name = fmt("key/%d/name", i);
        auto spec = fmt("tcp/host%d.domain.tld:19099", 10000+i);
        ServiceMapping toAdd{name, spec};
        addTo(mirror, toAdd);
        EXPECT_EQ(observer.last_event, MockEvent::ADD);
        EXPECT_EQ(observer.last_add, toAdd);
    }
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1984));
    ServiceMapping toRemove{"key/666/name", "tcp/host10666.domain.tld:19099"};
    removeFrom(mirror, toRemove);
    EXPECT_EQ(observer.last_event, MockEvent::REMOVE);
    EXPECT_EQ(observer.last_remove, toRemove);
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1985));

    ServiceMapping oldMapping{"key/1969/name", "tcp/host11969.domain.tld:19099"};
    ServiceMapping toUpdate{"key/1969/name", "tcp/woodstock:19069"};
    addTo(mirror, toUpdate);
    EXPECT_EQ(observer.last_event, MockEvent::UPDATE);
    EXPECT_EQ(observer.last_remove, oldMapping);
    EXPECT_EQ(observer.last_add, toUpdate);
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1986));

    auto map = dump(mirror);
    EXPECT_FALSE(map.contains("foo"));
    EXPECT_TRUE(map.contains("key/0/name"));
    EXPECT_FALSE(map.contains("key/666/name"));
    EXPECT_TRUE(map.contains("key/1983/name"));
    EXPECT_FALSE(map.contains("key/1984/name"));
    EXPECT_TRUE(map.contains("key/1969/name"));
    EXPECT_EQ(map["key/0/name"], "tcp/host10000.domain.tld:19099");
    EXPECT_EQ(map["key/123/name"], "tcp/host10123.domain.tld:19099");
    EXPECT_EQ(map["key/1983/name"], "tcp/host11983.domain.tld:19099");
    EXPECT_EQ(map["key/1969/name"], "tcp/woodstock:19069");
    EXPECT_EQ(map.size(), 1983ul);

    auto cur = mirror.currentGeneration();
    std::vector<vespalib::string> removes = {
        "key/123/name",
        "key/1983/name",
        "key/234/name",
        "key/345/name",
        "key/123/name",
        "key/456/name"
    };
    ServiceMappingList updates = {
        ServiceMapping{ "key/567/name", "bar/1/foo" },
        ServiceMapping{ "key/678/name", "bar/2/foo" },
        ServiceMapping{ "key/234/name", "bar/3/foo" },
        ServiceMapping{ "key/345/name", "bar/4/foo" },
        ServiceMapping{ "key/789/name", "bar/5/foo" },
        ServiceMapping{ "key/666/name", "bar/6/foo" },
        ServiceMapping{ "key/567/name", "bar/7/foo" }
    };
    auto nxt = cur;
    nxt.add();
    nxt.add();
    mirror.apply(MapDiff{cur, removes, updates, nxt});
    EXPECT_EQ(mirror.currentGeneration(), GenCnt(1988));
    map = dump(mirror);
    EXPECT_FALSE(map.contains("key/123/name"));
    EXPECT_FALSE(map.contains("key/1983/name"));
    EXPECT_FALSE(map.contains("key/456/name"));
    EXPECT_TRUE(map.contains("key/0/name"));
    EXPECT_TRUE(map.contains("key/234/name"));
    EXPECT_TRUE(map.contains("key/345/name"));
    EXPECT_TRUE(map.contains("key/567/name"));
    EXPECT_TRUE(map.contains("key/666/name"));
    EXPECT_TRUE(map.contains("key/678/name"));
    EXPECT_TRUE(map.contains("key/789/name"));
    EXPECT_EQ(map["key/234/name"], "bar/3/foo");
    EXPECT_EQ(map["key/345/name"], "bar/4/foo");
    EXPECT_EQ(map["key/567/name"], "bar/7/foo");
    EXPECT_EQ(map["key/666/name"], "bar/6/foo");
    EXPECT_EQ(map["key/678/name"], "bar/2/foo");
    EXPECT_EQ(map["key/789/name"], "bar/5/foo");
    EXPECT_EQ(map.size(), 1981ul);

    mirror.unregisterListener(observer);
}

GTEST_MAIN_RUN_ALL_TESTS()

<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// appleseed.renderer headers. Only include header files from renderer/api/.
#include "renderer/api/bsdf.h"
#include "renderer/api/camera.h"
#include "renderer/api/color.h"
#include "renderer/api/environment.h"
#include "renderer/api/environmentedf.h"
#include "renderer/api/environmentshader.h"
#include "renderer/api/frame.h"
#include "renderer/api/light.h"
#include "renderer/api/log.h"
#include "renderer/api/material.h"
#include "renderer/api/object.h"
#include "renderer/api/project.h"
#include "renderer/api/rendering.h"
#include "renderer/api/scene.h"
#include "renderer/api/surfaceshader.h"
#include "renderer/api/utility.h"

// appleseed.foundation headers.
#include "foundation/math/matrix.h"
#include "foundation/math/scalar.h"
#include "foundation/math/transform.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/log/consolelogtarget.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <cstddef>
#include <cstdio>
#include <memory>
#include <string>

// Define shorter namespaces for convenience.
namespace asf = foundation;
namespace asr = renderer;

asf::auto_release_ptr<asr::Project> build_project()
{
    // Create an empty project.
    asf::auto_release_ptr<asr::Project> project(asr::ProjectFactory::create("test project"));
    project->search_paths().push_back("data");

    // Add default configurations to the project.
    project->add_default_configurations();

    // Set the number of samples. This is the main quality parameter: the higher the
    // number of samples, the smoother the image but the longer the rendering time.
    project->configurations()
        .get_by_name("final")->get_parameters()
            .insert_path("uniform_pixel_renderer.samples", "25");

    // Create a scene.
    asf::auto_release_ptr<asr::Scene> scene(asr::SceneFactory::create());

    // Create an assembly.
    asf::auto_release_ptr<asr::Assembly> assembly(
        asr::AssemblyFactory::create(
            "assembly",
            asr::ParamArray()));

    //------------------------------------------------------------------------
    // Materials
    //------------------------------------------------------------------------

    // Create a color called "gray" and insert it into the assembly.
    static const float GrayReflectance[] = { 0.5f, 0.5f, 0.5f };
    assembly->colors().insert(
        asr::ColorEntityFactory::create(
            "gray",
            asr::ParamArray()
                .insert("color_space", "srgb"),
            asr::ColorValueArray(3, GrayReflectance)));

    // Create a BRDF called "diffuse_gray_brdf" and insert it into the assembly.
    assembly->bsdfs().insert(
        asr::LambertianBRDFFactory().create(
            "diffuse_gray_brdf",
            asr::ParamArray()
                .insert("reflectance", "gray")));

    // Create a physical surface shader and insert it into the assembly.
    assembly->surface_shaders().insert(
        asr::PhysicalSurfaceShaderFactory().create(
            "physical_surface_shader",
            asr::ParamArray()));

    // Create a material called "gray_material" and insert it into the assembly.
    assembly->materials().insert(
        asr::MaterialFactory::create(
            "gray_material",
            asr::ParamArray()
                .insert("surface_shader", "physical_surface_shader")
                .insert("bsdf", "diffuse_gray_brdf")));

    //------------------------------------------------------------------------
    // Geometry
    //------------------------------------------------------------------------

    // Load the scene geometry from disk.
    asr::MeshObjectArray objects;
    asr::MeshObjectReader::read(
        project->search_paths(),
        "cube",
        asr::ParamArray()
            .insert("filename", "scene.obj"),
        objects);

    // Insert all the objects into the assembly.
    for (size_t i = 0; i < objects.size(); ++i)
    {
        // Insert this object into the scene.
        asr::MeshObject* object = objects[i];
        assembly->objects().insert(asf::auto_release_ptr<asr::Object>(object));

        // Create an instance of this object and insert it into the assembly.
        const std::string instance_name = std::string(object->get_name()) + "_inst";
        assembly->object_instances().insert(
            asr::ObjectInstanceFactory::create(
                instance_name.c_str(),
                asr::ParamArray(),
                object->get_name(),
                asf::Transformd::identity(),
                asf::StringDictionary()
                    .insert("default", "gray_material")
                    .insert("default2", "gray_material")));
    }

    //------------------------------------------------------------------------
    // Light
    //------------------------------------------------------------------------

    // Create a color called "light_radiance" and insert it into the assembly.
    static const float LightRadiance[] = { 1.0f, 1.0f, 1.0f };
    assembly->colors().insert(
        asr::ColorEntityFactory::create(
            "light_radiance",
            asr::ParamArray()
                .insert("color_space", "srgb")
                .insert("multiplier", "30.0"),
            asr::ColorValueArray(3, LightRadiance)));

    // Create a point light called "light" and insert it into the assembly.
    asf::auto_release_ptr<asr::Light> light(
        asr::PointLightFactory().create(
            "light",
            asr::ParamArray()
                .insert("radiance", "light_radiance")));
    light->set_transform(
        asf::Transformd::from_local_to_parent(
            asf::Matrix4d::translation(asf::Vector3d(0.6, 2.0, 1.0))));
    assembly->lights().insert(light);

    // Create an instance of the assembly and insert it into the scene.
    asf::auto_release_ptr<asr::AssemblyInstance> assembly_instance(
        asr::AssemblyInstanceFactory::create(
            "assembly_inst",
            asr::ParamArray(),
            "assembly"));
    assembly_instance
        ->transform_sequence()
            .set_transform(
                0.0,
                asf::Transformd::identity());
    scene->assembly_instances().insert(assembly_instance);

    // Insert the assembly into the scene.
    scene->assemblies().insert(assembly);

    //------------------------------------------------------------------------
    // Environment
    //------------------------------------------------------------------------

    // Create a color called "sky_radiance" and insert it into the scene.
    static const float SkyRadiance[] = { 0.75f, 0.80f, 1.0f };
    scene->colors().insert(
        asr::ColorEntityFactory::create(
            "sky_radiance",
            asr::ParamArray()
                .insert("color_space", "srgb")
                .insert("multiplier", "0.5"),
            asr::ColorValueArray(3, SkyRadiance)));

    // Create an environment EDF called "sky_edf" and insert it into the scene.
    scene->environment_edfs().insert(
        asr::ConstantEnvironmentEDFFactory().create(
            "sky_edf",
            asr::ParamArray()
                .insert("radiance", "sky_radiance")));

    // Create an environment shader called "sky_shader" and insert it into the scene.
    scene->environment_shaders().insert(
        asr::EDFEnvironmentShaderFactory().create(
            "sky_shader",
            asr::ParamArray()
                .insert("environment_edf", "sky_edf")));

    // Create an environment called "sky" and bind it to the scene.
    scene->set_environment(
        asr::EnvironmentFactory::create(
            "sky",
            asr::ParamArray()
                .insert("environment_edf", "sky_edf")
                .insert("environment_shader", "sky_shader")));

    //------------------------------------------------------------------------
    // Camera
    //------------------------------------------------------------------------

    // Create a pinhole camera with film dimensions 0.980 x 0.735 in (24.892 x 18.669 mm).
    asf::auto_release_ptr<asr::Camera> camera(
        asr::PinholeCameraFactory().create(
            "camera",
            asr::ParamArray()
                .insert("film_dimensions", "0.024892 0.018669")
                .insert("focal_length", "0.035")));

    // Place and orient the camera. By default cameras are located in (0.0, 0.0, 0.0)
    // and are looking toward Z- (0.0, 0.0, -1.0).
    camera->transform_sequence().set_transform(
        0.0,
        asf::Transformd::from_local_to_parent(
            asf::Matrix4d::rotation(asf::Vector3d(1.0, 0.0, 0.0), asf::deg_to_rad(-20.0)) *
            asf::Matrix4d::translation(asf::Vector3d(0.0, 0.8, 11.0))));

    // Bind the camera to the scene.
    scene->set_camera(camera);

    //------------------------------------------------------------------------
    // Frame
    //------------------------------------------------------------------------

    // Create a frame and bind it to the project.
    project->set_frame(
        asr::FrameFactory::create(
            "beauty",
            asr::ParamArray()
                .insert("camera", scene->get_camera()->get_name())
                .insert("resolution", "640 480")
                .insert("color_space", "srgb")));

    // Bind the scene to the project.
    project->set_scene(scene);

    return project;
}

int main()
{
    // Create a log target that outputs to stderr, and binds it to the renderer's global logger.
    // Eventually you will probably want to redirect log messages to your own target. For this
    // you will need to implement foundation::ILogTarget (foundation/utility/log/ilogtarget.h).
    std::auto_ptr<asf::ILogTarget> log_target(asf::create_console_log_target(stderr));
    asr::global_logger().add_target(log_target.get());

    // Build the project.
    asf::auto_release_ptr<asr::Project> project(build_project());

    // Create the master renderer.
    asr::DefaultRendererController renderer_controller;
    asr::MasterRenderer renderer(
        project.ref(),
        project->configurations().get_by_name("final")->get_inherited_parameters(),
        &renderer_controller);

    // Render the frame.
    renderer.render();

    // Save the frame to disk.
    project->get_frame()->write_main_image("output/test.png");

    // Save the project to disk.
    asr::ProjectFileWriter::write(project.ref(), "output/test.appleseed");

    return 0;
}
<commit_msg>the devkit sample now starts by printing appleseed's version string.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// appleseed.renderer headers. Only include header files from renderer/api/.
#include "renderer/api/bsdf.h"
#include "renderer/api/camera.h"
#include "renderer/api/color.h"
#include "renderer/api/environment.h"
#include "renderer/api/environmentedf.h"
#include "renderer/api/environmentshader.h"
#include "renderer/api/frame.h"
#include "renderer/api/light.h"
#include "renderer/api/log.h"
#include "renderer/api/material.h"
#include "renderer/api/object.h"
#include "renderer/api/project.h"
#include "renderer/api/rendering.h"
#include "renderer/api/scene.h"
#include "renderer/api/surfaceshader.h"
#include "renderer/api/utility.h"

// appleseed.foundation headers.
#include "foundation/core/appleseed.h"
#include "foundation/math/matrix.h"
#include "foundation/math/scalar.h"
#include "foundation/math/transform.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/log/consolelogtarget.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/searchpaths.h"

// Standard headers.
#include <cstddef>
#include <cstdio>
#include <memory>
#include <string>

// Define shorter namespaces for convenience.
namespace asf = foundation;
namespace asr = renderer;

asf::auto_release_ptr<asr::Project> build_project()
{
    // Create an empty project.
    asf::auto_release_ptr<asr::Project> project(asr::ProjectFactory::create("test project"));
    project->search_paths().push_back("data");

    // Add default configurations to the project.
    project->add_default_configurations();

    // Set the number of samples. This is the main quality parameter: the higher the
    // number of samples, the smoother the image but the longer the rendering time.
    project->configurations()
        .get_by_name("final")->get_parameters()
            .insert_path("uniform_pixel_renderer.samples", "25");

    // Create a scene.
    asf::auto_release_ptr<asr::Scene> scene(asr::SceneFactory::create());

    // Create an assembly.
    asf::auto_release_ptr<asr::Assembly> assembly(
        asr::AssemblyFactory::create(
            "assembly",
            asr::ParamArray()));

    //------------------------------------------------------------------------
    // Materials
    //------------------------------------------------------------------------

    // Create a color called "gray" and insert it into the assembly.
    static const float GrayReflectance[] = { 0.5f, 0.5f, 0.5f };
    assembly->colors().insert(
        asr::ColorEntityFactory::create(
            "gray",
            asr::ParamArray()
                .insert("color_space", "srgb"),
            asr::ColorValueArray(3, GrayReflectance)));

    // Create a BRDF called "diffuse_gray_brdf" and insert it into the assembly.
    assembly->bsdfs().insert(
        asr::LambertianBRDFFactory().create(
            "diffuse_gray_brdf",
            asr::ParamArray()
                .insert("reflectance", "gray")));

    // Create a physical surface shader and insert it into the assembly.
    assembly->surface_shaders().insert(
        asr::PhysicalSurfaceShaderFactory().create(
            "physical_surface_shader",
            asr::ParamArray()));

    // Create a material called "gray_material" and insert it into the assembly.
    assembly->materials().insert(
        asr::MaterialFactory::create(
            "gray_material",
            asr::ParamArray()
                .insert("surface_shader", "physical_surface_shader")
                .insert("bsdf", "diffuse_gray_brdf")));

    //------------------------------------------------------------------------
    // Geometry
    //------------------------------------------------------------------------

    // Load the scene geometry from disk.
    asr::MeshObjectArray objects;
    asr::MeshObjectReader::read(
        project->search_paths(),
        "cube",
        asr::ParamArray()
            .insert("filename", "scene.obj"),
        objects);

    // Insert all the objects into the assembly.
    for (size_t i = 0; i < objects.size(); ++i)
    {
        // Insert this object into the scene.
        asr::MeshObject* object = objects[i];
        assembly->objects().insert(asf::auto_release_ptr<asr::Object>(object));

        // Create an instance of this object and insert it into the assembly.
        const std::string instance_name = std::string(object->get_name()) + "_inst";
        assembly->object_instances().insert(
            asr::ObjectInstanceFactory::create(
                instance_name.c_str(),
                asr::ParamArray(),
                object->get_name(),
                asf::Transformd::identity(),
                asf::StringDictionary()
                    .insert("default", "gray_material")
                    .insert("default2", "gray_material")));
    }

    //------------------------------------------------------------------------
    // Light
    //------------------------------------------------------------------------

    // Create a color called "light_radiance" and insert it into the assembly.
    static const float LightRadiance[] = { 1.0f, 1.0f, 1.0f };
    assembly->colors().insert(
        asr::ColorEntityFactory::create(
            "light_radiance",
            asr::ParamArray()
                .insert("color_space", "srgb")
                .insert("multiplier", "30.0"),
            asr::ColorValueArray(3, LightRadiance)));

    // Create a point light called "light" and insert it into the assembly.
    asf::auto_release_ptr<asr::Light> light(
        asr::PointLightFactory().create(
            "light",
            asr::ParamArray()
                .insert("radiance", "light_radiance")));
    light->set_transform(
        asf::Transformd::from_local_to_parent(
            asf::Matrix4d::translation(asf::Vector3d(0.6, 2.0, 1.0))));
    assembly->lights().insert(light);

    // Create an instance of the assembly and insert it into the scene.
    asf::auto_release_ptr<asr::AssemblyInstance> assembly_instance(
        asr::AssemblyInstanceFactory::create(
            "assembly_inst",
            asr::ParamArray(),
            "assembly"));
    assembly_instance
        ->transform_sequence()
            .set_transform(
                0.0,
                asf::Transformd::identity());
    scene->assembly_instances().insert(assembly_instance);

    // Insert the assembly into the scene.
    scene->assemblies().insert(assembly);

    //------------------------------------------------------------------------
    // Environment
    //------------------------------------------------------------------------

    // Create a color called "sky_radiance" and insert it into the scene.
    static const float SkyRadiance[] = { 0.75f, 0.80f, 1.0f };
    scene->colors().insert(
        asr::ColorEntityFactory::create(
            "sky_radiance",
            asr::ParamArray()
                .insert("color_space", "srgb")
                .insert("multiplier", "0.5"),
            asr::ColorValueArray(3, SkyRadiance)));

    // Create an environment EDF called "sky_edf" and insert it into the scene.
    scene->environment_edfs().insert(
        asr::ConstantEnvironmentEDFFactory().create(
            "sky_edf",
            asr::ParamArray()
                .insert("radiance", "sky_radiance")));

    // Create an environment shader called "sky_shader" and insert it into the scene.
    scene->environment_shaders().insert(
        asr::EDFEnvironmentShaderFactory().create(
            "sky_shader",
            asr::ParamArray()
                .insert("environment_edf", "sky_edf")));

    // Create an environment called "sky" and bind it to the scene.
    scene->set_environment(
        asr::EnvironmentFactory::create(
            "sky",
            asr::ParamArray()
                .insert("environment_edf", "sky_edf")
                .insert("environment_shader", "sky_shader")));

    //------------------------------------------------------------------------
    // Camera
    //------------------------------------------------------------------------

    // Create a pinhole camera with film dimensions 0.980 x 0.735 in (24.892 x 18.669 mm).
    asf::auto_release_ptr<asr::Camera> camera(
        asr::PinholeCameraFactory().create(
            "camera",
            asr::ParamArray()
                .insert("film_dimensions", "0.024892 0.018669")
                .insert("focal_length", "0.035")));

    // Place and orient the camera. By default cameras are located in (0.0, 0.0, 0.0)
    // and are looking toward Z- (0.0, 0.0, -1.0).
    camera->transform_sequence().set_transform(
        0.0,
        asf::Transformd::from_local_to_parent(
            asf::Matrix4d::rotation(asf::Vector3d(1.0, 0.0, 0.0), asf::deg_to_rad(-20.0)) *
            asf::Matrix4d::translation(asf::Vector3d(0.0, 0.8, 11.0))));

    // Bind the camera to the scene.
    scene->set_camera(camera);

    //------------------------------------------------------------------------
    // Frame
    //------------------------------------------------------------------------

    // Create a frame and bind it to the project.
    project->set_frame(
        asr::FrameFactory::create(
            "beauty",
            asr::ParamArray()
                .insert("camera", scene->get_camera()->get_name())
                .insert("resolution", "640 480")
                .insert("color_space", "srgb")));

    // Bind the scene to the project.
    project->set_scene(scene);

    return project;
}

int main()
{
    // Create a log target that outputs to stderr, and binds it to the renderer's global logger.
    // Eventually you will probably want to redirect log messages to your own target. For this
    // you will need to implement foundation::ILogTarget (foundation/utility/log/ilogtarget.h).
    std::auto_ptr<asf::ILogTarget> log_target(asf::create_console_log_target(stderr));
    asr::global_logger().add_target(log_target.get());

    // Print appleseed's version string.
    RENDERER_LOG_INFO("%s", asf::Appleseed::get_synthetic_version_string());

    // Build the project.
    asf::auto_release_ptr<asr::Project> project(build_project());

    // Create the master renderer.
    asr::DefaultRendererController renderer_controller;
    asr::MasterRenderer renderer(
        project.ref(),
        project->configurations().get_by_name("final")->get_inherited_parameters(),
        &renderer_controller);

    // Render the frame.
    renderer.render();

    // Save the frame to disk.
    project->get_frame()->write_main_image("output/test.png");

    // Save the project to disk.
    asr::ProjectFileWriter::write(project.ref(), "output/test.appleseed");

    return 0;
}
<|endoftext|>


<commit_before>// This file is part of playd.
// playd is licensed under the MIT licence: see LICENSE.txt.

/**
 * @file
 * Implementation of the PaAudioSystem class.
 * @see audio/audio_system.hpp
 */

#include <algorithm>
#include <cassert>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>

#include "portaudiocpp/PortAudioCpp.hxx"

#include "../errors.hpp"
#include "../messages.h"
#include "audio.hpp"
#include "audio_sink.hpp"
#include "audio_source.hpp"
#include "audio_system.hpp"
#include "sample_formats.hpp"

#include "sources/flac.hpp"
#include "sources/mp3.hpp"
#include "sources/sndfile.hpp"

PaAudioSystem::PaAudioSystem()
{
	portaudio::System::initialize();

#ifndef NO_MP3
	mpg123_init();
#endif // NO_MP3

	this->device_id = -1;
}

PaAudioSystem::~PaAudioSystem()
{
	portaudio::System::terminate();

#ifndef NO_MP3
	mpg123_exit();
#endif // NO_MP3
}

std::vector<AudioSystem::Device> PaAudioSystem::GetDevicesInfo()
{
	auto &pa = portaudio::System::instance();
	std::vector<AudioSystem::Device> list;

	for (auto d = pa.devicesBegin(); d != pa.devicesEnd(); ++d) {
		if (!d->isInputOnlyDevice()) {
			list.emplace_back(d->index(), d->name());
		}
	}
	return list;
}

bool PaAudioSystem::IsOutputDevice(int id)
{
	auto &pa = portaudio::System::instance();
	if (id < 0 || id >= pa.deviceCount()) return false;

	portaudio::Device &dev = pa.deviceByIndex(id);
	return !dev.isInputOnlyDevice();
}

void PaAudioSystem::SetDeviceID(int id)
{
	this->device_id = id;
}

Audio *PaAudioSystem::Load(const std::string &path) const
{
	AudioSource *source = this->LoadSource(path);
	assert(source != nullptr);

	auto sink = new AudioSink(*source, this->device_id);
	return new PipeAudio(source, sink);
}

AudioSource *PaAudioSystem::LoadSource(const std::string &path) const
{
	size_t extpoint = path.find_last_of('.');
	std::string ext = path.substr(extpoint + 1);

#ifndef NO_FLAC
	if (ext == "flac") {
		Debug() << "Using FlacAudioSource" << std::endl;
		return new FlacAudioSource(path);
	}
#endif

#ifndef NO_MP3
	if (ext == "mp3") {
		Debug() << "Using Mp3AudioSource" << std::endl;
		return new Mp3AudioSource(path);
	}
#endif

#ifndef NO_SNDFILE
	Debug() << "Using SndfileAudioSource" << std::endl;
	return new SndfileAudioSource(path);
#endif

	throw FileError("Unknown file format: " + ext);
}

<commit_msg>Initialise-list device_id.<commit_after>// This file is part of playd.
// playd is licensed under the MIT licence: see LICENSE.txt.

/**
 * @file
 * Implementation of the PaAudioSystem class.
 * @see audio/audio_system.hpp
 */

#include <algorithm>
#include <cassert>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>

#include "portaudiocpp/PortAudioCpp.hxx"

#include "../errors.hpp"
#include "../messages.h"
#include "audio.hpp"
#include "audio_sink.hpp"
#include "audio_source.hpp"
#include "audio_system.hpp"
#include "sample_formats.hpp"

#include "sources/flac.hpp"
#include "sources/mp3.hpp"
#include "sources/sndfile.hpp"

PaAudioSystem::PaAudioSystem() : device_id(-1)
{
	portaudio::System::initialize();

#ifndef NO_MP3
	mpg123_init();
#endif // NO_MP3
}

PaAudioSystem::~PaAudioSystem()
{
	portaudio::System::terminate();

#ifndef NO_MP3
	mpg123_exit();
#endif // NO_MP3
}

std::vector<AudioSystem::Device> PaAudioSystem::GetDevicesInfo()
{
	auto &pa = portaudio::System::instance();
	std::vector<AudioSystem::Device> list;

	for (auto d = pa.devicesBegin(); d != pa.devicesEnd(); ++d) {
		if (!d->isInputOnlyDevice()) {
			list.emplace_back(d->index(), d->name());
		}
	}
	return list;
}

bool PaAudioSystem::IsOutputDevice(int id)
{
	auto &pa = portaudio::System::instance();
	if (id < 0 || id >= pa.deviceCount()) return false;

	portaudio::Device &dev = pa.deviceByIndex(id);
	return !dev.isInputOnlyDevice();
}

void PaAudioSystem::SetDeviceID(int id)
{
	this->device_id = id;
}

Audio *PaAudioSystem::Load(const std::string &path) const
{
	AudioSource *source = this->LoadSource(path);
	assert(source != nullptr);

	auto sink = new AudioSink(*source, this->device_id);
	return new PipeAudio(source, sink);
}

AudioSource *PaAudioSystem::LoadSource(const std::string &path) const
{
	size_t extpoint = path.find_last_of('.');
	std::string ext = path.substr(extpoint + 1);

#ifndef NO_FLAC
	if (ext == "flac") {
		Debug() << "Using FlacAudioSource" << std::endl;
		return new FlacAudioSource(path);
	}
#endif

#ifndef NO_MP3
	if (ext == "mp3") {
		Debug() << "Using Mp3AudioSource" << std::endl;
		return new Mp3AudioSource(path);
	}
#endif

#ifndef NO_SNDFILE
	Debug() << "Using SndfileAudioSource" << std::endl;
	return new SndfileAudioSource(path);
#endif

	throw FileError("Unknown file format: " + ext);
}

<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3008
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 2005845 by chui@ocl-promo-incrementor on 2019/09/28 03:00:41<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3009
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2090
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1256294 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/04/11 03:00:11<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2091
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1721
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1115982 by johtaylo@johtaylo-JTBUILDER03-increment on 2015/01/28 03:00:14<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 1722
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>