<commit_before>#include "CoolingBuffer.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <iostream>

namespace Slic3r {

std::string
CoolingBuffer::append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z)
{
    std::string out;
    if (this->_last_z.find(obj_id) != this->_last_z.end()) {
        // A layer was finished, Z of the object's layer changed. Process the layer.
        out = this->flush();
    }

    this->_layer_id = layer_id;
    this->_last_z[obj_id] = print_z;
    this->_gcode += gcode;
    // This is a very rough estimate of the print time,
    // not taking into account the acceleration curves generated by the printer firmware.
    this->_elapsed_time += this->_gcodegen->elapsed_time;
    this->_gcodegen->elapsed_time = 0;

    return out;
}

void
apply_speed_factor(std::string &line, float speed_factor, float min_print_speed)
{
    // find pos of F
    size_t pos = line.find_first_of('F');
    size_t last_pos = line.find_first_of(' ', pos+1);

    // extract current speed
    float speed;
    {
        std::istringstream iss(line.substr(pos+1, last_pos));
        iss >> speed;
    }

    // change speed
    speed *= speed_factor;
    speed = std::max(speed, min_print_speed);

    // replace speed in string
    {
        std::ostringstream oss;
        oss << speed;
        line.replace(pos+1, (last_pos-pos), oss.str());
    }
}

std::string
CoolingBuffer::flush()
{
    GCode &gg = *this->_gcodegen;

    std::string gcode   = this->_gcode;
    float elapsed       = this->_elapsed_time;
    this->_gcode        = "";
    this->_elapsed_time = 0;
    this->_last_z.clear(); // reset the whole table otherwise we would compute overlapping times

    int fan_speed = gg.config.fan_always_on ? gg.config.min_fan_speed.value : 0;

    float speed_factor = 1.0;

    if (gg.config.cooling) {
        #ifdef SLIC3R_DEBUG
        printf("Layer %zu estimated printing time: %f seconds\n", layer_id, elapsed);
        #endif

        if (elapsed < (float)gg.config.slowdown_below_layer_time) {
            // Layer time very short. Enable the fan to a full throttle and slow down the print
            // (stretch the layer print time to slowdown_below_layer_time).
            fan_speed = gg.config.max_fan_speed;
            speed_factor = elapsed / (float)gg.config.slowdown_below_layer_time;
        } else if (elapsed < (float)gg.config.fan_below_layer_time) {
            // Layer time quite short. Enable the fan proportionally according to the current layer time.
            fan_speed = gg.config.max_fan_speed
                - (gg.config.max_fan_speed - gg.config.min_fan_speed)
                * (elapsed - (float)gg.config.slowdown_below_layer_time)
                / (gg.config.fan_below_layer_time - gg.config.slowdown_below_layer_time);
        }

        #ifdef SLIC3R_DEBUG
        printf("  fan = %d%%, speed = %f%%\n", fan_speed, speed_factor * 100);
        #endif

        if (speed_factor < 1.0) {
            // Adjust feed rate of G1 commands marked with an _EXTRUDE_SET_SPEED
            // as long as they are not _WIPE moves (they cannot if they are _EXTRUDE_SET_SPEED)
            // and they are not preceded directly by _BRIDGE_FAN_START (do not adjust bridging speed).
            std::string new_gcode;
            std::istringstream ss(gcode);
            std::string line;
            bool bridge_fan_start = false;
            while (std::getline(ss, line)) {
                if (boost::starts_with(line, "G1")
                    && boost::contains(line, ";_EXTRUDE_SET_SPEED")
                    && !boost::contains(line, ";_WIPE")
                    && !bridge_fan_start) {
                    apply_speed_factor(line, speed_factor, this->_min_print_speed);
                    boost::replace_first(line, ";_EXTRUDE_SET_SPEED", "");
                }
                bridge_fan_start = boost::contains(line, ";_BRIDGE_FAN_START");
                new_gcode += line + '\n';
            }
            gcode = new_gcode;
        }
    }
    if (this->_layer_id < gg.config.disable_fan_first_layers)
        fan_speed = 0;

    gcode = gg.writer.set_fan(fan_speed) + gcode;

    // bridge fan speed
    if (!gg.config.cooling || gg.config.bridge_fan_speed == 0 || this->_layer_id < gg.config.disable_fan_first_layers) {
        boost::replace_all(gcode, ";_BRIDGE_FAN_START", "");
        boost::replace_all(gcode, ";_BRIDGE_FAN_END", "");
    } else {
        boost::replace_all(gcode, ";_BRIDGE_FAN_START", gg.writer.set_fan(gg.config.bridge_fan_speed, true));
        boost::replace_all(gcode, ";_BRIDGE_FAN_END",   gg.writer.set_fan(fan_speed, true));
    }
    boost::replace_all(gcode, ";_WIPE", "");
    boost::replace_all(gcode, ";_EXTRUDE_SET_SPEED", "");

    return gcode;
}

}
<commit_msg>Fix typo in debug code, use this->_layer_id not plain layer_id.<commit_after>#include "CoolingBuffer.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <iostream>

namespace Slic3r {

std::string
CoolingBuffer::append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z)
{
    std::string out;
    if (this->_last_z.find(obj_id) != this->_last_z.end()) {
        // A layer was finished, Z of the object's layer changed. Process the layer.
        out = this->flush();
    }

    this->_layer_id = layer_id;
    this->_last_z[obj_id] = print_z;
    this->_gcode += gcode;
    // This is a very rough estimate of the print time,
    // not taking into account the acceleration curves generated by the printer firmware.
    this->_elapsed_time += this->_gcodegen->elapsed_time;
    this->_gcodegen->elapsed_time = 0;

    return out;
}

void
apply_speed_factor(std::string &line, float speed_factor, float min_print_speed)
{
    // find pos of F
    size_t pos = line.find_first_of('F');
    size_t last_pos = line.find_first_of(' ', pos+1);

    // extract current speed
    float speed;
    {
        std::istringstream iss(line.substr(pos+1, last_pos));
        iss >> speed;
    }

    // change speed
    speed *= speed_factor;
    speed = std::max(speed, min_print_speed);

    // replace speed in string
    {
        std::ostringstream oss;
        oss << speed;
        line.replace(pos+1, (last_pos-pos), oss.str());
    }
}

std::string
CoolingBuffer::flush()
{
    GCode &gg = *this->_gcodegen;

    std::string gcode   = this->_gcode;
    float elapsed       = this->_elapsed_time;
    this->_gcode        = "";
    this->_elapsed_time = 0;
    this->_last_z.clear(); // reset the whole table otherwise we would compute overlapping times

    int fan_speed = gg.config.fan_always_on ? gg.config.min_fan_speed.value : 0;

    float speed_factor = 1.0;

    if (gg.config.cooling) {
        #ifdef SLIC3R_DEBUG
        printf("Layer %zu estimated printing time: %f seconds\n", this->_layer_id, elapsed);
        #endif

        if (elapsed < (float)gg.config.slowdown_below_layer_time) {
            // Layer time very short. Enable the fan to a full throttle and slow down the print
            // (stretch the layer print time to slowdown_below_layer_time).
            fan_speed = gg.config.max_fan_speed;
            speed_factor = elapsed / (float)gg.config.slowdown_below_layer_time;
        } else if (elapsed < (float)gg.config.fan_below_layer_time) {
            // Layer time quite short. Enable the fan proportionally according to the current layer time.
            fan_speed = gg.config.max_fan_speed
                - (gg.config.max_fan_speed - gg.config.min_fan_speed)
                * (elapsed - (float)gg.config.slowdown_below_layer_time)
                / (gg.config.fan_below_layer_time - gg.config.slowdown_below_layer_time);
        }

        #ifdef SLIC3R_DEBUG
        printf("  fan = %d%%, speed = %f%%\n", fan_speed, speed_factor * 100);
        #endif

        if (speed_factor < 1.0) {
            // Adjust feed rate of G1 commands marked with an _EXTRUDE_SET_SPEED
            // as long as they are not _WIPE moves (they cannot if they are _EXTRUDE_SET_SPEED)
            // and they are not preceded directly by _BRIDGE_FAN_START (do not adjust bridging speed).
            std::string new_gcode;
            std::istringstream ss(gcode);
            std::string line;
            bool bridge_fan_start = false;
            while (std::getline(ss, line)) {
                if (boost::starts_with(line, "G1")
                    && boost::contains(line, ";_EXTRUDE_SET_SPEED")
                    && !boost::contains(line, ";_WIPE")
                    && !bridge_fan_start) {
                    apply_speed_factor(line, speed_factor, this->_min_print_speed);
                    boost::replace_first(line, ";_EXTRUDE_SET_SPEED", "");
                }
                bridge_fan_start = boost::contains(line, ";_BRIDGE_FAN_START");
                new_gcode += line + '\n';
            }
            gcode = new_gcode;
        }
    }
    if (this->_layer_id < gg.config.disable_fan_first_layers)
        fan_speed = 0;

    gcode = gg.writer.set_fan(fan_speed) + gcode;

    // bridge fan speed
    if (!gg.config.cooling || gg.config.bridge_fan_speed == 0 || this->_layer_id < gg.config.disable_fan_first_layers) {
        boost::replace_all(gcode, ";_BRIDGE_FAN_START", "");
        boost::replace_all(gcode, ";_BRIDGE_FAN_END", "");
    } else {
        boost::replace_all(gcode, ";_BRIDGE_FAN_START", gg.writer.set_fan(gg.config.bridge_fan_speed, true));
        boost::replace_all(gcode, ";_BRIDGE_FAN_END",   gg.writer.set_fan(fan_speed, true));
    }
    boost::replace_all(gcode, ";_WIPE", "");
    boost::replace_all(gcode, ";_EXTRUDE_SET_SPEED", "");

    return gcode;
}

}
<|endoftext|>


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

#include "content/browser/renderer_host/video_capture_controller.h"

#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "content/browser/browser_thread.h"
#include "content/browser/media_stream/video_capture_manager.h"
#include "media/base/yuv_convert.h"

#if defined(OS_WIN)
#include "content/common/section_util_win.h"
#endif

// The number of TransportDIBs VideoCaptureController allocate.
static const size_t kNoOfDIBS = 3;

VideoCaptureController::VideoCaptureController(
    ControllerId id,
    base::ProcessHandle render_process,
    EventHandler* event_handler)
    : render_handle_(render_process),
      report_ready_to_delete_(false),
      event_handler_(event_handler),
      id_(id) {}

VideoCaptureController::~VideoCaptureController() {
  // Delete all TransportDIBs.
  STLDeleteContainerPairSecondPointers(owned_dibs_.begin(),
                                       owned_dibs_.end());
}

void VideoCaptureController::StartCapture(
    const media::VideoCaptureParams& params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  params_ = params;
  media_stream::VideoCaptureManager* manager =
      media_stream::VideoCaptureManager::Get();
  // Order the manager to start the actual capture.
  manager->Start(params, this);
}

void VideoCaptureController::StopCapture(Task* stopped_task) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  media_stream::VideoCaptureManager* manager =
      media_stream::VideoCaptureManager::Get();
  manager->Stop(params_.session_id,
                NewRunnableMethod(this,
                                  &VideoCaptureController::OnDeviceStopped,
                                  stopped_task));
}

void VideoCaptureController::ReturnTransportDIB(TransportDIB::Handle handle) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool ready_to_delete;
  {
    base::AutoLock lock(lock_);
    free_dibs_.push_back(handle);
    ready_to_delete = (free_dibs_.size() == owned_dibs_.size());
  }
  if (report_ready_to_delete_ && ready_to_delete) {
    event_handler_->OnReadyToDelete(id_);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Implements VideoCaptureDevice::EventHandler.
// OnIncomingCapturedFrame is called the thread running the capture device.
// I.e.- DirectShow thread on windows and v4l2_thread on Linux.
void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
                                                     int length,
                                                     base::Time timestamp) {
  TransportDIB::Handle handle;
  TransportDIB* dib;
  // Check if there is a TransportDIB to fill.
  bool buffer_exist = false;
  {
    base::AutoLock lock(lock_);
    if (!report_ready_to_delete_ && free_dibs_.size() > 0) {
      handle = free_dibs_.back();
      free_dibs_.pop_back();
      DIBMap::iterator it = owned_dibs_.find(handle);
      if (it != owned_dibs_.end()) {
        dib = it->second;
        buffer_exist = true;
      }
    }
  }

  if (!buffer_exist) {
    return;
  }

  if (!dib->Map()) {
    VLOG(1) << "OnIncomingCapturedFrame - Failed to map handle.";
    base::AutoLock lock(lock_);
    free_dibs_.push_back(handle);
    return;
  }
  uint8* target = static_cast<uint8*>(dib->memory());
  CHECK(dib->size() >= static_cast<size_t> (frame_info_.width *
                                            frame_info_.height * 3) /
                                            2);

  // Do color conversion from the camera format to I420.
  switch (frame_info_.color) {
    case media::VideoCaptureDevice::kColorUnknown:  // Color format not set.
      break;
    case media::VideoCaptureDevice::kI420: {
      memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2);
      break;
    }
    case media::VideoCaptureDevice::kYUY2: {
      uint8* yplane = target;
      uint8* uplane = target + frame_info_.width * frame_info_.height;
      uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
      media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
                              frame_info_.height);
      break;
    }
    case media::VideoCaptureDevice::kRGB24: {
#if defined(OS_WIN)  // RGB on Windows start at the bottom line.
      uint8* yplane = target;
      uint8* uplane = target + frame_info_.width * frame_info_.height;
      uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
      int ystride = frame_info_.width;
      int uvstride = frame_info_.width / 2;
      int rgb_stride = - 3 * frame_info_.width;
      const uint8* rgb_src = data + 3 * frame_info_.width *
          (frame_info_.height -1);
#else
      uint8* yplane = target;
      uint8* uplane = target + frame_info_.width * frame_info_.height;
      uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
      int ystride = frame_info_.width;
      int uvstride = frame_info_.width / 2;
      int rgb_stride = 3 * frame_info_.width;
      const uint8* rgb_src = data;
#endif
      media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane,
                               frame_info_.width, frame_info_.height,
                               rgb_stride, ystride, uvstride);
      break;
    }
    case media::VideoCaptureDevice::kARGB: {
      uint8* yplane = target;
      uint8* uplane = target +  frame_info_.width * frame_info_.height;
      uint8* vplane = uplane +  (frame_info_.width * frame_info_.height) / 4;
      media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width,
                               frame_info_.height, frame_info_.width * 4,
                               frame_info_.width, frame_info_.width / 2);
      break;
    }
    default:
      NOTREACHED();
  }

  event_handler_->OnBufferReady(id_, handle, timestamp);
}

void VideoCaptureController::OnError() {
  event_handler_->OnError(id_);
}

void VideoCaptureController::OnFrameInfo(
    const media::VideoCaptureDevice::Capability& info) {
  DCHECK(owned_dibs_.empty());
  bool frames_created = true;
  const size_t needed_size = (info.width * info.height * 3) / 2;
  for (size_t i = 0; i < kNoOfDIBS; ++i) {
    TransportDIB* dib = TransportDIB::Create(needed_size, i);
    if (!dib) {
      frames_created = false;
      break;
    }
    // Lock needed since the buffers are used in OnIncomingFrame
    // and we need to use it there in order to avoid memcpy of complete frames.
    base::AutoLock lock(lock_);
#if defined(OS_WIN)
    // On Windows we need to get a handle the can be used in the render process.
    TransportDIB::Handle handle = chrome::GetSectionForProcess(
        dib->handle(), render_handle_, false);
#else
    TransportDIB::Handle handle = dib->handle();
#endif
    owned_dibs_.insert(std::make_pair(handle, dib));
    free_dibs_.push_back(handle);
  }
  frame_info_= info;

  // Check that all DIBs where created successfully.
  if (!frames_created) {
    event_handler_->OnError(id_);
  }
  event_handler_->OnFrameInfo(id_, info.width, info.height,
                              info.frame_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Called by VideoCaptureManager when a device have been stopped.
// This will report to the event handler that this object is ready to be deleted
// if all DIBS have been returned.
void VideoCaptureController::OnDeviceStopped(Task* stopped_task) {
  bool ready_to_delete_now;

  // Set flag to indicate we need to report when all DIBs have been returned.
  report_ready_to_delete_ = true;
  {
    base::AutoLock lock(lock_);
    ready_to_delete_now = (free_dibs_.size() == owned_dibs_.size());
  }

  if (ready_to_delete_now) {
    event_handler_->OnReadyToDelete(id_);
  }
  if (stopped_task) {
    stopped_task->Run();
    delete stopped_task;
  }
}
<commit_msg>Fix ARM build break introduced in r86927.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/video_capture_controller.h"

#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "content/browser/browser_thread.h"
#include "content/browser/media_stream/video_capture_manager.h"
#include "media/base/yuv_convert.h"

#if defined(OS_WIN)
#include "content/common/section_util_win.h"
#endif

// The number of TransportDIBs VideoCaptureController allocate.
static const size_t kNoOfDIBS = 3;

VideoCaptureController::VideoCaptureController(
    ControllerId id,
    base::ProcessHandle render_process,
    EventHandler* event_handler)
    : render_handle_(render_process),
      report_ready_to_delete_(false),
      event_handler_(event_handler),
      id_(id) {}

VideoCaptureController::~VideoCaptureController() {
  // Delete all TransportDIBs.
  STLDeleteContainerPairSecondPointers(owned_dibs_.begin(),
                                       owned_dibs_.end());
}

void VideoCaptureController::StartCapture(
    const media::VideoCaptureParams& params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  params_ = params;
  media_stream::VideoCaptureManager* manager =
      media_stream::VideoCaptureManager::Get();
  // Order the manager to start the actual capture.
  manager->Start(params, this);
}

void VideoCaptureController::StopCapture(Task* stopped_task) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  media_stream::VideoCaptureManager* manager =
      media_stream::VideoCaptureManager::Get();
  manager->Stop(params_.session_id,
                NewRunnableMethod(this,
                                  &VideoCaptureController::OnDeviceStopped,
                                  stopped_task));
}

void VideoCaptureController::ReturnTransportDIB(TransportDIB::Handle handle) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool ready_to_delete;
  {
    base::AutoLock lock(lock_);
    free_dibs_.push_back(handle);
    ready_to_delete = (free_dibs_.size() == owned_dibs_.size());
  }
  if (report_ready_to_delete_ && ready_to_delete) {
    event_handler_->OnReadyToDelete(id_);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Implements VideoCaptureDevice::EventHandler.
// OnIncomingCapturedFrame is called the thread running the capture device.
// I.e.- DirectShow thread on windows and v4l2_thread on Linux.
void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
                                                     int length,
                                                     base::Time timestamp) {
  TransportDIB::Handle handle;
  TransportDIB* dib = NULL;
  // Check if there is a TransportDIB to fill.
  bool buffer_exist = false;
  {
    base::AutoLock lock(lock_);
    if (!report_ready_to_delete_ && free_dibs_.size() > 0) {
      handle = free_dibs_.back();
      free_dibs_.pop_back();
      DIBMap::iterator it = owned_dibs_.find(handle);
      if (it != owned_dibs_.end()) {
        dib = it->second;
        buffer_exist = true;
      }
    }
  }

  if (!buffer_exist) {
    return;
  }

  if (!dib->Map()) {
    VLOG(1) << "OnIncomingCapturedFrame - Failed to map handle.";
    base::AutoLock lock(lock_);
    free_dibs_.push_back(handle);
    return;
  }
  uint8* target = static_cast<uint8*>(dib->memory());
  CHECK(dib->size() >= static_cast<size_t> (frame_info_.width *
                                            frame_info_.height * 3) /
                                            2);

  // Do color conversion from the camera format to I420.
  switch (frame_info_.color) {
    case media::VideoCaptureDevice::kColorUnknown:  // Color format not set.
      break;
    case media::VideoCaptureDevice::kI420: {
      memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2);
      break;
    }
    case media::VideoCaptureDevice::kYUY2: {
      uint8* yplane = target;
      uint8* uplane = target + frame_info_.width * frame_info_.height;
      uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
      media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width,
                              frame_info_.height);
      break;
    }
    case media::VideoCaptureDevice::kRGB24: {
#if defined(OS_WIN)  // RGB on Windows start at the bottom line.
      uint8* yplane = target;
      uint8* uplane = target + frame_info_.width * frame_info_.height;
      uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
      int ystride = frame_info_.width;
      int uvstride = frame_info_.width / 2;
      int rgb_stride = - 3 * frame_info_.width;
      const uint8* rgb_src = data + 3 * frame_info_.width *
          (frame_info_.height -1);
#else
      uint8* yplane = target;
      uint8* uplane = target + frame_info_.width * frame_info_.height;
      uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4;
      int ystride = frame_info_.width;
      int uvstride = frame_info_.width / 2;
      int rgb_stride = 3 * frame_info_.width;
      const uint8* rgb_src = data;
#endif
      media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane,
                               frame_info_.width, frame_info_.height,
                               rgb_stride, ystride, uvstride);
      break;
    }
    case media::VideoCaptureDevice::kARGB: {
      uint8* yplane = target;
      uint8* uplane = target +  frame_info_.width * frame_info_.height;
      uint8* vplane = uplane +  (frame_info_.width * frame_info_.height) / 4;
      media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width,
                               frame_info_.height, frame_info_.width * 4,
                               frame_info_.width, frame_info_.width / 2);
      break;
    }
    default:
      NOTREACHED();
  }

  event_handler_->OnBufferReady(id_, handle, timestamp);
}

void VideoCaptureController::OnError() {
  event_handler_->OnError(id_);
}

void VideoCaptureController::OnFrameInfo(
    const media::VideoCaptureDevice::Capability& info) {
  DCHECK(owned_dibs_.empty());
  bool frames_created = true;
  const size_t needed_size = (info.width * info.height * 3) / 2;
  for (size_t i = 0; i < kNoOfDIBS; ++i) {
    TransportDIB* dib = TransportDIB::Create(needed_size, i);
    if (!dib) {
      frames_created = false;
      break;
    }
    // Lock needed since the buffers are used in OnIncomingFrame
    // and we need to use it there in order to avoid memcpy of complete frames.
    base::AutoLock lock(lock_);
#if defined(OS_WIN)
    // On Windows we need to get a handle the can be used in the render process.
    TransportDIB::Handle handle = chrome::GetSectionForProcess(
        dib->handle(), render_handle_, false);
#else
    TransportDIB::Handle handle = dib->handle();
#endif
    owned_dibs_.insert(std::make_pair(handle, dib));
    free_dibs_.push_back(handle);
  }
  frame_info_= info;

  // Check that all DIBs where created successfully.
  if (!frames_created) {
    event_handler_->OnError(id_);
  }
  event_handler_->OnFrameInfo(id_, info.width, info.height,
                              info.frame_rate);
}

///////////////////////////////////////////////////////////////////////////////
// Called by VideoCaptureManager when a device have been stopped.
// This will report to the event handler that this object is ready to be deleted
// if all DIBS have been returned.
void VideoCaptureController::OnDeviceStopped(Task* stopped_task) {
  bool ready_to_delete_now;

  // Set flag to indicate we need to report when all DIBs have been returned.
  report_ready_to_delete_ = true;
  {
    base::AutoLock lock(lock_);
    ready_to_delete_now = (free_dibs_.size() == owned_dibs_.size());
  }

  if (ready_to_delete_now) {
    event_handler_->OnReadyToDelete(id_);
  }
  if (stopped_task) {
    stopped_task->Run();
    delete stopped_task;
  }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

  =========================================================================*/

#include "otbMachineLearningUtils.h"

#include <fstream>
#include <string>
#include <algorithm>

bool ReadDataFile(const char * infname, InputListSampleType * samples, TargetListSampleType * labels)
{
  std::ifstream ifs;
  ifs.open(infname);

  if(!ifs)
    {
    std::cerr<<"Could not read file "<<infname<<std::endl;
    return false;
    }

  unsigned int nbfeatures = 0;

    while (!ifs.eof())
      {
      std::string line;
      std::getline(ifs, line);

      if(nbfeatures == 0)
        {
        nbfeatures = std::count(line.begin(),line.end(),' ')-1;
        std::cout<<"Found "<<nbfeatures<<" features per samples"<<std::endl;
        }

      if(line.size()>1)
        {

        InputSampleType sample(nbfeatures);
        sample.Fill(0);

        std::string::size_type pos = line.find_first_of(" ", 0);

        // Parse label
        TargetSampleType label;
        label[0] = atoi(line.substr(0, pos).c_str());

        bool endOfLine = false;

        unsigned int id = 0;

        while(!endOfLine)
          {
          std::string::size_type nextpos = line.find_first_of(" ", pos+1);

          if(nextpos == std::string::npos)
            {
            endOfLine = true;
            nextpos = line.size()-1;
            }
          else
            {
            std::string feature = line.substr(pos,nextpos-pos);
            std::string::size_type semicolonpos = feature.find_first_of(":");
            sample[id] = atof(feature.substr(0,semicolonpos).c_str());
            ++id;
            pos = nextpos;
            }
          }
        samples->PushBack(sample);
        labels->PushBack(label);
        }
      }

    std::cout<<"Retrieved "<<samples->Size()<<" samples"<<std::endl;

  ifs.close();

  return true;
}
<commit_msg>Modifying read function to handle most datasets<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

  =========================================================================*/

#include "otbMachineLearningUtils.h"

#include <fstream>
#include <string>
#include <algorithm>

bool ReadDataFile(const char * infname, InputListSampleType * samples, TargetListSampleType * labels)
{
  std::ifstream ifs;
  ifs.open(infname);

  if(!ifs)
    {
    std::cerr<<"Could not read file "<<infname<<std::endl;
    return false;
    }

  unsigned int nbfeatures = 0;

    while (!ifs.eof())
      {
      std::string line;
      std::getline(ifs, line);

      if(nbfeatures == 0)
        {
        nbfeatures = std::count(line.begin(),line.end(),' ')-1;
        std::cout<<"Found "<<nbfeatures<<" features per samples"<<std::endl;
        }

      if(line.size()>1)
        {

        InputSampleType sample(nbfeatures);
        sample.Fill(0);

        std::string::size_type pos = line.find_first_of(" ", 0);

        // Parse label
        TargetSampleType label;
        label[0] = atoi(line.substr(0, pos).c_str());

        bool endOfLine = false;

        unsigned int id = 0;

        while(!endOfLine)
          {
          std::string::size_type nextpos = line.find_first_of(" ", pos+1);

          if(nextpos == std::string::npos)
            {
            endOfLine = true;
            nextpos = line.size()-1;
            }
          else
            {
            std::string feature = line.substr(pos,nextpos-pos);
            std::string::size_type semicolonpos = feature.find_first_of(":");
            id = atoi(feature.substr(0,semicolonpos).c_str());
            sample[id] = atof(feature.substr(semicolonpos+1,feature.size()-semicolonpos).c_str());
            pos = nextpos;
            }
          }
        samples->PushBack(sample);
        labels->PushBack(label);
        }
      }

    std::cout<<"Retrieved "<<samples->Size()<<" samples"<<std::endl;

  ifs.close();

  return true;
}
<|endoftext|>


<commit_before>#ifndef __CLUSTERING_REGISTRAR_HPP__
#define __CLUSTERING_REGISTRAR_HPP__

template<class protocol_t>
struct registrar_t {

    registrar_t(mailbox_cluster_t *cluster);

    registrar_metadata_t<protocol_t> get_business_card() {
    }

private:

};

#endif /* __CLUSTERING_REGISTRAR_HPP__ */
<commit_msg>More work on registrar<commit_after>#ifndef __CLUSTERING_REGISTRAR_HPP__
#define __CLUSTERING_REGISTRAR_HPP__

/* Each master constructs a `registrar_t` which is responsible for keeping track
of the mirrors associated with that branch. */

template<class protocol_t>
class registrar_t {

public:
    /* `registrant_t` represents a mirror that's registered with the branch. */
    class registrant_t {

    public:
        /* To send messages to the mirror, call `write()`, `writeread()`, or
        `read()`. It's illegal to call `writeread()` or `read()` if the mirror
        has not yet upgraded to reads. These operations all block until the
        mirror responds. If contact with the mirror is lost, or the mirror
        deregisters instead of responding, the operation will throw a
        `lost_exc_t`. */

        class lost_exc_t : public std::exception {
            const char *what() const throw () {
                return "registrant went offline before acking operation";
            }
        };

        void write(typename protocol_t::write_t write, repli_timestamp_t timestamp, order_token_t tok, signal_t *interruptor) {

            /* Lock the drain semaphore to avoid weird race conditions if we are
            deregistered mid-operation */
            drain_semaphore_t::lock_t dsem_lock(&drain_semaphore);

            cond_t ack_cond;
            async_mailbox_t<boost::function<void()> > ack_mailbox(
                registrar->cluster, boost::bind(&cond_t::pulse, &ack_cond));

            send(registrar->cluster, write_mailbox,
                write, timestamp, tok, &ack_mailbox);

            cond_t c;
            cond_link_t continue_if_acked(&ack_cond, &c);
            cond_link_t continue_if_interrupted(interruptor, &c);
            cond_link_t continue_if_lost(&lost_cond, &c);
            c.wait_lazily_unordered();

            if (interruptor->is_pulsed()) {
                throw interrupted_exc_t();
            }

            if (lost_cond.is_pulsed()) {
                throw lost_exc_t();
            }
        }

        typename protocol_t::write_response_t writeread(typename protocol_t::write_t write, repli_timestamp_t timestamp, order_token_t tok, signal_t *interruptor) {

            drain_semaphore_t::lock_t dsem_lock(&drain_semaphore);

            promise_t<
        }

        typename protocol_t::read_response_t read(typename protocol_t::read_t read, order_token_t tok, signal_t *interruptor) {
        }

    private:
        registrar_t *registrar;
        registrar_metadata_t<protocol_t>::write_mailbox_t::address_t write_mailbox;
        registrar_metadata_t<protocol_t>::writeread_mailbox_t::address_t writeread_mailbox;
        registrar_metadata_t<protocol_t>::read_mailbox_t::address_t read_mailbox;
        drain_semaphore_t drain_semaphore;
    };

    class callback_t {
    public:
        virtual void on_register(registrant_t *) = 0;
        virtual void on_upgrade_to_reads(registrant_t *) = 0;
        virtual void on_deregister(registrant_t *) = 0;
    };

    registrar_t(mailbox_cluster_t *cluster, callback_t *cb) :
        register_mailbox(cluster, boost::bind(&registrar_t::on_register, _1, _2)),
        upgrade_mailbox(cluster, boost::bind(&registrar_t::on_upgrade, _1, _2, _3)),
        deregister_mailbox(cluster, boost::bind(&registrar_t::on_deregister, _1)),
        callback(cb)
        { }

    registrar_metadata_t<protocol_t> get_business_card() {
        registrar_metadata_t<protocol_t> business_card;
        business_card.register_mailbox = &register_mailbox;
        business_card.upgrade_mailbox = &upgrade_mailbox;
        business_card.deregister_mailbox = &deregister_mailbox;
        return business_card;
    }

private:
    registrar_metadata_t<protocol_t>::register_mailbox_t register_mailbox;
    registrar_metadata_t<protocol_t>::upgrade_mailbox_t upgrade_mailbox;
    registrar_metadata_t<protocol_t>::deregister_mailbox_t deregister_mailbox;

    callback_t *callback;
};

#endif /* __CLUSTERING_REGISTRAR_HPP__ */
<|endoftext|>


<commit_before>/* Copyright (c) 2013 Simeon Bird <spb@ias.edu>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include "absorption.h"
#include <algorithm>
#include <cmath>

/* Physical constants, cgs units */
#define  SIGMA_T 6.652458558e-25 /* Thompson cross-section in cm^2*/
//Note BOLTZMANN is given in cgs units, velocities supplied
//from outside will be here are in km/s
#define  BOLTZMANN  1.3806504e-16  /*  ergs K-1 or cm2 g s-2 K-1 */

#define  LIGHT      2.99792458e10 /*in cm/s*/
// convert energy/unit mass to erg/g
#define  ESCALE 1.0e10
/* Some useful numbers */
#define  GAMMA (5.0/3.0)

/*Conversion factor between internal energy and mu and temperature in K */
#define TSCALE ((GAMMA-1.0) * PROTONMASS * ESCALE / BOLTZMANN)

#define NGRID 8

//Threshold of tau below which we stop computing profiles
#define TAUTAIL 0.001

inline double sph_kernel(const double q)
{
    if (q >= 1)
        return 0;
    if(q<0.5)
        return 1-6*q*q+6*q*q*q;
    else
        return 2*pow(1.- q,3);
}

/* Find the fraction of the total particle density in this pixel by integrating an SPH kernel
 * over the z direction. All distances in units of smoothing length.
 * Arguments:
 * zlow - Lower z limit for the integral (as z distance from particle center).
 * zhigh - Upper z limit for the integral (again as distance from particle center)
 * bb2 - transverse distance from particle to pixel, squared.
 *
 * If K(q) is the SPH kernel normalized such that 4 pi int_{q < 1} K(q) q^2 dq = 1
 * and q^2 = b^2 + z^2, then this is:
 * int_zlow^zhigh K(q) dz
 * */
double sph_kern_frac(double zlow, double zhigh, double bb2)
{
    //Outside useful range.
    if (zlow > sqrt(1-bb2) || zhigh < -sqrt(1-bb2)){
        return 0;
    }
    //Maximal range that will do anything
    zlow = std::max(zlow, -sqrt(1-bb2));
    zhigh = std::min(zhigh, sqrt(1-bb2));
    //return 3./(4*M_PI)*(zhigh - zlow);
    double total = sph_kernel(sqrt(bb2+zlow*zlow))/2.;
    const double deltaz=(zhigh-zlow)/NGRID;
    for(int i=1; i<NGRID; ++i)
    {
        const double zz = i*deltaz+zlow;
        const double q = sqrt(bb2+zz*zz);
        total+=sph_kernel(q);
    }
    double qhigh = sqrt(bb2+zhigh*zhigh);
    total += sph_kernel(qhigh)/2.;
    return 8*deltaz*total/M_PI;
}

/* Compute the Voigt or Gaussian profile.
 * Uses the approximation to the Voigt profile from Tepper-Garcia, 2006, MNRAS, 369, 2025
 * (astro-ph/0602124) eq. 25, somewhat simplified
 * which is accurate to 1% in the worst case, a narrow region between the wings and the core.
 * Arguments:
 * T0 = (vdiff/btherm)**2
 * aa: voigt_fac/btherm
 * (note btherm is sqrt(2k T / M))
 */
inline double profile(const double T0, const double aa)
{
    const double T1 = exp(-T0);
  #ifdef VOIGT
    const double T2 = 1.5/T0;
    const double profile_H1 = (T0 < 1.e-6 ? T1 : T1 - aa/sqrt(M_PI)/T0*(T1*T1*(4.0*T0*T0 + 7.0*T0 + 4.0 + T2) - T2 -1.0));
  #else
    const double profile_H1 = T1;
  #endif
    return profile_H1;
}

class SingleAbsorber
{
    public:

        /*This class evaluates the convolution integral for the optical depth.
         * This is:
         *
         * tau = int_{bin} dv' int_{sph kernel support} dv n(v) Phi(v-v')
         * where n is the local density and Phi is the broadening function.
         *
         * Arguments:
         * btherm: thermal b parameter: sqrt(2kT/m)
         * vel: velocity of particle parallel to sightline
         * vdr2: impact parameter from particle center to sightline in velocity units (km/s)
         * vsmooth: smoothing length in velocity units (km/s)
         * aa: voigt_fac/btherm the parameter for the Voight profile
         */
        SingleAbsorber(double bth_i, double vdr2_i, double vsm_i, double aa_i):
            btherm(bth_i), vdr2(vdr2_i), vsmooth(vsm_i), aa(aa_i)
        {};

        /*Evaluate the outer integral in the convolution which gives us the optical depth.
         * This is:
         *
         * tau = int_{bin} dv' tau_kern_inner(v)
         * Arguments:
         * vlow, vhigh: integration limits, which should be v_bin - v_particle
         */
        double tau_kern_outer(const double vlow, const double vhigh)
        {
            double total = tau_kern_inner(vlow)/2.;
            const double deltav=(vhigh-vlow)/NGRID;
            for(int i=1; i<NGRID; ++i)
            {
                const double vv = i*deltav+vlow;
                total += tau_kern_inner(vv);
            }
            total += tau_kern_inner(vhigh)/2.;
            return deltav*total;
        }

    private:
        /*Evaluate the inner integral in the convolution which gives us the optical depth.
         * This is:
         *
         * tau = int_{bin} dv' int_{sph kernel support} dv n(v) Phi(v-v')
         * where n is the local density and Phi is the broadening function.
         *
         * This does the inner function: int{sph kernel support} dv n(v) Phi(v-v')
         * (Strictly speaking internally we use v'' = v - v_part and v''' = v' - v_part)
         * Arguments:
         * vdr2: impact parameter from particle center to sightline in velocity units (km/s)
         * vouter: velocity value for the outer integral. This should be v_bin - v_particle.
         * btherm: thermal b parameter: sqrt(2kT/m)
         * vsmooth: smoothing length in velocity units (km/s)
         */
        inline double tau_kern_inner(const double vouter)
        {
            //Compute SPH kernel support region
            const double vhigh = sqrt(vsmooth*vsmooth-vdr2);
            //Integration region goes from -vhigh to vhigh
            const double deltav=2.*vhigh/NGRID;
            //Because we are integrating over the whole sph kernel,
            //the first and last terms will have q = 1, sph_kernel = 0, so don't need to compute them.
            double total = 0;
            for(int i=1; i<NGRID; ++i)
            {
                const double vv = i*deltav-vhigh;
                const double q = sqrt(vdr2+vv*vv)/vsmooth;
                //The difference between this velocity bin and the particle velocity
                const double vdiff = vv - vouter;
                const double T0 = pow(vdiff/btherm,2);
                total+=sph_kernel(q)*profile(T0,aa);
            }
            return 8*deltav*total/M_PI;
        }

        const double btherm;
        const double vdr2;
        const double vsmooth;
        const double aa;
};

//Factor of 1e5 in bfac converts from cm/s to km/s
LineAbsorption::LineAbsorption(const double lambda, const double gamma, const double fosc, const double amumass, const double velfac_i, const double boxsize, const double atime_i):
sigma_a( sqrt(3.0*M_PI*SIGMA_T/8.0) * lambda  * fosc ),
bfac( sqrt(2.0*BOLTZMANN/(amumass*PROTONMASS))/1e5 ),
voigt_fac( gamma*lambda/(4.*M_PI) ),
velfac(velfac_i), vbox(boxsize*velfac_i), atime(atime_i)
{
}

/* Add the absorption from a particle to the spectrum in the array
 * tau, and the density from the particle to the array colden
 * The slightly C-style interface is so we can easily use the data in python
 */
void LineAbsorption::add_particle(double * tau, double * colden, const int nbins, const double dr2, const float dens, const float ppos, const float pvel, const float temp, const float smooth)
{
  /*Factor to convert the dimensionless quantity found by sph_kern_frac to a column density,
   * in [dens units] * [h units] (atoms/cm^3 * kpc/h comov if from python,
   * (1e10 M_sun /h) / (kpc/h)^2 if from C).
   * The factor of h is because we compute int_z ρ dz, using dimensionless units for z, s.t. χ = z/h,
   */
  const double avgdens = dens * smooth;
  /*Impact parameter in units of the smoothing length */
  const double bb2 = dr2/smooth/smooth;
  const double vsmooth = velfac * smooth;
  /* Velocity of particle parallel to los: pos in kpc/h comoving
     to vel in km/s physical. Note that gadget velocities come comoving,
     so we need the sqrt(a) conversion factor.
     Finally divide by h * velfac to give the velocity in units of the smoothing length.*/
  const double vel = (velfac * ppos + pvel * sqrt(atime))/vsmooth;
  //Allowed z range in units of smoothing length
  const double zrange = sqrt(1. - bb2);
  //Conversion between units of the smoothing length to units of the box.
  const double boxtosm = vbox / vsmooth / nbins;
  // z is position in units of the box
  const int zlow = floor((vel - zrange) / boxtosm);
  const int zhigh = ceil((vel + zrange) / boxtosm);
  // Compute the column density
  for(int z=zlow; z<=zhigh; z++)
  {
      /*Difference between velocity of bin this edge and particle in units of the smoothing length*/
      const double vlow = (boxtosm*z - vel);
      const double vhigh = (boxtosm*(z+1) - vel);

      //colden in units of [den units]*[h units] * integral in terms of z / h
      const double colden_this = avgdens*sph_kern_frac(vlow, vhigh, bb2);

      // The index may be periodic wrapped.
      // Index in units of the box
      int j = z % nbins;
      if (j < 0)
        j+=nbins;
      colden[j] += colden_this;
  }
  //Finish now if not computing absorption
  if (!tau) {
      return;
  }

  /* btherm has the units of velocity: km/s*/
  const double btherm = bfac*sqrt(temp);
  // Create absorption object
  SingleAbsorber absorber ( btherm, velfac*velfac*dr2, vsmooth, voigt_fac/btherm );
  // Do the tau integral for each bin
  const double bintov = vbox/nbins;
  // Amplitude factor for the strength of the transition.
  // sqrt(pi)*c / btherm comes from the profile.
  const double amp = sigma_a / sqrt(M_PI) * (LIGHT/btherm);
  //Bin nearest the particle
  const int zmax = floor(vel/bintov);
  //Go from nearest the particle to half a box away.
  //After that we certainly want to stop as we will have wrapped around.
  //This means that damping wings which span a whole box will be cut off at the edges.
  for(int z=zmax; z<zmax+nbins/2; ++z)
  {
      double vlow = z*bintov - vel;
      const double taulast=amp*absorber.tau_kern_outer(vlow, vlow+bintov);
      tau[z % nbins ]+=taulast;
      //Absorption will only decrease as you go further from the particle.
      if(taulast < TAUTAIL)
        break;
  }
  //Go from the particle backwards
  for(int z=zmax-1; z>zmax-nbins/2; --z)
  {
      double vlow = z*bintov - vel;
      const double taulast=amp*absorber.tau_kern_outer(vlow, vlow+bintov);
      tau[(z + nbins) % nbins ]+=taulast;
      //Absorption will only decrease as you go further from the particle.
      if(taulast < TAUTAIL)
        break;
  }

  return;
}

/* Compute temperature (in K) from internal energy.
 * uu: internal energy in Gadget units
 * ne: electron abundance
 * xh: hydrogen mass fraction (0.76)
 * Factor to convert U (J/kg) to T (K) : U = N k T / (γ - 1)
 * T = U (γ-1) μ m_P / k_B
 * where k_B is the Boltzmann constant
 * γ is 5/3, the perfect gas constant
 * m_P is the proton mass
 * μ is 1 / (mean no. molecules per unit atomic weight) calculated in loop.
 */
double compute_temp(const double uu, const double ne, const double xh)
{
    /*Mean molecular weight:
     * \mu = 1 / molecules per unit atomic weight
     *     = 1 / (X + Y /4 + E)
     *     where E = Ne * X, and Y = (1-X).
     *     Can neglect metals as they are heavy.
     *     Leading contribution is from electrons, which is already included
     *     [+ Z / (12->16)] from metal species
     *     [+ Z/16*4 ] for OIV from electrons. */
    const double mu = 1.0/(xh*(0.75+ne) + 0.25);
    return uu*mu * TSCALE; /* T in K */
}
<commit_msg>Fix segfault by wrapping the indices properly.<commit_after>/* Copyright (c) 2013 Simeon Bird <spb@ias.edu>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include "absorption.h"
#include <algorithm>
#include <cmath>

/* Physical constants, cgs units */
#define  SIGMA_T 6.652458558e-25 /* Thompson cross-section in cm^2*/
//Note BOLTZMANN is given in cgs units, velocities supplied
//from outside will be here are in km/s
#define  BOLTZMANN  1.3806504e-16  /*  ergs K-1 or cm2 g s-2 K-1 */

#define  LIGHT      2.99792458e10 /*in cm/s*/
// convert energy/unit mass to erg/g
#define  ESCALE 1.0e10
/* Some useful numbers */
#define  GAMMA (5.0/3.0)

/*Conversion factor between internal energy and mu and temperature in K */
#define TSCALE ((GAMMA-1.0) * PROTONMASS * ESCALE / BOLTZMANN)

#define NGRID 8

//Threshold of tau below which we stop computing profiles
#define TAUTAIL 0.001

inline double sph_kernel(const double q)
{
    if (q >= 1)
        return 0;
    if(q<0.5)
        return 1-6*q*q+6*q*q*q;
    else
        return 2*pow(1.- q,3);
}

/* Find the fraction of the total particle density in this pixel by integrating an SPH kernel
 * over the z direction. All distances in units of smoothing length.
 * Arguments:
 * zlow - Lower z limit for the integral (as z distance from particle center).
 * zhigh - Upper z limit for the integral (again as distance from particle center)
 * bb2 - transverse distance from particle to pixel, squared.
 *
 * If K(q) is the SPH kernel normalized such that 4 pi int_{q < 1} K(q) q^2 dq = 1
 * and q^2 = b^2 + z^2, then this is:
 * int_zlow^zhigh K(q) dz
 * */
double sph_kern_frac(double zlow, double zhigh, double bb2)
{
    //Outside useful range.
    if (zlow > sqrt(1-bb2) || zhigh < -sqrt(1-bb2)){
        return 0;
    }
    //Maximal range that will do anything
    zlow = std::max(zlow, -sqrt(1-bb2));
    zhigh = std::min(zhigh, sqrt(1-bb2));
    //return 3./(4*M_PI)*(zhigh - zlow);
    double total = sph_kernel(sqrt(bb2+zlow*zlow))/2.;
    const double deltaz=(zhigh-zlow)/NGRID;
    for(int i=1; i<NGRID; ++i)
    {
        const double zz = i*deltaz+zlow;
        const double q = sqrt(bb2+zz*zz);
        total+=sph_kernel(q);
    }
    double qhigh = sqrt(bb2+zhigh*zhigh);
    total += sph_kernel(qhigh)/2.;
    return 8*deltaz*total/M_PI;
}

/* Compute the Voigt or Gaussian profile.
 * Uses the approximation to the Voigt profile from Tepper-Garcia, 2006, MNRAS, 369, 2025
 * (astro-ph/0602124) eq. 25, somewhat simplified
 * which is accurate to 1% in the worst case, a narrow region between the wings and the core.
 * Arguments:
 * T0 = (vdiff/btherm)**2
 * aa: voigt_fac/btherm
 * (note btherm is sqrt(2k T / M))
 */
inline double profile(const double T0, const double aa)
{
    const double T1 = exp(-T0);
  #ifdef VOIGT
    const double T2 = 1.5/T0;
    const double profile_H1 = (T0 < 1.e-6 ? T1 : T1 - aa/sqrt(M_PI)/T0*(T1*T1*(4.0*T0*T0 + 7.0*T0 + 4.0 + T2) - T2 -1.0));
  #else
    const double profile_H1 = T1;
  #endif
    return profile_H1;
}

class SingleAbsorber
{
    public:

        /*This class evaluates the convolution integral for the optical depth.
         * This is:
         *
         * tau = int_{bin} dv' int_{sph kernel support} dv n(v) Phi(v-v')
         * where n is the local density and Phi is the broadening function.
         *
         * Arguments:
         * btherm: thermal b parameter: sqrt(2kT/m)
         * vel: velocity of particle parallel to sightline
         * vdr2: impact parameter from particle center to sightline in velocity units (km/s)
         * vsmooth: smoothing length in velocity units (km/s)
         * aa: voigt_fac/btherm the parameter for the Voight profile
         */
        SingleAbsorber(double bth_i, double vdr2_i, double vsm_i, double aa_i):
            btherm(bth_i), vdr2(vdr2_i), vsmooth(vsm_i), aa(aa_i)
        {};

        /*Evaluate the outer integral in the convolution which gives us the optical depth.
         * This is:
         *
         * tau = int_{bin} dv' tau_kern_inner(v)
         * Arguments:
         * vlow, vhigh: integration limits, which should be v_bin - v_particle
         */
        double tau_kern_outer(const double vlow, const double vhigh)
        {
            double total = tau_kern_inner(vlow)/2.;
            const double deltav=(vhigh-vlow)/NGRID;
            for(int i=1; i<NGRID; ++i)
            {
                const double vv = i*deltav+vlow;
                total += tau_kern_inner(vv);
            }
            total += tau_kern_inner(vhigh)/2.;
            return deltav*total;
        }

    private:
        /*Evaluate the inner integral in the convolution which gives us the optical depth.
         * This is:
         *
         * tau = int_{bin} dv' int_{sph kernel support} dv n(v) Phi(v-v')
         * where n is the local density and Phi is the broadening function.
         *
         * This does the inner function: int{sph kernel support} dv n(v) Phi(v-v')
         * (Strictly speaking internally we use v'' = v - v_part and v''' = v' - v_part)
         * Arguments:
         * vdr2: impact parameter from particle center to sightline in velocity units (km/s)
         * vouter: velocity value for the outer integral. This should be v_bin - v_particle.
         * btherm: thermal b parameter: sqrt(2kT/m)
         * vsmooth: smoothing length in velocity units (km/s)
         */
        inline double tau_kern_inner(const double vouter)
        {
            //Compute SPH kernel support region
            const double vhigh = sqrt(vsmooth*vsmooth-vdr2);
            //Integration region goes from -vhigh to vhigh
            const double deltav=2.*vhigh/NGRID;
            //Because we are integrating over the whole sph kernel,
            //the first and last terms will have q = 1, sph_kernel = 0, so don't need to compute them.
            double total = 0;
            for(int i=1; i<NGRID; ++i)
            {
                const double vv = i*deltav-vhigh;
                const double q = sqrt(vdr2+vv*vv)/vsmooth;
                //The difference between this velocity bin and the particle velocity
                const double vdiff = vv - vouter;
                const double T0 = pow(vdiff/btherm,2);
                total+=sph_kernel(q)*profile(T0,aa);
            }
            return 8*deltav*total/M_PI;
        }

        const double btherm;
        const double vdr2;
        const double vsmooth;
        const double aa;
};

//Factor of 1e5 in bfac converts from cm/s to km/s
LineAbsorption::LineAbsorption(const double lambda, const double gamma, const double fosc, const double amumass, const double velfac_i, const double boxsize, const double atime_i):
sigma_a( sqrt(3.0*M_PI*SIGMA_T/8.0) * lambda  * fosc ),
bfac( sqrt(2.0*BOLTZMANN/(amumass*PROTONMASS))/1e5 ),
voigt_fac( gamma*lambda/(4.*M_PI) ),
velfac(velfac_i), vbox(boxsize*velfac_i), atime(atime_i)
{
}

/* Add the absorption from a particle to the spectrum in the array
 * tau, and the density from the particle to the array colden
 * The slightly C-style interface is so we can easily use the data in python
 */
void LineAbsorption::add_particle(double * tau, double * colden, const int nbins, const double dr2, const float dens, const float ppos, const float pvel, const float temp, const float smooth)
{
  /*Factor to convert the dimensionless quantity found by sph_kern_frac to a column density,
   * in [dens units] * [h units] (atoms/cm^3 * kpc/h comov if from python,
   * (1e10 M_sun /h) / (kpc/h)^2 if from C).
   * The factor of h is because we compute int_z ρ dz, using dimensionless units for z, s.t. χ = z/h,
   */
  const double avgdens = dens * smooth;
  /*Impact parameter in units of the smoothing length */
  const double bb2 = dr2/smooth/smooth;
  const double vsmooth = velfac * smooth;
  /* Velocity of particle parallel to los: pos in kpc/h comoving
     to vel in km/s physical. Note that gadget velocities come comoving,
     so we need the sqrt(a) conversion factor.
     Finally divide by h * velfac to give the velocity in units of the smoothing length.*/
  const double vel = (velfac * ppos + pvel * sqrt(atime))/vsmooth;
  //Allowed z range in units of smoothing length
  const double zrange = sqrt(1. - bb2);
  //Conversion between units of the smoothing length to units of the box.
  const double boxtosm = vbox / vsmooth / nbins;
  // z is position in units of the box
  const int zlow = floor((vel - zrange) / boxtosm);
  const int zhigh = ceil((vel + zrange) / boxtosm);
  // Compute the column density
  for(int z=zlow; z<=zhigh; z++)
  {
      /*Difference between velocity of bin this edge and particle in units of the smoothing length*/
      const double vlow = (boxtosm*z - vel);
      const double vhigh = (boxtosm*(z+1) - vel);

      //colden in units of [den units]*[h units] * integral in terms of z / h
      const double colden_this = avgdens*sph_kern_frac(vlow, vhigh, bb2);

      // The index may be periodic wrapped.
      // Index in units of the box
      int j = z % nbins;
      if (j<0)
        j+=nbins;
      colden[j] += colden_this;
  }
  //Finish now if not computing absorption
  if (!tau) {
      return;
  }

  /* btherm has the units of velocity: km/s*/
  const double btherm = bfac*sqrt(temp);
  // Create absorption object
  SingleAbsorber absorber ( btherm, velfac*velfac*dr2, vsmooth, voigt_fac/btherm );
  // Do the tau integral for each bin
  const double bintov = vbox/nbins;
  // Amplitude factor for the strength of the transition.
  // sqrt(pi)*c / btherm comes from the profile.
  const double amp = sigma_a / sqrt(M_PI) * (LIGHT/btherm);
  //Bin nearest the particle
  const int zmax = floor(vel/bintov);
  //Go from nearest the particle to half a box away.
  //After that we certainly want to stop as we will have wrapped around.
  //This means that damping wings which span a whole box will be cut off at the edges.
  for(int z=zmax; z<zmax+nbins/2; ++z)
  {
      double vlow = z*bintov - vel;
      const double taulast=amp*absorber.tau_kern_outer(vlow, vlow+bintov);
      // Make sure index is properly wrapped
      int j = z % nbins;
      if (j<0)
        j+=nbins;
      tau[j]+=taulast;
      //Absorption will only decrease as you go further from the particle.
      if(taulast < TAUTAIL)
        break;
  }
  //Go from the particle backwards
  for(int z=zmax-1; z>zmax-nbins/2; --z)
  {
      double vlow = z*bintov - vel;
      const double taulast=amp*absorber.tau_kern_outer(vlow, vlow+bintov);
      // Make sure index is properly wrapped
      int j = z % nbins;
      if (j<0)
        j+=nbins;
      tau[j]+=taulast;
      //Absorption will only decrease as you go further from the particle.
      if(taulast < TAUTAIL)
        break;
  }

  return;
}

/* Compute temperature (in K) from internal energy.
 * uu: internal energy in Gadget units
 * ne: electron abundance
 * xh: hydrogen mass fraction (0.76)
 * Factor to convert U (J/kg) to T (K) : U = N k T / (γ - 1)
 * T = U (γ-1) μ m_P / k_B
 * where k_B is the Boltzmann constant
 * γ is 5/3, the perfect gas constant
 * m_P is the proton mass
 * μ is 1 / (mean no. molecules per unit atomic weight) calculated in loop.
 */
double compute_temp(const double uu, const double ne, const double xh)
{
    /*Mean molecular weight:
     * \mu = 1 / molecules per unit atomic weight
     *     = 1 / (X + Y /4 + E)
     *     where E = Ne * X, and Y = (1-X).
     *     Can neglect metals as they are heavy.
     *     Leading contribution is from electrons, which is already included
     *     [+ Z / (12->16)] from metal species
     *     [+ Z/16*4 ] for OIV from electrons. */
    const double mu = 1.0/(xh*(0.75+ne) + 0.25);
    return uu*mu * TSCALE; /* T in K */
}
<|endoftext|>


<commit_before>/*
* Derived from poly1305-donna-64.h by Andrew Moon <liquidsun@gmail.com>
* in https://github.com/floodyberry/poly1305-donna
*
* (C) 2014 Andrew Moon
* (C) 2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/poly1305.h>
#include <botan/loadstor.h>
#include <botan/mul128.h>
#include <botan/internal/donna128.h>

namespace Botan {

namespace {

void poly1305_init(secure_vector<uint64_t>& X, const uint8_t key[32])
   {
   /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
   const uint64_t t0 = load_le<uint64_t>(key, 0);
   const uint64_t t1 = load_le<uint64_t>(key, 1);

   X[0] = ( t0                    ) & 0xffc0fffffff;
   X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
   X[2] = ((t1 >> 24)             ) & 0x00ffffffc0f;

   /* h = 0 */
   X[3] = 0;
   X[4] = 0;
   X[5] = 0;

   /* save pad for later */
   X[6] = load_le<uint64_t>(key, 2);
   X[7] = load_le<uint64_t>(key, 3);
   }

void poly1305_blocks(secure_vector<uint64_t>& X, const uint8_t *m, size_t blocks, bool is_final = false)
   {
#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
   typedef donna128 uint128_t;
#endif

   const uint64_t hibit = is_final ? 0 : (static_cast<uint64_t>(1) << 40); /* 1 << 128 */

   const uint64_t r0 = X[0];
   const uint64_t r1 = X[1];
   const uint64_t r2 = X[2];

   const uint64_t M44 = 0xfffffffffff;
   const uint64_t M42 = 0x3ffffffffff;

   uint64_t h0 = X[3+0];
   uint64_t h1 = X[3+1];
   uint64_t h2 = X[3+2];

   const uint64_t s1 = r1 * (5 << 2);
   const uint64_t s2 = r2 * (5 << 2);

   for(size_t i = 0; i != blocks; ++i)
      {
      const uint64_t t0 = load_le<uint64_t>(m, 0);
      const uint64_t t1 = load_le<uint64_t>(m, 1);

      h0 += (( t0                    ) & M44);
      h1 += (((t0 >> 44) | (t1 << 20)) & M44);
      h2 += (((t1 >> 24)             ) & M42) | hibit;

      const uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
      const uint64_t c0 = carry_shift(d0, 44);

      const uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2 + c0;
      const uint64_t c1 = carry_shift(d1, 44);

      const uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0 + c1;
      const uint64_t c2 = carry_shift(d2, 42);

      h0 = d0 & M44;
      h1 = d1 & M44;
      h2 = d2 & M42;

      h0 += c2 * 5;
      h1 += carry_shift(h0, 44);
      h0 = h0 & M44;

      m += 16;
      }

   X[3+0] = h0;
   X[3+1] = h1;
   X[3+2] = h2;
   }

void poly1305_finish(secure_vector<uint64_t>& X, uint8_t mac[16])
   {
   /* fully carry h */
   uint64_t h0 = X[3+0];
   uint64_t h1 = X[3+1];
   uint64_t h2 = X[3+2];

   uint64_t c;
                c = (h1 >> 44); h1 &= 0xfffffffffff;
   h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
   h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
   h1 += c;     c = (h1 >> 44); h1 &= 0xfffffffffff;
   h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
   h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
   h1 += c;

   /* compute h + -p */
   uint64_t g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
   uint64_t g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
   uint64_t g2 = h2 + c - (static_cast<uint64_t>(1) << 42);

   /* select h if h < p, or h + -p if h >= p */
   c = (g2 >> ((sizeof(uint64_t) * 8) - 1)) - 1;
   g0 &= c;
   g1 &= c;
   g2 &= c;
   c = ~c;
   h0 = (h0 & c) | g0;
   h1 = (h1 & c) | g1;
   h2 = (h2 & c) | g2;

   /* h = (h + pad) */
   const uint64_t t0 = X[6];
   const uint64_t t1 = X[7];

   h0 += (( t0                    ) & 0xfffffffffff)    ; c = (h0 >> 44); h0 &= 0xfffffffffff;
   h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff;
   h2 += (((t1 >> 24)             ) & 0x3ffffffffff) + c;                 h2 &= 0x3ffffffffff;

   /* mac = h % (2^128) */
   h0 = ((h0      ) | (h1 << 44));
   h1 = ((h1 >> 20) | (h2 << 24));

   store_le(mac, h0, h1);

   /* zero out the state */
   clear_mem(X.data(), X.size());
   }

}

void Poly1305::clear()
   {
   zap(m_poly);
   zap(m_buf);
   m_buf_pos = 0;
   }

void Poly1305::key_schedule(const uint8_t key[], size_t)
   {
   m_buf_pos = 0;
   m_buf.resize(16);
   m_poly.resize(8);

   poly1305_init(m_poly, key);
   }

void Poly1305::add_data(const uint8_t input[], size_t length)
   {
   verify_key_set(m_poly.size() == 8);

   if(m_buf_pos)
      {
      buffer_insert(m_buf, m_buf_pos, input, length);

      if(m_buf_pos + length >= m_buf.size())
         {
         poly1305_blocks(m_poly, m_buf.data(), 1);
         input += (m_buf.size() - m_buf_pos);
         length -= (m_buf.size() - m_buf_pos);
         m_buf_pos = 0;
         }
      }

   const size_t full_blocks = length / m_buf.size();
   const size_t remaining   = length % m_buf.size();

   if(full_blocks)
      poly1305_blocks(m_poly, input, full_blocks);

   buffer_insert(m_buf, m_buf_pos, input + full_blocks * m_buf.size(), remaining);
   m_buf_pos += remaining;
   }

void Poly1305::final_result(uint8_t out[])
   {
   verify_key_set(m_poly.size() == 8);

   if(m_buf_pos != 0)
      {
      m_buf[m_buf_pos] = 1;
      const size_t len = m_buf.size() - m_buf_pos - 1;
      if (len > 0)
         {
         clear_mem(&m_buf[m_buf_pos+1], len);
         }
      poly1305_blocks(m_poly, m_buf.data(), 1, true);
      }

   poly1305_finish(m_poly, out);

   m_poly.clear();
   m_buf_pos = 0;
   }

}
<commit_msg>Cleanups in Poly1305<commit_after>/*
* Derived from poly1305-donna-64.h by Andrew Moon <liquidsun@gmail.com>
* in https://github.com/floodyberry/poly1305-donna
*
* (C) 2014 Andrew Moon
* (C) 2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/poly1305.h>
#include <botan/loadstor.h>
#include <botan/mul128.h>
#include <botan/internal/donna128.h>
#include <botan/internal/ct_utils.h>

namespace Botan {

namespace {

void poly1305_init(secure_vector<uint64_t>& X, const uint8_t key[32])
   {
   /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
   const uint64_t t0 = load_le<uint64_t>(key, 0);
   const uint64_t t1 = load_le<uint64_t>(key, 1);

   X[0] = ( t0                    ) & 0xffc0fffffff;
   X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
   X[2] = ((t1 >> 24)             ) & 0x00ffffffc0f;

   /* h = 0 */
   X[3] = 0;
   X[4] = 0;
   X[5] = 0;

   /* save pad for later */
   X[6] = load_le<uint64_t>(key, 2);
   X[7] = load_le<uint64_t>(key, 3);
   }

void poly1305_blocks(secure_vector<uint64_t>& X, const uint8_t *m, size_t blocks, bool is_final = false)
   {
#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
   typedef donna128 uint128_t;
#endif

   const uint64_t hibit = is_final ? 0 : (static_cast<uint64_t>(1) << 40); /* 1 << 128 */

   const uint64_t r0 = X[0];
   const uint64_t r1 = X[1];
   const uint64_t r2 = X[2];

   const uint64_t M44 = 0xFFFFFFFFFFF;
   const uint64_t M42 = 0x3FFFFFFFFFF;

   uint64_t h0 = X[3+0];
   uint64_t h1 = X[3+1];
   uint64_t h2 = X[3+2];

   const uint64_t s1 = r1 * 20;
   const uint64_t s2 = r2 * 20;

   for(size_t i = 0; i != blocks; ++i)
      {
      const uint64_t t0 = load_le<uint64_t>(m, 0);
      const uint64_t t1 = load_le<uint64_t>(m, 1);

      h0 += (( t0                    ) & M44);
      h1 += (((t0 >> 44) | (t1 << 20)) & M44);
      h2 += (((t1 >> 24)             ) & M42) | hibit;

      const uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
      const uint64_t c0 = carry_shift(d0, 44);

      const uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2 + c0;
      const uint64_t c1 = carry_shift(d1, 44);

      const uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0 + c1;
      const uint64_t c2 = carry_shift(d2, 42);

      h0 = d0 & M44;
      h1 = d1 & M44;
      h2 = d2 & M42;

      h0 += c2 * 5;
      h1 += carry_shift(h0, 44);
      h0 = h0 & M44;

      m += 16;
      }

   X[3+0] = h0;
   X[3+1] = h1;
   X[3+2] = h2;
   }

void poly1305_finish(secure_vector<uint64_t>& X, uint8_t mac[16])
   {
   const uint64_t M44 = 0xFFFFFFFFFFF;
   const uint64_t M42 = 0x3FFFFFFFFFF;

   /* fully carry h */
   uint64_t h0 = X[3+0];
   uint64_t h1 = X[3+1];
   uint64_t h2 = X[3+2];

   uint64_t c;
                c = (h1 >> 44); h1 &= M44;
   h2 += c;     c = (h2 >> 42); h2 &= M42;
   h0 += c * 5; c = (h0 >> 44); h0 &= M44;
   h1 += c;     c = (h1 >> 44); h1 &= M44;
   h2 += c;     c = (h2 >> 42); h2 &= M42;
   h0 += c * 5; c = (h0 >> 44); h0 &= M44;
   h1 += c;

   /* compute h + -p */
   uint64_t g0 = h0 + 5; c = (g0 >> 44); g0 &= M44;
   uint64_t g1 = h1 + c; c = (g1 >> 44); g1 &= M44;
   uint64_t g2 = h2 + c - (static_cast<uint64_t>(1) << 42);

   /* select h if h < p, or h + -p if h >= p */
   c = CT::expand_mask<uint64_t>(c);
   h0 = CT::select(c, g0, h0);
   h1 = CT::select(c, g1, h1);
   h2 = CT::select(c, g2, h2);

   /* h = (h + pad) */
   const uint64_t t0 = X[6];
   const uint64_t t1 = X[7];

   h0 += (( t0                    ) & M44)    ; c = (h0 >> 44); h0 &= M44;
   h1 += (((t0 >> 44) | (t1 << 20)) & M44) + c; c = (h1 >> 44); h1 &= M44;
   h2 += (((t1 >> 24)             ) & M42) + c;                 h2 &= M42;

   /* mac = h % (2^128) */
   h0 = ((h0      ) | (h1 << 44));
   h1 = ((h1 >> 20) | (h2 << 24));

   store_le(mac, h0, h1);

   /* zero out the state */
   clear_mem(X.data(), X.size());
   }

}

void Poly1305::clear()
   {
   zap(m_poly);
   zap(m_buf);
   m_buf_pos = 0;
   }

void Poly1305::key_schedule(const uint8_t key[], size_t)
   {
   m_buf_pos = 0;
   m_buf.resize(16);
   m_poly.resize(8);

   poly1305_init(m_poly, key);
   }

void Poly1305::add_data(const uint8_t input[], size_t length)
   {
   verify_key_set(m_poly.size() == 8);

   if(m_buf_pos)
      {
      buffer_insert(m_buf, m_buf_pos, input, length);

      if(m_buf_pos + length >= m_buf.size())
         {
         poly1305_blocks(m_poly, m_buf.data(), 1);
         input += (m_buf.size() - m_buf_pos);
         length -= (m_buf.size() - m_buf_pos);
         m_buf_pos = 0;
         }
      }

   const size_t full_blocks = length / m_buf.size();
   const size_t remaining   = length % m_buf.size();

   if(full_blocks)
      poly1305_blocks(m_poly, input, full_blocks);

   buffer_insert(m_buf, m_buf_pos, input + full_blocks * m_buf.size(), remaining);
   m_buf_pos += remaining;
   }

void Poly1305::final_result(uint8_t out[])
   {
   verify_key_set(m_poly.size() == 8);

   if(m_buf_pos != 0)
      {
      m_buf[m_buf_pos] = 1;
      const size_t len = m_buf.size() - m_buf_pos - 1;
      if (len > 0)
         {
         clear_mem(&m_buf[m_buf_pos+1], len);
         }
      poly1305_blocks(m_poly, m_buf.data(), 1, true);
      }

   poly1305_finish(m_poly, out);

   m_poly.clear();
   m_buf_pos = 0;
   }

}
<|endoftext|>


<commit_before>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker 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 Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* fermin at tid dot es
*
* Author: developer
*/
#include <string>
#include <vector>

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"
#include "ConnectionInfo.h"
#include "clientSocketHttp.h"
#include "serviceRoutines/versionTreat.h"
#include <iostream>

#include <sys/types.h>                          // system types ...
#include <sys/socket.h>                         // socket, bind, listen
#include <sys/un.h>                             // sockaddr_un
#include <netinet/in.h>                         // struct sockaddr_in
#include <netdb.h>                              // gethostbyname
#include <arpa/inet.h>                          // inet_ntoa
#include <netinet/tcp.h>                        // TCP_NODELAY
#include <string>
#include <unistd.h>                             // close()

/* ****************************************************************************
*
* socketHttpConnect -
*/
int socketHttpConnect(std::string host, unsigned short port)
{
  int                 fd;
  struct hostent*     hp;
  struct sockaddr_in  peer;

  if ((hp = gethostbyname(host.c_str())) == NULL)
     LM_RE(-1, ("gethostbyname('%s'): %s", host.c_str(), strerror(errno)));

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
     LM_RE(-1, ("socket: %s", strerror(errno)));

  memset((char*) &peer, 0, sizeof(peer));

  peer.sin_family      = AF_INET;
  peer.sin_addr.s_addr = ((struct in_addr*) (hp->h_addr))->s_addr;
  peer.sin_port        = htons(port);

  if (connect(fd, (struct sockaddr*) &peer, sizeof(peer)) == -1)
  {
    close(fd);
    LM_E(("connect(%s, %d): %s", host.c_str(), port, strerror(errno)));
    return -1;
  }

  return fd;
}

/* ****************************************************************************
*
* sendHttpSocket -
*
* The waitForResponse arguments specifies if the method has to wait for response
* before return. If this argument is false, the return string is ""
*
* FIXME: I don't like too much "reusing" natural output to return "error" in the
* case of error. I think it would be smarter to use "std::string* error" in the
* arguments or (even better) and exception. To be solved in the future in a hardening
* period.
*
* Note, we are using an hybrid approach, consisting in an static thread-local buffer of
* small size that cope with the most of notifications to avoid expensive
* calloc/free syscalls if the notification payload is not very large.
*
*/
std::string sendHttpSocket
(
   std::string     ip,
   unsigned short  port,
   std::string     verb,
   std::string     resource,
   std::string     content_type,
   std::string     content,
   bool            waitForResponse
)
{
  char         buffer[TAM_BUF];
  char         response[TAM_BUF];
  char         preContent[TAM_BUF];
  char         msgStatic[MAX_STA_MSG_SIZE];

  std::string  result;
  char*        msgDynamic = NULL;
  char*        msg = msgStatic;   // by default, use the static buffer

  // Buffers clear
  memset(buffer, 0, TAM_BUF);
  memset(response, 0, TAM_BUF);
  memset(preContent, 0, TAM_BUF);
  memset(msg, 0, MAX_STA_MSG_SIZE);

  if (port == 0)        LM_RE("error", ("port is ZERO"));
  if (ip.empty())       LM_RE("error", ("ip is empty"));
  if (verb.empty())     LM_RE("error", ("verb is empty"));
  if (resource.empty()) LM_RE("error", ("resource is empty"));
  if ((content_type.empty()) && (!content.empty())) LM_RE("error", ("Content-Type is empty but there is actual content"));
  if ((!content_type.empty()) && (content.empty())) LM_RE("error", ("there is actual content but Content-Type is empty"));

  snprintf(preContent, sizeof(preContent),
           "%s %s HTTP/1.1\n"
           "User-Agent: orion/%s\n"
           "Host: %s:%d\n"
           "Accept: application/xml, application/json\n",
           verb.c_str(), resource.c_str(), versionGet(), ip.c_str(), (int) port);

  if (!content.empty())
  {

    char   headers[512];
    sprintf(headers,
            "Content-Type: %s\n"
            "Content-Length: %zu\n",
            content_type.c_str(), content.length() + 1);
    strncat(preContent, headers, sizeof(preContent) - strlen(preContent));

    /* Choose the right buffer (static or dynamic) to use. Note we are using +3 due to:
     *    + 1, for the \n between preContent and content
     *    + 1, for the \n at the end of the message
     *    + 1, for the \0 by the trailing character in C strings
     */
    if (content.length() + strlen(preContent) + 3 > MAX_DYN_MSG_SIZE) {
        LM_RE("error", ("HTTP request to send is too large: %s bytes", content.length() + strlen(preContent)));
    }
    else if (content.length() + strlen(preContent) + 3 > MAX_STA_MSG_SIZE) {
        msgDynamic = (char*) calloc(sizeof(char), content.length() + 1);
        if (msgDynamic == NULL) {
            LM_RE("error", ("dyncamic memory allocation fail"));
        }
        msg = msgDynamic;
        LM_T(LmtClientOutputPayload, ("Using dynamic buffer to send HTTP request"));
    }
    else {
        LM_T(LmtClientOutputPayload, ("Using static buffer to send HTTP request"));
    }

    /* The above checking should ensure that the three parts fit, so we are using
     * sprint() instead of snprintf() */
    sprintf(msg, "%s\n%s", preContent, content.c_str());

  }
  else
  {
    /* In the case of no-content we assume that MAX_STA_MSG_SIZE is enough to send the message */
    LM_T(LmtClientOutputPayload, ("Using static buffer to send HTTP request (empty content)"));
    sprintf(msg, "%s\n", preContent);
  }

  /* We add a final newline (I guess that HTTP protocol needs it) */
  strcat(msg, "\n");

  int fd = socketHttpConnect(ip, port); // Connecting to HTTP server
  if (fd == -1)
    LM_RE("error", ("Unable to connect to HTTP server at %s:%d", ip.c_str(), port));

  int nb;
  int sz = strlen(msg);

  LM_T(LmtClientOutputPayload, ("Sending to HTTP server %d bytes", sz));
  LM_T(LmtClientOutputPayload, ("Sending to HTTP server payload:\n%s", msg));
  nb = send(fd, msg, sz, 0);
  if (msgDynamic != NULL) {
      free (msgDynamic);
  }

  if (nb == -1)
    LM_RE("error", ("error sending to HTTP server: %s", strerror(errno)));
  else if (nb != sz)
     LM_E(("error sending to HTTP server. Sent %d bytes of %d", nb, sz));

  if (waitForResponse) {
      nb = recv(fd,&buffer,TAM_BUF-1,0);

      if (nb == -1)
        LM_RE("error", ("error recv from HTTP server: %s", strerror(errno)));
      else if ( nb >= TAM_BUF)
         LM_RE("error", ("recv from HTTP server too long"));
      else
      {
          memcpy(response, buffer, nb);
          LM_T(LmtClientInputPayload, ("Received from HTTP server:\n%s", response));
      }

      if (strlen(response) > 0)
          result = response;
  }
  else {
     LM_T(LmtClientInputPayload, ("not waiting for response"));
     result = "";
  }

  close(fd);
  return result;
}
<commit_msg>FIX sendHttpSocket: - Fix ammount of memory to allocate in the case of dynamic buffer - Improve the text in some LM_T() traces<commit_after>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker 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 Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* fermin at tid dot es
*
* Author: developer
*/
#include <string>
#include <vector>

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"
#include "ConnectionInfo.h"
#include "clientSocketHttp.h"
#include "serviceRoutines/versionTreat.h"
#include <iostream>

#include <sys/types.h>                          // system types ...
#include <sys/socket.h>                         // socket, bind, listen
#include <sys/un.h>                             // sockaddr_un
#include <netinet/in.h>                         // struct sockaddr_in
#include <netdb.h>                              // gethostbyname
#include <arpa/inet.h>                          // inet_ntoa
#include <netinet/tcp.h>                        // TCP_NODELAY
#include <string>
#include <unistd.h>                             // close()

/* ****************************************************************************
*
* socketHttpConnect -
*/
int socketHttpConnect(std::string host, unsigned short port)
{
  int                 fd;
  struct hostent*     hp;
  struct sockaddr_in  peer;

  if ((hp = gethostbyname(host.c_str())) == NULL)
     LM_RE(-1, ("gethostbyname('%s'): %s", host.c_str(), strerror(errno)));

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
     LM_RE(-1, ("socket: %s", strerror(errno)));

  memset((char*) &peer, 0, sizeof(peer));

  peer.sin_family      = AF_INET;
  peer.sin_addr.s_addr = ((struct in_addr*) (hp->h_addr))->s_addr;
  peer.sin_port        = htons(port);

  if (connect(fd, (struct sockaddr*) &peer, sizeof(peer)) == -1)
  {
    close(fd);
    LM_E(("connect(%s, %d): %s", host.c_str(), port, strerror(errno)));
    return -1;
  }

  return fd;
}

/* ****************************************************************************
*
* sendHttpSocket -
*
* The waitForResponse arguments specifies if the method has to wait for response
* before return. If this argument is false, the return string is ""
*
* FIXME: I don't like too much "reusing" natural output to return "error" in the
* case of error. I think it would be smarter to use "std::string* error" in the
* arguments or (even better) and exception. To be solved in the future in a hardening
* period.
*
* Note, we are using an hybrid approach, consisting in an static thread-local buffer of
* small size that cope with the most of notifications to avoid expensive
* calloc/free syscalls if the notification payload is not very large.
*
*/
std::string sendHttpSocket
(
   std::string     ip,
   unsigned short  port,
   std::string     verb,
   std::string     resource,
   std::string     content_type,
   std::string     content,
   bool            waitForResponse
)
{
  char         buffer[TAM_BUF];
  char         response[TAM_BUF];
  char         preContent[TAM_BUF];
  char         msgStatic[MAX_STA_MSG_SIZE];

  std::string  result;
  char*        msgDynamic = NULL;
  char*        msg = msgStatic;   // by default, use the static buffer

  // Preconditions check
  if (port == 0)        LM_RE("error", ("port is ZERO"));
  if (ip.empty())       LM_RE("error", ("ip is empty"));
  if (verb.empty())     LM_RE("error", ("verb is empty"));
  if (resource.empty()) LM_RE("error", ("resource is empty"));
  if ((content_type.empty()) && (!content.empty())) LM_RE("error", ("Content-Type is empty but there is actual content"));
  if ((!content_type.empty()) && (content.empty())) LM_RE("error", ("there is actual content but Content-Type is empty"));

  // Buffers clear
  memset(buffer, 0, TAM_BUF);
  memset(response, 0, TAM_BUF);
  memset(preContent, 0, TAM_BUF);
  memset(msg, 0, MAX_STA_MSG_SIZE);

  snprintf(preContent, sizeof(preContent),
           "%s %s HTTP/1.1\n"
           "User-Agent: orion/%s\n"
           "Host: %s:%d\n"
           "Accept: application/xml, application/json\n",
           verb.c_str(), resource.c_str(), versionGet(), ip.c_str(), (int) port);

  if (!content.empty())
  {

    char   headers[512];
    sprintf(headers,
            "Content-Type: %s\n"
            "Content-Length: %zu\n",
            content_type.c_str(), content.length() + 1);
    strncat(preContent, headers, sizeof(preContent) - strlen(preContent));

    /* Choose the right buffer (static or dynamic) to use. Note we are using +3 due to:
     *    + 1, for the \n between preContent and content
     *    + 1, for the \n at the end of the message
     *    + 1, for the \0 by the trailing character in C strings
     */
    int neededSize = content.length() + strlen(preContent) + 3;
    if (neededSize > MAX_DYN_MSG_SIZE) {
        LM_RE("error", ("HTTP request to send is too large: %d bytes", content.length() + strlen(preContent)));
    }
    else if (neededSize > MAX_STA_MSG_SIZE) {
        msgDynamic = (char*) calloc(sizeof(char), neededSize);
        if (msgDynamic == NULL) {
            LM_RE("error", ("dynamic memory allocation failure"));
        }
        msg = msgDynamic;
        LM_T(LmtClientOutputPayload, ("Using dynamic buffer to send HTTP request: %d bytes", neededSize));
    }
    else {
        LM_T(LmtClientOutputPayload, ("Using static buffer to send HTTP request"));
    }

    /* The above checking should ensure that the three parts fit, so we are using
     * sprint() instead of snprintf() */
    sprintf(msg, "%s\n%s", preContent, content.c_str());

  }
  else
  {
    /* In the case of no-content we assume that MAX_STA_MSG_SIZE is enough to send the message */
    LM_T(LmtClientOutputPayload, ("Using static buffer to send HTTP request (empty content)"));
    sprintf(msg, "%s\n", preContent);
  }

  /* We add a final newline (I guess that HTTP protocol needs it) */
  strcat(msg, "\n");

  int fd = socketHttpConnect(ip, port); // Connecting to HTTP server
  if (fd == -1)
    LM_RE("error", ("Unable to connect to HTTP server at %s:%d", ip.c_str(), port));

  int nb;
  int sz = strlen(msg);

  LM_T(LmtClientOutputPayload, ("Sending to HTTP server %d bytes", sz));
  LM_T(LmtClientOutputPayload, ("Sending to HTTP server payload:\n%s", msg));
  nb = send(fd, msg, sz, 0);
  if (msgDynamic != NULL) {
      free (msgDynamic);
  }

  if (nb == -1)
    LM_RE("error", ("error sending to HTTP server: %s", strerror(errno)));
  else if (nb != sz)
     LM_E(("error sending to HTTP server. Sent %d bytes of %d", nb, sz));

  if (waitForResponse) {
      nb = recv(fd,&buffer,TAM_BUF-1,0);

      if (nb == -1)
        LM_RE("error", ("error recv from HTTP server: %s", strerror(errno)));
      else if ( nb >= TAM_BUF)
         LM_RE("error", ("recv from HTTP server too long"));
      else
      {
          memcpy(response, buffer, nb);
          LM_T(LmtClientInputPayload, ("Received from HTTP server:\n%s", response));
      }

      if (strlen(response) > 0)
          result = response;
  }
  else {
     LM_T(LmtClientInputPayload, ("not waiting for response"));
     result = "";
  }

  close(fd);
  return result;
}
<|endoftext|>