<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/listen_socket_unittest.h"

#include <fcntl.h>

#include "base/eintr_wrapper.h"
#include "net/base/net_util.h"
#include "testing/platform_test.h"

const int ListenSocketTester::kTestPort = 9999;

static const int kReadBufSize = 1024;
static const char* kHelloWorld = "HELLO, WORLD";
static const int kMaxQueueSize = 20;
static const char* kLoopback = "127.0.0.1";
static const int kDefaultTimeoutMs = 5000;
#if defined(OS_POSIX)
static const char* kSemaphoreName = "chromium.listen_socket";
#endif

ListenSocket* ListenSocketTester::DoListen() {
  return ListenSocket::Listen(kLoopback, kTestPort, this);
}

void ListenSocketTester::SetUp() {
#if defined(OS_WIN)
  InitializeCriticalSection(&lock_);
  semaphore_ = CreateSemaphore(NULL, 0, kMaxQueueSize, NULL);
  server_ = NULL;
  net::EnsureWinsockInit();
#elif defined(OS_POSIX)
  ASSERT_EQ(0, pthread_mutex_init(&lock_, NULL ));
  sem_unlink(kSemaphoreName);
  semaphore_ = sem_open(kSemaphoreName, O_CREAT, 0, 0);
  ASSERT_NE(SEM_FAILED, semaphore_);
#endif
  base::Thread::Options options;
  options.message_loop_type = MessageLoop::TYPE_IO;
  thread_.reset(new base::Thread("socketio_test"));
  thread_->StartWithOptions(options);
  loop_ = (MessageLoopForIO*)thread_->message_loop();

  loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &ListenSocketTester::Listen));

  // verify Listen succeeded
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_FALSE(server_ == NULL);
  ASSERT_EQ(ACTION_LISTEN, last_action_.type());

  // verify the connect/accept and setup test_socket_
  test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  struct sockaddr_in client;
  client.sin_family = AF_INET;
  client.sin_addr.s_addr = inet_addr(kLoopback);
  client.sin_port = htons(kTestPort);
  int ret =
      HANDLE_EINTR(connect(test_socket_, reinterpret_cast<sockaddr*>(&client),
                           sizeof(client)));
  ASSERT_NE(ret, SOCKET_ERROR);

  net::SetNonBlocking(test_socket_);
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
}

void ListenSocketTester::TearDown() {
  // verify close
#if defined(OS_WIN)
  closesocket(test_socket_);
#elif defined(OS_POSIX)
  close(test_socket_);
#endif
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_CLOSE, last_action_.type());

  loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &ListenSocketTester::Shutdown));
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());

#if defined(OS_WIN)
  CloseHandle(semaphore_);
  semaphore_ = 0;
  DeleteCriticalSection(&lock_);
#elif defined(OS_POSIX)
  ASSERT_EQ(0, pthread_mutex_lock(&lock_));
  semaphore_ = NULL;
  ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
  ASSERT_EQ(0, sem_unlink(kSemaphoreName));
  ASSERT_EQ(0, pthread_mutex_destroy(&lock_));
#endif

  thread_.reset();
  loop_ = NULL;
}

void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) {
#if defined(OS_WIN)
  EnterCriticalSection(&lock_);
  queue_.push_back(action);
  LeaveCriticalSection(&lock_);
  ReleaseSemaphore(semaphore_, 1, NULL);
#elif defined(OS_POSIX)
  ASSERT_EQ(0, pthread_mutex_lock(&lock_));
  queue_.push_back(action);
  ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
  ASSERT_EQ(0, sem_post(semaphore_));
#endif
}

bool ListenSocketTester::NextAction(int timeout) {
#if defined(OS_WIN)
  DWORD ret = ::WaitForSingleObject(semaphore_, timeout);
  if (ret != WAIT_OBJECT_0)
    return false;
  EnterCriticalSection(&lock_);
  if (queue_.size() == 0) {
    LeaveCriticalSection(&lock_);
    return false;
  }
  last_action_ = queue_.front();
  queue_.pop_front();
  LeaveCriticalSection(&lock_);
  return true;
#elif defined(OS_POSIX)
  if (semaphore_ == SEM_FAILED)
    return false;
  while (true) {
    int result = sem_trywait(semaphore_);
    PlatformThread::Sleep(1); // 1MS sleep
    timeout--;
    if (timeout <= 0)
      return false;
    if (result == 0)
      break;
  }
  pthread_mutex_lock(&lock_);
  if (queue_.size() == 0) {
    pthread_mutex_unlock(&lock_);
    return false;
  }
  last_action_ = queue_.front();
  queue_.pop_front();
  pthread_mutex_unlock(&lock_);
  return true;
#endif
}

int ListenSocketTester::ClearTestSocket() {
  char buf[kReadBufSize];
  int len_ret = 0;
  int time_out = 0;
  do {
    int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0));
#if defined(OS_WIN)
    if (len == SOCKET_ERROR) {
      int err = WSAGetLastError();
      if (err == WSAEWOULDBLOCK) {
#elif defined(OS_POSIX)
    if (len == SOCKET_ERROR) {
      if (errno == EWOULDBLOCK || errno == EAGAIN) {
#endif
        PlatformThread::Sleep(1);
        time_out++;
        if (time_out > 10)
          break;
        continue;  // still trying
      }
    } else if (len == 0) {
      // socket closed
      break;
    } else {
      time_out = 0;
      len_ret += len;
    }
  } while (true);
  return len_ret;
}

void ListenSocketTester::Shutdown() {
  connection_->Release();
  connection_ = NULL;
  server_->Release();
  server_ = NULL;
  ReportAction(ListenSocketTestAction(ACTION_SHUTDOWN));
}

void ListenSocketTester::Listen() {
  server_ = DoListen();
  if (server_) {
    server_->AddRef();
    ReportAction(ListenSocketTestAction(ACTION_LISTEN));
  }
}

void ListenSocketTester::SendFromTester() {
  connection_->Send(kHelloWorld);
  ReportAction(ListenSocketTestAction(ACTION_SEND));
}

void ListenSocketTester::DidAccept(ListenSocket *server,
                                   ListenSocket *connection) {
  connection_ = connection;
  connection_->AddRef();
  ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
}

void ListenSocketTester::DidRead(ListenSocket *connection,
                                 const std::string& data) {
  ReportAction(ListenSocketTestAction(ACTION_READ, data));
}

void ListenSocketTester::DidClose(ListenSocket *sock) {
  ReportAction(ListenSocketTestAction(ACTION_CLOSE));
}

bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
  int len = static_cast<int>(str.length());
  int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
  if (send_len == SOCKET_ERROR) {
    LOG(ERROR) << "send failed: " << errno;
    return false;
  } else if (send_len != len) {
    return false;
  }
  return true;
}

void ListenSocketTester::TestClientSend() {
  ASSERT_TRUE(Send(test_socket_, kHelloWorld));
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_READ, last_action_.type());
  ASSERT_EQ(last_action_.data(), kHelloWorld);
}

void ListenSocketTester::TestClientSendLong() {
  int hello_len = strlen(kHelloWorld);
  std::string long_string;
  int long_len = 0;
  for (int i = 0; i < 200; i++) {
    long_string += kHelloWorld;
    long_len += hello_len;
  }
  ASSERT_TRUE(Send(test_socket_, long_string));
  int read_len = 0;
  while (read_len < long_len) {
    ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
    ASSERT_EQ(ACTION_READ, last_action_.type());
    std::string last_data = last_action_.data();
    size_t len = last_data.length();
    if (long_string.compare(read_len, len, last_data)) {
      ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
    }
    read_len += static_cast<int>(last_data.length());
  }
  ASSERT_EQ(read_len, long_len);
}

void ListenSocketTester::TestServerSend() {
  loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &ListenSocketTester::SendFromTester));
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_SEND, last_action_.type());
  // TODO(erikkay): Without this sleep, the recv seems to fail a small amount
  // of the time.  I could fix this by making the socket blocking, but then
  // this test might hang in the case of errors.  It would be nice to do
  // something that felt more reliable here.
  PlatformThread::Sleep(10);  // sleep for 10ms
  const int buf_len = 200;
  char buf[buf_len+1];
  int recv_len;
  do {
    recv_len = HANDLE_EINTR(recv(test_socket_, buf, buf_len, 0));
#if defined(OS_POSIX)
  } while (recv_len == SOCKET_ERROR && errno == EINTR);
#else
  } while (false);
#endif
  ASSERT_NE(recv_len, SOCKET_ERROR);
  buf[recv_len] = 0;
  ASSERT_STREQ(buf, kHelloWorld);
}

class ListenSocketTest: public PlatformTest {
 public:
  ListenSocketTest() {
    tester_ = NULL;
  }

  virtual void SetUp() {
    PlatformTest::SetUp();
    tester_ = new ListenSocketTester();
    tester_->SetUp();
  }

  virtual void TearDown() {
    PlatformTest::TearDown();
    tester_->TearDown();
    tester_ = NULL;
  }

  scoped_refptr<ListenSocketTester> tester_;
};

TEST_F(ListenSocketTest, ClientSend) {
  tester_->TestClientSend();
}

TEST_F(ListenSocketTest, ClientSendLong) {
  tester_->TestClientSendLong();
}

TEST_F(ListenSocketTest, ServerSend) {
  tester_->TestServerSend();
}
<commit_msg>Coverity: Assert that socket() returns a successful value.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/listen_socket_unittest.h"

#include <fcntl.h>

#include "base/eintr_wrapper.h"
#include "net/base/net_util.h"
#include "testing/platform_test.h"

const int ListenSocketTester::kTestPort = 9999;

static const int kReadBufSize = 1024;
static const char* kHelloWorld = "HELLO, WORLD";
static const int kMaxQueueSize = 20;
static const char* kLoopback = "127.0.0.1";
static const int kDefaultTimeoutMs = 5000;
#if defined(OS_POSIX)
static const char* kSemaphoreName = "chromium.listen_socket";
#endif

ListenSocket* ListenSocketTester::DoListen() {
  return ListenSocket::Listen(kLoopback, kTestPort, this);
}

void ListenSocketTester::SetUp() {
#if defined(OS_WIN)
  InitializeCriticalSection(&lock_);
  semaphore_ = CreateSemaphore(NULL, 0, kMaxQueueSize, NULL);
  server_ = NULL;
  net::EnsureWinsockInit();
#elif defined(OS_POSIX)
  ASSERT_EQ(0, pthread_mutex_init(&lock_, NULL));
  sem_unlink(kSemaphoreName);
  semaphore_ = sem_open(kSemaphoreName, O_CREAT, 0, 0);
  ASSERT_NE(SEM_FAILED, semaphore_);
#endif
  base::Thread::Options options;
  options.message_loop_type = MessageLoop::TYPE_IO;
  thread_.reset(new base::Thread("socketio_test"));
  thread_->StartWithOptions(options);
  loop_ = reinterpret_cast<MessageLoopForIO*>(thread_->message_loop());

  loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &ListenSocketTester::Listen));

  // verify Listen succeeded
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_FALSE(server_ == NULL);
  ASSERT_EQ(ACTION_LISTEN, last_action_.type());

  // verify the connect/accept and setup test_socket_
  test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  ASSERT_NE(-1, test_socket_);
  struct sockaddr_in client;
  client.sin_family = AF_INET;
  client.sin_addr.s_addr = inet_addr(kLoopback);
  client.sin_port = htons(kTestPort);
  int ret =
      HANDLE_EINTR(connect(test_socket_, reinterpret_cast<sockaddr*>(&client),
                           sizeof(client)));
  ASSERT_NE(ret, SOCKET_ERROR);

  net::SetNonBlocking(test_socket_);
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
}

void ListenSocketTester::TearDown() {
  // verify close
#if defined(OS_WIN)
  closesocket(test_socket_);
#elif defined(OS_POSIX)
  close(test_socket_);
#endif
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_CLOSE, last_action_.type());

  loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &ListenSocketTester::Shutdown));
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());

#if defined(OS_WIN)
  CloseHandle(semaphore_);
  semaphore_ = 0;
  DeleteCriticalSection(&lock_);
#elif defined(OS_POSIX)
  ASSERT_EQ(0, pthread_mutex_lock(&lock_));
  semaphore_ = NULL;
  ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
  ASSERT_EQ(0, sem_unlink(kSemaphoreName));
  ASSERT_EQ(0, pthread_mutex_destroy(&lock_));
#endif

  thread_.reset();
  loop_ = NULL;
}

void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) {
#if defined(OS_WIN)
  EnterCriticalSection(&lock_);
  queue_.push_back(action);
  LeaveCriticalSection(&lock_);
  ReleaseSemaphore(semaphore_, 1, NULL);
#elif defined(OS_POSIX)
  ASSERT_EQ(0, pthread_mutex_lock(&lock_));
  queue_.push_back(action);
  ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
  ASSERT_EQ(0, sem_post(semaphore_));
#endif
}

bool ListenSocketTester::NextAction(int timeout) {
#if defined(OS_WIN)
  DWORD ret = ::WaitForSingleObject(semaphore_, timeout);
  if (ret != WAIT_OBJECT_0)
    return false;
  EnterCriticalSection(&lock_);
  if (queue_.size() == 0) {
    LeaveCriticalSection(&lock_);
    return false;
  }
  last_action_ = queue_.front();
  queue_.pop_front();
  LeaveCriticalSection(&lock_);
  return true;
#elif defined(OS_POSIX)
  if (semaphore_ == SEM_FAILED)
    return false;
  while (true) {
    int result = sem_trywait(semaphore_);
    PlatformThread::Sleep(1);  // 1MS sleep
    timeout--;
    if (timeout <= 0)
      return false;
    if (result == 0)
      break;
  }
  pthread_mutex_lock(&lock_);
  if (queue_.size() == 0) {
    pthread_mutex_unlock(&lock_);
    return false;
  }
  last_action_ = queue_.front();
  queue_.pop_front();
  pthread_mutex_unlock(&lock_);
  return true;
#endif
}

int ListenSocketTester::ClearTestSocket() {
  char buf[kReadBufSize];
  int len_ret = 0;
  int time_out = 0;
  do {
    int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0));
#if defined(OS_WIN)
    if (len == SOCKET_ERROR) {
      int err = WSAGetLastError();
      if (err == WSAEWOULDBLOCK) {
#elif defined(OS_POSIX)
    if (len == SOCKET_ERROR) {
      if (errno == EWOULDBLOCK || errno == EAGAIN) {
#endif
        PlatformThread::Sleep(1);
        time_out++;
        if (time_out > 10)
          break;
        continue;  // still trying
      }
    } else if (len == 0) {
      // socket closed
      break;
    } else {
      time_out = 0;
      len_ret += len;
    }
  } while (true);
  return len_ret;
}

void ListenSocketTester::Shutdown() {
  connection_->Release();
  connection_ = NULL;
  server_->Release();
  server_ = NULL;
  ReportAction(ListenSocketTestAction(ACTION_SHUTDOWN));
}

void ListenSocketTester::Listen() {
  server_ = DoListen();
  if (server_) {
    server_->AddRef();
    ReportAction(ListenSocketTestAction(ACTION_LISTEN));
  }
}

void ListenSocketTester::SendFromTester() {
  connection_->Send(kHelloWorld);
  ReportAction(ListenSocketTestAction(ACTION_SEND));
}

void ListenSocketTester::DidAccept(ListenSocket *server,
                                   ListenSocket *connection) {
  connection_ = connection;
  connection_->AddRef();
  ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
}

void ListenSocketTester::DidRead(ListenSocket *connection,
                                 const std::string& data) {
  ReportAction(ListenSocketTestAction(ACTION_READ, data));
}

void ListenSocketTester::DidClose(ListenSocket *sock) {
  ReportAction(ListenSocketTestAction(ACTION_CLOSE));
}

bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
  int len = static_cast<int>(str.length());
  int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0));
  if (send_len == SOCKET_ERROR) {
    LOG(ERROR) << "send failed: " << errno;
    return false;
  } else if (send_len != len) {
    return false;
  }
  return true;
}

void ListenSocketTester::TestClientSend() {
  ASSERT_TRUE(Send(test_socket_, kHelloWorld));
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_READ, last_action_.type());
  ASSERT_EQ(last_action_.data(), kHelloWorld);
}

void ListenSocketTester::TestClientSendLong() {
  int hello_len = strlen(kHelloWorld);
  std::string long_string;
  int long_len = 0;
  for (int i = 0; i < 200; i++) {
    long_string += kHelloWorld;
    long_len += hello_len;
  }
  ASSERT_TRUE(Send(test_socket_, long_string));
  int read_len = 0;
  while (read_len < long_len) {
    ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
    ASSERT_EQ(ACTION_READ, last_action_.type());
    std::string last_data = last_action_.data();
    size_t len = last_data.length();
    if (long_string.compare(read_len, len, last_data)) {
      ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
    }
    read_len += static_cast<int>(last_data.length());
  }
  ASSERT_EQ(read_len, long_len);
}

void ListenSocketTester::TestServerSend() {
  loop_->PostTask(FROM_HERE, NewRunnableMethod(
      this, &ListenSocketTester::SendFromTester));
  ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
  ASSERT_EQ(ACTION_SEND, last_action_.type());
  // TODO(erikkay): Without this sleep, the recv seems to fail a small amount
  // of the time.  I could fix this by making the socket blocking, but then
  // this test might hang in the case of errors.  It would be nice to do
  // something that felt more reliable here.
  PlatformThread::Sleep(10);  // sleep for 10ms
  const int buf_len = 200;
  char buf[buf_len+1];
  int recv_len;
  do {
    recv_len = HANDLE_EINTR(recv(test_socket_, buf, buf_len, 0));
#if defined(OS_POSIX)
  } while (recv_len == SOCKET_ERROR && errno == EINTR);
#else
  } while (false);
#endif
  ASSERT_NE(recv_len, SOCKET_ERROR);
  buf[recv_len] = 0;
  ASSERT_STREQ(buf, kHelloWorld);
}

class ListenSocketTest: public PlatformTest {
 public:
  ListenSocketTest() {
    tester_ = NULL;
  }

  virtual void SetUp() {
    PlatformTest::SetUp();
    tester_ = new ListenSocketTester();
    tester_->SetUp();
  }

  virtual void TearDown() {
    PlatformTest::TearDown();
    tester_->TearDown();
    tester_ = NULL;
  }

  scoped_refptr<ListenSocketTester> tester_;
};

TEST_F(ListenSocketTest, ClientSend) {
  tester_->TestClientSend();
}

TEST_F(ListenSocketTest, ClientSendLong) {
  tester_->TestClientSendLong();
}

TEST_F(ListenSocketTest, ServerSend) {
  tester_->TestServerSend();
}
<|endoftext|>


<commit_before>#include "net/interface.h"
#include <cassert>
#include <cerrno>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>

namespace net {

static error getIndex(int fd, struct ifreq* ifr, int* index) {
    if (ioctl(fd, SIOCGIFINDEX, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    *index = ifr->ifr_ifindex;
    return error::nil;
}

static error getName(int fd, struct ifreq* ifr, std::string* name) {
#ifdef SIOCGIFNAME
    if (ioctl(fd, SIOCGIFNAME, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    *name = ifr->ifr_name;
#endif
    return error::nil;
}

static error getHardwareAddress(int fd, struct ifreq* ifr,
        std::array<uint8_t, 6>* hardwareAddress) {
    if (ioctl(fd, SIOCGIFHWADDR, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    for (size_t i = 0; i < hardwareAddress->size(); i++) {
        (*hardwareAddress)[i] = ifr->ifr_hwaddr.sa_data[i];
    }
    return error::nil;
}

static error getFlags(int fd, struct ifreq* ifr, bool* isUp, bool* isLoopback) {
    if (ioctl(fd, SIOCGIFFLAGS, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    *isUp = ifr->ifr_flags & IFF_UP;
    *isLoopback = ifr->ifr_flags & IFF_LOOPBACK;
    return error::nil;
}

error GetNetworkInterfaces(std::vector<NetworkInterface>* infs) {
    if (infs == nullptr) {
        assert(0 && "infs must not be nullptr");
        return error::illegal_argument;
    }

    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1) {
        return error::wrap(etype::os, errno);
    }

    struct ifconf ifc;

    // get the buffer size
    ifc.ifc_buf = nullptr;
    if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
        int err = errno;
        close(fd);
        return error::wrap(etype::os, err);
    }

    char* buf = new char[ifc.ifc_len];
    ifc.ifc_buf = buf;
    if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
        int err = errno;
        close(fd);
        return error::wrap(etype::os, err);
    }

    error err = error::nil;
    struct ifreq* it = ifc.ifc_req;
    struct ifreq* end = it + (ifc.ifc_len / sizeof(struct ifreq));
    for (; it != end; it++) {
        NetworkInterface inf = {0};
        err = getIndex(fd, it, &inf.Index);
        if (err != error::nil) {
            goto fail;
        }
        err = getName(fd, it, &inf.Name);
        if (err != error::nil) {
            goto fail;
        }
        err = getHardwareAddress(fd, it, &inf.HardwareAddress);
        if (err != error::nil) {
            goto fail;
        }
        err = getFlags(fd, it, &inf.IsUp, &inf.IsLoopback);
        if (err != error::nil) {
            goto fail;
        }
        infs->push_back(inf);
    }

fail:
    delete[] buf;
    close(fd);
    return err;
}

} // namespace net
<commit_msg>bug: Fix a memory leak in interface_linux.cpp<commit_after>#include "net/interface.h"
#include <cassert>
#include <cerrno>
#include <memory>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>

namespace net {

static error getIndex(int fd, struct ifreq* ifr, int* index) {
    if (ioctl(fd, SIOCGIFINDEX, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    *index = ifr->ifr_ifindex;
    return error::nil;
}

static error getName(int fd, struct ifreq* ifr, std::string* name) {
#ifdef SIOCGIFNAME
    if (ioctl(fd, SIOCGIFNAME, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    *name = ifr->ifr_name;
#endif
    return error::nil;
}

static error getHardwareAddress(int fd, struct ifreq* ifr,
        std::array<uint8_t, 6>* hardwareAddress) {
    if (ioctl(fd, SIOCGIFHWADDR, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    for (size_t i = 0; i < hardwareAddress->size(); i++) {
        (*hardwareAddress)[i] = ifr->ifr_hwaddr.sa_data[i];
    }
    return error::nil;
}

static error getFlags(int fd, struct ifreq* ifr, bool* isUp, bool* isLoopback) {
    if (ioctl(fd, SIOCGIFFLAGS, ifr) == -1) {
        return error::wrap(etype::os, errno);
    }
    *isUp = ifr->ifr_flags & IFF_UP;
    *isLoopback = ifr->ifr_flags & IFF_LOOPBACK;
    return error::nil;
}

error GetNetworkInterfaces(std::vector<NetworkInterface>* infs) {
    if (infs == nullptr) {
        assert(0 && "infs must not be nullptr");
        return error::illegal_argument;
    }

    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1) {
        return error::wrap(etype::os, errno);
    }

    struct ifconf ifc;

    // get the buffer size
    ifc.ifc_buf = nullptr;
    if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
        int err = errno;
        close(fd);
        return error::wrap(etype::os, err);
    }

    std::unique_ptr<char[]> buf(new char[ifc.ifc_len]);
    ifc.ifc_buf = buf.get();
    if (ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
        int err = errno;
        close(fd);
        return error::wrap(etype::os, err);
    }

    error err = error::nil;
    struct ifreq* it = ifc.ifc_req;
    struct ifreq* end = it + (ifc.ifc_len / sizeof(struct ifreq));
    for (; it != end; it++) {
        NetworkInterface inf = {0};
        err = getIndex(fd, it, &inf.Index);
        if (err != error::nil) {
            goto fail;
        }
        err = getName(fd, it, &inf.Name);
        if (err != error::nil) {
            goto fail;
        }
        err = getHardwareAddress(fd, it, &inf.HardwareAddress);
        if (err != error::nil) {
            goto fail;
        }
        err = getFlags(fd, it, &inf.IsUp, &inf.IsLoopback);
        if (err != error::nil) {
            goto fail;
        }
        infs->push_back(inf);
    }

fail:
    close(fd);
    return err;
}

} // namespace net
<|endoftext|>


<commit_before>#ifndef PYTHONIC_TYPES_NUMPY_BROADCAST_HPP
#define PYTHONIC_TYPES_NUMPY_BROADCAST_HPP

#include <array>

#ifdef USE_BOOST_SIMD
#include <boost/simd/sdk/simd/native.hpp>
#include <boost/simd/include/functions/load.hpp>
#include <boost/simd/include/functions/store.hpp>
#endif

#include "pythonic/types/vectorizable_type.hpp"

namespace pythonic {

    namespace types {

        /* Type adaptor for broadcasted array values
         *
         * Used when the args of a binary operator do not have the same dimensions:
         * in that case their first dimension always yields a copy
         */
        template<class T>
            struct broadcasted {
                static const bool is_vectorizable = false;
                static const bool is_strided = false;
                typedef typename T::dtype dtype;
                typedef typename T::value_type value_type;
                static constexpr size_t value = T::value + 1;

                T const & ref;
                std::array<long, value> shape;

                broadcasted(T const& ref) : ref(ref), shape() {
                    shape[0] = 1;
                    std::copy(ref.shape.begin(), ref.shape.end(), shape.begin() + 1);
                }

                T const & operator[](long i) const { return ref;}
                T const & fast(long i) const { return ref;}
#ifdef USE_BOOST_SIMD
                template<class I> // template to prevent automatic instantiation, but the declaration is still needed
                void load(I) const {
                  typedef typename T::this_should_never_happen omg;
                }
#endif

                long flat_size() const { return 0;}

            };

        /* Type adaptor for scalar values
         *
         * Have them behave like infinite arrays of that value
         *
         * B is the original type of the broadcast value, and T is the type of the expression it is combined with
         * if both B and T are integer types, we choose T instead of B to prevent automatic conversion into larger types
         *
         * That way, np.ones(10, dtype=np.uint8) + 1 yields an array of np.uint8, although 1 is of type long
         */
        template<class T, class B>
            struct broadcast {
                // Perform the type conversion here if it seems valid (although it is not always)
                typedef typename std::conditional<std::numeric_limits<T>::is_integer and std::numeric_limits<B>::is_integer,
                                          T,
                                          typename __combined<T, B>::type>::type dtype;
                static const bool is_vectorizable = types::is_vectorizable<dtype>::value;
                static const bool is_strided = false;
                typedef dtype value_type;
                static constexpr size_t value = 0;
                dtype _value;
#ifdef USE_BOOST_SIMD
                boost::simd::native<dtype, BOOST_SIMD_DEFAULT_EXTENSION> _splated ;
#endif

                broadcast() {}
                broadcast(dtype v) : _value(v)
#ifdef USE_BOOST_SIMD
                                     , _splated(boost::simd::splat<boost::simd::native<dtype, BOOST_SIMD_DEFAULT_EXTENSION>>(_value))
#endif
                                     {}

                dtype operator[](long ) const {
                    return _value;
                }
                dtype fast(long ) const {
                    return _value;
                }
#ifdef USE_BOOST_SIMD
                template<class I>
                auto load(I) const -> decltype(this -> _splated) { return _splated; }
#endif
                long flat_size() const { return 0; }
            };
    }
}

#endif
<commit_msg>Allow any type as broadcast constructor<commit_after>#ifndef PYTHONIC_TYPES_NUMPY_BROADCAST_HPP
#define PYTHONIC_TYPES_NUMPY_BROADCAST_HPP

#include <array>

#ifdef USE_BOOST_SIMD
#include <boost/simd/sdk/simd/native.hpp>
#include <boost/simd/include/functions/load.hpp>
#include <boost/simd/include/functions/store.hpp>
#endif

//#include "pythonic/types/tuple.hpp"
#include "pythonic/types/vectorizable_type.hpp"

namespace pythonic {

    namespace types {

        /* Type adaptor for broadcasted array values
         *
         * Used when the args of a binary operator do not have the same dimensions:
         * in that case their first dimension always yields a copy
         */
        template<class T>
            struct broadcasted {
                static const bool is_vectorizable = false;
                static const bool is_strided = false;
                typedef typename T::dtype dtype;
                typedef typename T::value_type value_type;
                static constexpr size_t value = T::value + 1;

                T const & ref;
                std::array<long, value> shape;

                broadcasted(T const& ref) : ref(ref), shape() {
                    shape[0] = 1;
                    std::copy(ref.shape.begin(), ref.shape.end(), shape.begin() + 1);
                }

                T const & operator[](long i) const { return ref;}
                T const & fast(long i) const { return ref;}
#ifdef USE_BOOST_SIMD
                template<class I> // template to prevent automatic instantiation, but the declaration is still needed
                void load(I) const {
                  typedef typename T::this_should_never_happen omg;
                }
#endif

                long flat_size() const { return 0;}

            };

        /* Type adaptor for scalar values
         *
         * Have them behave like infinite arrays of that value
         *
         * B is the original type of the broadcast value, and T is the type of the expression it is combined with
         * if both B and T are integer types, we choose T instead of B to prevent automatic conversion into larger types
         *
         * That way, np.ones(10, dtype=np.uint8) + 1 yields an array of np.uint8, although 1 is of type long
         */
        template<class T, class B>
            struct broadcast {
                // Perform the type conversion here if it seems valid (although it is not always)
                typedef typename std::conditional<std::numeric_limits<T>::is_integer and std::numeric_limits<B>::is_integer,
                                          T,
                                          typename __combined<T, B>::type>::type dtype;
                static const bool is_vectorizable = types::is_vectorizable<dtype>::value;
                static const bool is_strided = false;
                typedef dtype value_type;
                static constexpr size_t value = 0;
                dtype _value;
#ifdef USE_BOOST_SIMD
                boost::simd::native<dtype, BOOST_SIMD_DEFAULT_EXTENSION> _splated ;
#endif

                broadcast() {}
                template<class V>
                broadcast(V v) : _value(v)
#ifdef USE_BOOST_SIMD
                                     , _splated(boost::simd::splat<boost::simd::native<dtype, BOOST_SIMD_DEFAULT_EXTENSION>>(_value))
#endif
                                     {}

                dtype operator[](long ) const {
                    return _value;
                }
                dtype fast(long ) const {
                    return _value;
                }
#ifdef USE_BOOST_SIMD
                template<class I>
                auto load(I) const -> decltype(this -> _splated) { return _splated; }
#endif
                long flat_size() const { return 0; }
            };
    }
}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dlgutil.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: pb $ $Date: 2000-10-09 11:36:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVX_DLGUTIL_HXX
#define _SVX_DLGUTIL_HXX

// include ---------------------------------------------------------------
#ifndef _FIELD_HXX
#include <vcl/field.hxx>
#endif
#ifndef _SFXPOOLITEM_HXX
#include <svtools/poolitem.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif

// macro -----------------------------------------------------------------

#define GET_MODULE_FIELDUNIT( eFieldUnit )                                  \
{                                                                           \
    SfxApplication* pSfxApp = SFX_APP();                                    \
    eFieldUnit = pSfxApp->GetOptions().GetMetric();                         \
    SfxModule* pModule = pSfxApp->GetActiveModule();                        \
                                                                            \
    if ( pModule )                                                          \
    {                                                                       \
        const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC );     \
                                                                            \
        if ( pItem )                                                        \
            eFieldUnit = (FieldUnit)( (SfxUInt16Item*)pItem )->GetValue();  \
    }                                                                       \
}

// typedef ---------------------------------------------------------------

typedef long (*FUNC_CONVERT)(long);

// Functions -------------------------------------------------------------

// HM- und LanguageStrings aus der Resource laden
String  GetLanguageString( LanguageType eType );
String  GetDicInfoStr( const String& rName, const USHORT nLang,
                       const BOOL bNeg );

// FieldUnit im MetricField oder -Box umsetzen
void SetFieldUnit( MetricField& rCtrl,
                   FieldUnit eUnit, BOOL bAll = FALSE );
void SetFieldUnit( MetricBox& rCtrl,
                   FieldUnit eUnit, BOOL bAll = FALSE );

FieldUnit GetModuleFieldUnit();

// Metriken umrechnen
long        CalcToUnit( float nIn, SfxMapUnit eUnit );
long        CalcToPoint( long nIn, SfxMapUnit eUnit, USHORT nFaktor );

long        ItemToControl( long nIn, SfxMapUnit eItem, SfxFieldUnit eCtrl );
long        ControlToItem( long nIn, SfxFieldUnit eCtrl, SfxMapUnit eItem );

FieldUnit   MapToFieldUnit( const SfxMapUnit eUnit );
MapUnit     FieldToMapUnit( const SfxFieldUnit eUnit );

long        ConvertValueToMap( long nVal, SfxMapUnit eUnit );
long        ConvertValueToUnit( long nVal, SfxMapUnit eUnit );

void        SetMetricValue( MetricField& rField,
                            long lCoreValue, SfxMapUnit eUnit );
long        GetCoreValue( const MetricField& rField, SfxMapUnit eUnit );

// to Twips
long    CMToTwips( long nIn );
long    MMToTwips( long nIn );
long    InchToTwips( long nIn );
long    PointToTwips( long nIn );
long    PicaToTwips( long nIn );

// to CM
long    TwipsToCM( long nIn );
long    InchToCM( long nIn );
long    MMToCM( long nIn );
long    PointToCM( long nIn );
long    PicaToCM( long nIn );

// to MM
long    TwipsToMM( long nIn );
long    CMToMM( long nIn );
long    InchToMM( long nIn );
long    PointToMM( long nIn );
long    PicaToMM( long nIn );

// to Inch
long    TwipsToInch(long nIn );
long    CMToInch(long nIn );
long    MMToInch(long nIn );
long    PointToInch(long nIn );
long    PicaToInch(long nIn );

// to Point
long    TwipsToPoint(long nIn );
long    InchToPoint(long nIn );
long    CMToPoint(long nIn );
long    MMToPoint(long nIn );
long    PicaToPoint(long nIn );

// To Pica
long    TwipsToPica(long nIn );
long    InchToPica(long nIn );
long    PointToPica(long nIn );
long    CMToPica(long nIn );
long    MMToPica(long nIn );

// generische Wandlung
long    TransformMetric( long nVal, FieldUnit aOld, FieldUnit aNew );

#endif

<commit_msg>chg: GET_MODULE_FIELDUNIT() removed<commit_after>/*************************************************************************
 *
 *  $RCSfile: dlgutil.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: pb $ $Date: 2000-10-12 09:55:24 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVX_DLGUTIL_HXX
#define _SVX_DLGUTIL_HXX

// include ---------------------------------------------------------------
#ifndef _FIELD_HXX
#include <vcl/field.hxx>
#endif
#ifndef _SFXPOOLITEM_HXX
#include <svtools/poolitem.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif

// macro -----------------------------------------------------------------

#if SUPD<609
#define GET_MODULE_FIELDUNIT( eFieldUnit )                                  \
{                                                                           \
    SfxApplication* pSfxApp = SFX_APP();                                    \
    eFieldUnit = pSfxApp->GetOptions().GetMetric();                         \
    SfxModule* pModule = pSfxApp->GetActiveModule();                        \
                                                                            \
    if ( pModule )                                                          \
    {                                                                       \
        const SfxPoolItem* pItem = pModule->GetItem( SID_ATTR_METRIC );     \
                                                                            \
        if ( pItem )                                                        \
            eFieldUnit = (FieldUnit)( (SfxUInt16Item*)pItem )->GetValue();  \
    }                                                                       \
}
#endif

// typedef ---------------------------------------------------------------

typedef long (*FUNC_CONVERT)(long);

// Functions -------------------------------------------------------------

// HM- und LanguageStrings aus der Resource laden
String  GetLanguageString( LanguageType eType );
String  GetDicInfoStr( const String& rName, const USHORT nLang,
                       const BOOL bNeg );

// FieldUnit im MetricField oder -Box umsetzen
void SetFieldUnit( MetricField& rCtrl,
                   FieldUnit eUnit, BOOL bAll = FALSE );
void SetFieldUnit( MetricBox& rCtrl,
                   FieldUnit eUnit, BOOL bAll = FALSE );

FieldUnit GetModuleFieldUnit();

// Metriken umrechnen
long        CalcToUnit( float nIn, SfxMapUnit eUnit );
long        CalcToPoint( long nIn, SfxMapUnit eUnit, USHORT nFaktor );

long        ItemToControl( long nIn, SfxMapUnit eItem, SfxFieldUnit eCtrl );
long        ControlToItem( long nIn, SfxFieldUnit eCtrl, SfxMapUnit eItem );

FieldUnit   MapToFieldUnit( const SfxMapUnit eUnit );
MapUnit     FieldToMapUnit( const SfxFieldUnit eUnit );

long        ConvertValueToMap( long nVal, SfxMapUnit eUnit );
long        ConvertValueToUnit( long nVal, SfxMapUnit eUnit );

void        SetMetricValue( MetricField& rField,
                            long lCoreValue, SfxMapUnit eUnit );
long        GetCoreValue( const MetricField& rField, SfxMapUnit eUnit );

// to Twips
long    CMToTwips( long nIn );
long    MMToTwips( long nIn );
long    InchToTwips( long nIn );
long    PointToTwips( long nIn );
long    PicaToTwips( long nIn );

// to CM
long    TwipsToCM( long nIn );
long    InchToCM( long nIn );
long    MMToCM( long nIn );
long    PointToCM( long nIn );
long    PicaToCM( long nIn );

// to MM
long    TwipsToMM( long nIn );
long    CMToMM( long nIn );
long    InchToMM( long nIn );
long    PointToMM( long nIn );
long    PicaToMM( long nIn );

// to Inch
long    TwipsToInch(long nIn );
long    CMToInch(long nIn );
long    MMToInch(long nIn );
long    PointToInch(long nIn );
long    PicaToInch(long nIn );

// to Point
long    TwipsToPoint(long nIn );
long    InchToPoint(long nIn );
long    CMToPoint(long nIn );
long    MMToPoint(long nIn );
long    PicaToPoint(long nIn );

// To Pica
long    TwipsToPica(long nIn );
long    InchToPica(long nIn );
long    PointToPica(long nIn );
long    CMToPica(long nIn );
long    MMToPica(long nIn );

// generische Wandlung
long    TransformMetric( long nVal, FieldUnit aOld, FieldUnit aNew );

#endif

<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
//
//
// Constants
//
//

    //
    // Digits
    //
        // decimal
            1
            .1
            .239480
            .239480f
            0.
            0.f
            0.L
            0.LL
            4897430la
            32094.930123a
            4897430LL
            32094.930123F
            32094.930123f
            1'03'432'43
            123232'1231321
            3'20'94.93'01'23
            3'20'94.93'1'23
        // e
            0e1
            1e10f
            1.e10
            1.e10
            1.e-10
            1.79769e+308
            1.79'76'9e+3'0'8
        // octal
            01
            01001202
            010'0'120'2
            0'1'2'3'4
        // binary
            0b101010
            0b000001
            0b100001
            0b1'01'010
            0b1'00'001
        // hex
            0x01
            0xabcdef
            0xaBCDEf
            0xABCDEF
            0xAB.cdp5f
            0xAB.cdp5l
            0x20394afLL
            0x01
            0xabc'def
            0xa'BC'DEf
            0xABC'DEF
            0x20'394'a'fLL
        // hex floating point literal
            0x0.5p10F
            0x0.5p10f
            0x1ffp10
            0x0.23p10
            0x0.234985p10L
            0x139804.234985p10L
            0x0.53'84'92p10
            0x5.p10
            0x0.23p+10
            0x0.234985p+10L
            0x139804.234985p-10L
            0x0.53'84'92p-10
            0x5.p+10
            0x13'98'04.234985p10L
        // custom literals
            29042ms
            0xabcdefmm
            0xabc'defmm
            0xabcdefyards
            20ounces
            2000miles
            L"akdjfhald"

    //
    // chars
    //
        '1'
        'a'
        '\n'
        '\0'
    //
    // Strings
    //
        auto a = "things\n\b\v\t";
//
// Memory
//
    auto a = new int(5);
    delete a;
    new (&a_storage_of_callable.callable) type(forward<Callable>(a_callable));
    int *array = new int[100];
    delete[] array;
    char should_always_be_a_newline;
    char deleter;

//
//
// namespaces
//
//
    using namespace std;
    using namespace parent_namespace::std;

    namespace {}
    namespace scoped::console { }
    namespace console {
        template <typename ANYTYPE> void __MAGIC__show(ANYTYPE input) {
                // by default use the stream operator with cout
                std::cout << input;
            }
    }

//
// Scope resolution
//
    std::cout << input;
    numeric_limits<long double>::infinity();
    char_traits<ANYTYPE>::eof();
    numeric_limits<streamsize>::max();
    Task<ANY_OUTPUT_TYPE, ANY_INPUT_TYPE>::links_to;
    &TEST_CLASS::name;
    Event<ANYTYPE>::   ListenersFor[input_event.name]

//
// member access
//
    a_pointer.thread;
    a_pointer.*thread;
    a_pointer->thread;
    a_pointer->*thread;
    a_pointer.thread.thing;
    a_pointer.*thread.*thing;
    a_pointer->thread->thing;
    a_pointer->*thread->*thing;
    a_pointer.thread->*thing;
    a_pointer.*thread->thing;
    a_pointer->thread.*thing;
    a_pointer->*thread.thing;
    a_pointer.thread[0];
    a_pointer.*thread[0];
    a_pointer->thread[0];
    a_pointer->*thread[0];
    a_pointer.thread[0]->*thing;
    a_pointer.*thread[0]->thing;
    a_pointer->thread[0].*thing;
    a_pointer->*thread[0].thing;
    a_pointer.thread();
    a_pointer.*thread();
    ptr_to_original->Start();
    ptr_to_original->*Start();
    a_pointer.thread()->*thing;
    a_pointer.*thread()->thing;
    ptr_to_original->Start().*thing;
    ptr_to_original->*Start().thing;
    {
        a_pointer.thread;
        a_pointer.*thread;
        a_pointer->thread;
        a_pointer->*thread;
    }
    {
        a_pointer.thread();
        a_pointer.*thread();
        ptr_to_original->Start();
        ptr_to_original->*Start();
    }

//
// Operator keyword
//
    ostream& operator<<(ostream& out, const Item& input_) {};
    Item  operator+( const string&  base        , const int&    repetitions ) {};
    Item  operator-( const int&     the_input   , const Item&   input_item  ) {};
    Item  operator/( const Item&    input_item  , const int&    the_input   ) {};
    Item  operator^( const Item&    input_item  , const int&    the_input   ) {};
    // implicit conversions
    operator std::string() const {};
    operator double() const {};
    // custom literal
    void operator "" _km(long double);

//
//
// preprocessor
//
//
    #define Infinite    numeric_limits<long double>::infinity()
    #define DoubleMax   1.79769e+308
    #define Pi          3.1415926535897932384626
    #define show(argument) cout << #argument << "\n";
    #ifndef CEKO_LIBRARY
    #define CEKO_LIBRARY
    #endif

//
// templates
//
    template<int, typename Callable, typename Ret, typename... Args>
    auto internalConversionToFuncPtr(Callable&& a_callable, Ret (*)(Args...))
        {
            static bool used = false;
            static storage<Callable> a_storage_of_callable;
            using type = decltype(a_storage_of_callable.callable);

            if(used) {
                a_storage_of_callable.callable.~type();
            }
            new (&a_storage_of_callable.callable) type(forward<Callable>(a_callable));
            used = true;
            // lambda
            return [](Args... args) -> Ret {
                return Ret(a_storage_of_callable.callable(forward<Args>(args)...));
            };
        }
        template<typename RETURN_TYPE, int N = 0, typename Callable>
        RETURN_TYPE* convertToFunctionPointer(Callable&& c)
            {
                return internalConversionToFuncPtr<N>(forward<Callable>(c), (RETURN_TYPE*)nullptr);
            }

//
// Classes
//
    class Thing {
        public:
        public :
        private :
        private:
        protected:
            auto a = 1;
            Thing() {

            }
    };
    struct Thing2 {
        public:
        public :
        private :
        private:
        protected:
            auto a = 1;
            Thing() {

            }
    };

//
// Functions
//
    template <class ANYTYPE>
    string ToBinary(ANYTYPE input)
        {
            // depends on #include <bitset>
            return bitset<8>(input).to_string();
        }

int main() {
    return 0;
}<commit_msg>add type castings<commit_after>#include <iostream>
#include <sstream>
//
//
// Constants
//
//

    //
    // Digits
    //
        // decimal
            1
            .1
            .239480
            .239480f
            0.
            0.f
            0.L
            0.LL
            4897430la
            32094.930123a
            4897430LL
            32094.930123F
            32094.930123f
            1'03'432'43
            123232'1231321
            3'20'94.93'01'23
            3'20'94.93'1'23
        // e
            0e1
            1e10f
            1.e10
            1.e10
            1.e-10
            1.79769e+308
            1.79'76'9e+3'0'8
        // octal
            01
            01001202
            010'0'120'2
            0'1'2'3'4
        // binary
            0b101010
            0b000001
            0b100001
            0b1'01'010
            0b1'00'001
        // hex
            0x01
            0xabcdef
            0xaBCDEf
            0xABCDEF
            0xAB.cdp5f
            0xAB.cdp5l
            0x20394afLL
            0x01
            0xabc'def
            0xa'BC'DEf
            0xABC'DEF
            0x20'394'a'fLL
        // hex floating point literal
            0x0.5p10F
            0x0.5p10f
            0x1ffp10
            0x0.23p10
            0x0.234985p10L
            0x139804.234985p10L
            0x0.53'84'92p10
            0x5.p10
            0x0.23p+10
            0x0.234985p+10L
            0x139804.234985p-10L
            0x0.53'84'92p-10
            0x5.p+10
            0x13'98'04.234985p10L
        // custom literals
            29042ms
            0xabcdefmm
            0xabc'defmm
            0xabcdefyards
            20ounces
            2000miles
            L"akdjfhald"

    //
    // chars
    //
        '1'
        'a'
        '\n'
        '\0'
    //
    // Strings
    //
        auto a = "things\n\b\v\t";

//
// type castings
//
    dynamic_cast <int> (expression);
    reinterpret_cast <double> (expression);
    static_cast <Custom> (expression);
    const_cast <int> (expression);

//
// Storage types
//
    pthread_rwlockattr_t thing;
    padfthread_rwlockattr_t thing;

//
// Memory
//
    auto a = new int(5);
    delete a;
    new (&a_storage_of_callable.callable) type(forward<Callable>(a_callable));
    int *array = new int[100];
    delete[] array;
    char should_always_be_a_newline;
    char deleter;

//
//
// namespaces
//
//
    using namespace std;
    using namespace parent_namespace::std;

    namespace {}
    namespace scoped::console { }
    namespace console {
        template <typename ANYTYPE> void __MAGIC__show(ANYTYPE input) {
                // by default use the stream operator with cout
                std::cout << input;
            }
    }

//
// Scope resolution
//
    std::cout << input;
    numeric_limits<long double>::infinity();
    char_traits<ANYTYPE>::eof();
    numeric_limits<streamsize>::max();
    Task<ANY_OUTPUT_TYPE, ANY_INPUT_TYPE>::links_to;
    &TEST_CLASS::name;
    Event<ANYTYPE>::   ListenersFor[input_event.name]

//
// member access
//
    a_pointer.thread;
    a_pointer.*thread;
    a_pointer->thread;
    a_pointer->*thread;
    a_pointer.thread.thing;
    a_pointer.*thread.*thing;
    a_pointer->thread->thing;
    a_pointer->*thread->*thing;
    a_pointer.thread->*thing;
    a_pointer.*thread->thing;
    a_pointer->thread.*thing;
    a_pointer->*thread.thing;
    a_pointer.thread[0];
    a_pointer.*thread[0];
    a_pointer->thread[0];
    a_pointer->*thread[0];
    a_pointer.thread[0]->*thing;
    a_pointer.*thread[0]->thing;
    a_pointer->thread[0].*thing;
    a_pointer->*thread[0].thing;
    a_pointer.thread();
    a_pointer.*thread();
    ptr_to_original->Start();
    ptr_to_original->*Start();
    a_pointer.thread()->*thing;
    a_pointer.*thread()->thing;
    ptr_to_original->Start().*thing;
    ptr_to_original->*Start().thing;
    {
        a_pointer.thread[0]->*thing;
        a_pointer.*thread[0]->thing;
        a_pointer->thread[0].*thing;
        a_pointer->*thread[0].thing;
        a_pointer.thread;
        a_pointer.*thread;
        a_pointer->thread;
        a_pointer->*thread;
    }
    {
        a_pointer.thread();
        a_pointer.*thread();
        ptr_to_original->Start();
        ptr_to_original->*Start();
    }

//
// Operator keyword
//
    ostream& operator<<(ostream& out, const Item& input_) {};
    Item  operator+( const string&  base        , const int&    repetitions ) {};
    Item  operator-( const int&     the_input   , const Item&   input_item  ) {};
    Item  operator/( const Item&    input_item  , const int&    the_input   ) {};
    Item  operator^( const Item&    input_item  , const int&    the_input   ) {};
    // implicit conversions
    operator std::string() const {};
    operator double() const {};
    // custom literal
    void operator "" _km(long double);

//
//
// preprocessor
//
//
    #define Infinite    numeric_limits<long double>::infinity()
    #define DoubleMax   1.79769e+308
    #define Pi          3.1415926535897932384626
    #define show(argument) cout << #argument << "\n";
    #ifndef CEKO_LIBRARY
    #define CEKO_LIBRARY
    #endif

//
// templates
//
    template<int, typename Callable, typename Ret, typename... Args>
    auto internalConversionToFuncPtr(Callable&& a_callable, Ret (*)(Args...))
        {
            static bool used = false;
            static storage<Callable> a_storage_of_callable;
            using type = decltype(a_storage_of_callable.callable);

            if(used) {
                a_storage_of_callable.callable.~type();
            }
            new (&a_storage_of_callable.callable) type(forward<Callable>(a_callable));
            used = true;
            // lambda
            return [](Args... args) -> Ret {
                return Ret(a_storage_of_callable.callable(forward<Args>(args)...));
            };
        }
        template<typename RETURN_TYPE, int N = 0, typename Callable>
        RETURN_TYPE* convertToFunctionPointer(Callable&& c)
            {
                return internalConversionToFuncPtr<N>(forward<Callable>(c), (RETURN_TYPE*)nullptr);
            }

//
// Classes
//
    class Thing {
        public:
        public :
        private :
        private:
        protected:
            auto a = 1;
            Thing() {

            }
    };
    struct Thing2 {
        public:
        public :
        private :
        private:
        protected:
            auto a = 1;
            Thing() {

            }
    };

//
// Functions
//
    template <class ANYTYPE>
    string ToBinary(ANYTYPE input)
        {
            // depends on #include <bitset>
            return bitset<8>(input).to_string();
        }

int main() {
    return 0;
}<|endoftext|>


<commit_before>/***********************************************************************
 dbinfo.cpp - Example showing how to request information about the
	database schema, such as table names, column types, etc.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

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

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <mysql++.h>

#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

static ostream&
separator(ostream& os)
{
	os << endl << "---------------------------" << endl << endl;
	return os;
}

int
main(int argc, char* argv[])
{
	mysqlpp::Connection con(mysqlpp::use_exceptions);
	try {
		connect_to_db(argc, argv, con, "");

		// Show MySQL version
		cout << "MySQL version: " << con.client_info() << separator;

		// Show all the databases we can see
		mysqlpp::Query query = con.query("show databases");
		cout << "Query: " << query.preview() << endl;

		mysqlpp::Result res = query.store();
		cout << "Databases found: " << res.size();

		cout.setf(ios::left);
		mysqlpp::Result::iterator rit;
		for (rit = res.begin(); rit != res.end(); ++rit) {
			cout << endl << '\t' << setw(17) << (*rit)[0];
		}
		cout << separator;

		// Show the tables in the mysql database
		con.select_db("mysql");

		query.reset();
		query << "show tables";
		cout << "Query: " << query.preview() << endl;

		res = query.store();
		cout << "Tables found: " << res.size();

		vector<string> tables;
		cout.setf(ios::left);
		for (rit = res.begin(); rit != res.end(); ++rit) {
			string tbl((*rit)[0]);
			cout << endl << '\t' << setw(17) << tbl;
			tables.push_back(tbl);
		}
		cout << separator;

		// Show information about each of the tables we found
		vector<string>::iterator vit;
		for (vit = tables.begin(); vit != tables.end(); ++vit) {
			query.reset();
			query << "describe " << *vit;
			cout << "Query: " << query.preview() << endl;
			res = query.store();
			unsigned int columns = res.num_fields();
			vector<int> widths;
			for (int i = 0; i < columns; ++i) {
				string s = res.names(i);
				if (s.compare("field") == 0) {
					widths.push_back(22);
				}
				else if (s.compare("type") == 0) {
					widths.push_back(20);
				}
				else if (s.compare("null") == 0) {
					widths.push_back(4);
				}
				else if (s.compare("key") == 0) {
					widths.push_back(3);
				}
				else if (s.compare("extra") == 0) {
					widths.push_back(0);
				}
				else {
					widths.push_back(15);
				}

				if (widths[i]) {
					cout << '|' << setw(widths[i]) <<
							res.names(i) << '|';
				}
			}
			cout << endl;

			for (rit = res.begin(); rit != res.end(); ++rit) {
				for (int i = 0; i < columns; ++i) {
					if (widths[i]) {
						cout << ' ' << setw(widths[i]) << (*rit)[i] << ' ';
					}
				}
				cout << endl;
			}

			cout << separator;
		}

		// Show the user table contents
		query.reset();
	 	query << "select * from user";
		cout << "Query: " << query.preview() << endl << endl;

		res = query.store();
		int columns = res.num_fields();
		cout << "fields = " << res.num_fields() << ", rows = " <<
				res.size() << endl;
		volatile MYSQL_RES* ress = res.raw_result();
		if (!ress)
			return -1;
		for (rit = res.begin(); rit != res.end(); ++rit) {
			for (int i = 0; i < columns; ++i) {
				cout << (*rit)[i] << "  ";
			}
			cout << endl;
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}
<commit_msg>Massive rework of dbinfo example output to be easier to read and to fit on a single screen.<commit_after>/***********************************************************************
 dbinfo.cpp - Example showing how to request information about the
	database schema, such as table names, column types, etc.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

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

 MySQL++ 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 MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <mysql++.h>

#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

// Insert a bar into the stream with the given query string centered
static void
separator(ostream& os, string qstr)
{
	string sep("========================================"
			"========================================");
	if (qstr.size()) {
		string::size_type start = (sep.size() - qstr.size()) / 2;
		sep.replace(start - 1, 1, 1, ' ');
		sep.replace(start, qstr.size(), qstr);
		sep.replace(start + qstr.size(), 1, 1, ' ');
		os << "\n\n";
	}
	os << sep << endl;
}

// Print out the MySQL server version
static void
show_mysql_version(mysqlpp::Connection& con)
{
	separator(cout, "");
    cout << "MySQL version: " << con.client_info();
}

// Print out the names of all the databases managed by the server
static void
show_databases(mysqlpp::Connection& con)
{
    mysqlpp::Query query = con.query("show databases");
	separator(cout, query.preview());
    mysqlpp::Result res = query.store();

    cout << "Databases found: " << res.size();
    cout.setf(ios::left);
    mysqlpp::Result::iterator rit;
    for (rit = res.begin(); rit != res.end(); ++rit) {
        cout << "\n\t" << (*rit)[0];
    }
}

// Print information about each of the tables we found
static void
show_table_info(mysqlpp::Connection& con, const vector<string>& tables)
{
	vector<string>::const_iterator it;
	for (it = tables.begin(); it != tables.end(); ++it) {
		mysqlpp::Query query = con.query();
		query << "describe " << *it;
		separator(cout, query.preview());
		mysqlpp::Result res = query.store();

		unsigned int columns = res.num_fields();
		vector<int> widths;
		for (int i = 0; i < columns; ++i) {
			string s = res.names(i);
			if (s.compare("field") == 0) {
				widths.push_back(22);
			}
			else if (s.compare("type") == 0) {
				widths.push_back(20);
			}
			else if (s.compare("null") == 0) {
				widths.push_back(4);
			}
			else if (s.compare("key") == 0) {
				widths.push_back(3);
			}
			else if (s.compare("extra") == 0) {
				widths.push_back(0);
			}
			else {
				widths.push_back(15);
			}

			if (widths[i]) {
				cout << '|' << setw(widths[i]) << res.names(i) << '|';
			}
		}
		cout << endl;

		mysqlpp::Result::iterator rit;
		for (rit = res.begin(); rit != res.end(); ++rit) {
			for (int i = 0; i < columns; ++i) {
				if (widths[i]) {
					cout << ' ' << setw(widths[i]) <<
							(*rit)[i].c_str() << ' ';
				}
			}
			cout << endl;
		}
	}
}

// Print out the names of all tables in the sample database, and
// return the list of tables.
static void
show_tables(mysqlpp::Connection& con)
{
    mysqlpp::Query query = con.query("show tables");
	separator(cout, query.preview());
	mysqlpp::Result res = query.store();

	cout << "Tables found: " << res.size();
	cout.setf(ios::left);
	vector<string> tables;
    mysqlpp::Result::iterator rit;
	for (rit = res.begin(); rit != res.end(); ++rit) {
		string tbl((*rit)[0]);
		cout << "\n\t" << tbl;
		tables.push_back(tbl);
	}

	show_table_info(con, tables);
}

// Call all the above functions in sequence
int
main(int argc, char* argv[])
{
	try {
		mysqlpp::Connection con;
		if (connect_to_db(argc, argv, con)) {
            show_mysql_version(con);
            show_databases(con);
			show_tables(con);
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 "array.h"
#include "benchmark.h"

#include <random>
#include <iostream>

using namespace nda;

// The standard matrix notation is to refer to elements by 'row,
// column'. To make this efficient for typical programs, we're going
// to make the second dimension the dense dim. This shape has the
// option of making the size of the matrix compile-time constant via
// the template parameters.
template <index_t Rows = UNK, index_t Cols = UNK>
using matrix_shape = shape<dim<UNK, Rows>, dense_dim<UNK, Cols>>;

// A matrix or matrix_ref is an array or array_ref with Shape =
// matrix_shape.
template <typename T, index_t Rows = UNK, index_t Cols = UNK,
          typename Alloc = std::allocator<T>>
using matrix = array<T, matrix_shape<Rows, Cols>, Alloc>;
template <typename T, index_t Rows = UNK, index_t Cols = UNK>
using matrix_ref = array_ref<T, matrix_shape<Rows, Cols>>;

// Make a reference to a submatrix of 'm', of size 'rows' x 'cols',
// starting at 'row', 'col'.
template <index_t Rows = UNK, index_t Cols = UNK, typename T>
matrix_ref<T> submatrix(const matrix_ref<T>& m, index_t row, index_t col,
                        index_t rows = Rows, index_t cols = Cols) {
  assert(row >= m.i().min());
  assert(row + rows <= m.i().max() + 1);
  assert(col >= m.j().min());
  assert(col + cols <= m.j().max() + 1);
  matrix_shape<Rows, Cols> s({row, rows, m.i().stride()}, {col, cols});
  return matrix_ref<T>(&m(row, col), s);
}

// A textbook implementation of matrix multiplication.
template <typename TAB, typename TC, index_t Rows, index_t Cols>
__attribute__((noinline))
void multiply_naive(const matrix_ref<TAB>& a, const matrix_ref<TAB>& b,
                    const matrix_ref<TC, Rows, Cols>& c) {
  for (int i : c.i()) {
    for (int j : c.j()) {
      TC c_ij = 0;
      for (int k : a.j()) {
        c_ij += a(i, k) * b(k, j);
      }
      c(i, j) = c_ij;
    }
  }
}

// This implementation of matrix multiplication reorders the loops
// so the inner loop is over the columns of the result. This makes
// it possible to vectorize the inner loop.
template <typename TAB, typename TC, index_t Rows, index_t Cols>
__attribute__((noinline))
void multiply_cols_innermost(const matrix_ref<TAB>& a, const matrix_ref<TAB>& b,
                             const matrix_ref<TC, Rows, Cols>& c) {
  for (int i : c.i()) {
    for (int j : c.j()) {
      c(i, j) = 0;
    }
    for (int k : a.j()) {
      for (int j : c.j()) {
        c(i, j) += a(i, k) * b(k, j);
      }
    }
  }
}

// This implementation of matrix multiplication splits the loops over
// the output matrix into chunks, and reorders the inner loops
// innermost to form tiles. This implementation should allow the compiler
// to keep all of the accumulators for the output in registers.
template <typename TAB, typename TC>
__attribute__((noinline))
void multiply_tiles_innermost(const matrix_ref<TAB>& a, const matrix_ref<TAB>& b,
                              const matrix_ref<TC>& c) {
  // We want the tiles to be as big as possible without spilling any
  // of the accumulator registers to the stack.
  constexpr index_t tile_rows = 3;
  constexpr index_t tile_cols = 32;
  using matrix_tile =
      matrix<TC, tile_rows, tile_cols, stack_allocator<TC, tile_rows * tile_cols>>;

  for (index_t io = 0; io < c.rows(); io += tile_rows) {
    for (index_t jo = 0; jo < c.columns(); jo += tile_cols) {
      // Make a local accumulator matrix. Hopefully this is only ever
      // stored in registers.
      matrix_tile c_tile({{io, tile_rows}, {jo, tile_cols}}, 0);
      // Compute this tile of the result.
      for (int k : a.j()) {
        for (int i : c_tile.i()) {
          for (int j : c_tile.j()) {
            c_tile(i, j) += a(i, k) * b(k, j);
          }
        }
      }
      // Copy this tile to the result. This may be cropped if the output matrix
      // size does not divide the tile size.
      index_t rows = std::min(c.rows() - io, tile_rows);
      index_t cols = std::min(c.columns() - jo, tile_cols);
      copy(c_tile, submatrix(c.ref(), io, jo, rows, cols));
    }
  }
}

int main(int, const char**) {
  // Define two input matrices.
  constexpr int M = 128;
  constexpr int K = 256;
  constexpr int N = 512;
  matrix<float> a({M, K});
  matrix<float> b({K, N});

  // 'for_each_value' calls the given function with a reference to
  // each value in the array. Use this to randomly initialize the
  // matrices with random values.
  std::mt19937_64 rng;
  std::uniform_real_distribution<float> uniform(0, 1);
  a.for_each_value([&](float& x) { x = uniform(rng); });
  b.for_each_value([&](float& x) { x = uniform(rng); });

  // Compute the result using all matrix multiply methods.
  matrix<float> c_naive({M, N});
  double naive_time = benchmark([&]() {
    multiply_naive(a.ref(), b.ref(), c_naive.ref());
  });
  std::cout << "naive time: " << naive_time * 1e3 << " ms" << std::endl;

  matrix<float> c_cols_innermost({M, N});
  double cols_innermost_time = benchmark([&]() {
    multiply_cols_innermost(a.ref(), b.ref(), c_cols_innermost.ref());
  });
  std::cout << "rows innermost time: " << cols_innermost_time * 1e3 << " ms" << std::endl;

  matrix<float> c_tiles_innermost({M, N});
  double tiles_innermost_time = benchmark([&]() {
    multiply_tiles_innermost(a.ref(), b.ref(), c_tiles_innermost.ref());
  });
  std::cout << "tiles innermost time: " << tiles_innermost_time * 1e3 << " ms" << std::endl;

  // Verify the results from all methods are equal.
  const float epsilon = 1e-4f;
  for (int i = 0; i < M; i++) {
    for (int j = 0; j < N; j++) {
      if (std::abs(c_cols_innermost(i, j) - c_naive(i, j)) > epsilon) {
        std::cout
          << "c_cols_innermost(" << i << ", " << j << ") = " << c_cols_innermost(i, j)
          << " != c_naive(" << i << ", " << j << ") = " << c_naive(i, j) << std::endl;
        return -1;
      }
      if (std::abs(c_tiles_innermost(i, j) - c_naive(i, j)) > epsilon) {
        std::cout
          << "c_tiles_innermost(" << i << ", " << j << ") = " << c_tiles_innermost(i, j)
          << " != c_naive(" << i << ", " << j << ") = " << c_naive(i, j) << std::endl;
        return -1;
      }
    }
  }
  return 0;
}

<commit_msg>Fix misleading cols vs. rows.<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 "array.h"
#include "benchmark.h"

#include <random>
#include <iostream>

using namespace nda;

// The standard matrix notation is to refer to elements by 'row,
// column'. To make this efficient for typical programs, we're going
// to make the second dimension the dense dim. This shape has the
// option of making the size of the matrix compile-time constant via
// the template parameters.
template <index_t Rows = UNK, index_t Cols = UNK>
using matrix_shape = shape<dim<UNK, Rows>, dense_dim<UNK, Cols>>;

// A matrix or matrix_ref is an array or array_ref with Shape =
// matrix_shape.
template <typename T, index_t Rows = UNK, index_t Cols = UNK,
          typename Alloc = std::allocator<T>>
using matrix = array<T, matrix_shape<Rows, Cols>, Alloc>;
template <typename T, index_t Rows = UNK, index_t Cols = UNK>
using matrix_ref = array_ref<T, matrix_shape<Rows, Cols>>;

// Make a reference to a submatrix of 'm', of size 'rows' x 'cols',
// starting at 'row', 'col'.
template <index_t Rows = UNK, index_t Cols = UNK, typename T>
matrix_ref<T> submatrix(const matrix_ref<T>& m, index_t row, index_t col,
                        index_t rows = Rows, index_t cols = Cols) {
  assert(row >= m.i().min());
  assert(row + rows <= m.i().max() + 1);
  assert(col >= m.j().min());
  assert(col + cols <= m.j().max() + 1);
  matrix_shape<Rows, Cols> s({row, rows, m.i().stride()}, {col, cols});
  return matrix_ref<T>(&m(row, col), s);
}

// A textbook implementation of matrix multiplication.
template <typename TAB, typename TC, index_t Rows, index_t Cols>
__attribute__((noinline))
void multiply_naive(const matrix_ref<TAB>& a, const matrix_ref<TAB>& b,
                    const matrix_ref<TC, Rows, Cols>& c) {
  for (int i : c.i()) {
    for (int j : c.j()) {
      TC c_ij = 0;
      for (int k : a.j()) {
        c_ij += a(i, k) * b(k, j);
      }
      c(i, j) = c_ij;
    }
  }
}

// This implementation of matrix multiplication reorders the loops
// so the inner loop is over the columns of the result. This makes
// it possible to vectorize the inner loop.
template <typename TAB, typename TC, index_t Rows, index_t Cols>
__attribute__((noinline))
void multiply_cols_innermost(const matrix_ref<TAB>& a, const matrix_ref<TAB>& b,
                             const matrix_ref<TC, Rows, Cols>& c) {
  for (int i : c.i()) {
    for (int j : c.j()) {
      c(i, j) = 0;
    }
    for (int k : a.j()) {
      for (int j : c.j()) {
        c(i, j) += a(i, k) * b(k, j);
      }
    }
  }
}

// This implementation of matrix multiplication splits the loops over
// the output matrix into chunks, and reorders the inner loops
// innermost to form tiles. This implementation should allow the compiler
// to keep all of the accumulators for the output in registers.
template <typename TAB, typename TC>
__attribute__((noinline))
void multiply_tiles_innermost(const matrix_ref<TAB>& a, const matrix_ref<TAB>& b,
                              const matrix_ref<TC>& c) {
  // We want the tiles to be as big as possible without spilling any
  // of the accumulator registers to the stack.
  constexpr index_t tile_rows = 3;
  constexpr index_t tile_cols = 32;
  using matrix_tile =
      matrix<TC, tile_rows, tile_cols, stack_allocator<TC, tile_rows * tile_cols>>;

  for (index_t io = 0; io < c.rows(); io += tile_rows) {
    for (index_t jo = 0; jo < c.columns(); jo += tile_cols) {
      // Make a local accumulator matrix. Hopefully this is only ever
      // stored in registers.
      matrix_tile c_tile({{io, tile_rows}, {jo, tile_cols}}, 0);
      // Compute this tile of the result.
      for (int k : a.j()) {
        for (int i : c_tile.i()) {
          for (int j : c_tile.j()) {
            c_tile(i, j) += a(i, k) * b(k, j);
          }
        }
      }
      // Copy this tile to the result. This may be cropped if the output matrix
      // size does not divide the tile size.
      index_t rows = std::min(c.rows() - io, tile_rows);
      index_t cols = std::min(c.columns() - jo, tile_cols);
      copy(c_tile, submatrix(c.ref(), io, jo, rows, cols));
    }
  }
}

int main(int, const char**) {
  // Define two input matrices.
  constexpr int M = 128;
  constexpr int K = 256;
  constexpr int N = 512;
  matrix<float> a({M, K});
  matrix<float> b({K, N});

  // 'for_each_value' calls the given function with a reference to
  // each value in the array. Use this to randomly initialize the
  // matrices with random values.
  std::mt19937_64 rng;
  std::uniform_real_distribution<float> uniform(0, 1);
  a.for_each_value([&](float& x) { x = uniform(rng); });
  b.for_each_value([&](float& x) { x = uniform(rng); });

  // Compute the result using all matrix multiply methods.
  matrix<float> c_naive({M, N});
  double naive_time = benchmark([&]() {
    multiply_naive(a.ref(), b.ref(), c_naive.ref());
  });
  std::cout << "naive time: " << naive_time * 1e3 << " ms" << std::endl;

  matrix<float> c_cols_innermost({M, N});
  double cols_innermost_time = benchmark([&]() {
    multiply_cols_innermost(a.ref(), b.ref(), c_cols_innermost.ref());
  });
  std::cout << "cols innermost time: " << cols_innermost_time * 1e3 << " ms" << std::endl;

  matrix<float> c_tiles_innermost({M, N});
  double tiles_innermost_time = benchmark([&]() {
    multiply_tiles_innermost(a.ref(), b.ref(), c_tiles_innermost.ref());
  });
  std::cout << "tiles innermost time: " << tiles_innermost_time * 1e3 << " ms" << std::endl;

  // Verify the results from all methods are equal.
  const float epsilon = 1e-4f;
  for (int i = 0; i < M; i++) {
    for (int j = 0; j < N; j++) {
      if (std::abs(c_cols_innermost(i, j) - c_naive(i, j)) > epsilon) {
        std::cout
          << "c_cols_innermost(" << i << ", " << j << ") = " << c_cols_innermost(i, j)
          << " != c_naive(" << i << ", " << j << ") = " << c_naive(i, j) << std::endl;
        return -1;
      }
      if (std::abs(c_tiles_innermost(i, j) - c_naive(i, j)) > epsilon) {
        std::cout
          << "c_tiles_innermost(" << i << ", " << j << ") = " << c_tiles_innermost(i, j)
          << " != c_naive(" << i << ", " << j << ") = " << c_naive(i, j) << std::endl;
        return -1;
      }
    }
  }
  return 0;
}

<|endoftext|>


<commit_before>/**
* @version		GrPPI v0.1
* @copyright		Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license		GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>

#include <chrono>
#include <farm.h>

using namespace std;
using namespace grppi;

std::vector<int> read_list(std::istream & is){
  std::vector<int> result;
  string line;
  is >> ws;
  if(!getline(is,line)) return result;
  istringstream iline{line};
  int x;
  while(iline >> x){
    result.push_back(x);
  }
  return result;
}

std::string read_line(std::istream & is){
  std::string res;
  std::string line;
  is >> ws;
  if(!getline(is,line)) return res;
  return line;
}

void farm_example1() {

#ifndef NTHREADS
#define NTHREADS 6
#endif

#ifdef SEQ
    sequential_execution p{};
#elif OMP
    parallel_execution_omp p{NTHREADS};
#elif TBB
    parallel_execution_tbb p{NTHREADS};
#elif THR
    parallel_execution_thr p{NTHREADS};
#else
    sequential_execution p{};
#endif

    std::ifstream is{"txt/filelist.txt"};
    if (!is.good()) { cerr << "TXT file not found!" << endl; return; }

    farm(p,
        // farm generator as lambda
        [&]() {
            auto f = read_line(is);

            return ( f.empty() ) ? optional<std::string>( ) : optional<std::string>( f );
        },

        // farm kernel as lambda
        [&]( std::string fname ) {
            std::fstream file (fname);
            auto v = read_list(file);
            int acumm = 0;
            for(int j = 0; j< v.size() ; j++) {
                acumm += v[j];
            }
            file << acumm;
        }
    );
}

int main() {

    //$ auto start = std::chrono::high_resolution_clock::now();
    farm_example1();
    //$ auto elapsed = std::chrono::high_resolution_clock::now() - start;

    //$ long long microseconds = std::chrono::duration_cast<std::chrono::microseconds>( elapsed ).count();
    //$ std::cout << "Execution time : " << microseconds << " us" << std::endl;

    return 0;
}
<commit_msg>Fixed farm_example test<commit_after>/**
* @version		GrPPI v0.1
* @copyright		Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license		GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>

#include <chrono>
#include <farm.h>

#include <atomic>

using namespace std;
using namespace grppi;

std::vector<int> read_list(std::istream & is){
  std::vector<int> result;
  string line;
  is >> ws;
  if(!getline(is,line)) return result;
  istringstream iline{line};
  int x;
  while(iline >> x){
    result.push_back(x);
  }
  return result;
}

std::string read_line(std::istream & is){
  std::string res;
  std::string line;
  is >> ws;
  if(!getline(is,line)) return res;
  return line;
}

void farm_example1() {

#ifndef NTHREADS
#define NTHREADS 6
#endif

std::atomic<int>output;
output = 0;

#ifdef SEQ
    sequential_execution p{};
#elif OMP
    parallel_execution_omp p{NTHREADS};
#elif TBB
    parallel_execution_tbb p{NTHREADS};
#elif THR
    parallel_execution_thr p{NTHREADS};
#else
    sequential_execution p{};
#endif

    std::ifstream is{"txt/filelist.txt"};
    if (!is.good()) { cerr << "TXT file not found!" << endl; return; }

    farm(p,
        // farm generator as lambda
        [&]() {
            auto f = read_line(is);

            return ( f.empty() ) ? optional<std::string>( ) : optional<std::string>( f );
        },

        // farm kernel as lambda
        [&]( std::string fname ) {
            fname.insert(0, "txt/");
            std::fstream file (fname);
            auto v = read_list(file);
            int acumm = 0;
            for(int j = 0; j< v.size() ; j++) {
                acumm += v[j];
            }
            /*std::fstream fileOut (fname);
            fileOut << acumm;

            fileOut.close();*/
            file.close();
            output += acumm;
        }
    );

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

int main() {

    //$ auto start = std::chrono::high_resolution_clock::now();
    farm_example1();
    //$ auto elapsed = std::chrono::high_resolution_clock::now() - start;

    //$ long long microseconds = std::chrono::duration_cast<std::chrono::microseconds>( elapsed ).count();
    //$ std::cout << "Execution time : " << microseconds << " us" << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "lapack_common.h"
#include <Eigen/SVD>
#include <unsupported/Eigen/BDCSVD>

// computes the singular values/vectors a general M-by-N matrix A using divide-and-conquer
EIGEN_LAPACK_FUNC(gesdd,(char *jobz, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int * /*iwork*/, int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if(*jobz!='A' && *jobz!='S' && *jobz!='O' && *jobz!='N')  *info = -1;
  else  if(*m<0)                                                  *info = -2;
  else  if(*n<0)                                                  *info = -3;
  else  if(*lda<std::max(1,*m))                                   *info = -5;
  else  if(*lda<std::max(1,*m))                                   *info = -8;
  else  if(*ldu <1 || (*jobz=='A' && *ldu <*m)
                   || (*jobz=='O' && *m<*n && *ldu<*m))           *info = -8;
  else  if(*ldvt<1 || (*jobz=='A' && *ldvt<*n)
                   || (*jobz=='S' && *ldvt<diag_size)
                   || (*jobz=='O' && *m>=*n && *ldvt<*n))         *info = -10;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESDD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = *jobz=='A' ? ComputeFullU|ComputeFullV
             : *jobz=='S' ? ComputeThinU|ComputeThinV
             : *jobz=='O' ? ComputeThinU|ComputeThinV
             : 0;

  BDCSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

  if(*jobz=='A')
  {
    matrix(u,*m,*m,*ldu)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='S')
  {
    matrix(u,*m,diag_size,*ldu)   = svd.matrixU();
    matrix(vt,diag_size,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O' && *m>=*n)
  {
    matrix(a,*m,*n,*lda)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O')
  {
    matrix(u,*m,*m,*ldu)        = svd.matrixU();
    matrix(a,diag_size,*n,*lda) = svd.matrixV().adjoint();
  }

  return 0;
}

// computes the singular values/vectors a general M-by-N matrix A using two sided jacobi algorithm
EIGEN_LAPACK_FUNC(gesvd,(char *jobu, char *jobv, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if( *jobu!='A' && *jobu!='S' && *jobu!='O' && *jobu!='N') *info = -1;
  else  if((*jobv!='A' && *jobv!='S' && *jobv!='O' && *jobv!='N')
           || (*jobu=='O' && *jobv=='O'))                         *info = -2;
  else  if(*m<0)                                                  *info = -3;
  else  if(*n<0)                                                  *info = -4;
  else  if(*lda<std::max(1,*m))                                   *info = -6;
  else  if(*ldu <1 || ((*jobu=='A' || *jobu=='S') && *ldu<*m))    *info = -9;
  else  if(*ldvt<1 || (*jobv=='A' && *ldvt<*n)
                   || (*jobv=='S' && *ldvt<diag_size))            *info = -11;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESVD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = (*jobu=='A' ? ComputeFullU : *jobu=='S' || *jobu=='O' ? ComputeThinU : 0)
             | (*jobv=='A' ? ComputeFullV : *jobv=='S' || *jobv=='O' ? ComputeThinV : 0);

  JacobiSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

        if(*jobu=='A') matrix(u,*m,*m,*ldu)           = svd.matrixU();
  else  if(*jobu=='S') matrix(u,*m,diag_size,*ldu)    = svd.matrixU();
  else  if(*jobu=='O') matrix(a,*m,diag_size,*lda)           = svd.matrixU();

        if(*jobv=='A') matrix(vt,*n,*n,*ldvt)         = svd.matrixV().adjoint();
  else  if(*jobv=='S') matrix(vt,diag_size,*n,*ldvt)  = svd.matrixV().adjoint();
  else  if(*jobv=='O') matrix(a,diag_size,*n,*lda)    = svd.matrixV().adjoint();

  return 0;
}
<commit_msg>Removed deprecated header (unsupported/Eigen/BDCSVD is included in Eigen/SVD now)<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "lapack_common.h"
#include <Eigen/SVD>

// computes the singular values/vectors a general M-by-N matrix A using divide-and-conquer
EIGEN_LAPACK_FUNC(gesdd,(char *jobz, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int * /*iwork*/, int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if(*jobz!='A' && *jobz!='S' && *jobz!='O' && *jobz!='N')  *info = -1;
  else  if(*m<0)                                                  *info = -2;
  else  if(*n<0)                                                  *info = -3;
  else  if(*lda<std::max(1,*m))                                   *info = -5;
  else  if(*lda<std::max(1,*m))                                   *info = -8;
  else  if(*ldu <1 || (*jobz=='A' && *ldu <*m)
                   || (*jobz=='O' && *m<*n && *ldu<*m))           *info = -8;
  else  if(*ldvt<1 || (*jobz=='A' && *ldvt<*n)
                   || (*jobz=='S' && *ldvt<diag_size)
                   || (*jobz=='O' && *m>=*n && *ldvt<*n))         *info = -10;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESDD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = *jobz=='A' ? ComputeFullU|ComputeFullV
             : *jobz=='S' ? ComputeThinU|ComputeThinV
             : *jobz=='O' ? ComputeThinU|ComputeThinV
             : 0;

  BDCSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

  if(*jobz=='A')
  {
    matrix(u,*m,*m,*ldu)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='S')
  {
    matrix(u,*m,diag_size,*ldu)   = svd.matrixU();
    matrix(vt,diag_size,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O' && *m>=*n)
  {
    matrix(a,*m,*n,*lda)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O')
  {
    matrix(u,*m,*m,*ldu)        = svd.matrixU();
    matrix(a,diag_size,*n,*lda) = svd.matrixV().adjoint();
  }

  return 0;
}

// computes the singular values/vectors a general M-by-N matrix A using two sided jacobi algorithm
EIGEN_LAPACK_FUNC(gesvd,(char *jobu, char *jobv, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if( *jobu!='A' && *jobu!='S' && *jobu!='O' && *jobu!='N') *info = -1;
  else  if((*jobv!='A' && *jobv!='S' && *jobv!='O' && *jobv!='N')
           || (*jobu=='O' && *jobv=='O'))                         *info = -2;
  else  if(*m<0)                                                  *info = -3;
  else  if(*n<0)                                                  *info = -4;
  else  if(*lda<std::max(1,*m))                                   *info = -6;
  else  if(*ldu <1 || ((*jobu=='A' || *jobu=='S') && *ldu<*m))    *info = -9;
  else  if(*ldvt<1 || (*jobv=='A' && *ldvt<*n)
                   || (*jobv=='S' && *ldvt<diag_size))            *info = -11;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESVD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = (*jobu=='A' ? ComputeFullU : *jobu=='S' || *jobu=='O' ? ComputeThinU : 0)
             | (*jobv=='A' ? ComputeFullV : *jobv=='S' || *jobv=='O' ? ComputeThinV : 0);

  JacobiSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

        if(*jobu=='A') matrix(u,*m,*m,*ldu)           = svd.matrixU();
  else  if(*jobu=='S') matrix(u,*m,diag_size,*ldu)    = svd.matrixU();
  else  if(*jobu=='O') matrix(a,*m,diag_size,*lda)           = svd.matrixU();

        if(*jobv=='A') matrix(vt,*n,*n,*ldvt)         = svd.matrixV().adjoint();
  else  if(*jobv=='S') matrix(vt,diag_size,*n,*ldvt)  = svd.matrixV().adjoint();
  else  if(*jobv=='O') matrix(a,diag_size,*n,*lda)    = svd.matrixV().adjoint();

  return 0;
}
<|endoftext|>