<commit_before>///////////////////////////////////////////////////////////////////////
// File:        svutil.cpp
// Description: ScrollView Utilities
// Author:      Joern Wanke
// Created:     Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// SVUtil contains the SVSync and SVNetwork classes, which are used for
// thread/process creation & synchronization and network connection.

#include <stdio.h>
#ifdef _WIN32
struct addrinfo {
  struct sockaddr* ai_addr;
  int ai_addrlen;
  int ai_family;
  int ai_socktype;
  int ai_protocol;
};
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/socket.h>
#ifdef __linux__
#include <sys/prctl.h>
#endif
#include <unistd.h>
#endif

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>

// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
#include "config_auto.h"
#endif

#ifndef GRAPHICS_DISABLED

#include "svutil.h"

const int kMaxMsgSize = 4096;

// Signals a thread to exit.
void SVSync::ExitThread() {
#ifdef _WIN32
  // ExitThread(0);
#else
  pthread_exit(0);
#endif
}

// Starts a new process.
void SVSync::StartProcess(const char* executable, const char* args) {
  std::string proc;
  proc.append(executable);
  proc.append(" ");
  proc.append(args);
  std::cout << "Starting " << proc << std::endl;
#ifdef _WIN32
  STARTUPINFO start_info;
  PROCESS_INFORMATION proc_info;
  GetStartupInfo(&start_info);
  if (!CreateProcess(NULL, const_cast<char*>(proc.c_str()), NULL, NULL, FALSE,
                CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL,
                &start_info, &proc_info))
    return;
#else
  int pid = fork();
  if (pid != 0) {   // The father process returns
  } else {
#ifdef __linux__
    // Make sure the java process terminates on exit, since its
    // broken socket detection seems to be useless.
    prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
#endif
    char* mutable_args = strdup(args);
    int argc = 1;
    for (int i = 0; mutable_args[i]; ++i) {
      if (mutable_args[i] == ' ') {
        ++argc;
      }
    }
    char** argv = new char*[argc + 2];
    argv[0] = strdup(executable);
    argv[1] = mutable_args;
    argc = 2;
    bool inquote = false;
    for (int i = 0; mutable_args[i]; ++i) {
      if (!inquote && mutable_args[i] == ' ') {
        mutable_args[i] = '\0';
        argv[argc++] = mutable_args + i + 1;
      } else if (mutable_args[i] == '"') {
        inquote = !inquote;
        mutable_args[i] = ' ';
      }
    }
    argv[argc] = NULL;
    execvp(executable, argv);
  }
#endif
}

SVSemaphore::SVSemaphore() {
#ifdef _WIN32
  semaphore_ = CreateSemaphore(0, 0, 10, 0);
#elif defined(__APPLE__)
  char name[50];
  snprintf(name, sizeof(name), "%ld", random());
  sem_unlink(name);
  semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
  if (semaphore_ == SEM_FAILED) {
    perror("sem_open");
  }
#else
  sem_init(&semaphore_, 0, 0);
#endif
}

void SVSemaphore::Signal() {
#ifdef _WIN32
  ReleaseSemaphore(semaphore_, 1, NULL);
#elif defined(__APPLE__)
  sem_post(semaphore_);
#else
  sem_post(&semaphore_);
#endif
}

void SVSemaphore::Wait() {
#ifdef _WIN32
  WaitForSingleObject(semaphore_, INFINITE);
#elif defined(__APPLE__)
  sem_wait(semaphore_);
#else
  sem_wait(&semaphore_);
#endif
}

SVMutex::SVMutex() {
#ifdef _WIN32
  mutex_ = CreateMutex(0, FALSE, 0);
#else
  pthread_mutex_init(&mutex_, NULL);
#endif
}

void SVMutex::Lock() {
#ifdef _WIN32
  WaitForSingleObject(mutex_, INFINITE);
#else
  pthread_mutex_lock(&mutex_);
#endif
}

void SVMutex::Unlock() {
#ifdef _WIN32
  ReleaseMutex(mutex_);
#else
  pthread_mutex_unlock(&mutex_);
#endif
}

// Create new thread.

void SVSync::StartThread(void *(*func)(void*), void* arg) {
#ifdef _WIN32
  LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE) func;
  DWORD threadid;
  HANDLE newthread = CreateThread(
  NULL,          // default security attributes
  0,             // use default stack size
  f,             // thread function
  arg,           // argument to thread function
  0,             // use default creation flags
  &threadid);    // returns the thread identifier
#else
  pthread_t helper;
  pthread_create(&helper, NULL, func, arg);
#endif
}

// Place a message in the message buffer (and flush it).
void SVNetwork::Send(const char* msg) {
  mutex_send_->Lock();
  msg_buffer_out_.append(msg);
  mutex_send_->Unlock();
}

// Send the whole buffer.
void SVNetwork::Flush() {
  mutex_send_->Lock();
  while (msg_buffer_out_.size() > 0) {
    int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
    msg_buffer_out_.erase(0, i);
  }
  mutex_send_->Unlock();
}

// Receive a message from the server.
// This will always return one line of char* (denoted by \n).
char* SVNetwork::Receive() {
  char* result = NULL;
#if defined(_WIN32) || defined(__CYGWIN__)
  if (has_content) { result = strtok (NULL, "\n"); }
#else
  if (buffer_ptr_ != NULL) { result = strtok_r(NULL, "\n", &buffer_ptr_); }
#endif

  // This means there is something left in the buffer and we return it.
  if (result != NULL) { return result;
  // Otherwise, we read from the stream_.
  } else {
    buffer_ptr_ = NULL;
    has_content = false;

    // The timeout length is not really important since we are looping anyway
    // until a new message is delivered.
    struct timeval tv;
    tv.tv_sec = 10;
    tv.tv_usec = 0;

    // Set the flags to return when the stream_ is ready to be read.
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(stream_, &readfds);

    int i = select(stream_+1, &readfds, NULL, NULL, &tv);

    // The stream_ died.
    if (i == 0) { return NULL; }

    // Read the message buffer.
    i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);

    // Server quit (0) or error (-1).
    if (i <= 0) { return NULL; }
    msg_buffer_in_[i] = '\0';
    has_content = true;
#ifdef _WIN32
    return strtok(msg_buffer_in_, "\n");
#else
    // Setup a new string tokenizer.
    return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
#endif
  }
}

// Close the connection to the server.
void SVNetwork::Close() {
#ifdef _WIN32
  closesocket(stream_);
#else
  close(stream_);
#endif
}

// The program to invoke to start ScrollView
static const char* ScrollViewProg() {
#ifdef _WIN32
  const char* prog = "java -Xms512m -Xmx1024m";
#else
  const char* prog = "sh";
#endif
  return prog;
}

// The arguments to the program to invoke to start ScrollView
static std::string ScrollViewCommand(std::string scrollview_path) {
  // The following ugly ifdef is to enable the output of the java runtime
  // to be sent down a black hole on non-windows to ignore all the
  // exceptions in piccolo. Ideally piccolo would be debugged to make
  // this unnecessary.
  // Also the path has to be separated by ; on windows and : otherwise.
#ifdef _WIN32
  const char* cmd_template = "-Djava.library.path=%s -jar %s/ScrollView.jar";

#else
  const char* cmd_template = "-c \"trap 'kill %%1' 0 1 2 ; java "
      "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar"
      " & wait\"";
#endif
  int cmdlen = strlen(cmd_template) + 4*strlen(scrollview_path.c_str()) + 1;
  char* cmd = new char[cmdlen];
  const char* sv_path = scrollview_path.c_str();
  snprintf(cmd, cmdlen, cmd_template, sv_path, sv_path, sv_path, sv_path);
  std::string command(cmd);
  delete [] cmd;
  return command;
}

// Platform-independent freeaddrinfo()
static void FreeAddrInfo(struct addrinfo* addr_info) {
  #if defined(__linux__)
  freeaddrinfo(addr_info);
  #else
  delete addr_info->ai_addr;
  delete addr_info;
  #endif
}

// Non-linux version of getaddrinfo()
#if !defined(__linux__)
static int GetAddrInfoNonLinux(const char* hostname, int port,
                               struct addrinfo** addr_info) {
// Get the host data depending on the OS.
  struct sockaddr_in* address;
  *addr_info = new struct addrinfo;
  memset(*addr_info, 0, sizeof(struct addrinfo));
  address = new struct sockaddr_in;
  memset(address, 0, sizeof(struct sockaddr_in));

  (*addr_info)->ai_addr = (struct sockaddr*) address;
  (*addr_info)->ai_addrlen = sizeof(struct sockaddr);
  (*addr_info)->ai_family = AF_INET;
  (*addr_info)->ai_socktype = SOCK_STREAM;

  struct hostent *name;
#ifdef _WIN32
  WSADATA wsaData;
  WSAStartup(MAKEWORD(1, 1), &wsaData);
  name = gethostbyname(hostname);
#else
  name = gethostbyname(hostname);
#endif

  if (name == NULL) {
    FreeAddrInfo(*addr_info);
    *addr_info = NULL;
    return -1;
  }

  // Fill in the appropriate variables to be able to connect to the server.
  address->sin_family = name->h_addrtype;
  memcpy((char *) &address->sin_addr.s_addr,
         name->h_addr_list[0], name->h_length);
  address->sin_port = htons(port);
  return 0;
}
#endif

// Platform independent version of getaddrinfo()
//   Given a hostname:port, produce an addrinfo struct
static int GetAddrInfo(const char* hostname, int port,
                       struct addrinfo** address) {
#if defined(__linux__)
  char port_str[40];
  snprintf(port_str, 40, "%d", port);
  return getaddrinfo(hostname, port_str, NULL, address);
#else
  return GetAddrInfoNonLinux(hostname, port, address);
#endif
}

// Set up a connection to a ScrollView on hostname:port.
SVNetwork::SVNetwork(const char* hostname, int port) {
  mutex_send_ = new SVMutex();
  msg_buffer_in_ = new char[kMaxMsgSize + 1];
  msg_buffer_in_[0] = '\0';

  has_content = false;
  buffer_ptr_ = NULL;

  struct addrinfo *addr_info = NULL;

  if (GetAddrInfo(hostname, port, &addr_info) != 0) {
    std::cerr << "Error resolving name for ScrollView host "
              << std::string(hostname) << ":" << port << std::endl;
  }

  stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);

  // If server is not there, we will start a new server as local child process.
  if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
    const char* scrollview_path = getenv("SCROLLVIEW_PATH");
    if (scrollview_path == NULL) {
#ifdef SCROLLVIEW_PATH
#define _STR(a) #a
#define _XSTR(a) _STR(a)
      scrollview_path = _XSTR(SCROLLVIEW_PATH);
#undef _XSTR
#undef _STR
#else
      scrollview_path = ".";
#endif
    }
    const char *prog = ScrollViewProg();
    std::string command = ScrollViewCommand(scrollview_path);
    SVSync::StartProcess(prog, command.c_str());

    // Wait for server to show up.
    // Note: There is no exception handling in case the server never turns up.

    stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);

    while (connect(stream_, addr_info->ai_addr,
                   addr_info->ai_addrlen) < 0) {
      std::cout << "ScrollView: Waiting for server...\n";
#ifdef _WIN32
      Sleep(1000);
#else
      sleep(1);
#endif

      stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);
    }
  }
  FreeAddrInfo(addr_info);
}

SVNetwork::~SVNetwork() {
  delete[] msg_buffer_in_;
  delete mutex_send_;
}

#endif  // GRAPHICS_DISABLED
<commit_msg>viewer/svutil: Fix memory leak<commit_after>///////////////////////////////////////////////////////////////////////
// File:        svutil.cpp
// Description: ScrollView Utilities
// Author:      Joern Wanke
// Created:     Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// SVUtil contains the SVSync and SVNetwork classes, which are used for
// thread/process creation & synchronization and network connection.

#include <stdio.h>
#ifdef _WIN32
struct addrinfo {
  struct sockaddr* ai_addr;
  int ai_addrlen;
  int ai_family;
  int ai_socktype;
  int ai_protocol;
};
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/socket.h>
#ifdef __linux__
#include <sys/prctl.h>
#endif
#include <unistd.h>
#endif

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>

// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
#include "config_auto.h"
#endif

#ifndef GRAPHICS_DISABLED

#include "svutil.h"

const int kMaxMsgSize = 4096;

// Signals a thread to exit.
void SVSync::ExitThread() {
#ifdef _WIN32
  // ExitThread(0);
#else
  pthread_exit(0);
#endif
}

// Starts a new process.
void SVSync::StartProcess(const char* executable, const char* args) {
  std::string proc;
  proc.append(executable);
  proc.append(" ");
  proc.append(args);
  std::cout << "Starting " << proc << std::endl;
#ifdef _WIN32
  STARTUPINFO start_info;
  PROCESS_INFORMATION proc_info;
  GetStartupInfo(&start_info);
  if (!CreateProcess(NULL, const_cast<char*>(proc.c_str()), NULL, NULL, FALSE,
                CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL,
                &start_info, &proc_info))
    return;
#else
  int pid = fork();
  if (pid != 0) {   // The father process returns
  } else {
#ifdef __linux__
    // Make sure the java process terminates on exit, since its
    // broken socket detection seems to be useless.
    prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
#endif
    char* mutable_args = strdup(args);
    int argc = 1;
    for (int i = 0; mutable_args[i]; ++i) {
      if (mutable_args[i] == ' ') {
        ++argc;
      }
    }
    char** argv = new char*[argc + 2];
    argv[0] = strdup(executable);
    argv[1] = mutable_args;
    argc = 2;
    bool inquote = false;
    for (int i = 0; mutable_args[i]; ++i) {
      if (!inquote && mutable_args[i] == ' ') {
        mutable_args[i] = '\0';
        argv[argc++] = mutable_args + i + 1;
      } else if (mutable_args[i] == '"') {
        inquote = !inquote;
        mutable_args[i] = ' ';
      }
    }
    argv[argc] = NULL;
    execvp(executable, argv);
    free(argv[0]);
    free(argv[1]);
    delete[] argv;
  }
#endif
}

SVSemaphore::SVSemaphore() {
#ifdef _WIN32
  semaphore_ = CreateSemaphore(0, 0, 10, 0);
#elif defined(__APPLE__)
  char name[50];
  snprintf(name, sizeof(name), "%ld", random());
  sem_unlink(name);
  semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
  if (semaphore_ == SEM_FAILED) {
    perror("sem_open");
  }
#else
  sem_init(&semaphore_, 0, 0);
#endif
}

void SVSemaphore::Signal() {
#ifdef _WIN32
  ReleaseSemaphore(semaphore_, 1, NULL);
#elif defined(__APPLE__)
  sem_post(semaphore_);
#else
  sem_post(&semaphore_);
#endif
}

void SVSemaphore::Wait() {
#ifdef _WIN32
  WaitForSingleObject(semaphore_, INFINITE);
#elif defined(__APPLE__)
  sem_wait(semaphore_);
#else
  sem_wait(&semaphore_);
#endif
}

SVMutex::SVMutex() {
#ifdef _WIN32
  mutex_ = CreateMutex(0, FALSE, 0);
#else
  pthread_mutex_init(&mutex_, NULL);
#endif
}

void SVMutex::Lock() {
#ifdef _WIN32
  WaitForSingleObject(mutex_, INFINITE);
#else
  pthread_mutex_lock(&mutex_);
#endif
}

void SVMutex::Unlock() {
#ifdef _WIN32
  ReleaseMutex(mutex_);
#else
  pthread_mutex_unlock(&mutex_);
#endif
}

// Create new thread.

void SVSync::StartThread(void *(*func)(void*), void* arg) {
#ifdef _WIN32
  LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE) func;
  DWORD threadid;
  HANDLE newthread = CreateThread(
  NULL,          // default security attributes
  0,             // use default stack size
  f,             // thread function
  arg,           // argument to thread function
  0,             // use default creation flags
  &threadid);    // returns the thread identifier
#else
  pthread_t helper;
  pthread_create(&helper, NULL, func, arg);
#endif
}

// Place a message in the message buffer (and flush it).
void SVNetwork::Send(const char* msg) {
  mutex_send_->Lock();
  msg_buffer_out_.append(msg);
  mutex_send_->Unlock();
}

// Send the whole buffer.
void SVNetwork::Flush() {
  mutex_send_->Lock();
  while (msg_buffer_out_.size() > 0) {
    int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
    msg_buffer_out_.erase(0, i);
  }
  mutex_send_->Unlock();
}

// Receive a message from the server.
// This will always return one line of char* (denoted by \n).
char* SVNetwork::Receive() {
  char* result = NULL;
#if defined(_WIN32) || defined(__CYGWIN__)
  if (has_content) { result = strtok (NULL, "\n"); }
#else
  if (buffer_ptr_ != NULL) { result = strtok_r(NULL, "\n", &buffer_ptr_); }
#endif

  // This means there is something left in the buffer and we return it.
  if (result != NULL) { return result;
  // Otherwise, we read from the stream_.
  } else {
    buffer_ptr_ = NULL;
    has_content = false;

    // The timeout length is not really important since we are looping anyway
    // until a new message is delivered.
    struct timeval tv;
    tv.tv_sec = 10;
    tv.tv_usec = 0;

    // Set the flags to return when the stream_ is ready to be read.
    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(stream_, &readfds);

    int i = select(stream_+1, &readfds, NULL, NULL, &tv);

    // The stream_ died.
    if (i == 0) { return NULL; }

    // Read the message buffer.
    i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);

    // Server quit (0) or error (-1).
    if (i <= 0) { return NULL; }
    msg_buffer_in_[i] = '\0';
    has_content = true;
#ifdef _WIN32
    return strtok(msg_buffer_in_, "\n");
#else
    // Setup a new string tokenizer.
    return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
#endif
  }
}

// Close the connection to the server.
void SVNetwork::Close() {
#ifdef _WIN32
  closesocket(stream_);
#else
  close(stream_);
#endif
}

// The program to invoke to start ScrollView
static const char* ScrollViewProg() {
#ifdef _WIN32
  const char* prog = "java -Xms512m -Xmx1024m";
#else
  const char* prog = "sh";
#endif
  return prog;
}

// The arguments to the program to invoke to start ScrollView
static std::string ScrollViewCommand(std::string scrollview_path) {
  // The following ugly ifdef is to enable the output of the java runtime
  // to be sent down a black hole on non-windows to ignore all the
  // exceptions in piccolo. Ideally piccolo would be debugged to make
  // this unnecessary.
  // Also the path has to be separated by ; on windows and : otherwise.
#ifdef _WIN32
  const char* cmd_template = "-Djava.library.path=%s -jar %s/ScrollView.jar";

#else
  const char* cmd_template = "-c \"trap 'kill %%1' 0 1 2 ; java "
      "-Xms1024m -Xmx2048m -jar %s/ScrollView.jar"
      " & wait\"";
#endif
  int cmdlen = strlen(cmd_template) + 4*strlen(scrollview_path.c_str()) + 1;
  char* cmd = new char[cmdlen];
  const char* sv_path = scrollview_path.c_str();
  snprintf(cmd, cmdlen, cmd_template, sv_path, sv_path, sv_path, sv_path);
  std::string command(cmd);
  delete [] cmd;
  return command;
}

// Platform-independent freeaddrinfo()
static void FreeAddrInfo(struct addrinfo* addr_info) {
  #if defined(__linux__)
  freeaddrinfo(addr_info);
  #else
  delete addr_info->ai_addr;
  delete addr_info;
  #endif
}

// Non-linux version of getaddrinfo()
#if !defined(__linux__)
static int GetAddrInfoNonLinux(const char* hostname, int port,
                               struct addrinfo** addr_info) {
// Get the host data depending on the OS.
  struct sockaddr_in* address;
  *addr_info = new struct addrinfo;
  memset(*addr_info, 0, sizeof(struct addrinfo));
  address = new struct sockaddr_in;
  memset(address, 0, sizeof(struct sockaddr_in));

  (*addr_info)->ai_addr = (struct sockaddr*) address;
  (*addr_info)->ai_addrlen = sizeof(struct sockaddr);
  (*addr_info)->ai_family = AF_INET;
  (*addr_info)->ai_socktype = SOCK_STREAM;

  struct hostent *name;
#ifdef _WIN32
  WSADATA wsaData;
  WSAStartup(MAKEWORD(1, 1), &wsaData);
  name = gethostbyname(hostname);
#else
  name = gethostbyname(hostname);
#endif

  if (name == NULL) {
    FreeAddrInfo(*addr_info);
    *addr_info = NULL;
    return -1;
  }

  // Fill in the appropriate variables to be able to connect to the server.
  address->sin_family = name->h_addrtype;
  memcpy((char *) &address->sin_addr.s_addr,
         name->h_addr_list[0], name->h_length);
  address->sin_port = htons(port);
  return 0;
}
#endif

// Platform independent version of getaddrinfo()
//   Given a hostname:port, produce an addrinfo struct
static int GetAddrInfo(const char* hostname, int port,
                       struct addrinfo** address) {
#if defined(__linux__)
  char port_str[40];
  snprintf(port_str, 40, "%d", port);
  return getaddrinfo(hostname, port_str, NULL, address);
#else
  return GetAddrInfoNonLinux(hostname, port, address);
#endif
}

// Set up a connection to a ScrollView on hostname:port.
SVNetwork::SVNetwork(const char* hostname, int port) {
  mutex_send_ = new SVMutex();
  msg_buffer_in_ = new char[kMaxMsgSize + 1];
  msg_buffer_in_[0] = '\0';

  has_content = false;
  buffer_ptr_ = NULL;

  struct addrinfo *addr_info = NULL;

  if (GetAddrInfo(hostname, port, &addr_info) != 0) {
    std::cerr << "Error resolving name for ScrollView host "
              << std::string(hostname) << ":" << port << std::endl;
  }

  stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);

  // If server is not there, we will start a new server as local child process.
  if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
    const char* scrollview_path = getenv("SCROLLVIEW_PATH");
    if (scrollview_path == NULL) {
#ifdef SCROLLVIEW_PATH
#define _STR(a) #a
#define _XSTR(a) _STR(a)
      scrollview_path = _XSTR(SCROLLVIEW_PATH);
#undef _XSTR
#undef _STR
#else
      scrollview_path = ".";
#endif
    }
    const char *prog = ScrollViewProg();
    std::string command = ScrollViewCommand(scrollview_path);
    SVSync::StartProcess(prog, command.c_str());

    // Wait for server to show up.
    // Note: There is no exception handling in case the server never turns up.

    stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);

    while (connect(stream_, addr_info->ai_addr,
                   addr_info->ai_addrlen) < 0) {
      std::cout << "ScrollView: Waiting for server...\n";
#ifdef _WIN32
      Sleep(1000);
#else
      sleep(1);
#endif

      stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
                   addr_info->ai_protocol);
    }
  }
  FreeAddrInfo(addr_info);
}

SVNetwork::~SVNetwork() {
  delete[] msg_buffer_in_;
  delete mutex_send_;
}

#endif  // GRAPHICS_DISABLED
<|endoftext|>


<commit_before>#include "core/lumix.h"
#include "core/MTJD/group.h"
#include "core/mt/atomic.h"

namespace Lumix
{
	namespace MTJD
	{
		Group::Group(bool sync_event)
			: BaseEntry(0, sync_event)
		{
		}

		Group::~Group()
		{
		}

		void Group::addStaticDependency(BaseEntry* entry)
		{
#if TYPE == MULTI_THREAD

			m_static_dependency_table.push(entry);
			if (m_dependency_count > 0)
			{
				entry->incrementDependency();
			}

#endif //TYPE == MULTI_THREAD
		}

		void Group::incrementDependency()
		{
#if TYPE == MULTI_THREAD

			uint32_t count = MT::atomicIncrement(&m_dependency_count);
			if (1 == count)
			{
				dependencyNotReady();
			}

#endif //TYPE == MULTI_THREAD
		}

		void Group::decrementDependency()
		{
#if TYPE == MULTI_THREAD

			uint32_t count = MT::atomicDecrement(&m_dependency_count);
			if (0 == count)
			{
				dependencyReady();
			}

			ASSERT(0 <= count);

#endif //TYPE == MULTI_THREAD
		}

		void Group::dependencyNotReady()
		{
#if TYPE == MULTI_THREAD

			for (uint32_t i = 0, c = m_static_dependency_table.size(); c > i; ++i)
			{
				m_static_dependency_table[i]->incrementDependency();
			}

			for (uint32_t i = 0, c = m_dependency_table.size(); c > i; ++i)
			{
				m_dependency_table[i]->incrementDependency();
			}

			if (m_sync_event)
			{
				m_sync_event->reset();
			}

#endif //TYPE == MULTI_THREAD
		}

		void Group::dependencyReady()
		{
#if TYPE == MULTI_THREAD

			BaseEntry::dependencyReady();

			for (uint32_t i = 0, c = m_static_dependency_table.size(); c > i; ++i)
			{
				m_static_dependency_table[i]->decrementDependency();
			}

#endif //TYPE == MULTI_THREAD
		}
	} // ~namepsace MTJD
} // ~namepsace Lumix
<commit_msg>fixes #314<commit_after>#include "core/lumix.h"
#include "core/MTJD/group.h"
#include "core/mt/atomic.h"

namespace Lumix
{
	namespace MTJD
	{
		Group::Group(bool sync_event)
			: BaseEntry(0, sync_event)
		{
		}

		Group::~Group()
		{
		}

		void Group::addStaticDependency(BaseEntry* entry)
		{
#if TYPE == MULTI_THREAD

			m_static_dependency_table.push(entry);
			if (m_dependency_count > 0)
			{
				entry->incrementDependency();
			}

#endif //TYPE == MULTI_THREAD
		}

		void Group::incrementDependency()
		{
#if TYPE == MULTI_THREAD

			int32_t count = MT::atomicIncrement(&m_dependency_count);
			if (1 == count)
			{
				dependencyNotReady();
			}

#endif //TYPE == MULTI_THREAD
		}

		void Group::decrementDependency()
		{
#if TYPE == MULTI_THREAD

			int32_t count = MT::atomicDecrement(&m_dependency_count);
			if (0 == count)
			{
				dependencyReady();
			}

			ASSERT(0 <= count);

#endif //TYPE == MULTI_THREAD
		}

		void Group::dependencyNotReady()
		{
#if TYPE == MULTI_THREAD

			for (uint32_t i = 0, c = m_static_dependency_table.size(); c > i; ++i)
			{
				m_static_dependency_table[i]->incrementDependency();
			}

			for (uint32_t i = 0, c = m_dependency_table.size(); c > i; ++i)
			{
				m_dependency_table[i]->incrementDependency();
			}

			if (m_sync_event)
			{
				m_sync_event->reset();
			}

#endif //TYPE == MULTI_THREAD
		}

		void Group::dependencyReady()
		{
#if TYPE == MULTI_THREAD

			BaseEntry::dependencyReady();

			for (uint32_t i = 0, c = m_static_dependency_table.size(); c > i; ++i)
			{
				m_static_dependency_table[i]->decrementDependency();
			}

#endif //TYPE == MULTI_THREAD
		}
	} // ~namepsace MTJD
} // ~namepsace Lumix
<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by Clément Pernet
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK 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.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */

//--------------------------------------------------------------------------
//                        Test for charpoly
//
//--------------------------------------------------------------------------
// Clement Pernet
//-------------------------------------------------------------------------

#include <iomanip>
#include <iostream>
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/field/modular-positive.h"
// #include "fflas-ffpack/field/modular-int.h"
#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/utils/Matio.h"
#include "fflas-ffpack/ffpack/ffpack.h"

#include "fflas-ffpack/utils/args-parser.h"

using namespace std;

//typedef ModularBalanced<double> Field;
typedef Givaro::ModularBalanced<double> Field;
//typedef Givaro::Modular<double> Field;
//typedef Givaro::Modular<float> Field;
//typedef Givaro::Modular<int> Field;
//typedef Givaro::Modular<double> Field;

typedef vector<Field::Element> Polynomial;

using namespace FFPACK;
template <class Field, class Polynomial>
void printPolynomial (const Field &F, const Polynomial &v)
{
	for (int i = v.size () - 1; i >= 0; i--) {
		F.write (cout, v[i]);
		if (i > 0)
			cout << " x^" << i << " + ";
	}
	cout << endl;
}

template<class Field>
bool launch_test(const Field & F, typename Field::Element * A, int n,
		 size_t p, size_t nbit, FFPACK::FFPACK_CHARPOLY_TAG CT)
{
 FFLAS::Timer tim,t; t.clear();tim.clear();
	list<Polynomial> P_list;
	for(size_t i = 0;i<nbit;++i){
		P_list.clear();
		t.clear();
		t.start();

		FFPACK::CharPoly (F, P_list, n, A, n, CT);
		t.stop();
		tim+=t;
		/*  test */
		// apply P_list.A.V and check 0 for random V
	}

#ifdef _FF_TIMING
	double mflops = (2+(2.0/3.0))*(n*n/1000000.0)*nbit*n/tim.usertime();
	list<Polynomial>::iterator P_it = P_list.begin();
	for (;P_it!=P_list.end();++P_it)
		printPolynomial ( F, *P_it);

	F.write(cerr<<"n = "<<n<<" #inv. fact = "<<P_list.size()<<" Charpoly (A) over ") << " : t= "
	<< tim.usertime()/nbit
	<< " s, Mffops = "<<mflops
	<< endl;

	cout<<n<<" "<<P_list.size()<<" "<<mflops<<" "<<tim.usertime()/nbit<<endl;
#endif
	return true ;

}

int main(int argc, char** argv)
{

	cerr<<setprecision(10);

	static size_t       p = 13; // characteristic
	static size_t       nbit = 2; // repetitions
	static int          n = 100;
	static std::string  file = "" ; // file where
	static int variant =0;

	static Argument as[] = {
		{ 'p', "-p P", "Set the field characteristic.", TYPE_INT , &p },
		{ 'n', "-n N", "Set the size of the matrix.", TYPE_INT , &p },
		{ 'r', "-r R", "Set number of repetitions.", TYPE_INT , &nbit },
		{ 'f', "-f file", "Set input file", TYPE_STR, &file },
		{ 'a', "-a algorithm", "Set the algorithm variant", TYPE_INT, &variant },
		END_OF_ARGUMENTS
	};
	FFLAS::parseArguments(argc,argv,as);

	FFPACK::FFPACK_CHARPOLY_TAG CT;
	switch (variant){
	    case 0: CT = FfpackLUK; break;
	    case 1: CT = FfpackKG; break;
	    case 2: CT = FfpackDanilevski; break;
	    case 3: CT = FfpackKGFast; break;
	    case 4: CT = FfpackKGFastG; break;
	    case 5: CT = FfpackHybrid; break;
	    case 6: CT = FfpackArithProg; break;
	    default: CT = FfpackLUK; break;
	}
	Field F((long unsigned int)p);
	Field::Element * A;
	if (!file.empty()) {
		const char * filestring = file.c_str();
		A = read_field<Field>(F,const_cast<char*>(filestring),&n,&n);
		bool passed = launch_test<Field>(F,A,n,p,nbit,CT);
		FFLAS::fflas_delete( A);
		return !passed ;
	}
	else {
		std::cerr << std::endl << "##################################"<< std::endl;
		std::cerr << std::endl << "  **** not implemented yet ! ***" << std::endl;
		std::cerr << std::endl << "##################################"<< std::endl;
		// create A random
		// create A diagonal
		// create A nilpotent
		// create A non invertible
		return false ;
	}

}

<commit_msg>correct n param<commit_after>/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by Clément Pernet
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK 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.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */

//--------------------------------------------------------------------------
//                        Test for charpoly
//
//--------------------------------------------------------------------------
// Clement Pernet
//-------------------------------------------------------------------------

#include <iomanip>
#include <iostream>
#include "fflas-ffpack/field/modular-balanced.h"
#include "fflas-ffpack/field/modular-positive.h"
// #include "fflas-ffpack/field/modular-int.h"
#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/utils/Matio.h"
#include "fflas-ffpack/ffpack/ffpack.h"

#include "fflas-ffpack/utils/args-parser.h"

using namespace std;

//typedef ModularBalanced<double> Field;
typedef Givaro::ModularBalanced<double> Field;
//typedef Givaro::Modular<double> Field;
//typedef Givaro::Modular<float> Field;
//typedef Givaro::Modular<int> Field;
//typedef Givaro::Modular<double> Field;

typedef vector<Field::Element> Polynomial;

using namespace FFPACK;
template <class Field, class Polynomial>
void printPolynomial (const Field &F, const Polynomial &v)
{
	for (int i = v.size () - 1; i >= 0; i--) {
		F.write (cout, v[i]);
		if (i > 0)
			cout << " x^" << i << " + ";
	}
	cout << endl;
}

template<class Field>
bool launch_test(const Field & F, typename Field::Element * A, int n,
		 size_t p, size_t nbit, FFPACK::FFPACK_CHARPOLY_TAG CT)
{
 FFLAS::Timer tim,t; t.clear();tim.clear();
	list<Polynomial> P_list;
	for(size_t i = 0;i<nbit;++i){
		P_list.clear();
		t.clear();
		t.start();

		FFPACK::CharPoly (F, P_list, n, A, n, CT);
		t.stop();
		tim+=t;
		/*  test */
		// apply P_list.A.V and check 0 for random V
	}

#ifdef _FF_TIMING
	double mflops = (2+(2.0/3.0))*(n*n/1000000.0)*nbit*n/tim.usertime();
	list<Polynomial>::iterator P_it = P_list.begin();
	for (;P_it!=P_list.end();++P_it)
		printPolynomial ( F, *P_it);

	F.write(cerr<<"n = "<<n<<" #inv. fact = "<<P_list.size()<<" Charpoly (A) over ") << " : t= "
	<< tim.usertime()/nbit
	<< " s, Mffops = "<<mflops
	<< endl;

	cout<<n<<" "<<P_list.size()<<" "<<mflops<<" "<<tim.usertime()/nbit<<endl;
#endif
	return true ;

}

int main(int argc, char** argv)
{

	cerr<<setprecision(10);

	static size_t       p = 13; // characteristic
	static size_t       nbit = 2; // repetitions
	static int          n = 100;
	static std::string  file = "" ; // file where
	static int variant =0;

	static Argument as[] = {
		{ 'p', "-p P", "Set the field characteristic.", TYPE_INT , &p },
		{ 'n', "-n N", "Set the size of the matrix.", TYPE_INT , &n },
		{ 'r', "-r R", "Set number of repetitions.", TYPE_INT , &nbit },
		{ 'f', "-f file", "Set input file", TYPE_STR, &file },
		{ 'a', "-a algorithm", "Set the algorithm variant", TYPE_INT, &variant },
		END_OF_ARGUMENTS
	};
	FFLAS::parseArguments(argc,argv,as);

	FFPACK::FFPACK_CHARPOLY_TAG CT;
	switch (variant){
	    case 0: CT = FfpackLUK; break;
	    case 1: CT = FfpackKG; break;
	    case 2: CT = FfpackDanilevski; break;
	    case 3: CT = FfpackKGFast; break;
	    case 4: CT = FfpackKGFastG; break;
	    case 5: CT = FfpackHybrid; break;
	    case 6: CT = FfpackArithProg; break;
	    default: CT = FfpackLUK; break;
	}
	Field F((long unsigned int)p);
	Field::Element * A;
	if (!file.empty()) {
		const char * filestring = file.c_str();
		A = read_field<Field>(F,const_cast<char*>(filestring),&n,&n);
		bool passed = launch_test<Field>(F,A,n,p,nbit,CT);
		FFLAS::fflas_delete( A);
		return !passed ;
	}
	else {
		std::cerr << std::endl << "##################################"<< std::endl;
		std::cerr << std::endl << "  **** not implemented yet ! ***" << std::endl;
		std::cerr << std::endl << "##################################"<< std::endl;
		// create A random
		// create A diagonal
		// create A nilpotent
		// create A non invertible
		return false ;
	}

}

<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN

#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include "yahttp/yahttp.hpp"
#include "yahttp/router.hpp"

using namespace boost;

class RouteTargetHandler {
public:
  static std::map<std::string, bool> routes;

  static bool Handler(YaHTTP::Request *req, YaHTTP::Response *resp) {
    std::cout << "Hello, got " << req->routeName << std::endl;
    routes[req->routeName] = true;
  }
} rth;

std::map<std::string, bool> RouteTargetHandler::routes;

struct RouterFixture {
  RouterFixture() {
    BOOST_TEST_MESSAGE("Setup router");
    YaHTTP::Router::Get("/test/<object>/<attribute>.<format>", rth.Handler, "object_attribute_format_get");
    YaHTTP::Router::Map("patch", "/test/<object>/<attribute>.<format>", rth.Handler, "object_attribute_format_update");
    YaHTTP::Router::Get("/test", rth.Handler, "test_index");
    YaHTTP::Router::Get("/", rth.Handler, "root_path");

    // reset routes to false
    BOOST_FOREACH(YaHTTP::TRoute route, YaHTTP::Router::GetRoutes()) {
#ifdef HAVE_CXX11
      rth.routes[std::get<3>(route)] = false;
#else
      rth.routes[route.get<3>()] = false;
#endif
    }

    // print routes
    YaHTTP::Router::PrintRoutes(std::cout);
  };

};

BOOST_FIXTURE_TEST_SUITE( test_router, RouterFixture )

BOOST_AUTO_TEST_CASE( test_router_basic ) {
  // setup request
  YaHTTP::Request req;
  YaHTTP::Response resp;
  req.setup("get", "http://test.org/");

  BOOST_CHECK(YaHTTP::Router::Route(&req, &resp));

  // check if it was hit
  BOOST_CHECK(rth.routes["root_path"]);
};

}
<commit_msg>Add missing return<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN

#include <boost/test/unit_test.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include "yahttp/yahttp.hpp"
#include "yahttp/router.hpp"

using namespace boost;

class RouteTargetHandler {
public:
  static std::map<std::string, bool> routes;

  static bool Handler(YaHTTP::Request *req, YaHTTP::Response *resp) {
    std::cout << "Hello, got " << req->routeName << std::endl;
    routes[req->routeName] = true;
    return true;
  }
} rth;

std::map<std::string, bool> RouteTargetHandler::routes;

struct RouterFixture {
  RouterFixture() {
    BOOST_TEST_MESSAGE("Setup router");
    YaHTTP::Router::Get("/test/<object>/<attribute>.<format>", rth.Handler, "object_attribute_format_get");
    YaHTTP::Router::Map("patch", "/test/<object>/<attribute>.<format>", rth.Handler, "object_attribute_format_update");
    YaHTTP::Router::Get("/test", rth.Handler, "test_index");
    YaHTTP::Router::Get("/", rth.Handler, "root_path");

    // reset routes to false
    BOOST_FOREACH(YaHTTP::TRoute route, YaHTTP::Router::GetRoutes()) {
#ifdef HAVE_CXX11
      rth.routes[std::get<3>(route)] = false;
#else
      rth.routes[route.get<3>()] = false;
#endif
    }

    // print routes
    YaHTTP::Router::PrintRoutes(std::cout);
  };

};

BOOST_FIXTURE_TEST_SUITE( test_router, RouterFixture )

BOOST_AUTO_TEST_CASE( test_router_basic ) {
  // setup request
  YaHTTP::Request req;
  YaHTTP::Response resp;
  req.setup("get", "http://test.org/");

  BOOST_CHECK(YaHTTP::Router::Route(&req, &resp));

  // check if it was hit
  BOOST_CHECK(rth.routes["root_path"]);
};

}
<|endoftext|>


<commit_before>/// Causal Dynamical Triangulations in C++ using CGAL
///
/// Copyright (c) 2014 Adam Getchell
///
/// A program that generates spacetimes
///
/// Inspired by https://github.com/ucdavis/CDT
///
/// \done Use Docopt
/// for a beautiful command line interface.

/// @file cdt.cpp
/// @brief The main body of the program
/// @author Adam Getchell
/// @bug
/// scan-build: No bugs found.

// CGAL headers
#include <CGAL/Timer.h>

// C++ headers
#include <iostream>
#include <cstdlib>
#include <map>
#include <string>
#include <vector>

// Docopt
#include "docopt/docopt.h"

// CDT headers
#include "./utilities.h"
#include "S3Triangulation.h"

// Help message parsed by docopt into options
static const char USAGE[] =
R"(Causal Dynamical Triangulations in C++ using CGAL.

Copyright (c) 2014 Adam Getchell

A program that generates d-dimensional triangulated spacetimes
with a defined causal structure and evolves them according
to the Metropolis algorithm. Specify the number of passes to control
how much evolution is desired. Each pass attempts a number of ergodic
moves equal to the number of simplices in the simulation.

Usage:./cdt (--spherical | --toroidal) -n SIMPLICES -t TIMESLICES [-d DIM] -k K --alpha ALPHA --lambda LAMBDA [-p PASSES]

Examples:
./cdt --spherical -n 64000 -t 256 --alpha 1.1 -k 2.2 --lambda 3.3 --passes 1000
./cdt --s -n64000 -t256 -a1.1 -k2.2 -l3.3 -p1000

Options:
  -h --help             Show this message
  --version             Show program version
  -n SIMPLICES          Approximate number of simplices
  -t TIMESLICES         Number of timeslices
  -d DIM                Dimensionality [default: 3]
  -a --alpha ALPHA      Negative squared geodesic length of 1-d timelike edges
  -k K                  K = 1/(8*pi*G_newton)
  -l --lambda LAMBDA    K * Cosmological constant
  -p --passes PASSES    Number of passes [default: 10000]
)";

int main(int argc, char const *argv[]) {
  // Start running time
  CGAL::Timer t;
  t.start();

  // docopt option parser
  std::map<std::string, docopt::value> args
    = docopt::docopt(USAGE,
                     { argv + 1, argv + argc},
                     true,          // print help message automatically
                     "CDT 1.0");    // Version

  enum topology_type { TOROIDAL, SPHERICAL};

  // These contain cell handles for the (3,1), (2,2), and (1,3) simplices
  std::vector<Cell_handle> three_one;
  std::vector<Cell_handle> two_two;
  std::vector<Cell_handle> one_three;

  // Debugging
  // for (auto const& arg : args) {
  //   std::cout << arg.first << " " << arg.second << std::endl;
  // }

  // Parse docopt::values in args map
  unsigned simplices = std::stoul(args["-n"].asString());
  unsigned timeslices = std::stoul(args["-t"].asString());
  unsigned dimensions = std::stoul(args["-d"].asString());
  long double alpha = std::stold(args["--alpha"].asString());
  long double k = std::stold(args["-k"].asString());
  long double lambda = std::stold(args["--lambda"].asString());
  unsigned passes = std::stoul(args["--passes"].asString());

  // Topology of simulation
  topology_type topology;
  if (args["--spherical"].asBool() == true) {
    topology = SPHERICAL;
  } else {
    topology = TOROIDAL;
  }

  // Display job parameters
  std::cout << "Topology is "
  << (topology == TOROIDAL ? " toroidal " : "spherical ") << std::endl;
  std::cout << "Number of dimensions = " << dimensions << std::endl;
  std::cout << "Number of simplices = " << simplices << std::endl;
  std::cout << "Number of timeslices = " << timeslices << std::endl;
  std::cout << "Alpha = " << alpha << std::endl;
  std::cout << "K = " << k << std::endl;
  std::cout << "Lambda = " << lambda << std::endl;
  std::cout << "Number of passes = " << passes << std::endl;
  std::cout << "User = " << getEnvVar("USER") << std::endl;
  std::cout << "Hostname = " << hostname() << std::endl;

  // Initialize spherical Delaunay triangulation
  Delaunay Sphere3;

  // Ensure Triangle inequalities hold
  // See http://arxiv.org/abs/hep-th/0105267 for details
  if (dimensions == 3 && std::abs(alpha) < 0.5) {
    std::cout << "Alpha in 3D should be greater than 1/2." << std::endl;
    std::cout << "Triangle inequalities violated ... Exiting." << std::endl;
    return 1;
  }

  switch (topology) {
    case SPHERICAL:
      if (dimensions == 3) {
        make_S3_triangulation(&Sphere3, simplices, timeslices, false,
                              &three_one, &two_two, &one_three);
      } else {
        std::cout << "Currently, dimensions cannot be higher than 3.";
        std::cout << std::endl;
      }
      break;
    case TOROIDAL:
      std::cout << "make_T3_triangulation not implemented yet." << std::endl;
      t.stop();  // End running time counter
      break;
  }

  std::cout << "Universe has been initialized ..." << std::endl;
  std::cout << "Now performing " << passes << " passes of ergodic moves."
            << std::endl;

  // TODO: Ergodic moves

  // Output results
  t.stop();  // End running time counter
  std::cout << "Final Delaunay triangulation has ";
  print_results(&Sphere3, &t);

  // Write results to file
  // TODO: Fixup so that cell->info() and vertex->info() values are written
  write_file(&Sphere3, 's', dimensions, Sphere3.number_of_finite_cells(),
             timeslices);

  return 0;
}
<commit_msg>Initialize data and data structures for ergodic moves<commit_after>/// Causal Dynamical Triangulations in C++ using CGAL
///
/// Copyright (c) 2014 Adam Getchell
///
/// A program that generates spacetimes
///
/// Inspired by https://github.com/ucdavis/CDT
///
/// \todo Invoke complete set of ergodic (Pachner) moves
/// \todo Use Metropolis-Hastings algorithm
/// \todo Fix write_file() to include cell->info() and vertex->info()
/// \done Use docopt
/// for a beautiful command line interface.

/// @file cdt.cpp
/// @brief The main body of the program
/// @author Adam Getchell
/// @bug
/// scan-build: No bugs found.

// CGAL headers
#include <CGAL/Timer.h>

// C++ headers
#include <iostream>
#include <cstdlib>
#include <map>
#include <string>
#include <vector>

// Docopt
#include "docopt/docopt.h"

// CDT headers
#include "./utilities.h"
#include "S3Triangulation.h"

/// Help message parsed by docopt into options
static const char USAGE[] =
R"(Causal Dynamical Triangulations in C++ using CGAL.

Copyright (c) 2014 Adam Getchell

A program that generates d-dimensional triangulated spacetimes
with a defined causal structure and evolves them according
to the Metropolis algorithm. Specify the number of passes to control
how much evolution is desired. Each pass attempts a number of ergodic
moves equal to the number of simplices in the simulation.

Usage:./cdt (--spherical | --toroidal) -n SIMPLICES -t TIMESLICES [-d DIM] -k K --alpha ALPHA --lambda LAMBDA [-p PASSES]

Examples:
./cdt --spherical -n 64000 -t 256 --alpha 1.1 -k 2.2 --lambda 3.3 --passes 1000
./cdt --s -n64000 -t256 -a1.1 -k2.2 -l3.3 -p1000

Options:
  -h --help             Show this message
  --version             Show program version
  -n SIMPLICES          Approximate number of simplices
  -t TIMESLICES         Number of timeslices
  -d DIM                Dimensionality [default: 3]
  -a --alpha ALPHA      Negative squared geodesic length of 1-d timelike edges
  -k K                  K = 1/(8*pi*G_newton)
  -l --lambda LAMBDA    K * Cosmological constant
  -p --passes PASSES    Number of passes [default: 10000]
)";

/// @brief The main path of the CDT++ program
///
/// @param[in,out]  argc  Argument count = 1 + number of arguments
/// @param[in,out]  argv  Argument vector (array) to be passed to docopt
/// @return         Integer value 0 if successful, 1 on failure
int main(int argc, char* const argv[]) {
  // Start running time
  CGAL::Timer t;
  t.start();

  // docopt option parser
  std::map<std::string, docopt::value> args
    = docopt::docopt(USAGE,
                     { argv + 1, argv + argc},
                     true,          // print help message automatically
                     "CDT 1.0");    // Version

  enum topology_type { TOROIDAL, SPHERICAL};

  // Debugging
  // for (auto const& arg : args) {
  //   std::cout << arg.first << " " << arg.second << std::endl;
  // }

  // Parse docopt::values in args map
  unsigned simplices = std::stoul(args["-n"].asString());
  unsigned timeslices = std::stoul(args["-t"].asString());
  unsigned dimensions = std::stoul(args["-d"].asString());
  long double alpha = std::stold(args["--alpha"].asString());
  long double k = std::stold(args["-k"].asString());
  long double lambda = std::stold(args["--lambda"].asString());
  unsigned passes = std::stoul(args["--passes"].asString());

  // Topology of simulation
  topology_type topology;
  if (args["--spherical"].asBool() == true) {
    topology = SPHERICAL;
  } else {
    topology = TOROIDAL;
  }

  // Display job parameters
  std::cout << "Topology is "
  << (topology == TOROIDAL ? " toroidal " : "spherical ") << std::endl;
  std::cout << "Number of dimensions = " << dimensions << std::endl;
  std::cout << "Number of simplices = " << simplices << std::endl;
  std::cout << "Number of timeslices = " << timeslices << std::endl;
  std::cout << "Alpha = " << alpha << std::endl;
  std::cout << "K = " << k << std::endl;
  std::cout << "Lambda = " << lambda << std::endl;
  std::cout << "Number of passes = " << passes << std::endl;
  std::cout << "User = " << getEnvVar("USER") << std::endl;
  std::cout << "Hostname = " << hostname() << std::endl;

  // Initialize spherical Delaunay triangulation
  Delaunay Sphere3;

  // These contain cell handles for the (3,1), (2,2), and (1,3) simplices
  std::vector<Cell_handle> three_one;
  std::vector<Cell_handle> two_two;
  std::vector<Cell_handle> one_three;

  // Ensure Triangle inequalities hold
  // See http://arxiv.org/abs/hep-th/0105267 for details
  if (dimensions == 3 && std::abs(alpha) < 0.5) {
    std::cout << "Alpha in 3D should be greater than 1/2." << std::endl;
    std::cout << "Triangle inequalities violated ... Exiting." << std::endl;
    return 1;
  }

  switch (topology) {
    case SPHERICAL:
      if (dimensions == 3) {
        make_S3_triangulation(&Sphere3, simplices, timeslices, false,
                              &three_one, &two_two, &one_three);
      } else {
        std::cout << "Currently, dimensions cannot be higher than 3.";
        std::cout << std::endl;
      }
      break;
    case TOROIDAL:
      std::cout << "make_T3_triangulation not implemented yet." << std::endl;
      t.stop();  // End running time counter
      break;
  }

  std::cout << "Universe has been initialized ..." << std::endl;
  std::cout << "Now performing " << passes << " passes of ergodic moves."
            << std::endl;

  // TODO: Ergodic moves using Metropolis algorithm
  // Initialize data and data structures needed for ergodic moves
  //
  // make_23_move(&Sphere3, &two_two) does the (2,2) move
  // These hold the timelike edges needed for a (3,2) move
  std::vector<Edge_tuple> V2;
  unsigned N1_SL{0};

  // Get timelike edges V2 that make_32_move(&Sphere3, &V2) can be called on
  get_timelike_edges(&Sphere3, &V2, &N1_SL);

  // Metropolis algorithm to select moves goes here

  // Output results
  t.stop();  // End running time counter
  std::cout << "Final Delaunay triangulation has ";
  print_results(&Sphere3, &t);

  // Write results to file
  // TODO: Fixup so that cell->info() and vertex->info() values are written
  write_file(&Sphere3, 's', dimensions, Sphere3.number_of_finite_cells(),
             timeslices);

  return 0;
}
<|endoftext|>


<commit_before>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "trackerstore.h"
#include <QSparqlConnection>
#include <QSparqlQuery>
#include <QUrl>
#if defined(QT4)
#include <QDeclarativeInfo>
#elif defined(QT5)
#include <QQmlInfo>
#endif
#include <QSparqlResult>
#include <QScopedPointer>
#include <QSparqlError>
#include <QDebug>
#include <QDateTime>

#define BEGIN_IMAGE "INSERT { _:x a nfo:Image, nmm:Photo"
#define BEGIN_VIDEO "INSERT { _:x a nfo:Video, nmm:Video"
#define QUERY_END ", nie:DataObject, nie:InformationElement, nfo:Media, nfo:Visual ; nie:url ?:file_url ; nfo:equipment ?:equipment^^xsd:string ; nie:contentCreated ?:contentCreated . }"

#define IMAGE_QUERY BEGIN_IMAGE QUERY_END
#define VIDEO_QUERY BEGIN_VIDEO QUERY_END

TrackerStore::TrackerStore(QObject *parent) :
  QObject(parent),
  m_connection(0) {

}

TrackerStore::~TrackerStore() {

}

bool TrackerStore::isActive() const {
  return m_connection != 0;
}

void TrackerStore::setActive(bool active) {
  if (isActive() == active) {
    return;
  }

  if (active) {
    m_connection = new QSparqlConnection("QTRACKER_DIRECT", QSparqlConnectionOptions(), this);
  }
  else {
    m_connection->deleteLater();
    m_connection = 0;
  }

  emit activeChanged();
}

QString TrackerStore::manufacturer() const {
  return m_manufacturer;
}

void TrackerStore::setManufacturer(const QString& manufacturer) {
  if (m_manufacturer != manufacturer) {
    m_manufacturer = manufacturer;
    emit manufacturerChanged();
  }
}

QString TrackerStore::model() const {
  return m_model;
}

void TrackerStore::setModel(const QString& model) {
  if (m_model != model) {
    m_model = model;
    emit modelChanged();
  }
}

void TrackerStore::storeImage(const QString& path) {
  execQuery(IMAGE_QUERY, path);
}

void TrackerStore::storeVideo(const QString& path) {
  execQuery(VIDEO_QUERY, path);
}

bool TrackerStore::execQuery(const QString& query, const QString& path) {
  QDateTime dateTime = QDateTime::currentDateTime();

  if (!isActive()) {
    qmlInfo(this) << "TrackerStore is not active";
    return false;
  }

  QString equipment = QString("urn:equipment:%1:%2:").arg(m_manufacturer).arg(m_model);

  QSparqlQuery q(query, QSparqlQuery::InsertStatement);
  q.bindValue("file_url", QUrl::fromLocalFile(path));
  q.bindValue("equipment", equipment);
  q.bindValue("contentCreated", dateTime.toString(Qt::ISODate) +
		  "." + QString().sprintf("%.3d", dateTime.time().msec()));

  return exec(q);
}

bool TrackerStore::exec(QSparqlQuery& q) {
  QScopedPointer<QSparqlResult> r(m_connection->syncExec(q));

  if (!r->hasError()) {
    return true;
  }

  while (r->next()) {
    // Nothing
  }

  qmlInfo(this) << "QtSparql error:" << r->lastError().message();

  return false;
}
<commit_msg>Revert "Revert "sailfish: don't create a virtual tracker file before capturing media""<commit_after>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "trackerstore.h"
#include <QSparqlConnection>
#include <QSparqlQuery>
#include <QUrl>
#if defined(QT4)
#include <QDeclarativeInfo>
#elif defined(QT5)
#include <QQmlInfo>
#endif
#include <QSparqlResult>
#include <QScopedPointer>
#include <QSparqlError>
#include <QDebug>
#include <QDateTime>

#define BEGIN_IMAGE "INSERT { _:x a nfo:Image, nmm:Photo"
#define BEGIN_VIDEO "INSERT { _:x a nfo:Video, nmm:Video"
#define QUERY_END ", nie:DataObject, nie:InformationElement, nfo:Media, nfo:Visual ; nie:url ?:file_url ; nfo:equipment ?:equipment^^xsd:string ; nie:contentCreated ?:contentCreated . }"

#define IMAGE_QUERY BEGIN_IMAGE QUERY_END
#define VIDEO_QUERY BEGIN_VIDEO QUERY_END

TrackerStore::TrackerStore(QObject *parent) :
  QObject(parent),
  m_connection(0) {

}

TrackerStore::~TrackerStore() {

}

bool TrackerStore::isActive() const {
  return m_connection != 0;
}

void TrackerStore::setActive(bool active) {
  if (isActive() == active) {
    return;
  }

  if (active) {
    m_connection = new QSparqlConnection("QTRACKER_DIRECT", QSparqlConnectionOptions(), this);
  }
  else {
    m_connection->deleteLater();
    m_connection = 0;
  }

  emit activeChanged();
}

QString TrackerStore::manufacturer() const {
  return m_manufacturer;
}

void TrackerStore::setManufacturer(const QString& manufacturer) {
  if (m_manufacturer != manufacturer) {
    m_manufacturer = manufacturer;
    emit manufacturerChanged();
  }
}

QString TrackerStore::model() const {
  return m_model;
}

void TrackerStore::setModel(const QString& model) {
  if (m_model != model) {
    m_model = model;
    emit modelChanged();
  }
}

void TrackerStore::storeImage(const QString& path) {
#ifdef HARMATTAN
  execQuery(IMAGE_QUERY, path);
#else
  Q_UNUSED(path);
#endif
}

void TrackerStore::storeVideo(const QString& path) {
#ifdef HARMATTAN
  execQuery(VIDEO_QUERY, path);
#else
  Q_UNUSED(path);
#endif
}

bool TrackerStore::execQuery(const QString& query, const QString& path) {
  QDateTime dateTime = QDateTime::currentDateTime();

  if (!isActive()) {
    qmlInfo(this) << "TrackerStore is not active";
    return false;
  }

  QString equipment = QString("urn:equipment:%1:%2:").arg(m_manufacturer).arg(m_model);

  QSparqlQuery q(query, QSparqlQuery::InsertStatement);
  q.bindValue("file_url", QUrl::fromLocalFile(path));
  q.bindValue("equipment", equipment);
  q.bindValue("contentCreated", dateTime.toString(Qt::ISODate) +
		  "." + QString().sprintf("%.3d", dateTime.time().msec()));

  return exec(q);
}

bool TrackerStore::exec(QSparqlQuery& q) {
  QScopedPointer<QSparqlResult> r(m_connection->syncExec(q));

  if (!r->hasError()) {
    return true;
  }

  while (r->next()) {
    // Nothing
  }

  qmlInfo(this) << "QtSparql error:" << r->lastError().message();

  return false;
}
<|endoftext|>


<commit_before>// Standard tutorial macro for performing an inverted  hypothesis test
//
// This macro will perform a scan of tehe p-values for computing the limit
//

#include "TFile.h"
#include "RooWorkspace.h"
#include "RooAbsPdf.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooStats/ModelConfig.h"
#include "TGraphErrors.h"
#include "TGraphAsymmErrors.h"
#include "TCanvas.h"
#include "TLine.h"

#include "RooStats/HybridCalculator.h"
#include "RooStats/FrequentistCalculator.h"
#include "RooStats/ToyMCSampler.h"
#include "RooStats/HypoTestPlot.h"

#include "RooStats/NumEventsTestStat.h"
#include "RooStats/ProfileLikelihoodTestStat.h"
#include "RooStats/SimpleLikelihoodRatioTestStat.h"
#include "RooStats/RatioOfProfiledLikelihoodsTestStat.h"
#include "RooStats/MaxLikelihoodEstimateTestStat.h"

#include "RooStats/HypoTestInverter.h"
#include "RooStats/HypoTestInverterResult.h"
#include "RooStats/HypoTestInverterPlot.h"

using namespace RooFit;
using namespace RooStats;

bool plotHypoTestResult = true;
bool useProof = true;
bool optimize = false;
bool writeResult = false;
int nworkers = 2;

// internal routine to run the inverter
HypoTestInverterResult * RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName, const char * dataName,
                                     int type,  int testStatType, int npoints, double poimin, double poimax, int ntoys, bool useCls );

void StandardHypoTestInvDemo(const char * fileName =0,
                             const char * wsName = "combined",
                             const char * modelSBName = "ModelConfig",
                             const char * modelBName = "",
                             const char * dataName = "obsData",
                             int calculatorType = 0,
                             int testStatType = 3,
                             bool useCls = true ,
                             int npoints = 5,
                             double poimin = 0,
                             double poimax = 5,
                             int ntoys=1000 )
{
/*

   Other Parameter to pass in tutorial
   apart from standard for filename, ws, modelconfig and data

    type = 0 Freq calculator
    type = 1 Hybrid

    testStatType = 0 LEP
                 = 1 Tevatron
                 = 2 Profile Likelihood
                 = 3 Profile Likelihood one sided (i.e. = 0 if mu < mu_hat)

    useCLs          scan for CLs (otherwise for CLs+b)

    npoints:        number of points to scan , for autoscan set npoints = -1

    poimin,poimax:  min/max value to scan in case of fixed scans
                    (if min >= max, try to find automatically)

    ntoys:         number of toys to use

    extra options are available as global paramters of the macro. They are:

    plotHypoTestResult   plot result of tests at each point (TS distributions)
    useProof = true;
    writeResult = true;
    nworkers = 4;

   */

   if (fileName==0) {
      fileName = "results/example_combined_GaussExample_model.root";
      std::cout << "Use standard file generated with HistFactory :" << fileName << std::endl;
   }
   TFile * file = new TFile(fileName);

   RooWorkspace * w = dynamic_cast<RooWorkspace*>( file->Get(wsName) );
   HypoTestInverterResult * r = 0;
   std::cout << w << "\t" << fileName << std::endl;
   if (w != NULL) {
      r = RunInverter(w, modelSBName, modelBName, dataName, calculatorType, testStatType, npoints, poimin, poimax,  ntoys, useCls );
      if (!r) {
         std::cerr << "Error running the HypoTestInverter - Exit " << std::endl;
         return;
      }
   }
   else
   {
      // case workspace is not present look for the inverter result
      std::cout << "Reading an HypoTestInverterResult with name " << wsName << " from file " << fileName << std::endl;
      r = dynamic_cast<HypoTestInverterResult*>( file->Get(wsName) ); //
      if (!r) {
         std::cerr << "File " << fileName << " does not contain a workspace or an HypoTestInverterResult - Exit "
                   << std::endl;
         file->ls();
         return;
      }
   }

   double upperLimit = r->UpperLimit();
   double ulError = r->UpperLimitEstimatedError();

   std::cout << "The computed upper limit is: " << upperLimit << " +/- " << ulError << std::endl;

   const int nEntries = r->ArraySize();

   const char *  typeName = (calculatorType == 0) ? "Frequentist" : "Hybrid";
   const char * resultName = (w) ? w->GetName() : r->GetName();
   TString plotTitle = TString::Format("%s CL Scan for workspace %s",typeName,resultName);
   HypoTestInverterPlot *plot = new HypoTestInverterPlot("HTI_Result_Plot",plotTitle,r);
   plot->Draw("CLb 2CL");  // plot all and Clb

   if (plotHypoTestResult) {
      TCanvas * c2 = new TCanvas();
      c2->Divide( 2, TMath::Ceil(nEntries/2));
      for (int i=0; i<nEntries; i++) {
         c2->cd(i+1);
         SamplingDistPlot * pl = plot->MakeTestStatPlot(i);
         pl->SetLogYaxis(true);
         pl->Draw();
      }
   }

   std::cout << " expected limit (median) " <<  r->GetExpectedUpperLimit(0) << std::endl;
   std::cout << " expected limit (-1 sig) " << r->GetExpectedUpperLimit(-1) << std::endl;
   std::cout << " expected limit (+1 sig) " << r->GetExpectedUpperLimit(1) << std::endl;

   if (w != NULL && writeResult) {

      // write to a file the results
      const char *  calcType = (calculatorType == 0) ? "Freq" : "Hybr";
      const char *  limitType = (useCls) ? "CLs" : "Cls+b";
      const char * scanType = (npoints < 0) ? "auto" : "grid";
      TString resultFileName = TString::Format("%s_%s_%s_ts%d_",calcType,limitType,scanType,testStatType);
      resultFileName += fileName;

      TFile * fileOut = new TFile(resultFileName,"RECREATE");
      r->Write();
      fileOut->Close();
   }

}

// internal routine to run the inverter
HypoTestInverterResult *  RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName,
                                      const char * dataName, int type,  int testStatType,
                                      int npoints, double poimin, double poimax,
                                      int ntoys, bool useCls )
{

   std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl;

   w->Print();

   RooAbsData * data = w->data(dataName);
   if (!data) {
      Error("StandardHypoTestDemo","Not existing data %s",dataName);
      return 0;
   }
   else
      std::cout << "Using data set " << dataName << std::endl;

   // get models from WS
   // get the modelConfig out of the file
   ModelConfig* bModel = (ModelConfig*) w->obj(modelBName);
   ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName);

   if (!sbModel) {
      Error("StandardHypoTestDemo","Not existing ModelConfig %s",modelSBName);
      return 0;
   }
   // check the model
   if (!sbModel->GetPdf()) {
      Error("StandardHypoTestDemo","Model %s has no pdf ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestInvDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetSnapshot() ) {
      Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi",modelSBName);
      sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() );
   }

   if (!bModel || bModel == sbModel) {
      Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName);
      Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName);
      bModel = (ModelConfig*) sbModel->Clone();
      bModel->SetName(TString(modelSBName)+TString("_with_poi_0"));
      RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
      if (!var) return 0;
      double oldval = var->getVal();
      var->setVal(0);
      bModel->SetSnapshot( RooArgSet(*var)  );
      var->setVal(oldval);
   }
   else {
      if (!bModel->GetSnapshot() ) {
         Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi and 0 values ",modelBName);
         RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
         if (var) {
            double oldval = var->getVal();
            var->setVal(0);
            bModel->SetSnapshot( RooArgSet(*var)  );
            var->setVal(oldval);
         }
         else {
            Error("StandardHypoTestInvDemo","Model %s has no valid poi",modelBName);
            return 0;
         }
      }
   }

   SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf());
   if (sbModel->GetSnapshot()) slrts.SetNullParameters(*sbModel->GetSnapshot());
   if (bModel->GetSnapshot()) slrts.SetAltParameters(*bModel->GetSnapshot());

   // ratio of profile likelihood - need to pass snapshot for the alt
   RatioOfProfiledLikelihoodsTestStat
      ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot());
   ropl.SetSubtractMLE(false);

   ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
   if (testStatType == 3) profll.SetOneSided(1);
   if (optimize) profll.SetReuseNLL(true);

   TestStatistic * testStat = &slrts;
   if (testStatType == 1) testStat = &ropl;
   if (testStatType == 2 || testStatType == 3) testStat = &profll;

   HypoTestCalculatorGeneric *  hc = 0;
   if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel);
   else hc = new HybridCalculator(*data, *bModel, *sbModel);

   ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
   //toymcs->SetNEventsPerToy(1);
   toymcs->SetTestStatistic(testStat);
   if (optimize) toymcs->SetUseMultiGen(true);

   if (type == 1) {
      HybridCalculator *hhc = (HybridCalculator*) hc;
      hhc->SetToys(ntoys,ntoys);

      // check for nuisance prior pdf
      if (bModel->GetPriorPdf() && sbModel->GetPriorPdf() ) {
         hhc->ForcePriorNuisanceAlt(*bModel->GetPriorPdf());
         hhc->ForcePriorNuisanceNull(*sbModel->GetPriorPdf());
      }
      else {
         if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) {
            Error("StandardHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified");
            return 0;
         }
      }
   }
   else
      ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys);

   // Get the result
   RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);

   TStopwatch tw; tw.Start();
   const RooArgSet * poiSet = sbModel->GetParametersOfInterest();
   RooRealVar *poi = (RooRealVar*)poiSet->first();

   // fit the data first
   sbModel->GetPdf()->fitTo(*data);
   double poihat  = poi->getVal();

   HypoTestInverter calc(*hc);
   calc.SetConfidenceLevel(0.95);

   calc.UseCLs(useCls);
   calc.SetVerbose(true);

   // can speed up using proof-lite
   if (useProof && nworkers > 1) {
      ProofConfig pc(*w, nworkers, "", kFALSE);
      toymcs->SetProofConfig(&pc);    // enable proof
   }

   if (npoints > 0) {
      if (poimin >= poimax) {
         // if no min/max given scan between MLE and +4 sigma
         poimin = int(poihat);
         poimax = int(poihat +  4 * poi->getError());
      }
      std::cout << "Doing a fixed scan  in interval : " << poimin << " , " << poimax << std::endl;
      calc.SetFixedScan(npoints,poimin,poimax);
   }
   else {
      //poi->setMax(10*int( (poihat+ 10 *poi->getError() )/10 ) );
      std::cout << "Doing an  automatic scan  in interval : " << poi->getMin() << " , " << poi->getMax() << std::endl;
   }

   HypoTestInverterResult * r = calc.GetInterval();

   return r;
}

void ReadResult(const char * fileName, const char * resultName="", bool useCLs=true) {
   // read a previous stored result from a file given the result name

   StandardHypoTestInvDemo(fileName, resultName,"","","",0,0,useCLs);
}

int main() {
   StandardHypoTestInvDemo();
}
<commit_msg>new version of tutorial with:   - fixed treatment of nuisance prior when using HybridCalculator by adding the  possibility    for user to pass the name of the nuisance pdf<commit_after>// Standard tutorial macro for performing an inverted  hypothesis test
//
// This macro will perform a scan of tehe p-values for computing the limit
//

#include "TFile.h"
#include "RooWorkspace.h"
#include "RooAbsPdf.h"
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooStats/ModelConfig.h"
#include "TGraphErrors.h"
#include "TGraphAsymmErrors.h"
#include "TCanvas.h"
#include "TLine.h"

#include "RooStats/HybridCalculator.h"
#include "RooStats/FrequentistCalculator.h"
#include "RooStats/ToyMCSampler.h"
#include "RooStats/HypoTestPlot.h"

#include "RooStats/NumEventsTestStat.h"
#include "RooStats/ProfileLikelihoodTestStat.h"
#include "RooStats/SimpleLikelihoodRatioTestStat.h"
#include "RooStats/RatioOfProfiledLikelihoodsTestStat.h"
#include "RooStats/MaxLikelihoodEstimateTestStat.h"

#include "RooStats/HypoTestInverter.h"
#include "RooStats/HypoTestInverterResult.h"
#include "RooStats/HypoTestInverterPlot.h"

using namespace RooFit;
using namespace RooStats;

bool plotHypoTestResult = true;
bool useProof = true;
bool optimize = false;
bool writeResult = false;
int nworkers = 2;

// internal routine to run the inverter
HypoTestInverterResult * RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName, const char * dataName,
                                     int type,  int testStatType, int npoints, double poimin, double poimax, int ntoys,
                                     bool useCls, bool useNumberCounting, const char * nuisPriorName);

void StandardHypoTestInvDemo(const char * fileName =0,
                             const char * wsName = "combined",
                             const char * modelSBName = "ModelConfig",
                             const char * modelBName = "",
                             const char * dataName = "obsData",
                             int calculatorType = 0,
                             int testStatType = 3,
                             bool useCls = true ,
                             int npoints = 5,
                             double poimin = 0,
                             double poimax = 5,
                             int ntoys=1000,
                             bool useNumberCounting = false,
                             const char * nuisPriorName = 0)
{
/*

   Other Parameter to pass in tutorial
   apart from standard for filename, ws, modelconfig and data

    type = 0 Freq calculator
    type = 1 Hybrid

    testStatType = 0 LEP
                 = 1 Tevatron
                 = 2 Profile Likelihood
                 = 3 Profile Likelihood one sided (i.e. = 0 if mu < mu_hat)

    useCLs          scan for CLs (otherwise for CLs+b)

    npoints:        number of points to scan , for autoscan set npoints = -1

    poimin,poimax:  min/max value to scan in case of fixed scans
                    (if min >= max, try to find automatically)

    ntoys:         number of toys to use

    useNumberCounting:  set to true when using number counting events

    nuisPriorName:   name of prior for the nnuisance. This is often expressed as constraint term in the global model
                     It is needed only when using the HybridCalculator (type=1)
                     If not given by default the prior pdf from ModelConfig is used.

    extra options are available as global paramters of the macro. They are:

    plotHypoTestResult   plot result of tests at each point (TS distributions)
    useProof = true;
    writeResult = true;
    nworkers = 4;

   */

   if (fileName==0) {
      fileName = "results/example_combined_GaussExample_model.root";
      std::cout << "Use standard file generated with HistFactory :" << fileName << std::endl;
   }
   TFile * file = new TFile(fileName);

   RooWorkspace * w = dynamic_cast<RooWorkspace*>( file->Get(wsName) );
   HypoTestInverterResult * r = 0;
   std::cout << w << "\t" << fileName << std::endl;
   if (w != NULL) {
      r = RunInverter(w, modelSBName, modelBName, dataName, calculatorType, testStatType, npoints, poimin, poimax,
                      ntoys, useCls, useNumberCounting, nuisPriorName );
      if (!r) {
         std::cerr << "Error running the HypoTestInverter - Exit " << std::endl;
         return;
      }
   }
   else
   {
      // case workspace is not present look for the inverter result
      std::cout << "Reading an HypoTestInverterResult with name " << wsName << " from file " << fileName << std::endl;
      r = dynamic_cast<HypoTestInverterResult*>( file->Get(wsName) ); //
      if (!r) {
         std::cerr << "File " << fileName << " does not contain a workspace or an HypoTestInverterResult - Exit "
                   << std::endl;
         file->ls();
         return;
      }
   }

   double upperLimit = r->UpperLimit();
   double ulError = r->UpperLimitEstimatedError();

   std::cout << "The computed upper limit is: " << upperLimit << " +/- " << ulError << std::endl;

   const int nEntries = r->ArraySize();

   const char *  typeName = (calculatorType == 0) ? "Frequentist" : "Hybrid";
   const char * resultName = (w) ? w->GetName() : r->GetName();
   TString plotTitle = TString::Format("%s CL Scan for workspace %s",typeName,resultName);
   HypoTestInverterPlot *plot = new HypoTestInverterPlot("HTI_Result_Plot",plotTitle,r);
   plot->Draw("CLb 2CL");  // plot all and Clb

   if (plotHypoTestResult) {
      TCanvas * c2 = new TCanvas();
      c2->Divide( 2, TMath::Ceil(nEntries/2));
      for (int i=0; i<nEntries; i++) {
         c2->cd(i+1);
         SamplingDistPlot * pl = plot->MakeTestStatPlot(i);
         pl->SetLogYaxis(true);
         pl->Draw();
      }
   }

   std::cout << " expected limit (median) " <<  r->GetExpectedUpperLimit(0) << std::endl;
   std::cout << " expected limit (-1 sig) " << r->GetExpectedUpperLimit(-1) << std::endl;
   std::cout << " expected limit (+1 sig) " << r->GetExpectedUpperLimit(1) << std::endl;

   if (w != NULL && writeResult) {

      // write to a file the results
      const char *  calcType = (calculatorType == 0) ? "Freq" : "Hybr";
      const char *  limitType = (useCls) ? "CLs" : "Cls+b";
      const char * scanType = (npoints < 0) ? "auto" : "grid";
      TString resultFileName = TString::Format("%s_%s_%s_ts%d_",calcType,limitType,scanType,testStatType);
      resultFileName += fileName;

      TFile * fileOut = new TFile(resultFileName,"RECREATE");
      r->Write();
      fileOut->Close();
   }

}

// internal routine to run the inverter
HypoTestInverterResult *  RunInverter(RooWorkspace * w, const char * modelSBName, const char * modelBName,
                                      const char * dataName, int type,  int testStatType,
                                      int npoints, double poimin, double poimax,
                                      int ntoys, bool useCls, bool useNumberCounting, const char * nuisPriorName )
{

   std::cout << "Running HypoTestInverter on the workspace " << w->GetName() << std::endl;

   w->Print();

   RooAbsData * data = w->data(dataName);
   if (!data) {
      Error("StandardHypoTestDemo","Not existing data %s",dataName);
      return 0;
   }
   else
      std::cout << "Using data set " << dataName << std::endl;

   // get models from WS
   // get the modelConfig out of the file
   ModelConfig* bModel = (ModelConfig*) w->obj(modelBName);
   ModelConfig* sbModel = (ModelConfig*) w->obj(modelSBName);

   if (!sbModel) {
      Error("StandardHypoTestDemo","Not existing ModelConfig %s",modelSBName);
      return 0;
   }
   // check the model
   if (!sbModel->GetPdf()) {
      Error("StandardHypoTestDemo","Model %s has no pdf ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetParametersOfInterest()) {
      Error("StandardHypoTestInvDemo","Model %s has no poi ",modelSBName);
      return 0;
   }
   if (!sbModel->GetSnapshot() ) {
      Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi",modelSBName);
      sbModel->SetSnapshot( *sbModel->GetParametersOfInterest() );
   }

   if (!bModel || bModel == sbModel) {
      Info("StandardHypoTestInvDemo","The background model %s does not exist",modelBName);
      Info("StandardHypoTestInvDemo","Copy it from ModelConfig %s and set POI to zero",modelSBName);
      bModel = (ModelConfig*) sbModel->Clone();
      bModel->SetName(TString(modelSBName)+TString("_with_poi_0"));
      RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
      if (!var) return 0;
      double oldval = var->getVal();
      var->setVal(0);
      bModel->SetSnapshot( RooArgSet(*var)  );
      var->setVal(oldval);
   }
   else {
      if (!bModel->GetSnapshot() ) {
         Info("StandardHypoTestInvDemo","Model %s has no snapshot  - make one using model poi and 0 values ",modelBName);
         RooRealVar * var = dynamic_cast<RooRealVar*>(bModel->GetParametersOfInterest()->first());
         if (var) {
            double oldval = var->getVal();
            var->setVal(0);
            bModel->SetSnapshot( RooArgSet(*var)  );
            var->setVal(oldval);
         }
         else {
            Error("StandardHypoTestInvDemo","Model %s has no valid poi",modelBName);
            return 0;
         }
      }
   }

   SimpleLikelihoodRatioTestStat slrts(*sbModel->GetPdf(),*bModel->GetPdf());
   if (sbModel->GetSnapshot()) slrts.SetNullParameters(*sbModel->GetSnapshot());
   if (bModel->GetSnapshot()) slrts.SetAltParameters(*bModel->GetSnapshot());

   // ratio of profile likelihood - need to pass snapshot for the alt
   RatioOfProfiledLikelihoodsTestStat
      ropl(*sbModel->GetPdf(), *bModel->GetPdf(), bModel->GetSnapshot());
   ropl.SetSubtractMLE(false);

   ProfileLikelihoodTestStat profll(*sbModel->GetPdf());
   if (testStatType == 3) profll.SetOneSided(1);
   if (optimize) profll.SetReuseNLL(true);

   TestStatistic * testStat = &slrts;
   if (testStatType == 1) testStat = &ropl;
   if (testStatType == 2 || testStatType == 3) testStat = &profll;

   HypoTestCalculatorGeneric *  hc = 0;
   if (type == 0) hc = new FrequentistCalculator(*data, *bModel, *sbModel);
   else hc = new HybridCalculator(*data, *bModel, *sbModel);

   ToyMCSampler *toymcs = (ToyMCSampler*)hc->GetTestStatSampler();
   if (useNumberCounting) toymcs->SetNEventsPerToy(1);
   toymcs->SetTestStatistic(testStat);
   if (optimize) toymcs->SetUseMultiGen(true);

   if (type == 1) {
      HybridCalculator *hhc = (HybridCalculator*) hc;
      hhc->SetToys(ntoys,ntoys);

      // check for nuisance prior pdf in case of nuisance parameters
      if (bModel->GetNuisanceParameters() || sbModel->GetNuisanceParameters() ) {
         RooAbsPdf * nuisPdf = 0;
         if (nuisPriorName) nuisPdf = w->pdf(nuisPriorName);
         // use prior defined first in bModel (then in SbModel)
         if (!nuisPdf)  {
            Info("StandardHypoTestInvDemo","No nuisance pdf given for the HybridCalculator - try to use the prior pdf from the model");
            nuisPdf = (bModel->GetPriorPdf() ) ?  bModel->GetPriorPdf() : sbModel->GetPriorPdf();
         }
         if (!nuisPdf) {
            Error("StandardHypoTestInvDemo","Cannnot run Hybrid calculator because no prior on the nuisance parameter is specified");
            return 0;
         }
         const RooArgSet * nuisParams = (bModel->GetNuisanceParameters() ) ? bModel->GetNuisanceParameters() : sbModel->GetNuisanceParameters();
         RooArgSet * np = nuisPdf->getObservables(*nuisParams);
         if (np->getSize() == 0) {
            Warning("StandardHypoTestInvDemo","Prior nuisance does not depend on nuisance parameters. They will be smeared in their full range");
         }
         delete np;
         hhc->ForcePriorNuisanceAlt(*nuisPdf);
         hhc->ForcePriorNuisanceNull(*nuisPdf);
      }
   }
   else
      ((FrequentistCalculator*) hc)->SetToys(ntoys,ntoys);

   // Get the result
   RooMsgService::instance().getStream(1).removeTopic(RooFit::NumIntegration);

   TStopwatch tw; tw.Start();
   const RooArgSet * poiSet = sbModel->GetParametersOfInterest();
   RooRealVar *poi = (RooRealVar*)poiSet->first();

   // fit the data first
   sbModel->GetPdf()->fitTo(*data);
   double poihat  = poi->getVal();

   HypoTestInverter calc(*hc);
   calc.SetConfidenceLevel(0.95);

   calc.UseCLs(useCls);
   calc.SetVerbose(true);

   // can speed up using proof-lite
   if (useProof && nworkers > 1) {
      ProofConfig pc(*w, nworkers, "", kFALSE);
      toymcs->SetProofConfig(&pc);    // enable proof
   }

   if (npoints > 0) {
      if (poimin >= poimax) {
         // if no min/max given scan between MLE and +4 sigma
         poimin = int(poihat);
         poimax = int(poihat +  4 * poi->getError());
      }
      std::cout << "Doing a fixed scan  in interval : " << poimin << " , " << poimax << std::endl;
      calc.SetFixedScan(npoints,poimin,poimax);
   }
   else {
      //poi->setMax(10*int( (poihat+ 10 *poi->getError() )/10 ) );
      std::cout << "Doing an  automatic scan  in interval : " << poi->getMin() << " , " << poi->getMax() << std::endl;
   }

   HypoTestInverterResult * r = calc.GetInterval();

   return r;
}

void ReadResult(const char * fileName, const char * resultName="", bool useCLs=true) {
   // read a previous stored result from a file given the result name

   StandardHypoTestInvDemo(fileName, resultName,"","","",0,0,useCLs);
}

int main() {
   StandardHypoTestInvDemo();
}
<|endoftext|>


<commit_before><commit_msg>And of course we also have to change the forward slot in KMReaderMainWin (3rd part of the fix for bug 69880 (Default personality used when forwarding as MIME digest)).<commit_after><|endoftext|>