PLaSK library

Loading...
Searching...
No Matches
2d.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__VECTOR2D_H
15#define PLASK__VECTOR2D_H
16
21#include <iostream>
22
23#include "../math.hpp"
24#include <plask/exceptions.hpp>
25
26#include <cassert>
27#include "common.hpp"
28
29#include "../utils/metaprog.hpp" // for is_callable
30#include "../utils/warnings.hpp"
31
32 namespace plask {
33
37 template <typename T> struct Vec<2, T> {
38 static const int DIMS = 2;
39
40 T c0, c1;
41
42 T& tran() { return c0; }
43 constexpr const T& tran() const { return c0; }
44
45 T& vert() { return c1; }
46 constexpr const T& vert() const { return c1; }
47
48 // radial coordinates
49 T& rad_r() { return c0; }
50 constexpr const T& rad_r() const { return c0; }
51 T& rad_z() { return c1; }
52 constexpr const T& rad_z() const { return c1; }
53
54 // for surface-emitting lasers (z-axis up)
55 T& se_y() { return c0; }
56 constexpr const T& se_y() const { return c0; }
57 T& se_z() { return c1; }
58 constexpr const T& se_z() const { return c1; }
59
60 // for surface-emitting lasers (z-axis up)
61 T& zup_y() { return c0; }
62 constexpr const T& z_up_y() const { return c0; }
63 T& zup_z() { return c1; }
64 constexpr const T& z_up_z() const { return c1; }
65
66 // for edge emitting lasers (y-axis up), we keep the coordinates right-handed
67 T& ee_x() { return c0; }
68 constexpr const T& ee_x() const { return c0; }
69 T& ee_y() { return c1; }
70 constexpr const T& ee_y() const { return c1; }
71
72 // for edge emitting lasers (y-axis up), we keep the coordinates right-handed
73 T& yup_x() { return c0; }
74 constexpr const T& y_up_x() const { return c0; }
75 T& yup_y() { return c1; }
76 constexpr const T& y_up_y() const { return c1; }
77
81 typedef T* iterator;
82
86 typedef const T* const_iterator;
87
89 Vec() {}
90
95 template <typename OtherT> constexpr Vec(const Vec<2, OtherT>& p) : c0(p.c0), c1(p.c1) {}
96
101 constexpr Vec(const T& c0__tran, const T& c1__up) : c0(c0__tran), c1(c1__up) {}
102
107 template <typename T0, typename T1> constexpr Vec(const std::pair<T0, T1>& comp) : c0(comp.first), c1(comp.second) {}
108
114 template <typename InputIteratorType> static inline Vec<2, T> fromIterator(InputIteratorType inputIt) {
115 Vec<2, T> result;
116 result.c0 = T(*inputIt);
117 result.c1 = T(*++inputIt);
118 return result;
119 }
120
125 iterator begin() { return &c0; }
126
131 const_iterator begin() const { return &c0; }
132
137 iterator end() { return &c0 + 2; }
138
143 const_iterator end() const { return &c0 + 2; }
144
150 template <typename OtherT> constexpr bool operator==(const Vec<2, OtherT>& p) const { return p.c0 == c0 && p.c1 == c1; }
151
158 template <typename OtherT, typename SuprType>
159 constexpr bool equals(const Vec<2, OtherT>& p, const SuprType& abs_supremum) const {
160 return is_zero(p.c0 - c0, abs_supremum) && is_zero(p.c1 - c1, abs_supremum);
161 }
162
168 template <typename OtherT> constexpr bool equals(const Vec<2, OtherT>& p) const {
169 return is_zero(p.c0 - c0) && is_zero(p.c1 - c1);
170 }
171
177 template <typename OtherT> constexpr bool operator!=(const Vec<2, OtherT>& p) const { return p.c0 != c0 || p.c1 != c1; }
178
185 inline T& operator[](size_t i) {
186 assert(i < 2);
187 return *(&c0 + i);
188 }
189
196 inline const T& operator[](size_t i) const {
197 assert(i < 2);
198 return *(&c0 + i);
199 }
200
206 template <typename OtherT> constexpr auto operator+(const Vec<2, OtherT>& other) const -> Vec<2, decltype(c0 + other.c0)> {
207 return Vec<2, decltype(this->c0 + other.c0)>(c0 + other.c0, c1 + other.c1);
208 }
209
215 Vec<2, T>& operator+=(const Vec<2, T>& other) {
216 c0 += other.c0;
217 c1 += other.c1;
218 return *this;
219 }
220
227 template <typename OtherT> constexpr auto operator-(const Vec<2, OtherT>& other) const -> Vec<2, decltype(c0 - other.c0)> {
228 return Vec<2, decltype(this->c0 - other.c0)>(c0 - other.c0, c1 - other.c1);
229 }
230
236 Vec<2, T>& operator-=(const Vec<2, T>& other) {
237 c0 -= other.c0;
238 c1 -= other.c1;
239 return *this;
240 }
241
247 template <typename OtherT> constexpr auto operator*(const OtherT scale) const -> Vec<2, decltype(c0 * scale)> {
248 PLASK_NO_CONVERSION_WARNING_BEGIN
249 return Vec<2, decltype(c0 * scale)>(c0 * scale, c1 * scale);
250 PLASK_NO_WARNING_END
251 }
252
258 Vec<2, T>& operator*=(const T scalar) {
259 c0 *= scalar;
260 c1 *= scalar;
261 return *this;
262 }
263
269 template <typename OtherT> constexpr auto operator/(const OtherT scale) const -> Vec<2, decltype(c0 / scale)> {
270 PLASK_NO_CONVERSION_WARNING_BEGIN
271 return Vec<2, decltype(c0 * scale)>(c0 / scale, c1 / scale);
272 PLASK_NO_WARNING_END
273 }
274
280 Vec<2, T>& operator/=(const T scalar) {
281 c0 /= scalar;
282 c1 /= scalar;
283 return *this;
284 }
285
290 constexpr Vec<2, T> operator-() const { return Vec<2, T>(-c0, -c1); }
291
296 Vec<2, T> sqr() const { return Vec<2, T>(c0 * c0, c1 * c1); }
297
302 Vec<2, T>& sqr_inplace() {
303 c0 *= c0;
304 c1 *= c1;
305 return *this;
306 }
307
312 Vec<2, T> sqrt() const {
313 PLASK_NO_CONVERSION_WARNING_BEGIN
314 return Vec<2, T>(std::sqrt(c0), std::sqrt(c1));
315 PLASK_NO_WARNING_END
316 }
317
322 Vec<2, T>& sqrt_inplace() {
323 c0 = std::sqrt(c0);
324 c1 = std::sqrt(c1);
325 return *this;
326 }
327
332 template <typename OtherT> Vec<2, T> pow(OtherT a) const { return Vec<2, T>(std::pow(c0, a), std::pow(c1, a)); }
333
339 inline void flip(size_t i) {
340 assert(i < 2);
341 operator[](i) = -operator[](i);
342 }
343
350 inline Vec<2, T> flipped(size_t i) {
351 Vec<2, T> res = *this;
352 res.flip(i);
353 return res;
354 }
355
362 friend inline std::ostream& operator<<(std::ostream& out, const Vec<2, T>& to_print) {
363 return out << '[' << to_print.c0 << ", " << to_print.c1 << ']';
364 }
365
373 template <class OT> inline bool operator<(Vec<2, OT> const& v) const {
374 if (dbl_compare_lt(this->c0, v.c0)) return true;
375 if (dbl_compare_gt(this->c0, v.c0)) return false;
376 return dbl_compare_lt(this->c1, v.c1);
377 }
378};
379
385 template <typename T> inline constexpr Vec<2, T> conj(const Vec<2, T>& v) { return Vec<2, T>(conj(v.c0), conj(v.c1)); }
386
393 template <typename T1, typename T2> inline auto dot(const Vec<2, T1>& v1, const Vec<2, T2>& v2) -> decltype(v1.c0 * v2.c0) {
394 return ::plask::fma(v1.c0, v2.c0, v1.c1 * v2.c1); // MSVC needs ::plask::
395}
396
402 template <typename T1, typename T2> inline auto cross(const Vec<2, T1>& v1, const Vec<2, T2>& v2) -> decltype(v1.c0 * v2.c1) {
403 return ::plask::fma(v1.c0, v2.c1, -v1.c1 * v2.c0); // MSVC needs ::plask::
404}
405
412// template <> //MSVC2015 doesn't support this specialization, and using overloding shouldn't have negative consequences
413 inline auto dot(const Vec<2, dcomplex>& v1, const Vec<2, double>& v2) -> decltype(v1.c0 * v2.c0) {
414 return ::plask::fma(conj(v1.c0), v2.c0, conj(v1.c1) * v2.c1); // MSVC needs ::plask::
415}
416
423// template <> //MSVC2015 doesn't support this specialization, and using overloding shouldn't have negative consequences
424 inline auto dot(const Vec<2, dcomplex>& v1, const Vec<2, dcomplex>& v2) -> decltype(v1.c0 * v2.c0) {
425 return ::plask::fma(conj(v1.c0), v2.c0, conj(v1.c1) * v2.c1); // MSVC needs ::plask::
426}
427
433 template <typename T> inline constexpr Vec<2, T> vec(const T c0__tran, const T c1__up) { return Vec<2, T>(c0__tran, c1__up); }
434
436 template <typename T> struct NaNImpl<Vec<2, T>> {
437 static constexpr Vec<2, T> get() { return Vec<2, T>(NaN<T>(), NaN<T>()); }
438};
439
441 template <typename T> struct ZeroImpl<Vec<2, T>> {
442 static constexpr Vec<2, T> get() { return Vec<2, T>(0., 0.); }
443};
444
447 template <typename T> inline bool is_zero(const Vec<2, T>& v) { return is_zero(v.c0) && is_zero(v.c1); }
448
449 PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_STRUCT(Vec<2, double>)
450 PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_STRUCT(Vec<2, std::complex<double>>)
451
452} // namespace plask
453
454 namespace std {
455 template <typename T> plask::Vec<2, T> sqrt(plask::Vec<2, T> vec) { return vec.sqrt(); }
456
457 template <typename T, typename OtherT> plask::Vec<2, T> pow(plask::Vec<2, T> vec, OtherT a) { return vec.pow(a); }
458} // namespace std
459
460#if FMT_VERSION >= 90000
461 template <typename T> struct fmt::formatter<plask::Vec<2, T>> : ostream_formatter {};
462#endif
463
464#endif // PLASK__VECTOR2D_H