<commit_before>#include <gtest/gtest.h>

#include <nnpack.h>

#include <testers/pooling.h>

/*
 * Test that implementation works for a single-channel image with a single-pool
 */

TEST(MaxPooling2x2, single_pool) {
	PoolingTester()
		.inputSize(2, 2)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100)
		.testOutput();
}

/*
 * Test that implementation works for a single-channel image with few horizontal pools
 */

TEST(MaxPooling2x2, few_horizontal_pools) {
	for (size_t imageWidth = 4; imageWidth <= 50; imageWidth += 2) {
		PoolingTester()
			.inputSize(2, imageWidth)
			.poolingSize(2, 2)
			.poolingStride(2, 2)
			.iterations(100)
			.testOutput();
	}
}

/*
 * Test that implementation works for a single-channel image with few vertical pools
 */

TEST(MaxPooling2x2, few_vertical_pools) {
	for (size_t imageHeight = 4; imageHeight <= 50; imageHeight += 2) {
		PoolingTester()
			.inputSize(imageHeight, 2)
			.poolingSize(2, 2)
			.poolingStride(2, 2)
			.iterations(100)
			.testOutput();
	}
}

/*
 * Test that implementation works for a single-channel image with multiple horizontal and vertical pools
 */

TEST(MaxPooling2x2, large_image) {
	PoolingTester()
		.inputSize(128, 128)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100)
		.testOutput();
}

/*
 * Test that implementation works for a single-channel image with size which is not perfectly divisible by the pool size
 */

TEST(MaxPooling2x2, indivisible_size) {
	PoolingTester()
		.inputSize(5, 5)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100)
		.testOutput();
}

/*
 * Test that implementation works for a single-channel image with implicit padding
 */

TEST(MaxPooling2x2, DISABLED_implicit_padding) {
	PoolingTester tester;
	tester.inputSize(24, 24)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100);
	for (size_t paddingTop = 0; paddingTop < tester.kernelHeight(); paddingTop++) {
		for (size_t paddingRight = 0; paddingRight < tester.kernelWidth(); paddingRight++) {
			for (size_t paddingLeft = 0; paddingLeft < tester.kernelWidth(); paddingLeft++) {
				for (size_t paddingBottom = 0; paddingBottom < tester.kernelHeight(); paddingBottom++) {
					tester.inputPadding(paddingTop, paddingRight, paddingLeft, paddingBottom)
						.testOutput();
				}
			}
		}
	}
}

/*
 * Test that implementation can handle small non-unit batch_size
 */

TEST(MaxPooling2x2, small_batch) {
	PoolingTester tester;
	tester.inputSize(12, 12)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100);
	for (size_t batchSize = 2; batchSize <= 5; batchSize++) {
		tester.batchSize(batchSize)
			.testOutput();
	}
}

/*
 * Test that implementation can handle small non-unit number of channels
 */

TEST(MaxPooling2x2, few_channels) {
	PoolingTester tester;
	tester.inputSize(12, 12)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100);
	for (size_t channels = 2; channels <= 5; channels++) {
		tester.channels(channels)
			.testOutput();
	}
}

int main(int argc, char* argv[]) {
	const enum nnp_status init_status = nnp_initialize();
	assert(init_status == nnp_status_success);
	setenv("TERM", "xterm-256color", 0);
	::testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}
<commit_msg>Test: fix compilation error in max-pooling output test<commit_after>#include <gtest/gtest.h>

#include <nnpack.h>

#include <testers/pooling.h>

/*
 * Test that implementation works for a single-channel image with a single-pool
 */

TEST(MaxPooling2x2, single_pool) {
	PoolingTester()
		.inputSize(2, 2)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100)
		.testOutput();
}

/*
 * Test that implementation works for a single-channel image with few horizontal pools
 */

TEST(MaxPooling2x2, few_horizontal_pools) {
	for (size_t imageWidth = 4; imageWidth <= 50; imageWidth += 2) {
		PoolingTester()
			.inputSize(2, imageWidth)
			.poolingSize(2, 2)
			.poolingStride(2, 2)
			.iterations(100)
			.testOutput();
	}
}

/*
 * Test that implementation works for a single-channel image with few vertical pools
 */

TEST(MaxPooling2x2, few_vertical_pools) {
	for (size_t imageHeight = 4; imageHeight <= 50; imageHeight += 2) {
		PoolingTester()
			.inputSize(imageHeight, 2)
			.poolingSize(2, 2)
			.poolingStride(2, 2)
			.iterations(100)
			.testOutput();
	}
}

/*
 * Test that implementation works for a single-channel image with multiple horizontal and vertical pools
 */

TEST(MaxPooling2x2, large_image) {
	PoolingTester()
		.inputSize(128, 128)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100)
		.testOutput();
}

/*
 * Test that implementation works for a single-channel image with size which is not perfectly divisible by the pool size
 */

TEST(MaxPooling2x2, indivisible_size) {
	PoolingTester()
		.inputSize(5, 5)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100)
		.testOutput();
}

/*
 * Test that implementation works for a single-channel image with implicit padding
 */

TEST(MaxPooling2x2, DISABLED_implicit_padding) {
	PoolingTester tester;
	tester.inputSize(24, 24)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100);
	for (size_t paddingTop = 0; paddingTop < tester.poolingHeight(); paddingTop++) {
		for (size_t paddingRight = 0; paddingRight < tester.poolingWidth(); paddingRight++) {
			for (size_t paddingLeft = 0; paddingLeft < tester.poolingWidth(); paddingLeft++) {
				for (size_t paddingBottom = 0; paddingBottom < tester.poolingHeight(); paddingBottom++) {
					tester.inputPadding(paddingTop, paddingRight, paddingLeft, paddingBottom)
						.testOutput();
				}
			}
		}
	}
}

/*
 * Test that implementation can handle small non-unit batch_size
 */

TEST(MaxPooling2x2, small_batch) {
	PoolingTester tester;
	tester.inputSize(12, 12)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100);
	for (size_t batchSize = 2; batchSize <= 5; batchSize++) {
		tester.batchSize(batchSize)
			.testOutput();
	}
}

/*
 * Test that implementation can handle small non-unit number of channels
 */

TEST(MaxPooling2x2, few_channels) {
	PoolingTester tester;
	tester.inputSize(12, 12)
		.poolingSize(2, 2)
		.poolingStride(2, 2)
		.iterations(100);
	for (size_t channels = 2; channels <= 5; channels++) {
		tester.channels(channels)
			.testOutput();
	}
}

int main(int argc, char* argv[]) {
	const enum nnp_status init_status = nnp_initialize();
	assert(init_status == nnp_status_success);
	setenv("TERM", "xterm-256color", 0);
	::testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/experimental/symbolizer/StackTrace.h>

#include <memory>

#include <folly/CppAttributes.h>
#include <folly/Portability.h>
#include <folly/portability/Config.h>

#if FOLLY_HAVE_LIBUNWIND
// Must be first to ensure that UNW_LOCAL_ONLY is defined
#define UNW_LOCAL_ONLY 1
#include <libunwind.h>
#endif

#if FOLLY_HAVE_BACKTRACE
#include <execinfo.h>
#endif

namespace folly {
namespace symbolizer {

ssize_t getStackTrace(
    FOLLY_MAYBE_UNUSED uintptr_t* addresses,
    FOLLY_MAYBE_UNUSED size_t maxAddresses) {
  static_assert(
      sizeof(uintptr_t) == sizeof(void*), "uintptr_t / pointer size mismatch");
  // The libunwind documentation says that unw_backtrace is
  // async-signal-safe but, as of libunwind 1.0.1, it isn't
  // (tdep_trace allocates memory on x86_64)
  //
  // There are two major variants of libunwind. libunwind on Linux
  // (https://www.nongnu.org/libunwind/) provides unw_backtrace, and
  // Apache/LLVM libunwind (notably used on Apple platforms)
  // doesn't. They can be distinguished with the UNW_VERSION #define.
  //
  // When unw_backtrace is not available, fall back on the standard
  // `backtrace` function from execinfo.h.
#if FOLLY_HAVE_LIBUNWIND && defined(UNW_VERSION)
  int r = unw_backtrace(reinterpret_cast<void**>(addresses), maxAddresses);
  return r < 0 ? -1 : r;
#elif FOLLY_HAVE_BACKTRACE
  int r = backtrace(reinterpret_cast<void**>(addresses), maxAddresses);
  return r < 0 ? -1 : r;
#else
  return -1;
#endif
}

namespace {

#if FOLLY_HAVE_LIBUNWIND

inline bool getFrameInfo(unw_cursor_t* cursor, uintptr_t& ip) {
  unw_word_t uip;
  if (unw_get_reg(cursor, UNW_REG_IP, &uip) < 0) {
    return false;
  }
  int r = unw_is_signal_frame(cursor);
  if (r < 0) {
    return false;
  }
  // Use previous instruction in normal (call) frames (because the
  // return address might not be in the same function for noreturn functions)
  // but not in signal frames.
  ip = uip - (r == 0);
  return true;
}

FOLLY_ALWAYS_INLINE
ssize_t getStackTraceInPlace(
    unw_context_t& context,
    unw_cursor_t& cursor,
    uintptr_t* addresses,
    size_t maxAddresses) {
  if (maxAddresses == 0) {
    return 0;
  }
  if (unw_getcontext(&context) < 0) {
    return -1;
  }
  if (unw_init_local(&cursor, &context) < 0) {
    return -1;
  }
  if (!getFrameInfo(&cursor, *addresses)) {
    return -1;
  }
  ++addresses;
  size_t count = 1;
  for (; count != maxAddresses; ++count, ++addresses) {
    int r = unw_step(&cursor);
    if (r < 0) {
      return -1;
    }
    if (r == 0) {
      break;
    }
    if (!getFrameInfo(&cursor, *addresses)) {
      return -1;
    }
  }
  return count;
}

#endif // FOLLY_HAVE_LIBUNWIND

} // namespace

ssize_t getStackTraceSafe(
    FOLLY_MAYBE_UNUSED uintptr_t* addresses,
    FOLLY_MAYBE_UNUSED size_t maxAddresses) {
#if FOLLY_HAVE_LIBUNWIND
  unw_context_t context;
  unw_cursor_t cursor;
  return getStackTraceInPlace(context, cursor, addresses, maxAddresses);
#else
  return -1;
#endif
}

ssize_t getStackTraceHeap(
    FOLLY_MAYBE_UNUSED uintptr_t* addresses,
    FOLLY_MAYBE_UNUSED size_t maxAddresses) {
#if FOLLY_HAVE_LIBUNWIND
  struct Ctx {
    unw_context_t context;
    unw_cursor_t cursor;
  };
  auto ctx_ptr = std::make_unique<Ctx>();
  if (!ctx_ptr) {
    return -1;
  }
  return getStackTraceInPlace(
      ctx_ptr->context, ctx_ptr->cursor, addresses, maxAddresses);
#else
  return -1;
#endif
}
} // namespace symbolizer
} // namespace folly
<commit_msg>Allow symbolizer to fall back to getStackTraceSafe<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/experimental/symbolizer/StackTrace.h>

#include <memory>

#include <folly/CppAttributes.h>
#include <folly/Portability.h>
#include <folly/portability/Config.h>

#if FOLLY_HAVE_LIBUNWIND
// Must be first to ensure that UNW_LOCAL_ONLY is defined
#define UNW_LOCAL_ONLY 1
#include <libunwind.h>
#endif

#if FOLLY_HAVE_BACKTRACE
#include <execinfo.h>
#endif

namespace folly {
namespace symbolizer {

ssize_t getStackTrace(
    FOLLY_MAYBE_UNUSED uintptr_t* addresses,
    FOLLY_MAYBE_UNUSED size_t maxAddresses) {
  static_assert(
      sizeof(uintptr_t) == sizeof(void*), "uintptr_t / pointer size mismatch");
  // The libunwind documentation says that unw_backtrace is
  // async-signal-safe but, as of libunwind 1.0.1, it isn't
  // (tdep_trace allocates memory on x86_64)
  //
  // There are two major variants of libunwind. libunwind on Linux
  // (https://www.nongnu.org/libunwind/) provides unw_backtrace, and
  // Apache/LLVM libunwind (notably used on Apple platforms)
  // doesn't. They can be distinguished with the UNW_VERSION #define.
  //
  // When unw_backtrace is not available, fall back on the standard
  // `backtrace` function from execinfo.h.
#if FOLLY_HAVE_LIBUNWIND && defined(UNW_VERSION)
  int r = unw_backtrace(reinterpret_cast<void**>(addresses), maxAddresses);
  return r < 0 ? -1 : r;
#elif FOLLY_HAVE_BACKTRACE
  int r = backtrace(reinterpret_cast<void**>(addresses), maxAddresses);
  return r < 0 ? -1 : r;
#elif FOLLY_HAVE_LIBUNWIND
  return getStackTraceSafe(addresses, maxAddresses);
#else
  return -1;
#endif
}

namespace {

#if FOLLY_HAVE_LIBUNWIND

inline bool getFrameInfo(unw_cursor_t* cursor, uintptr_t& ip) {
  unw_word_t uip;
  if (unw_get_reg(cursor, UNW_REG_IP, &uip) < 0) {
    return false;
  }
  int r = unw_is_signal_frame(cursor);
  if (r < 0) {
    return false;
  }
  // Use previous instruction in normal (call) frames (because the
  // return address might not be in the same function for noreturn functions)
  // but not in signal frames.
  ip = uip - (r == 0);
  return true;
}

FOLLY_ALWAYS_INLINE
ssize_t getStackTraceInPlace(
    unw_context_t& context,
    unw_cursor_t& cursor,
    uintptr_t* addresses,
    size_t maxAddresses) {
  if (maxAddresses == 0) {
    return 0;
  }
  if (unw_getcontext(&context) < 0) {
    return -1;
  }
  if (unw_init_local(&cursor, &context) < 0) {
    return -1;
  }
  if (!getFrameInfo(&cursor, *addresses)) {
    return -1;
  }
  ++addresses;
  size_t count = 1;
  for (; count != maxAddresses; ++count, ++addresses) {
    int r = unw_step(&cursor);
    if (r < 0) {
      return -1;
    }
    if (r == 0) {
      break;
    }
    if (!getFrameInfo(&cursor, *addresses)) {
      return -1;
    }
  }
  return count;
}

#endif // FOLLY_HAVE_LIBUNWIND

} // namespace

ssize_t getStackTraceSafe(
    FOLLY_MAYBE_UNUSED uintptr_t* addresses,
    FOLLY_MAYBE_UNUSED size_t maxAddresses) {
#if FOLLY_HAVE_LIBUNWIND
  unw_context_t context;
  unw_cursor_t cursor;
  return getStackTraceInPlace(context, cursor, addresses, maxAddresses);
#else
  return -1;
#endif
}

ssize_t getStackTraceHeap(
    FOLLY_MAYBE_UNUSED uintptr_t* addresses,
    FOLLY_MAYBE_UNUSED size_t maxAddresses) {
#if FOLLY_HAVE_LIBUNWIND
  struct Ctx {
    unw_context_t context;
    unw_cursor_t cursor;
  };
  auto ctx_ptr = std::make_unique<Ctx>();
  if (!ctx_ptr) {
    return -1;
  }
  return getStackTraceInPlace(
      ctx_ptr->context, ctx_ptr->cursor, addresses, maxAddresses);
#else
  return -1;
#endif
}
} // namespace symbolizer
} // namespace folly
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#ifdef _WIN32
#define _WINSOCKAPI_ // to include Winsock2.h instead of Winsock.h from windows.h
#include <winsock2.h>

#if defined(__GNUC__) || defined(__MINGW32__)
extern "C" {
    WINSOCK_API_LINKAGE  INT WSAAPI inet_pton( INT Family, PCSTR pszAddrString, PVOID pAddrBuf);
    WINSOCK_API_LINKAGE  PCSTR WSAAPI inet_ntop(INT  Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize);
}
#endif

#define INC__WIN_WINTIME // exclude gettimeofday from srt headers
#endif

#include "srt.h"

TEST(Core, ConnectionTimeout) {
    ASSERT_EQ(srt_startup(), 0);

    const SRTSOCKET client_sock = srt_socket(AF_INET, SOCK_DGRAM, 0);
    ASSERT_GT(client_sock, 0);    // socket_id should be > 0

    // First let's check the default connection timeout value.
    // It should be 3 seconds (3000 ms)
    int conn_timeout     = 0;
    int conn_timeout_len = sizeof conn_timeout;
    EXPECT_EQ(srt_getsockopt(client_sock, 0, SRTO_CONNTIMEO, &conn_timeout, &conn_timeout_len), SRT_SUCCESS);
    EXPECT_EQ(conn_timeout, 3000);

    // Set connection timeout to 500 ms to reduce the test execution time
    const int connection_timeout_ms = 500;
    EXPECT_EQ(srt_setsockopt(client_sock, 0, SRTO_CONNTIMEO, &connection_timeout_ms, sizeof connection_timeout_ms), SRT_SUCCESS);

    const int yes = 1;
    const int no = 0;
    ASSERT_EQ(srt_setsockopt(client_sock, 0, SRTO_RCVSYN,    &no,  sizeof no),  SRT_SUCCESS); // for async connect
    ASSERT_EQ(srt_setsockopt(client_sock, 0, SRTO_SNDSYN,    &no,  sizeof no),  SRT_SUCCESS); // for async connect
    ASSERT_EQ(srt_setsockopt(client_sock, 0, SRTO_TSBPDMODE, &yes, sizeof yes), SRT_SUCCESS);
    ASSERT_EQ(srt_setsockflag(client_sock,   SRTO_SENDER,    &yes, sizeof yes), SRT_SUCCESS);

    const int pollid = srt_epoll_create();
    ASSERT_GE(pollid, 0);
    const int epoll_out = SRT_EPOLL_OUT | SRT_EPOLL_ERR;
    ASSERT_NE(srt_epoll_add_usock(pollid, client_sock, &epoll_out), SRT_ERROR);

    sockaddr_in sa;
    memset(&sa, 0, sizeof sa);
    sa.sin_family = AF_INET;
    sa.sin_port = htons(5555);

    ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr), 1);

    sockaddr* psa = (sockaddr*)&sa;
    ASSERT_NE(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);

    // Socket readiness for connection is checked by polling on WRITE allowed sockets.
    {
        int rlen = 2;
        SRTSOCKET read[2];

        int wlen = 2;
        SRTSOCKET write[2];

        // Here we check the connection timeout.
        // Epoll timeout is set 100 ms greater than socket's TTL
        EXPECT_EQ(srt_epoll_wait(pollid, read, &rlen,
                                 write, &wlen,
                                 connection_timeout_ms + 100,   // +100 ms
                                 0, 0, 0, 0)
        /* Expected return value is 2. We have only 1 socket, but
         * sockets with exceptions are returned to both read and write sets.
        */
                 , 2);

        EXPECT_EQ(rlen, 1);
        EXPECT_EQ(read[0], client_sock);
        EXPECT_EQ(wlen, 1);
        EXPECT_EQ(write[0], client_sock);
    }

    EXPECT_EQ(srt_epoll_remove_usock(pollid, client_sock), SRT_SUCCESS);
    EXPECT_EQ(srt_close(client_sock), SRT_SUCCESS);
    (void)srt_epoll_release(pollid);
    (void)srt_cleanup();
}
<commit_msg>[tests] Added +/-30 ms confidence interval for connection timeout check<commit_after>#include <gtest/gtest.h>
#include <chrono>

#ifdef _WIN32
#define _WINSOCKAPI_ // to include Winsock2.h instead of Winsock.h from windows.h
#include <winsock2.h>

#if defined(__GNUC__) || defined(__MINGW32__)
extern "C" {
    WINSOCK_API_LINKAGE  INT WSAAPI inet_pton( INT Family, PCSTR pszAddrString, PVOID pAddrBuf);
    WINSOCK_API_LINKAGE  PCSTR WSAAPI inet_ntop(INT  Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize);
}
#endif

#define INC__WIN_WINTIME // exclude gettimeofday from srt headers
#endif

#include "srt.h"

/**
 * The test creates a socket and tries to connect to a localhost port 5555
 * in a non-blocking mode. This means we wait on epoll for a notification
 * about SRT_EPOLL_OUT | SRT_EPOLL_ERR events on the socket calling srt_epoll_wait(...).
 * The test expects a connection timeout to happen within the time,
 * set with SRTO_CONNTIMEO (500 ms).
 * The expected behavior is to return from srt_epoll_wait(...)
 *
 * @remarks  Inspired by Max Tomilov (maxtomilov) in issue #468
*/
TEST(Core, ConnectionTimeout) {
    ASSERT_EQ(srt_startup(), 0);

    const SRTSOCKET client_sock = srt_socket(AF_INET, SOCK_DGRAM, 0);
    ASSERT_GT(client_sock, 0);    // socket_id should be > 0

    // First let's check the default connection timeout value.
    // It should be 3 seconds (3000 ms)
    int conn_timeout     = 0;
    int conn_timeout_len = sizeof conn_timeout;
    EXPECT_EQ(srt_getsockopt(client_sock, 0, SRTO_CONNTIMEO, &conn_timeout, &conn_timeout_len), SRT_SUCCESS);
    EXPECT_EQ(conn_timeout, 3000);

    // Set connection timeout to 500 ms to reduce the test execution time
    const int connection_timeout_ms = 500;
    EXPECT_EQ(srt_setsockopt(client_sock, 0, SRTO_CONNTIMEO, &connection_timeout_ms, sizeof connection_timeout_ms), SRT_SUCCESS);

    const int yes = 1;
    const int no = 0;
    ASSERT_EQ(srt_setsockopt(client_sock, 0, SRTO_RCVSYN,    &no,  sizeof no),  SRT_SUCCESS); // for async connect
    ASSERT_EQ(srt_setsockopt(client_sock, 0, SRTO_SNDSYN,    &no,  sizeof no),  SRT_SUCCESS); // for async connect
    ASSERT_EQ(srt_setsockopt(client_sock, 0, SRTO_TSBPDMODE, &yes, sizeof yes), SRT_SUCCESS);
    ASSERT_EQ(srt_setsockflag(client_sock,   SRTO_SENDER,    &yes, sizeof yes), SRT_SUCCESS);

    const int pollid = srt_epoll_create();
    ASSERT_GE(pollid, 0);
    const int epoll_out = SRT_EPOLL_OUT | SRT_EPOLL_ERR;
    ASSERT_NE(srt_epoll_add_usock(pollid, client_sock, &epoll_out), SRT_ERROR);

    sockaddr_in sa;
    memset(&sa, 0, sizeof sa);
    sa.sin_family = AF_INET;
    sa.sin_port = htons(5555);

    ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr), 1);

    sockaddr* psa = (sockaddr*)&sa;
    ASSERT_NE(srt_connect(client_sock, psa, sizeof sa), SRT_ERROR);

    // Socket readiness for connection is checked by polling on WRITE allowed sockets.
    {
        int rlen = 2;
        SRTSOCKET read[2];

        int wlen = 2;
        SRTSOCKET write[2];

        using namespace std;
        const chrono::steady_clock::time_point chrono_ts_start = chrono::steady_clock::now();

        // Here we check the connection timeout.
        // Epoll timeout is set 100 ms greater than socket's TTL
        EXPECT_EQ(srt_epoll_wait(pollid, read, &rlen,
                                 write, &wlen,
                                 connection_timeout_ms + 100,   // +100 ms
                                 0, 0, 0, 0)
        /* Expected return value is 2. We have only 1 socket, but
         * sockets with exceptions are returned to both read and write sets.
        */
                 , 2);
        // Check the actual timeout
        const chrono::steady_clock::time_point chrono_ts_end = chrono::steady_clock::now();
        const auto delta_ms = chrono::duration_cast<chrono::milliseconds>(chrono_ts_end - chrono_ts_start).count();
        // Confidence interval border : +/-30 ms
        EXPECT_LT(delta_ms, connection_timeout_ms + 30);
        EXPECT_GT(delta_ms, connection_timeout_ms - 30);
        cerr << "Timeout was: " << delta_ms << "\n";

        EXPECT_EQ(rlen, 1);
        EXPECT_EQ(read[0], client_sock);
        EXPECT_EQ(wlen, 1);
        EXPECT_EQ(write[0], client_sock);
    }

    EXPECT_EQ(srt_epoll_remove_usock(pollid, client_sock), SRT_SUCCESS);
    EXPECT_EQ(srt_close(client_sock), SRT_SUCCESS);
    (void)srt_epoll_release(pollid);
    (void)srt_cleanup();
}
<|endoftext|>


<commit_before>#include <iostream>

#include "PersistenceDiagram.hh"

#include "distances/Wasserstein.hh"

using namespace aleph;
using namespace aleph::distances;

using DataType = double;
using Diagram  = PersistenceDiagram<DataType>;

int main()
{
  Diagram D1;
  D1.add( 0.9, 1.0 );
  D1.add( 1.9, 2.0 );
  D1.add( 2.9, 3.0 );
  D1.add( 3.9, 4.0 );

  Diagram D2;
  D2.add( 0.9, 1.0 );
  D2.add( 1.9, 2.0 );
  D2.add( 2.9, 3.0 );
  D2.add( 3.9, 4.0 );

  auto d11 = wassersteinDistance( D1, D1 );
  auto d12 = wassersteinDistance( D1, D2 );

  std::cerr << "d11 = " << d11 << std::endl
            << "d12 = " << d12 << std::endl;
}
<commit_msg>Extended Wasserstein distance tests<commit_after>#include <iostream>

#include "PersistenceDiagram.hh"

#include "distances/Wasserstein.hh"

using namespace aleph;
using namespace aleph::distances;

using DataType = double;
using Diagram  = PersistenceDiagram<DataType>;

int main()
{
  Diagram D1;
  D1.add( 0.9, 1.0 );
  D1.add( 1.9, 2.0 );
  D1.add( 2.9, 3.0 );
  D1.add( 3.9, 4.0 );

  {
    auto d11 = wassersteinDistance( D1, D1 );

    assert( d11 >= DataType() );
    assert( d11 == DataType() );
  }

  Diagram D2;
  D2.add( 0.9, 1.0 );
  D2.add( 1.9, 2.0 );
  D2.add( 2.9, 3.0 );
  D2.add( 3.9, 9.9 );

  {
    auto d12 = wassersteinDistance( D1, D2 );
    auto d21 = wassersteinDistance( D2, D1 );

    assert( d12 >= DataType() );
    assert( d21 >= DataType() );

    assert( d12 == d21 );

    std::cerr << "d12 = " << d12 << std::endl;
    std::cerr << "d21 = " << d21 << std::endl;

    assert( d12 == DataType( 3.0 ) );
  }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * thrill/api/read_lines.hpp
 *
 * Part of Project Thrill.
 *
 * Copyright (C) 2015 Alexander Noe <aleexnoe@gmail.com>
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef THRILL_API_READ_LINES_HEADER
#define THRILL_API_READ_LINES_HEADER

#include <thrill/api/dia.hpp>
#include <thrill/api/source_node.hpp>
#include <thrill/common/defines.hpp>
#include <thrill/common/logger.hpp>
#include <thrill/common/math.hpp>
#include <thrill/common/string.hpp>
#include <thrill/core/file_io.hpp>
#include <thrill/net/buffer_builder.hpp>

#include <string>
#include <utility>
#include <vector>

namespace thrill {
namespace api {

//! \addtogroup api Interface
//! \{

/*!
 * A DIANode which performs a line-based Read operation. Read reads a file from
 * the file system and emits it as a DIA.
 */
class ReadLinesNode : public SourceNode<std::string>
{
public:
    using Super = SourceNode<std::string>;
    using Super::context_;

    using FileSizePair = std::pair<std::string, size_t>;

    static const bool debug = false;

    /*!
     * Constructor for a ReadLinesNode. Sets the Context
     * and file path.
     *
     * \param ctx Reference to Context, which holds references to data and
     * network.
     *
     * \param path Path of the input file(s)
     */
    ReadLinesNode(Context& ctx,
                  const std::string& path,
                  StatsNode* stats_node)
        : Super(ctx, { }, stats_node),
          path_(path)
    {
		LOG << "Opening read notes for " << path_;

        filesize_prefix_ = core::GlobFileSizePrefixSum(path_);

        for (auto file : filesize_prefix_) {
            if (core::IsCompressed(file.first)) {
                contains_compressed_file_ = true;
                break;
            }
        }
    }

    void PushData() final {
        if (contains_compressed_file_) {
            InputLineIteratorCompressed it = InputLineIteratorCompressed(
                filesize_prefix_, context_.my_rank(), context_.num_workers());

            // Hook Read
            while (it.HasNext()) {
                this->PushItem(it.Next());
            }
        }
        else {
            InputLineIteratorUncompressed it = InputLineIteratorUncompressed(
                filesize_prefix_, context_.my_rank(), context_.num_workers());

            // Hook Read
            while (it.HasNext()) {
                this->PushItem(it.Next());
            }
        }
    }

    void Dispose() final { }

    /*!
     * Produces an 'empty' function stack, which only contains the identity
     * emitter function.
     *
     * \return Empty function stack
     */
    auto ProduceStack() {
        return FunctionStack<std::string>();
    }

private:
    //! True, if at least one input file is compressed.
    bool contains_compressed_file_ = false;
    //! Path of the input file.
    std::string path_;

    std::vector<std::pair<std::string, size_t> > filesize_prefix_;

    // REVIEW(an): this is useless, you never use the inheritance.  But, you
    // actually SHOULD use it! for all member fields and methods that are in
    // common. But NOT for virtual functions. Remove the virtuals. Find out what
    // functions the methods below have in common and make them functions of the
    // superclass.
    class InputLineIterator
    {
    public:
        static const bool debug = false;
        const size_t read_size = 2 * 1024 * 1024;

		//! String, which Next() references to
		std::string data_;

        virtual ~InputLineIterator() { }
    };

    //! InputLineIterator gives you access to lines of a file
    class InputLineIteratorUncompressed : public InputLineIterator
    {
    public:
        using Base = InputLineIterator;

        //! Creates an instance of iterator that reads file line based
        InputLineIteratorUncompressed(
            std::vector<FileSizePair> files,
            size_t my_id,
            size_t num_workers)
            : files_(files),
			  my_id_(my_id),
              num_workers_(num_workers) {

            input_size_ = files[NumFiles()].second;
            // Go to start of 'local part'.
            size_t my_start;
            std::tie(my_start, my_end_) = common::CalculateLocalRange(input_size_, num_workers_, my_id_);

            while (files_[current_file_ + 1].second <= my_start) {
                current_file_++;
            }
            if (my_start < my_end_) {
                LOG << "Opening file " << current_file_;
                c_file_ = OpenFile(files_[current_file_].first);
            }
            else {
                LOG << "my_start : " << my_start << " my_end_: " << my_end_;
                return;
            }

            // find offset in current file:
            // offset = start - sum of previous file sizes
            offset_ = lseek(c_file_, my_start - files_[current_file_].second, SEEK_CUR);
            buffer_.Reserve(Base::read_size);
            ssize_t buffer_size = read(c_file_, buffer_.data(), Base::read_size);
            buffer_.set_size(buffer_size);
			current_ = buffer_.begin();

            if (offset_ != 0) {
                bool found_n = false;

                // find next newline, discard all previous data as previous worker already covers it
                while (!found_n) {
                    for (auto it = current_; it != buffer_.end(); it++) {
                        if (THRILL_UNLIKELY(*it == '\n')) {
                            current_ = it + 1;
                            found_n = true;
                            break;
                        }
                    }
                    // no newline found: read new data into buffer_builder
                    if (!found_n) {
                        current_ = buffer_.begin();
                        offset_ += buffer_.size();
                        buffer_size = read(c_file_, buffer_.data(), Base::read_size);
                        // EOF = newline per definition
                        if (!buffer_size) {
                            found_n = true;
                        }
                        buffer_.set_size(buffer_size);
                    }
                }
                assert(*(current_ - 1) == '\n' || !buffer_size);
            }
			Base::data_.reserve(4 * 1024);
        }

        //! returns the next element if one exists
        //!
        //! does no checks whether a next element exists!
        const std::string& Next() {
			Base::data_.clear();
            while (true) {
                for (auto it = current_; it != buffer_.end(); it++) {
                    if (THRILL_UNLIKELY(*it == '\n')) {
                        current_ = it + 1;
						return Base::data_;
                    } else {
						Base::data_.push_back(*it);
					}
                }
                current_ = buffer_.begin();
                ssize_t buffer_size = read(c_file_, buffer_.data(), Base::read_size);
                offset_ += buffer_.size();
                if (buffer_size) {
                    buffer_.set_size(buffer_size);
                }
                else {
                    close(c_file_);
                    current_file_++;
                    offset_ = 0;

                    if (current_file_ < NumFiles()) {
                        c_file_ = OpenFile(files_[current_file_].first);
                        ssize_t buffer_size = read(c_file_, buffer_.data(), Base::read_size);
                        buffer_.set_size(buffer_size);
                    }
                    else {
                        current_ = buffer_.begin() + files_[current_file_].second - files_[current_file_ - 1].second;
                    }

                    if (Base::data_.length()) {
                        return Base::data_;
                    }
                }
            }
        }

        //! returns true, if an element is available in local part
        bool HasNext() {
            size_t global_index = offset_ + current_ - buffer_.begin() + files_[current_file_].second;
            return global_index < my_end_ ||
				(global_index == my_end_ &&
				 files_[current_file_ + 1].second - files_[current_file_].second >
				 offset_ + (current_ - buffer_.begin()));
        }

        size_t NumFiles() {
            return files_.size() - 1;
        }

        //! Open file and return file handle
        //! \param path Path to open
        int OpenFile(const std::string& path) {
            return open(path.c_str(), O_RDONLY);
        }

    private:
        //! Input files with size prefixsum.
        std::vector<FileSizePair> files_; // REVIEW(an): use a const & to the vector
        //! Index of current file in files_
        size_t current_file_ = 0;
        //! File handle to files_[current_file_]
        int c_file_;
        //! Offset of current block in c_file_.
        size_t offset_ = 0;
        //! Start of next element in current buffer.
		unsigned char* current_;
        //! (exclusive) end of local block
        size_t my_end_;
        //! Byte buffer to create line-std::strings
        net::BufferBuilder buffer_;
        //! Worker ID
        size_t my_id_;
        //! total number of workers
        size_t num_workers_;
        //! Size of all files combined (in bytes)
        size_t input_size_;
    };

    //! InputLineIterator gives you access to lines of a file
    class InputLineIteratorCompressed : public InputLineIterator
    {
    public:
        using Base = InputLineIterator;

        //! Creates an instance of iterator that reads file line based
        InputLineIteratorCompressed(
            std::vector<FileSizePair> files,
            size_t my_id,
            size_t num_workers)
            : files_(files),
              my_id_(my_id),
              num_workers_(num_workers) {

            input_size_ = files[NumFiles()].second;

            // Go to start of 'local part'.
            size_t my_start;
            std::tie(my_start, my_end_) = common::CalculateLocalRange(input_size_, num_workers_, my_id_);

            while (files_[current_file_ + 1].second <= my_start) {
                current_file_++;
            }

            for (size_t file_nr = current_file_; file_nr < NumFiles(); file_nr++) {
                if (files[file_nr + 1].second == my_end_) {
                    break;
                }
                if (files[file_nr + 1].second > my_end_) {
                    my_end_ = files_[file_nr].second;
                    break;
                }
            }

            if (my_start < my_end_) {
                LOG << "Opening file " << current_file_;
                LOG << "my_start : " << my_start << " my_end_: " << my_end_;
                c_file_ = core::SysFile::OpenForRead(files_[current_file_].first);
            }
            else {
                // No local files, set buffer size to 2, so HasNext() does not try to read
                LOG << "my_start : " << my_start << " my_end_: " << my_end_;
                buffer_.Reserve(2);
                buffer_.set_size(2);
				current_ = buffer_.begin();
                return;
            }
            buffer_.Reserve(read_size);
            ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
            buffer_.set_size(buffer_size);
			current_ = buffer_.begin();
			Base::data_.reserve(4 * 1024);
        }

        //! returns the next element if one exists
        //!
        //! does no checks whether a next element exists!
        const std::string& Next() {
            while (true) {
				Base::data_.clear();
                for (auto it = current_; it != buffer_.end(); it++) {
                    if (THRILL_UNLIKELY(*it == '\n')) {
                        current_ = it + 1;
						return Base::data_;
                    } else {
						Base::data_.push_back(*it);
					}
                }
                current_ = buffer_.begin();
                ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
                if (buffer_size) {
                    buffer_.set_size(buffer_size);
                }
                else {
                    LOG << "Opening new file!";
                    c_file_.close();
                    current_file_++;

                    if (current_file_ < NumFiles()) {
                        c_file_ = core::SysFile::OpenForRead(files_[current_file_].first);
                        ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
                        buffer_.set_size(buffer_size);
                    }
                    else {
                        current_ = buffer_.begin();
                    }

                    if (Base::data_.length()) {
                        LOG << "end - returning string of length" << Base::data_.length();
                        return Base::data_;
                    }
                }
            }
        }

        size_t NumFiles() {
            return files_.size() - 1;
        }

        //! returns true, if an element is available in local part
        bool HasNext() {
            // if block is fully read, read next block. needs to be done here
            // as HasNext() has to know if file is finished
            //         v-- no new line at end ||   v-- newline at end of file
            if (current_ >= buffer_.end() || (current_ + 1 >= buffer_.end() && *current_ == '\n')) {
                LOG << "New buffer in HasNext()";
                current_ = buffer_.begin();
                ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
                if (buffer_size > 1 || (buffer_size == 1 && buffer_[0] != '\n')) {
                    buffer_.set_size(buffer_size);
                    return true;
                }
                else {
                    LOG << "Opening new file in HasNext()";
                    // already at last file
                    if (current_file_ >= NumFiles() - 1) {
                        return false;
                    }
                    c_file_.close();
                    // if (this worker reads at least one more file)
                    if (my_end_ > files_[current_file_ + 1].second) {
                        current_file_++;
                        c_file_ = core::SysFile::OpenForRead(files_[current_file_].first);
                        buffer_.set_size(c_file_.read(buffer_.data(), read_size));
                        return true;
                    }
                    else {
                        return false;
                    }
                }
            }
            else {
				return files_[current_file_].second < my_end_;
            }
        }

    private:
        //! Input files with size prefixsum.
        std::vector<FileSizePair> files_;
        //! Index of current file in files_
        size_t current_file_ = 0;
        //! File handle to files_[current_file_]
        core::SysFile c_file_;
        //! Start of next element in current buffer.
		unsigned char* current_;
        //! (exclusive) end of local block
        size_t my_end_;
        //! Byte buffer to create line-std::strings
        net::BufferBuilder buffer_;
        //! Worker ID
        size_t my_id_;
        //! total number of workers
        size_t num_workers_;
        //! Size of all files combined (in bytes)
        size_t input_size_;
    };
};

DIARef<std::string> ReadLines(Context& ctx, std::string filepath) {

    StatsNode* stats_node = ctx.stats_graph().AddNode(
        "ReadLines", DIANodeType::DOP);

    auto shared_node =
        std::make_shared<ReadLinesNode>(
            ctx, filepath, stats_node);

    auto read_stack = shared_node->ProduceStack();

    return DIARef<std::string, decltype(read_stack)>(
        shared_node, read_stack, { stats_node });
}

//! \}

} // namespace api
} // namespace thrill

#endif // !THRILL_API_READ_LINES_HEADER

/******************************************************************************/
<commit_msg>remove unused parameters<commit_after>/*******************************************************************************
 * thrill/api/read_lines.hpp
 *
 * Part of Project Thrill.
 *
 * Copyright (C) 2015 Alexander Noe <aleexnoe@gmail.com>
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef THRILL_API_READ_LINES_HEADER
#define THRILL_API_READ_LINES_HEADER

#include <thrill/api/dia.hpp>
#include <thrill/api/source_node.hpp>
#include <thrill/common/defines.hpp>
#include <thrill/common/logger.hpp>
#include <thrill/common/math.hpp>
#include <thrill/common/string.hpp>
#include <thrill/core/file_io.hpp>
#include <thrill/net/buffer_builder.hpp>

#include <string>
#include <utility>
#include <vector>

namespace thrill {
namespace api {

//! \addtogroup api Interface
//! \{

/*!
 * A DIANode which performs a line-based Read operation. Read reads a file from
 * the file system and emits it as a DIA.
 */
class ReadLinesNode : public SourceNode<std::string>
{
public:
    using Super = SourceNode<std::string>;
    using Super::context_;

    using FileSizePair = std::pair<std::string, size_t>;

    static const bool debug = false;

    /*!
     * Constructor for a ReadLinesNode. Sets the Context
     * and file path.
     *
     * \param ctx Reference to Context, which holds references to data and
     * network.
     *
     * \param path Path of the input file(s)
     */
    ReadLinesNode(Context& ctx,
                  const std::string& path,
                  StatsNode* stats_node)
        : Super(ctx, { }, stats_node),
          path_(path)
    {
		LOG << "Opening read notes for " << path_;

        filesize_prefix_ = core::GlobFileSizePrefixSum(path_);

        for (auto file : filesize_prefix_) {
            if (core::IsCompressed(file.first)) {
                contains_compressed_file_ = true;
                break;
            }
        }
    }

    void PushData() final {
        if (contains_compressed_file_) {
            InputLineIteratorCompressed it = InputLineIteratorCompressed(
                filesize_prefix_, context_);

            // Hook Read
            while (it.HasNext()) {
                this->PushItem(it.Next());
            }
        }
        else {
            InputLineIteratorUncompressed it = InputLineIteratorUncompressed(
                filesize_prefix_, context_);

            // Hook Read
            while (it.HasNext()) {
                this->PushItem(it.Next());
            }
        }
    }

    void Dispose() final { }

    /*!
     * Produces an 'empty' function stack, which only contains the identity
     * emitter function.
     *
     * \return Empty function stack
     */
    auto ProduceStack() {
        return FunctionStack<std::string>();
    }

private:
    //! True, if at least one input file is compressed.
    bool contains_compressed_file_ = false;
    //! Path of the input file.
    std::string path_;

    std::vector<std::pair<std::string, size_t> > filesize_prefix_;

    // REVIEW(an): this is useless, you never use the inheritance.  But, you
    // actually SHOULD use it! for all member fields and methods that are in
    // common. But NOT for virtual functions. Remove the virtuals. Find out what
    // functions the methods below have in common and make them functions of the
    // superclass.
    class InputLineIterator
    {
    public:
        static const bool debug = false;
        const size_t read_size = 2 * 1024 * 1024;

		//! String, which Next() references to
		std::string data_;

        virtual ~InputLineIterator() { }
    };

    //! InputLineIterator gives you access to lines of a file
    class InputLineIteratorUncompressed : public InputLineIterator
    {
    public:
        using Base = InputLineIterator;

        //! Creates an instance of iterator that reads file line based
        InputLineIteratorUncompressed(
            std::vector<FileSizePair> files,
            Context& ctx)
            : files_(files) {

            input_size_ = files[NumFiles()].second;
            // Go to start of 'local part'.
            size_t my_start;
            std::tie(my_start, my_end_) = common::CalculateLocalRange(input_size_, ctx.num_workers(), ctx.my_rank());

            while (files_[current_file_ + 1].second <= my_start) {
                current_file_++;
            }
            if (my_start < my_end_) {
                LOG << "Opening file " << current_file_;
                c_file_ = OpenFile(files_[current_file_].first);
            }
            else {
                LOG << "my_start : " << my_start << " my_end_: " << my_end_;
                return;
            }

            // find offset in current file:
            // offset = start - sum of previous file sizes
            offset_ = lseek(c_file_, my_start - files_[current_file_].second, SEEK_CUR);
            buffer_.Reserve(Base::read_size);
            ssize_t buffer_size = read(c_file_, buffer_.data(), Base::read_size);
            buffer_.set_size(buffer_size);
			current_ = buffer_.begin();

            if (offset_ != 0) {
                bool found_n = false;

                // find next newline, discard all previous data as previous worker already covers it
                while (!found_n) {
                    for (auto it = current_; it != buffer_.end(); it++) {
                        if (THRILL_UNLIKELY(*it == '\n')) {
                            current_ = it + 1;
                            found_n = true;
                            break;
                        }
                    }
                    // no newline found: read new data into buffer_builder
                    if (!found_n) {
                        current_ = buffer_.begin();
                        offset_ += buffer_.size();
                        buffer_size = read(c_file_, buffer_.data(), Base::read_size);
                        // EOF = newline per definition
                        if (!buffer_size) {
                            found_n = true;
                        }
                        buffer_.set_size(buffer_size);
                    }
                }
                assert(*(current_ - 1) == '\n' || !buffer_size);
            }
			Base::data_.reserve(4 * 1024);
        }

        //! returns the next element if one exists
        //!
        //! does no checks whether a next element exists!
        const std::string& Next() {
			Base::data_.clear();
            while (true) {
                for (auto it = current_; it != buffer_.end(); it++) {
                    if (THRILL_UNLIKELY(*it == '\n')) {
                        current_ = it + 1;
						return Base::data_;
                    } else {
						Base::data_.push_back(*it);
					}
                }
                current_ = buffer_.begin();
                ssize_t buffer_size = read(c_file_, buffer_.data(), Base::read_size);
                offset_ += buffer_.size();
                if (buffer_size) {
                    buffer_.set_size(buffer_size);
                }
                else {
                    close(c_file_);
                    current_file_++;
                    offset_ = 0;

                    if (current_file_ < NumFiles()) {
                        c_file_ = OpenFile(files_[current_file_].first);
                        ssize_t buffer_size = read(c_file_, buffer_.data(), Base::read_size);
                        buffer_.set_size(buffer_size);
                    }
                    else {
                        current_ = buffer_.begin() + files_[current_file_].second - files_[current_file_ - 1].second;
                    }

                    if (Base::data_.length()) {
                        return Base::data_;
                    }
                }
            }
        }

        //! returns true, if an element is available in local part
        bool HasNext() {
            size_t global_index = offset_ + current_ - buffer_.begin() + files_[current_file_].second;
            return global_index < my_end_ ||
				(global_index == my_end_ &&
				 files_[current_file_ + 1].second - files_[current_file_].second >
				 offset_ + (current_ - buffer_.begin()));
        }

        size_t NumFiles() {
            return files_.size() - 1;
        }

        //! Open file and return file handle
        //! \param path Path to open
        int OpenFile(const std::string& path) {
            return open(path.c_str(), O_RDONLY);
        }

    private:
        //! Input files with size prefixsum.
        std::vector<FileSizePair> files_; // REVIEW(an): use a const & to the vector
        //! Index of current file in files_
        size_t current_file_ = 0;
        //! File handle to files_[current_file_]
        int c_file_;
        //! Offset of current block in c_file_.
        size_t offset_ = 0;
        //! Start of next element in current buffer.
		unsigned char* current_;
        //! (exclusive) end of local block
        size_t my_end_;
        //! Byte buffer to create line-std::strings
        net::BufferBuilder buffer_;
        //! Size of all files combined (in bytes)
        size_t input_size_;
    };

    //! InputLineIterator gives you access to lines of a file
    class InputLineIteratorCompressed : public InputLineIterator
    {
    public:
        using Base = InputLineIterator;

        //! Creates an instance of iterator that reads file line based
        InputLineIteratorCompressed(
            std::vector<FileSizePair> files,
			Context& ctx)
            : files_(files) {

            input_size_ = files[NumFiles()].second;

            // Go to start of 'local part'.
            size_t my_start;
            std::tie(my_start, my_end_) = common::CalculateLocalRange(input_size_, ctx.num_workers(), ctx.my_rank());

            while (files_[current_file_ + 1].second <= my_start) {
                current_file_++;
            }

            for (size_t file_nr = current_file_; file_nr < NumFiles(); file_nr++) {
                if (files[file_nr + 1].second == my_end_) {
                    break;
                }
                if (files[file_nr + 1].second > my_end_) {
                    my_end_ = files_[file_nr].second;
                    break;
                }
            }

            if (my_start < my_end_) {
                LOG << "Opening file " << current_file_;
                LOG << "my_start : " << my_start << " my_end_: " << my_end_;
                c_file_ = core::SysFile::OpenForRead(files_[current_file_].first);
            }
            else {
                // No local files, set buffer size to 2, so HasNext() does not try to read
                LOG << "my_start : " << my_start << " my_end_: " << my_end_;
                buffer_.Reserve(2);
                buffer_.set_size(2);
				current_ = buffer_.begin();
                return;
            }
            buffer_.Reserve(read_size);
            ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
            buffer_.set_size(buffer_size);
			current_ = buffer_.begin();
			Base::data_.reserve(4 * 1024);
        }

        //! returns the next element if one exists
        //!
        //! does no checks whether a next element exists!
        const std::string& Next() {
            while (true) {
				Base::data_.clear();
                for (auto it = current_; it != buffer_.end(); it++) {
                    if (THRILL_UNLIKELY(*it == '\n')) {
                        current_ = it + 1;
						return Base::data_;
                    } else {
						Base::data_.push_back(*it);
					}
                }
                current_ = buffer_.begin();
                ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
                if (buffer_size) {
                    buffer_.set_size(buffer_size);
                }
                else {
                    LOG << "Opening new file!";
                    c_file_.close();
                    current_file_++;

                    if (current_file_ < NumFiles()) {
                        c_file_ = core::SysFile::OpenForRead(files_[current_file_].first);
                        ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
                        buffer_.set_size(buffer_size);
                    }
                    else {
                        current_ = buffer_.begin();
                    }

                    if (Base::data_.length()) {
                        LOG << "end - returning string of length" << Base::data_.length();
                        return Base::data_;
                    }
                }
            }
        }

        size_t NumFiles() {
            return files_.size() - 1;
        }

        //! returns true, if an element is available in local part
        bool HasNext() {
            // if block is fully read, read next block. needs to be done here
            // as HasNext() has to know if file is finished
            //         v-- no new line at end ||   v-- newline at end of file
            if (current_ >= buffer_.end() || (current_ + 1 >= buffer_.end() && *current_ == '\n')) {
                LOG << "New buffer in HasNext()";
                current_ = buffer_.begin();
                ssize_t buffer_size = c_file_.read(buffer_.data(), read_size);
                if (buffer_size > 1 || (buffer_size == 1 && buffer_[0] != '\n')) {
                    buffer_.set_size(buffer_size);
                    return true;
                }
                else {
                    LOG << "Opening new file in HasNext()";
                    // already at last file
                    if (current_file_ >= NumFiles() - 1) {
                        return false;
                    }
                    c_file_.close();
                    // if (this worker reads at least one more file)
                    if (my_end_ > files_[current_file_ + 1].second) {
                        current_file_++;
                        c_file_ = core::SysFile::OpenForRead(files_[current_file_].first);
                        buffer_.set_size(c_file_.read(buffer_.data(), read_size));
                        return true;
                    }
                    else {
                        return false;
                    }
                }
            }
            else {
				return files_[current_file_].second < my_end_;
            }
        }

    private:
        //! Input files with size prefixsum.
        std::vector<FileSizePair> files_;
        //! Index of current file in files_
        size_t current_file_ = 0;
        //! File handle to files_[current_file_]
        core::SysFile c_file_;
        //! Start of next element in current buffer.
		unsigned char* current_;
        //! (exclusive) end of local block
        size_t my_end_;
        //! Byte buffer to create line-std::strings
        net::BufferBuilder buffer_;
        //! Size of all files combined (in bytes)
        size_t input_size_;
    };
};

DIARef<std::string> ReadLines(Context& ctx, std::string filepath) {

    StatsNode* stats_node = ctx.stats_graph().AddNode(
        "ReadLines", DIANodeType::DOP);

    auto shared_node =
        std::make_shared<ReadLinesNode>(
            ctx, filepath, stats_node);

    auto read_stack = shared_node->ProduceStack();

    return DIARef<std::string, decltype(read_stack)>(
        shared_node, read_stack, { stats_node });
}

//! \}

} // namespace api
} // namespace thrill

#endif // !THRILL_API_READ_LINES_HEADER

/******************************************************************************/
<|endoftext|>


<commit_before>#include <bmi.hxx>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

void print_var_names (BMI::Model model);

int
main (void)
{
  int i;
  const int n_steps = 10;
  BMI::Model model;

  model.initialize ("");

  std::cout << model.get_component_name () << std::endl;

  print_var_names (model);

  model.finalize ();

  return EXIT_SUCCESS;
}

void
print_var_names (BMI::Model model)
{
  char **var_names = NULL;
  char **name;

  var_names = (char**)model.get_input_var_names ();
  fprintf (stdout, "Input var names\n");
  fprintf (stdout, "===============\n");
  for (name = var_names; *name; name++)
    fprintf (stdout, "%s\n", *name);
  fprintf (stdout, "\n");

  var_names = (char**)model.get_output_var_names ();
  fprintf (stdout, "Output var names\n");
  fprintf (stdout, "================\n");
  for (name = var_names; *name; name++)
    fprintf (stdout, "%s\n", *name);
  fprintf (stdout, "\n");

  return;
}
<commit_msg>Updated for new interface.<commit_after>#include <heat/bmi_heat.hxx>

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

void print_var_names (BmiHeat model);

int
main (void)
{
  int i;
  const int n_steps = 10;
  BmiHeat model;
  char name[2048];

  model.Initialize("");

  model.GetComponentName(name);
  std::cout << name << std::endl;

  print_var_names (model);

  model.Finalize();

  return EXIT_SUCCESS;
}

void
print_var_names (BmiHeat model)
{
  char **names;
  int number_of_names;

  model.GetInputVarNameCount(&number_of_names);
  fprintf (stdout, "Number of input names: %d\n", number_of_names);

  names = new char*[number_of_names];
  for (int i=0; i<number_of_names; i++) {
    names[i] = new char[2048];
  }

  model.GetInputVarNames(names);
  for (int i=0; i<number_of_names; i++)
    fprintf (stdout, "%s\n", names[i]);
  fprintf (stdout, "\n");

  model.GetOutputVarNameCount(&number_of_names);
  fprintf (stdout, "Number of output names: %d\n", number_of_names);

  names = new char*[number_of_names];
  for (int i=0; i<number_of_names; i++) {
    names[i] = new char[2048];
  }

  model.GetOutputVarNames(names);
  for (int i=0; i<number_of_names; i++)
    fprintf (stdout, "%s\n", names[i]);
  fprintf (stdout, "\n");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unomemorystream.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:23:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <toolkit/helper/unomemorystream.hxx>
#include <algorithm>

//  ----------------------------------------------------
//  class UnoMemoryStream
//  ----------------------------------------------------
UnoMemoryStream::UnoMemoryStream( sal_uInt32 nInitSize, sal_uInt32 nResize )
    : SvMemoryStream( nInitSize, nResize )
{
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any UnoMemoryStream::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::io::XInputStream*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::io::XInputStream
sal_Int32 UnoMemoryStream::readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    sal_Int32 nRead = available();
    if ( nRead > nBytesToRead )
        nRead = nBytesToRead;

    rData = ::com::sun::star::uno::Sequence< sal_Int8 >( nRead );
    Read( rData.getArray(), nRead );

    return nRead;
}

sal_Int32 UnoMemoryStream::readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    sal_Int32 nAvailable = available();
    if( nAvailable )
    {
        return readBytes( rData, std::min( nMaxBytesToRead , nAvailable ) );
    }
    else
    {
        // Not the most effective method, but it sticks to the specification
        return readBytes( rData, 1 );
    }
}

void UnoMemoryStream::skipBytes( sal_Int32 nBytesToSkip ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    SeekRel( nBytesToSkip );
}

sal_Int32 UnoMemoryStream::available() throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    sal_uInt32 nPos = Tell();
    sal_uInt32 nEnd = Seek( STREAM_SEEK_TO_END );
    Seek( nPos );
    return nEnd - nPos;
}

void UnoMemoryStream::closeInput() throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    // nothing to do
}

<commit_msg>INTEGRATION: CWS warnings01 (1.5.26); FILE MERGED 2005/11/14 10:36:09 pl 1.5.26.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unomemorystream.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 23:06:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <toolkit/helper/unomemorystream.hxx>
#include <algorithm>

//  ----------------------------------------------------
//  class UnoMemoryStream
//  ----------------------------------------------------
UnoMemoryStream::UnoMemoryStream( sal_uInt32 nInitSize, sal_uInt32 nInitResize )
    : SvMemoryStream( nInitSize, nInitResize )
{
}

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any UnoMemoryStream::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::io::XInputStream*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::io::XInputStream
sal_Int32 UnoMemoryStream::readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    sal_Int32 nRead = available();
    if ( nRead > nBytesToRead )
        nRead = nBytesToRead;

    rData = ::com::sun::star::uno::Sequence< sal_Int8 >( nRead );
    Read( rData.getArray(), nRead );

    return nRead;
}

sal_Int32 UnoMemoryStream::readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    sal_Int32 nAvailable = available();
    if( nAvailable )
    {
        return readBytes( rData, std::min( nMaxBytesToRead , nAvailable ) );
    }
    else
    {
        // Not the most effective method, but it sticks to the specification
        return readBytes( rData, 1 );
    }
}

void UnoMemoryStream::skipBytes( sal_Int32 nBytesToSkip ) throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    SeekRel( nBytesToSkip );
}

sal_Int32 UnoMemoryStream::available() throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    sal_uInt32 nStreamPos = Tell();
    sal_uInt32 nEnd = Seek( STREAM_SEEK_TO_END );
    Seek( nStreamPos );
    return nEnd - nStreamPos;
}

void UnoMemoryStream::closeInput() throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
    // nothing to do
}

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author David N. Bertoni
 */
#if !defined(XPATHENVSUPPORTDEFAULT_HEADER_GUARD_1357924680)
#define XPATHENVSUPPORTDEFAULT_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <XPath/XPathDefinitions.hpp>

#include <vector>

#include <XPath/XPathEnvSupport.hpp>

/**
 * Dummy class in order to make the XPath object happy
 * for diagnostic purposes.
 */
class XALAN_XPATH_EXPORT XPathEnvSupportDefault : public XPathEnvSupport
{
public:

#if defined(XALAN_NO_NAMESPACES)
	typedef map<XalanDOMString, XalanDocument*, less<XalanDOMString> >		SourceDocsTableType;
	typedef map<XalanDOMString, Function*, less<XalanDOMString> >			FunctionTableType;
	typedef map<XalanDOMString, FunctionTableType, less<XalanDOMString> >	NamespaceFunctionTablesType;
#else
	typedef std::map<XalanDOMString, XalanDocument*>	SourceDocsTableType;
	typedef std::map<XalanDOMString, Function*>			FunctionTableType;
	typedef std::map<XalanDOMString, FunctionTableType>	NamespaceFunctionTablesType;
#endif

	/**
	 * Perform initialization of statics -- must be called before any
	 * processing occurs.  See class XPathInit.
	 */
	static void
	initialize();

	/**
	 * Perform termination of statics.  See class XPathInit.
	 */
	static void
	terminate();

	XPathEnvSupportDefault();

	virtual
	~XPathEnvSupportDefault();

	// Interfaces to install and uninstall external functions globally.
	// These calls are not thread-safe, and should happen during
	// processing.

	/**
	 * Install an external function in the global space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	static void
	installExternalFunctionGlobal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName,
			const Function&			function);

	/**
	 * Uninstall an external function from the global space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 */
	static void
	uninstallExternalFunctionGlobal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName);

	// Interfaces to install and uninstall external functions in this instance.

	/**
	 * Install an external function in the local space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	virtual void
	installExternalFunctionLocal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName,
			const Function&			function);

	/**
	 * Uninstall an external function from the local space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 */
	virtual void
	uninstallExternalFunctionLocal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName);

	// These interfaces are inherited from XPathEnvSupport...

	virtual XalanDocument*
	parseXML(
			const XalanDOMString&	urlString,
			const XalanDOMString&	base);

	virtual XalanDocument*
	getSourceDocument(const XalanDOMString&	theURI) const;

	virtual void
	setSourceDocument(
			const XalanDOMString&	theURI,
			XalanDocument*			theDocument);

	virtual XalanDOMString
	findURIFromDoc(const XalanDocument*		owner) const;

	virtual XalanDocument*
	getDOMFactory() const;

	virtual bool
	elementAvailable(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	elementName) const;

	virtual bool
	functionAvailable(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName) const;

	virtual XObject*
	extFunction(
			XPathExecutionContext&			executionContext,
			const XalanDOMString&			theNamespace,
			const XalanDOMString&			functionName,
			XalanNode*						context,
			const XObjectArgVectorType&		argVec) const;

	virtual XLocator*
	getXLocatorFromNode(const XalanNode*	node) const;

	virtual void
	associateXLocatorToNode(
			const XalanNode*	node,
			XLocator*			xlocator);

	virtual bool
	shouldStripSourceNode(
			XPathExecutionContext&	executionContext,
			const XalanNode&		node) const;

	virtual bool
	problem(
			eSource					where,
			eClassification			classification,
			const XalanNode*		styleNode,
			const XalanNode*		sourceNode,
			const XalanDOMString&	msg,
			int						lineNo,
			int						charOffset) const;

	virtual bool
	problem(
			eSource					where,
			eClassification			classification,
			const PrefixResolver*	resolver,
			const XalanNode*		sourceNode,
			const XalanDOMString&	msg,
			int						lineNo,
			int						charOffset) const;

	// These interfaces are inherited from Resettable...

	virtual void
	reset();

	// Delete functor for table cleanup...
	struct NamespaceFunctionTableDeleteFunctor
	{
		typedef FunctionTableType				FunctionTableType;
		typedef NamespaceFunctionTablesType		NamespaceFunctionTablesType;

		/**
		 * Delete the value object in a map value pair.  The value of the pair must
		 * be of pointer type.
		 *
		 * @param thePair key-value pair
		 */
		void
		operator()(const NamespaceFunctionTablesType::value_type&	thePair) const;
	};

protected:

	/**
	 * Find an external function.
	 *
	 * @param theNamespace The namespace for the function.
	 * @param functionName The name of the function.
	 * @return a pointer to the function if found, or 0 if not found.
	 */
	virtual Function*
	findFunction(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName) const;

private:

	// These are not implemented...
	XPathEnvSupportDefault(const XPathEnvSupportDefault&);

	XPathEnvSupportDefault&
	operator=(const XPathEnvSupportDefault&);

	bool
	operator==(const XPathEnvSupportDefault&) const;

	/**
	 * Update the supplied function table.  If the parameter
	 * function is 0, and a function with the supplied
	 * namespace and name exists in the table, it will be
	 * removed.  If function is not 0, and a function with
	 * the supplied namespace and name exists in the table,
	 * it will be replaced with the new function.  Otherwise,
	 * the function will be added.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	static void
	updateFunctionTable(
			NamespaceFunctionTablesType&	theTable,
			const XalanDOMString&			theNamespace,
			const XalanDOMString&			functionName,
			const Function*					function);

	/**
	 * Find an external function in the supplied table.
	 *
	 * @param theTable The table to search.
	 * @param theNamespace The namespace for the function.
	 * @param functionName The name of the function.
	 * @return a pointer to the function if found, or 0 if not found.
	 */
	Function*
	findFunction(
			const NamespaceFunctionTablesType&	theTable,
			const XalanDOMString&				theNamespace,
			const XalanDOMString&				functionName) const;

	// Data members...

	SourceDocsTableType						m_sourceDocs;

	NamespaceFunctionTablesType				m_externalFunctions;

	static 	NamespaceFunctionTablesType		s_externalFunctions;
};

#endif	// XPATHENVSUPPORTDEFAULT_HEADER_GUARD_1357924680
<commit_msg>Resolve scope for AIX.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author David N. Bertoni
 */
#if !defined(XPATHENVSUPPORTDEFAULT_HEADER_GUARD_1357924680)
#define XPATHENVSUPPORTDEFAULT_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <XPath/XPathDefinitions.hpp>

#include <vector>

#include <XPath/XPathEnvSupport.hpp>

/**
 * Dummy class in order to make the XPath object happy
 * for diagnostic purposes.
 */
class XALAN_XPATH_EXPORT XPathEnvSupportDefault : public XPathEnvSupport
{
public:

#if defined(XALAN_NO_NAMESPACES)
	typedef map<XalanDOMString, XalanDocument*, less<XalanDOMString> >		SourceDocsTableType;
	typedef map<XalanDOMString, Function*, less<XalanDOMString> >			FunctionTableType;
	typedef map<XalanDOMString, FunctionTableType, less<XalanDOMString> >	NamespaceFunctionTablesType;
#else
	typedef std::map<XalanDOMString, XalanDocument*>	SourceDocsTableType;
	typedef std::map<XalanDOMString, Function*>			FunctionTableType;
	typedef std::map<XalanDOMString, FunctionTableType>	NamespaceFunctionTablesType;
#endif

	/**
	 * Perform initialization of statics -- must be called before any
	 * processing occurs.  See class XPathInit.
	 */
	static void
	initialize();

	/**
	 * Perform termination of statics.  See class XPathInit.
	 */
	static void
	terminate();

	XPathEnvSupportDefault();

	virtual
	~XPathEnvSupportDefault();

	// Interfaces to install and uninstall external functions globally.
	// These calls are not thread-safe, and should happen during
	// processing.

	/**
	 * Install an external function in the global space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	static void
	installExternalFunctionGlobal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName,
			const Function&			function);

	/**
	 * Uninstall an external function from the global space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 */
	static void
	uninstallExternalFunctionGlobal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName);

	// Interfaces to install and uninstall external functions in this instance.

	/**
	 * Install an external function in the local space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	virtual void
	installExternalFunctionLocal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName,
			const Function&			function);

	/**
	 * Uninstall an external function from the local space.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 */
	virtual void
	uninstallExternalFunctionLocal(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName);

	// These interfaces are inherited from XPathEnvSupport...

	virtual XalanDocument*
	parseXML(
			const XalanDOMString&	urlString,
			const XalanDOMString&	base);

	virtual XalanDocument*
	getSourceDocument(const XalanDOMString&	theURI) const;

	virtual void
	setSourceDocument(
			const XalanDOMString&	theURI,
			XalanDocument*			theDocument);

	virtual XalanDOMString
	findURIFromDoc(const XalanDocument*		owner) const;

	virtual XalanDocument*
	getDOMFactory() const;

	virtual bool
	elementAvailable(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	elementName) const;

	virtual bool
	functionAvailable(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName) const;

	virtual XObject*
	extFunction(
			XPathExecutionContext&			executionContext,
			const XalanDOMString&			theNamespace,
			const XalanDOMString&			functionName,
			XalanNode*						context,
			const XObjectArgVectorType&		argVec) const;

	virtual XLocator*
	getXLocatorFromNode(const XalanNode*	node) const;

	virtual void
	associateXLocatorToNode(
			const XalanNode*	node,
			XLocator*			xlocator);

	virtual bool
	shouldStripSourceNode(
			XPathExecutionContext&	executionContext,
			const XalanNode&		node) const;

	virtual bool
	problem(
			eSource					where,
			eClassification			classification,
			const XalanNode*		styleNode,
			const XalanNode*		sourceNode,
			const XalanDOMString&	msg,
			int						lineNo,
			int						charOffset) const;

	virtual bool
	problem(
			eSource					where,
			eClassification			classification,
			const PrefixResolver*	resolver,
			const XalanNode*		sourceNode,
			const XalanDOMString&	msg,
			int						lineNo,
			int						charOffset) const;

	// These interfaces are inherited from Resettable...

	virtual void
	reset();

	// Delete functor for table cleanup...
	struct NamespaceFunctionTableDeleteFunctor
	{
		typedef XPathEnvSupportDefault::FunctionTableType			FunctionTableType;
		typedef XPathEnvSupportDefault::NamespaceFunctionTablesType		NamespaceFunctionTablesType;

		/**
		 * Delete the value object in a map value pair.  The value of the pair must
		 * be of pointer type.
		 *
		 * @param thePair key-value pair
		 */
		void
		operator()(const NamespaceFunctionTablesType::value_type&	thePair) const;
	};

protected:

	/**
	 * Find an external function.
	 *
	 * @param theNamespace The namespace for the function.
	 * @param functionName The name of the function.
	 * @return a pointer to the function if found, or 0 if not found.
	 */
	virtual Function*
	findFunction(
			const XalanDOMString&	theNamespace,
			const XalanDOMString&	functionName) const;

private:

	// These are not implemented...
	XPathEnvSupportDefault(const XPathEnvSupportDefault&);

	XPathEnvSupportDefault&
	operator=(const XPathEnvSupportDefault&);

	bool
	operator==(const XPathEnvSupportDefault&) const;

	/**
	 * Update the supplied function table.  If the parameter
	 * function is 0, and a function with the supplied
	 * namespace and name exists in the table, it will be
	 * removed.  If function is not 0, and a function with
	 * the supplied namespace and name exists in the table,
	 * it will be replaced with the new function.  Otherwise,
	 * the function will be added.
	 *
	 * @param theNamespace The namespace for the functionl
	 * @param functionName The name of the function.
	 * @param function The function to install.
	 */
	static void
	updateFunctionTable(
			NamespaceFunctionTablesType&	theTable,
			const XalanDOMString&			theNamespace,
			const XalanDOMString&			functionName,
			const Function*					function);

	/**
	 * Find an external function in the supplied table.
	 *
	 * @param theTable The table to search.
	 * @param theNamespace The namespace for the function.
	 * @param functionName The name of the function.
	 * @return a pointer to the function if found, or 0 if not found.
	 */
	Function*
	findFunction(
			const NamespaceFunctionTablesType&	theTable,
			const XalanDOMString&				theNamespace,
			const XalanDOMString&				functionName) const;

	// Data members...

	SourceDocsTableType						m_sourceDocs;

	NamespaceFunctionTablesType				m_externalFunctions;

	static 	NamespaceFunctionTablesType		s_externalFunctions;
};

#endif	// XPATHENVSUPPORTDEFAULT_HEADER_GUARD_1357924680
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006-2008 Music Technology Group (MTG)
 *                         Universitat Pompeu Fabra
 */

#include "erbbands.h"

using namespace std;
using namespace essentia;
using namespace standard;

const char* ERBBands::name = "ERBBands";
const char* ERBBands::version = "1.0";
const char* ERBBands::description = DOC("This algorithm computes magnitudes in bands spaced on an Equivalent Rectangular Bandwidth (ERB) scale, given a spectrum. It applies a frequency domain filterbank using gammatone filters. Adapted from matlab code in:  D. P. W. Ellis (2009). 'Gammatone-like spectrograms', web resource [1].\n"
"\n"
"References:\n"
"  [1] http://www.ee.columbia.edu/~dpwe/resources/matlab/gammatonegram/\n"
"  [2] Moore, B. C., & Glasberg, B. R. (1983). Suggested formulae for calculating auditory‐filter bandwidths and excitation patterns. The Journal of the Acoustical Society of America, 74, 750."

);

const Real ERBBands::EarQ = 9.26449;
const Real ERBBands::minBW = 24.7;

void ERBBands::configure() {
  if (parameter("highFrequencyBound").toReal() >
        parameter("sampleRate").toReal()*0.5 ) {
    throw EssentiaException(
        "ERBBands: High frequency bound cannot be higher than Nyquist frequency");
  }
  if (parameter("highFrequencyBound").toReal() <=
        parameter("lowFrequencyBound").toReal()) {
    throw EssentiaException(
        "ERBands: High frequency bound cannot be lower than low frequency bound");
  }

  _numberBands = parameter("numberBands").toInt();
  _sampleRate = parameter("sampleRate").toReal();
  _maxFrequency = parameter("highFrequencyBound").toReal();
  _minFrequency = parameter("lowFrequencyBound").toReal();
  _width = parameter("width").toReal();
  calculateFilterFrequencies();
  createFilters(parameter("inputSize").toInt());

  _type = parameter("method").toLower();
}

void ERBBands::calculateFilterFrequencies() {
  int filterSize = _numberBands;
  _filterFrequencies.resize(filterSize);
  Real filterSizeInv = 1.0/filterSize;
  Real bw = EarQ*minBW;

  for (int i=1; i<filterSize+1; i++) {
	_filterFrequencies[filterSize-i] = -bw +
		exp(i*(-log(_maxFrequency + bw) + log(_minFrequency + bw)) * filterSizeInv) * (_maxFrequency + bw);
  }
}

void ERBBands::createFilters(int spectrumSize) {
  if (spectrumSize < 2) {
    throw EssentiaException("ERBBands: Filter bank cannot be computed from a spectrum with less than 2 bins");
  }

  int filterSize = _numberBands;
  vector<complex<Real> > ucirc = vector<complex<Real> >(spectrumSize);
  complex<Real> oneJ(0,1);
  Real order = 1;
  Real pi = Real(M_PI);
  _filterCoefficients = vector<vector<Real> >(filterSize, vector<Real>(spectrumSize, 0.0));
  Real fftSize = (spectrumSize-1)*2;
  for (int i=0; i<spectrumSize; i++) {
 	  ucirc[i] = exp((oneJ*Real(2.0)*pi*Real(i))/fftSize);
  }

  Real sqrP = sqrt(3+pow(2,1.5));
  Real sqrM = sqrt(3-pow(2,1.5));

  for (int i=0; i<filterSize; i++) {
    Real cf = _filterFrequencies[i];
    Real ERB = _width*pow((pow((cf/EarQ),order) +
                          pow(minBW,order)),Real(1.0/order));
    Real B = Real(1.019)*2*M_PI*ERB;
    Real r = exp(-B/ _sampleRate);
    Real theta = Real(2)*M_PI*cf/ _sampleRate;
    complex<Real> pole = r*exp(oneJ*theta);
    Real T = 1.0/ _sampleRate;
    Real GTord = 4;

    Real sinCf =  sin(2*cf*pi*T);
    Real cosCf = cos(2*cf*pi*T);
    Real gtCos = 2*T*cosCf/exp(B*T);
    Real gtSin = T*sinCf/exp(B*T);

    Real A11 = -(gtCos + 2*sqrP * gtSin)/2;
    Real A12 = -(gtCos - 2*sqrP * gtSin)/2;
    Real A13 = -(gtCos + 2*sqrM * gtSin)/2;
    Real A14 = -(gtCos - 2*sqrM * gtSin)/2;

	  vector<Real> zeros = vector<Real>(4);
	  zeros[0] = - A11 / T;
	  zeros[1] = - A12 / T;
	  zeros[2] = - A13 / T;
	  zeros[3] = - A14 / T;

    complex<Real> g1 = Real(-2)*exp(Real(4)*oneJ*cf*pi*T)*T;
    complex<Real> g2 = Real(2)*exp(-(B*T) + Real(2)*oneJ*cf*pi*T)*T;
    complex<Real> cxExp = exp(Real(4)*oneJ*cf*pi*T);

    Real filterGain = abs(
      (g1 + g2 *(cosCf - sqrM *sinCf)) *
      (g1 + g2 *(cosCf + sqrM *sinCf)) *
      (g1 +g2 * (cosCf - sqrP *sinCf)) *
      (g1 +g2 * (cosCf + sqrP *sinCf)) /
      pow((Real(-2) / exp(Real(2)*B*T) -
                Real(2)* cxExp + Real(2)*(Real(1) + cxExp)/exp(B*T)),Real(4)));

    for (int j=0; j<spectrumSize; j++) {
      _filterCoefficients[i][j] = (pow(T,4)/filterGain) *
            abs(ucirc[j]-zeros[0]) * abs(ucirc[j]-zeros[1]) *
            abs(ucirc[j]-zeros[2]) * abs(ucirc[j]-zeros[3]) *
            pow(abs((pole-ucirc[j])*(pole-ucirc[j])),(-GTord));
    }
  }
}

void ERBBands::compute() {

  const std::vector<Real>& spectrum = _spectrumInput.get();
  std::vector<Real>& bands = _bandsOutput.get();

  int filterSize = _numberBands;
  int spectrumSize = spectrum.size();

  if (_filterCoefficients.empty() ||
      int(_filterCoefficients[0].size()) != spectrumSize) {
    cout << "ERBBands: input spectrum size does not correspond to the \"inputSize\" parameter. Recomputing the filter bank." << endl;
    createFilters(spectrumSize);
  }

  bands.resize(filterSize);

  // NB: Band magnitudes are returned, while BarkBands and MelBands algorithms
  // return energy. Gerard Roma have found magnitudes work better when
  // working with sound effects.  Band magnitudes option is required for
  // OnsetDetectionGlobal algorithm.

  // TODO: probably all *Bands algorithms should have an option {magnitude,energy}

  if (_type=="magnitude") {
    for (int i=0; i<filterSize; ++i) {
      bands[i] = 0;
      for (int j=0; j<spectrumSize; ++j) {
        bands[i] += (spectrum[j]) * _filterCoefficients[i][j];
      }
    }
  }
  else if (_type=="energy") {
    for (int i=0; i<filterSize; ++i) {
      bands[i] = 0;
      for (int j=0; j<spectrumSize; ++j) {
        bands[i] += (spectrum[j] * spectrum[j]) * _filterCoefficients[i][j];
      }
    }
  }
}
<commit_msg>fixed compilation<commit_after>/*
 * Copyright (C) 2006-2008 Music Technology Group (MTG)
 *                         Universitat Pompeu Fabra
 */

#include "erbbands.h"

using namespace std;
using namespace essentia;
using namespace standard;

const char* ERBBands::name = "ERBBands";
const char* ERBBands::version = "1.0";
const char* ERBBands::description = DOC("This algorithm computes magnitudes in bands spaced on an Equivalent Rectangular Bandwidth (ERB) scale, given a spectrum. It applies a frequency domain filterbank using gammatone filters. Adapted from matlab code in:  D. P. W. Ellis (2009). 'Gammatone-like spectrograms', web resource [1].\n"
"\n"
"References:\n"
"  [1] http://www.ee.columbia.edu/~dpwe/resources/matlab/gammatonegram/\n"
"  [2] Moore, B. C., & Glasberg, B. R. (1983). Suggested formulae for calculating auditory‐filter bandwidths and excitation patterns. The Journal of the Acoustical Society of America, 74, 750."

);

const Real ERBBands::EarQ = 9.26449;
const Real ERBBands::minBW = 24.7;

void ERBBands::configure() {
  if (parameter("highFrequencyBound").toReal() >
        parameter("sampleRate").toReal()*0.5 ) {
    throw EssentiaException(
        "ERBBands: High frequency bound cannot be higher than Nyquist frequency");
  }
  if (parameter("highFrequencyBound").toReal() <=
        parameter("lowFrequencyBound").toReal()) {
    throw EssentiaException(
        "ERBands: High frequency bound cannot be lower than low frequency bound");
  }

  _numberBands = parameter("numberBands").toInt();
  _sampleRate = parameter("sampleRate").toReal();
  _maxFrequency = parameter("highFrequencyBound").toReal();
  _minFrequency = parameter("lowFrequencyBound").toReal();
  _width = parameter("width").toReal();
  calculateFilterFrequencies();
  createFilters(parameter("inputSize").toInt());

  _type = parameter("type").toLower();
}

void ERBBands::calculateFilterFrequencies() {
  int filterSize = _numberBands;
  _filterFrequencies.resize(filterSize);
  Real filterSizeInv = 1.0/filterSize;
  Real bw = EarQ*minBW;

  for (int i=1; i<filterSize+1; i++) {
	_filterFrequencies[filterSize-i] = -bw +
		exp(i*(-log(_maxFrequency + bw) + log(_minFrequency + bw)) * filterSizeInv) * (_maxFrequency + bw);
  }
}

void ERBBands::createFilters(int spectrumSize) {
  if (spectrumSize < 2) {
    throw EssentiaException("ERBBands: Filter bank cannot be computed from a spectrum with less than 2 bins");
  }

  int filterSize = _numberBands;
  vector<complex<Real> > ucirc = vector<complex<Real> >(spectrumSize);
  complex<Real> oneJ(0,1);
  Real order = 1;
  Real pi = Real(M_PI);
  _filterCoefficients = vector<vector<Real> >(filterSize, vector<Real>(spectrumSize, 0.0));
  Real fftSize = (spectrumSize-1)*2;
  for (int i=0; i<spectrumSize; i++) {
 	  ucirc[i] = exp((oneJ*Real(2.0)*pi*Real(i))/fftSize);
  }

  Real sqrP = sqrt(3+pow(2,1.5));
  Real sqrM = sqrt(3-pow(2,1.5));

  for (int i=0; i<filterSize; i++) {
    Real cf = _filterFrequencies[i];
    Real ERB = _width*pow((pow((cf/EarQ),order) +
                          pow(minBW,order)),Real(1.0/order));
    Real B = Real(1.019)*2*M_PI*ERB;
    Real r = exp(-B/ _sampleRate);
    Real theta = Real(2)*M_PI*cf/ _sampleRate;
    complex<Real> pole = r*exp(oneJ*theta);
    Real T = 1.0/ _sampleRate;
    Real GTord = 4;

    Real sinCf =  sin(2*cf*pi*T);
    Real cosCf = cos(2*cf*pi*T);
    Real gtCos = 2*T*cosCf/exp(B*T);
    Real gtSin = T*sinCf/exp(B*T);

    Real A11 = -(gtCos + 2*sqrP * gtSin)/2;
    Real A12 = -(gtCos - 2*sqrP * gtSin)/2;
    Real A13 = -(gtCos + 2*sqrM * gtSin)/2;
    Real A14 = -(gtCos - 2*sqrM * gtSin)/2;

	  vector<Real> zeros = vector<Real>(4);
	  zeros[0] = - A11 / T;
	  zeros[1] = - A12 / T;
	  zeros[2] = - A13 / T;
	  zeros[3] = - A14 / T;

    complex<Real> g1 = Real(-2)*exp(Real(4)*oneJ*cf*pi*T)*T;
    complex<Real> g2 = Real(2)*exp(-(B*T) + Real(2)*oneJ*cf*pi*T)*T;
    complex<Real> cxExp = exp(Real(4)*oneJ*cf*pi*T);

    Real filterGain = abs(
      (g1 + g2 *(cosCf - sqrM *sinCf)) *
      (g1 + g2 *(cosCf + sqrM *sinCf)) *
      (g1 +g2 * (cosCf - sqrP *sinCf)) *
      (g1 +g2 * (cosCf + sqrP *sinCf)) /
      pow((Real(-2) / exp(Real(2)*B*T) -
                Real(2)* cxExp + Real(2)*(Real(1) + cxExp)/exp(B*T)),Real(4)));

    for (int j=0; j<spectrumSize; j++) {
      _filterCoefficients[i][j] = (pow(T,4)/filterGain) *
            abs(ucirc[j]-zeros[0]) * abs(ucirc[j]-zeros[1]) *
            abs(ucirc[j]-zeros[2]) * abs(ucirc[j]-zeros[3]) *
            pow(abs((pole-ucirc[j])*(pole-ucirc[j])),(-GTord));
    }
  }
}

void ERBBands::compute() {

  const std::vector<Real>& spectrum = _spectrumInput.get();
  std::vector<Real>& bands = _bandsOutput.get();

  int filterSize = _numberBands;
  int spectrumSize = spectrum.size();

  if (_filterCoefficients.empty() ||
      int(_filterCoefficients[0].size()) != spectrumSize) {
    cout << "ERBBands: input spectrum size does not correspond to the \"inputSize\" parameter. Recomputing the filter bank." << endl;
    createFilters(spectrumSize);
  }

  bands.resize(filterSize);

  // NB: Band magnitudes are returned, while BarkBands and MelBands algorithms
  // return energy. Gerard Roma have found magnitudes work better when
  // working with sound effects.  Band magnitudes option is required for
  // OnsetDetectionGlobal algorithm.

  // TODO: probably all *Bands algorithms should have an option {magnitude,energy}

  if (_type=="magnitude") {
    for (int i=0; i<filterSize; ++i) {
      bands[i] = 0;
      for (int j=0; j<spectrumSize; ++j) {
        bands[i] += (spectrum[j]) * _filterCoefficients[i][j];
      }
    }
  }
  else if (_type=="energy") {
    for (int i=0; i<filterSize; ++i) {
      bands[i] = 0;
      for (int j=0; j<spectrumSize; ++j) {
        bands[i] += (spectrum[j] * spectrum[j]) * _filterCoefficients[i][j];
      }
    }
  }
}
<|endoftext|>