<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// The state of a thread is controlled by the two member variables
// alive_ and dead_.
// alive_ represents the state the thread has been ordered to achieve.
// It is set to true by the thread at startup, and is set to false by
// other threads, using SetNotAlive() and Stop().
// dead_ represents the state the thread has achieved.
// It is written by the thread encapsulated by this class only
// (except at init). It is read only by the Stop() method.
// The Run() method fires event_ when it's started; this ensures that the
// Start() method does not continue until after dead_ is false.
// This protects against premature Stop() calls from the creator thread, but
// not from other threads.

// Their transitions and states:
// alive_    dead_  Set by
// false     true   Constructor
// true      false  Run() method entry
// false     any    Run() method run_function failure
// any       false  Run() method exit (happens only with alive_ false)
// false     any    SetNotAlive
// false     any    Stop         Stop waits for dead_ to become true.
//
// Summarized a different way:
// Variable   Writer               Reader
// alive_     Constructor(false)   Run.loop
//            Run.start(true)
//            Run.fail(false)
//            SetNotAlive(false)
//            Stop(false)
//
// dead_      Constructor(true)    Stop.loop
//            Run.start(false)
//            Run.exit(true)

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <assert.h>
#include <errno.h>
#include <string.h>  // strncpy
#include <time.h>    // nanosleep
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <sys/types.h>
#include <sched.h>
#include <sys/syscall.h>
#include <linux/unistd.h>
#include <sys/prctl.h>
#endif

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  assert(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  assert(false);
  return low_prio;
}

extern "C"
{
  static void* StartThread(void* lp_parameter) {
    static_cast<ThreadPosix*>(lp_parameter)->Run();
    return 0;
  }
}

ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
                                   ThreadPriority prio,
                                   const char* thread_name) {
  ThreadPosix* ptr = new ThreadPosix(func, obj, prio, thread_name);
  if (!ptr) {
    return NULL;
  }
  const int error = ptr->Construct();
  if (error) {
    delete ptr;
    return NULL;
  }
  return ptr;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, ThreadObj obj,
                         ThreadPriority prio, const char* thread_name)
    : run_function_(func),
      obj_(obj),
      crit_state_(CriticalSectionWrapper::CreateCriticalSection()),
      alive_(false),
      dead_(true),
      prio_(prio),
      event_(EventWrapper::Create()),
      name_(),
      set_thread_name_(false),
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
      pid_(-1),
#endif
      attr_(),
      thread_(0) {
  if (thread_name != NULL) {
    set_thread_name_ = true;
    strncpy(name_, thread_name, kThreadMaxNameLength);
    name_[kThreadMaxNameLength - 1] = '\0';
  }
}

uint32_t ThreadWrapper::GetThreadId() {
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX)
  return static_cast<uint32_t>(syscall(__NR_gettid));
#else
  return reinterpret_cast<uint32_t>(pthread_self());
#endif
}

int ThreadPosix::Construct() {
  int result = 0;
#if !defined(WEBRTC_ANDROID)
  // Enable immediate cancellation if requested, see Shutdown().
  result = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  if (result != 0) {
    return -1;
  }
  result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  if (result != 0) {
    return -1;
  }
#endif
  result = pthread_attr_init(&attr_);
  if (result != 0) {
    return -1;
  }
  return 0;
}

ThreadPosix::~ThreadPosix() {
  pthread_attr_destroy(&attr_);
  delete event_;
  delete crit_state_;
}

#define HAS_THREAD_ID !defined(WEBRTC_IOS) && !defined(WEBRTC_MAC)

bool ThreadPosix::Start(unsigned int& thread_id)
{
  int result = pthread_attr_setdetachstate(&attr_, PTHREAD_CREATE_DETACHED);
  // Set the stack stack size to 1M.
  result |= pthread_attr_setstacksize(&attr_, 1024 * 1024);
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  event_->Reset();
  // If pthread_create was successful, a thread was created and is running.
  // Don't return false if it was successful since if there are any other
  // failures the state will be: thread was started but not configured as
  // asked for. However, the caller of this API will assume that a false
  // return value means that the thread never started.
  result |= pthread_create(&thread_, &attr_, &StartThread, this);
  if (result != 0) {
    return false;
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = false;
  }

  // Wait up to 10 seconds for the OS to call the callback function. Prevents
  // race condition if Stop() is called too quickly after start.
  if (kEventSignaled != event_->Wait(WEBRTC_EVENT_10_SEC)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "posix thread event never triggered");
    // Timed out. Something went wrong.
    return true;
  }

#if HAS_THREAD_ID
  thread_id = static_cast<unsigned int>(thread_);
#endif
  sched_param param;

  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);

  if ((min_prio == EINVAL) || (max_prio == EINVAL)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return true;
  }
  if (max_prio - min_prio <= 2) {
    // There is no room for setting priorities with any granularity.
    return true;
  }
  param.sched_priority = ConvertToSystemPriority(prio_, min_prio, max_prio);
  result = pthread_setschedparam(thread_, policy, &param);
  if (result == EINVAL) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to set thread priority");
  }
  return true;
}

// CPU_ZERO and CPU_SET are not available in NDK r7, so disable
// SetAffinity on Android for now.
#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID)))
bool ThreadPosix::SetAffinity(const int* processor_numbers,
                              const unsigned int amount_of_processors) {
  if (!processor_numbers || (amount_of_processors == 0)) {
    return false;
  }
  cpu_set_t mask;
  CPU_ZERO(&mask);

  for (unsigned int processor = 0;
       processor < amount_of_processors;
       ++processor) {
    CPU_SET(processor_numbers[processor], &mask);
  }
#if defined(WEBRTC_ANDROID)
  // Android.
  const int result = syscall(__NR_sched_setaffinity,
                             pid_,
                             sizeof(mask),
                             &mask);
#else
  // "Normal" Linux.
  const int result = sched_setaffinity(pid_,
                                       sizeof(mask),
                                       &mask);
#endif
  if (result != 0) {
    return false;
  }
  return true;
}

#else
// NOTE: On Mac OS X, use the Thread affinity API in
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
// instead of Linux gettid() syscall.
bool ThreadPosix::SetAffinity(const int* , const unsigned int) {
  return false;
}
#endif

void ThreadPosix::SetNotAlive() {
  CriticalSectionScoped cs(crit_state_);
  alive_ = false;
}

bool ThreadPosix::Stop() {
  bool dead = false;
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = false;
    dead = dead_;
  }

  // TODO(hellner) why not use an event here?
  // Wait up to 10 seconds for the thread to terminate
  for (int i = 0; i < 1000 && !dead; ++i) {
    timespec t;
    t.tv_sec = 0;
    t.tv_nsec = 10 * 1000 * 1000;
    nanosleep(&t, NULL);
    {
      CriticalSectionScoped cs(crit_state_);
      dead = dead_;
    }
  }
  if (dead) {
    return true;
  } else {
    return false;
  }
}

void ThreadPosix::Run() {
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = true;
  }
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
  pid_ = GetThreadId();
#endif
  // The event the Start() is waiting for.
  event_->Set();

  if (set_thread_name_) {
#ifdef WEBRTC_LINUX
    prctl(PR_SET_NAME, (unsigned long)name_, 0, 0, 0);
#endif
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread with name:%s started ", name_);
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name started");
  }
  bool alive = true;
  bool run = true;
  while (alive) {
    run = run_function_(obj_);
    CriticalSectionScoped cs(crit_state_);
    if (!run) {
      alive_ = false;
    }
    alive = alive_;
  }

  if (set_thread_name_) {
    // Don't set the name for the trace thread because it may cause a
    // deadlock. TODO(hellner) there should be a better solution than
    // coupling the thread and the trace class like this.
    if (strcmp(name_, "Trace")) {
      WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                   "Thread with name:%s stopped", name_);
    }
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name stopped");
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = true;
  }
}

} // namespace webrtc
<commit_msg>Mac 64-bit compatibility for WebRTC.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// The state of a thread is controlled by the two member variables
// alive_ and dead_.
// alive_ represents the state the thread has been ordered to achieve.
// It is set to true by the thread at startup, and is set to false by
// other threads, using SetNotAlive() and Stop().
// dead_ represents the state the thread has achieved.
// It is written by the thread encapsulated by this class only
// (except at init). It is read only by the Stop() method.
// The Run() method fires event_ when it's started; this ensures that the
// Start() method does not continue until after dead_ is false.
// This protects against premature Stop() calls from the creator thread, but
// not from other threads.

// Their transitions and states:
// alive_    dead_  Set by
// false     true   Constructor
// true      false  Run() method entry
// false     any    Run() method run_function failure
// any       false  Run() method exit (happens only with alive_ false)
// false     any    SetNotAlive
// false     any    Stop         Stop waits for dead_ to become true.
//
// Summarized a different way:
// Variable   Writer               Reader
// alive_     Constructor(false)   Run.loop
//            Run.start(true)
//            Run.fail(false)
//            SetNotAlive(false)
//            Stop(false)
//
// dead_      Constructor(true)    Stop.loop
//            Run.start(false)
//            Run.exit(true)

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <assert.h>
#include <errno.h>
#include <string.h>  // strncpy
#include <time.h>    // nanosleep
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <sys/types.h>
#include <sched.h>
#include <sys/syscall.h>
#include <linux/unistd.h>
#include <sys/prctl.h>
#endif

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  assert(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  assert(false);
  return low_prio;
}

extern "C"
{
  static void* StartThread(void* lp_parameter) {
    static_cast<ThreadPosix*>(lp_parameter)->Run();
    return 0;
  }
}

ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
                                   ThreadPriority prio,
                                   const char* thread_name) {
  ThreadPosix* ptr = new ThreadPosix(func, obj, prio, thread_name);
  if (!ptr) {
    return NULL;
  }
  const int error = ptr->Construct();
  if (error) {
    delete ptr;
    return NULL;
  }
  return ptr;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, ThreadObj obj,
                         ThreadPriority prio, const char* thread_name)
    : run_function_(func),
      obj_(obj),
      crit_state_(CriticalSectionWrapper::CreateCriticalSection()),
      alive_(false),
      dead_(true),
      prio_(prio),
      event_(EventWrapper::Create()),
      name_(),
      set_thread_name_(false),
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
      pid_(-1),
#endif
      attr_(),
      thread_(0) {
  if (thread_name != NULL) {
    set_thread_name_ = true;
    strncpy(name_, thread_name, kThreadMaxNameLength);
    name_[kThreadMaxNameLength - 1] = '\0';
  }
}

uint32_t ThreadWrapper::GetThreadId() {
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX)
  return static_cast<uint32_t>(syscall(__NR_gettid));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  return pthread_mach_thread_np(pthread_self());
#else
  return reinterpret_cast<uint32_t>(pthread_self());
#endif
}

int ThreadPosix::Construct() {
  int result = 0;
#if !defined(WEBRTC_ANDROID)
  // Enable immediate cancellation if requested, see Shutdown().
  result = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  if (result != 0) {
    return -1;
  }
  result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
  if (result != 0) {
    return -1;
  }
#endif
  result = pthread_attr_init(&attr_);
  if (result != 0) {
    return -1;
  }
  return 0;
}

ThreadPosix::~ThreadPosix() {
  pthread_attr_destroy(&attr_);
  delete event_;
  delete crit_state_;
}

#define HAS_THREAD_ID !defined(WEBRTC_IOS) && !defined(WEBRTC_MAC)

bool ThreadPosix::Start(unsigned int& thread_id)
{
  int result = pthread_attr_setdetachstate(&attr_, PTHREAD_CREATE_DETACHED);
  // Set the stack stack size to 1M.
  result |= pthread_attr_setstacksize(&attr_, 1024 * 1024);
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  event_->Reset();
  // If pthread_create was successful, a thread was created and is running.
  // Don't return false if it was successful since if there are any other
  // failures the state will be: thread was started but not configured as
  // asked for. However, the caller of this API will assume that a false
  // return value means that the thread never started.
  result |= pthread_create(&thread_, &attr_, &StartThread, this);
  if (result != 0) {
    return false;
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = false;
  }

  // Wait up to 10 seconds for the OS to call the callback function. Prevents
  // race condition if Stop() is called too quickly after start.
  if (kEventSignaled != event_->Wait(WEBRTC_EVENT_10_SEC)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "posix thread event never triggered");
    // Timed out. Something went wrong.
    return true;
  }

#if HAS_THREAD_ID
  thread_id = static_cast<unsigned int>(thread_);
#endif
  sched_param param;

  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);

  if ((min_prio == EINVAL) || (max_prio == EINVAL)) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return true;
  }
  if (max_prio - min_prio <= 2) {
    // There is no room for setting priorities with any granularity.
    return true;
  }
  param.sched_priority = ConvertToSystemPriority(prio_, min_prio, max_prio);
  result = pthread_setschedparam(thread_, policy, &param);
  if (result == EINVAL) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to set thread priority");
  }
  return true;
}

// CPU_ZERO and CPU_SET are not available in NDK r7, so disable
// SetAffinity on Android for now.
#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID)))
bool ThreadPosix::SetAffinity(const int* processor_numbers,
                              const unsigned int amount_of_processors) {
  if (!processor_numbers || (amount_of_processors == 0)) {
    return false;
  }
  cpu_set_t mask;
  CPU_ZERO(&mask);

  for (unsigned int processor = 0;
       processor < amount_of_processors;
       ++processor) {
    CPU_SET(processor_numbers[processor], &mask);
  }
#if defined(WEBRTC_ANDROID)
  // Android.
  const int result = syscall(__NR_sched_setaffinity,
                             pid_,
                             sizeof(mask),
                             &mask);
#else
  // "Normal" Linux.
  const int result = sched_setaffinity(pid_,
                                       sizeof(mask),
                                       &mask);
#endif
  if (result != 0) {
    return false;
  }
  return true;
}

#else
// NOTE: On Mac OS X, use the Thread affinity API in
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
// instead of Linux gettid() syscall.
bool ThreadPosix::SetAffinity(const int* , const unsigned int) {
  return false;
}
#endif

void ThreadPosix::SetNotAlive() {
  CriticalSectionScoped cs(crit_state_);
  alive_ = false;
}

bool ThreadPosix::Stop() {
  bool dead = false;
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = false;
    dead = dead_;
  }

  // TODO(hellner) why not use an event here?
  // Wait up to 10 seconds for the thread to terminate
  for (int i = 0; i < 1000 && !dead; ++i) {
    timespec t;
    t.tv_sec = 0;
    t.tv_nsec = 10 * 1000 * 1000;
    nanosleep(&t, NULL);
    {
      CriticalSectionScoped cs(crit_state_);
      dead = dead_;
    }
  }
  if (dead) {
    return true;
  } else {
    return false;
  }
}

void ThreadPosix::Run() {
  {
    CriticalSectionScoped cs(crit_state_);
    alive_ = true;
  }
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
  pid_ = GetThreadId();
#endif
  // The event the Start() is waiting for.
  event_->Set();

  if (set_thread_name_) {
#ifdef WEBRTC_LINUX
    prctl(PR_SET_NAME, (unsigned long)name_, 0, 0, 0);
#endif
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread with name:%s started ", name_);
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name started");
  }
  bool alive = true;
  bool run = true;
  while (alive) {
    run = run_function_(obj_);
    CriticalSectionScoped cs(crit_state_);
    if (!run) {
      alive_ = false;
    }
    alive = alive_;
  }

  if (set_thread_name_) {
    // Don't set the name for the trace thread because it may cause a
    // deadlock. TODO(hellner) there should be a better solution than
    // coupling the thread and the trace class like this.
    if (strcmp(name_, "Trace")) {
      WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                   "Thread with name:%s stopped", name_);
    }
  } else {
    WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
                 "Thread without name stopped");
  }
  {
    CriticalSectionScoped cs(crit_state_);
    dead_ = true;
  }
}

} // namespace webrtc
<|endoftext|>


<commit_before><commit_msg>glsl: don't eliminate subroutine types.<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include "md5.h"

using namespace std;

MD5::MD5()
{
	Init();
}

void MD5::Init()
{
    context.count[0] = context.count[1] = 0;
    context.state[0] = 0x67452301;
    context.state[1] = 0xefcdab89;
    context.state[2] = 0x98badcfe;
    context.state[3] = 0x10325476;
}

void MD5::Encode(unsigned char* output, UINT4* input, unsigned int len)
{
    unsigned int i, j;
    for (i = 0, j = 0; j < len; i++, j += 4)
	{
		output[j] = (unsigned char)(input[i] & 0xff);
		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
    }
}

void MD5::Decode(UINT4* output, unsigned char* input, unsigned int len)
{
    unsigned int i, j;
    for (i = 0, j = 0; j < len; i++, j += 4)
	{
		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
	}
}

void MD5::Update(unsigned char* input, unsigned int inputLen)
{
	unsigned int i, index, partLen;
	index = (unsigned int)((context.count[0] >> 3) & 0x3F);

    if ((context.count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
	{
		context.count[1]++;
	}

	context.count[1] += ((UINT4)inputLen >> 29);
    partLen = 64 - index;

    if (inputLen >= partLen)
	{
		memcpy((POINTER)&context.buffer[index], (POINTER)input, partLen);
		MD5Transform (context.state, context.buffer);

		for (i = partLen; i + 63 < inputLen; i += 64)
		{
			MD5Transform (context.state, &input[i]);
		}
		index = 0;
    }
    else
	{
		i = 0;
	}
    memcpy((POINTER)&context.buffer[index], (POINTER)&input[i], inputLen-i);
}

char* MD5::digestFile(char* filename)
{
	Init();

    FILE *file;
    int len;
    unsigned char buffer[524288];

    if(fopen_s(&file, filename, "rb"))
	{
		cout << filename << " can't be opened" << endl;
		//printf("%s can't be opened\n", filename);
		return NULL;
	}
	else
    {
		while(len = (int)fread(buffer, 1, 524288, file))
		{
			Update(buffer, len);
		}
		Final();
		fclose(file);
    }
    return digestChars;
}

void MD5::Final()
{
    unsigned char bits[8];
    unsigned int index, padLen;

    Encode(bits, context.count, 8);
    index = (unsigned int)((context.count[0] >> 3) & 0x3f);
    padLen = (index < 56) ? (56 - index) : (120 - index);
    Update(PADDING, padLen);
    Update(bits, 8);
    Encode(digestRaw, context.state, 16);
    memset((POINTER)&context, 0, sizeof(context));
    writeToString();
}

void MD5::writeToString()
{
	int pos;
    for(pos = 0; pos < 16; pos++)
	{
		sprintf_s(digestChars + (pos * 2), sizeof(digestChars + (pos * 2)), "%02x", digestRaw[pos]);
	}
}

void MD5::MD5Transform(UINT4 state[4], unsigned char block[64])
{
    UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];

    Decode(x, block, 64);

    /* Round 1 */
    FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
    FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
    FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
    FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
    FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
    FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
    FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
    FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
    FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
    FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

    /* Round 2 */
    GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
    GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
    GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
    GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
    GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
    GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
    GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
    GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
    GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
    GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
    GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

    /* Round 3 */
    HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
    HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
    HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
    HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
    HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
    HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
    HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
    HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
    HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
    HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

    /* Round 4 */
    II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
    II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
    II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
    II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
    II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
    II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
    II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
    II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
    II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
    II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;

    memset((POINTER)x, 0, sizeof (x));
}

<commit_msg>portability fixes.<commit_after>#include <iostream>
#include "md5.h"

using namespace std;

MD5::MD5()
{
	Init();
}

void MD5::Init()
{
    context.count[0] = context.count[1] = 0;
    context.state[0] = 0x67452301;
    context.state[1] = 0xefcdab89;
    context.state[2] = 0x98badcfe;
    context.state[3] = 0x10325476;
}

void MD5::Encode(unsigned char* output, UINT4* input, unsigned int len)
{
    unsigned int i, j;
    for (i = 0, j = 0; j < len; i++, j += 4)
	{
		output[j] = (unsigned char)(input[i] & 0xff);
		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
    }
}

void MD5::Decode(UINT4* output, unsigned char* input, unsigned int len)
{
    unsigned int i, j;
    for (i = 0, j = 0; j < len; i++, j += 4)
	{
		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
	}
}

void MD5::Update(unsigned char* input, unsigned int inputLen)
{
	unsigned int i, index, partLen;
	index = (unsigned int)((context.count[0] >> 3) & 0x3F);

    if ((context.count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
	{
		context.count[1]++;
	}

	context.count[1] += ((UINT4)inputLen >> 29);
    partLen = 64 - index;

    if (inputLen >= partLen)
	{
		memcpy((POINTER)&context.buffer[index], (POINTER)input, partLen);
		MD5Transform (context.state, context.buffer);

		for (i = partLen; i + 63 < inputLen; i += 64)
		{
			MD5Transform (context.state, &input[i]);
		}
		index = 0;
    }
    else
	{
		i = 0;
	}
    memcpy((POINTER)&context.buffer[index], (POINTER)&input[i], inputLen-i);
}

char* MD5::digestFile(char* filename)
{
	Init();

    FILE *file;
    int len;
    unsigned char buffer[524288];

	file = fopen(filename, "rb");
	if (file == NULL)
	{
		std::cout << filename << " can't be opened" << endl;
		return NULL;
	}
	else
    {
		while(len = (int)fread(buffer, 1, 524288, file))
		{
			Update(buffer, len);
		}
		Final();
		fclose(file);
    }
    return digestChars;
}

void MD5::Final()
{
    unsigned char bits[8];
    unsigned int index, padLen;

    Encode(bits, context.count, 8);
    index = (unsigned int)((context.count[0] >> 3) & 0x3f);
    padLen = (index < 56) ? (56 - index) : (120 - index);
    Update(PADDING, padLen);
    Update(bits, 8);
    Encode(digestRaw, context.state, 16);
    memset((POINTER)&context, 0, sizeof(context));
    writeToString();
}

void MD5::writeToString()
{
	int pos;
    for(pos = 0; pos < 16; pos++)
	{
		sprintf(digestChars + (pos * 2),"%02x", digestRaw[pos]);
	}
}

void MD5::MD5Transform(UINT4 state[4], unsigned char block[64])
{
    UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];

    Decode(x, block, 64);

    /* Round 1 */
    FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
    FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
    FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
    FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
    FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
    FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
    FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
    FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
    FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
    FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

    /* Round 2 */
    GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
    GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
    GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
    GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
    GG(d, a, b, c, x[10], S22,  0x2441453); /* 22 */
    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
    GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
    GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
    GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
    GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
    GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
    GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

    /* Round 3 */
    HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
    HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
    HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
    HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
    HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
    HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
    HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
    HH(b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
    HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
    HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

    /* Round 4 */
    II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
    II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
    II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
    II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
    II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
    II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
    II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
    II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
    II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
    II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;

    memset((POINTER)x, 0, sizeof (x));
}

<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File: testNekManager.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Test code for NekManager
//
///////////////////////////////////////////////////////////////////////////////

#include <LibUtilities/BasicUtils/NekManager.hpp>

#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/progress.hpp>

#include <iostream>

using std::cout;
using std::endl;

// Test stuff.
double MyCreator(const int &key)
{
   return key + 2.5;
};

class Temp
{
    public:
        Temp() {};

        static double create(const int &key)
        {
            return key*1.025;
        }
};

namespace Nektar
{
   namespace UnitTests
   {
       void testNekManager()
       {
            typedef NekManager<int, double> ManagerType;

            ManagerType manager;
            int key = 10;

            // Registering a C function
            manager.RegisterCreator(key, MyCreator);

            // Registering a static class method
            manager.RegisterCreator(20, Temp::create);

            double value = manager.GetValue(key);
            BOOST_CHECK(value == 12.5);

            value = manager.GetValue(20);
            BOOST_CHECK(value == 20.5);

            manager.AddValue(17, -2.0);
            BOOST_CHECK_EQUAL(manager.GetValue(17), -2.0);
        }
   }
}

/**
   $Log: testNekManager.cpp,v $
   Revision 1.2  2006/08/25 01:38:58  bnelson
   no message

   Revision 1.1  2006/07/05 20:22:05  jfrazier
   Initial checkin.

**/
<commit_msg>Added tests for the global create function.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File: testNekManager.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Test code for NekManager
//
///////////////////////////////////////////////////////////////////////////////

#include <LibUtilities/BasicUtils/NekManager.hpp>

#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/progress.hpp>

#include <iostream>

using std::cout;
using std::endl;

// Test stuff.
double MyCreator(const int &key)
{
   return key + 2.5;
};

class Temp
{
    public:
        Temp() {};

        static double create(const int &key)
        {
            return key*1.025;
        }
};

class GlobalCreator
{
    public:
        double operator()(const int& key)
        {
            return key;
        }
};

namespace Nektar
{
   namespace UnitTests
   {
       void testNekManager()
       {
            typedef NekManager<int, double> ManagerType;

            /// TODO - See why I can't do GlobalCreator() directly in the constructor call.
            GlobalCreator c;
            ManagerType manager(c);
            int key = 10;

            // Registering a C function
            manager.RegisterCreator(key, MyCreator);

            // Registering a static class method
            manager.RegisterCreator(20, Temp::create);

            double value = manager[key];
            BOOST_CHECK(value == 12.5);

            value = manager[20];
            BOOST_CHECK(value == 20.5);

            manager[17] = -2.0;
            BOOST_CHECK_EQUAL(manager[17], -2.0);
        }
   }
}

/**
   $Log: testNekManager.cpp,v $
   Revision 1.3  2006/12/10 21:36:08  bnelson
   *** empty log message ***

   Revision 1.2  2006/08/25 01:38:58  bnelson
   no message

   Revision 1.1  2006/07/05 20:22:05  jfrazier
   Initial checkin.

**/
<|endoftext|>


<commit_before>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_LINEARELLIPTIC_DISCRETEPROBLEM_HH
#define DUNE_HDD_LINEARELLIPTIC_DISCRETEPROBLEM_HH

#include <memory>

#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/misc/mpimanager.hh>
#endif

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/grid/provider.hh>
#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/common/configtree.hh>
#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/grid/partview.hh>
#include <dune/stuff/common/memory.hh>

#include <dune/hdd/linearelliptic/problems.hh>

namespace Dune {
namespace HDD {
namespace LinearElliptic {

template< class GridImp >
class DiscreteProblem
{
public:
  typedef GridImp GridType;
  typedef Stuff::Grid::ProviderInterface< GridType >  GridProviderType;
private:
  typedef Stuff::GridProviders< GridType > GridProviders;
  typedef typename GridType::LeafIntersection IntersectionType;
  typedef Stuff::Grid::BoundaryInfoProvider< IntersectionType > BoundaryInfoProvider;
  typedef typename GridType::template Codim< 0 >::Entity EntityType;
  typedef typename GridType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridType::dimension;
public:
  typedef double RangeFieldType;
  static const unsigned int dimRange = 1;
  typedef LinearElliptic::ProblemInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange > ProblemType;
  typedef LinearElliptic::ProblemProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange > ProblemProvider;

  static void write_config(const std::string filename, const std::string id)
  {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    write_keys_to_file("gridprovider", GridProviders::available(), file);
    write_keys_to_file("boundaryinfo", BoundaryInfoProvider::available(), file);
    write_keys_to_file("problem", ProblemProvider::available(), file);
    file << "[logging]" << std::endl;
    file << "info  = true" << std::endl;
    file << "debug = true" << std::endl;
    file << "file  = false" << std::endl;
    file << "[parameter]" << std::endl;
    file << "0.diffusion_factor = [0.1; 0.1; 1.0; 1.0]" << std::endl;
    file << "1.diffusion_factor = [1.0; 1.0; 0.1; 0.1]" << std::endl;
    write_config_to_file< GridProviders >(file);
    write_config_to_file< BoundaryInfoProvider >(file);
    write_config_to_file< ProblemProvider >(file);
    file.close();
  } // ... write_config(...)

  DiscreteProblem(const std::string id, const std::vector< std::string >& arguments, const bool visualize = true)
  {
    // mpi
    int argc = arguments.size();
    char** argv = Stuff::Common::String::vectorToMainArgs(arguments);
#if HAVE_DUNE_FEM
    Fem::MPIManager::initialize(argc, argv);
#else
    MPIHelper::instance(argc, argv);
#endif

    // configuration
    config_ = Stuff::Common::ConfigTree(argc, argv, id + ".cfg");
    if (!config_.has_sub(id))
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::configuration_error,
                            "Missing sub '" << id << "' in the following ConfigTree:\n\n" << config_);
    filename_ = config_.get(id + ".filename", id);

    // logger
    const Stuff::Common::ConfigTree& logger_config = config_.sub("logging");
    int log_flags = Stuff::Common::LOG_CONSOLE;
    debug_logging_ = logger_config.get< bool >("debug", false);
    if (logger_config.get< bool >("info"))
      log_flags = log_flags | Stuff::Common::LOG_INFO;
    if (debug_logging_)
      log_flags = log_flags | Stuff::Common::LOG_DEBUG;
    if (logger_config.get< bool >("file", false))
      log_flags = log_flags | Stuff::Common::LOG_FILE;
    Stuff::Common::Logger().create(log_flags, id, "", "");
    auto& info  = Stuff::Common::Logger().info();

    Timer timer;
    const std::string griprovider_type = config_.get< std::string >(id + ".gridprovider");
    info << "creating grid with '" << griprovider_type << "'... " << std::flush;
    grid_provider_ = GridProviders::create(griprovider_type, config_);
    const auto grid_view = grid_provider_->leaf_view();
    info << " done (took " << timer.elapsed()
         << "s, has " << grid_view->indexSet().size(0) << " element";
    if (grid_view->indexSet().size(0) > 1)
      info << "s";
    info << ")" << std::endl;

    const std::string boundary_info_type = config_.get< std::string >(id + ".boundaryinfo");
    if (config_.has_sub(boundary_info_type))
      boundary_info_ = config_.sub(boundary_info_type);
    else
      boundary_info_ = Stuff::Common::ConfigTree("type", boundary_info_type);

    info << "setting up ";
    const std::string problem_type = config_.get< std::string >(id + ".problem");
    info << "'" << problem_type << "'... " << std::flush;
    timer.reset();
    problem_ = ProblemProvider::create(problem_type, config_);
    info << "done (took " << timer.elapsed() << "s)" << std::endl;

    if (visualize) {
      info << "visualizing grid and problem... " << std::flush;
      timer.reset();
      grid_provider_->visualize(boundary_info_, filename_ + ".grid");
      problem_->visualize(*grid_view, filename_ + ".problem");
      info << "done (took " << timer.elapsed() << "s)" << std::endl;
    } // if (visualize)
  } // DiscreteProblem

  std::string filename() const
  {
    return filename_;
  }

  const Stuff::Common::ConfigTree& config() const
  {
    return config_;
  }

  bool debug_logging() const
  {
    return debug_logging_;
  }

  GridProviderType& grid_provider()
  {
    return *grid_provider_;
  }

  const GridProviderType& grid_provider() const
  {
    return *grid_provider_;
  }

  const Stuff::Common::ConfigTree& boundary_info() const
  {
    return boundary_info_;
  }

  const ProblemType& problem() const
  {
    return *problem_;
  }

private:
  static void write_keys_to_file(const std::string name, const std::vector< std::string > keys, std::ofstream& file)
  {
    std::string whitespace = Stuff::Common::whitespaceify(name + " = ");
    file << name << " = " << keys[0] << std::endl;
    for (size_t ii = 1; ii < keys.size(); ++ii)
      file << whitespace << keys[ii] << std::endl;
  } // ... write_keys_to_file(...)

  template< class ConfigProvider >
  static void write_config_to_file(std::ofstream& file)
  {
    for (const auto& type : ConfigProvider::available()) {
      auto config = ConfigProvider::default_config(type, type);
      if (!config.empty())
      file << config;
    }
  } // ... write_config_to_file(...)

  std::string filename_;
  Stuff::Common::ConfigTree config_;
  bool debug_logging_;
  std::unique_ptr< GridProviderType > grid_provider_;
  Stuff::Common::ConfigTree boundary_info_;
  std::unique_ptr< const ProblemType > problem_;
}; // class DiscreteProblem

} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_LINEARELLIPTIC_DISCRETEPROBLEM_HH
<commit_msg>[linearelliptic.discreteproblem] * updated config tree usage * added visualize flag * added problem report<commit_after>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_LINEARELLIPTIC_DISCRETEPROBLEM_HH
#define DUNE_HDD_LINEARELLIPTIC_DISCRETEPROBLEM_HH

#include <memory>

#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

#if HAVE_DUNE_FEM
# include <dune/fem/misc/mpimanager.hh>
#endif

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/string.hh>
#include <dune/stuff/grid/provider.hh>
#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/common/configtree.hh>
#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/grid/partview.hh>
#include <dune/stuff/common/memory.hh>

#include <dune/hdd/linearelliptic/problems.hh>

namespace Dune {
namespace HDD {
namespace LinearElliptic {

template< class GridImp >
class DiscreteProblem
{
public:
  typedef GridImp GridType;
  typedef Stuff::Grid::ProviderInterface< GridType >  GridProviderType;
private:
  typedef Stuff::GridProviders< GridType > GridProviders;
  typedef typename GridType::LeafIntersection IntersectionType;
  typedef Stuff::Grid::BoundaryInfoProvider< IntersectionType > BoundaryInfoProvider;
  typedef typename GridType::template Codim< 0 >::Entity EntityType;
  typedef typename GridType::ctype DomainFieldType;
  static const unsigned int dimDomain = GridType::dimension;
public:
  typedef double RangeFieldType;
  static const unsigned int dimRange = 1;
  typedef LinearElliptic::ProblemInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange > ProblemType;
  typedef LinearElliptic::ProblemProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange > ProblemProvider;

  static void write_config(const std::string filename, const std::string id)
  {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    write_keys_to_file("gridprovider", GridProviders::available(), file);
    write_keys_to_file("boundaryinfo", BoundaryInfoProvider::available(), file);
    write_keys_to_file("problem", ProblemProvider::available(), file);
    file << "[logging]" << std::endl;
    file << "info  = true" << std::endl;
    file << "debug = true" << std::endl;
    file << "file  = false" << std::endl;
    file << "visualize = true" << std::endl;
    file << "[parameter]" << std::endl;
    file << "0.diffusion_factor = [0.1 0.1 1.0 1.0]" << std::endl;
    file << "1.diffusion_factor = [1.0 1.0 0.1 0.1]" << std::endl;
    write_config_to_file< GridProviders >(file);
    write_config_to_file< BoundaryInfoProvider >(file);
    write_config_to_file< ProblemProvider >(file);
    file.close();
  } // ... write_config(...)

  DiscreteProblem(const std::string id, const std::vector< std::string >& arguments)
  {
    // mpi
    int argc = arguments.size();
    char** argv = Stuff::Common::String::vectorToMainArgs(arguments);
#if HAVE_DUNE_FEM
    Fem::MPIManager::initialize(argc, argv);
#else
    MPIHelper::instance(argc, argv);
#endif

    // configuration
    config_ = Stuff::Common::ConfigTree(argc, argv, id + ".cfg");
    if (!config_.has_sub(id))
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::configuration_error,
                            "Missing sub '" << id << "' in the following ConfigTree:\n\n" << config_);
    filename_ = config_.get(id + ".filename", id);

    // logger
    const Stuff::Common::ConfigTree logger_config = config_.sub("logging");
    int log_flags = Stuff::Common::LOG_CONSOLE;
    debug_logging_ = logger_config.get< bool >("debug", false);
    if (logger_config.get< bool >("info"))
      log_flags = log_flags | Stuff::Common::LOG_INFO;
    if (debug_logging_)
      log_flags = log_flags | Stuff::Common::LOG_DEBUG;
    if (logger_config.get< bool >("file", false))
      log_flags = log_flags | Stuff::Common::LOG_FILE;
    Stuff::Common::Logger().create(log_flags, id, "", "");
    auto& info  = Stuff::Common::Logger().info();

    Timer timer;
    const std::string griprovider_type = config_.get< std::string >(id + ".gridprovider");
    info << "creating grid with '" << griprovider_type << "'... " << std::flush;
    grid_provider_ = GridProviders::create(griprovider_type, config_);
    const auto grid_view = grid_provider_->leaf_view();
    info << " done (took " << timer.elapsed()
         << "s, has " << grid_view->indexSet().size(0) << " element";
    if (grid_view->indexSet().size(0) > 1)
      info << "s";
    info << ")" << std::endl;

    const std::string boundary_info_type = config_.get< std::string >(id + ".boundaryinfo");
    if (config_.has_sub(boundary_info_type))
      boundary_info_ = config_.sub(boundary_info_type);
    else
      boundary_info_ = Stuff::Common::ConfigTree("type", boundary_info_type);

    info << "setting up ";
    timer.reset();
    const std::string problem_type = config_.get< std::string >(id + ".problem");
    if (!debug_logging_)
      info << "'" << problem_type << "'... " << std::flush;
    problem_ = ProblemProvider::create(problem_type, config_);
    if (debug_logging_)
      info << *problem_ << std::endl;
    else
      info << "done (took " << timer.elapsed() << "s)" << std::endl;

    if (logger_config.get("visualize", true)) {
      info << "visualizing grid and problem... " << std::flush;
      timer.reset();
      grid_provider_->visualize(boundary_info_, filename_ + ".grid");
      problem_->visualize(*grid_view, filename_ + ".problem");
      info << "done (took " << timer.elapsed() << "s)" << std::endl;
    } // if (visualize)
  } // DiscreteProblem

  std::string filename() const
  {
    return filename_;
  }

  const Stuff::Common::ConfigTree& config() const
  {
    return config_;
  }

  bool debug_logging() const
  {
    return debug_logging_;
  }

  GridProviderType& grid_provider()
  {
    return *grid_provider_;
  }

  const GridProviderType& grid_provider() const
  {
    return *grid_provider_;
  }

  const Stuff::Common::ConfigTree& boundary_info() const
  {
    return boundary_info_;
  }

  const ProblemType& problem() const
  {
    return *problem_;
  }

private:
  static void write_keys_to_file(const std::string name, const std::vector< std::string > keys, std::ofstream& file)
  {
    std::string whitespace = Stuff::Common::whitespaceify(name + " = ");
    file << name << " = " << keys[0] << std::endl;
    for (size_t ii = 1; ii < keys.size(); ++ii)
      file << whitespace << keys[ii] << std::endl;
  } // ... write_keys_to_file(...)

  template< class ConfigProvider >
  static void write_config_to_file(std::ofstream& file)
  {
    for (const auto& type : ConfigProvider::available()) {
      auto config = ConfigProvider::default_config(type, type);
      if (!config.empty())
      file << config;
    }
  } // ... write_config_to_file(...)

  std::string filename_;
  Stuff::Common::ConfigTree config_;
  bool debug_logging_;
  std::unique_ptr< GridProviderType > grid_provider_;
  Stuff::Common::ConfigTree boundary_info_;
  std::unique_ptr< const ProblemType > problem_;
}; // class DiscreteProblem

} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_LINEARELLIPTIC_DISCRETEPROBLEM_HH
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "MethodSimilarityOrderer.h"

#include "DexInstruction.h"
#include "Show.h"
#include "Trace.h"

void MethodSimilarityOrderer::gather_code_hash_ids(
    const DexCode* code, std::unordered_set<CodeHashId>& code_hash_ids) {
  auto& instructions = code->get_instructions();

  // First, we partition the instructions into chunks, where each chunk ends
  // when an instruction can change control-flow.
  struct Chunk {
    size_t start;
    size_t end;
  };
  std::vector<Chunk> chunks;
  size_t start{0};
  for (size_t i = 0; i < instructions.size(); i++) {
    auto op = instructions.at(i)->opcode();
    if (dex_opcode::is_branch(op) || dex_opcode::is_return(op) ||
        op == DOPCODE_THROW) {
      chunks.push_back({start, i + 1});
      start = i;
    }
  }

  // For any instruction-sequence, we can compute a (stable) hash representing
  // it
  auto hash_sub_chunk = [&](const Chunk& sub_chunk) {
    always_assert(sub_chunk.start < sub_chunk.end);
    uint64_t code_hash{0};
    for (size_t i = sub_chunk.start; i < sub_chunk.end; i++) {
      auto insn = instructions.at(i);
      auto op = insn->opcode();
      code_hash = code_hash * 23 + op;
      if (insn->has_literal()) {
        code_hash = code_hash * 7 + insn->get_literal();
      }
      if (insn->has_range()) {
        code_hash =
            (code_hash * 11 + insn->range_base()) * 11 + insn->range_size();
      }
      if (insn->has_dest()) {
        code_hash = code_hash * 13 + insn->dest();
      }
      for (unsigned j = 0; j < insn->srcs_size(); j++) {
        code_hash = code_hash * 17 + insn->src(j);
      }
    }
    auto it = m_code_hash_ids.find(code_hash);
    if (it == m_code_hash_ids.end()) {
      it = m_code_hash_ids.emplace(code_hash, m_code_hash_ids.size()).first;
    }
    code_hash_ids.insert(it->second);
  };

  // We'll further partition chunks into smaller pieces, and then hash those
  // sub-chunks
  for (auto& chunk : chunks) {
    constexpr size_t chunk_size = 3;
    if (chunk.end - chunk.start < chunk_size) {
      hash_sub_chunk(chunk);
      continue;
    }
    for (size_t i = chunk.start; i <= chunk.end - chunk_size; i++) {
      hash_sub_chunk({i, i + chunk_size});
    }
  }
}

void MethodSimilarityOrderer::insert(DexMethod* method) {
  always_assert(m_method_indices.count(method) == 0);
  size_t index = m_methods.size();
  m_methods.emplace(index, method);
  m_method_indices.emplace(method, index);

  auto& code_hash_ids = m_method_code_hash_ids[method];
  auto* code = method->get_dex_code();
  if (code) {
    gather_code_hash_ids(code, code_hash_ids);
  }

  for (auto code_hash_id : code_hash_ids) {
    m_code_hash_id_methods[code_hash_id].insert(method);
  }
}

DexMethod* MethodSimilarityOrderer::get_next() {
  if (m_methods.empty()) {
    return nullptr;
  }
  boost::optional<size_t> best_candidate_index;
  if (!m_last_code_hash_ids.empty()) {
    struct Score {
      int shared{0};
      int missing{0};
      int additional{0};
      int value() const { return 2 * shared - missing - 2 * additional; }
    };
    std::unordered_map<DexMethod*, Score> candidate_scores;
    // To compute the score, we add up how many matching code-hash-ids we
    // have...
    for (auto code_hash_id : m_last_code_hash_ids) {
      for (auto method : m_code_hash_id_methods.at(code_hash_id)) {
        candidate_scores[method].shared++;
      }
    }
    // minus penalty points for every non-matching code-hash-id
    for (auto& p : candidate_scores) {
      auto& other_code_hash_ids = m_method_code_hash_ids.at(p.first);
      for (auto other_code_hash_id : other_code_hash_ids) {
        if (!m_last_code_hash_ids.count(other_code_hash_id)) {
          p.second.additional++;
        }
      }
      for (auto code_hash_id : m_last_code_hash_ids) {
        if (!other_code_hash_ids.count(code_hash_id)) {
          p.second.missing++;
        }
      }
    }
    // Then we'll find the best matching candidate with a non-negative score.
    boost::optional<Score> best_candidate_score;
    for (auto& p : candidate_scores) {
      auto& score = p.second;
      if (score.value() < 0) {
        continue;
      }
      if (!best_candidate_score ||
          score.value() > best_candidate_score->value() ||
          (score.value() == best_candidate_score->value() &&
           best_candidate_index &&
           m_method_indices.at(p.first) < *best_candidate_index)) {
        best_candidate_index = m_method_indices.at(p.first);
        best_candidate_score = p.second;
      }
    }
    if (best_candidate_score) {
      TRACE(OPUT, 3,
            "[method-similarity-orderer]   selected %s with %d = %d - %d - %d",
            SHOW(m_methods.at(*best_candidate_index)),
            best_candidate_score->value(), best_candidate_score->shared,
            best_candidate_score->missing, best_candidate_score->additional);
    }
  }
  if (!best_candidate_index) {
    best_candidate_index = m_methods.begin()->first;
    TRACE(OPUT, 3, "[method-similarity-orderer] reverted to %s",
          SHOW(m_methods.at(*best_candidate_index)));
  }
  auto best_candidate_method = m_methods.at(*best_candidate_index);
  m_last_code_hash_ids =
      std::move(m_method_code_hash_ids.at(best_candidate_method));
  m_methods.erase(*best_candidate_index);
  m_method_code_hash_ids.erase(best_candidate_method);
  for (auto it = m_last_code_hash_ids.begin();
       it != m_last_code_hash_ids.end();) {
    auto code_hash_id = *it;
    auto& methods = m_code_hash_id_methods.at(code_hash_id);
    methods.erase(best_candidate_method);
    if (methods.empty()) {
      m_code_hash_id_methods.erase(code_hash_id);
      it = m_last_code_hash_ids.erase(it);
    } else {
      it++;
    }
  }
  return best_candidate_method;
}
<commit_msg>speed up the best candidate computations<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "MethodSimilarityOrderer.h"

#include "DexInstruction.h"
#include "Show.h"
#include "Trace.h"

void MethodSimilarityOrderer::gather_code_hash_ids(
    const DexCode* code, std::unordered_set<CodeHashId>& code_hash_ids) {
  auto& instructions = code->get_instructions();

  // First, we partition the instructions into chunks, where each chunk ends
  // when an instruction can change control-flow.
  struct Chunk {
    size_t start;
    size_t end;
  };
  std::vector<Chunk> chunks;
  size_t start{0};
  for (size_t i = 0; i < instructions.size(); i++) {
    auto op = instructions.at(i)->opcode();
    if (dex_opcode::is_branch(op) || dex_opcode::is_return(op) ||
        op == DOPCODE_THROW) {
      chunks.push_back({start, i + 1});
      start = i;
    }
  }

  // For any instruction-sequence, we can compute a (stable) hash representing
  // it
  auto hash_sub_chunk = [&](const Chunk& sub_chunk) {
    always_assert(sub_chunk.start < sub_chunk.end);
    uint64_t code_hash{0};
    for (size_t i = sub_chunk.start; i < sub_chunk.end; i++) {
      auto insn = instructions.at(i);
      auto op = insn->opcode();
      code_hash = code_hash * 23 + op;
      if (insn->has_literal()) {
        code_hash = code_hash * 7 + insn->get_literal();
      }
      if (insn->has_range()) {
        code_hash =
            (code_hash * 11 + insn->range_base()) * 11 + insn->range_size();
      }
      if (insn->has_dest()) {
        code_hash = code_hash * 13 + insn->dest();
      }
      for (unsigned j = 0; j < insn->srcs_size(); j++) {
        code_hash = code_hash * 17 + insn->src(j);
      }
    }
    auto it = m_code_hash_ids.find(code_hash);
    if (it == m_code_hash_ids.end()) {
      it = m_code_hash_ids.emplace(code_hash, m_code_hash_ids.size()).first;
    }
    code_hash_ids.insert(it->second);
  };

  // We'll further partition chunks into smaller pieces, and then hash those
  // sub-chunks
  for (auto& chunk : chunks) {
    constexpr size_t chunk_size = 3;
    if (chunk.end - chunk.start < chunk_size) {
      hash_sub_chunk(chunk);
      continue;
    }
    for (size_t i = chunk.start; i <= chunk.end - chunk_size; i++) {
      hash_sub_chunk({i, i + chunk_size});
    }
  }
}

void MethodSimilarityOrderer::insert(DexMethod* method) {
  always_assert(m_method_indices.count(method) == 0);
  size_t index = m_methods.size();
  m_methods.emplace(index, method);
  m_method_indices.emplace(method, index);

  auto& code_hash_ids = m_method_code_hash_ids[method];
  auto* code = method->get_dex_code();
  if (code) {
    gather_code_hash_ids(code, code_hash_ids);
  }

  for (auto code_hash_id : code_hash_ids) {
    m_code_hash_id_methods[code_hash_id].insert(method);
  }
}

DexMethod* MethodSimilarityOrderer::get_next() {
  if (m_methods.empty()) {
    return nullptr;
  }
  boost::optional<size_t> best_candidate_index;
  if (!m_last_code_hash_ids.empty()) {
    struct Score {
      size_t shared{0};
      size_t missing{0};
      size_t additional{0};
      int value() const { return 2 * shared - missing - 2 * additional; }
    };
    std::unordered_map<DexMethod*, Score> candidate_scores;
    // To compute the score, we add up how many matching code-hash-ids we
    // have...
    for (auto code_hash_id : m_last_code_hash_ids) {
      for (auto method : m_code_hash_id_methods.at(code_hash_id)) {
        candidate_scores[method].shared++;
      }
    }
    // minus penalty points for every non-matching code-hash-id
    for (auto& p : candidate_scores) {
      auto& other_code_hash_ids = m_method_code_hash_ids.at(p.first);

      size_t other_code_hash_ids_size = other_code_hash_ids.size();
      size_t last_code_hash_ids_size = m_last_code_hash_ids.size();

      p.second.additional = other_code_hash_ids_size - p.second.shared;
      p.second.missing = last_code_hash_ids_size - p.second.shared;
    }
    // Then we'll find the best matching candidate with a non-negative score.
    boost::optional<Score> best_candidate_score;
    for (auto& p : candidate_scores) {
      auto& score = p.second;
      if (score.value() < 0) {
        continue;
      }
      if (!best_candidate_score ||
          score.value() > best_candidate_score->value() ||
          (score.value() == best_candidate_score->value() &&
           best_candidate_index &&
           m_method_indices.at(p.first) < *best_candidate_index)) {
        best_candidate_index = m_method_indices.at(p.first);
        best_candidate_score = p.second;
      }
    }
    if (best_candidate_score) {
      TRACE(OPUT, 3,
            "[method-similarity-orderer]   selected %s with %d = %d - %d - %d",
            SHOW(m_methods.at(*best_candidate_index)),
            best_candidate_score->value(), best_candidate_score->shared,
            best_candidate_score->missing, best_candidate_score->additional);
    }
  }
  if (!best_candidate_index) {
    best_candidate_index = m_methods.begin()->first;
    TRACE(OPUT, 3, "[method-similarity-orderer] reverted to %s",
          SHOW(m_methods.at(*best_candidate_index)));
  }
  auto best_candidate_method = m_methods.at(*best_candidate_index);
  m_last_code_hash_ids =
      std::move(m_method_code_hash_ids.at(best_candidate_method));
  m_methods.erase(*best_candidate_index);
  m_method_code_hash_ids.erase(best_candidate_method);
  for (auto it = m_last_code_hash_ids.begin();
       it != m_last_code_hash_ids.end();) {
    auto code_hash_id = *it;
    auto& methods = m_code_hash_id_methods.at(code_hash_id);
    methods.erase(best_candidate_method);
    if (methods.empty()) {
      m_code_hash_id_methods.erase(code_hash_id);
      it = m_last_code_hash_ids.erase(it);
    } else {
      it++;
    }
  }
  return best_candidate_method;
}
<|endoftext|>


<commit_before><commit_msg>fix compile error<commit_after><|endoftext|>


<commit_before><commit_msg>Add a reminder to test against the actual version<commit_after><|endoftext|>


<commit_before><commit_msg>Fortify TestTextError<commit_after><|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /fs/turing/cvs/copasi_dev/copasi/UI/CQExpressionMmlStackedWidget.cpp,v $
//   $Revision: 1.2 $
//   $Name: HEAD $
//   $Author: pwilly $
//   $Date: 2009/10/01 12:58:00 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "CQExpressionMmlStackedWidget.h"

#include "utilities/CCopasiException.h"

#include "CQMessageBox.h"
#include "qtUtilities.h" // for UTF8
#include "CopasiFileDialog.h"
#include "tex/CMathMLToTeX.h"

#include <QtDebug>

/*
 *  Constructs a CQExpressionMmlWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
CQExpressionMmlStackedWidget::CQExpressionMmlStackedWidget(QWidget* parent)
    : QStackedWidget(parent)
{
  setupUi(this);

  const QIcon icon = qt_get_icon(image0_ID);
  mpBtnExpressionObject->setIcon(icon);

  const QIcon icon1 = qt_get_icon(image1_ID);
  mpBtnViewExpression->setIcon(icon1);

  const QIcon icon2 = qt_get_icon(image2_ID);
  mpBtnEditExpression->setIcon(icon2);

  const QIcon icon3 = qt_get_icon(image3_ID);
  mpBtnSaveExpression->setIcon(icon3);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQExpressionMmlStackedWidget::~CQExpressionMmlStackedWidget()
{
  // no need to delete child widgets, Qt does it all for us
}

/*
 *  Sets the strings of the subwidgets using the current
 *  language.
 */
void CQExpressionMmlStackedWidget::languageChange()
{
  retranslateUi(this);
}

void CQExpressionMmlStackedWidget::slotGoExpressionWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::slotGoExpressionWidget() -";
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpExpressionPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::slotGoMmlWidget()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpMmlPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::updateWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::updateWidget() -";
#endif

#ifdef HAVE_MML

  std::ostringstream mml;
  std::vector<std::vector<std::string> > params;

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif

  if (mpExpressionWidget->text().isEmpty() ||
      !mpExpressionWidget->isValid())
    setCurrentWidget(mpExpressionPage);
  else
    {
      mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

#ifdef DEBUG_UI
      qDebug() << "mml.str() = " << FROM_UTF8(mml.str());
#endif

      setCurrentWidget(mpMmlPage);
      mpMmlScrollView->updateWidget(mml);
      MMLStr = FROM_UTF8(mml.str());
    }

#endif /* HAVE_MML */

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::init()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif

#ifndef HAVE_MML
  mpBtnViewExpression->hide();
#endif // not HAVE_MML
}

void CQExpressionMmlStackedWidget::slotSaveExpression()
{
  QString *filter = new QString;
  QString outfilename;

  C_INT32 Answer = QMessageBox::No;

  while (Answer == QMessageBox::No)
    {
      outfilename =
        CopasiFileDialog::getSaveFileName(this,
                                          "Save File Dialog",
                                          "untitled.mml",
                                          "MathML (*.mml);;TeX (*.tex)",
//                                          "Save Expression to Disk", new QString);
                                          "Save Expression to Disk", filter);

      if (outfilename.isEmpty()) return;

      // Checks whether the file exists
      Answer = checkSelection(outfilename);

      if (Answer == QMessageBox::Cancel)
        return;
    }

  QString suffix = FROM_UTF8(CDirEntry::suffix(TO_UTF8(outfilename)));

#ifdef DEBUG_UI
  qDebug() << "\non CQEMSW::slotSaveExpression -> outfilename = " << outfilename;
  qDebug() << "\non CQEMSW::slotSaveExpression -> suffix = " << suffix;
  qDebug() << "\non CQEMSW::slotSaveExpression -> filter = " << *filter << "\n";
#endif

  if (filter->contains("tex"))
    saveTeX(outfilename);
  else
    saveMML(outfilename);
}

void CQExpressionMmlStackedWidget::saveMML(const QString outfilename)
{
  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
  ofile << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"HTMLFiles/xhtml-math11-f.dtd\">" << std::endl;
  ofile << "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">" << std::endl;

  mpExpressionWidget->mpValidator->getExpression()->writeMathML(ofile, false, 0);

  ofile << "</math>" << std::endl;

  ofile.close();
}

void CQExpressionMmlStackedWidget::saveTeX(const QString outfilename)
{
  std::ostringstream mml;
  mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

  QString latexStr(FROM_UTF8(mml.str()));

  CMathMLToTeX::convert(latexStr);

  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << TO_UTF8(latexStr);

  ofile.close();
}
<commit_msg>Fix bug by deleting unnecessary variable.<commit_after>// Begin CVS Header
//   $Source: /fs/turing/cvs/copasi_dev/copasi/UI/CQExpressionMmlStackedWidget.cpp,v $
//   $Revision: 1.2 $
//   $Name: HEAD $
//   $Author: pwilly $
//   $Date: 2009/10/01 12:58:00 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include "CQExpressionMmlStackedWidget.h"

#include "utilities/CCopasiException.h"

#include "CQMessageBox.h"
#include "qtUtilities.h" // for UTF8
#include "CopasiFileDialog.h"
#include "tex/CMathMLToTeX.h"

#include <QtDebug>

/*
 *  Constructs a CQExpressionMmlWidget as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
CQExpressionMmlStackedWidget::CQExpressionMmlStackedWidget(QWidget* parent)
    : QStackedWidget(parent)
{
  setupUi(this);

  const QIcon icon = qt_get_icon(image0_ID);
  mpBtnExpressionObject->setIcon(icon);

  const QIcon icon1 = qt_get_icon(image1_ID);
  mpBtnViewExpression->setIcon(icon1);

  const QIcon icon2 = qt_get_icon(image2_ID);
  mpBtnEditExpression->setIcon(icon2);

  const QIcon icon3 = qt_get_icon(image3_ID);
  mpBtnSaveExpression->setIcon(icon3);

  init();
}

/*
 *  Destroys the object and frees any allocated resources
 */
CQExpressionMmlStackedWidget::~CQExpressionMmlStackedWidget()
{
  // no need to delete child widgets, Qt does it all for us
}

/*
 *  Sets the strings of the subwidgets using the current
 *  language.
 */
void CQExpressionMmlStackedWidget::languageChange()
{
  retranslateUi(this);
}

void CQExpressionMmlStackedWidget::slotGoExpressionWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::slotGoExpressionWidget() -";
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpExpressionPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::slotGoMmlWidget()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
#endif

  setCurrentWidget(mpMmlPage);

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::updateWidget()
{
#ifdef DEBUG_UI
  qDebug() << "- here on CQExpressionMmlStackedWidget::updateWidget() -";
#endif

#ifdef HAVE_MML

  std::ostringstream mml;
  std::vector<std::vector<std::string> > params;

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget NEW = " << currentIndex();
#endif

  if (mpExpressionWidget->text().isEmpty() ||
      !mpExpressionWidget->isValid())
    setCurrentWidget(mpExpressionPage);
  else
    {
      mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

#ifdef DEBUG_UI
      qDebug() << "mml.str() = " << FROM_UTF8(mml.str());
#endif

      setCurrentWidget(mpMmlPage);
      mpMmlScrollView->updateWidget(mml);
      MMLStr = FROM_UTF8(mml.str());
    }

#endif /* HAVE_MML */

#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif
}

void CQExpressionMmlStackedWidget::init()
{
#ifdef DEBUG_UI
  qDebug() << "L" << __LINE__ << " on CQEMSW mpExpressionWidget->text() = " << mpExpressionWidget->text();
  qDebug() << "L" << __LINE__ << " on CQEMSW: activeWidget = " << currentIndex();
#endif

#ifndef HAVE_MML
  mpBtnViewExpression->hide();
#endif // not HAVE_MML
}

void CQExpressionMmlStackedWidget::slotSaveExpression()
{
  QString *filter = new QString;
  QString outfilename;

  C_INT32 Answer = QMessageBox::No;

  while (Answer == QMessageBox::No)
    {
      outfilename =
        CopasiFileDialog::getSaveFileName(this,
                                          "Save File Dialog",
                                          "untitled.mml",
                                          "MathML (*.mml);;TeX (*.tex)",
//                                          "Save Expression to Disk", new QString);
                                          "Save Expression to Disk", filter);

      if (outfilename.isEmpty()) return;

      // Checks whether the file exists
      Answer = checkSelection(outfilename);

      if (Answer == QMessageBox::Cancel)
        return;
    }

#ifdef DEBUG_UI
  qDebug() << "\non CQEMSW::slotSaveExpression -> filter = " << *filter << "\n";
#endif

  if (filter->contains("tex"))
    saveTeX(outfilename);
  else
    saveMML(outfilename);
}

void CQExpressionMmlStackedWidget::saveMML(const QString outfilename)
{
  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
  ofile << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"HTMLFiles/xhtml-math11-f.dtd\">" << std::endl;
  ofile << "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">" << std::endl;

  mpExpressionWidget->mpValidator->getExpression()->writeMathML(ofile, false, 0);

  ofile << "</math>" << std::endl;

  ofile.close();
}

void CQExpressionMmlStackedWidget::saveTeX(const QString outfilename)
{
  std::ostringstream mml;
  mpExpressionWidget->mpValidator->getExpression()->writeMathML(mml, false, 0);

  QString latexStr(FROM_UTF8(mml.str()));

  CMathMLToTeX::convert(latexStr);

  std::ofstream ofile;
  ofile.open(utf8ToLocale(TO_UTF8(outfilename)).c_str(), std::ios::trunc);

  ofile << TO_UTF8(latexStr);

  ofile.close();
}
<|endoftext|>


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

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

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

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

#include <iostream>
#include "absl/strings/str_split.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {

class AssertOp : public OpKernel {
 public:
  explicit AssertOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("summarize", &summarize_));
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& cond = ctx->input(0);
    OP_REQUIRES(ctx, IsLegacyScalar(cond.shape()),
                errors::InvalidArgument("In[0] should be a scalar: ",
                                        cond.shape().DebugString()));

    if (cond.scalar<bool>()()) {
      return;
    }
    string msg = "assertion failed: ";
    for (int i = 1; i < ctx->num_inputs(); ++i) {
      strings::StrAppend(&msg, "[", ctx->input(i).SummarizeValue(summarize_),
                         "]");
      if (i < ctx->num_inputs() - 1) strings::StrAppend(&msg, " ");
    }
    ctx->SetStatus(errors::InvalidArgument(msg));
  }

 private:
  int32 summarize_ = 0;
};

REGISTER_KERNEL_BUILDER(Name("Assert").Device(DEVICE_CPU), AssertOp);

class PrintOp : public OpKernel {
 public:
  explicit PrintOp(OpKernelConstruction* ctx)
      : OpKernel(ctx), call_counter_(0) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("message", &message_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("first_n", &first_n_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("summarize", &summarize_));
  }

  void Compute(OpKernelContext* ctx) override {
    if (IsRefType(ctx->input_dtype(0))) {
      ctx->forward_ref_input_to_ref_output(0, 0);
    } else {
      ctx->set_output(0, ctx->input(0));
    }
    if (first_n_ >= 0) {
      mutex_lock l(mu_);
      if (call_counter_ >= first_n_) return;
      call_counter_++;
    }
    string msg;
    strings::StrAppend(&msg, message_);
    for (int i = 1; i < ctx->num_inputs(); ++i) {
      strings::StrAppend(&msg, ctx->input(i).SummarizeValue(summarize_));
    }
    std::cerr << msg << std::endl;
  }

 private:
  mutex mu_;
  int64 call_counter_ GUARDED_BY(mu_) = 0;
  int64 first_n_ = 0;
  int32 summarize_ = 0;
  string message_;
};

REGISTER_KERNEL_BUILDER(Name("Print").Device(DEVICE_CPU), PrintOp);

class PrintV2Op : public OpKernel {
 public:
  explicit PrintV2Op(OpKernelConstruction* ctx) : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("output_stream", &output_stream_));

    auto output_stream_index =
        std::find(std::begin(valid_output_streams_),
                  std::end(valid_output_streams_), output_stream_);

    if (output_stream_index == std::end(valid_output_streams_)) {
      string error_msg = strings::StrCat(
          "Unknown output stream: ", output_stream_, ", Valid streams are:");
      for (auto valid_stream : valid_output_streams_) {
        strings::StrAppend(&error_msg, " ", valid_stream);
      }
      OP_REQUIRES(ctx, false, errors::InvalidArgument(error_msg));
    }
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor* input_;
    OP_REQUIRES_OK(ctx, ctx->input("input", &input_));
    const string& msg = input_->scalar<string>()();

    if (output_stream_ == "stdout") {
      std::cout << msg << std::endl;
    } else if (output_stream_ == "stderr") {
      std::cerr << msg << std::endl;
    } else if (output_stream_ == "log(info)") {
      LOG(INFO) << msg << std::endl;
    } else if (output_stream_ == "log(warning)") {
      LOG(WARNING) << msg << std::endl;
    } else if (output_stream_ == "log(error)") {
      LOG(ERROR) << msg << std::endl;
    } else {
      string error_msg = strings::StrCat(
          "Unknown output stream: ", output_stream_, ", Valid streams are:");
      for (auto valid_stream : valid_output_streams_) {
        strings::StrAppend(&error_msg, " ", valid_stream);
      }
      OP_REQUIRES(ctx, false, errors::InvalidArgument(error_msg));
    }
  }

  const char* valid_output_streams_[6] = {"stdout", "stderr", "log(info)",
                                          "log(warning)", "log(error)"};

 private:
  string output_stream_;
};

REGISTER_KERNEL_BUILDER(Name("PrintV2").Device(DEVICE_CPU), PrintV2Op);

class TimestampOp : public OpKernel {
 public:
  explicit TimestampOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    TensorShape output_shape;  // Default shape is 0 dim, 1 element
    Tensor* output_tensor = nullptr;
    OP_REQUIRES_OK(context,
                   context->allocate_output(0, output_shape, &output_tensor));

    auto output_scalar = output_tensor->scalar<double>();
    double now_us = static_cast<double>(Env::Default()->NowMicros());
    double now_s = now_us / 1000000;
    output_scalar() = now_s;
  }
};

REGISTER_KERNEL_BUILDER(Name("Timestamp").Device(DEVICE_CPU), TimestampOp);

}  // end namespace tensorflow
<commit_msg>Fixes regression to tf.Print that removed square braces around printed tensors.<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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

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

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

#include <iostream>
#include "absl/strings/str_split.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {

class AssertOp : public OpKernel {
 public:
  explicit AssertOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("summarize", &summarize_));
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& cond = ctx->input(0);
    OP_REQUIRES(ctx, IsLegacyScalar(cond.shape()),
                errors::InvalidArgument("In[0] should be a scalar: ",
                                        cond.shape().DebugString()));

    if (cond.scalar<bool>()()) {
      return;
    }
    string msg = "assertion failed: ";
    for (int i = 1; i < ctx->num_inputs(); ++i) {
      strings::StrAppend(&msg, "[", ctx->input(i).SummarizeValue(summarize_),
                         "]");
      if (i < ctx->num_inputs() - 1) strings::StrAppend(&msg, " ");
    }
    ctx->SetStatus(errors::InvalidArgument(msg));
  }

 private:
  int32 summarize_ = 0;
};

REGISTER_KERNEL_BUILDER(Name("Assert").Device(DEVICE_CPU), AssertOp);

class PrintOp : public OpKernel {
 public:
  explicit PrintOp(OpKernelConstruction* ctx)
      : OpKernel(ctx), call_counter_(0) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("message", &message_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("first_n", &first_n_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("summarize", &summarize_));
  }

  void Compute(OpKernelContext* ctx) override {
    if (IsRefType(ctx->input_dtype(0))) {
      ctx->forward_ref_input_to_ref_output(0, 0);
    } else {
      ctx->set_output(0, ctx->input(0));
    }
    if (first_n_ >= 0) {
      mutex_lock l(mu_);
      if (call_counter_ >= first_n_) return;
      call_counter_++;
    }
    string msg;
    strings::StrAppend(&msg, message_);
    for (int i = 1; i < ctx->num_inputs(); ++i) {
      strings::StrAppend(&msg, "[", ctx->input(i).SummarizeValue(summarize_),
                         "]");
    }
    std::cerr << msg << std::endl;
  }

 private:
  mutex mu_;
  int64 call_counter_ GUARDED_BY(mu_) = 0;
  int64 first_n_ = 0;
  int32 summarize_ = 0;
  string message_;
};

REGISTER_KERNEL_BUILDER(Name("Print").Device(DEVICE_CPU), PrintOp);

class PrintV2Op : public OpKernel {
 public:
  explicit PrintV2Op(OpKernelConstruction* ctx) : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("output_stream", &output_stream_));

    auto output_stream_index =
        std::find(std::begin(valid_output_streams_),
                  std::end(valid_output_streams_), output_stream_);

    if (output_stream_index == std::end(valid_output_streams_)) {
      string error_msg = strings::StrCat(
          "Unknown output stream: ", output_stream_, ", Valid streams are:");
      for (auto valid_stream : valid_output_streams_) {
        strings::StrAppend(&error_msg, " ", valid_stream);
      }
      OP_REQUIRES(ctx, false, errors::InvalidArgument(error_msg));
    }
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor* input_;
    OP_REQUIRES_OK(ctx, ctx->input("input", &input_));
    const string& msg = input_->scalar<string>()();

    if (output_stream_ == "stdout") {
      std::cout << msg << std::endl;
    } else if (output_stream_ == "stderr") {
      std::cerr << msg << std::endl;
    } else if (output_stream_ == "log(info)") {
      LOG(INFO) << msg << std::endl;
    } else if (output_stream_ == "log(warning)") {
      LOG(WARNING) << msg << std::endl;
    } else if (output_stream_ == "log(error)") {
      LOG(ERROR) << msg << std::endl;
    } else {
      string error_msg = strings::StrCat(
          "Unknown output stream: ", output_stream_, ", Valid streams are:");
      for (auto valid_stream : valid_output_streams_) {
        strings::StrAppend(&error_msg, " ", valid_stream);
      }
      OP_REQUIRES(ctx, false, errors::InvalidArgument(error_msg));
    }
  }

  const char* valid_output_streams_[6] = {"stdout", "stderr", "log(info)",
                                          "log(warning)", "log(error)"};

 private:
  string output_stream_;
};

REGISTER_KERNEL_BUILDER(Name("PrintV2").Device(DEVICE_CPU), PrintV2Op);

class TimestampOp : public OpKernel {
 public:
  explicit TimestampOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    TensorShape output_shape;  // Default shape is 0 dim, 1 element
    Tensor* output_tensor = nullptr;
    OP_REQUIRES_OK(context,
                   context->allocate_output(0, output_shape, &output_tensor));

    auto output_scalar = output_tensor->scalar<double>();
    double now_us = static_cast<double>(Env::Default()->NowMicros());
    double now_s = now_us / 1000000;
    output_scalar() = now_s;
  }
};

REGISTER_KERNEL_BUILDER(Name("Timestamp").Device(DEVICE_CPU), TimestampOp);

}  // end namespace tensorflow
<|endoftext|>


<commit_before><commit_msg>Positive return codes and better handling in array parsing test<commit_after><|endoftext|>