Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added span implementation #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions include/dsplib/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <dsplib/types.h>
#include <dsplib/slice.h>
#include <dsplib/span.h>
#include <dsplib/indexing.h>
#include <dsplib/throw.h>

Expand Down Expand Up @@ -138,22 +139,39 @@ class base_array
}

//--------------------------------------------------------------------
slice_t<T> slice(int i1, int i2, int m = 1) {
slice_t<T> slice(int i1, int i2, int m) {
return slice_t<T>(*this, i1, i2, m);
}

const_slice_t<T> slice(int i1, int i2, int m = 1) const {
return const_slice_t<T>(*this, i1, i2, m);
slice_t<T> slice(int i1, indexing::end_t, int m) {
return slice_t<T>(*this, i1, size(), m);
}

slice_t<T> slice(int i1, indexing::end_t, int m = 1) {
return slice_t<T>(*this, i1, size(), m);
const_slice_t<T> slice(int i1, int i2, int m) const {
return const_slice_t<T>(*this, i1, i2, m);
}

const_slice_t<T> slice(int i1, indexing::end_t, int m = 1) const {
const_slice_t<T> slice(int i1, indexing::end_t, int m) const {
return const_slice_t<T>(*this, i1, size(), m);
}

//use span for stride=1
span_t<T> slice(int i1, int i2) {
return span_t<T>(*this, i1, i2);
}

span_t<T> slice(int i1, indexing::end_t) {
return span_t<T>(*this, i1, size());
}

const_span_t<T> slice(int i1, int i2) const {
return const_span_t<T>(*this, i1, i2);
}

const_span_t<T> slice(int i1, indexing::end_t) const {
return const_span_t<T>(*this, i1, size());
}

//--------------------------------------------------------------------
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;
Expand Down
1 change: 1 addition & 0 deletions include/dsplib/math.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <dsplib/array.h>
#include <dsplib/span.h>

#include <limits>

Expand Down
9 changes: 5 additions & 4 deletions include/dsplib/slice.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ class const_slice_t : public base_slice_t
, _base{rhs._base} {
}

int size() const {
int size() const noexcept {
return _nc;
}

private:
protected:
const base_array<T>& _base;
};

Expand All @@ -113,7 +113,7 @@ class slice_t : public base_slice_t
, _base{rhs._base} {
}

int size() const {
int size() const noexcept {
return _nc;
}

Expand Down Expand Up @@ -142,6 +142,7 @@ class slice_t : public base_slice_t
const bool is_dirrect = (dst_t0 < dst_t1) && (src_t0 < src_t1);

//simple block copy/move
//TODO: move to span implementation
if ((dst_step == src_step) && (dst_step == 1) && is_dirrect) {
if (!is_same_vec) {
std::memcpy((dst_p + dst_t0), (src_p + src_t0), count * sizeof(T));
Expand Down Expand Up @@ -189,7 +190,7 @@ class slice_t : public base_slice_t
return (*this = base_array<T>(list));
}

private:
protected:
static void _assign(const T* restrict src, T* restrict dst, int src_step, int dst_step, int src_init, int dst_init,
int count) {
int idx_dst = dst_init;
Expand Down
130 changes: 130 additions & 0 deletions include/dsplib/span.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#pragma once

#include <dsplib/slice.h>

namespace dsplib {

template<class T>
class const_span_t;

template<class T>
class span_t;

//span is a slice with a stride of 1
//used to quickly access vector elements in functions (without memory allocation)

//mutable span
template<typename T>
class span_t : public slice_t<T>
{
public:
friend class const_span_t<T>;

explicit span_t(base_array<T>& v, int i1, int i2)
: slice_t<T>(v, i1, i2, 1)
, _ptr{v.data() + i1}
, _len{slice_t<T>::size()} {
}

span_t(base_array<T>& v)
: span_t(v, 0, v.size()) {
}

T* data() noexcept {
return _ptr;
}

int size() const noexcept {
return _len;
}

T& operator()(int i) noexcept {
assert((i >= 0) && (i < _len));
return _ptr[i];
}

T& operator[](int i) noexcept {
assert((i >= 0) && (i < _len));
return _ptr[i];
}

//TODO: override fast implementation for span

span_t& operator=(const const_slice_t<T>& rhs) {
slice_t<T>::operator=(rhs);
return *this;
}

span_t& operator=(const slice_t<T>& rhs) {
slice_t<T>::operator=(rhs);
return *this;
}

span_t& operator=(const base_array<T>& rhs) {
slice_t<T>::operator=(rhs);
return *this;
}

span_t& operator=(const T& rhs) {
std::fill(_ptr, (_ptr + _len), rhs);
return *this;
}

span_t& operator=(const std::initializer_list<T>& rhs) {
slice_t<T>::operator=(rhs);
return *this;
}

private:
T* _ptr{nullptr};
int _len{0};
};

//immutable span
template<typename T>
class const_span_t : public const_slice_t<T>
{
public:
friend class span_t<T>;

explicit const_span_t(const base_array<T>& v, int i1, int i2)
: const_slice_t<T>(v, i1, i2, 1)
, _ptr{v.data() + i1}
, _len{const_slice_t<T>::size()} {
}

const_span_t(const span_t<T>& v)
: const_span_t(v._base, v._i1, v._i2) {
}

const_span_t(const base_array<T>& v)
: const_span_t(v, 0, v.size()) {
}

const T* data() const noexcept {
return _ptr;
}

int size() const noexcept {
return _len;
}

const T& operator()(int i) const noexcept {
assert((i >= 0) && (i < _len));
return _ptr[i];
}

const T& operator[](int i) const noexcept {
assert((i >= 0) && (i < _len));
return _ptr[i];
}

private:
const T* _ptr{nullptr};
int _len{0};
};

using const_span_real = const_span_t<real_t>;
using const_span_cmplx = const_span_t<cmplx_t>;

} // namespace dsplib
36 changes: 36 additions & 0 deletions tests/span_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "tests_common.h"
#include <gtest/gtest.h>

using namespace dsplib;

static real_t _first_span_elem(const const_span_real& x) {
return x[0];
}

//-------------------------------------------------------------------------------------------------
TEST(SpanTest, Base) {
{
arr_real x1 = {-1, 1, 2, 3};
auto span = x1.slice(0, indexing::end);
ASSERT_EQ(span.size(), 4);
arr_real x2(span);
ASSERT_EQ_ARR_REAL(x1, x2);
ASSERT_EQ(_first_span_elem(span), -1);
ASSERT_EQ(_first_span_elem(x1), -1);
}

{
arr_real x1 = {-1, 2, -3, 4, -5};
auto span = x1.slice(1, 3);
ASSERT_EQ(span.size(), 2);
arr_real x2(span);
ASSERT_EQ_ARR_REAL(x2, arr_real{2, -3});
ASSERT_EQ(_first_span_elem(span), 2);
}

{
arr_real x1 = {-1, 2, -3, 4, -5};
x1.slice(0, 2) = 100;
ASSERT_EQ_ARR_REAL(x1, arr_real{100, 100, -3, 4, -5});
}
}