Skip to content

Commit

Permalink
Squashed 'externals/coda-oss/' changes from df4e0fc1f..28926b673
Browse files Browse the repository at this point in the history
28926b673 provide our own (simple) mdspan implementation (#759)
6bb722454 make SpanRC API match std::mdspan (#758)

git-subtree-dir: externals/coda-oss
git-subtree-split: 28926b673931c3f148882ceca7d3de203accfa4e
  • Loading branch information
Dan Smith committed Dec 1, 2023
1 parent ce6eb2f commit f5abe98
Show file tree
Hide file tree
Showing 12 changed files with 311 additions and 98 deletions.
3 changes: 3 additions & 0 deletions modules/c++/coda-oss.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
<ClInclude Include="coda_oss\include\coda_oss\bit.h" />
<ClInclude Include="coda_oss\include\coda_oss\CPlusPlus.h" />
<ClInclude Include="coda_oss\include\coda_oss\cstddef.h" />
<ClInclude Include="coda_oss\include\coda_oss\mdspan.h" />
<ClInclude Include="coda_oss\include\coda_oss\mdspan_.h" />
<ClInclude Include="coda_oss\include\coda_oss\namespace_.h" />
<ClInclude Include="coda_oss\include\coda_oss\numbers.h" />
<ClInclude Include="coda_oss\include\coda_oss\optional.h" />
Expand Down Expand Up @@ -509,6 +511,7 @@
<None Include="std\include\std\bit" />
<None Include="std\include\std\cstddef" />
<None Include="std\include\std\filesystem" />
<None Include="std\include\std\mdspan" />
<None Include="std\include\std\memory" />
<None Include="std\include\std\numbers" />
<None Include="std\include\std\optional" />
Expand Down
9 changes: 9 additions & 0 deletions modules/c++/coda-oss.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,12 @@
<ClInclude Include="str\include\str\W1252string.h">
<Filter>str</Filter>
</ClInclude>
<ClInclude Include="coda_oss\include\coda_oss\mdspan.h">
<Filter>coda_oss</Filter>
</ClInclude>
<ClInclude Include="coda_oss\include\coda_oss\mdspan_.h">
<Filter>coda_oss</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp" />
Expand Down Expand Up @@ -1559,5 +1565,8 @@
<None Include="sys\source\CppUnitTestAssert_.cpp_">
<Filter>sys</Filter>
</None>
<None Include="std\include\std\mdspan">
<Filter>std</Filter>
</None>
</ItemGroup>
</Project>
73 changes: 73 additions & 0 deletions modules/c++/coda_oss/include/coda_oss/mdspan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* =========================================================================
* This file is part of coda_oss-c++
* =========================================================================
*
* (C) Copyright 2004 - 2014, MDA Information Systems LLC
* © Copyright 2023, Maxar Technologies, Inc.
*
* coda_oss-c++ 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; If not,
* see <http://www.gnu.org/licenses/>.
*
*/
#pragma once

#include "coda_oss/CPlusPlus.h"

// This should always work ... it's in a `details` namespace
#include "coda_oss/mdspan_.h"

// This logic needs to be here rather than <std/mdspan> so that `coda_oss::mdspan` will
// be the same as `std::mdspan`.
#ifndef CODA_OSS_HAVE_std_mdspan_
#define CODA_OSS_HAVE_std_mdspan_ 0 // assume no <mdspan>
#endif
#ifndef CODA_OSS_HAVE_experimental_mdspan_
#define CODA_OSS_HAVE_experimental_mdspan_ 0 // assume no std::experimental::mdspan
#endif
#if CODA_OSS_cpp17 // __has_include
#if __has_include(<mdspan>) // <mdspan> not until C++23
#include <mdspan>
#undef CODA_OSS_HAVE_std_mdspan_
#define CODA_OSS_HAVE_std_mdspan_ 1 // provided by the implementation, probably C++23
#endif

#if CODA_OSS_cpp20 // Can't even #include this file with older C++14/17 compilers! :-(
// Put this in a __has_include so that it's optional. Our simple implemtnation works
// for our needs, and this brings along a lot of code that our older compilers don't
// like. By the time we need more functionality, maybe we'll be using C++23?
//
// Until then, having this available allows checking our implementation against
// something much more real. https://github.com/kokkos/mdspan
#if __has_include("coda_oss/experimental/mdspan")
#include "coda_oss/experimental/mdspan"
#undef CODA_OSS_HAVE_experimental_mdspan_
#define CODA_OSS_HAVE_experimental_mdspan_ 1 // provided coda_oss/experimental/mdspan
#endif
#endif
#endif // CODA_OSS_cpp17

namespace coda_oss
{
#if CODA_OSS_HAVE_std_mdspan_
using std::mdspan;
using std::dextents;
#elif CODA_OSS_HAVE_experimental_mdspan_
using std::experimental::mdspan;
using std::experimental::dextents;
#else
using details::mdspan;
using details::dextents;
#endif
}

151 changes: 151 additions & 0 deletions modules/c++/coda_oss/include/coda_oss/mdspan_.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* =========================================================================
* This file is part of coda_oss-c++
* =========================================================================
*
* (C) Copyright 2004 - 2014, MDA Information Systems LLC
* © Copyright 2023, Maxar Technologies, Inc.
*
* coda_oss-c++ 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; If not,
* see <http://www.gnu.org/licenses/>.
*
*/
#pragma once

#include <assert.h>

#include <array>

#include "coda_oss/span.h"

// This is a simple, partial, and incomplete implementation of `std::mdspan` (in C++23).
// https://en.cppreference.com/w/cpp/container/mdspan
//
// Why? Our (current) needs are much more limited than all the use-cases for `std::mdspan`:
// dynamic (not static) extents, rank of 2 (rows × cols), contiguous memory, ...
// By the time we really need more features, maybe we'll be using C++23?
namespace coda_oss
{
namespace details
{
// https://en.cppreference.com/w/cpp/container/mdspan/extents
template<typename IndexType, size_t Rank>
struct dextents final // this is actually supposed to be an alias template with all dynamic extents
{
static_assert(Rank == 2, "Rank must have a value of 2");
using index_type = IndexType;
using size_type = index_type;
using rank_type = size_t;

constexpr dextents() = default;

// These are supposed to be templates, but we don't need that complication right now.
constexpr dextents(index_type i0, index_type i1) noexcept : exts_{i0, i1}
{
}
constexpr explicit dextents(const std::array<index_type, Rank>& exts) noexcept : exts_(exts)
{
}

dextents(const dextents&) = default;
dextents& operator=(const dextents&) = default;
dextents(dextents&&) = default;
dextents& operator=(dextents&&) = default;

constexpr index_type extent(rank_type r) const noexcept
{
return exts_[r];
}

static constexpr auto rank() noexcept
{
return Rank;
}

private:
std::array<index_type, Rank> exts_;
};

template<typename T, typename TExtents>
class mdspan final
{
coda_oss::span<T> s_; // `span` instead of a raw pointer to get more range checking.
TExtents ext_;

// c.f., `types::RowCol`
template <typename IndexType, size_t Rank>
static size_t area(const dextents<IndexType, Rank>& exts)
{
return exts.extent(0) * exts.extent(1);
}

public:
using extents_type = TExtents;
using size_type = typename extents_type::size_type;
using data_handle_type = T*;
using reference = T&;

constexpr mdspan() = default;

// Again, these are supposed to be templates ...
mdspan(data_handle_type p, const extents_type& ext) noexcept : s_(p, area(ext)), ext_(ext)
{
}
mdspan(data_handle_type p, const std::array<size_type, 2>& dims) noexcept : mdspan(p, extents_type(dims))
{
}

mdspan(const mdspan&) = default;
mdspan& operator=(const mdspan&) = default;
mdspan(mdspan&&) = default;
mdspan& operator=(mdspan&&) = default;

constexpr data_handle_type data_handle() const noexcept
{
return s_.data();
}

/*constexpr*/ reference operator[](size_t idx) const noexcept
{
assert(idx < size()); // prevents "constexpr" in C++11
return data_handle()[idx];
}
/*constexpr*/ reference operator()(size_t r, size_t c) const noexcept
{
const auto offset = (r * extent(1)) + c;
return (*this)[offset];
}

constexpr size_t size() const noexcept
{
return s_.size();
}

constexpr bool empty() const noexcept
{
return s_.empty();
}

auto extent(size_type rank) const
{
return ext_.extent(rank);
}

static constexpr auto rank() noexcept
{
return extents_type::rank();
}
};
}
}

7 changes: 3 additions & 4 deletions modules/c++/coda_oss/include/coda_oss/optional.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

#include "coda_oss/CPlusPlus.h"

// always compile; it's in a details namespace
#include "coda_oss/optional_.h"

// This logic needs to be here rather than <std/optional> so that `coda_oss::optional` will
// be the same as `std::optional`.
#ifndef CODA_OSS_HAVE_std_optional_
Expand All @@ -37,10 +40,6 @@
#endif
#endif // CODA_OSS_cpp17

#if !CODA_OSS_HAVE_std_optional_
#include "coda_oss/optional_.h"
#endif

namespace coda_oss
{
#if CODA_OSS_HAVE_std_optional_
Expand Down
2 changes: 0 additions & 2 deletions modules/c++/gsl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,3 @@ coda_add_module(
${MODULE_NAME}
VERSION 1.0
DEPS config-c++)


81 changes: 3 additions & 78 deletions modules/c++/hdf5.lite/include/hdf5/lite/SpanRC.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,94 +20,19 @@
*
*/

#pragma once
#ifndef CODA_OSS_hdf5_lite_SpanRC_h_INCLUDED_
#define CODA_OSS_hdf5_lite_SpanRC_h_INCLUDED_
#pragma once

/*!
* \file SpanRC.h
*
* This is a super-simple version of C++23's mdspan. It's here because 1) don't want widespread use, and
* 2) CODA already has a View2D.
*/

#include <assert.h>

#include "config/Exports.h"
#include "coda_oss/span.h"
#include "types/RowCol.h"
#include "coda_oss/mdspan.h"

namespace hdf5
{
namespace lite
{

template<typename T>
struct SpanRC final
{
using size_type = types::RowCol<size_t>;
using element_type = T;
using pointer = T*;
using reference = T&;

SpanRC() = default;
SpanRC(pointer p, size_type rc) noexcept : s_(p, rc.area()), rc_(rc)
{
}
SpanRC(pointer p, size_t r, size_t c) noexcept : SpanRC(p, size_type(r, c))
{
}
SpanRC(const SpanRC&) noexcept = default;

constexpr pointer data() const noexcept
{
return s_.data();
}

/*constexpr*/ reference operator[](size_t idx) const noexcept
{
assert(idx < size()); // prevents "constexpr" in C++11
return data()[idx];
}
/*constexpr*/ reference operator()(size_t r, size_t c) const noexcept
{
const auto offset = (r * dims().col) + c;
return (*this)[offset];
}
/*constexpr*/ reference operator[](size_type idx) const noexcept
{
return (*this)(idx.row, idx.col);
}

constexpr size_t size() const noexcept
{
assert(s_.size() == rc_.area());
return s_.size();
}
constexpr size_t area() const noexcept
{
return size();
}

constexpr size_type size_bytes() const noexcept
{
return s_.size_bytes();
}

constexpr bool empty() const noexcept
{
return s_.empty();
}

const auto& dims() const
{
return rc_;
}

private:
coda_oss::span<T> s_;
types::RowCol<size_t> rc_;
};
using SpanRC = coda_oss::mdspan<T, coda_oss::dextents<size_t, 2>>;

}
}
Expand Down
Loading

0 comments on commit f5abe98

Please sign in to comment.