<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __BSE_MIDI_EVENT_HH__
#define __BSE_MIDI_EVENT_HH__

#include <bse/memory.hh>

namespace Bse {

namespace AudioSignal {

/// Type of MIDI Events.
enum class EventType : uint8_t {};

/// MIDI Event data structure.
struct Event {
  constexpr static EventType NOTE_OFF         = EventType (0x80);
  constexpr static EventType NOTE_ON          = EventType (0x90);
  constexpr static EventType AFTERTOUCH       = EventType (0xA0); ///< Key Pressure, polyphonic aftertouch
  constexpr static EventType CONTROL_CHANGE   = EventType (0xB0); ///< Control Change
  constexpr static EventType PROGRAM_CHANGE   = EventType (0xC0);
  constexpr static EventType CHANNEL_PRESSURE = EventType (0xD0); ///< Channel Aftertouch
  constexpr static EventType PITCH_BEND       = EventType (0xE0);
  constexpr static EventType SYSEX            = EventType (0xF0);
  EventType type;       ///< Event type, one of the EventType members
  int8      frame;      ///< Offset into current block, delayed if negative
  uint16    channel;    ///< 1…16 for standard events
  union {
    uint    length;     ///< Data event length of byte array.
    uint    param;      ///< PROGRAM_CHANGE program, CONTROL_CHANGE controller, 0…0x7f
    struct {
      uint8 pitch;      ///< NOTE, KEY_PRESSURE MIDI note, 0…0x7f, 60 = middle C at 261.63 Hz.
      uint  noteid :24; ///< NOTE, identifier for note expression handling or 0xffffff.
    };
  };
  union {
    char   *data;       ///< Data event byte array.
    struct {
      float  value;     ///< CONTROL_CHANGE 0…+1, CHANNEL_PRESSURE, 0…+1, PITCH_BEND -1…+1
      uint   cval;      ///< CONTROL_CHANGE control value, 0…0x7f
    };
    struct {
      float velocity;   ///< NOTE, KEY_PRESSURE, CHANNEL_PRESSURE, 0…+1
      float tuning;     ///< NOTE, fine tuning in ±cents
    };
  };
  explicit Event     (EventType etype = EventType (0));
  /*copy*/ Event     (const Event &other);
  Event&   operator= (const Event &other);
  /*des*/ ~Event     ();
  std::string  to_string  () const;
};

Event make_note_on    (uint16 chnl, uint8 ptch, float velo, float tune = 0, uint nid = 0xffffff);
Event make_note_off   (uint16 chnl, uint8 ptch, float velo, float tune = 0, uint nid = 0xffffff);
Event make_aftertouch (uint16 chnl, uint8 ptch, float velo, float tune = 0, uint nid = 0xffffff);
Event make_pressure   (uint16 chnl, float velo);
Event make_control    (uint16 chnl, uint prm, float val);
Event make_control8   (uint16 chnl, uint prm, uint8 cval);
Event make_program    (uint16 chnl, uint prgrm);
Event make_pitch_bend (uint16 chnl, float val);

/// A stream of writable Event structures.
class EventStream {
  std::vector<Event> events_; // TODO: use O(1) allocator
  friend class EventRange;
public:
  explicit     EventStream ();
  void         append      (int8_t frame, const Event &event);
  const Event* begin       () const     { return &*events_.begin(); }
  const Event* end         () const     { return &*events_.end(); }
  size_t       size        () const     { return events_.size(); }
  void         clear       () noexcept  { events_.clear(); }
};

/// A readonly view and iterator into an EventStream.
class EventRange {
  const EventStream estream_;
public:
  const Event* begin          () const  { return &*estream_.begin(); }
  const Event* end            () const  { return &*estream_.end(); }
  size_t       events_pending () const  { return estream_.size(); }
  explicit     EventRange     (const EventStream estream);
};

} // AudioSignal
} // Bse

#endif // __BSE_MIDI_EVENT_HH__
<commit_msg>BSE: midievent.hh: add EventStream.empty()<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __BSE_MIDI_EVENT_HH__
#define __BSE_MIDI_EVENT_HH__

#include <bse/memory.hh>

namespace Bse {

namespace AudioSignal {

/// Type of MIDI Events.
enum class EventType : uint8_t {};

/// MIDI Event data structure.
struct Event {
  constexpr static EventType NOTE_OFF         = EventType (0x80);
  constexpr static EventType NOTE_ON          = EventType (0x90);
  constexpr static EventType AFTERTOUCH       = EventType (0xA0); ///< Key Pressure, polyphonic aftertouch
  constexpr static EventType CONTROL_CHANGE   = EventType (0xB0); ///< Control Change
  constexpr static EventType PROGRAM_CHANGE   = EventType (0xC0);
  constexpr static EventType CHANNEL_PRESSURE = EventType (0xD0); ///< Channel Aftertouch
  constexpr static EventType PITCH_BEND       = EventType (0xE0);
  constexpr static EventType SYSEX            = EventType (0xF0);
  EventType type;       ///< Event type, one of the EventType members
  int8      frame;      ///< Offset into current block, delayed if negative
  uint16    channel;    ///< 1…16 for standard events
  union {
    uint    length;     ///< Data event length of byte array.
    uint    param;      ///< PROGRAM_CHANGE program, CONTROL_CHANGE controller, 0…0x7f
    struct {
      uint8 pitch;      ///< NOTE, KEY_PRESSURE MIDI note, 0…0x7f, 60 = middle C at 261.63 Hz.
      uint  noteid :24; ///< NOTE, identifier for note expression handling or 0xffffff.
    };
  };
  union {
    char   *data;       ///< Data event byte array.
    struct {
      float  value;     ///< CONTROL_CHANGE 0…+1, CHANNEL_PRESSURE, 0…+1, PITCH_BEND -1…+1
      uint   cval;      ///< CONTROL_CHANGE control value, 0…0x7f
    };
    struct {
      float velocity;   ///< NOTE, KEY_PRESSURE, CHANNEL_PRESSURE, 0…+1
      float tuning;     ///< NOTE, fine tuning in ±cents
    };
  };
  explicit Event     (EventType etype = EventType (0));
  /*copy*/ Event     (const Event &other);
  Event&   operator= (const Event &other);
  /*des*/ ~Event     ();
  std::string  to_string  () const;
};

Event make_note_on    (uint16 chnl, uint8 ptch, float velo, float tune = 0, uint nid = 0xffffff);
Event make_note_off   (uint16 chnl, uint8 ptch, float velo, float tune = 0, uint nid = 0xffffff);
Event make_aftertouch (uint16 chnl, uint8 ptch, float velo, float tune = 0, uint nid = 0xffffff);
Event make_pressure   (uint16 chnl, float velo);
Event make_control    (uint16 chnl, uint prm, float val);
Event make_control8   (uint16 chnl, uint prm, uint8 cval);
Event make_program    (uint16 chnl, uint prgrm);
Event make_pitch_bend (uint16 chnl, float val);

/// A stream of writable Event structures.
class EventStream {
  std::vector<Event> events_; // TODO: use O(1) allocator
  friend class EventRange;
public:
  explicit     EventStream ();
  void         append      (int8_t frame, const Event &event);
  const Event* begin       () const noexcept { return &*events_.begin(); }
  const Event* end         () const noexcept { return &*events_.end(); }
  size_t       size        () const noexcept { return events_.size(); }
  bool         empty       () const noexcept { return events_.empty(); }
  void         clear       () noexcept       { events_.clear(); }
};

/// A readonly view and iterator into an EventStream.
class EventRange {
  const EventStream estream_;
public:
  const Event* begin          () const  { return &*estream_.begin(); }
  const Event* end            () const  { return &*estream_.end(); }
  size_t       events_pending () const  { return estream_.size(); }
  explicit     EventRange     (const EventStream estream);
};

} // AudioSignal
} // Bse

#endif // __BSE_MIDI_EVENT_HH__
<|endoftext|>


<commit_before>/*
 +----------------------------------------------------------------------+
 | Swoole                                                               |
 +----------------------------------------------------------------------+
 | Copyright (c) 2012-2015 The Swoole Group                             |
 +----------------------------------------------------------------------+
 | This source file is subject to version 2.0 of the Apache license,    |
 | that is bundled with this package in the file LICENSE, and is        |
 | available through the world-wide-web at the following url:           |
 | http://www.apache.org/licenses/LICENSE-2.0.html                      |
 | If you did not receive a copy of the Apache2.0 license and are unable|
 | to obtain it through the world-wide-web, please send a note to       |
 | license@swoole.com so we can mail you a copy immediately.            |
 +----------------------------------------------------------------------+
 | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
 +----------------------------------------------------------------------+
 */

#include "mqtt.h"

void swMqtt_print_package(swMqtt_packet *pkg) {
    printf("type=%d, length=%d\n", pkg->type, pkg->length);
}

void swMqtt_set_protocol(swProtocol *protocol) {
    protocol->package_length_size = SW_MQTT_PAYLOAD_LENGTH_SIZE;
    protocol->package_length_offset = 1;
    protocol->package_body_offset = 0;
    protocol->get_package_length = swMqtt_get_package_length;
}

static sw_inline ssize_t swMqtt_get_length(const char *data, uint32_t size, ssize_t *count) {
    uint8_t byte;
    int mul = 1;
    ssize_t length = 0;

    *count = 0;
    do {
        byte = data[*count + 1];
        length += (byte & 127) * mul;
        mul *= 128;
        (*count)++;
    } while ((byte & 128) != 0);

    return length;
}

#if 0
int swMqtt_unpack(swMqtt_packet *pkg, char *data, uint32_t size)
{
    uint8_t byte = data[0];
    off_t offset;

    pkg->type = (byte & 0xF0) >> 4;
    pkg->dup = (byte & 0x08) >> 3;
    pkg->qos = (byte & 0x06) >> 1;
    pkg->retain = byte & 0x01;

    offset += 1;

    int count = 0;
    pkg->length = swMqtt_get_length(data, size, &count);
    offset += count + 1;
    return 0;
}
#endif

ssize_t swMqtt_get_package_length(swProtocol *protocol, swSocket *conn, const char *data, uint32_t size) {
    if (size < SW_MQTT_MIN_LENGTH) {
        return 0;
    }
    ssize_t count = 0;
    ssize_t length = swMqtt_get_length(data, size, &count);
    return length + count + 1;
}
<commit_msg>remove mqtt unused code<commit_after>/*
 +----------------------------------------------------------------------+
 | Swoole                                                               |
 +----------------------------------------------------------------------+
 | Copyright (c) 2012-2015 The Swoole Group                             |
 +----------------------------------------------------------------------+
 | This source file is subject to version 2.0 of the Apache license,    |
 | that is bundled with this package in the file LICENSE, and is        |
 | available through the world-wide-web at the following url:           |
 | http://www.apache.org/licenses/LICENSE-2.0.html                      |
 | If you did not receive a copy of the Apache2.0 license and are unable|
 | to obtain it through the world-wide-web, please send a note to       |
 | license@swoole.com so we can mail you a copy immediately.            |
 +----------------------------------------------------------------------+
 | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
 +----------------------------------------------------------------------+
 */

#include "mqtt.h"

void swMqtt_print_package(swMqtt_packet *pkg) {
    printf("type=%d, length=%d\n", pkg->type, pkg->length);
}

void swMqtt_set_protocol(swProtocol *protocol) {
    protocol->package_length_size = SW_MQTT_PAYLOAD_LENGTH_SIZE;
    protocol->package_length_offset = 1;
    protocol->package_body_offset = 0;
    protocol->get_package_length = swMqtt_get_package_length;
}

static sw_inline ssize_t swMqtt_get_length(const char *data, ssize_t *count) {
    uint8_t byte;
    int mul = 1;
    ssize_t length = 0;

    *count = 0;
    do {
        byte = data[*count + 1];
        length += (byte & 127) * mul;
        mul *= 128;
        (*count)++;
    } while ((byte & 128) != 0);

    return length;
}

#if 0
int swMqtt_unpack(swMqtt_packet *pkg, char *data, uint32_t size)
{
    uint8_t byte = data[0];
    off_t offset;

    pkg->type = (byte & 0xF0) >> 4;
    pkg->dup = (byte & 0x08) >> 3;
    pkg->qos = (byte & 0x06) >> 1;
    pkg->retain = byte & 0x01;

    offset += 1;

    int count = 0;
    pkg->length = swMqtt_get_length(data, size, &count);
    offset += count + 1;
    return 0;
}
#endif

ssize_t swMqtt_get_package_length(swProtocol *protocol, swSocket *conn, const char *data, uint32_t size) {
    if (size < SW_MQTT_MIN_LENGTH) {
        return 0;
    }
    ssize_t count = 0;
    ssize_t length = swMqtt_get_length(data, &count);
    return length + count + 1;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "public_utils.h"

#include "utils.h"

#include <algorithm>

using namespace tcam;

std::vector<TCAM_DEVICE_TYPE> tcam::get_device_type_list()
{
    return { TCAM_DEVICE_TYPE_UNKNOWN, TCAM_DEVICE_TYPE_V4L2,   TCAM_DEVICE_TYPE_ARAVIS,
             TCAM_DEVICE_TYPE_LIBUSB,  TCAM_DEVICE_TYPE_PIMIPI, TCAM_DEVICE_TYPE_MIPI,
             TCAM_DEVICE_TYPE_TEGRA };
}

std::vector<std::string> tcam::get_device_type_list_strings()
{
    auto vec = get_device_type_list();

    std::vector<std::string> ret;

    ret.reserve(vec.size());

    for (const auto& v : vec) { ret.push_back(tcam_device_type_to_string(v)); }

    return ret;
}

std::string tcam::tcam_device_type_to_string(TCAM_DEVICE_TYPE type)
{
    switch (type)
    {
        case TCAM_DEVICE_TYPE_V4L2:
            return "v4l2";
        case TCAM_DEVICE_TYPE_ARAVIS:
            return "aravis";
        case TCAM_DEVICE_TYPE_LIBUSB:
            return "libusb";
        case TCAM_DEVICE_TYPE_PIMIPI:
            return "pimipi";
        case TCAM_DEVICE_TYPE_MIPI:
            return "mipi";
        case TCAM_DEVICE_TYPE_TEGRA:
            return "tegra";
        default:
            return "unknown";
    }
}

TCAM_DEVICE_TYPE tcam::tcam_device_from_string(const std::string& input)
{
    std::string str = input;

    std::transform(
        str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });

    if (str == "v4l2")
        return TCAM_DEVICE_TYPE_V4L2;
    else if (str == "aravis")
        return TCAM_DEVICE_TYPE_ARAVIS;
    else if (str == "libusb")
        return TCAM_DEVICE_TYPE_LIBUSB;
    else if (str == "pimipi")
        return TCAM_DEVICE_TYPE_PIMIPI;
    else if (str == "mipi")
        return TCAM_DEVICE_TYPE_MIPI;
    else if (str == "tegra")
        return TCAM_DEVICE_TYPE_TEGRA;

    return TCAM_DEVICE_TYPE_UNKNOWN;
}

std::vector<tcam_image_size> tcam::get_standard_resolutions(const tcam_image_size& min,
                                                            const tcam_image_size& max)
{
    static const tcam_image_size resolutions[] = {
        { 128, 96 },    { 320, 240 },   { 360, 280 },   { 544, 480 },   { 640, 480 },
        { 352, 288 },   { 576, 480 },   { 720, 480 },   { 960, 720 },   { 1280, 720 },
        { 1440, 1080 }, { 1920, 1080 }, { 1920, 1200 }, { 2048, 1152 }, { 2048, 1536 },
        { 2560, 1440 }, { 3840, 2160 }, { 4096, 3072 }, { 7680, 4320 }, { 7680, 4800 },
    };

    std::vector<struct tcam_image_size> ret;
    ret.reserve(std::size_t(resolutions));
    for (const auto& r : resolutions)
    {
        if ((min < r) && (r < max))
        {
            ret.push_back(r);
        }
    }

    return ret;
}
<commit_msg>srcs: Fix bad_alloc segfault in standard_resolution lookup<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "public_utils.h"

#include "utils.h"

#include <algorithm>

using namespace tcam;

std::vector<TCAM_DEVICE_TYPE> tcam::get_device_type_list()
{
    return { TCAM_DEVICE_TYPE_UNKNOWN, TCAM_DEVICE_TYPE_V4L2,   TCAM_DEVICE_TYPE_ARAVIS,
             TCAM_DEVICE_TYPE_LIBUSB,  TCAM_DEVICE_TYPE_PIMIPI, TCAM_DEVICE_TYPE_MIPI,
             TCAM_DEVICE_TYPE_TEGRA };
}

std::vector<std::string> tcam::get_device_type_list_strings()
{
    auto vec = get_device_type_list();

    std::vector<std::string> ret;

    ret.reserve(vec.size());

    for (const auto& v : vec) { ret.push_back(tcam_device_type_to_string(v)); }

    return ret;
}

std::string tcam::tcam_device_type_to_string(TCAM_DEVICE_TYPE type)
{
    switch (type)
    {
        case TCAM_DEVICE_TYPE_V4L2:
            return "v4l2";
        case TCAM_DEVICE_TYPE_ARAVIS:
            return "aravis";
        case TCAM_DEVICE_TYPE_LIBUSB:
            return "libusb";
        case TCAM_DEVICE_TYPE_PIMIPI:
            return "pimipi";
        case TCAM_DEVICE_TYPE_MIPI:
            return "mipi";
        case TCAM_DEVICE_TYPE_TEGRA:
            return "tegra";
        default:
            return "unknown";
    }
}

TCAM_DEVICE_TYPE tcam::tcam_device_from_string(const std::string& input)
{
    std::string str = input;

    std::transform(
        str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });

    if (str == "v4l2")
        return TCAM_DEVICE_TYPE_V4L2;
    else if (str == "aravis")
        return TCAM_DEVICE_TYPE_ARAVIS;
    else if (str == "libusb")
        return TCAM_DEVICE_TYPE_LIBUSB;
    else if (str == "pimipi")
        return TCAM_DEVICE_TYPE_PIMIPI;
    else if (str == "mipi")
        return TCAM_DEVICE_TYPE_MIPI;
    else if (str == "tegra")
        return TCAM_DEVICE_TYPE_TEGRA;

    return TCAM_DEVICE_TYPE_UNKNOWN;
}

std::vector<tcam_image_size> tcam::get_standard_resolutions(const tcam_image_size& min,
                                                            const tcam_image_size& max)
{
    static const tcam_image_size resolutions[] = {
        { 128, 96 },    { 320, 240 },   { 360, 280 },   { 544, 480 },   { 640, 480 },
        { 352, 288 },   { 576, 480 },   { 720, 480 },   { 960, 720 },   { 1280, 720 },
        { 1440, 1080 }, { 1920, 1080 }, { 1920, 1200 }, { 2048, 1152 }, { 2048, 1536 },
        { 2560, 1440 }, { 3840, 2160 }, { 4096, 3072 }, { 7680, 4320 }, { 7680, 4800 },
    };

    std::vector<struct tcam_image_size> ret;
    ret.reserve(std::size(resolutions));
    for (const auto& r : resolutions)
    {
        if ((min < r) && (r < max))
        {
            ret.push_back(r);
        }
    }

    return ret;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Resolver.hxx"
#include "Registry.hxx"
#include "Widget.hxx"
#include "Class.hxx"
#include "pool/pool.hxx"
#include "pool/Holder.hxx"
#include "util/Cancellable.hxx"
#include "util/DestructObserver.hxx"

#include <boost/intrusive/list.hpp>

class WidgetResolver;

class WidgetResolverListener final
	: public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>,
	  PoolHolder,
	  Cancellable {

	WidgetResolver &resolver;

	const WidgetResolverCallback callback;

#ifndef NDEBUG
	bool finished = false, aborted = false;
#endif

public:
	template<typename P>
	WidgetResolverListener(P &&_pool, WidgetResolver &_resolver,
			       WidgetResolverCallback _callback,
			       CancellablePointer &cancel_ptr) noexcept
		:PoolHolder(std::forward<P>(_pool)), resolver(_resolver),
		 callback(_callback) {
		cancel_ptr = *this;
	}

	void Finish() noexcept;

private:
	void Destroy() noexcept {
		this->~WidgetResolverListener();
	}

	/* virtual methods from class Cancellable */
	void Cancel() noexcept override;
};

class WidgetResolver final : DestructAnchor {
	Widget &widget;

	boost::intrusive::list<WidgetResolverListener,
			       boost::intrusive::constant_time_size<false>> listeners;

	CancellablePointer cancel_ptr;

	bool finished = false;

#ifndef NDEBUG
	bool aborted = false;
#endif

public:
	explicit WidgetResolver(Widget &_widget) noexcept
		:widget(_widget) {}

	bool IsFinished() const noexcept {
		return finished;
	}

	void Start(WidgetRegistry &registry) noexcept {
		/* use the widget pool because the listener pool may be
		   aborted, while the others still run */
		registry.LookupWidgetClass(widget.pool, widget.pool,
					   widget.class_name,
					   BIND_THIS_METHOD(RegistryCallback),
					   cancel_ptr);
	}

	void AddListener(WidgetResolverListener &listener) noexcept {
		assert(!finished);

		listeners.push_back(listener);
	}

	void RemoveListener(WidgetResolverListener &listener) noexcept;

private:
	void Destroy() noexcept {
		this->~WidgetResolver();
	}

	void Abort() noexcept;

	void RegistryCallback(const WidgetClass *cls) noexcept;
};

void
WidgetResolver::RemoveListener(WidgetResolverListener &listener) noexcept
{
	assert(widget.resolver == this);
	assert(!listeners.empty());
	assert(!aborted);

	listeners.erase(listeners.iterator_to(listener));

	if (listeners.empty()) {
		/* the last listener has been aborted: abort the widget
		   registry */
		if (finished)
			/* destroy the resolver before returning from
			   WidgetResolverListener::Cancel() because its caller may
			   destroy the memory pool */
			Destroy();
		else
			Abort();
	}
}

void
WidgetResolver::Abort() noexcept
{
	assert(listeners.empty());
	assert(widget.resolver == this);

#ifndef NDEBUG
	aborted = true;
#endif

	widget.resolver = nullptr;
	cancel_ptr.Cancel();
	Destroy();
}

/*
 * async operation
 *
 */

void
WidgetResolverListener::Cancel() noexcept
{
	assert(!finished);
	assert(!aborted);

#ifndef NDEBUG
	aborted = true;
#endif

	resolver.RemoveListener(*this);

	Destroy();
}

/*
 * registry callback
 *
 */

inline void
WidgetResolverListener::Finish() noexcept
{
	assert(!finished);
	assert(!aborted);

#ifndef NDEBUG
	finished = true;
#endif

	callback();
	Destroy();
}

void
WidgetResolver::RegistryCallback(const WidgetClass *cls) noexcept
{
	assert(widget.cls == nullptr);
	assert(widget.resolver == this);
	assert(!listeners.empty());
	assert(!finished);
	assert(!aborted);

	finished = true;

	widget.cls = cls;

	widget.from_template.view = widget.from_request.view = cls != nullptr
		? widget_view_lookup(&cls->views, widget.from_template.view_name)
		: nullptr;

	widget.session_sync_pending = cls != nullptr && cls->stateful &&
		/* the widget session code requires a valid view */
		widget.from_template.view != nullptr;

	const DestructObserver destructed(*this);

	do {
		assert(!listeners.empty());
		auto &l = listeners.front();
		listeners.pop_front();

		if (listeners.empty())
			/* destruct this object before invoking the last callback
			   because the callback may free the memory pool */
			Destroy();

		l.Finish();

		if (destructed)
			return;
	} while (!listeners.empty());

	/* this is reachable only if the last listener has been canceled
	   from within the previous listener callback */
	Destroy();
}

/*
 * constructor
 *
 */

static WidgetResolver *
widget_resolver_alloc(Widget &widget) noexcept
{
	return widget.resolver = NewFromPool<WidgetResolver>(widget.pool, widget);
}

void
ResolveWidget(struct pool &pool,
	      Widget &widget,
	      WidgetRegistry &registry,
	      WidgetResolverCallback callback,
	      CancellablePointer &cancel_ptr) noexcept
{
	bool is_new = false;

	assert(widget.class_name != nullptr);
	assert(pool_contains(widget.pool, &widget, sizeof(widget)));

	if (widget.cls != nullptr) {
		/* already resolved successfully */
		callback();
		return;
	}

	/* create new resolver object if it does not already exist */

	WidgetResolver *resolver = widget.resolver;
	if (resolver == nullptr) {
		resolver = widget_resolver_alloc(widget);
		is_new = true;
	} else if (resolver->IsFinished()) {
		/* we have already failed to resolve this widget class; return
		   immediately, don't try again */
		callback();
		return;
	}

	assert(pool_contains(widget.pool, widget.resolver,
			     sizeof(*widget.resolver)));

	/* add a new listener to the resolver */

	auto listener = NewFromPool<WidgetResolverListener>(pool, pool, *resolver,
							    callback,
							    cancel_ptr);

	resolver->AddListener(*listener);

	/* finally send request to the widget registry */

	if (is_new)
		resolver->Start(registry);
}
<commit_msg>widget/Resolver: use IntrusiveList<><commit_after>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Resolver.hxx"
#include "Registry.hxx"
#include "Widget.hxx"
#include "Class.hxx"
#include "pool/pool.hxx"
#include "pool/Holder.hxx"
#include "util/Cancellable.hxx"
#include "util/DestructObserver.hxx"
#include "util/IntrusiveList.hxx"

class WidgetResolver;

class WidgetResolverListener final
	: public IntrusiveListHook,
	  PoolHolder,
	  Cancellable {

	WidgetResolver &resolver;

	const WidgetResolverCallback callback;

#ifndef NDEBUG
	bool finished = false, aborted = false;
#endif

public:
	template<typename P>
	WidgetResolverListener(P &&_pool, WidgetResolver &_resolver,
			       WidgetResolverCallback _callback,
			       CancellablePointer &cancel_ptr) noexcept
		:PoolHolder(std::forward<P>(_pool)), resolver(_resolver),
		 callback(_callback) {
		cancel_ptr = *this;
	}

	void Finish() noexcept;

private:
	void Destroy() noexcept {
		this->~WidgetResolverListener();
	}

	/* virtual methods from class Cancellable */
	void Cancel() noexcept override;
};

class WidgetResolver final : DestructAnchor {
	Widget &widget;

	IntrusiveList<WidgetResolverListener> listeners;

	CancellablePointer cancel_ptr;

	bool finished = false;

#ifndef NDEBUG
	bool aborted = false;
#endif

public:
	explicit WidgetResolver(Widget &_widget) noexcept
		:widget(_widget) {}

	bool IsFinished() const noexcept {
		return finished;
	}

	void Start(WidgetRegistry &registry) noexcept {
		/* use the widget pool because the listener pool may be
		   aborted, while the others still run */
		registry.LookupWidgetClass(widget.pool, widget.pool,
					   widget.class_name,
					   BIND_THIS_METHOD(RegistryCallback),
					   cancel_ptr);
	}

	void AddListener(WidgetResolverListener &listener) noexcept {
		assert(!finished);

		listeners.push_back(listener);
	}

	void RemoveListener(WidgetResolverListener &listener) noexcept;

private:
	void Destroy() noexcept {
		this->~WidgetResolver();
	}

	void Abort() noexcept;

	void RegistryCallback(const WidgetClass *cls) noexcept;
};

void
WidgetResolver::RemoveListener(WidgetResolverListener &listener) noexcept
{
	assert(widget.resolver == this);
	assert(!listeners.empty());
	assert(!aborted);

	listener.unlink();

	if (listeners.empty()) {
		/* the last listener has been aborted: abort the widget
		   registry */
		if (finished)
			/* destroy the resolver before returning from
			   WidgetResolverListener::Cancel() because its caller may
			   destroy the memory pool */
			Destroy();
		else
			Abort();
	}
}

void
WidgetResolver::Abort() noexcept
{
	assert(listeners.empty());
	assert(widget.resolver == this);

#ifndef NDEBUG
	aborted = true;
#endif

	widget.resolver = nullptr;
	cancel_ptr.Cancel();
	Destroy();
}

/*
 * async operation
 *
 */

void
WidgetResolverListener::Cancel() noexcept
{
	assert(!finished);
	assert(!aborted);

#ifndef NDEBUG
	aborted = true;
#endif

	resolver.RemoveListener(*this);

	Destroy();
}

/*
 * registry callback
 *
 */

inline void
WidgetResolverListener::Finish() noexcept
{
	assert(!finished);
	assert(!aborted);

#ifndef NDEBUG
	finished = true;
#endif

	callback();
	Destroy();
}

void
WidgetResolver::RegistryCallback(const WidgetClass *cls) noexcept
{
	assert(widget.cls == nullptr);
	assert(widget.resolver == this);
	assert(!listeners.empty());
	assert(!finished);
	assert(!aborted);

	finished = true;

	widget.cls = cls;

	widget.from_template.view = widget.from_request.view = cls != nullptr
		? widget_view_lookup(&cls->views, widget.from_template.view_name)
		: nullptr;

	widget.session_sync_pending = cls != nullptr && cls->stateful &&
		/* the widget session code requires a valid view */
		widget.from_template.view != nullptr;

	const DestructObserver destructed(*this);

	do {
		assert(!listeners.empty());
		auto &l = listeners.front();
		listeners.pop_front();

		if (listeners.empty())
			/* destruct this object before invoking the last callback
			   because the callback may free the memory pool */
			Destroy();

		l.Finish();

		if (destructed)
			return;
	} while (!listeners.empty());

	/* this is reachable only if the last listener has been canceled
	   from within the previous listener callback */
	Destroy();
}

/*
 * constructor
 *
 */

static WidgetResolver *
widget_resolver_alloc(Widget &widget) noexcept
{
	return widget.resolver = NewFromPool<WidgetResolver>(widget.pool, widget);
}

void
ResolveWidget(struct pool &pool,
	      Widget &widget,
	      WidgetRegistry &registry,
	      WidgetResolverCallback callback,
	      CancellablePointer &cancel_ptr) noexcept
{
	bool is_new = false;

	assert(widget.class_name != nullptr);
	assert(pool_contains(widget.pool, &widget, sizeof(widget)));

	if (widget.cls != nullptr) {
		/* already resolved successfully */
		callback();
		return;
	}

	/* create new resolver object if it does not already exist */

	WidgetResolver *resolver = widget.resolver;
	if (resolver == nullptr) {
		resolver = widget_resolver_alloc(widget);
		is_new = true;
	} else if (resolver->IsFinished()) {
		/* we have already failed to resolve this widget class; return
		   immediately, don't try again */
		callback();
		return;
	}

	assert(pool_contains(widget.pool, widget.resolver,
			     sizeof(*widget.resolver)));

	/* add a new listener to the resolver */

	auto listener = NewFromPool<WidgetResolverListener>(pool, pool, *resolver,
							    callback,
							    cancel_ptr);

	resolver->AddListener(*listener);

	/* finally send request to the widget registry */

	if (is_new)
		resolver->Start(registry);
}
<|endoftext|>


<commit_before>#include "include/marketassaykit.h"

MarketAssayKit::MarketAssayKit(QObject *parent, ConfigMT4 *cfg) :
    QObject(parent),
    config(cfg)
{
    setConnections();
    ma_nnWorker.setConfigKit( cfg );
    ma_nnWorker.moveToThread(&maThread);
    maThread.start();
}

MarketAssayKit::~MarketAssayKit()
{
    maThread.exit();
}

void MarketAssayKit::setConnections()
{
    connect( this, SIGNAL( runTraining() ), &ma_nnWorker, SLOT( runTraining() ) );
    connect( this, SIGNAL( runPrediction() ), &ma_nnWorker, SLOT( runPrediction() ) );
    connect( this, SIGNAL( stop() ), &ma_nnWorker, SLOT( stop() ) );
    connect( &ma_nnWorker, SIGNAL( trained(QString) ), this, SIGNAL( trained(QString) ) );
    connect( &ma_nnWorker, SIGNAL( progress(QString, qint32) ),
             this, SIGNAL( progress(QString, qint32) ) );
    connect( &ma_nnWorker, SIGNAL( message(QString, QString) ),
             this, SIGNAL( message(QString, QString) ) );
}
<commit_msg>- fix close thread exeptions;<commit_after>#include "include/marketassaykit.h"

MarketAssayKit::MarketAssayKit(QObject *parent, ConfigMT4 *cfg) :
    QObject(parent),
    config(cfg)
{
    setConnections();
    ma_nnWorker.setConfigKit( cfg );
    ma_nnWorker.moveToThread(&maThread);
    maThread.start();
}

MarketAssayKit::~MarketAssayKit()
{
    maThread.exit();
    maThread.wait();
}

void MarketAssayKit::setConnections()
{
    connect( this, SIGNAL( runTraining() ), &ma_nnWorker, SLOT( runTraining() ) );
    connect( this, SIGNAL( runPrediction() ), &ma_nnWorker, SLOT( runPrediction() ) );
    connect( this, SIGNAL( stop() ), &ma_nnWorker, SLOT( stop() ) );
    connect( &ma_nnWorker, SIGNAL( trained(QString) ), this, SIGNAL( trained(QString) ) );
    connect( &ma_nnWorker, SIGNAL( progress(QString, qint32) ),
             this, SIGNAL( progress(QString, qint32) ) );
    connect( &ma_nnWorker, SIGNAL( message(QString, QString) ),
             this, SIGNAL( message(QString, QString) ) );
}
<|endoftext|>


<commit_before>#include "rendersystem.h"
#include "componentmanager.h"
#include "rendercomponent.h"
#include "movecomponent.h"
#include <iostream>

using namespace std;

RenderSystem::RenderSystem() {
	//Initialize SDL
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        cout << "ERROR: SDL could not initialize! SDL_Error: " << SDL_GetError() << endl;
    } else {
        window = SDL_CreateWindow(
            "SDL Tutorial",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            SCREEN_WIDTH,
            SCREEN_HEIGHT,
            SDL_WINDOW_SHOWN);

        if(!window) {
            cout << "Window could not be created! SDL_Error: " << SDL_GetError() << endl;
        } else {
            //Get window surface
            screenSurface = SDL_GetWindowSurface( window );

            //Fill the surface white
            SDL_FillRect(screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF));

            //Update the surface
            SDL_UpdateWindowSurface(window);
        }
    }

    //We want to access surfaces by their image path later on, so store paths right away
    for(auto a : {
            "./resources/images/HelloWorld.bmp",
            }
        )
    {
        SDL_Surface* surface = SDL_LoadBMP(a);
        if(!surface) {
            cout << "ERROR: Couldn't load image on: " << a << endl;
        } else {
            surfaces.insert(
                make_pair(
                    a,
                    surface
                )
            );
        }
    }
}

RenderSystem::~RenderSystem() {
    //Free all loaded images
    for(auto a : surfaces) {
        free(get<1>(a));
    }

	//Destroy window
    SDL_DestroyWindow(window);

    //Quit SDL subsystems
    SDL_Quit();
}

void RenderSystem::add(unsigned long long int* id) {
	renderDatas.insert(
        make_pair(
            id,
            RenderData{
                componentManager->renderComponents.at(id),
                componentManager->moveComponents.at(id)
            }
        )
    );
}

void RenderSystem::remove(unsigned long long int* id) {
	if(id == nullptr) {
		cout << "WARNING: No id on adress: " << id << endl;
		return;
	}
	if(renderDatas.erase(id) == 0) {
		cout << "WARNING: RenderSystem tried to erase unpresent ID " << *id << ", segfault inc!" << endl;
	}
}

void RenderSystem::update() {
	for(auto data : renderDatas) {
		render(get<1>(data));
	}
}

unsigned int RenderSystem::count() const {
	return renderDatas.size();
}

void RenderSystem::render(const RenderData& data) const {
    cout << "rendering" << endl;

    SDL_Rect pos{
        (int)(data.moveComponent->xpos + data.renderComponent->xoffset),
        (int)(data.moveComponent->ypos + data.renderComponent->yoffset)
    };

    SDL_BlitSurface(
        surfaces.at(
            data.renderComponent->imagePath
        ),
        NULL,
        screenSurface,
        &pos
    );
    SDL_UpdateWindowSurface(window);
}

const string RenderSystem::getIdentifier() const {
	return "RenderSystem";
}<commit_msg>removed cave-man debugging logs<commit_after>#include "rendersystem.h"
#include "componentmanager.h"
#include "rendercomponent.h"
#include "movecomponent.h"
#include <iostream>

using namespace std;

RenderSystem::RenderSystem() {
	//Initialize SDL
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        cout << "ERROR: SDL could not initialize! SDL_Error: " << SDL_GetError() << endl;
    } else {
        window = SDL_CreateWindow(
            "SDL Tutorial",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            SCREEN_WIDTH,
            SCREEN_HEIGHT,
            SDL_WINDOW_SHOWN);

        if(!window) {
            cout << "Window could not be created! SDL_Error: " << SDL_GetError() << endl;
        } else {
            //Get window surface
            screenSurface = SDL_GetWindowSurface( window );

            //Fill the surface white
            SDL_FillRect(screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF));

            //Update the surface
            SDL_UpdateWindowSurface(window);
        }
    }

    //We want to access surfaces by their image path later on, so store paths right away
    for(auto a : {
            "./resources/images/HelloWorld.bmp",
            }
        )
    {
        SDL_Surface* surface = SDL_LoadBMP(a);
        if(!surface) {
            cout << "ERROR: Couldn't load image on: " << a << endl;
        } else {
            surfaces.insert(
                make_pair(
                    a,
                    surface
                )
            );
        }
    }
}

RenderSystem::~RenderSystem() {
    //Free all loaded images
    for(auto a : surfaces) {
        free(get<1>(a));
    }

	//Destroy window
    SDL_DestroyWindow(window);

    //Quit SDL subsystems
    SDL_Quit();
}

void RenderSystem::add(unsigned long long int* id) {
	renderDatas.insert(
        make_pair(
            id,
            RenderData{
                componentManager->renderComponents.at(id),
                componentManager->moveComponents.at(id)
            }
        )
    );
}

void RenderSystem::remove(unsigned long long int* id) {
	if(id == nullptr) {
		cout << "WARNING: No id on adress: " << id << endl;
		return;
	}
	if(renderDatas.erase(id) == 0) {
		cout << "WARNING: RenderSystem tried to erase unpresent ID " << *id << ", segfault inc!" << endl;
	}
}

void RenderSystem::update() {
	for(auto data : renderDatas) {
		render(get<1>(data));
	}
}

unsigned int RenderSystem::count() const {
	return renderDatas.size();
}

void RenderSystem::render(const RenderData& data) const {
    SDL_Rect pos{
        (int)(data.moveComponent->xpos + data.renderComponent->xoffset),
        (int)(data.moveComponent->ypos + data.renderComponent->yoffset)
    };

    SDL_BlitSurface(
        surfaces.at(
            data.renderComponent->imagePath
        ),
        NULL,
        screenSurface,
        &pos
    );
    SDL_UpdateWindowSurface(window);
}

const string RenderSystem::getIdentifier() const {
	return "RenderSystem";
}<|endoftext|>


<commit_before>#include <Python.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
#include <string>
#include <vector>
#include "repeatFinder.h"

using namespace std;

#define REPEAT_LEN                    11
#define HASH_LEN     (1<<(REPEAT_LEN*2))

unsigned INIT_DNA_LEN = 120000000;

char inputfile[256] = "test.fasta";
char *dna;
int converter[128], complement[128];
int dna_len;
int output_rep_len = REPEAT_LEN;

vector<int> allrepeats[HASH_LEN];
struct repeat{
	int fst;
	int sec;
	int len;
	int seclen;
	int visited;
	int exact;
}R;

vector<repeat> rep;
int gap_len = 0;//allow gap < gap_len

void input()
{
	FILE *f;
	dna = new char[INIT_DNA_LEN+1];
	if(!dna){
		printf("Can not allocate memory\n");
		exit(0);
	}

	//input dna
	f = fopen(inputfile, "r");
	if(f == NULL){
		printf("Can not find input file %s\n",inputfile);
		exit(0);
	}
	char *my_new_check = fgets(dna,INIT_DNA_LEN,f);
	(void) my_new_check; // remove an unused parameter warning

	strcpy(dna,"");
	while(fscanf(f, "%s", dna+dna_len)==1) {
		int t = strlen(dna+dna_len);
		dna_len += t;
	}
	fclose(f);

	//printf("dna len = %d\n",dna_len);
}

// find all the 11 length substring and store their start position
void find_repeats()
{
	int key,start,keylen=2*(REPEAT_LEN-1);

	key = 0;
	for(start = 0;start < REPEAT_LEN; start++)
		key = (key<<2) + converter[(int) dna[start]];
	allrepeats[key].push_back(0);

	for(start = 1;start < dna_len-REPEAT_LEN+1; start++)
	{
		key = ((key&((1<<keylen)-1))<< 2) + converter[(int) dna[start+REPEAT_LEN-1]];
		allrepeats[key].push_back(start);
	}

	//find reverse repeat
	key = 0;
	for(start = dna_len-1;start >dna_len-1-REPEAT_LEN; start--)
		key = (key<<2) + converter[complement[(int) dna[start]]];
	allrepeats[key].push_back((dna_len-1)*(-1));

	for(start = dna_len-2;start >REPEAT_LEN-2; start--)
	{
		key= ((key&((1<<keylen)-1))<<2) + converter[complement[(int) dna[start-REPEAT_LEN+1]]];
		allrepeats[key].push_back(start*(-1));
	}
}

void find_maxlen(int fst, int sec)
{
	int i,j,k;
	//  check whther to compute //

	if(sec-fst < REPEAT_LEN)
		return;

	if (fst >0)
		if(dna[fst-1] == dna[sec-1])
			return;

	k=0;
	for(i = REPEAT_LEN+fst, j = REPEAT_LEN+sec ; i<sec && j<dna_len; i++, j++)
		if (dna[i] == dna[j])
			k++;
		else
			break;

	R.fst=fst+1;
	R.sec=sec+1;
	R.len=REPEAT_LEN + k;
	R.seclen = R.len;
	R.visited = 0;
	R.exact = 0;
	rep.push_back(R);
}

void find_maxlen_rev(int fst, int sec)
{
	int i,j,k;

	sec = sec *(-1);
	//  check whther to compute //
	if(sec-fst +1< 2 * REPEAT_LEN)
		return;

	if (fst >0 && sec < dna_len-1 )
		if(dna[fst-1] == complement[(int) dna[sec+1]])
			return;
///////////////

	k=0;
	for(i = REPEAT_LEN+fst, j = sec - REPEAT_LEN ; i<dna_len && j>-1 && i<j; i++, j--)
		if (dna[i] == complement[(int) dna[j]])
			k++;
		else
			break;

	R.fst=fst+1;
	R.sec=sec*(-1)-1;
	R.len=REPEAT_LEN + k;
	R.seclen = R.len;
	R.visited = 0;
	R.exact = 0;
	rep.push_back(R);
}

void extend_repeats()
{
	int i,j,key,keylen=2*(REPEAT_LEN-1);

	key = 0;
	for(i = 0;i < REPEAT_LEN; i++)
		key = (key<<2) + converter[(int) dna[i]];
	for(j=0; j < (int) allrepeats[key].size(); j++)
		if(allrepeats[key][j]<0)
			find_maxlen_rev(0,allrepeats[key][j]);
		else
			find_maxlen(0,allrepeats[key][j]);

	for(i =1;i<dna_len-REPEAT_LEN+1;i++){
		key = ((key&((1<<keylen)-1))<< 2) + converter[(int) dna[i+REPEAT_LEN-1]];
		for(j=0; j < (int) allrepeats[key].size(); j++)
			if(allrepeats[key][j]<0)
				find_maxlen_rev(i,allrepeats[key][j]);
			else
				find_maxlen(i,allrepeats[key][j]);
	}
}

int check_extend(int fst,int n)
{
	int i,j = rep[fst].fst + rep[fst].len -1 +n, len = rep.size(),k, head , tail, mid;

	// binery search
	head = fst+1;
	tail = len-1;
	mid = (head +tail)/2;
	while(rep[mid].fst!= j && head<=tail){
		mid = (head +tail)/2;
		if(rep[mid].fst<j)
			head = mid+1;
		else
			tail = mid-1;
	}

	if (head <= tail)
		return -1;

	i = mid-1;
	// while (rep[mid].fst == rep[i].fst && i >-1)
	while(rep[mid].fst == rep[i].fst && i > tail-1)
		i--;
	i++;
////
	k = rep[fst].sec+rep[fst].seclen -1;

	for(; i < (int) rep.size() && rep[i].fst == j;i++)
		if(rep[i].visited == 0){
			if ( (rep[i].fst + rep[i].len -1) <rep[fst].sec || (rep[i].fst + rep[i].len -1)<(rep[i].sec)*(-1)-rep[i].seclen+1)
				//check for 2nd copy
				if(rep[i].sec-k <= gap_len && rep[i].sec-k >= 0)
					return i;
		}
	return -1;
}

void extend_gapped_repeat()
{
	int i,j,k, len = rep.size();

	for(i =0;i<len;i++)
		if(rep[i].visited==0)
			for(j=1;j<=gap_len;j++){

				k = check_extend(i,j);
				if(k==-1)
					continue;

				//extend repeat
				rep[i].len += j+ rep[k].len-1;
				rep[i].seclen += rep[k].sec -(rep[i].sec+rep[i].seclen -1) + rep[k].seclen-1;
				rep[i].exact = 1;
				rep[k].visited = 1;
				i--;
				break;
			}
}

void print_output()
{
	int i,j;
	FILE *f;
	char outputfile[256];

    strcpy (outputfile,inputfile);
    strcat (outputfile,".repeatfinder");
    f = fopen(outputfile,"w");

	j = rep.size();

	int totalRep = 0;
	for(i=0;i<j;i++)
		if(rep[i].visited==0 && rep[i].len>= output_rep_len){
			fprintf(f,"%d\t%d\t",rep[i].fst,rep[i].fst+rep[i].len-1);
			if(rep[i].sec>-1)
				fprintf(f,"%d\t%d\n",rep[i].sec,rep[i].sec+rep[i].seclen-1);
			else
				fprintf(f,"%d\t%d\n",rep[i].sec*(-1),(rep[i].sec+rep[i].seclen-1)*(-1));
			totalRep++;
		}
	fclose(f);
}

void run() {

	//initialize
	converter[(int) 'A']=0;
	converter[(int) 'a']=0;
	converter[(int) 'C']=1;
	converter[(int) 'c']=1;
	converter[(int) 'G']=2;
	converter[(int) 'g']=2;
	converter[(int) 'T']=3;
	converter[(int) 't']=3;
	complement[(int) 'A']='T';
	complement[(int) 'a']='t';
	complement[(int) 'C']='G';
	complement[(int) 'c']='g';
	complement[(int) 'G']='C';
	complement[(int) 'g']='c';
	complement[(int) 'T']='A';
	complement[(int) 't']='a';

	find_repeats();
	extend_repeats();

	gap_len++;
	//printf("total rep without join = %d\n",rep.size());

	if(gap_len>1)
		extend_gapped_repeat();

}

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

	/*if(argc<2){
		fprintf(stderr, "Command line not valid.\n -f \"fileName\" -g \"Gap Length\"\nUse 0 for no gap\n");
		exit(0);
	}*/

	for(i=1;i<argc;i++) {
		if(!strcmp(argv[i], "-f")  || !strcmp(argv[i], "-F")) {
			assert(i+1 < argc);
			strcpy(inputfile, argv[i+1]);
			i++;
		}
		else if(!strcmp(argv[i], "-g")  || !strcmp(argv[i], "-G")) {
			assert(i+1 < argc);
			sscanf(argv[i+1], "%d", &gap_len);
			i++;
		}
		/*		else if(!strcmp(argv[i], "-l")  || !strcmp(argv[i], "-L")) {
			assert(i+1 < argc);
			sscanf(argv[i+1], "%u", &INIT_DNA_LEN);
			i++;
			}*/
		else if(!strcmp(argv[i], "-l")  || !strcmp(argv[i], "-L")) {
			assert(i+1 < argc);
			sscanf(argv[i+1], "%u", &output_rep_len);
			i++;
		}
		else {
			fprintf(stderr, "Command line not valid. -f \"fileName\" \n-g \"Gap Length\" (Use 0 for not joining) \n-l \"dna length\" (Specify DNA length if its > 10 million)\n");
			exit(0);
		}
	}

	input();
    run();
    print_output();
	return 0;
}

static PyObject *
python_input(PyObject *self, PyObject *args) {
    /* Parse arguments */
    if(!PyArg_ParseTuple(args, "si", &dna, &gap_len)) {
        PyErr_SetString(PyExc_RuntimeError, "Could not parse the arguments to python_input");
        return NULL;
    }
    dna_len = strlen(dna);
    run();

    // incase you need to debug, uncomment these two lines
    //strcpy(inputfile, "ROBTEST");
    //print_output();

    // convert our vector of arrays to a Python object
    Py_ssize_t len = rep.size();
    PyObject *result = PyList_New(0);

    int totalRep = 0;
	for(int i=0;i<len;i++) {
		if(rep[i].visited==0 && rep[i].len>= output_rep_len){
            // we just use a temp variable to deal with the
            // case when second start < 0
		    int ss = rep[i].sec;
		    int se = rep[i].sec+rep[i].seclen-1;
		    if(rep[i].sec<0) {
		        ss = rep[i].sec*(-1);
		        se = (rep[i].sec+rep[i].seclen-1)*(-1);
		    }
			totalRep++;

		    PyObject *item = Py_BuildValue("{s:i, s:i,s:i,s:i,s:i}",
		    "repeat_number", totalRep,
            "first_start", rep[i].fst,
            "first_end", rep[i].fst+rep[i].len-1,
            "second_start", ss,
            "second_end", se
            );
           PyList_Append(result, item);
           }
    }
    return result;
}

PyMODINIT_FUNC PyInit_PhiSpyRepeatFinder(void) {
    return PyModule_Create(&PhiSpyRepeatFinderModule);
}
<commit_msg>Fixing a bug in finding repeats when the sequences has mutliple contigs<commit_after>#include <Python.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
#include <string>
#include <vector>
#include "repeatFinder.h"

using namespace std;

#define REPEAT_LEN                    11
#define HASH_LEN     (1<<(REPEAT_LEN*2))

unsigned INIT_DNA_LEN = 120000000;

char inputfile[256] = "test.fasta";
char *dna;
int converter[128], complement[128];
int dna_len;
int output_rep_len = REPEAT_LEN;
int debug = 0;

vector<int> allrepeats[HASH_LEN];
struct repeat{
	int fst;
	int sec;
	int len;
	int seclen;
	int visited;
	int exact;
}R;

vector<repeat> rep;
int gap_len = 0; //allow gap < gap_len
int ppno = 0; // which prophage are we working on

void input()
{
	FILE *f;
	dna = new char[INIT_DNA_LEN+1];
	if(!dna){
		printf("Can not allocate memory\n");
		exit(0);
	}

	//input dna
	f = fopen(inputfile, "r");
	if(f == NULL){
		printf("Can not find input file %s\n",inputfile);
		exit(0);
	}
	char *my_new_check = fgets(dna,INIT_DNA_LEN,f);
	(void) my_new_check; // remove an unused parameter warning

	strcpy(dna,"");
	while(fscanf(f, "%s", dna+dna_len)==1) {
		int t = strlen(dna+dna_len);
		dna_len += t;
	}
	fclose(f);

	//printf("dna len = %d\n",dna_len);
}

// find all the 11 length substring and store their start position
void find_repeats()
{
	int key,start,keylen=2*(REPEAT_LEN-1);

	key = 0;
	for(start = 0;start < REPEAT_LEN; start++)
		key = (key<<2) + converter[(int) dna[start]];
	allrepeats[key].push_back(0);

	for(start = 1;start < dna_len-REPEAT_LEN+1; start++)
	{
		key = ((key&((1<<keylen)-1))<< 2) + converter[(int) dna[start+REPEAT_LEN-1]];
		allrepeats[key].push_back(start);
	}

	//find reverse repeat
	key = 0;
	for(start = dna_len-1;start >dna_len-1-REPEAT_LEN; start--)
		key = (key<<2) + converter[complement[(int) dna[start]]];
	allrepeats[key].push_back((dna_len-1)*(-1));

	for(start = dna_len-2;start >REPEAT_LEN-2; start--)
	{
		key= ((key&((1<<keylen)-1))<<2) + converter[complement[(int) dna[start-REPEAT_LEN+1]]];
		allrepeats[key].push_back(start*(-1));
	}
}

void find_maxlen(int fst, int sec)
{
	int i,j,k;
	//  check whther to compute //

	if(sec-fst < REPEAT_LEN)
		return;

	if (fst >0)
		if(dna[fst-1] == dna[sec-1])
			return;

	k=0;
	for(i = REPEAT_LEN+fst, j = REPEAT_LEN+sec ; i<sec && j<dna_len; i++, j++)
		if (dna[i] == dna[j])
			k++;
		else
			break;

    if (debug && sec > dna_len) {
        fprintf(stderr, "In find_maxlen we added a repeat with sec %d that is longer than dna_len (%d)\n", sec, dna_len);
    }

	R.fst=fst+1;
	R.sec=sec+1;
	R.len=REPEAT_LEN + k;
	R.seclen = R.len;
	R.visited = 0;
	R.exact = 0;
	rep.push_back(R);
}

void find_maxlen_rev(int fst, int sec)
{
	int i,j,k;

	sec = sec *(-1);
	//  check whther to compute //
	if(sec-fst +1< 2 * REPEAT_LEN)
		return;

	if (fst >0 && sec < dna_len-1 )
		if(dna[fst-1] == complement[(int) dna[sec+1]])
			return;
///////////////

	k=0;
	for(i = REPEAT_LEN+fst, j = sec - REPEAT_LEN ; i<dna_len && j>-1 && i<j; i++, j--)
		if (dna[i] == complement[(int) dna[j]])
			k++;
		else
			break;

	R.fst=fst+1;
	R.sec=sec*(-1)-1;
	R.len=REPEAT_LEN + k;
	R.seclen = R.len;
	R.visited = 0;
	R.exact = 0;
	rep.push_back(R);
}

void extend_repeats()
{
	int i,j,key,keylen=2*(REPEAT_LEN-1);

	key = 0;
	for(i = 0;i < REPEAT_LEN; i++)
		key = (key<<2) + converter[(int) dna[i]];
	for(j=0; j < (int) allrepeats[key].size(); j++)
		if(allrepeats[key][j]<0)
			find_maxlen_rev(0,allrepeats[key][j]);
		else
			find_maxlen(0,allrepeats[key][j]);

	for(i =1;i<dna_len-REPEAT_LEN+1;i++){
		key = ((key&((1<<keylen)-1))<< 2) + converter[(int) dna[i+REPEAT_LEN-1]];
		for(j=0; j < (int) allrepeats[key].size(); j++)
			if(allrepeats[key][j]<0)
				find_maxlen_rev(i,allrepeats[key][j]);
			else
				find_maxlen(i,allrepeats[key][j]);
	}
}

int check_extend(int fst,int n)
{
	int i,j = rep[fst].fst + rep[fst].len -1 +n, len = rep.size(),k, head , tail, mid;

	// binery search
	head = fst+1;
	tail = len-1;
	mid = (head +tail)/2;
	while(rep[mid].fst!= j && head<=tail){
		mid = (head +tail)/2;
		if(rep[mid].fst<j)
			head = mid+1;
		else
			tail = mid-1;
	}

	if (head <= tail)
		return -1;

	i = mid-1;
	// while (rep[mid].fst == rep[i].fst && i >-1)
	while(rep[mid].fst == rep[i].fst && i > tail-1)
		i--;
	i++;
////
	k = rep[fst].sec+rep[fst].seclen -1;

	for(; i < (int) rep.size() && rep[i].fst == j;i++)
		if(rep[i].visited == 0){
			if ( (rep[i].fst + rep[i].len -1) <rep[fst].sec || (rep[i].fst + rep[i].len -1)<(rep[i].sec)*(-1)-rep[i].seclen+1)
				//check for 2nd copy
				if(rep[i].sec-k <= gap_len && rep[i].sec-k >= 0)
					return i;
		}
	return -1;
}

void extend_gapped_repeat()
{
	int i,j,k, len = rep.size();

	for(i =0;i<len;i++)
		if(rep[i].visited==0)
			for(j=1;j<=gap_len;j++){

				k = check_extend(i,j);
				if(k==-1)
					continue;

				//extend repeat
				rep[i].len += j+ rep[k].len-1;
				rep[i].seclen += rep[k].sec -(rep[i].sec+rep[i].seclen -1) + rep[k].seclen-1;
				rep[i].exact = 1;
				rep[k].visited = 1;
				i--;
				break;
			}
}

void write_dna()
{
// write the dna sequence we are testing to a file. This is for debugging purposes!
    FILE *f;
	char outputfile[300];

    sprintf(outputfile, "%s.prophage.%hu.fasta", inputfile, (unsigned short) ppno);
    f = fopen(outputfile,"w");
    fprintf(f, ">pp_%d\n%s\n", ppno, dna);
    fclose(f);
}

void print_output()
{
	int i,j;
	FILE *f;
	char outputfile[300];

    sprintf(outputfile, "%s.prophage.%hu.repeatfinder", inputfile, (unsigned short) ppno);
    f = fopen(outputfile,"w");
    fprintf(f, "First repeat start\tFirst repeat end\tSecond repeat start\tSecond repeat end\tFirst len\tSecond len\tExact\tVisited\n");

	j = rep.size();

	int totalRep = 0;
	for(i=0;i<j;i++)
		if(rep[i].visited==0 && rep[i].len>= output_rep_len){
			fprintf(f,"%d\t%d\t",rep[i].fst,rep[i].fst+rep[i].len-1);
			if(rep[i].sec>-1)
				fprintf(f,"%d\t%d",rep[i].sec,rep[i].sec+rep[i].seclen-1);
			else
				fprintf(f,"%d\t%d",rep[i].sec*(-1),(rep[i].sec+rep[i].seclen-1)*(-1));
			fprintf(f, "\t%d\t%d\t%d\t%d\n", rep[i].len, rep[i].seclen, rep[i].exact, rep[i].visited);
			totalRep++;
		}
	fclose(f);
}

void run() {

	//initialize
	converter[(int) 'A']=0;
	converter[(int) 'a']=0;
	converter[(int) 'C']=1;
	converter[(int) 'c']=1;
	converter[(int) 'G']=2;
	converter[(int) 'g']=2;
	converter[(int) 'T']=3;
	converter[(int) 't']=3;
	complement[(int) 'A']='T';
	complement[(int) 'a']='t';
	complement[(int) 'C']='G';
	complement[(int) 'c']='g';
	complement[(int) 'G']='C';
	complement[(int) 'g']='c';
	complement[(int) 'T']='A';
	complement[(int) 't']='a';

	find_repeats();
	extend_repeats();

	gap_len++;
	//printf("total rep without join = %d\n",rep.size());

	if(gap_len>1)
		extend_gapped_repeat();

}

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

	/*if(argc<2){
		fprintf(stderr, "Command line not valid.\n -f \"fileName\" -g \"Gap Length\"\nUse 0 for no gap\n");
		exit(0);
	}*/

	for(i=1;i<argc;i++) {
		if(!strcmp(argv[i], "-f")  || !strcmp(argv[i], "-F")) {
			assert(i+1 < argc);
			strcpy(inputfile, argv[i+1]);
			i++;
		}
		else if(!strcmp(argv[i], "-g")  || !strcmp(argv[i], "-G")) {
			assert(i+1 < argc);
			sscanf(argv[i+1], "%d", &gap_len);
			i++;
		}
		/*		else if(!strcmp(argv[i], "-l")  || !strcmp(argv[i], "-L")) {
			assert(i+1 < argc);
			sscanf(argv[i+1], "%u", &INIT_DNA_LEN);
			i++;
			}*/
		else if(!strcmp(argv[i], "-l")  || !strcmp(argv[i], "-L")) {
			assert(i+1 < argc);
			sscanf(argv[i+1], "%u", &output_rep_len);
			i++;
		}
		else {
			fprintf(stderr, "Command line not valid. -f \"fileName\" \n-g \"Gap Length\" (Use 0 for not joining) \n-l \"dna length\" (Specify DNA length if its > 10 million)\n");
			exit(0);
		}
	}

	input();
    run();
    print_output();
    write_dna();
	return 0;
}

PyObject *
python_input(PyObject *self, PyObject *args) {
    /* Parse arguments */
    if(!PyArg_ParseTuple(args, "siii", &dna, &gap_len, &ppno, &debug)) {
        PyErr_SetString(PyExc_RuntimeError, "Could not parse the arguments to python_input");
        return NULL;
    }
    dna_len = strlen(dna);
    run();

    if (debug) {
        strcpy(inputfile, "DEBUGGING_REPEATFINDER");
        print_output();
        write_dna();
    }

    // convert our vector of arrays to a Python object
    Py_ssize_t len = rep.size();
    PyObject *result = PyList_New(0);

    int totalRep = 0;
	for(int i=0;i<len;i++) {
		if(rep[i].visited==0 && rep[i].len>= output_rep_len){
            // we just use a temp variable to deal with the
            // case when second start < 0
		    int ss = rep[i].sec;
		    int se = rep[i].sec+rep[i].seclen-1;
		    if(rep[i].sec<0) {
		        ss = rep[i].sec*(-1);
		        se = (rep[i].sec+rep[i].seclen-1)*(-1);
		    }
			totalRep++;

		    PyObject *item = Py_BuildValue("{s:i, s:i,s:i,s:i,s:i}",
		    "repeat_number", totalRep,
            "first_start", rep[i].fst,
            "first_end", rep[i].fst+rep[i].len-1,
            "second_start", ss,
            "second_end", se
            );
           PyList_Append(result, item);
           }
    }

    // CRITICAL: We need to reset the repeats before we
    // call this method again from within the same run!
    for (int i=0; i<HASH_LEN; i++)
        allrepeats[i].clear();

    rep.clear();
    return result;
}

PyMODINIT_FUNC PyInit_PhiSpyRepeatFinder(void) {
    return PyModule_Create(&PhiSpyRepeatFinderModule);
}
<|endoftext|>


<commit_before>// This file is triangularView of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen 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 or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void trmv(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;

  RealScalar largerEps = 10*test_precision<RealScalar>();

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  VectorType v1 = VectorType::Random(rows);

  Scalar s1 = internal::random<Scalar>();

  m1 = MatrixType::Random(rows, cols);

  // check with a column-major matrix
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (col-major)
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY(((s1*m3).conjugate() * v1).isApprox((s1*m1).conjugate().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.conjugate() * v1.conjugate()).isApprox(m1.conjugate().template triangularView<Eigen::Upper>() * v1.conjugate(), largerEps));

  // check with a row-major matrix
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (row-major)
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.adjoint() * v1).isApprox(m1.adjoint().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.adjoint() * (s1*v1.conjugate())).isApprox(m1.adjoint().template triangularView<Eigen::Upper>() * (s1*v1.conjugate()), largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();

  // check transposed cases:
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((v1.transpose() * m3).isApprox(v1.transpose() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3.adjoint()).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>().adjoint(), largerEps));

  // TODO check with sub-matrices
}

void test_product_trmv()
{
  int s;
  for(int i = 0; i < g_repeat ; i++) {
    CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
    CALL_SUBTEST_3( trmv(Matrix3d()) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_4( trmv(MatrixXcf(s,internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_5( trmv(MatrixXcd(s,s)) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
    CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
  }
}
<commit_msg>fix trmv unit test<commit_after>// This file is triangularView of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen 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 or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void trmv(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;

  RealScalar largerEps = 10*test_precision<RealScalar>();

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  VectorType v1 = VectorType::Random(rows);

  Scalar s1 = internal::random<Scalar>();

  m1 = MatrixType::Random(rows, cols);

  // check with a column-major matrix
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (col-major)
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY(((s1*m3).conjugate() * v1).isApprox((s1*m1).conjugate().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.conjugate() * v1.conjugate()).isApprox(m1.conjugate().template triangularView<Eigen::Upper>() * v1.conjugate(), largerEps));

  // check with a row-major matrix
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Upper>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitLower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::UnitLower>();
  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitUpper>() * v1, largerEps));

  // check conjugated and scalar multiple expressions (row-major)
  m3 = m1.template triangularView<Eigen::Upper>();
  VERIFY((m3.adjoint() * v1).isApprox(m1.adjoint().template triangularView<Eigen::Lower>() * v1, largerEps));
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((m3.adjoint() * (s1*v1.conjugate())).isApprox(m1.adjoint().template triangularView<Eigen::Upper>() * (s1*v1.conjugate()), largerEps));
  m3 = m1.template triangularView<Eigen::UnitUpper>();

  // check transposed cases:
  m3 = m1.template triangularView<Eigen::Lower>();
  VERIFY((v1.transpose() * m3).isApprox(v1.transpose() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>(), largerEps));
  VERIFY((v1.adjoint() * m3.adjoint()).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>().adjoint(), largerEps));

  // TODO check with sub-matrices
}

void test_product_trmv()
{
  int s;
  for(int i = 0; i < g_repeat ; i++) {
    CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
    CALL_SUBTEST_3( trmv(Matrix3d()) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_4( trmv(MatrixXcf(s,s)) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
    CALL_SUBTEST_5( trmv(MatrixXcd(s,s)) );
    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
    CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
  }
}
<|endoftext|>


<commit_before>#include "two_clients_and_server_setup.h"
#include "server_setup.h"
#include "client_setup.h"
#include "game/transcendental/types_specification/all_component_includes.h"

void two_clients_and_server_setup::process(game_window& window) {
	server_setup serv_setup;

	std::thread server_thread([&window, &serv_setup]() {
		serv_setup.process(window, true);
	});

	serv_setup.wait_for_listen_server();

	client_setup setups[2];
	setups[0].init(window, "recorded_0.inputs");
	setups[1].init(window, "recorded_1.inputs", true);

	setups[0].session.camera.visible_world_area.x /= 2;
	setups[1].session.camera.visible_world_area.x /= 2;

	setups[0].session.viewport_coordinates = vec2i(0, 0);
	setups[1].session.viewport_coordinates = vec2i(static_cast<int>(setups[1].session.camera.visible_world_area.x), 0);

	unsigned current_window = 0;

	bool alive[2] = { true, true };

	while (!should_quit) {
		auto precollected = window.collect_entropy();

		if (process_exit_key(precollected))
			break;

		for (const auto& n : precollected) {
			if (n.key_event == augs::window::event::key_changed::PRESSED) {
				if (n.key == augs::window::event::keys::CAPSLOCK) {
					++current_window;
					current_window %= 2;

					if (!alive[current_window]) {
						++current_window;
						current_window %= 2;
					}
				}

				if (n.key == augs::window::event::keys::F1) {
					alive[0] = false;
					current_window = 1;
				}

				if (n.key == augs::window::event::keys::F2) {
					alive[1] = false;
					current_window = 0;
				}
			}
		}

		if (!alive[0] && !alive[1]) {
			should_quit = true;
			break;
		}

		auto& target = renderer::get_current();
		target.clear_current_fbo();

		if (current_window == 0) {
			if(alive[0]) setups[0].process_once(window, precollected, false);
			if(alive[1]) setups[1].process_once(window, augs::machine_entropy::local_type(), false);
		}

		if (current_window == 1) {
			if(alive[0]) setups[0].process_once(window, augs::machine_entropy::local_type(), false);
			if(alive[1]) setups[1].process_once(window, precollected, false);
		}

		window.swap_buffers();
	}

	serv_setup.should_quit = true;
	server_thread.join();
}<commit_msg>rendering order<commit_after>#include "two_clients_and_server_setup.h"
#include "server_setup.h"
#include "client_setup.h"
#include "game/transcendental/types_specification/all_component_includes.h"

void two_clients_and_server_setup::process(game_window& window) {
	server_setup serv_setup;

	std::thread server_thread([&window, &serv_setup]() {
		serv_setup.process(window, true);
	});

	serv_setup.wait_for_listen_server();

	client_setup setups[2];
	setups[0].init(window, "recorded_0.inputs");
	setups[1].init(window, "recorded_1.inputs", true);

	setups[0].session.camera.visible_world_area.x /= 2;
	setups[1].session.camera.visible_world_area.x /= 2;

	setups[0].session.viewport_coordinates = vec2i(0, 0);
	setups[1].session.viewport_coordinates = vec2i(static_cast<int>(setups[1].session.camera.visible_world_area.x), 0);

	unsigned current_window = 0;

	bool alive[2] = { true, true };

	while (!should_quit) {
		auto precollected = window.collect_entropy();

		if (process_exit_key(precollected))
			break;

		for (const auto& n : precollected) {
			if (n.key_event == augs::window::event::key_changed::PRESSED) {
				if (n.key == augs::window::event::keys::CAPSLOCK) {
					++current_window;
					current_window %= 2;

					if (!alive[current_window]) {
						++current_window;
						current_window %= 2;
					}
				}

				if (n.key == augs::window::event::keys::F1) {
					alive[0] = false;
					current_window = 1;
				}

				if (n.key == augs::window::event::keys::F2) {
					alive[1] = false;
					current_window = 0;
				}
			}
		}

		if (!alive[0] && !alive[1]) {
			should_quit = true;
			break;
		}

		auto& target = renderer::get_current();
		target.clear_current_fbo();

		if (current_window == 0) {
			if(alive[0]) setups[0].process_once(window, precollected, false);
			if(alive[1]) setups[1].process_once(window, augs::machine_entropy::local_type(), false);
		}

		if (current_window == 1) {
			if(alive[1]) setups[1].process_once(window, precollected, false);
			if(alive[0]) setups[0].process_once(window, augs::machine_entropy::local_type(), false);
		}

		window.swap_buffers();
	}

	serv_setup.should_quit = true;
	server_thread.join();
}<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "TransferFunction.h"
// stl
#include <vector>
// ospcommon
#include "ospcommon/box.h"
using namespace ospcommon;

namespace ospray {
  namespace testing {

    struct RGB : public TransferFunction
    {
      RGB();
      ~RGB() override = default;
    };

    // Inlined definitions ////////////////////////////////////////////////////

    RGB::RGB()
    {
      colors.emplace_back(0, 0, 1);
      colors.emplace_back(0, 1, 0);
      colors.emplace_back(1, 0, 0);
    }

    OSP_REGISTER_TESTING_TRANSFER_FUNCTION(RGB, rgb);

  }  // namespace testing
}  // namespace ospray
<commit_msg>compile fix for Windows (RGB is defined as a macro somewhere...)<commit_after>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "TransferFunction.h"
// stl
#include <vector>
// ospcommon
#include "ospcommon/box.h"
using namespace ospcommon;

namespace ospray {
  namespace testing {

    // NOTE(jda) - Can't use the name 'RGB' because that is a MACRO defined on
    //             Windows somewhere...
    struct RedGreenBlue : public TransferFunction
    {
      RedGreenBlue();
      ~RedGreenBlue() override = default;
    };

    // Inlined definitions ////////////////////////////////////////////////////

    RedGreenBlue::RedGreenBlue()
    {
      colors.emplace_back(0, 0, 1);
      colors.emplace_back(0, 1, 0);
      colors.emplace_back(1, 0, 0);
    }

    OSP_REGISTER_TESTING_TRANSFER_FUNCTION(RedGreenBlue, rgb);

  }  // namespace testing
}  // namespace ospray
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XEUS_EXPORT_HPP
#define XEUS_EXPORT_HPP

#ifdef _WIN32
    #ifdef XEUS_EXPORTS
        #define XEUS_API __declspec(dllexport)
    #else
        #define XEUS_API __declspec(dllimport)
    #endif
#else
    #define XEUS_API
#endif

#define XEUS_VERSION_MAJOR 0
#define XEUS_VERSION_MINOR 5
#define XEUS_VERSION_PATCH 1

#endif
<commit_msg>Release 0.5.2<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XEUS_EXPORT_HPP
#define XEUS_EXPORT_HPP

#ifdef _WIN32
    #ifdef XEUS_EXPORTS
        #define XEUS_API __declspec(dllexport)
    #else
        #define XEUS_API __declspec(dllimport)
    #endif
#else
    #define XEUS_API
#endif

#define XEUS_VERSION_MAJOR 0
#define XEUS_VERSION_MINOR 5
#define XEUS_VERSION_PATCH 2

#endif
<|endoftext|>


<commit_before>#ifndef GROUP__BY__HPP
#define GROUP__BY__HPP

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container &&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> &&, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container & container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container &&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T> &&, KF);

            using key_func_ret =
                decltype(std::declval<KeyFunc>()(
                            std::declval<iterator_deref<Container>>()));

            GroupBy(Container && container, KeyFunc key_func) :
                container(container),
                key_func(key_func)
            { }

        public:
            GroupBy () = delete;
            GroupBy(const GroupBy &) = delete;
            GroupBy& operator=(const GroupBy &) = delete;

            GroupBy (GroupBy &&) = default;
            GroupBy & operator=(GroupBy &&) = default;

            class Iterator;
            class Group;

            class Iterator {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_iter_peek;
                    const iterator_type<Container> sub_end;
                    KeyFunc key_func;

                    using KeyGroupPair =
                        std::pair<key_func_ret, Group>;

                public:
                    Iterator (iterator_type<Container> si,
                              iterator_type<Container> end,
                              KeyFunc key_func) :
                        sub_iter(si),
                        sub_end(end),
                        key_func(key_func)
                    { }

                    KeyGroupPair operator*() {
                        return KeyGroupPair(
                                this->key_func(*this->sub_iter),
                                Group(
                                    *this,
                                    this->key_func(*this->sub_iter)));
                    }

                    Iterator & operator++() {
                        return *this;
                    }

                    bool operator!=(const Iterator &) const {
                        return !this->exhausted();
                    }

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                        }
                    }

                    bool exhausted() const {
                        return this->sub_iter == this->sub_end;
                    }

                    iterator_deref<Container> current() const {
                        return *this->sub_iter;
                    }

                    key_func_ret next_key() const {
                        return this->key_func(*this->sub_iter);
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator & owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    mutable bool completed = false;

                    Group(Iterator & owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // movable, non-copyable
                    Group () = delete;
                    Group (const Group &) = delete;
                    Group & operator=(const Group &) = delete;

                    Group & operator=(Group &&) = default;
                    Group (Group && other) :
                            owner(other.owner),
                            key(other.key),
                            completed(other.completed) {
                        other.completed = true;
                    }

                    class GroupIterator {
                        private:
                            const key_func_ret key;
                            const Group & group;

                            bool not_at_end() const {
                                return !this->group.owner.exhausted() &&
                                    this->group.owner.next_key() == this->key;
                            }

                        public:
                            GroupIterator(const Group & group,
                                          key_func_ret key) :
                                key(key),
                                group(group)
                            { }

                            GroupIterator(const GroupIterator &) = default;

                            bool operator!=(const GroupIterator &) const {
                                if (this->not_at_end()) {
                                    return true;
                                } else {
                                    this->group.completed = true;
                                    return false;
                                }
                            }

                            GroupIterator & operator++() {
                                this->group.owner.increment_iterator();
                                return *this;
                            }

                            iterator_deref<Container> operator*() const {
                                return this->group.owner.current();
                            }
                    };

                    GroupIterator begin() const {
                        return GroupIterator(*this, key);
                    }

                    GroupIterator end() const {
                        return GroupIterator(*this, key);
                    }

            };

            Iterator begin() const {
                return Iterator(
                        std::begin(this->container),
                        std::end(this->container),
                        this->key_func);
            }

            Iterator end() const {
                return Iterator(
                        std::end(this->container),
                        std::end(this->container),
                        this->key_func);
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            ItemReturner() = default;
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container && container, KeyFunc key_func) {
        return GroupBy<Container, KeyFunc>(
                std::forward<Container>(container),
                key_func);
    }

    template <typename Container>
    auto groupby(Container && container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> && il, KeyFunc key_func) {
        return GroupBy<std::initializer_list<T>, KeyFunc>(
                std::move(il),
                key_func);
    }

    template <typename T>
    auto groupby(std::initializer_list<T> && il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif //#ifndef GROUP__BY__HPP
<commit_msg>uniform initialization updates<commit_after>#ifndef GROUP__BY__HPP
#define GROUP__BY__HPP

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container &&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> &&, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container & container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container &&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T> &&, KF);

            using key_func_ret =
                decltype(std::declval<KeyFunc>()(
                            std::declval<iterator_deref<Container>>()));

            GroupBy(Container && container, KeyFunc key_func)
                : container{container},
                key_func(key_func)
            { }

        public:
            GroupBy () = delete;
            GroupBy(const GroupBy &) = delete;
            GroupBy& operator=(const GroupBy &) = delete;

            GroupBy (GroupBy &&) = default;
            GroupBy & operator=(GroupBy &&) = default;

            class Iterator;
            class Group;

            class Iterator {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_iter_peek;
                    const iterator_type<Container> sub_end;
                    KeyFunc key_func;

                    using KeyGroupPair =
                        std::pair<key_func_ret, Group>;

                public:
                    Iterator (iterator_type<Container> si,
                              iterator_type<Container> end,
                              KeyFunc key_func)
                        : sub_iter{si},
                        sub_end{end},
                        key_func(key_func)
                    { }

                    KeyGroupPair operator*() {
                        return KeyGroupPair(
                                this->key_func(*this->sub_iter),
                                Group(
                                    *this,
                                    this->key_func(*this->sub_iter)));
                    }

                    Iterator & operator++() {
                        return *this;
                    }

                    bool operator!=(const Iterator &) const {
                        return !this->exhausted();
                    }

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                        }
                    }

                    bool exhausted() const {
                        return this->sub_iter == this->sub_end;
                    }

                    iterator_deref<Container> current() const {
                        return *this->sub_iter;
                    }

                    key_func_ret next_key() const {
                        return this->key_func(*this->sub_iter);
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator & owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    mutable bool completed = false;

                    Group(Iterator & owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // movable, non-copyable
                    Group () = delete;
                    Group (const Group &) = delete;
                    Group & operator=(const Group &) = delete;

                    Group & operator=(Group &&) = default;
                    Group (Group && other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator {
                        private:
                            const key_func_ret key;
                            const Group & group;

                            bool not_at_end() const {
                                return !this->group.owner.exhausted() &&
                                    this->group.owner.next_key() == this->key;
                            }

                        public:
                            GroupIterator(const Group & group,
                                          key_func_ret key)
                                : key{key},
                                group{group}
                            { }

                            GroupIterator(const GroupIterator &) = default;

                            bool operator!=(const GroupIterator &) const {
                                if (this->not_at_end()) {
                                    return true;
                                } else {
                                    this->group.completed = true;
                                    return false;
                                }
                            }

                            GroupIterator & operator++() {
                                this->group.owner.increment_iterator();
                                return *this;
                            }

                            iterator_deref<Container> operator*() const {
                                return this->group.owner.current();
                            }
                    };

                    GroupIterator begin() const {
                        return {*this, key};
                    }

                    GroupIterator end() const {
                        return {*this, key};
                    }

            };

            Iterator begin() const {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() const {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            ItemReturner() = default;
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container && container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container && container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> && il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> && il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif //#ifndef GROUP__BY__HPP
<|endoftext|>