diff --git a/externals/coda-oss/modules/c++/coda-oss.vcxproj b/externals/coda-oss/modules/c++/coda-oss.vcxproj
index 0f376dc0c..6aacf1781 100644
--- a/externals/coda-oss/modules/c++/coda-oss.vcxproj
+++ b/externals/coda-oss/modules/c++/coda-oss.vcxproj
@@ -19,6 +19,8 @@
+
+
@@ -509,6 +511,7 @@
+
diff --git a/externals/coda-oss/modules/c++/coda-oss.vcxproj.filters b/externals/coda-oss/modules/c++/coda-oss.vcxproj.filters
index 50db46175..a94b8aafd 100644
--- a/externals/coda-oss/modules/c++/coda-oss.vcxproj.filters
+++ b/externals/coda-oss/modules/c++/coda-oss.vcxproj.filters
@@ -951,6 +951,12 @@
str
+
+ coda_oss
+
+
+ coda_oss
+
@@ -1559,5 +1565,8 @@
sys
+
+ std
+
\ No newline at end of file
diff --git a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/mdspan.h b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/mdspan.h
new file mode 100644
index 000000000..3569440f4
--- /dev/null
+++ b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/mdspan.h
@@ -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 .
+ *
+ */
+#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 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
+#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() // not until C++23
+ #include
+ #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
+}
+
diff --git a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/mdspan_.h b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/mdspan_.h
new file mode 100644
index 000000000..b678051d8
--- /dev/null
+++ b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/mdspan_.h
@@ -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 .
+ *
+ */
+#pragma once
+
+#include
+
+#include
+
+#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
+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& 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 exts_;
+};
+
+template
+class mdspan final
+{
+ coda_oss::span s_; // `span` instead of a raw pointer to get more range checking.
+ TExtents ext_;
+
+ // c.f., `types::RowCol`
+ template
+ static size_t area(const dextents& 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& 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();
+ }
+};
+}
+}
+
diff --git a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/optional.h b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/optional.h
index f1fab3a0b..86298871c 100644
--- a/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/optional.h
+++ b/externals/coda-oss/modules/c++/coda_oss/include/coda_oss/optional.h
@@ -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 so that `coda_oss::optional` will
// be the same as `std::optional`.
#ifndef CODA_OSS_HAVE_std_optional_
@@ -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_
diff --git a/externals/coda-oss/modules/c++/gsl/CMakeLists.txt b/externals/coda-oss/modules/c++/gsl/CMakeLists.txt
index 6f17aa779..10d694163 100644
--- a/externals/coda-oss/modules/c++/gsl/CMakeLists.txt
+++ b/externals/coda-oss/modules/c++/gsl/CMakeLists.txt
@@ -4,5 +4,3 @@ coda_add_module(
${MODULE_NAME}
VERSION 1.0
DEPS config-c++)
-
-
diff --git a/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/SpanRC.h b/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/SpanRC.h
index 9392890bb..aea2d9c51 100644
--- a/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/SpanRC.h
+++ b/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/SpanRC.h
@@ -20,22 +20,11 @@
*
*/
+#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
-
-#include "config/Exports.h"
-#include "coda_oss/span.h"
-#include "types/RowCol.h"
+#include "coda_oss/mdspan.h"
namespace hdf5
{
@@ -43,71 +32,7 @@ namespace lite
{
template
-struct SpanRC final
-{
- using size_type = types::RowCol;
- 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 s_;
- types::RowCol rc_;
-};
+using SpanRC = coda_oss::mdspan>;
}
}
diff --git a/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/highfive.h b/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/highfive.h
index fb276e681..d5d91987b 100644
--- a/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/highfive.h
+++ b/externals/coda-oss/modules/c++/hdf5.lite/include/hdf5/lite/highfive.h
@@ -56,10 +56,10 @@ inline auto vv_load(const H5Easy::File& file, const std::string& dataset_name)
template
inline HighFive::DataSet writeDataSet(H5Easy::File& file, const std::string& dataset_name, SpanRC data /*, TODO ...*/)
{
- const std::vector dims{data.dims().row, data.dims().col};
+ const std::vector dims{data.extent(0), data.extent(1)};
const HighFive::DataSpace dataspace{dims};
auto retval = file.createDataSet(dataset_name, dataspace);
- retval.write_raw(data.data());
+ retval.write_raw(data.data_handle());
return retval;
}
@@ -87,7 +87,7 @@ inline SpanRC readDataSet(const HighFive::DataSet& dataSet, std::vector& r
result.resize(dims.area());
dataSet.read(result.data());
- return SpanRC(result.data(), dims);
+ return SpanRC(result.data(), std::array{dims.row, dims.col});
}
template
diff --git a/externals/coda-oss/modules/c++/hdf5.lite/unittests/test_highfive.cpp b/externals/coda-oss/modules/c++/hdf5.lite/unittests/test_highfive.cpp
index f54526ab9..9fbfd7654 100644
--- a/externals/coda-oss/modules/c++/hdf5.lite/unittests/test_highfive.cpp
+++ b/externals/coda-oss/modules/c++/hdf5.lite/unittests/test_highfive.cpp
@@ -53,10 +53,11 @@ TEST_CASE(test_highfive_load)
{
std::vector lat;
const auto rc = hdf5::lite::loadDataSet(file, "/g4/lat", lat);
+ static_assert(decltype(rc)::rank() == 2, "wrong rank()");
TEST_ASSERT_EQ(lat.size(), 19);
- TEST_ASSERT_EQ(lat.size(), rc.area());
- TEST_ASSERT_EQ(rc.dims().row, 19);
- TEST_ASSERT_EQ(rc.dims().col, 1);
+ TEST_ASSERT_EQ(lat.size(), rc.size());
+ TEST_ASSERT_EQ(rc.extent(0), 19);
+ TEST_ASSERT_EQ(rc.extent(1), 1);
TEST_ASSERT_ALMOST_EQ(lat[0], -90.0);
TEST_ASSERT_ALMOST_EQ(lat[0], -lat[18]);
}
@@ -103,9 +104,9 @@ template
static auto read_complex(const HighFive::DataSet& r, const HighFive::DataSet& i)
{
std::vector r_result;
- hdf5::lite::readDataSet(r, r_result);
+ std::ignore = hdf5::lite::readDataSet(r, r_result);
std::vector i_result;
- hdf5::lite::readDataSet(i, i_result);
+ std::ignore = hdf5::lite::readDataSet(i, i_result);
return std::make_pair(r, i);
}
template
@@ -405,11 +406,11 @@ TEST_CASE(test_highfive_write)
const types::RowCol dims{10, 20};
std::vector data_(dims.area());
- const hdf5::lite::SpanRC data(data_.data(), dims);
+ hdf5::lite::SpanRC data(data_.data(), std::array{dims.row, dims.col});
double d = 0.0;
- for (size_t r = 0; r result;
const auto rc = hdf5::lite::loadDataSet(file, "/DS1", result);
- TEST_ASSERT(rc.dims() == dims);
+ TEST_ASSERT(rc.extent(0) == dims.row);
+ TEST_ASSERT(rc.extent(1) == dims.col);
TEST_ASSERT_EQ(dims.area(), result.size());
for (size_t i = 0; i < result.size(); i++)
{
diff --git a/externals/coda-oss/modules/c++/std/include/import/std.h b/externals/coda-oss/modules/c++/std/include/import/std.h
index 32702da30..5c41ee61b 100644
--- a/externals/coda-oss/modules/c++/std/include/import/std.h
+++ b/externals/coda-oss/modules/c++/std/include/import/std.h
@@ -102,6 +102,7 @@ CODA_OSS_disable_warning_system_header_push
#include
#include
#include
+#include
CODA_OSS_disable_warning_pop
diff --git a/externals/coda-oss/modules/c++/std/include/std/mdspan b/externals/coda-oss/modules/c++/std/include/std/mdspan
new file mode 100644
index 000000000..b25c5447d
--- /dev/null
+++ b/externals/coda-oss/modules/c++/std/include/std/mdspan
@@ -0,0 +1,46 @@
+/* =========================================================================
+ * This file is part of std-c++
+ * =========================================================================
+ *
+ * © Copyright 2023, Maxar Technologies, Inc.
+ *
+ * std-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, http://www.gnu.org/licenses/.
+ *
+ */
+#pragma once
+
+#include "coda_oss/mdspan.h"
+#include "coda_oss/CPlusPlus.h"
+
+// Make it (too?) easy for clients to get our various std:: implementations
+#ifndef CODA_OSS_NO_std_mdspan
+ #if CODA_OSS_cpp23
+ #include
+ #define CODA_OSS_NO_std_mdspan 1 // part of C++23
+ #else
+ #define CODA_OSS_NO_std_mdspan 0 // use our own
+ #endif
+#endif
+
+#if !CODA_OSS_NO_std_mdspan
+namespace std // This is slightly uncouth: we're not supposed to augment "std".
+{
+ using coda_oss::mdspan;
+ using coda_oss::dextents;
+}
+#ifndef __cpp_lib_mdspan
+#define __cpp_lib_mdspan 202002L // https://en.cppreference.com/w/cpp/feature_test#cpp_lib_mdspan
+#endif
+
+#endif // CODA_OSS_NO_std_mdspan
diff --git a/externals/coda-oss/modules/c++/types/include/types/RowCol.h b/externals/coda-oss/modules/c++/types/include/types/RowCol.h
index e13f125a2..846280aaa 100644
--- a/externals/coda-oss/modules/c++/types/include/types/RowCol.h
+++ b/externals/coda-oss/modules/c++/types/include/types/RowCol.h
@@ -19,7 +19,7 @@
* see .
*
*/
-
+ #pragma once
#ifndef __TYPES_ROW_COL_H__
#define __TYPES_ROW_COL_H__
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include "gsl/gsl.h"
@@ -78,6 +79,11 @@ template class RowCol
row = p.first;
col = p.second;
}
+ explicit RowCol(const std::array& a) noexcept
+ {
+ row = a[0];
+ col = a[1];
+ }
template RowCol& operator=(const RowCol& p) noexcept
{