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

#include <stdio.h>

#include <map>
#include <memory>
#include <sstream>

#include "gflags/gflags.h"
#include "webrtc/base/checks.h"
#include "webrtc/call/call.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/system_wrappers/include/sleep.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/null_transport.h"
#include "webrtc/test/rtp_file_reader.h"
#include "webrtc/test/run_loop.h"
#include "webrtc/test/run_test.h"
#include "webrtc/test/video_capturer.h"
#include "webrtc/test/video_renderer.h"
#include "webrtc/typedefs.h"
#include "webrtc/video_decoder.h"

namespace webrtc {
namespace flags {

// TODO(pbos): Multiple receivers.

// Flag for payload type.
static bool ValidatePayloadType(const char* flagname, int32_t payload_type) {
  return payload_type > 0 && payload_type <= 127;
}
DEFINE_int32(payload_type, 0, "Payload type");
static int PayloadType() { return static_cast<int>(FLAGS_payload_type); }
static const bool payload_dummy =
    google::RegisterFlagValidator(&FLAGS_payload_type, &ValidatePayloadType);

// Flag for SSRC.
static bool ValidateSsrc(const char* flagname, uint64_t ssrc) {
  return ssrc > 0 && ssrc <= 0xFFFFFFFFu;
}

DEFINE_uint64(ssrc, 0, "Incoming SSRC");
static uint32_t Ssrc() { return static_cast<uint32_t>(FLAGS_ssrc); }
static const bool ssrc_dummy =
    google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrc);

static bool ValidateOptionalPayloadType(const char* flagname,
                                        int32_t payload_type) {
  return payload_type == -1 || ValidatePayloadType(flagname, payload_type);
}

// Flag for RED payload type.
DEFINE_int32(red_payload_type, -1, "RED payload type");
static int RedPayloadType() {
  return static_cast<int>(FLAGS_red_payload_type);
}
static const bool red_dummy =
    google::RegisterFlagValidator(&FLAGS_red_payload_type,
                                  &ValidateOptionalPayloadType);

// Flag for ULPFEC payload type.
DEFINE_int32(fec_payload_type, -1, "ULPFEC payload type");
static int FecPayloadType() {
  return static_cast<int>(FLAGS_fec_payload_type);
}
static const bool fec_dummy =
    google::RegisterFlagValidator(&FLAGS_fec_payload_type,
                                  &ValidateOptionalPayloadType);

// Flag for abs-send-time id.
static bool ValidateRtpHeaderExtensionId(const char* flagname,
                                         int32_t extension_id) {
  return extension_id >= -1 || extension_id < 15;
}
DEFINE_int32(abs_send_time_id, -1, "RTP extension ID for abs-send-time");
static int AbsSendTimeId() { return static_cast<int>(FLAGS_abs_send_time_id); }
static const bool abs_send_time_dummy =
    google::RegisterFlagValidator(&FLAGS_abs_send_time_id,
                                  &ValidateRtpHeaderExtensionId);

// Flag for transmission-offset id.
DEFINE_int32(transmission_offset_id,
             -1,
             "RTP extension ID for transmission-offset");
static int TransmissionOffsetId() {
  return static_cast<int>(FLAGS_transmission_offset_id);
}
static const bool timestamp_offset_dummy =
    google::RegisterFlagValidator(&FLAGS_transmission_offset_id,
                                  &ValidateRtpHeaderExtensionId);

// Flag for rtpdump input file.
bool ValidateInputFilenameNotEmpty(const char* flagname,
                                   const std::string& string) {
  return !string.empty();
}

DEFINE_string(input_file, "", "input file");
static std::string InputFile() {
  return static_cast<std::string>(FLAGS_input_file);
}
static const bool input_file_dummy =
    google::RegisterFlagValidator(&FLAGS_input_file,
                                  &ValidateInputFilenameNotEmpty);

// Flag for raw output files.
DEFINE_string(out_base, "", "Basename (excluding .yuv) for raw output");
static std::string OutBase() {
  return static_cast<std::string>(FLAGS_out_base);
}

DEFINE_string(decoder_bitstream_filename, "", "Decoder bitstream output file");
static std::string DecoderBitstreamFilename() {
  return static_cast<std::string>(FLAGS_decoder_bitstream_filename);
}

// Flag for video codec.
DEFINE_string(codec, "VP8", "Video codec");
static std::string Codec() { return static_cast<std::string>(FLAGS_codec); }

}  // namespace flags

static const uint32_t kReceiverLocalSsrc = 0x123456;

class FileRenderPassthrough : public rtc::VideoSinkInterface<VideoFrame> {
 public:
  FileRenderPassthrough(const std::string& basename,
                        rtc::VideoSinkInterface<VideoFrame>* renderer)
      : basename_(basename),
        renderer_(renderer),
        file_(nullptr),
        count_(0),
        last_width_(0),
        last_height_(0) {}

  ~FileRenderPassthrough() {
    if (file_)
      fclose(file_);
  }

 private:
  void OnFrame(const VideoFrame& video_frame) override {
    if (renderer_)
      renderer_->OnFrame(video_frame);
    if (basename_.empty())
      return;
    if (last_width_ != video_frame.width() ||
        last_height_ != video_frame.height()) {
      if (file_)
        fclose(file_);
      std::stringstream filename;
      filename << basename_;
      if (++count_ > 1)
        filename << '-' << count_;
      filename << '_' << video_frame.width() << 'x' << video_frame.height()
               << ".yuv";
      file_ = fopen(filename.str().c_str(), "wb");
      if (!file_) {
        fprintf(stderr,
                "Couldn't open file for writing: %s\n",
                filename.str().c_str());
      }
    }
    last_width_ = video_frame.width();
    last_height_ = video_frame.height();
    if (!file_)
      return;
    PrintVideoFrame(video_frame, file_);
  }

  const std::string basename_;
  rtc::VideoSinkInterface<VideoFrame>* const renderer_;
  FILE* file_;
  size_t count_;
  int last_width_;
  int last_height_;
};

class DecoderBitstreamFileWriter : public EncodedFrameObserver {
 public:
  explicit DecoderBitstreamFileWriter(const char* filename)
      : file_(fopen(filename, "wb")) {
    RTC_DCHECK(file_);
  }
  ~DecoderBitstreamFileWriter() { fclose(file_); }

  virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
    fwrite(encoded_frame.data_, 1, encoded_frame.length_, file_);
  }

 private:
  FILE* file_;
};

void RtpReplay() {
  std::unique_ptr<test::VideoRenderer> playback_video(
      test::VideoRenderer::Create("Playback Video", 640, 480));
  FileRenderPassthrough file_passthrough(flags::OutBase(),
                                         playback_video.get());

  webrtc::RtcEventLogNullImpl event_log;
  std::unique_ptr<Call> call(Call::Create(Call::Config(&event_log)));

  test::NullTransport transport;
  VideoReceiveStream::Config receive_config(&transport);
  receive_config.rtp.remote_ssrc = flags::Ssrc();
  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
  receive_config.rtp.ulpfec.ulpfec_payload_type = flags::FecPayloadType();
  receive_config.rtp.ulpfec.red_payload_type = flags::RedPayloadType();
  receive_config.rtp.nack.rtp_history_ms = 1000;
  if (flags::TransmissionOffsetId() != -1) {
    receive_config.rtp.extensions.push_back(RtpExtension(
        RtpExtension::kTimestampOffsetUri, flags::TransmissionOffsetId()));
  }
  if (flags::AbsSendTimeId() != -1) {
    receive_config.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAbsSendTimeUri, flags::AbsSendTimeId()));
  }
  receive_config.renderer = &file_passthrough;

  VideoSendStream::Config::EncoderSettings encoder_settings;
  encoder_settings.payload_name = flags::Codec();
  encoder_settings.payload_type = flags::PayloadType();
  VideoReceiveStream::Decoder decoder;
  std::unique_ptr<DecoderBitstreamFileWriter> bitstream_writer;
  if (!flags::DecoderBitstreamFilename().empty()) {
    bitstream_writer.reset(new DecoderBitstreamFileWriter(
        flags::DecoderBitstreamFilename().c_str()));
    receive_config.pre_decode_callback = bitstream_writer.get();
  }
  decoder = test::CreateMatchingDecoder(encoder_settings);
  if (!flags::DecoderBitstreamFilename().empty()) {
    // Replace with a null decoder if we're writing the bitstream to a file
    // instead.
    delete decoder.decoder;
    decoder.decoder = new test::FakeNullDecoder();
  }
  receive_config.decoders.push_back(decoder);

  VideoReceiveStream* receive_stream =
      call->CreateVideoReceiveStream(std::move(receive_config));

  std::unique_ptr<test::RtpFileReader> rtp_reader(test::RtpFileReader::Create(
      test::RtpFileReader::kRtpDump, flags::InputFile()));
  if (!rtp_reader) {
    rtp_reader.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap,
                                                 flags::InputFile()));
    if (!rtp_reader) {
      fprintf(stderr,
              "Couldn't open input file as either a rtpdump or .pcap. Note "
              "that .pcapng is not supported.\nTrying to interpret the file as "
              "length/packet interleaved.\n");
      rtp_reader.reset(test::RtpFileReader::Create(
          test::RtpFileReader::kLengthPacketInterleaved, flags::InputFile()));
      if (!rtp_reader) {
        fprintf(stderr,
                "Unable to open input file with any supported format\n");
        return;
      }
    }
  }
  receive_stream->Start();

  uint32_t last_time_ms = 0;
  int num_packets = 0;
  std::map<uint32_t, int> unknown_packets;
  while (true) {
    test::RtpPacket packet;
    if (!rtp_reader->NextPacket(&packet))
      break;
    ++num_packets;
    switch (call->Receiver()->DeliverPacket(webrtc::MediaType::ANY, packet.data,
                                            packet.length, PacketTime())) {
      case PacketReceiver::DELIVERY_OK:
        break;
      case PacketReceiver::DELIVERY_UNKNOWN_SSRC: {
        RTPHeader header;
        std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
        parser->Parse(packet.data, packet.length, &header);
        if (unknown_packets[header.ssrc] == 0)
          fprintf(stderr, "Unknown SSRC: %u!\n", header.ssrc);
        ++unknown_packets[header.ssrc];
        break;
      }
      case PacketReceiver::DELIVERY_PACKET_ERROR:
        fprintf(stderr, "Packet error, corrupt packets or incorrect setup?\n");
        break;
    }
    if (last_time_ms != 0 && last_time_ms != packet.time_ms) {
      SleepMs(packet.time_ms - last_time_ms);
    }
    last_time_ms = packet.time_ms;
  }
  fprintf(stderr, "num_packets: %d\n", num_packets);

  for (std::map<uint32_t, int>::const_iterator it = unknown_packets.begin();
       it != unknown_packets.end();
       ++it) {
    fprintf(
        stderr, "Packets for unknown ssrc '%u': %d\n", it->first, it->second);
  }

  call->DestroyVideoReceiveStream(receive_stream);

  delete decoder.decoder;
}
}  // namespace webrtc

int main(int argc, char* argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  google::ParseCommandLineFlags(&argc, &argv, true);

  webrtc::test::RunTest(webrtc::RtpReplay);
  return 0;
}
<commit_msg>replay: output rtp header elements for errors<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdio.h>

#include <map>
#include <memory>
#include <sstream>

#include "gflags/gflags.h"
#include "webrtc/base/checks.h"
#include "webrtc/call/call.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/system_wrappers/include/sleep.h"
#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/null_transport.h"
#include "webrtc/test/rtp_file_reader.h"
#include "webrtc/test/run_loop.h"
#include "webrtc/test/run_test.h"
#include "webrtc/test/video_capturer.h"
#include "webrtc/test/video_renderer.h"
#include "webrtc/typedefs.h"
#include "webrtc/video_decoder.h"

namespace webrtc {
namespace flags {

// TODO(pbos): Multiple receivers.

// Flag for payload type.
static bool ValidatePayloadType(const char* flagname, int32_t payload_type) {
  return payload_type > 0 && payload_type <= 127;
}
DEFINE_int32(payload_type, 0, "Payload type");
static int PayloadType() { return static_cast<int>(FLAGS_payload_type); }
static const bool payload_dummy =
    google::RegisterFlagValidator(&FLAGS_payload_type, &ValidatePayloadType);

// Flag for SSRC.
static bool ValidateSsrc(const char* flagname, uint64_t ssrc) {
  return ssrc > 0 && ssrc <= 0xFFFFFFFFu;
}

DEFINE_uint64(ssrc, 0, "Incoming SSRC");
static uint32_t Ssrc() { return static_cast<uint32_t>(FLAGS_ssrc); }
static const bool ssrc_dummy =
    google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrc);

static bool ValidateOptionalPayloadType(const char* flagname,
                                        int32_t payload_type) {
  return payload_type == -1 || ValidatePayloadType(flagname, payload_type);
}

// Flag for RED payload type.
DEFINE_int32(red_payload_type, -1, "RED payload type");
static int RedPayloadType() {
  return static_cast<int>(FLAGS_red_payload_type);
}
static const bool red_dummy =
    google::RegisterFlagValidator(&FLAGS_red_payload_type,
                                  &ValidateOptionalPayloadType);

// Flag for ULPFEC payload type.
DEFINE_int32(fec_payload_type, -1, "ULPFEC payload type");
static int FecPayloadType() {
  return static_cast<int>(FLAGS_fec_payload_type);
}
static const bool fec_dummy =
    google::RegisterFlagValidator(&FLAGS_fec_payload_type,
                                  &ValidateOptionalPayloadType);

// Flag for abs-send-time id.
static bool ValidateRtpHeaderExtensionId(const char* flagname,
                                         int32_t extension_id) {
  return extension_id >= -1 || extension_id < 15;
}
DEFINE_int32(abs_send_time_id, -1, "RTP extension ID for abs-send-time");
static int AbsSendTimeId() { return static_cast<int>(FLAGS_abs_send_time_id); }
static const bool abs_send_time_dummy =
    google::RegisterFlagValidator(&FLAGS_abs_send_time_id,
                                  &ValidateRtpHeaderExtensionId);

// Flag for transmission-offset id.
DEFINE_int32(transmission_offset_id,
             -1,
             "RTP extension ID for transmission-offset");
static int TransmissionOffsetId() {
  return static_cast<int>(FLAGS_transmission_offset_id);
}
static const bool timestamp_offset_dummy =
    google::RegisterFlagValidator(&FLAGS_transmission_offset_id,
                                  &ValidateRtpHeaderExtensionId);

// Flag for rtpdump input file.
bool ValidateInputFilenameNotEmpty(const char* flagname,
                                   const std::string& string) {
  return !string.empty();
}

DEFINE_string(input_file, "", "input file");
static std::string InputFile() {
  return static_cast<std::string>(FLAGS_input_file);
}
static const bool input_file_dummy =
    google::RegisterFlagValidator(&FLAGS_input_file,
                                  &ValidateInputFilenameNotEmpty);

// Flag for raw output files.
DEFINE_string(out_base, "", "Basename (excluding .yuv) for raw output");
static std::string OutBase() {
  return static_cast<std::string>(FLAGS_out_base);
}

DEFINE_string(decoder_bitstream_filename, "", "Decoder bitstream output file");
static std::string DecoderBitstreamFilename() {
  return static_cast<std::string>(FLAGS_decoder_bitstream_filename);
}

// Flag for video codec.
DEFINE_string(codec, "VP8", "Video codec");
static std::string Codec() { return static_cast<std::string>(FLAGS_codec); }

}  // namespace flags

static const uint32_t kReceiverLocalSsrc = 0x123456;

class FileRenderPassthrough : public rtc::VideoSinkInterface<VideoFrame> {
 public:
  FileRenderPassthrough(const std::string& basename,
                        rtc::VideoSinkInterface<VideoFrame>* renderer)
      : basename_(basename),
        renderer_(renderer),
        file_(nullptr),
        count_(0),
        last_width_(0),
        last_height_(0) {}

  ~FileRenderPassthrough() {
    if (file_)
      fclose(file_);
  }

 private:
  void OnFrame(const VideoFrame& video_frame) override {
    if (renderer_)
      renderer_->OnFrame(video_frame);
    if (basename_.empty())
      return;
    if (last_width_ != video_frame.width() ||
        last_height_ != video_frame.height()) {
      if (file_)
        fclose(file_);
      std::stringstream filename;
      filename << basename_;
      if (++count_ > 1)
        filename << '-' << count_;
      filename << '_' << video_frame.width() << 'x' << video_frame.height()
               << ".yuv";
      file_ = fopen(filename.str().c_str(), "wb");
      if (!file_) {
        fprintf(stderr,
                "Couldn't open file for writing: %s\n",
                filename.str().c_str());
      }
    }
    last_width_ = video_frame.width();
    last_height_ = video_frame.height();
    if (!file_)
      return;
    PrintVideoFrame(video_frame, file_);
  }

  const std::string basename_;
  rtc::VideoSinkInterface<VideoFrame>* const renderer_;
  FILE* file_;
  size_t count_;
  int last_width_;
  int last_height_;
};

class DecoderBitstreamFileWriter : public EncodedFrameObserver {
 public:
  explicit DecoderBitstreamFileWriter(const char* filename)
      : file_(fopen(filename, "wb")) {
    RTC_DCHECK(file_);
  }
  ~DecoderBitstreamFileWriter() { fclose(file_); }

  virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
    fwrite(encoded_frame.data_, 1, encoded_frame.length_, file_);
  }

 private:
  FILE* file_;
};

void RtpReplay() {
  std::unique_ptr<test::VideoRenderer> playback_video(
      test::VideoRenderer::Create("Playback Video", 640, 480));
  FileRenderPassthrough file_passthrough(flags::OutBase(),
                                         playback_video.get());

  webrtc::RtcEventLogNullImpl event_log;
  std::unique_ptr<Call> call(Call::Create(Call::Config(&event_log)));

  test::NullTransport transport;
  VideoReceiveStream::Config receive_config(&transport);
  receive_config.rtp.remote_ssrc = flags::Ssrc();
  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
  receive_config.rtp.ulpfec.ulpfec_payload_type = flags::FecPayloadType();
  receive_config.rtp.ulpfec.red_payload_type = flags::RedPayloadType();
  receive_config.rtp.nack.rtp_history_ms = 1000;
  if (flags::TransmissionOffsetId() != -1) {
    receive_config.rtp.extensions.push_back(RtpExtension(
        RtpExtension::kTimestampOffsetUri, flags::TransmissionOffsetId()));
  }
  if (flags::AbsSendTimeId() != -1) {
    receive_config.rtp.extensions.push_back(
        RtpExtension(RtpExtension::kAbsSendTimeUri, flags::AbsSendTimeId()));
  }
  receive_config.renderer = &file_passthrough;

  VideoSendStream::Config::EncoderSettings encoder_settings;
  encoder_settings.payload_name = flags::Codec();
  encoder_settings.payload_type = flags::PayloadType();
  VideoReceiveStream::Decoder decoder;
  std::unique_ptr<DecoderBitstreamFileWriter> bitstream_writer;
  if (!flags::DecoderBitstreamFilename().empty()) {
    bitstream_writer.reset(new DecoderBitstreamFileWriter(
        flags::DecoderBitstreamFilename().c_str()));
    receive_config.pre_decode_callback = bitstream_writer.get();
  }
  decoder = test::CreateMatchingDecoder(encoder_settings);
  if (!flags::DecoderBitstreamFilename().empty()) {
    // Replace with a null decoder if we're writing the bitstream to a file
    // instead.
    delete decoder.decoder;
    decoder.decoder = new test::FakeNullDecoder();
  }
  receive_config.decoders.push_back(decoder);

  VideoReceiveStream* receive_stream =
      call->CreateVideoReceiveStream(std::move(receive_config));

  std::unique_ptr<test::RtpFileReader> rtp_reader(test::RtpFileReader::Create(
      test::RtpFileReader::kRtpDump, flags::InputFile()));
  if (!rtp_reader) {
    rtp_reader.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap,
                                                 flags::InputFile()));
    if (!rtp_reader) {
      fprintf(stderr,
              "Couldn't open input file as either a rtpdump or .pcap. Note "
              "that .pcapng is not supported.\nTrying to interpret the file as "
              "length/packet interleaved.\n");
      rtp_reader.reset(test::RtpFileReader::Create(
          test::RtpFileReader::kLengthPacketInterleaved, flags::InputFile()));
      if (!rtp_reader) {
        fprintf(stderr,
                "Unable to open input file with any supported format\n");
        return;
      }
    }
  }
  receive_stream->Start();

  uint32_t last_time_ms = 0;
  int num_packets = 0;
  std::map<uint32_t, int> unknown_packets;
  while (true) {
    test::RtpPacket packet;
    if (!rtp_reader->NextPacket(&packet))
      break;
    ++num_packets;
    switch (call->Receiver()->DeliverPacket(webrtc::MediaType::ANY, packet.data,
                                            packet.length, PacketTime())) {
      case PacketReceiver::DELIVERY_OK:
        break;
      case PacketReceiver::DELIVERY_UNKNOWN_SSRC: {
        RTPHeader header;
        std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
        parser->Parse(packet.data, packet.length, &header);
        if (unknown_packets[header.ssrc] == 0)
          fprintf(stderr, "Unknown SSRC: %u!\n", header.ssrc);
        ++unknown_packets[header.ssrc];
        break;
      }
      case PacketReceiver::DELIVERY_PACKET_ERROR: {
        fprintf(stderr, "Packet error, corrupt packets or incorrect setup?\n");
        RTPHeader header;
        std::unique_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
        parser->Parse(packet.data, packet.length, &header);
        fprintf(stderr, "Packet len=%ld pt=%u seq=%u ts=%u ssrc=0x%8x\n",
            packet.length, header.payloadType, header.sequenceNumber,
            header.timestamp, header.ssrc);
        break;
      }
    }
    if (last_time_ms != 0 && last_time_ms != packet.time_ms) {
      SleepMs(packet.time_ms - last_time_ms);
    }
    last_time_ms = packet.time_ms;
  }
  fprintf(stderr, "num_packets: %d\n", num_packets);

  for (std::map<uint32_t, int>::const_iterator it = unknown_packets.begin();
       it != unknown_packets.end();
       ++it) {
    fprintf(
        stderr, "Packets for unknown ssrc '%u': %d\n", it->first, it->second);
  }

  call->DestroyVideoReceiveStream(receive_stream);

  delete decoder.decoder;
}
}  // namespace webrtc

int main(int argc, char* argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  google::ParseCommandLineFlags(&argc, &argv, true);

  webrtc::test::RunTest(webrtc::RtpReplay);
  return 0;
}
<|endoftext|>


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

#ifndef MAPNIK_RULE_HPP
#define MAPNIK_RULE_HPP

// mapnik
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/glyph_symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/filter_factory.hpp>
#include <mapnik/expression_string.hpp>

// boost
#include <boost/concept_check.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/variant.hpp>

// stl
#include <string>
#include <vector>

namespace mapnik
{
inline bool operator==(point_symbolizer const& lhs,
                       point_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}
inline bool operator==(line_symbolizer const& lhs,
                       line_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}
inline bool operator==(line_pattern_symbolizer const& lhs,
                       line_pattern_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(polygon_symbolizer const& lhs,
                       polygon_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(polygon_pattern_symbolizer const& lhs,
                       polygon_pattern_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(raster_symbolizer const& lhs,
                       raster_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(text_symbolizer const& lhs,
                       text_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(shield_symbolizer const& lhs,
                       shield_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(building_symbolizer const& lhs,
                       building_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(markers_symbolizer const& lhs,
                       markers_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(glyph_symbolizer const& lhs,
                       glyph_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}
typedef boost::variant<point_symbolizer,
                       line_symbolizer,
                       line_pattern_symbolizer,
                       polygon_symbolizer,
                       polygon_pattern_symbolizer,
                       raster_symbolizer,
                       shield_symbolizer,
                       text_symbolizer,
                       building_symbolizer,
                       markers_symbolizer,
                       glyph_symbolizer> symbolizer;

class rule
{
public:
    typedef std::vector<symbolizer> symbolizers;
private:

    std::string name_;
    double min_scale_;
    double max_scale_;
    symbolizers syms_;
    expression_ptr filter_;
    bool else_filter_;
    bool also_filter_;

    struct deepcopy_symbolizer : public boost::static_visitor<>
    {

        void operator () (markers_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (point_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (polygon_pattern_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (line_pattern_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (raster_symbolizer & sym) const
        {
            raster_colorizer_ptr old_colorizer = sym.get_colorizer();
            raster_colorizer_ptr new_colorizer = raster_colorizer_ptr();
            new_colorizer->set_stops(old_colorizer->get_stops());
            new_colorizer->set_default_mode(old_colorizer->get_default_mode());
            new_colorizer->set_default_color(old_colorizer->get_default_color());
            new_colorizer->set_epsilon(old_colorizer->get_epsilon());
            sym.set_colorizer(new_colorizer);
        }

        void operator () (text_symbolizer & sym) const
        {
            copy_text_ptr(sym);
        }

        void operator () (shield_symbolizer & sym) const
        {
            copy_path_ptr(sym);
            copy_text_ptr(sym);
        }

        void operator () (building_symbolizer & sym) const
        {
            copy_height_ptr(sym);
        }

        template <typename T> void operator () (T &sym) const
        {
            boost::ignore_unused_variable_warning(sym);
        }

    private:
        template <class T>
        void copy_path_ptr(T & sym) const
        {
            std::string path = path_processor_type::to_string(*sym.get_filename());
            sym.set_filename( parse_path(path) );
        }

        template <class T>
        void copy_text_ptr(T & sym) const
        {
            std::string name = to_expression_string(*sym.get_name());
            sym.set_name( parse_expression(name) );

            // FIXME - orientation doesn't appear to be initialized in constructor?
            //std::string orientation = to_expression_string(*sym->get_orientation());
            //sym->set_orientation( parse_expression(orientation) );

            float text_size = sym.get_text_size();
            position displace = sym.get_displacement();
            vertical_alignment_e valign = sym.get_vertical_alignment();
            horizontal_alignment_e halign = sym.get_horizontal_alignment();
            justify_alignment_e jalign = sym.get_justify_alignment();

            text_placements_ptr placements = text_placements_ptr(boost::make_shared<text_placements_dummy>());
            sym.set_placement_options( placements );
            sym.set_text_size(text_size);
            sym.set_displacement(displace);
            sym.set_vertical_alignment(valign);
            sym.set_horizontal_alignment(halign);
            sym.set_justify_alignment(jalign);
        }

        template <class T>
        void copy_height_ptr(T & sym) const
        {
            std::string height_expr = to_expression_string(sym.height());
            sym.set_height(parse_expression(height_expr,"utf8"));
        }
    };

public:
    rule()
        : name_(),
          min_scale_(0),
          max_scale_(std::numeric_limits<double>::infinity()),
          syms_(),
          filter_(boost::make_shared<mapnik::expr_node>(true)),
          else_filter_(false),
          also_filter_(false) {}

    rule(const std::string& name,
         double min_scale_denominator=0,
         double max_scale_denominator=std::numeric_limits<double>::infinity())
        : name_(name),
          min_scale_(min_scale_denominator),
          max_scale_(max_scale_denominator),
          syms_(),
          filter_(boost::make_shared<mapnik::expr_node>(true)),
          else_filter_(false),
          also_filter_(false)  {}

    rule(const rule& rhs, bool deep_copy = false)
        : name_(rhs.name_),
          min_scale_(rhs.min_scale_),
          max_scale_(rhs.max_scale_),
          syms_(rhs.syms_),
          filter_(rhs.filter_),
          else_filter_(rhs.else_filter_),
          also_filter_(rhs.also_filter_)
    {
        if (deep_copy) {

            std::string expr = to_expression_string(rhs.filter_);
            filter_ = parse_expression(expr,"utf8");

            symbolizers::iterator it  = syms_.begin(),
                                  end = syms_.end();

            // FIXME - metawriter_ptr?

            for(; it != end; ++it)
            {
                boost::apply_visitor(deepcopy_symbolizer(),*it);
            }
        }
    }

    rule& operator=(rule const& rhs)
    {
        rule tmp(rhs);
        swap(tmp);
        return *this;
    }
    bool operator==(rule const& other)
    {
        return  (this == &other);
    }

    void set_max_scale(double scale)
    {
        max_scale_=scale;
    }

    double get_max_scale() const
    {
        return max_scale_;
    }

    void set_min_scale(double scale)
    {
        min_scale_=scale;
    }

    double get_min_scale() const
    {
        return min_scale_;
    }

    void set_name(std::string const& name)
    {
        name_=name;
    }

    std::string const& get_name() const
    {
        return name_;
    }

    void append(const symbolizer& sym)
    {
        syms_.push_back(sym);
    }

    void remove_at(size_t index)
    {
        if (index < syms_.size())
        {
            syms_.erase(syms_.begin()+index);
        }
    }

    const symbolizers& get_symbolizers() const
    {
        return syms_;
    }

    symbolizers::const_iterator begin() const
    {
        return syms_.begin();
    }

    symbolizers::const_iterator end() const
    {
        return syms_.end();
    }

    symbolizers::iterator begin()
    {
        return syms_.begin();
    }

    symbolizers::iterator end()
    {
        return syms_.end();
    }

    void set_filter(const expression_ptr& filter)
    {
        filter_=filter;
    }

    expression_ptr const& get_filter() const
    {
        return filter_;
    }

    void set_else(bool else_filter)
    {
        else_filter_=else_filter;
    }

    bool has_else_filter() const
    {
        return else_filter_;
    }

    void set_also(bool also_filter)
    {
        also_filter_=also_filter;
    }

    bool has_also_filter() const
    {
        return also_filter_;
    }

    bool active(double scale) const
    {
        return ( scale >= min_scale_ - 1e-6 && scale < max_scale_ + 1e-6);
    }

private:

    void swap(rule& rhs) throw()
    {
        name_=rhs.name_;
        min_scale_=rhs.min_scale_;
        max_scale_=rhs.max_scale_;
        syms_=rhs.syms_;
        filter_=rhs.filter_;
        else_filter_=rhs.else_filter_;
        also_filter_=rhs.also_filter_;
    }
};

}

#endif // MAPNIK_RULE_HPP
<commit_msg>copy filter expressions fix use const_iterator<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RULE_HPP
#define MAPNIK_RULE_HPP

// mapnik
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/glyph_symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/filter_factory.hpp>
#include <mapnik/expression_string.hpp>

// boost
#include <boost/concept_check.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/variant.hpp>

// stl
#include <string>
#include <vector>

namespace mapnik
{
inline bool operator==(point_symbolizer const& lhs,
                       point_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}
inline bool operator==(line_symbolizer const& lhs,
                       line_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}
inline bool operator==(line_pattern_symbolizer const& lhs,
                       line_pattern_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(polygon_symbolizer const& lhs,
                       polygon_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(polygon_pattern_symbolizer const& lhs,
                       polygon_pattern_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(raster_symbolizer const& lhs,
                       raster_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(text_symbolizer const& lhs,
                       text_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(shield_symbolizer const& lhs,
                       shield_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(building_symbolizer const& lhs,
                       building_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(markers_symbolizer const& lhs,
                       markers_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}

inline bool operator==(glyph_symbolizer const& lhs,
                       glyph_symbolizer const& rhs)
{
    return (&lhs == &rhs);
}
typedef boost::variant<point_symbolizer,
                       line_symbolizer,
                       line_pattern_symbolizer,
                       polygon_symbolizer,
                       polygon_pattern_symbolizer,
                       raster_symbolizer,
                       shield_symbolizer,
                       text_symbolizer,
                       building_symbolizer,
                       markers_symbolizer,
                       glyph_symbolizer> symbolizer;

class rule
{
public:
    typedef std::vector<symbolizer> symbolizers;
private:

    std::string name_;
    double min_scale_;
    double max_scale_;
    symbolizers syms_;
    expression_ptr filter_;
    bool else_filter_;
    bool also_filter_;

    struct deepcopy_symbolizer : public boost::static_visitor<>
    {

        void operator () (markers_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (point_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (polygon_pattern_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (line_pattern_symbolizer & sym) const
        {
            copy_path_ptr(sym);
        }

        void operator () (raster_symbolizer & sym) const
        {
            raster_colorizer_ptr old_colorizer = sym.get_colorizer();
            raster_colorizer_ptr new_colorizer = raster_colorizer_ptr();
            new_colorizer->set_stops(old_colorizer->get_stops());
            new_colorizer->set_default_mode(old_colorizer->get_default_mode());
            new_colorizer->set_default_color(old_colorizer->get_default_color());
            new_colorizer->set_epsilon(old_colorizer->get_epsilon());
            sym.set_colorizer(new_colorizer);
        }

        void operator () (text_symbolizer & sym) const
        {
            copy_text_ptr(sym);
        }

        void operator () (shield_symbolizer & sym) const
        {
            copy_path_ptr(sym);
            copy_text_ptr(sym);
        }

        void operator () (building_symbolizer & sym) const
        {
            copy_height_ptr(sym);
        }

        template <typename T> void operator () (T &sym) const
        {
            boost::ignore_unused_variable_warning(sym);
        }

    private:
        template <class T>
        void copy_path_ptr(T & sym) const
        {
            std::string path = path_processor_type::to_string(*sym.get_filename());
            sym.set_filename( parse_path(path) );
        }

        template <class T>
        void copy_text_ptr(T & sym) const
        {
            std::string name = to_expression_string(*sym.get_name());
            sym.set_name( parse_expression(name) );

            // FIXME - orientation doesn't appear to be initialized in constructor?
            //std::string orientation = to_expression_string(*sym->get_orientation());
            //sym->set_orientation( parse_expression(orientation) );

            float text_size = sym.get_text_size();
            position displace = sym.get_displacement();
            vertical_alignment_e valign = sym.get_vertical_alignment();
            horizontal_alignment_e halign = sym.get_horizontal_alignment();
            justify_alignment_e jalign = sym.get_justify_alignment();

            text_placements_ptr placements = text_placements_ptr(boost::make_shared<text_placements_dummy>());
            sym.set_placement_options( placements );
            sym.set_text_size(text_size);
            sym.set_displacement(displace);
            sym.set_vertical_alignment(valign);
            sym.set_horizontal_alignment(halign);
            sym.set_justify_alignment(jalign);
        }

        template <class T>
        void copy_height_ptr(T & sym) const
        {
            std::string height_expr = to_expression_string(sym.height());
            sym.set_height(parse_expression(height_expr,"utf8"));
        }
    };

public:
    rule()
        : name_(),
          min_scale_(0),
          max_scale_(std::numeric_limits<double>::infinity()),
          syms_(),
          filter_(boost::make_shared<mapnik::expr_node>(true)),
          else_filter_(false),
          also_filter_(false) {}

    rule(const std::string& name,
         double min_scale_denominator=0,
         double max_scale_denominator=std::numeric_limits<double>::infinity())
        : name_(name),
          min_scale_(min_scale_denominator),
          max_scale_(max_scale_denominator),
          syms_(),
          filter_(boost::make_shared<mapnik::expr_node>(true)),
          else_filter_(false),
          also_filter_(false)  {}

    rule(const rule& rhs, bool deep_copy = false)
        : name_(rhs.name_),
          min_scale_(rhs.min_scale_),
          max_scale_(rhs.max_scale_),
          syms_(rhs.syms_),
          filter_(rhs.filter_),
          else_filter_(rhs.else_filter_),
          also_filter_(rhs.also_filter_)
    {
        if (deep_copy) {

            std::string expr = to_expression_string(*filter_);
            filter_ = parse_expression(expr,"utf8");
            symbolizers::const_iterator it  = syms_.begin();
            symbolizers::const_iterator end = syms_.end();

            // FIXME - metawriter_ptr?

            for(; it != end; ++it)
            {
                boost::apply_visitor(deepcopy_symbolizer(),*it);
            }
        }
    }

    rule& operator=(rule const& rhs)
    {
        rule tmp(rhs);
        swap(tmp);
        return *this;
    }
    bool operator==(rule const& other)
    {
        return  (this == &other);
    }

    void set_max_scale(double scale)
    {
        max_scale_=scale;
    }

    double get_max_scale() const
    {
        return max_scale_;
    }

    void set_min_scale(double scale)
    {
        min_scale_=scale;
    }

    double get_min_scale() const
    {
        return min_scale_;
    }

    void set_name(std::string const& name)
    {
        name_=name;
    }

    std::string const& get_name() const
    {
        return name_;
    }

    void append(const symbolizer& sym)
    {
        syms_.push_back(sym);
    }

    void remove_at(size_t index)
    {
        if (index < syms_.size())
        {
            syms_.erase(syms_.begin()+index);
        }
    }

    const symbolizers& get_symbolizers() const
    {
        return syms_;
    }

    symbolizers::const_iterator begin() const
    {
        return syms_.begin();
    }

    symbolizers::const_iterator end() const
    {
        return syms_.end();
    }

    symbolizers::iterator begin()
    {
        return syms_.begin();
    }

    symbolizers::iterator end()
    {
        return syms_.end();
    }

    void set_filter(const expression_ptr& filter)
    {
        filter_=filter;
    }

    expression_ptr const& get_filter() const
    {
        return filter_;
    }

    void set_else(bool else_filter)
    {
        else_filter_=else_filter;
    }

    bool has_else_filter() const
    {
        return else_filter_;
    }

    void set_also(bool also_filter)
    {
        also_filter_=also_filter;
    }

    bool has_also_filter() const
    {
        return also_filter_;
    }

    bool active(double scale) const
    {
        return ( scale >= min_scale_ - 1e-6 && scale < max_scale_ + 1e-6);
    }

private:

    void swap(rule& rhs) throw()
    {
        name_=rhs.name_;
        min_scale_=rhs.min_scale_;
        max_scale_=rhs.max_scale_;
        syms_=rhs.syms_;
        filter_=rhs.filter_;
        else_filter_=rhs.else_filter_;
        also_filter_=rhs.also_filter_;
    }
};

}

#endif // MAPNIK_RULE_HPP
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2009-2012
  \file      main.cpp
  \author      (rdo@rk9.bmstu.ru)
  \date      01.05.2012
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#define BOOST_TEST_MODULE RDOCalc_Test
#include <boost/test/included/unit_test.hpp>
#include <boost/tuple/tuple.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_runtime.h"
#include "simulator/runtime/calc/procedural/calc_const.h"
#include "simulator/runtime/calc/procedural/calc_statement.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

BOOST_AUTO_TEST_SUITE(RDOCalc_Test)

static const double const1 = 10.5;
static const double const2 = 11.4;

typedef  boost::tuple<LPRDORuntime, LPRDOCalc, LPRDOCalc>  CalcPair;

template <class F>
RDOValue calc(F binder, CREF(CalcPair) calcPair)
{
	BOOST_CHECK(calcPair.get<0>());
	BOOST_CHECK(calcPair.get<1>());
	BOOST_CHECK(calcPair.get<2>());

	return binder.operator()(calcPair.get<1>()->calcValue(calcPair.get<0>()), calcPair.get<2>()->calcValue(calcPair.get<0>()));
}

CalcPair prepair()
{
	LPRDORuntime pRuntime = rdo::Factory<RDORuntime>::create();
	BOOST_CHECK(pRuntime);

	LPRDOCalc pLeft = rdo::Factory<RDOCalcConst>::create(RDOValue(const1));
	BOOST_CHECK(pLeft);

	LPRDOCalc pRight = rdo::Factory<RDOCalcConst>::create(RDOValue(const2));
	BOOST_CHECK(pRight);

	return CalcPair(pRuntime, pLeft, pRight);
}

BOOST_AUTO_TEST_CASE(RDOCalc_MultDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator*, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 * const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_DivDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator/, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 / const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_PlusDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator+, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 + const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_MinusDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator-, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 - const2);
}

struct RecursCalcSimulator
{
	struct Param
	{
		Param(int value)
			: m_value(value)
		{}

		//! ,    int,   REF(int)
		int value()
		{
			return m_value;
		}

		Param& dec()
		{
			--m_value;
			return *this;
		}

	private:
		int m_value;
	};

	int fun1(Param& param)
	{
		if (param.value() == 1)
		{
			return 1;
		}
		else
		{
			return fun1(param.dec()) * param.value();
		}
	}

	int fun2(Param& param)
	{
		if (param.value() == 1)
		{
			return 1;
		}
		else
		{
			return param.value() * fun2(param.dec());
		}
	}
};

BOOST_AUTO_TEST_CASE(RDOCalc_Recurs)
{
	RecursCalcSimulator calc1;
	RecursCalcSimulator calc2;
	RecursCalcSimulator::Param param1(5);
	RecursCalcSimulator::Param param2(5);

	int result1 = calc1.fun1(param1);
	int result2 = calc2.fun2(param2);
	BOOST_CHECK(result1 == 1);
	BOOST_CHECK(result2 == 120);
}

BOOST_AUTO_TEST_SUITE_END() // RDOCalc_Test

CLOSE_RDO_RUNTIME_NAMESPACE
<commit_msg> - форматирование<commit_after>/*!
  \copyright (c) RDO-Team, 2009-2012
  \file      main.cpp
  \author      (rdo@rk9.bmstu.ru)
  \date      01.05.2012
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#define BOOST_TEST_MODULE RDOCalc_Test
#include <boost/test/included/unit_test.hpp>
#include <boost/tuple/tuple.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_runtime.h"
#include "simulator/runtime/calc/procedural/calc_const.h"
#include "simulator/runtime/calc/procedural/calc_statement.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

BOOST_AUTO_TEST_SUITE(RDOCalc_Test)

static const double const1 = 10.5;
static const double const2 = 11.4;

typedef  boost::tuple<LPRDORuntime, LPRDOCalc, LPRDOCalc>  CalcPair;

template <class F>
RDOValue calc(F binder, CREF(CalcPair) calcPair)
{
	BOOST_CHECK(calcPair.get<0>());
	BOOST_CHECK(calcPair.get<1>());
	BOOST_CHECK(calcPair.get<2>());

	return binder.operator()(calcPair.get<1>()->calcValue(calcPair.get<0>()), calcPair.get<2>()->calcValue(calcPair.get<0>()));
}

CalcPair prepair()
{
	LPRDORuntime pRuntime = rdo::Factory<RDORuntime>::create();
	BOOST_CHECK(pRuntime);

	LPRDOCalc pLeft = rdo::Factory<RDOCalcConst>::create(RDOValue(const1));
	BOOST_CHECK(pLeft);

	LPRDOCalc pRight = rdo::Factory<RDOCalcConst>::create(RDOValue(const2));
	BOOST_CHECK(pRight);

	return CalcPair(pRuntime, pLeft, pRight);
}

BOOST_AUTO_TEST_CASE(RDOCalc_MultDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator*, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 * const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_DivDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator/, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 / const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_PlusDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator+, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 + const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_MinusDouble)
{
	RDOValue result = calc(boost::bind(&RDOValue::operator-, _1, _2), prepair());
	BOOST_CHECK(result.getDouble() == const1 - const2);
}

BOOST_AUTO_TEST_CASE(RDOCalc_RecursSimulator)
{
	struct RecursCalcSimulator
	{
		struct Param
		{
			Param(int value)
				: m_value(value)
			{}

			//! ,    int,   int&
			//!       1
			//!   1  120
			int value()
			{
				return m_value;
			}

			Param& dec()
			{
				--m_value;
				return *this;
			}

		private:
			int m_value;
		};

		int funError(Param& param)
		{
			if (param.value() == 1)
			{
				return 1;
			}
			else
			{
				return funError(param.dec()) * param.value();
			}
		}

		int funOk(Param& param)
		{
			if (param.value() == 1)
			{
				return 1;
			}
			else
			{
				return param.value() * funOk(param.dec());
			}
		}
	};

	RecursCalcSimulator calc1;
	RecursCalcSimulator calc2;
	RecursCalcSimulator::Param param1(5);
	RecursCalcSimulator::Param param2(5);

	int resultError = calc1.funError(param1);
	int resultOk    = calc2.funOk   (param2);
	BOOST_CHECK(resultError == 1);
	BOOST_CHECK(resultOk    == 120);
}

BOOST_AUTO_TEST_SUITE_END() // RDOCalc_Test

CLOSE_RDO_RUNTIME_NAMESPACE
<|endoftext|>


<commit_before>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <deque>
#include <cassert>
#include <functional>
#include <iostream>
#include <iterator>

#include <boost/array.hpp>
#include <boost/container/set.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>

namespace rank_filter
{

template<class I1,
         class I2>
inline void lineRankOrderFilter1D(const I1& src_begin, const I1& src_end,
        I2& dest_begin, I2& dest_end,
        size_t half_length, double rank)
{
    // Types in use.
    typedef typename std::iterator_traits<I1>::value_type T1;
    typedef typename std::iterator_traits<I2>::value_type T2;

    // Establish common types to work with source and destination values.
    BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
    typedef T1 T;

    // Define container types that will be used.
    typedef boost::container::multiset< T,
            std::less<T>,
            boost::container::node_allocator<T>,
            boost::container::tree_assoc_options< boost::container::tree_type<boost::container::scapegoat_tree> >::type> multiset;
    typedef std::deque< typename multiset::iterator > deque;

    // Precompute some window lengths.
    const size_t half_length_add_1 = half_length + 1;
    const size_t length_sub_1 = 2 * half_length;
    const size_t length = length_sub_1 + 1;

    // Ensure the result will fit.
    assert(std::distance(src_begin, src_end) <= std::distance(dest_begin, dest_end));

    // Window length cannot exceed input data with reflection.
    assert(half_length_add_1 <= std::distance(src_begin, src_end));

    // Rank must be in the range 0 to 1.
    assert((0 <= rank) && (rank <= 1));

    // Track values in window both in sorted and sequential order.
    multiset sorted_window;
    deque window_iters(length);

    // Iterators in source and destination
    I1 src_pos = src_begin;
    I1 dest_pos = dest_begin;

    // Get the initial window in sequential order with reflection
    // Insert elements in order to the multiset for sorting.
    // Store all multiset iterators into the deque in sequential order.
    {
        std::deque<T> window_init(half_length_add_1);
        for (size_t j = half_length_add_1; j > 0;)
        {
            window_init[--j] = *(src_pos++);
        }
        for (size_t j = 0; j < half_length; j++)
        {
            window_iters[j] = sorted_window.insert(window_init[j]);
        }
        for (size_t j = half_length; j < length; j++)
        {
            window_iters[j] = sorted_window.insert(window_init.back());
            window_init.pop_back();
        }
    }

    // Window position corresponding to this rank.
    const size_t rank_pos = static_cast<size_t>(boost::math::round(rank * length_sub_1));
    typename multiset::iterator rank_point = sorted_window.begin();
    std::advance(rank_point, rank_pos);

    // Roll window forward one value at a time.
    typename multiset::iterator prev_iter;
    T prev_value;
    T rank_value = *rank_point;
    *dest_pos = rank_value;
    T next_value;
    size_t window_reflect_pos = length_sub_1;
    bool src_not_empty = ( src_pos != src_end );
    while ( src_not_empty || ( window_reflect_pos > 0 ) )
    {
        prev_iter = window_iters.front();
        prev_value = *prev_iter;
        window_iters.pop_front();

        // Determine next value to add to window.
        // Handle special cases like reflection at the end.
        if ( src_not_empty )
        {
            next_value = *(src_pos++);
            src_not_empty = ( src_pos != src_end );
        }
        else
        {
            window_reflect_pos -= 2;
            next_value = *(window_iters[window_reflect_pos]);
        }

        // Remove old value and add new value to the window.
        // Handle special cases where `rank_pos` may have an adjusted position
        // due to where the old and new values are inserted.
        if ( ( rank_value < prev_value ) && ( rank_value <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( rank_value >= prev_value ) && ( rank_value > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;
                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( rank_value < prev_value ) && ( rank_value > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
            rank_point--;
        }
        else if ( ( rank_value >= prev_value ) && ( rank_value <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;
                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;
            }
        }

        // Store rank value in the destination.
        *(++dest_pos) = rank_value = *rank_point;
    }
}

}

namespace std
{
    template <class T, size_t N>
    ostream& operator<<(ostream& out, const boost::array<T, N>& that)
    {
        out << "{ ";
        for (unsigned int i = 0; i < (N - 1); i++)
        {
            out << that[i] << ", ";
        }
        out << that[N - 1] << " }";

        return(out);
    }
}

#endif //__RANK_FILTER__
<commit_msg>Use prefix increment with src and dest iterators<commit_after>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <deque>
#include <cassert>
#include <functional>
#include <iostream>
#include <iterator>

#include <boost/array.hpp>
#include <boost/container/set.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>

namespace rank_filter
{

template<class I1,
         class I2>
inline void lineRankOrderFilter1D(const I1& src_begin, const I1& src_end,
        I2& dest_begin, I2& dest_end,
        size_t half_length, double rank)
{
    // Types in use.
    typedef typename std::iterator_traits<I1>::value_type T1;
    typedef typename std::iterator_traits<I2>::value_type T2;

    // Establish common types to work with source and destination values.
    BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
    typedef T1 T;

    // Define container types that will be used.
    typedef boost::container::multiset< T,
            std::less<T>,
            boost::container::node_allocator<T>,
            boost::container::tree_assoc_options< boost::container::tree_type<boost::container::scapegoat_tree> >::type> multiset;
    typedef std::deque< typename multiset::iterator > deque;

    // Precompute some window lengths.
    const size_t half_length_add_1 = half_length + 1;
    const size_t length_sub_1 = 2 * half_length;
    const size_t length = length_sub_1 + 1;

    // Ensure the result will fit.
    assert(std::distance(src_begin, src_end) <= std::distance(dest_begin, dest_end));

    // Window length cannot exceed input data with reflection.
    assert(half_length_add_1 <= std::distance(src_begin, src_end));

    // Rank must be in the range 0 to 1.
    assert((0 <= rank) && (rank <= 1));

    // Track values in window both in sorted and sequential order.
    multiset sorted_window;
    deque window_iters(length);

    // Iterators in source and destination
    I1 src_pos = src_begin;
    I1 dest_pos = dest_begin;

    // Get the initial window in sequential order with reflection
    // Insert elements in order to the multiset for sorting.
    // Store all multiset iterators into the deque in sequential order.
    {
        std::deque<T> window_init(half_length_add_1);
        for (size_t j = half_length_add_1; j > 0;)
        {
            window_init[--j] = *src_pos;
            ++src_pos;
        }
        for (size_t j = 0; j < half_length; j++)
        {
            window_iters[j] = sorted_window.insert(window_init[j]);
        }
        for (size_t j = half_length; j < length; j++)
        {
            window_iters[j] = sorted_window.insert(window_init.back());
            window_init.pop_back();
        }
    }

    // Window position corresponding to this rank.
    const size_t rank_pos = static_cast<size_t>(boost::math::round(rank * length_sub_1));
    typename multiset::iterator rank_point = sorted_window.begin();
    std::advance(rank_point, rank_pos);

    // Roll window forward one value at a time.
    typename multiset::iterator prev_iter;
    T prev_value;
    T rank_value = *rank_point;
    *dest_pos = rank_value;
    T next_value;
    size_t window_reflect_pos = length_sub_1;
    bool src_not_empty = ( src_pos != src_end );
    while ( src_not_empty || ( window_reflect_pos > 0 ) )
    {
        prev_iter = window_iters.front();
        prev_value = *prev_iter;
        window_iters.pop_front();

        // Determine next value to add to window.
        // Handle special cases like reflection at the end.
        if ( src_not_empty )
        {
            next_value = *src_pos;
            ++src_pos;
            src_not_empty = ( src_pos != src_end );
        }
        else
        {
            window_reflect_pos -= 2;
            next_value = *(window_iters[window_reflect_pos]);
        }

        // Remove old value and add new value to the window.
        // Handle special cases where `rank_pos` may have an adjusted position
        // due to where the old and new values are inserted.
        if ( ( rank_value < prev_value ) && ( rank_value <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( rank_value >= prev_value ) && ( rank_value > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;
                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( rank_value < prev_value ) && ( rank_value > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
            rank_point--;
        }
        else if ( ( rank_value >= prev_value ) && ( rank_value <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;
                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;
            }
        }

        // Store rank value in the destination.
        *(++dest_pos) = rank_value = *rank_point;
    }
}

}

namespace std
{
    template <class T, size_t N>
    ostream& operator<<(ostream& out, const boost::array<T, N>& that)
    {
        out << "{ ";
        for (unsigned int i = 0; i < (N - 1); i++)
        {
            out << that[i] << ", ";
        }
        out << that[N - 1] << " }";

        return(out);
    }
}

#endif //__RANK_FILTER__
<|endoftext|>


<commit_before>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <deque>
#include <cmath>
#include <cassert>
#include <functional>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>

#include <boost/container/set.hpp>
#include <boost/container/node_allocator.hpp>

#include <vigra/multi_array.hxx>

namespace rank_filter
{

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N == 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned long half_length, double rank, unsigned int axis = 0)
{
    // Will ignore boundaries initially.
    // Then will try adding reflection.

    // Rank must be in the range 0 to 1
    assert((0 <= rank) && (rank <= 1));

    const unsigned long rank_pos = round(rank * (2 * half_length));

    // The position of the
    typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 window_begin(0);

    typedef boost::container::multiset< T1,
            std::less<T1>,
            boost::container::node_allocator<T1>,
            boost::container::tree_assoc_options< boost::container::tree_type<boost::container::scapegoat_tree> >::type> multiset;

    typedef std::deque< typename multiset::iterator > deque;

    multiset sorted_window;
    deque window_iters;

    // Get the initial sorted window.
    // Include the reflection.
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(half_length); j > 0; j--)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(0); j <= half_length; j++)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }

    typename multiset::iterator rank_point = sorted_window.begin();

    for (unsigned long i = 0; i < rank_pos; i++)
    {
        rank_point++;
    }

    typename multiset::iterator prev_iter;
    T1 prev_value;
    T1 next_value;
    while ( window_begin < src.size() )
    {
        dest[window_begin] = *rank_point;

        prev_iter = window_iters.front();
        prev_value = *prev_iter;
        window_iters.pop_front();

        window_begin++;

        if ( window_begin < (src.size() - half_length) )
        {
            next_value = src[window_begin + half_length];
        }
        else
        {
            next_value = *(window_iters[window_iters.size() + 2*src.size() - 2*(window_begin + half_length) - 2]);
        }

        if ( ( *rank_point < prev_value ) && ( *rank_point <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( *rank_point >= prev_value ) && ( *rank_point > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( *rank_point < prev_value ) && ( *rank_point > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));

            rank_point--;
        }
        else if ( ( *rank_point >= prev_value ) && ( *rank_point <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));

                rank_point++;
            }
        }
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N > 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned long half_length, double rank, unsigned int axis = 0)
{
    typename vigra::MultiArrayView<N, T1, S1>::difference_type transposed_axes;

    for (unsigned int i = 0; i < N; i++)
    {
        transposed_axes[i] = i;
    }

    std::swap(transposed_axes[0], transposed_axes[axis]);

    vigra::MultiArray<N, T1> src_transposed(src.transpose(transposed_axes));

    vigra::MultiArrayView<N, T2, S2> dest_transposed(dest.transpose(transposed_axes));

    typename vigra::MultiArrayView<N - 1, T1, S1>::difference_type pos;
    pos = 0;

    bool done = false;
    bool carry = true;
    while (!done)
    {
        lineRankOrderFilterND(src_transposed.bindOuter(pos), dest_transposed.bindOuter(pos), half_length, rank, 0);

        carry = true;
        for (unsigned int i = 0; ( carry && (i < (N - 1)) ); i++)
        {
            if ( (++pos[i]) < src_transposed.shape(i + 1) )
            {
                carry = false;
            }
            else
            {
                pos[i] = 0;
                carry = true;
            }
        }

        done = carry;
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilter(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned long half_length, double rank, unsigned int axis = 0)
{
    lineRankOrderFilterND(src, dest, half_length, rank, axis);
}

}

namespace vigra {

template <unsigned int N, class T, class S, typename std::enable_if<(N == 1), int>::type = 0>
std::ostream& println(std::ostream& out, const vigra::MultiArrayView<N, T, S>& array, unsigned int indent=0)
{
    for (unsigned int i = 0; i < indent; i++)
    {
        out << " ";
    }
    out << "{ ";

    for (unsigned int i = 0; i < (array.shape(0) - 1); i++)
    {
        out << array[i] << ", ";
    }
    out << array[array.shape(0) - 1] << " }";

    return(out);
}

template <unsigned int N, class T, class S, typename std::enable_if<(N > 1), int>::type = 0>
std::ostream& println(std::ostream& out, const vigra::MultiArrayView<N, T, S>& array, unsigned int indent=0)
{
    for (unsigned int i = 0; i < indent; i++)
    {
        out << " ";
    }
    out << "{" << std::endl;

    for (unsigned int i = 0; i < (array.shape(0) - 1); i++)
    {
        println(out, array.bindOuter(i), indent+1);
        out << ", " << std::endl;
    }
    println(out, array.bindOuter(array.shape(0) - 1), indent+1);
    out << std::endl;

    for (unsigned int i = 0; i < indent; i++)
    {
        out << " ";
    }
    out << "}";

    return(out);
}

template <unsigned int N, class T, class S>
std::ostream& operator<<(std::ostream& out, const vigra::MultiArrayView<N, T, S>& array)
{
    return(println(out, array));
}

}

#endif //__RANK_FILTER__
<commit_msg>include/rank_filter.hxx: Drop the `iterator` header as it is unused.<commit_after>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <deque>
#include <cmath>
#include <cassert>
#include <functional>
#include <iostream>
#include <type_traits>
#include <utility>

#include <boost/container/set.hpp>
#include <boost/container/node_allocator.hpp>

#include <vigra/multi_array.hxx>

namespace rank_filter
{

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N == 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned long half_length, double rank, unsigned int axis = 0)
{
    // Will ignore boundaries initially.
    // Then will try adding reflection.

    // Rank must be in the range 0 to 1
    assert((0 <= rank) && (rank <= 1));

    const unsigned long rank_pos = round(rank * (2 * half_length));

    // The position of the
    typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 window_begin(0);

    typedef boost::container::multiset< T1,
            std::less<T1>,
            boost::container::node_allocator<T1>,
            boost::container::tree_assoc_options< boost::container::tree_type<boost::container::scapegoat_tree> >::type> multiset;

    typedef std::deque< typename multiset::iterator > deque;

    multiset sorted_window;
    deque window_iters;

    // Get the initial sorted window.
    // Include the reflection.
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(half_length); j > 0; j--)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(0); j <= half_length; j++)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }

    typename multiset::iterator rank_point = sorted_window.begin();

    for (unsigned long i = 0; i < rank_pos; i++)
    {
        rank_point++;
    }

    typename multiset::iterator prev_iter;
    T1 prev_value;
    T1 next_value;
    while ( window_begin < src.size() )
    {
        dest[window_begin] = *rank_point;

        prev_iter = window_iters.front();
        prev_value = *prev_iter;
        window_iters.pop_front();

        window_begin++;

        if ( window_begin < (src.size() - half_length) )
        {
            next_value = src[window_begin + half_length];
        }
        else
        {
            next_value = *(window_iters[window_iters.size() + 2*src.size() - 2*(window_begin + half_length) - 2]);
        }

        if ( ( *rank_point < prev_value ) && ( *rank_point <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( *rank_point >= prev_value ) && ( *rank_point > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( *rank_point < prev_value ) && ( *rank_point > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));

            rank_point--;
        }
        else if ( ( *rank_point >= prev_value ) && ( *rank_point <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));

                rank_point++;
            }
        }
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N > 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned long half_length, double rank, unsigned int axis = 0)
{
    typename vigra::MultiArrayView<N, T1, S1>::difference_type transposed_axes;

    for (unsigned int i = 0; i < N; i++)
    {
        transposed_axes[i] = i;
    }

    std::swap(transposed_axes[0], transposed_axes[axis]);

    vigra::MultiArray<N, T1> src_transposed(src.transpose(transposed_axes));

    vigra::MultiArrayView<N, T2, S2> dest_transposed(dest.transpose(transposed_axes));

    typename vigra::MultiArrayView<N - 1, T1, S1>::difference_type pos;
    pos = 0;

    bool done = false;
    bool carry = true;
    while (!done)
    {
        lineRankOrderFilterND(src_transposed.bindOuter(pos), dest_transposed.bindOuter(pos), half_length, rank, 0);

        carry = true;
        for (unsigned int i = 0; ( carry && (i < (N - 1)) ); i++)
        {
            if ( (++pos[i]) < src_transposed.shape(i + 1) )
            {
                carry = false;
            }
            else
            {
                pos[i] = 0;
                carry = true;
            }
        }

        done = carry;
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilter(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned long half_length, double rank, unsigned int axis = 0)
{
    lineRankOrderFilterND(src, dest, half_length, rank, axis);
}

}

namespace vigra {

template <unsigned int N, class T, class S, typename std::enable_if<(N == 1), int>::type = 0>
std::ostream& println(std::ostream& out, const vigra::MultiArrayView<N, T, S>& array, unsigned int indent=0)
{
    for (unsigned int i = 0; i < indent; i++)
    {
        out << " ";
    }
    out << "{ ";

    for (unsigned int i = 0; i < (array.shape(0) - 1); i++)
    {
        out << array[i] << ", ";
    }
    out << array[array.shape(0) - 1] << " }";

    return(out);
}

template <unsigned int N, class T, class S, typename std::enable_if<(N > 1), int>::type = 0>
std::ostream& println(std::ostream& out, const vigra::MultiArrayView<N, T, S>& array, unsigned int indent=0)
{
    for (unsigned int i = 0; i < indent; i++)
    {
        out << " ";
    }
    out << "{" << std::endl;

    for (unsigned int i = 0; i < (array.shape(0) - 1); i++)
    {
        println(out, array.bindOuter(i), indent+1);
        out << ", " << std::endl;
    }
    println(out, array.bindOuter(array.shape(0) - 1), indent+1);
    out << std::endl;

    for (unsigned int i = 0; i < indent; i++)
    {
        out << " ";
    }
    out << "}";

    return(out);
}

template <unsigned int N, class T, class S>
std::ostream& operator<<(std::ostream& out, const vigra::MultiArrayView<N, T, S>& array)
{
    return(println(out, array));
}

}

#endif //__RANK_FILTER__
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"
#include "platform/runtime.hpp"
#include "utils/versions.hpp"

std::vector<amd::Context*> g_devices;

namespace hip {

thread_local amd::Context* g_context = nullptr;
thread_local std::stack<amd::Context*> g_ctxtStack;
thread_local hipError_t g_lastError = hipSuccess;
std::once_flag g_ihipInitialized;

std::map<amd::Context*, amd::HostQueue*> g_nullStreams;

void init() {
  if (!amd::Runtime::initialized()) {
    amd::Runtime::init();
  }

  const std::vector<amd::Device*>& devices = amd::Device::getDevices(CL_DEVICE_TYPE_GPU, false);

  for (unsigned int i=0; i<devices.size(); i++) {
    const std::vector<amd::Device*> device(1, devices[i]);
    amd::Context* context = new amd::Context(device, amd::Context::Info());
    if (!context) return;

    if (context && CL_SUCCESS != context->create(nullptr)) {
      context->release();
    } else {
      g_devices.push_back(context);
    }
  }
}

amd::Context* getCurrentContext() {
  return g_context;
}

void setCurrentContext(unsigned int index) {
  assert(index<g_devices.size());
  g_context = g_devices[index];
}

amd::HostQueue* getNullStream() {
  auto stream = g_nullStreams.find(getCurrentContext());
  if (stream == g_nullStreams.end()) {
    amd::Device* device = getCurrentContext()->devices()[0];
    amd::HostQueue* queue = new amd::HostQueue(*hip::getCurrentContext(), *device, 0,
                                               amd::CommandQueue::RealTimeDisabled,
                                               amd::CommandQueue::Priority::Normal);
    g_nullStreams[getCurrentContext()] = queue;
    return queue;
  }
  syncStreams();
  return stream->second;
}

};

using namespace hip;

hipError_t hipInit(unsigned int flags) {
  HIP_INIT_API(flags);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxCreate(hipCtx_t *ctx, unsigned int flags,  hipDevice_t device) {
  HIP_INIT_API(ctx, flags, device);

  if (static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *ctx = reinterpret_cast<hipCtx_t>(g_devices[device]);

  // Increment ref count for device primary context
  g_devices[device]->retain();
  g_ctxtStack.push(g_devices[device]);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxSetCurrent(hipCtx_t ctx) {
  HIP_INIT_API(ctx);

  if (ctx == nullptr) {
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
  } else {
    hip::g_context = reinterpret_cast<amd::Context*>(as_amd(ctx));
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
    g_ctxtStack.push(hip::getCurrentContext());
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(ctx);

  *ctx = reinterpret_cast<hipCtx_t>(hip::getCurrentContext());

  HIP_RETURN(hipSuccess);
}

hipError_t hipRuntimeGetVersion(int *runtimeVersion) {
  HIP_INIT_API(runtimeVersion);

  if (!runtimeVersion) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *runtimeVersion = AMD_PLATFORM_BUILD_NUMBER;

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxDestroy(hipCtx_t ctx) {
  HIP_INIT_API(ctx);

  amd::Context* amdContext = reinterpret_cast<amd::Context*>(as_amd(ctx));
  if (amdContext == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  // Need to remove the ctx of calling thread if its the top one
  if (!g_ctxtStack.empty() && g_ctxtStack.top() == amdContext) {
    g_ctxtStack.pop();
  }

  // Remove context from global context list
  for (unsigned int i = 0; i < g_devices.size(); i++) {
    if (g_devices[i] == amdContext) {
      // Decrement ref count for device primary context
      amdContext->release();
    }
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPopCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(ctx);

  amd::Context* amdContext = reinterpret_cast<amd::Context*>(as_amd(ctx));
  if (amdContext == nullptr) {
    HIP_RETURN(hipErrorInvalidContext);
  }

  if (!g_ctxtStack.empty()) {
    amdContext = g_ctxtStack.top();
    g_ctxtStack.pop();
  } else {
    HIP_RETURN(hipErrorInvalidContext);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPushCurrent(hipCtx_t ctx) {
  HIP_INIT_API(ctx);

  amd::Context* amdContext = reinterpret_cast<amd::Context*>(as_amd(ctx));
  if (amdContext == nullptr) {
    HIP_RETURN(hipErrorInvalidContext);
  }

  hip::g_context = amdContext;
  g_ctxtStack.push(hip::getCurrentContext());

  HIP_RETURN(hipSuccess);
}

hipError_t hipDriverGetVersion(int* driverVersion) {
  HIP_INIT_API(driverVersion);

  auto* deviceHandle = g_devices[0]->devices()[0];
  const auto& info = deviceHandle->info();

  if (driverVersion) {
    *driverVersion = AMD_PLATFORM_BUILD_NUMBER * 100 +
                     AMD_PLATFORM_REVISION_NUMBER;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetDevice(hipDevice_t* device) {
  HIP_INIT_API(device);

  if (device != nullptr) {
    for (unsigned int i = 0; i < g_devices.size(); i++) {
      if (g_devices[i] == hip::getCurrentContext()) {
        *device = static_cast<hipDevice_t>(i);
        HIP_RETURN(hipSuccess);
      }
    }
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  return hipErrorUnknown;
}

hipError_t hipCtxGetApiVersion(hipCtx_t ctx, int* apiVersion) {
  HIP_INIT_API(apiVersion);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxGetCacheConfig(hipFuncCache_t* cacheConfig) {
  HIP_INIT_API(cacheConfig);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxSetCacheConfig(hipFuncCache_t cacheConfig) {
  HIP_INIT_API(cacheConfig);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxSetSharedMemConfig(hipSharedMemConfig config) {
  HIP_INIT_API(config);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxSynchronize(void) {
  HIP_INIT_API(1);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxGetFlags(unsigned int* flags) {
  HIP_INIT_API(flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxGetState(hipDevice_t dev, unsigned int* flags, int* active) {
  HIP_INIT_API(dev, flags, active);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxRelease(hipDevice_t dev) {
  HIP_INIT_API(dev);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxRetain(hipCtx_t* pctx, hipDevice_t dev) {
  HIP_INIT_API(pctx, dev);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxReset(hipDevice_t dev) {
  HIP_INIT_API(dev);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxSetFlags(hipDevice_t dev, unsigned int flags) {
  HIP_INIT_API(dev, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}
<commit_msg>P4 to Git Change 1604364 by cpaquot@cpaquot-ocl-lc-lnx on 2018/09/11 15:43:44<commit_after>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"
#include "platform/runtime.hpp"
#include "utils/versions.hpp"

std::vector<amd::Context*> g_devices;

namespace hip {

thread_local amd::Context* g_context = nullptr;
thread_local std::stack<amd::Context*> g_ctxtStack;
thread_local hipError_t g_lastError = hipSuccess;
std::once_flag g_ihipInitialized;

std::map<amd::Context*, amd::HostQueue*> g_nullStreams;

void init() {
  if (!amd::Runtime::initialized()) {
    amd::Runtime::init();
  }

  const std::vector<amd::Device*>& devices = amd::Device::getDevices(CL_DEVICE_TYPE_GPU, false);

  for (unsigned int i=0; i<devices.size(); i++) {
    const std::vector<amd::Device*> device(1, devices[i]);
    amd::Context* context = new amd::Context(device, amd::Context::Info());
    if (!context) return;

    if (context && CL_SUCCESS != context->create(nullptr)) {
      context->release();
    } else {
      g_devices.push_back(context);
    }
  }
}

amd::Context* getCurrentContext() {
  return g_context;
}

void setCurrentContext(unsigned int index) {
  assert(index<g_devices.size());
  g_context = g_devices[index];
}

amd::HostQueue* getNullStream() {
  auto stream = g_nullStreams.find(getCurrentContext());
  if (stream == g_nullStreams.end()) {
    amd::Device* device = getCurrentContext()->devices()[0];
    amd::HostQueue* queue = new amd::HostQueue(*hip::getCurrentContext(), *device, 0,
                                               amd::CommandQueue::RealTimeDisabled,
                                               amd::CommandQueue::Priority::Normal);
    g_nullStreams[getCurrentContext()] = queue;
    return queue;
  }
  syncStreams();
  return stream->second;
}

};

using namespace hip;

hipError_t hipInit(unsigned int flags) {
  HIP_INIT_API(flags);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxCreate(hipCtx_t *ctx, unsigned int flags,  hipDevice_t device) {
  HIP_INIT_API(ctx, flags, device);

  if (static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *ctx = reinterpret_cast<hipCtx_t>(g_devices[device]);

  // Increment ref count for device primary context
  g_devices[device]->retain();
  g_ctxtStack.push(g_devices[device]);

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxSetCurrent(hipCtx_t ctx) {
  HIP_INIT_API(ctx);

  if (ctx == nullptr) {
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
  } else {
    hip::g_context = reinterpret_cast<amd::Context*>(as_amd(ctx));
    if(!g_ctxtStack.empty()) {
      g_ctxtStack.pop();
    }
    g_ctxtStack.push(hip::getCurrentContext());
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(ctx);

  *ctx = reinterpret_cast<hipCtx_t>(hip::getCurrentContext());

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetSharedMemConfig(hipSharedMemConfig* pConfig) {
  HIP_INIT_API(pConfig);

  *pConfig = hipSharedMemBankSizeFourByte;

  HIP_RETURN(hipSuccess);
}

hipError_t hipRuntimeGetVersion(int *runtimeVersion) {
  HIP_INIT_API(runtimeVersion);

  if (!runtimeVersion) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  *runtimeVersion = AMD_PLATFORM_BUILD_NUMBER;

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxDestroy(hipCtx_t ctx) {
  HIP_INIT_API(ctx);

  amd::Context* amdContext = reinterpret_cast<amd::Context*>(as_amd(ctx));
  if (amdContext == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  // Need to remove the ctx of calling thread if its the top one
  if (!g_ctxtStack.empty() && g_ctxtStack.top() == amdContext) {
    g_ctxtStack.pop();
  }

  // Remove context from global context list
  for (unsigned int i = 0; i < g_devices.size(); i++) {
    if (g_devices[i] == amdContext) {
      // Decrement ref count for device primary context
      amdContext->release();
    }
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPopCurrent(hipCtx_t* ctx) {
  HIP_INIT_API(ctx);

  amd::Context* amdContext = reinterpret_cast<amd::Context*>(as_amd(ctx));
  if (amdContext == nullptr) {
    HIP_RETURN(hipErrorInvalidContext);
  }

  if (!g_ctxtStack.empty()) {
    amdContext = g_ctxtStack.top();
    g_ctxtStack.pop();
  } else {
    HIP_RETURN(hipErrorInvalidContext);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxPushCurrent(hipCtx_t ctx) {
  HIP_INIT_API(ctx);

  amd::Context* amdContext = reinterpret_cast<amd::Context*>(as_amd(ctx));
  if (amdContext == nullptr) {
    HIP_RETURN(hipErrorInvalidContext);
  }

  hip::g_context = amdContext;
  g_ctxtStack.push(hip::getCurrentContext());

  HIP_RETURN(hipSuccess);
}

hipError_t hipDriverGetVersion(int* driverVersion) {
  HIP_INIT_API(driverVersion);

  auto* deviceHandle = g_devices[0]->devices()[0];
  const auto& info = deviceHandle->info();

  if (driverVersion) {
    *driverVersion = AMD_PLATFORM_BUILD_NUMBER * 100 +
                     AMD_PLATFORM_REVISION_NUMBER;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
}

hipError_t hipCtxGetDevice(hipDevice_t* device) {
  HIP_INIT_API(device);

  if (device != nullptr) {
    for (unsigned int i = 0; i < g_devices.size(); i++) {
      if (g_devices[i] == hip::getCurrentContext()) {
        *device = static_cast<hipDevice_t>(i);
        HIP_RETURN(hipSuccess);
      }
    }
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  return hipErrorUnknown;
}

hipError_t hipCtxGetApiVersion(hipCtx_t ctx, int* apiVersion) {
  HIP_INIT_API(apiVersion);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxGetCacheConfig(hipFuncCache_t* cacheConfig) {
  HIP_INIT_API(cacheConfig);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxSetCacheConfig(hipFuncCache_t cacheConfig) {
  HIP_INIT_API(cacheConfig);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxSetSharedMemConfig(hipSharedMemConfig config) {
  HIP_INIT_API(config);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxSynchronize(void) {
  HIP_INIT_API(1);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipCtxGetFlags(unsigned int* flags) {
  HIP_INIT_API(flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxGetState(hipDevice_t dev, unsigned int* flags, int* active) {
  HIP_INIT_API(dev, flags, active);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxRelease(hipDevice_t dev) {
  HIP_INIT_API(dev);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxRetain(hipCtx_t* pctx, hipDevice_t dev) {
  HIP_INIT_API(pctx, dev);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxReset(hipDevice_t dev) {
  HIP_INIT_API(dev);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipDevicePrimaryCtxSetFlags(hipDevice_t dev, unsigned int flags) {
  HIP_INIT_API(dev, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}
<|endoftext|>


<commit_before><commit_msg>coverity#708211 Uninitialized scalar field<commit_after><|endoftext|>