<commit_before>//
// Copyright (c) 2015-2017, Deutsches Forschungszentrum für Künstliche Intelligenz GmbH.
// Copyright (c) 2015-2017, University of Bremen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef __MAPS_POINT_HPP__
#define __MAPS_POINT_HPP__

/** Boost serialization **/
#include <boost/serialization/nvp.hpp>

/** Eigen **/
#include <Eigen/Core>
#include <Eigen/Geometry>

#include <utility>

namespace maps { namespace geometric
{
    /**@brief Point class IEEE 1873 standard
     * adapted to point in D-space.
     * T type (e.g. float or double)
     * D int specification for the dimensional space
     * **/
    template <typename T, int D>
    class Point: public Eigen::Matrix<T, D, 1, Eigen::DontAlign>
    {

    public:
        template <typename... Ts>
        Point(Ts&&... args) : Eigen::Matrix<T, D, 1, Eigen::DontAlign> (std::forward<Ts>(args)...)
        {
        }
    };

    typedef Point<double, 2> Point2d;
    typedef Point<double, 3> Point3d;
    typedef Point<float, 2> Point2f;
    typedef Point<float, 3> Point3f;
}}

namespace boost { namespace serialization
{
    template<class Archive, typename T, int D>
    void serialize(Archive & ar, ::maps::geometric::Point<T, D> & t, const unsigned int version)
    {
        for(size_t i=0; i<t.size(); i++)
            ar & BOOST_SERIALIZATION_NVP(t.data()[i]);
    }
}}

#endif /* __MAPS_POINT_HPP__ */
<commit_msg>fix warning<commit_after>//
// Copyright (c) 2015-2017, Deutsches Forschungszentrum für Künstliche Intelligenz GmbH.
// Copyright (c) 2015-2017, University of Bremen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef __MAPS_POINT_HPP__
#define __MAPS_POINT_HPP__

/** Boost serialization **/
#include <boost/serialization/nvp.hpp>

/** Eigen **/
#include <Eigen/Core>
#include <Eigen/Geometry>

#include <utility>

namespace maps { namespace geometric
{
    /**@brief Point class IEEE 1873 standard
     * adapted to point in D-space.
     * T type (e.g. float or double)
     * D int specification for the dimensional space
     * **/
    template <typename T, int D>
    class Point: public Eigen::Matrix<T, D, 1, Eigen::DontAlign>
    {

    public:
        template <typename... Ts>
        Point(Ts&&... args) : Eigen::Matrix<T, D, 1, Eigen::DontAlign> (std::forward<Ts>(args)...)
        {
        }
    };

    typedef Point<double, 2> Point2d;
    typedef Point<double, 3> Point3d;
    typedef Point<float, 2> Point2f;
    typedef Point<float, 3> Point3f;
}}

namespace boost { namespace serialization
{
    template<class Archive, typename T, int D>
    void serialize(Archive & ar, ::maps::geometric::Point<T, D> & t, const unsigned int version)
    {
        for(Eigen::Index i=0; i<t.size(); i++)
            ar & BOOST_SERIALIZATION_NVP(t[i]);
    }
}}

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


<commit_before>// Copyright (c) 2010 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 "media/filters/ffmpeg_video_decode_engine.h"

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/task.h"
#include "media/base/buffers.h"
#include "media/base/callback.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/ffmpeg/ffmpeg_util.h"
#include "media/filters/ffmpeg_demuxer.h"

namespace media {

FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine()
    : codec_context_(NULL),
      av_stream_(NULL),
      event_handler_(NULL) {
}

FFmpegVideoDecodeEngine::~FFmpegVideoDecodeEngine() {
}

void FFmpegVideoDecodeEngine::Initialize(
    MessageLoop* message_loop,
    VideoDecodeEngine::EventHandler* event_handler,
    const VideoCodecConfig& config) {
  // Always try to use three threads for video decoding.  There is little reason
  // not to since current day CPUs tend to be multi-core and we measured
  // performance benefits on older machines such as P4s with hyperthreading.
  //
  // Handling decoding on separate threads also frees up the pipeline thread to
  // continue processing. Although it'd be nice to have the option of a single
  // decoding thread, FFmpeg treats having one thread the same as having zero
  // threads (i.e., avcodec_decode_video() will execute on the calling thread).
  // Yet another reason for having three threads :)
  static const int kDecodeThreads = 3;
  static const int kMaxDecodeThreads = 16;

  av_stream_ = static_cast<AVStream*>(config.opaque_context_);
  codec_context_ = av_stream_->codec;
  codec_context_->flags2 |= CODEC_FLAG2_FAST;  // Enable faster H264 decode.
  // Enable motion vector search (potentially slow), strong deblocking filter
  // for damaged macroblocks, and set our error detection sensitivity.
  codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
  codec_context_->error_recognition = FF_ER_CAREFUL;

  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);

  // TODO(fbarchard): Improve thread logic based on size / codec.
  int decode_threads = (codec_context_->codec_id == CODEC_ID_THEORA)
      ? 1 : kDecodeThreads;

  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
  std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
  if ((!threads.empty() &&
      !base::StringToInt(threads, &decode_threads)) ||
      decode_threads < 0 || decode_threads > kMaxDecodeThreads) {
    decode_threads = kDecodeThreads;
  }

  // We don't allocate AVFrame on the stack since different versions of FFmpeg
  // may change the size of AVFrame, causing stack corruption.  The solution is
  // to let FFmpeg allocate the structure via avcodec_alloc_frame().
  av_frame_.reset(avcodec_alloc_frame());
  VideoCodecInfo info;
  info.success_ = false;
  info.provides_buffers_ = false;
  info.stream_info_.surface_type_ = VideoFrame::TYPE_SYSTEM_MEMORY;
  info.stream_info_.surface_format_ = GetSurfaceFormat();
  info.stream_info_.surface_width_ = config.width_;
  info.stream_info_.surface_height_ = config.height_;
  if (codec &&
      avcodec_thread_init(codec_context_, decode_threads) >= 0 &&
      avcodec_open(codec_context_, codec) >= 0 &&
      av_frame_.get()) {
    info.success_ = true;
  }
  event_handler_ = event_handler;
  event_handler_->OnInitializeComplete(info);
}

// TODO(fbarchard): Find way to remove this memcpy of the entire image.
static void CopyPlane(size_t plane,
                      scoped_refptr<VideoFrame> video_frame,
                      const AVFrame* frame) {
  DCHECK_EQ(video_frame->width() % 2, 0u);
  const uint8* source = frame->data[plane];
  const size_t source_stride = frame->linesize[plane];
  uint8* dest = video_frame->data(plane);
  const size_t dest_stride = video_frame->stride(plane);
  size_t bytes_per_line = video_frame->width();
  size_t copy_lines = video_frame->height();
  if (plane != VideoFrame::kYPlane) {
    bytes_per_line /= 2;
    if (video_frame->format() == VideoFrame::YV12) {
      copy_lines = (copy_lines + 1) / 2;
    }
  }
  DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride);
  for (size_t i = 0; i < copy_lines; ++i) {
    memcpy(dest, source, bytes_per_line);
    source += source_stride;
    dest += dest_stride;
  }
}

void FFmpegVideoDecodeEngine::EmptyThisBuffer(
    scoped_refptr<Buffer> buffer) {
  DecodeFrame(buffer);
}

void FFmpegVideoDecodeEngine::FillThisBuffer(scoped_refptr<VideoFrame> frame) {
  scoped_refptr<Buffer> buffer;
  event_handler_->OnEmptyBufferCallback(buffer);
}

// Try to decode frame when both input and output are ready.
void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) {
  scoped_refptr<VideoFrame> video_frame;

  // Create a packet for input data.
  // Due to FFmpeg API changes we no longer have const read-only pointers.
  AVPacket packet;
  av_init_packet(&packet);
  packet.data = const_cast<uint8*>(buffer->GetData());
  packet.size = buffer->GetDataSize();

  // Let FFmpeg handle presentation timestamp reordering.
  codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds();

  // This is for codecs not using get_buffer to initialize
  // |av_frame_->reordered_opaque|
  av_frame_->reordered_opaque = codec_context_->reordered_opaque;

  int frame_decoded = 0;
  int result = avcodec_decode_video2(codec_context_,
                                     av_frame_.get(),
                                     &frame_decoded,
                                     &packet);

  // Log the problem if we can't decode a video frame and exit early.
  if (result < 0) {
    LOG(INFO) << "Error decoding a video frame with timestamp: "
              << buffer->GetTimestamp().InMicroseconds() << " us"
              << " , duration: "
              << buffer->GetDuration().InMicroseconds() << " us"
              << " , packet size: "
              << buffer->GetDataSize() << " bytes";
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // If frame_decoded == 0, then no frame was produced.
  if (frame_decoded == 0) {
    if (buffer->IsEndOfStream())  // We had started flushing.
      event_handler_->OnFillBufferCallback(video_frame);
    else
      event_handler_->OnEmptyBufferCallback(buffer);
    return;
  }

  // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
  // The decoder is in a bad state and not decoding correctly.
  // Checking for NULL avoids a crash in CopyPlane().
  if (!av_frame_->data[VideoFrame::kYPlane] ||
      !av_frame_->data[VideoFrame::kUPlane] ||
      !av_frame_->data[VideoFrame::kVPlane]) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Determine timestamp and calculate the duration based on the repeat picture
  // count.  According to FFmpeg docs, the total duration can be calculated as
  // follows:
  //   duration = (1 / fps) + (repeat_pict) / (2 * fps)
  //            = (2 + repeat_pict) / (2 * fps)
  DCHECK_LE(av_frame_->repeat_pict, 2);  // Sanity check.
  // Even frame rate is fixed, for some streams and codecs, the value of
  // |codec_context_->time_base| and |av_stream_->time_base| are not the
  // inverse of the |av_stream_->r_frame_rate|. They use 1 milli-second as
  // time-base units and use increment of av_packet->pts which is not one.
  // Use the inverse of |av_stream_->r_frame_rate| instead of time_base.
  AVRational doubled_time_base;
  doubled_time_base.den = av_stream_->r_frame_rate.num;
  doubled_time_base.num = av_stream_->r_frame_rate.den;
  doubled_time_base.den *= 2;

  base::TimeDelta timestamp =
      base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque);
  base::TimeDelta duration =
      ConvertTimestamp(doubled_time_base, 2 + av_frame_->repeat_pict);

  VideoFrame::CreateFrame(GetSurfaceFormat(),
                          codec_context_->width,
                          codec_context_->height,
                          timestamp,
                          duration,
                          &video_frame);
  if (!video_frame.get()) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
  // output, meaning the data is only valid until the next
  // avcodec_decode_video() call.
  // TODO(scherkus): figure out pre-allocation/buffer cycling scheme.
  // TODO(scherkus): is there a cleaner way to figure out the # of planes?
  CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get());

  event_handler_->OnFillBufferCallback(video_frame);
}

void FFmpegVideoDecodeEngine::Uninitialize() {
  // TODO(jiesun): Release buffers when we support buffer recycling.
  event_handler_->OnUninitializeComplete();
}

void FFmpegVideoDecodeEngine::Flush() {
  avcodec_flush_buffers(codec_context_);
  event_handler_->OnFlushComplete();
}

void FFmpegVideoDecodeEngine::Seek() {
  event_handler_->OnSeekComplete();
}

VideoFrame::Format FFmpegVideoDecodeEngine::GetSurfaceFormat() const {
  // J (Motion JPEG) versions of YUV are full range 0..255.
  // Regular (MPEG) YUV is 16..240.
  // For now we will ignore the distinction and treat them the same.
  switch (codec_context_->pix_fmt) {
    case PIX_FMT_YUV420P:
    case PIX_FMT_YUVJ420P:
      return VideoFrame::YV12;
      break;
    case PIX_FMT_YUV422P:
    case PIX_FMT_YUVJ422P:
      return VideoFrame::YV16;
      break;
    default:
      // TODO(scherkus): More formats here?
      return VideoFrame::INVALID;
  }
}

}  // namespace media
<commit_msg>enable multicore decode for ogg theora video BUG=none TEST=media layout tests should not be flakey.<commit_after>// Copyright (c) 2010 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 "media/filters/ffmpeg_video_decode_engine.h"

#include "base/command_line.h"
#include "base/string_number_conversions.h"
#include "base/task.h"
#include "media/base/buffers.h"
#include "media/base/callback.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/ffmpeg/ffmpeg_common.h"
#include "media/ffmpeg/ffmpeg_util.h"
#include "media/filters/ffmpeg_demuxer.h"

namespace media {

FFmpegVideoDecodeEngine::FFmpegVideoDecodeEngine()
    : codec_context_(NULL),
      av_stream_(NULL),
      event_handler_(NULL) {
}

FFmpegVideoDecodeEngine::~FFmpegVideoDecodeEngine() {
}

void FFmpegVideoDecodeEngine::Initialize(
    MessageLoop* message_loop,
    VideoDecodeEngine::EventHandler* event_handler,
    const VideoCodecConfig& config) {
  // Always try to use three threads for video decoding.  There is little reason
  // not to since current day CPUs tend to be multi-core and we measured
  // performance benefits on older machines such as P4s with hyperthreading.
  //
  // Handling decoding on separate threads also frees up the pipeline thread to
  // continue processing. Although it'd be nice to have the option of a single
  // decoding thread, FFmpeg treats having one thread the same as having zero
  // threads (i.e., avcodec_decode_video() will execute on the calling thread).
  // Yet another reason for having three threads :)
  static const int kDecodeThreads = 3;
  static const int kMaxDecodeThreads = 16;

  av_stream_ = static_cast<AVStream*>(config.opaque_context_);
  codec_context_ = av_stream_->codec;
  codec_context_->flags2 |= CODEC_FLAG2_FAST;  // Enable faster H264 decode.
  // Enable motion vector search (potentially slow), strong deblocking filter
  // for damaged macroblocks, and set our error detection sensitivity.
  codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
  codec_context_->error_recognition = FF_ER_CAREFUL;

  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);

  // TODO(fbarchard): Improve thread logic based on size / codec.
  int decode_threads = kDecodeThreads;

  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
  std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
  if ((!threads.empty() &&
      !base::StringToInt(threads, &decode_threads)) ||
      decode_threads < 0 || decode_threads > kMaxDecodeThreads) {
    decode_threads = kDecodeThreads;
  }

  // We don't allocate AVFrame on the stack since different versions of FFmpeg
  // may change the size of AVFrame, causing stack corruption.  The solution is
  // to let FFmpeg allocate the structure via avcodec_alloc_frame().
  av_frame_.reset(avcodec_alloc_frame());
  VideoCodecInfo info;
  info.success_ = false;
  info.provides_buffers_ = false;
  info.stream_info_.surface_type_ = VideoFrame::TYPE_SYSTEM_MEMORY;
  info.stream_info_.surface_format_ = GetSurfaceFormat();
  info.stream_info_.surface_width_ = config.width_;
  info.stream_info_.surface_height_ = config.height_;
  if (codec &&
      avcodec_thread_init(codec_context_, decode_threads) >= 0 &&
      avcodec_open(codec_context_, codec) >= 0 &&
      av_frame_.get()) {
    info.success_ = true;
  }
#if !defined(FF_THREAD_FRAME)
#pragma message ("Warning: Not building with FFmpeg MT.")
#else
#pragma message ("Building with FFmpeg MT.")
#endif
  event_handler_ = event_handler;
  event_handler_->OnInitializeComplete(info);
}

// TODO(fbarchard): Find way to remove this memcpy of the entire image.
static void CopyPlane(size_t plane,
                      scoped_refptr<VideoFrame> video_frame,
                      const AVFrame* frame) {
  DCHECK_EQ(video_frame->width() % 2, 0u);
  const uint8* source = frame->data[plane];
  const size_t source_stride = frame->linesize[plane];
  uint8* dest = video_frame->data(plane);
  const size_t dest_stride = video_frame->stride(plane);
  size_t bytes_per_line = video_frame->width();
  size_t copy_lines = video_frame->height();
  if (plane != VideoFrame::kYPlane) {
    bytes_per_line /= 2;
    if (video_frame->format() == VideoFrame::YV12) {
      copy_lines = (copy_lines + 1) / 2;
    }
  }
  DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride);
  for (size_t i = 0; i < copy_lines; ++i) {
    memcpy(dest, source, bytes_per_line);
    source += source_stride;
    dest += dest_stride;
  }
}

void FFmpegVideoDecodeEngine::EmptyThisBuffer(
    scoped_refptr<Buffer> buffer) {
  DecodeFrame(buffer);
}

void FFmpegVideoDecodeEngine::FillThisBuffer(scoped_refptr<VideoFrame> frame) {
  scoped_refptr<Buffer> buffer;
  event_handler_->OnEmptyBufferCallback(buffer);
}

// Try to decode frame when both input and output are ready.
void FFmpegVideoDecodeEngine::DecodeFrame(scoped_refptr<Buffer> buffer) {
  scoped_refptr<VideoFrame> video_frame;

  // Create a packet for input data.
  // Due to FFmpeg API changes we no longer have const read-only pointers.
  AVPacket packet;
  av_init_packet(&packet);
  packet.data = const_cast<uint8*>(buffer->GetData());
  packet.size = buffer->GetDataSize();

  // Let FFmpeg handle presentation timestamp reordering.
  codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds();

  // This is for codecs not using get_buffer to initialize
  // |av_frame_->reordered_opaque|
  av_frame_->reordered_opaque = codec_context_->reordered_opaque;

  int frame_decoded = 0;
  int result = avcodec_decode_video2(codec_context_,
                                     av_frame_.get(),
                                     &frame_decoded,
                                     &packet);

  // Log the problem if we can't decode a video frame and exit early.
  if (result < 0) {
    LOG(INFO) << "Error decoding a video frame with timestamp: "
              << buffer->GetTimestamp().InMicroseconds() << " us"
              << " , duration: "
              << buffer->GetDuration().InMicroseconds() << " us"
              << " , packet size: "
              << buffer->GetDataSize() << " bytes";
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // If frame_decoded == 0, then no frame was produced.
  if (frame_decoded == 0) {
    if (buffer->IsEndOfStream())  // We had started flushing.
      event_handler_->OnFillBufferCallback(video_frame);
    else
      event_handler_->OnEmptyBufferCallback(buffer);
    return;
  }

  // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
  // The decoder is in a bad state and not decoding correctly.
  // Checking for NULL avoids a crash in CopyPlane().
  if (!av_frame_->data[VideoFrame::kYPlane] ||
      !av_frame_->data[VideoFrame::kUPlane] ||
      !av_frame_->data[VideoFrame::kVPlane]) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Determine timestamp and calculate the duration based on the repeat picture
  // count.  According to FFmpeg docs, the total duration can be calculated as
  // follows:
  //   duration = (1 / fps) + (repeat_pict) / (2 * fps)
  //            = (2 + repeat_pict) / (2 * fps)
  DCHECK_LE(av_frame_->repeat_pict, 2);  // Sanity check.
  // Even frame rate is fixed, for some streams and codecs, the value of
  // |codec_context_->time_base| and |av_stream_->time_base| are not the
  // inverse of the |av_stream_->r_frame_rate|. They use 1 milli-second as
  // time-base units and use increment of av_packet->pts which is not one.
  // Use the inverse of |av_stream_->r_frame_rate| instead of time_base.
  AVRational doubled_time_base;
  doubled_time_base.den = av_stream_->r_frame_rate.num;
  doubled_time_base.num = av_stream_->r_frame_rate.den;
  doubled_time_base.den *= 2;

  base::TimeDelta timestamp =
      base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque);
  base::TimeDelta duration =
      ConvertTimestamp(doubled_time_base, 2 + av_frame_->repeat_pict);

  VideoFrame::CreateFrame(GetSurfaceFormat(),
                          codec_context_->width,
                          codec_context_->height,
                          timestamp,
                          duration,
                          &video_frame);
  if (!video_frame.get()) {
    // TODO(jiesun): call event_handler_->OnError() instead.
    event_handler_->OnFillBufferCallback(video_frame);
    return;
  }

  // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
  // output, meaning the data is only valid until the next
  // avcodec_decode_video() call.
  // TODO(scherkus): figure out pre-allocation/buffer cycling scheme.
  // TODO(scherkus): is there a cleaner way to figure out the # of planes?
  CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get());
  CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get());

  event_handler_->OnFillBufferCallback(video_frame);
}

void FFmpegVideoDecodeEngine::Uninitialize() {
  // TODO(jiesun): Release buffers when we support buffer recycling.
  event_handler_->OnUninitializeComplete();
}

void FFmpegVideoDecodeEngine::Flush() {
  avcodec_flush_buffers(codec_context_);
  event_handler_->OnFlushComplete();
}

void FFmpegVideoDecodeEngine::Seek() {
  event_handler_->OnSeekComplete();
}

VideoFrame::Format FFmpegVideoDecodeEngine::GetSurfaceFormat() const {
  // J (Motion JPEG) versions of YUV are full range 0..255.
  // Regular (MPEG) YUV is 16..240.
  // For now we will ignore the distinction and treat them the same.
  switch (codec_context_->pix_fmt) {
    case PIX_FMT_YUV420P:
    case PIX_FMT_YUVJ420P:
      return VideoFrame::YV12;
      break;
    case PIX_FMT_YUV422P:
    case PIX_FMT_YUVJ422P:
      return VideoFrame::YV16;
      break;
    default:
      // TODO(scherkus): More formats here?
      return VideoFrame::INVALID;
  }
}

}  // namespace media
<|endoftext|>


<commit_before>#ifndef EASYRLECOMPRESSOR_HPP
#define EASYRLECOMPRESSOR_HPP
#include <tudocomp/util.hpp>
#include <tudocomp/util/vbyte.hpp>
#include <tudocomp/Env.hpp>
#include <tudocomp/Compressor.hpp>

namespace tdc {

/**
 * Encode a byte-stream with run length encoding
 * each run of the same character is substituted with two occurrences of the same character and the length of the run minus two,
 * encoded in vbyte coding.
 */
template<class char_type>
void rle_encode(std::basic_istream<char_type>& is, std::basic_ostream<char_type>& os) {
	char_type prev;
	if(!is.get(prev)) return;
	os << prev;
	char_type c;
	while(is.get(c)) {
		if(prev == c) {
			size_t run = 0;
			while(is.peek() == c) { ++run; is.get(); }
			os << c;
			write_vbyte(os, run);
		} else {
			os << c;
		}
		prev = c;
	}
}
/**
 * Decodes a run length encoded stream
 */
template<class char_type>
void rle_decode(std::basic_istream<char_type>& is, std::basic_ostream<char_type>& os) {
	char_type prev;
	if(!is.get(prev)) return;
	os << prev;
	char_type c;
	while(is.get(c)) {
		if(prev == c) {
			size_t run = read_vbyte<size_t>(is);
			while(run-- > 0) { os << c; }
		}
		os << c;
		prev = c;
	}
}

template<typename len_t = uint32_t>
class EasyRLECompressor : public Compressor {
public:
    inline static Meta meta() {
        Meta m("compressor", "easyrle", "Easy Run Length Encoding Compressor");
        return m;
    }
    inline EasyRLECompressor(Env&& env)
		: Compressor(std::move(env)) {
    }

    inline virtual void compress(Input& input, Output& output) override {
		auto is = input.as_stream();
		auto os = output.as_stream();
		rle_encode(is,os);
	}
    inline virtual void decompress(Input& input, Output& output) override {
		auto is = input.as_stream();
		auto os = output.as_stream();
		rle_decode(is,os);
	}
};

}//ns
#endif /* EASYRLECOMPRESSOR_HPP */
<commit_msg>Fix another whitespace issue<commit_after>#ifndef EASYRLECOMPRESSOR_HPP
#define EASYRLECOMPRESSOR_HPP
#include <tudocomp/util.hpp>
#include <tudocomp/util/vbyte.hpp>
#include <tudocomp/Env.hpp>
#include <tudocomp/Compressor.hpp>

namespace tdc {

/**
 * Encode a byte-stream with run length encoding
 * each run of the same character is substituted with two occurrences of the same character and the length of the run minus two,
 * encoded in vbyte coding.
 */
template<class char_type>
void rle_encode(std::basic_istream<char_type>& is, std::basic_ostream<char_type>& os) {
	char_type prev;
	if(!is.get(prev)) return;
	os << prev;
	char_type c;
	while(is.get(c)) {
		if(prev == c) {
			size_t run = 0;
			while(is.peek() == c) { ++run; is.get(); }
			os << c;
			write_vbyte(os, run);
		} else {
			os << c;
		}
		prev = c;
	}
}
/**
 * Decodes a run length encoded stream
 */
template<class char_type>
void rle_decode(std::basic_istream<char_type>& is, std::basic_ostream<char_type>& os) {
	char_type prev;
	if(!is.get(prev)) return;
	os << prev;
	char_type c;
	while(is.get(c)) {
		if(prev == c) {
			size_t run = read_vbyte<size_t>(is);
			while(run-- > 0) { os << c; }
		}
		os << c;
		prev = c;
	}
}

template<typename len_t = uint32_t>
class EasyRLECompressor : public Compressor {
public:
    inline static Meta meta() {
        Meta m("compressor", "easyrle", "Easy Run Length Encoding Compressor");
        return m;
    }
    inline EasyRLECompressor(Env&& env)
		: Compressor(std::move(env)) {
    }

    inline virtual void compress(Input& input, Output& output) override {
		auto is = input.as_stream();
		auto os = output.as_stream();
		rle_encode(is,os);
	}
    inline virtual void decompress(Input& input, Output& output) override {
		auto is = input.as_stream();
		auto os = output.as_stream();
		rle_decode(is,os);
	}
};

}//ns
#endif /* EASYRLECOMPRESSOR_HPP */
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Luke San Antonio
 * All rights reserved.
 */
#include "programs.h"
#include <vector>
#include <algorithm>
#include "../../common/json.h"
namespace survive
{
  namespace gfx
  {
    namespace gl
    {
      std::shared_ptr<Program> load_program(std::string decl) noexcept
      {
        static std::vector<std::shared_ptr<Program> > progs;

        using std::begin; using std::end;
        auto prog_find = std::find_if(begin(progs), end(progs),
        [&decl](auto const& val)
        {
          return val->name == decl;
        });

        std::shared_ptr<Program> ret;

        if(prog_find == end(progs))
        {
          auto doc = load_json(decl);

          auto vs = std::string{doc["vshade"].GetString()};
          auto fs = std::string{doc["fshade"].GetString()};

          ret = std::make_shared<Program>(Program::from_files(vs, fs));
          progs.push_back(ret);
        }
        else
        {
          ret = *prog_find;
        }
        return ret;
      }
    }
  }
}
<commit_msg>The programs cache now sets the name of each program the respective decl json it was loaded from.<commit_after>/*
 * Copyright (C) 2014 Luke San Antonio
 * All rights reserved.
 */
#include "programs.h"
#include <vector>
#include <algorithm>
#include "../../common/json.h"
namespace survive
{
  namespace gfx
  {
    namespace gl
    {
      std::shared_ptr<Program> load_program(std::string decl) noexcept
      {
        static std::vector<std::shared_ptr<Program> > progs;

        using std::begin; using std::end;
        auto prog_find = std::find_if(begin(progs), end(progs),
        [&decl](auto const& val)
        {
          return val->name == decl;
        });

        std::shared_ptr<Program> ret;

        if(prog_find == end(progs))
        {
          auto doc = load_json(decl);

          auto vs = std::string{doc["vshade"].GetString()};
          auto fs = std::string{doc["fshade"].GetString()};

          ret = std::make_shared<Program>(Program::from_files(vs, fs));
          ret->name = decl;
          progs.push_back(ret);
        }
        else
        {
          ret = *prog_find;
        }
        return ret;
      }
    }
  }
}
<|endoftext|>


<commit_before>// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: c-index-test -test-load-source all -comments-xml-schema=%S/../../bindings/xml/comment-xml-schema.rng -target x86_64-apple-darwin10 std=c++11 %s > %t/out
// RUN: FileCheck %s < %t/out

// Ensure that XML we generate is not invalid.
// RUN: FileCheck %s -check-prefix=WRONG < %t/out
// WRONG-NOT: CommentXMLInvalid
// rdar://12378714

/**
 * \brief Aaa
*/
template<typename T> struct A {
/**
 * \brief Bbb
*/
  A();
/**
 * \brief Ccc
*/
  ~A();
/**
 * \brief Ddd
*/
  void f() { }
};
// CHECK: <Declaration>template <typename T> struct A {\n}</Declaration>
// CHECL: <Declaration>A<T>()</Declaration>
// CHECK: <Declaration>void ~A<T>()</Declaration>

/**
 * \Brief Eee
*/
template <typename T> struct D : A<T> {
/**
 * \brief
*/
  using A<T>::f;

  void f();
};
// CHECK: <Declaration>template <typename T> struct D :  A<T> {\n}</Declaration>
// CHECK: <Declaration>using A<T>::f</Declaration>
<commit_msg>more test of template declarations in a <declaration> XML tag. // rdar://12378714<commit_after>// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: c-index-test -test-load-source all -comments-xml-schema=%S/../../bindings/xml/comment-xml-schema.rng -target x86_64-apple-darwin10 std=c++11 %s > %t/out
// RUN: FileCheck %s < %t/out

// Ensure that XML we generate is not invalid.
// RUN: FileCheck %s -check-prefix=WRONG < %t/out
// WRONG-NOT: CommentXMLInvalid
// rdar://12378714

/**
 * \brief Aaa
*/
template<typename T> struct A {
/**
 * \brief Bbb
*/
  A();
/**
 * \brief Ccc
*/
  ~A();
/**
 * \brief Ddd
*/
  void f() { }
};
// CHECK: <Declaration>template <typename T> struct A {\n}</Declaration>
// CHECL: <Declaration>A<T>()</Declaration>
// CHECK: <Declaration>void ~A<T>()</Declaration>

/**
 * \Brief Eee
*/
template <typename T> struct D : A<T> {
/**
 * \brief
*/
  using A<T>::f;

  void f();
};
// CHECK: <Declaration>template <typename T> struct D :  A<T> {\n}</Declaration>
// CHECK: <Declaration>using A<T>::f</Declaration>

struct Base {
    int foo;
};
/**
 * \brief
*/
template<typename T> struct E : Base {
/**
 * \brief
*/
  using Base::foo;
};
// CHECK: <Declaration>template <typename T> struct E :  Base {\n}</Declaration>
// CHECK: <Declaration>using Base::foo</Declaration>

/// \tparam
/// \param AAA Blah blah
template<typename T>
void func_template_1(T AAA);
// CHECK: <Declaration>template <typename T> void func_template_1(T AAA)</Declaration>

template<template<template<typename CCC> class DDD, class BBB> class AAA>
void func_template_2();
<Declaration>template <template <template <typename CCC> class DDD, class BBB> class AAA> void func_template_2()</Declaration>
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <math.h>

#include <rtl/math.hxx>
#include "sbcomp.hxx"
#include "expr.hxx"

SbiExprNode::SbiExprNode( void )
{
    pLeft = NULL;
    pRight = NULL;
    eNodeType = SbxDUMMY;
}

SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
{
    BaseInit( p );

    pLeft     = l;
    pRight    = r;
    eTok      = t;
    nVal      = 0;
    eType     = SbxVARIANT;     // Nodes are always Variant
    eNodeType = SbxNODE;
}

SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
{
    BaseInit( p );

    eType     = t;
    eNodeType = SbxNUMVAL;
    nVal      = n;
}

SbiExprNode::SbiExprNode( SbiParser* p, const OUString& rVal )
{
    BaseInit( p );

    eType     = SbxSTRING;
    eNodeType = SbxSTRVAL;
    aStrVal   = rVal;
}

SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
{
    BaseInit( p );

    eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
    eNodeType = SbxVARVAL;
    aVar.pDef = (SbiSymDef*) &r;
    aVar.pPar = l;
    aVar.pvMorePar = NULL;
    aVar.pNext= NULL;
}

// #120061 TypeOf
SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
{
    BaseInit( p );

    pLeft      = l;
    eType      = SbxBOOL;
    eNodeType  = SbxTYPEOF;
    nTypeStrId = nId;
}

// new <type>
SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
{
    BaseInit( p );

    eType     = SbxOBJECT;
    eNodeType = SbxNEW;
    nTypeStrId = nId;
}

// From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
void SbiExprNode::BaseInit( SbiParser* p )
{
    pGen = &p->aGen;
    eTok = NIL;
    pLeft       = NULL;
    pRight      = NULL;
    pWithParent = NULL;
    bError      = false;
}

SbiExprNode::~SbiExprNode()
{
    delete pLeft;
    delete pRight;
    if( IsVariable() )
    {
        delete aVar.pPar;
        delete aVar.pNext;
        SbiExprListVector* pvMorePar = aVar.pvMorePar;
        if( pvMorePar )
        {
            SbiExprListVector::iterator it;
            for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
                delete *it;
            delete pvMorePar;
        }
    }
}

SbiSymDef* SbiExprNode::GetVar()
{
    if( eNodeType == SbxVARVAL )
        return aVar.pDef;
    else
        return NULL;
}

SbiSymDef* SbiExprNode::GetRealVar()
{
    SbiExprNode* p = GetRealNode();
    if( p )
        return p->GetVar();
    else
        return NULL;
}

// From 1995-12-18
SbiExprNode* SbiExprNode::GetRealNode()
{
    if( eNodeType == SbxVARVAL )
    {
        SbiExprNode* p = this;
        while( p->aVar.pNext )
            p = p->aVar.pNext;
        return p;
    }
    else
        return NULL;
}

// This method transform the type, if it fits into the Integer range

bool SbiExprNode::IsIntConst()
{
    if( eNodeType == SbxNUMVAL )
    {
        if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
        {
            double n;
            if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
            {
                nVal = (double) (short) nVal;
                eType = SbxINTEGER;
                return true;
            }
        }
    }
    return false;
}

bool SbiExprNode::IsNumber()
{
    return eNodeType == SbxNUMVAL;
}

bool SbiExprNode::IsVariable()
{
    return eNodeType == SbxVARVAL;
}

bool SbiExprNode::IsLvalue()
{
    return IsVariable();
}

// Identify of the depth of a tree

short SbiExprNode::GetDepth()
{
    if( IsOperand() ) return 0;
    else
    {
        short d1 = pLeft->GetDepth();
        short d2 = pRight->GetDepth();
        return( (d1 < d2 ) ? d2 : d1 ) + 1;
    }
}

// Adjustment of a tree:
// 1. Constant Folding
// 2. Type-Adjustment
// 3. Conversion of the operans into Strings
// 4. Lifting of the composite- and error-bits

void SbiExprNode::Optimize()
{
    FoldConstants();
    CollectBits();
}

// Lifting of the error-bits

void SbiExprNode::CollectBits()
{
    if( pLeft )
    {
        pLeft->CollectBits();
        bError = bError || pLeft->bError;
    }
    if( pRight )
    {
        pRight->CollectBits();
        bError = bError || pRight->bError;
    }
}

// If a twig can be converted, True will be returned. In this case
// the result is in the left twig.

void SbiExprNode::FoldConstants()
{
    if( IsOperand() || eTok == LIKE ) return;
    if( pLeft )
        pLeft->FoldConstants();
    if( pRight )
    {
        pRight->FoldConstants();
        if( pLeft->IsConstant() && pRight->IsConstant()
            && pLeft->eNodeType == pRight->eNodeType )
        {
            CollectBits();
            if( eTok == CAT )
                // CAT affiliate also two numbers!
                eType = SbxSTRING;
            if( pLeft->eType == SbxSTRING )
                // No Type Mismatch!
                eType = SbxSTRING;
            if( eType == SbxSTRING )
            {
                OUString rl( pLeft->GetString() );
                OUString rr( pRight->GetString() );
                delete pLeft; pLeft = NULL;
                delete pRight; pRight = NULL;
                if( eTok == PLUS || eTok == CAT )
                {
                    eTok = CAT;
                    // Linking:
                    aStrVal = rl;
                    aStrVal += rr;
                    eType = SbxSTRING;
                    eNodeType = SbxSTRVAL;
                }
                else
                {
                    eType = SbxDOUBLE;
                    eNodeType = SbxNUMVAL;
                    int eRes = rr.compareTo( rl );
                    switch( eTok )
                    {
                    case EQ:
                        nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case NE:
                        nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case LT:
                        nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case GT:
                        nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case LE:
                        nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case GE:
                        nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    default:
                        pGen->GetParser()->Error( SbERR_CONVERSION );
                        bError = true;
                        break;
                    }
                }
            }
            else
            {
                double nl = pLeft->nVal;
                double nr = pRight->nVal;
                long ll = 0, lr = 0;
                long llMod = 0, lrMod = 0;
                if( ( eTok >= AND && eTok <= IMP )
                   || eTok == IDIV || eTok == MOD )
                {
                    // Integer operations
                    bool err = false;
                    if( nl > SbxMAXLNG ) err = true, nl = SbxMAXLNG;
                    else if( nl < SbxMINLNG ) err = true, nl = SbxMINLNG;
                    if( nr > SbxMAXLNG ) err = true, nr = SbxMAXLNG;
                    else if( nr < SbxMINLNG ) err = true, nr = SbxMINLNG;
                    ll = (long) nl; lr = (long) nr;
                    llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
                    lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
                    if( err )
                    {
                        pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
                        bError = true;
                    }
                }
                bool bBothInt = ( pLeft->eType < SbxSINGLE
                                   && pRight->eType < SbxSINGLE );
                delete pLeft; pLeft = NULL;
                delete pRight; pRight = NULL;
                nVal = 0;
                eType = SbxDOUBLE;
                eNodeType = SbxNUMVAL;
                bool bCheckType = false;
                switch( eTok )
                {
                    case EXPON:
                        nVal = pow( nl, nr ); break;
                    case MUL:
                        bCheckType = true;
                        nVal = nl * nr; break;
                    case DIV:
                        if( !nr )
                        {
                            pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
                            bError = true;
                        } else nVal = nl / nr;
                        break;
                    case PLUS:
                        bCheckType = true;
                        nVal = nl + nr; break;
                    case MINUS:
                        bCheckType = true;
                        nVal = nl - nr; break;
                    case EQ:
                        nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case NE:
                        nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case LT:
                        nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case GT:
                        nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case LE:
                        nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case GE:
                        nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case IDIV:
                        if( !lr )
                        {
                            pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
                            bError = true;
                        } else nVal = ll / lr;
                        eType = SbxLONG; break;
                    case MOD:
                        if( !lr )
                        {
                            pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
                            bError = true;
                        } else nVal = llMod % lrMod;
                        eType = SbxLONG; break;
                    case AND:
                        nVal = (double) ( ll & lr ); eType = SbxLONG; break;
                    case OR:
                        nVal = (double) ( ll | lr ); eType = SbxLONG; break;
                    case XOR:
                        nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
                    case EQV:
                        nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
                    case IMP:
                        nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
                    default: break;
                }

                if( !::rtl::math::isFinite( nVal ) )
                    pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );

                // Recover the data type to kill rounding error
                if( bCheckType && bBothInt
                 && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
                {
                    // Decimal place away
                    long n = (long) nVal;
                    nVal = n;
                    eType = ( n >= SbxMININT && n <= SbxMAXINT )
                          ? SbxINTEGER : SbxLONG;
                }
            }
        }
    }
    else if( pLeft && pLeft->IsNumber() )
    {
        nVal = pLeft->nVal;
        delete pLeft;
        pLeft = NULL;
        eType = SbxDOUBLE;
        eNodeType = SbxNUMVAL;
        switch( eTok )
        {
            case NEG:
                nVal = -nVal; break;
            case NOT: {
                // Integer operation!
                bool err = false;
                if( nVal > SbxMAXLNG ) err = true, nVal = SbxMAXLNG;
                else if( nVal < SbxMINLNG ) err = true, nVal = SbxMINLNG;
                if( err )
                {
                    pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
                    bError = true;
                }
                nVal = (double) ~((long) nVal);
                eType = SbxLONG;
                } break;
            default: break;
        }
    }
    if( eNodeType == SbxNUMVAL )
    {
        // Potentially convolve in INTEGER (because of better opcode)?
        if( eType == SbxSINGLE || eType == SbxDOUBLE )
        {
            double x;
            if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
            && !modf( nVal, &x ) )
                eType = SbxLONG;
        }
        if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
            eType = SbxINTEGER;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>CID#707643 uninitialized members<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <math.h>

#include <rtl/math.hxx>
#include "sbcomp.hxx"
#include "expr.hxx"

SbiExprNode::SbiExprNode()
{
    pLeft = NULL;
    pRight = NULL;
    pWithParent = NULL;
    pGen = NULL;
    eNodeType = SbxDUMMY;
    eType = SbxVARIANT;
    eTok = NIL;
    bError = false;
}

SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
{
    BaseInit( p );

    pLeft     = l;
    pRight    = r;
    eTok      = t;
    nVal      = 0;
    eType     = SbxVARIANT;     // Nodes are always Variant
    eNodeType = SbxNODE;
}

SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
{
    BaseInit( p );

    eType     = t;
    eNodeType = SbxNUMVAL;
    nVal      = n;
}

SbiExprNode::SbiExprNode( SbiParser* p, const OUString& rVal )
{
    BaseInit( p );

    eType     = SbxSTRING;
    eNodeType = SbxSTRVAL;
    aStrVal   = rVal;
}

SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
{
    BaseInit( p );

    eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
    eNodeType = SbxVARVAL;
    aVar.pDef = (SbiSymDef*) &r;
    aVar.pPar = l;
    aVar.pvMorePar = NULL;
    aVar.pNext= NULL;
}

// #120061 TypeOf
SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
{
    BaseInit( p );

    pLeft      = l;
    eType      = SbxBOOL;
    eNodeType  = SbxTYPEOF;
    nTypeStrId = nId;
}

// new <type>
SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
{
    BaseInit( p );

    eType     = SbxOBJECT;
    eNodeType = SbxNEW;
    nTypeStrId = nId;
}

// From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
void SbiExprNode::BaseInit( SbiParser* p )
{
    pGen = &p->aGen;
    eTok = NIL;
    pLeft       = NULL;
    pRight      = NULL;
    pWithParent = NULL;
    bError      = false;
}

SbiExprNode::~SbiExprNode()
{
    delete pLeft;
    delete pRight;
    if( IsVariable() )
    {
        delete aVar.pPar;
        delete aVar.pNext;
        SbiExprListVector* pvMorePar = aVar.pvMorePar;
        if( pvMorePar )
        {
            SbiExprListVector::iterator it;
            for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
                delete *it;
            delete pvMorePar;
        }
    }
}

SbiSymDef* SbiExprNode::GetVar()
{
    if( eNodeType == SbxVARVAL )
        return aVar.pDef;
    else
        return NULL;
}

SbiSymDef* SbiExprNode::GetRealVar()
{
    SbiExprNode* p = GetRealNode();
    if( p )
        return p->GetVar();
    else
        return NULL;
}

// From 1995-12-18
SbiExprNode* SbiExprNode::GetRealNode()
{
    if( eNodeType == SbxVARVAL )
    {
        SbiExprNode* p = this;
        while( p->aVar.pNext )
            p = p->aVar.pNext;
        return p;
    }
    else
        return NULL;
}

// This method transform the type, if it fits into the Integer range

bool SbiExprNode::IsIntConst()
{
    if( eNodeType == SbxNUMVAL )
    {
        if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
        {
            double n;
            if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
            {
                nVal = (double) (short) nVal;
                eType = SbxINTEGER;
                return true;
            }
        }
    }
    return false;
}

bool SbiExprNode::IsNumber()
{
    return eNodeType == SbxNUMVAL;
}

bool SbiExprNode::IsVariable()
{
    return eNodeType == SbxVARVAL;
}

bool SbiExprNode::IsLvalue()
{
    return IsVariable();
}

// Identify of the depth of a tree

short SbiExprNode::GetDepth()
{
    if( IsOperand() ) return 0;
    else
    {
        short d1 = pLeft->GetDepth();
        short d2 = pRight->GetDepth();
        return( (d1 < d2 ) ? d2 : d1 ) + 1;
    }
}

// Adjustment of a tree:
// 1. Constant Folding
// 2. Type-Adjustment
// 3. Conversion of the operans into Strings
// 4. Lifting of the composite- and error-bits

void SbiExprNode::Optimize()
{
    FoldConstants();
    CollectBits();
}

// Lifting of the error-bits

void SbiExprNode::CollectBits()
{
    if( pLeft )
    {
        pLeft->CollectBits();
        bError = bError || pLeft->bError;
    }
    if( pRight )
    {
        pRight->CollectBits();
        bError = bError || pRight->bError;
    }
}

// If a twig can be converted, True will be returned. In this case
// the result is in the left twig.

void SbiExprNode::FoldConstants()
{
    if( IsOperand() || eTok == LIKE ) return;
    if( pLeft )
        pLeft->FoldConstants();
    if( pRight )
    {
        pRight->FoldConstants();
        if( pLeft->IsConstant() && pRight->IsConstant()
            && pLeft->eNodeType == pRight->eNodeType )
        {
            CollectBits();
            if( eTok == CAT )
                // CAT affiliate also two numbers!
                eType = SbxSTRING;
            if( pLeft->eType == SbxSTRING )
                // No Type Mismatch!
                eType = SbxSTRING;
            if( eType == SbxSTRING )
            {
                OUString rl( pLeft->GetString() );
                OUString rr( pRight->GetString() );
                delete pLeft; pLeft = NULL;
                delete pRight; pRight = NULL;
                if( eTok == PLUS || eTok == CAT )
                {
                    eTok = CAT;
                    // Linking:
                    aStrVal = rl;
                    aStrVal += rr;
                    eType = SbxSTRING;
                    eNodeType = SbxSTRVAL;
                }
                else
                {
                    eType = SbxDOUBLE;
                    eNodeType = SbxNUMVAL;
                    int eRes = rr.compareTo( rl );
                    switch( eTok )
                    {
                    case EQ:
                        nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case NE:
                        nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case LT:
                        nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case GT:
                        nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case LE:
                        nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    case GE:
                        nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
                        break;
                    default:
                        pGen->GetParser()->Error( SbERR_CONVERSION );
                        bError = true;
                        break;
                    }
                }
            }
            else
            {
                double nl = pLeft->nVal;
                double nr = pRight->nVal;
                long ll = 0, lr = 0;
                long llMod = 0, lrMod = 0;
                if( ( eTok >= AND && eTok <= IMP )
                   || eTok == IDIV || eTok == MOD )
                {
                    // Integer operations
                    bool err = false;
                    if( nl > SbxMAXLNG ) err = true, nl = SbxMAXLNG;
                    else if( nl < SbxMINLNG ) err = true, nl = SbxMINLNG;
                    if( nr > SbxMAXLNG ) err = true, nr = SbxMAXLNG;
                    else if( nr < SbxMINLNG ) err = true, nr = SbxMINLNG;
                    ll = (long) nl; lr = (long) nr;
                    llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
                    lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
                    if( err )
                    {
                        pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
                        bError = true;
                    }
                }
                bool bBothInt = ( pLeft->eType < SbxSINGLE
                                   && pRight->eType < SbxSINGLE );
                delete pLeft; pLeft = NULL;
                delete pRight; pRight = NULL;
                nVal = 0;
                eType = SbxDOUBLE;
                eNodeType = SbxNUMVAL;
                bool bCheckType = false;
                switch( eTok )
                {
                    case EXPON:
                        nVal = pow( nl, nr ); break;
                    case MUL:
                        bCheckType = true;
                        nVal = nl * nr; break;
                    case DIV:
                        if( !nr )
                        {
                            pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
                            bError = true;
                        } else nVal = nl / nr;
                        break;
                    case PLUS:
                        bCheckType = true;
                        nVal = nl + nr; break;
                    case MINUS:
                        bCheckType = true;
                        nVal = nl - nr; break;
                    case EQ:
                        nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case NE:
                        nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case LT:
                        nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case GT:
                        nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case LE:
                        nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case GE:
                        nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
                        eType = SbxINTEGER; break;
                    case IDIV:
                        if( !lr )
                        {
                            pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
                            bError = true;
                        } else nVal = ll / lr;
                        eType = SbxLONG; break;
                    case MOD:
                        if( !lr )
                        {
                            pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
                            bError = true;
                        } else nVal = llMod % lrMod;
                        eType = SbxLONG; break;
                    case AND:
                        nVal = (double) ( ll & lr ); eType = SbxLONG; break;
                    case OR:
                        nVal = (double) ( ll | lr ); eType = SbxLONG; break;
                    case XOR:
                        nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
                    case EQV:
                        nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
                    case IMP:
                        nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
                    default: break;
                }

                if( !::rtl::math::isFinite( nVal ) )
                    pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );

                // Recover the data type to kill rounding error
                if( bCheckType && bBothInt
                 && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
                {
                    // Decimal place away
                    long n = (long) nVal;
                    nVal = n;
                    eType = ( n >= SbxMININT && n <= SbxMAXINT )
                          ? SbxINTEGER : SbxLONG;
                }
            }
        }
    }
    else if( pLeft && pLeft->IsNumber() )
    {
        nVal = pLeft->nVal;
        delete pLeft;
        pLeft = NULL;
        eType = SbxDOUBLE;
        eNodeType = SbxNUMVAL;
        switch( eTok )
        {
            case NEG:
                nVal = -nVal; break;
            case NOT: {
                // Integer operation!
                bool err = false;
                if( nVal > SbxMAXLNG ) err = true, nVal = SbxMAXLNG;
                else if( nVal < SbxMINLNG ) err = true, nVal = SbxMINLNG;
                if( err )
                {
                    pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
                    bError = true;
                }
                nVal = (double) ~((long) nVal);
                eType = SbxLONG;
                } break;
            default: break;
        }
    }
    if( eNodeType == SbxNUMVAL )
    {
        // Potentially convolve in INTEGER (because of better opcode)?
        if( eType == SbxSINGLE || eType == SbxDOUBLE )
        {
            double x;
            if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
            && !modf( nVal, &x ) )
                eType = SbxLONG;
        }
        if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
            eType = SbxINTEGER;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>//- ------------------------------------------------------------------
//-    Copyright (c) James W. Grenning -- All Rights Reserved
//-    For use by owners of Test-Driven Development for Embedded C,
//-    and attendees of Renaissance Software Consulting, Co. training
//-    classes.
//-
//-    Available at http://pragprog.com/titles/jgade/
//-        ISBN 1-934356-62-X, ISBN13 978-1-934356-62-3
//-
//-    Authorized users may use this source code in your own
//-    projects, however the source code may not be used to
//-    create training material, courses, books, articles, and
//-    the like. We make no guarantees that this source code is
//-    fit for any purpose.
//-
//-    www.renaissancesoftware.net james@renaissancesoftware.net
//- ------------------------------------------------------------------
//- ------------------------------------------------------------------
//-    Yasuhiro SHIMIZU ported this code to GoogleTest.
//- ------------------------------------------------------------------

#include "util/MockRuntimeError.h"

#include "LedDriver/LedDriver.h"

using ::testing::_;
using ::testing::Eq;
using ::testing::NotNull;
using ::testing::ByRef;
using ::testing::Sequence;

namespace LedDriver {

class LedDriver : public ::testing::TestWithParam<int> {
protected:
    virtual void SetUp()
    {
        util::gMockRuntimerErrorPtr = &mockRuntimeError_;

        LedDriver_Create(&virtualLeds_);
    }

    virtual void TearDown()
    {
        LedDriver_Destroy();
    }

    uint16_t virtualLeds_;

    util::MockRunuimeError mockRuntimeError_;

    Sequence sequence_;
};

TEST_F(LedDriver, leds_are_off_after_create)
{
    LedDriver_Destroy();
    LedDriver_Create(&virtualLeds_);
    ASSERT_THAT(virtualLeds_, Eq(0u));
}

TEST_F(LedDriver, turn_on_led_one)
{
    LedDriver_TurnOn(1);
    ASSERT_THAT(virtualLeds_, Eq(1u));
}

TEST_F(LedDriver, turn_off_led_one)
{
    LedDriver_TurnOn(1);
    LedDriver_TurnOff(1);
    ASSERT_THAT(virtualLeds_, Eq(0u));
}

TEST_F(LedDriver, turn_on_multiple_leds)
{
    LedDriver_TurnOn(9);
    LedDriver_TurnOn(8);
    ASSERT_THAT(virtualLeds_, Eq(0x180u));
}

TEST_F(LedDriver, turn_off_any_led)
{
    LedDriver_TurnAllOn();
    LedDriver_TurnOff(8);
    ASSERT_THAT(virtualLeds_, Eq(0xff7fu));
}

TEST_F(LedDriver, led_memory_is_not_readable)
{
    virtualLeds_ = 0xffffu;
    LedDriver_TurnOn(8);
    ASSERT_THAT(virtualLeds_, Eq(0x80u));
}

TEST_F(LedDriver, UpperAndLowerBounds)
{
    LedDriver_TurnOn(1);
    LedDriver_TurnOn(16);
    ASSERT_THAT(virtualLeds_, Eq(0x8001u));
}

TEST_P(LedDriver, out_of_bounds_turn_on_does_no_harm)
{
    const int n = GetParam();

    EXPECT_CALL(mockRuntimeError_, AddLog(_, n, _, _))
        .Times(1)
        .InSequence(sequence_);

    LedDriver_TurnOn(n);

    ASSERT_THAT(virtualLeds_, Eq(0u));
}

TEST_P(LedDriver, out_of_bounds_turn_off_does_no_harm)
{
    LedDriver_TurnAllOn();

    const int n = GetParam();

    EXPECT_CALL(mockRuntimeError_, AddLog(_, n, _, _))
        .Times(1)
        .InSequence(sequence_);

    LedDriver_TurnOn(n);

    ASSERT_THAT(virtualLeds_, Eq(0xffffu));
}

INSTANTIATE_TEST_CASE_P(
    OutOfBoundaries,
    LedDriver,
    ::testing::Values(-1, 0u, 17u, 3141u));

#if 0
TEST_F(LedDriver, out_of_bounds_to_do)
{
    //TODO: what should we do during runtime?
}
#endif

TEST_F(LedDriver, out_of_bounds_produces_runtime_error)
{
    const std::string kExpectLog{ "LED Driver: out-of-bounds LED" };

    EXPECT_CALL(mockRuntimeError_, AddLog(kExpectLog, _, _, _))
        .Times(1)
        .InSequence(sequence_);

    LedDriver_TurnOn(-1);
}

TEST_F(LedDriver, IsOn)
{
    ASSERT_THAT(LedDriver_IsOn(1), Eq(false));
    LedDriver_TurnOn(1);
    ASSERT_THAT(LedDriver_IsOn(1), Eq(true));
}

TEST_F(LedDriver, IsOff)
{
    ASSERT_THAT(LedDriver_IsOff(12), Eq(true));
    LedDriver_TurnOn(12);
    ASSERT_THAT(LedDriver_IsOff(12), Eq(false));
}

TEST_F(LedDriver, out_of_bounds_leds_are_always_off)
{
    EXPECT_CALL(mockRuntimeError_, AddLog(_, _, _, _))
        .Times(4);

    ASSERT_THAT(LedDriver_IsOff(0),  Eq(true));
    ASSERT_THAT(LedDriver_IsOff(17), Eq(true));
    ASSERT_THAT(LedDriver_IsOn(0),   Eq(false));
    ASSERT_THAT(LedDriver_IsOn(17),  Eq(false));
}

TEST_F(LedDriver, all_on)
{
    LedDriver_TurnAllOn();
    ASSERT_THAT(virtualLeds_, Eq(0xffffu));
}

TEST_F(LedDriver, all_off)
{
    LedDriver_TurnAllOn();
    LedDriver_TurnAllOff();
    ASSERT_THAT(virtualLeds_, Eq(0u));
}

} // namespace LedDriver

<commit_msg>Fix wrong method call.<commit_after>//- ------------------------------------------------------------------
//-    Copyright (c) James W. Grenning -- All Rights Reserved
//-    For use by owners of Test-Driven Development for Embedded C,
//-    and attendees of Renaissance Software Consulting, Co. training
//-    classes.
//-
//-    Available at http://pragprog.com/titles/jgade/
//-        ISBN 1-934356-62-X, ISBN13 978-1-934356-62-3
//-
//-    Authorized users may use this source code in your own
//-    projects, however the source code may not be used to
//-    create training material, courses, books, articles, and
//-    the like. We make no guarantees that this source code is
//-    fit for any purpose.
//-
//-    www.renaissancesoftware.net james@renaissancesoftware.net
//- ------------------------------------------------------------------
//- ------------------------------------------------------------------
//-    Yasuhiro SHIMIZU ported this code to GoogleTest.
//- ------------------------------------------------------------------

#include "util/MockRuntimeError.h"

#include "LedDriver/LedDriver.h"

using ::testing::_;
using ::testing::Eq;
using ::testing::NotNull;
using ::testing::ByRef;
using ::testing::Sequence;

namespace LedDriver {

class LedDriver : public ::testing::TestWithParam<int> {
protected:
    virtual void SetUp()
    {
        util::gMockRuntimerErrorPtr = &mockRuntimeError_;

        LedDriver_Create(&virtualLeds_);
    }

    virtual void TearDown()
    {
        LedDriver_Destroy();
    }

    uint16_t virtualLeds_;

    util::MockRunuimeError mockRuntimeError_;

    Sequence sequence_;
};

TEST_F(LedDriver, leds_are_off_after_create)
{
    LedDriver_Destroy();
    LedDriver_Create(&virtualLeds_);
    ASSERT_THAT(virtualLeds_, Eq(0u));
}

TEST_F(LedDriver, turn_on_led_one)
{
    LedDriver_TurnOn(1);
    ASSERT_THAT(virtualLeds_, Eq(1u));
}

TEST_F(LedDriver, turn_off_led_one)
{
    LedDriver_TurnOn(1);
    LedDriver_TurnOff(1);
    ASSERT_THAT(virtualLeds_, Eq(0u));
}

TEST_F(LedDriver, turn_on_multiple_leds)
{
    LedDriver_TurnOn(9);
    LedDriver_TurnOn(8);
    ASSERT_THAT(virtualLeds_, Eq(0x180u));
}

TEST_F(LedDriver, turn_off_any_led)
{
    LedDriver_TurnAllOn();
    LedDriver_TurnOff(8);
    ASSERT_THAT(virtualLeds_, Eq(0xff7fu));
}

TEST_F(LedDriver, led_memory_is_not_readable)
{
    virtualLeds_ = 0xffffu;
    LedDriver_TurnOn(8);
    ASSERT_THAT(virtualLeds_, Eq(0x80u));
}

TEST_F(LedDriver, UpperAndLowerBounds)
{
    LedDriver_TurnOn(1);
    LedDriver_TurnOn(16);
    ASSERT_THAT(virtualLeds_, Eq(0x8001u));
}

TEST_P(LedDriver, out_of_bounds_turn_on_does_no_harm)
{
    const int n = GetParam();

    EXPECT_CALL(mockRuntimeError_, AddLog(_, n, _, _))
        .Times(1)
        .InSequence(sequence_);

    LedDriver_TurnOn(n);

    ASSERT_THAT(virtualLeds_, Eq(0u));
}

TEST_P(LedDriver, out_of_bounds_turn_off_does_no_harm)
{
    LedDriver_TurnAllOn();

    const int n = GetParam();

    EXPECT_CALL(mockRuntimeError_, AddLog(_, n, _, _))
        .Times(1)
        .InSequence(sequence_);

    LedDriver_TurnOff(n);

    ASSERT_THAT(virtualLeds_, Eq(0xffffu));
}

INSTANTIATE_TEST_CASE_P(
    OutOfBoundaries,
    LedDriver,
    ::testing::Values(-1, 0u, 17u, 3141u));

#if 0
TEST_F(LedDriver, out_of_bounds_to_do)
{
    //TODO: what should we do during runtime?
}
#endif

TEST_F(LedDriver, out_of_bounds_produces_runtime_error)
{
    const std::string kExpectLog{ "LED Driver: out-of-bounds LED" };

    EXPECT_CALL(mockRuntimeError_, AddLog(kExpectLog, _, _, _))
        .Times(1)
        .InSequence(sequence_);

    LedDriver_TurnOn(-1);
}

TEST_F(LedDriver, IsOn)
{
    ASSERT_THAT(LedDriver_IsOn(1), Eq(false));
    LedDriver_TurnOn(1);
    ASSERT_THAT(LedDriver_IsOn(1), Eq(true));
}

TEST_F(LedDriver, IsOff)
{
    ASSERT_THAT(LedDriver_IsOff(12), Eq(true));
    LedDriver_TurnOn(12);
    ASSERT_THAT(LedDriver_IsOff(12), Eq(false));
}

TEST_F(LedDriver, out_of_bounds_leds_are_always_off)
{
    EXPECT_CALL(mockRuntimeError_, AddLog(_, _, _, _))
        .Times(4);

    ASSERT_THAT(LedDriver_IsOff(0),  Eq(true));
    ASSERT_THAT(LedDriver_IsOff(17), Eq(true));
    ASSERT_THAT(LedDriver_IsOn(0),   Eq(false));
    ASSERT_THAT(LedDriver_IsOn(17),  Eq(false));
}

TEST_F(LedDriver, all_on)
{
    LedDriver_TurnAllOn();
    ASSERT_THAT(virtualLeds_, Eq(0xffffu));
}

TEST_F(LedDriver, all_off)
{
    LedDriver_TurnAllOn();
    LedDriver_TurnAllOff();
    ASSERT_THAT(virtualLeds_, Eq(0u));
}

} // namespace LedDriver

<|endoftext|>


<commit_before>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <algebra/NDSS.h>
#include <thread>
#include <atomic>
#include <vector>

#ifdef FHE_THREADS
const long WORKER_NR = 8;
#else // ifdef FHE_THREADS
const long WORKER_NR = 1;
#endif // ifdef FHE_THREAD

std::vector<MDL::EncVector>encrypt(const MDL::Matrix<long>& data,
                                   const FHEPubKey        & pk,
                                   const EncryptedArray   & ea,
                                   long                     rows_to_proces = 0)
{
    MDL::Timer timer;
    std::vector<MDL::EncVector> ctxts(data.rows(), pk);
    std::vector<std::thread>    workers;
    std::atomic<size_t> counter(0);

    rows_to_proces = rows_to_proces == 0 ? data.rows() : rows_to_proces;
    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&data, &ea, &rows_to_proces,
                                                 &counter, &ctxts]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < rows_to_proces) {
                ctxts[next].pack(data[next], ea);
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    timer.end();
    printf("Encrypt %ld data with %ld workers costed %f sec\n", rows_to_proces,
           WORKER_NR, timer.second());
    return ctxts;
}

MDL::EncVector mean(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) {
        wr.join();
    }

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Mean %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

MDL::EncVector variance(std::vector<MDL::EncVector>& ctxts)
{
    MDL::Timer timer;
    NTL::ZZX   N(ctxts.size());
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    timer.start();
    WORKER_NR = 1;
    auto sum_sq = mean(ctxts);
    sum_sq.square();
    MDL::Timer mult_timer;
    mult_timer.start();
    WORKER_NR = 8;

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&ctxts, &counter]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ctxts[next].square();
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    mult_timer.end();
    printf("Square costed %f sec\n", mult_timer.second());
    WORKER_NR = 1;
    auto sq_sum = mean(ctxts);
    WORKER_NR = 8;
    sq_sum.multByConstant(N);
    sq_sum.addCtxt(sum_sq, true);
    timer.end();
    printf("Variance %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return sq_sum;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data   = load_csv("adult.data", 100);
    auto result = load_csv("adult_result");
    auto ctxts  = encrypt(data, pk, ea);

    // {
    //     MDL::Vector<long> ret;
    //     auto summaiton = mean(ctxts);
    //     summaiton.unpack(ret, sk, ea);
    //     std::cout << ret << std::endl;
    //     std::cout << result[0] << std::endl;
    // }

    {
        MDL::Vector<long> ret;

        auto var = variance(ctxts);
        var.unpack(ret, sk, ea);
        std::cout << ret << std::endl;
        std::cout << result[1] << std::endl;
    }
    return 0;
}
<commit_msg>modifiable WORKER_NR<commit_after>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <algebra/NDSS.h>
#include <thread>
#include <atomic>
#include <vector>

#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREAD

std::vector<MDL::EncVector>encrypt(const MDL::Matrix<long>& data,
                                   const FHEPubKey        & pk,
                                   const EncryptedArray   & ea,
                                   long                     rows_to_proces = 0)
{
    MDL::Timer timer;
    std::vector<MDL::EncVector> ctxts(data.rows(), pk);
    std::vector<std::thread>    workers;
    std::atomic<size_t> counter(0);

    rows_to_proces = rows_to_proces == 0 ? data.rows() : rows_to_proces;
    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&data, &ea, &rows_to_proces,
                                                 &counter, &ctxts]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < rows_to_proces) {
                ctxts[next].pack(data[next], ea);
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    timer.end();
    printf("Encrypt %ld data with %ld workers costed %f sec\n", rows_to_proces,
           WORKER_NR, timer.second());
    return ctxts;
}

MDL::EncVector mean(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) {
        wr.join();
    }

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Mean %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

MDL::EncVector variance(std::vector<MDL::EncVector>& ctxts)
{
    MDL::Timer timer;
    NTL::ZZX   N(ctxts.size());
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    timer.start();
    WORKER_NR = 1;
    auto sum_sq = mean(ctxts);
    sum_sq.square();
    MDL::Timer mult_timer;
    mult_timer.start();
    WORKER_NR = 8;

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&ctxts, &counter]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ctxts[next].square();
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    mult_timer.end();
    printf("Square costed %f sec\n", mult_timer.second());
    WORKER_NR = 1;
    auto sq_sum = mean(ctxts);
    WORKER_NR = 8;
    sq_sum.multByConstant(N);
    sq_sum.addCtxt(sum_sq, true);
    timer.end();
    printf("Variance %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return sq_sum;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data   = load_csv("adult.data", 100);
    auto result = load_csv("adult_result");
    auto ctxts  = encrypt(data, pk, ea);

    // {
    //     MDL::Vector<long> ret;
    //     auto summaiton = mean(ctxts);
    //     summaiton.unpack(ret, sk, ea);
    //     std::cout << ret << std::endl;
    //     std::cout << result[0] << std::endl;
    // }

    {
        MDL::Vector<long> ret;

        auto var = variance(ctxts);
        var.unpack(ret, sk, ea);
        std::cout << ret << std::endl;
        std::cout << result[1] << std::endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// query_logger_test.cpp
//
// Identification: test/brain/query_logger_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>

#include "catalog/catalog.h"
#include "common/harness.h"
#include "concurrency/transaction_manager_factory.h"
#include "sql/testing_sql_util.h"
#include "settings/settings_manager.h"
#include "parser/pg_query.h"
#include "threadpool/brain_thread_pool.h"

using std::vector;
using std::string;

namespace peloton {
namespace test {

class QueryLoggerTests : public PelotonTest {
 protected:
  virtual void SetUp() override {
    settings::SettingsManager::SetBool(settings::SettingId::brain, true);
    PelotonInit::Initialize();

    // query to check that logging is done
    select_query =
        "SELECT query_string, fingerprint FROM pg_catalog.pg_query_history;";
    select_query_fingerprint =
        pg_query_fingerprint(select_query.c_str()).hexdigest;
    wait_time = 2;
  }

  virtual void TearDown() override { PelotonInit::Shutdown(); }

  // Executes the given query and then checks if the queries that are executed
  // till now are actually logged
  void TestSimpleUtil(string const &test_query,
                      vector<std::string> &expected_result) {
    string test_query_fingerprint =
        pg_query_fingerprint(test_query.c_str()).hexdigest;
    expected_result.push_back(test_query + "|" + test_query_fingerprint);
    TestingSQLUtil::ExecuteSQLQuery(test_query.c_str());

    // give some time to actually log this query
    sleep(wait_time);

    TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query.c_str(),
                                                  expected_result, true);

    // the select query we used will also be logged for next time
    expected_result.push_back(select_query + "|" + select_query_fingerprint);
  }

  // Executes the given query and then checks if the queries that are executed
  // till now are actually logged only when the transaction commits. Otherwise
  // stores to queries for checking this later when commit happens.
  void TestTransactionUtil(string const &test_query,
                           vector<std::string> &expected_result,
                           bool committed) {
    static vector<std::string> temporary_expected_result;
    string test_query_fingerprint =
        pg_query_fingerprint(test_query.c_str()).hexdigest;
    temporary_expected_result.push_back(test_query + "|" +
                                        test_query_fingerprint);
    TestingSQLUtil::ExecuteSQLQuery(test_query.c_str());

    // give some time to actually log this query
    sleep(wait_time);

    // only check once the the transaction has committed
    if (committed) {
      expected_result.insert(expected_result.end(),
                             temporary_expected_result.begin(),
                             temporary_expected_result.end());
      temporary_expected_result.clear();
      TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query.c_str(),
                                                    expected_result, true);
      // the select query we used will also be logged for next time
      expected_result.push_back(select_query + "|" + select_query_fingerprint);
    }
  }

 protected:
  string select_query;  // fixed query to check the queries logged in the table
  string select_query_fingerprint;  // fingerprint for the fixed query
  int wait_time;  // time to wait in seconds for the query to log into the table
};

// Testing the functionality of query logging
TEST_F(QueryLoggerTests, QueriesTest) {
  vector<std::string> expected_result;  // used to store the expected result

  // create the table and do some inserts and check
  TestSimpleUtil("CREATE TABLE test(a INT);", expected_result);
  TestSimpleUtil("INSERT INTO test VALUES (1);", expected_result);
  TestSimpleUtil("INSERT INTO test VALUES (2);", expected_result);

  // check if the queries are logged only when the transaction actually commits
  TestTransactionUtil("BEGIN;", expected_result, false);
  TestTransactionUtil("INSERT INTO test VALUES (1);", expected_result, false);
  TestTransactionUtil("COMMIT;", expected_result, true);

  // final check to see if everything is ok
  TestSimpleUtil(select_query, expected_result);
}

}  // namespace test
}  // namespace peloton
<commit_msg>make transaction test more robust<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// query_logger_test.cpp
//
// Identification: test/brain/query_logger_test.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>

#include "catalog/catalog.h"
#include "common/harness.h"
#include "concurrency/transaction_manager_factory.h"
#include "sql/testing_sql_util.h"
#include "settings/settings_manager.h"
#include "parser/pg_query.h"
#include "threadpool/brain_thread_pool.h"

using std::vector;
using std::string;

namespace peloton {
namespace test {

class QueryLoggerTests : public PelotonTest {
 protected:
  virtual void SetUp() override {
    settings::SettingsManager::SetBool(settings::SettingId::brain, true);
    PelotonInit::Initialize();

    // query to check that logging is done
    select_query =
        "SELECT query_string, fingerprint FROM pg_catalog.pg_query_history;";
    select_query_fingerprint =
        pg_query_fingerprint(select_query.c_str()).hexdigest;
    wait_time = 2;
  }

  virtual void TearDown() override { PelotonInit::Shutdown(); }

  // Executes the given query and then checks if the queries that are executed
  // till now are actually logged
  void TestSimpleUtil(string const &test_query,
                      vector<std::string> &expected_result) {
    string test_query_fingerprint =
        pg_query_fingerprint(test_query.c_str()).hexdigest;
    expected_result.push_back(test_query + "|" + test_query_fingerprint);
    TestingSQLUtil::ExecuteSQLQuery(test_query.c_str());

    // give some time to actually log this query
    sleep(wait_time);

    TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query.c_str(),
                                                  expected_result, true);

    // the select query we used will also be logged for next time
    expected_result.push_back(select_query + "|" + select_query_fingerprint);
  }

  // Executes the given query and then checks if the queries that are executed
  // till now are actually logged only when the transaction commits. Otherwise
  // stores to queries for checking this later when commit happens.
  void TestTransactionUtil(string const &test_query,
                           vector<std::string> &expected_result,
                           bool committed) {
    static vector<std::string> temporary_expected_result;
    string test_query_fingerprint =
        pg_query_fingerprint(test_query.c_str()).hexdigest;
    temporary_expected_result.push_back(test_query + "|" +
                                        test_query_fingerprint);
    TestingSQLUtil::ExecuteSQLQuery(test_query.c_str());

    // give some time to actually log this query
    sleep(wait_time);

    // only check once the the transaction has committed
    if (committed) {
      // accounting for the select_query that happened before this txn
      expected_result.push_back(select_query + "|" + select_query_fingerprint);

      expected_result.insert(expected_result.end(),
                             temporary_expected_result.begin(),
                             temporary_expected_result.end());
      temporary_expected_result.clear();
      TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query.c_str(),
                                                    expected_result, true);

      // the select query we used will also be logged for next time
      expected_result.push_back(select_query + "|" + select_query_fingerprint);

    } else {
      // verify that the logging does not happen before the txn commit
      TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query.c_str(),
                                                    expected_result, true);
      // the select query we used will also be logged for next time
      temporary_expected_result.push_back(select_query + "|" +
                                          select_query_fingerprint);
    }
  }

 protected:
  string select_query;  // fixed query to check the queries logged in the table
  string select_query_fingerprint;  // fingerprint for the fixed query
  int wait_time;  // time to wait in seconds for the query to log into the table
};

// Testing the functionality of query logging
TEST_F(QueryLoggerTests, QueriesTest) {
  vector<std::string> expected_result;  // used to store the expected result

  // create the table and do some inserts and check
  TestSimpleUtil("CREATE TABLE test(a INT);", expected_result);
  TestSimpleUtil("INSERT INTO test VALUES (1);", expected_result);
  TestSimpleUtil("INSERT INTO test VALUES (2);", expected_result);

  expected_result.pop_back();  // the select_query done at the end of above test
                               // won't be logged till the txn below commits

  // check if the queries are logged only when the transaction actually commits
  TestTransactionUtil("BEGIN;", expected_result, false);
  TestTransactionUtil("INSERT INTO test VALUES (1);", expected_result, false);
  TestTransactionUtil("COMMIT;", expected_result, true);

  // final check to see if everything is ok
  TestSimpleUtil(select_query, expected_result);
}

}  // namespace test
}  // namespace peloton
<|endoftext|>