COPP C++ API
C++ interface for COPP trajectory optimization
Loading...
Searching...
No Matches
core.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <initializer_list>
5#include <optional>
6#include <stdexcept>
7#include <string>
8#include <type_traits>
9#include <utility>
10#include <vector>
11
12#if defined(_WIN32)
13#if defined(COPP_CPP_BUILDING_LIBRARY)
14#define COPP_API __declspec(dllexport)
15#elif defined(COPP_CPP_SHARED) && COPP_CPP_SHARED
16#define COPP_API __declspec(dllimport)
17#else
18#define COPP_API
19#endif
20#elif defined(__GNUC__) || defined(__clang__)
21#define COPP_API __attribute__((visibility("default")))
22#else
23#define COPP_API
24#endif
25
26namespace copp
27{
28
34 enum class Status
35 {
36 ok = 0,
39 };
40
46 enum class Verbosity
47 {
48 Silent = 0,
50 Debug = 2,
51 Trace = 3,
52 };
53
61 COPP_API std::string version();
62
67 {
68 std::size_t idx_s_start = 0;
69 std::size_t idx_s_final = 0;
70 };
71
76 struct Boundary2
77 {
78 double a_start = 0.0;
79 double a_final = 0.0;
80 };
81
86 struct Boundary3
87 {
88 double a_start = 0.0;
89 double a_final = 0.0;
90 double b_start = 0.0;
91 double b_final = 0.0;
92 };
93
99 class Error : public std::runtime_error
100 {
101 public:
102 Error(Status status, std::string message)
103 : std::runtime_error(std::move(message)), status_(status) {}
104
105 Status status() const noexcept { return status_; }
106
107 private:
108 Status status_;
109 };
110
116 enum class MatrixLayout
117 {
120 };
121
137 template <typename T>
138 class Span
139 {
140 public:
141 using element_type = T;
142 using pointer = T *;
143 using reference = T &;
144
145 constexpr Span() noexcept = default;
146
147 constexpr Span(pointer data, std::size_t size) noexcept : data_(data), size_(size) {}
148
149 template <std::size_t N>
150 constexpr Span(element_type (&data)[N]) noexcept : data_(data), size_(N) {}
151
152 template <
153 typename Container,
154 typename = decltype(std::declval<Container &>().data()),
155 typename = decltype(std::declval<Container &>().size())>
156 Span(Container &container) noexcept
157 : data_(container.data()), size_(static_cast<std::size_t>(container.size())) {}
158
159 template <
160 typename Container,
161 typename = decltype(std::declval<const Container &>().data()),
162 typename = decltype(std::declval<const Container &>().size()),
163 typename U = element_type,
164 typename = typename std::enable_if<std::is_const<U>::value>::type>
165 Span(const Container &container) noexcept
166 : data_(container.data()), size_(static_cast<std::size_t>(container.size())) {}
167
168 constexpr pointer data() const noexcept { return data_; }
169 constexpr std::size_t size() const noexcept { return size_; }
170 constexpr bool empty() const noexcept { return size_ == 0; }
171
172 reference operator[](std::size_t index) const noexcept { return data_[index]; }
173
174 private:
175 pointer data_ = nullptr;
176 std::size_t size_ = 0;
177 };
178
205 {
206 public:
207 constexpr MatrixView() noexcept = default;
208
209 constexpr MatrixView(
210 const double *data,
211 std::size_t rows,
212 std::size_t cols,
214 std::size_t leading_dim) noexcept
215 : data_(data), rows_(rows), cols_(cols), layout_(layout), leading_dim_(leading_dim) {}
216
217 static constexpr MatrixView column_major(
218 const double *data,
219 std::size_t rows,
220 std::size_t cols) noexcept
221 {
223 }
224
226 const double *data,
227 std::size_t rows,
228 std::size_t cols,
229 std::size_t leading_dim) noexcept
230 {
232 }
233
234 static constexpr MatrixView row_major(
235 const double *data,
236 std::size_t rows,
237 std::size_t cols) noexcept
238 {
240 }
241
242 constexpr const double *data() const noexcept { return data_; }
243 constexpr std::size_t rows() const noexcept { return rows_; }
244 constexpr std::size_t cols() const noexcept { return cols_; }
245 constexpr MatrixLayout layout() const noexcept { return layout_; }
246 constexpr std::size_t leading_dim() const noexcept { return leading_dim_; }
247
248 constexpr std::size_t storage_size() const noexcept
249 {
250 if (rows_ == 0 || cols_ == 0)
251 {
252 return 0;
253 }
254 if (layout_ == MatrixLayout::ColumnMajor)
255 {
256 return leading_dim_ * (cols_ - 1) + rows_;
257 }
258 return leading_dim_ * (rows_ - 1) + cols_;
259 }
260
261 private:
262 const double *data_ = nullptr;
263 std::size_t rows_ = 0;
264 std::size_t cols_ = 0;
266 std::size_t leading_dim_ = 0;
267 };
268
288 {
289 public:
290 constexpr MatrixRef() noexcept = default;
291
292 constexpr MatrixRef(
293 double *data,
294 std::size_t rows,
295 std::size_t cols,
296 std::size_t leading_dim) noexcept
297 : data_(data), rows_(rows), cols_(cols), leading_dim_(leading_dim) {}
298
299 static constexpr MatrixRef column_major(
300 double *data,
301 std::size_t rows,
302 std::size_t cols) noexcept
303 {
304 return MatrixRef(data, rows, cols, rows);
305 }
306
308 double *data,
309 std::size_t rows,
310 std::size_t cols,
311 std::size_t leading_dim) noexcept
312 {
314 }
315
316 constexpr double *data() const noexcept { return data_; }
317 constexpr std::size_t rows() const noexcept { return rows_; }
318 constexpr std::size_t cols() const noexcept { return cols_; }
319 constexpr std::size_t leading_dim() const noexcept { return leading_dim_; }
320
321 double &operator()(std::size_t row, std::size_t col) const noexcept
322 {
323 return data_[row + col * leading_dim_];
324 }
325
326 private:
327 double *data_ = nullptr;
328 std::size_t rows_ = 0;
329 std::size_t cols_ = 0;
330 std::size_t leading_dim_ = 0;
331 };
332
351 class Matrix
352 {
353 public:
354 Matrix() = default;
355
356 Matrix(std::size_t rows, std::size_t cols)
357 : rows_(rows), cols_(cols), data_(rows * cols) {}
358
359 Matrix(std::size_t rows, std::size_t cols, std::vector<double> data)
360 : rows_(rows), cols_(cols), data_(std::move(data))
361 {
362 if (data_.size() != rows_ * cols_)
363 {
364 throw Error(Status::invalid_input, "Matrix data length does not match shape");
365 }
366 }
367
382 static Matrix from_rows(std::initializer_list<std::initializer_list<double>> rows)
383 {
384 if (rows.size() == 0)
385 {
386 throw Error(Status::invalid_input, "Matrix::from_rows requires at least one row");
387 }
388
389 const std::size_t row_count = rows.size();
390 const std::size_t col_count = rows.begin()->size();
391 if (col_count == 0)
392 {
393 throw Error(Status::invalid_input, "Matrix::from_rows requires at least one column");
394 }
395
396 Matrix matrix(row_count, col_count);
397 std::size_t row = 0;
398 for (const auto &row_values : rows)
399 {
400 if (row_values.size() != col_count)
401 {
402 throw Error(Status::invalid_input, "Matrix::from_rows requires rectangular input");
403 }
404 std::size_t col = 0;
405 for (double value : row_values)
406 {
407 matrix(row, col) = value;
408 ++col;
409 }
410 ++row;
411 }
412 return matrix;
413 }
414
433 static Matrix from_columns(std::initializer_list<std::initializer_list<double>> columns)
434 {
435 if (columns.size() == 0)
436 {
437 throw Error(Status::invalid_input, "Matrix::from_columns requires at least one column");
438 }
439
440 const std::size_t col_count = columns.size();
441 const std::size_t row_count = columns.begin()->size();
442 if (row_count == 0)
443 {
444 throw Error(Status::invalid_input, "Matrix::from_columns requires at least one row");
445 }
446
447 Matrix matrix(row_count, col_count);
448 std::size_t col = 0;
449 for (const auto &col_values : columns)
450 {
451 if (col_values.size() != row_count)
452 {
453 throw Error(Status::invalid_input, "Matrix::from_columns requires rectangular input");
454 }
455 std::size_t row = 0;
456 for (double value : col_values)
457 {
458 matrix(row, col) = value;
459 ++row;
460 }
461 ++col;
462 }
463 return matrix;
464 }
465
466 std::size_t rows() const noexcept { return rows_; }
467 std::size_t cols() const noexcept { return cols_; }
468 std::size_t size() const noexcept { return data_.size(); }
469 bool empty() const noexcept { return data_.empty(); }
470
471 double *data() noexcept { return data_.data(); }
472 const double *data() const noexcept { return data_.data(); }
473
474 std::vector<double> &values() noexcept { return data_; }
475 const std::vector<double> &values() const noexcept { return data_; }
476
477 MatrixView view() const noexcept
478 {
479 return MatrixView::column_major(data(), rows_, cols_);
480 }
481
482 double &operator()(std::size_t row, std::size_t col) noexcept
483 {
484 return data_[row + col * rows_];
485 }
486
487 double operator()(std::size_t row, std::size_t col) const noexcept
488 {
489 return data_[row + col * rows_];
490 }
491
492 private:
493 std::size_t rows_ = 0;
494 std::size_t cols_ = 0;
495 std::vector<double> data_;
496 };
497
503 {
505 std::string message;
506 };
507
525 template <typename T>
527 {
528 public:
529 Expected(T value) : value_(std::move(value)) {}
530
531 static Expected failure(Status status, std::string message)
532 {
533 Expected out;
534 out.error_ = ErrorInfo{status, std::move(message)};
535 return out;
536 }
537
538 bool has_value() const noexcept { return value_.has_value(); }
539 explicit operator bool() const noexcept { return has_value(); }
540
541 T &value() &
542 {
543 if (!value_)
544 {
545 throw Error(error_.status, error_.message);
546 }
547 return *value_;
548 }
549
550 const T &value() const &
551 {
552 if (!value_)
553 {
554 throw Error(error_.status, error_.message);
555 }
556 return *value_;
557 }
558
559 T &&value() &&
560 {
561 if (!value_)
562 {
563 throw Error(error_.status, error_.message);
564 }
565 return std::move(*value_);
566 }
567
568 const ErrorInfo &error() const noexcept { return error_; }
569
570 private:
571 Expected() = default;
572
573 std::optional<T> value_;
574 ErrorInfo error_;
575 };
576
577 namespace detail
578 {
579 template <typename Fn>
580 auto expected_from(Fn &&fn) -> Expected<typename std::decay<decltype(fn())>::type>
581 {
582 using T = typename std::decay<decltype(fn())>::type;
583 try
584 {
585 return Expected<T>(fn());
586 }
587 catch (const Error &error)
588 {
589 return Expected<T>::failure(error.status(), error.what());
590 }
591 catch (const std::exception &error)
592 {
593 return Expected<T>::failure(Status::invalid_input, error.what());
594 }
595 catch (...)
596 {
597 return Expected<T>::failure(Status::bridge_error, "unknown C++ exception");
598 }
599 }
600 } // namespace detail
601
608 {
609 explicit constexpr NoThrowTag() = default;
610 };
611
612 inline constexpr NoThrowTag no_throw{};
613
614} // namespace copp
Exception type thrown by the default C++ API.
Definition core.hpp:100
Status status() const noexcept
Definition core.hpp:105
Error(Status status, std::string message)
Definition core.hpp:102
Small C++17 expected-like result used by no-throw overloads.
Definition core.hpp:527
bool has_value() const noexcept
Definition core.hpp:538
const ErrorInfo & error() const noexcept
Definition core.hpp:568
T && value() &&
Definition core.hpp:559
const T & value() const &
Definition core.hpp:550
T & value() &
Definition core.hpp:541
static Expected failure(Status status, std::string message)
Definition core.hpp:531
Expected(T value)
Definition core.hpp:529
double & operator()(std::size_t row, std::size_t col) noexcept
Definition core.hpp:482
const double * data() const noexcept
Definition core.hpp:472
static Matrix from_columns(std::initializer_list< std::initializer_list< double > > columns)
Build a matrix from column-major initializer-list notation.
Definition core.hpp:433
double operator()(std::size_t row, std::size_t col) const noexcept
Definition core.hpp:487
std::size_t cols() const noexcept
Definition core.hpp:467
MatrixView view() const noexcept
Definition core.hpp:477
std::size_t size() const noexcept
Definition core.hpp:468
Matrix()=default
bool empty() const noexcept
Definition core.hpp:469
const std::vector< double > & values() const noexcept
Definition core.hpp:475
std::size_t rows() const noexcept
Definition core.hpp:466
Matrix(std::size_t rows, std::size_t cols)
Definition core.hpp:356
std::vector< double > & values() noexcept
Definition core.hpp:474
static Matrix from_rows(std::initializer_list< std::initializer_list< double > > rows)
Build a matrix from row-major initializer-list notation.
Definition core.hpp:382
Matrix(std::size_t rows, std::size_t cols, std::vector< double > data)
Definition core.hpp:359
double * data() noexcept
Definition core.hpp:471
double & operator()(std::size_t row, std::size_t col) const noexcept
Definition core.hpp:321
constexpr std::size_t leading_dim() const noexcept
Definition core.hpp:319
constexpr double * data() const noexcept
Definition core.hpp:316
static constexpr MatrixRef strided_column_major(double *data, std::size_t rows, std::size_t cols, std::size_t leading_dim) noexcept
Definition core.hpp:307
constexpr MatrixRef() noexcept=default
constexpr std::size_t cols() const noexcept
Definition core.hpp:318
constexpr std::size_t rows() const noexcept
Definition core.hpp:317
static constexpr MatrixRef column_major(double *data, std::size_t rows, std::size_t cols) noexcept
Definition core.hpp:299
Non-owning view of a two-dimensional double matrix.
Definition core.hpp:205
constexpr std::size_t storage_size() const noexcept
Definition core.hpp:248
constexpr std::size_t leading_dim() const noexcept
Definition core.hpp:246
constexpr MatrixLayout layout() const noexcept
Definition core.hpp:245
static constexpr MatrixView row_major(const double *data, std::size_t rows, std::size_t cols) noexcept
Definition core.hpp:234
constexpr std::size_t cols() const noexcept
Definition core.hpp:244
static constexpr MatrixView strided_column_major(const double *data, std::size_t rows, std::size_t cols, std::size_t leading_dim) noexcept
Definition core.hpp:225
static constexpr MatrixView column_major(const double *data, std::size_t rows, std::size_t cols) noexcept
Definition core.hpp:217
constexpr MatrixView() noexcept=default
constexpr std::size_t rows() const noexcept
Definition core.hpp:243
constexpr const double * data() const noexcept
Definition core.hpp:242
constexpr bool empty() const noexcept
Definition core.hpp:170
constexpr Span() noexcept=default
constexpr Span(element_type(&data)[N]) noexcept
Definition core.hpp:150
Span(Container &container) noexcept
Definition core.hpp:156
constexpr pointer data() const noexcept
Definition core.hpp:168
T * pointer
Definition core.hpp:142
constexpr std::size_t size() const noexcept
Definition core.hpp:169
Span(const Container &container) noexcept
Definition core.hpp:165
T & reference
Definition core.hpp:143
reference operator[](std::size_t index) const noexcept
Definition core.hpp:172
T element_type
Definition core.hpp:141
#define COPP_API
Definition core.hpp:23
auto expected_from(Fn &&fn) -> Expected< typename std::decay< decltype(fn())>::type >
Definition core.hpp:580
Root namespace for the C++ facade: paths, robots, constraints, matrices, profiles,...
MatrixLayout
Memory layout for borrowed matrix views.
Definition core.hpp:117
Verbosity
Diagnostic verbosity for solver algorithms.
Definition core.hpp:47
Status
Coarse error category reported by the C++ facade.
Definition core.hpp:35
@ invalid_input
Definition core.hpp:37
@ bridge_error
Definition core.hpp:38
constexpr NoThrowTag no_throw
Definition core.hpp:612
@ Error
Throw copp::Error when any query sample is outside [s_min, s_max].
Definition path.hpp:299
COPP_API std::string version()
Return the Rust crate version backing this C++ facade.
Second-order endpoint boundary values.
Definition core.hpp:77
double a_final
Definition core.hpp:79
double a_start
Definition core.hpp:78
Third-order endpoint boundary values.
Definition core.hpp:87
double a_final
Definition core.hpp:89
double a_start
Definition core.hpp:88
double b_start
Definition core.hpp:90
double b_final
Definition core.hpp:91
Lightweight error payload returned by no-throw APIs.
Definition core.hpp:503
Status status
Definition core.hpp:504
std::string message
Definition core.hpp:505
Closed station-index interval used by TOPP/COPP problem descriptors.
Definition core.hpp:67
std::size_t idx_s_final
Definition core.hpp:69
std::size_t idx_s_start
Definition core.hpp:68
Tag object selecting no-throw overloads.
Definition core.hpp:608
constexpr NoThrowTag()=default