PLaSK library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 "common.hpp"
27#include <cassert>
28
29#include "../utils/metaprog.hpp" // for is_callable
30#include "../utils/warnings.hpp"
31
32namespace plask {
33
37template <typename T>
38struct Vec<2,T> {
39
40 static const int DIMS = 2;
41
42 T c0, c1;
43
44 T& tran() { return c0; }
45 constexpr const T& tran() const { return c0; }
46
47 T& vert() { return c1; }
48 constexpr const T& vert() const { return c1; }
49
50 // radial coordinates
51 T& rad_r() { return c0; }
52 constexpr const T& rad_r() const { return c0; }
53 T& rad_z() { return c1; }
54 constexpr const T& rad_z() const { return c1; }
55
56 // for surface-emitting lasers (z-axis up)
57 T& se_y() { return c0; }
58 constexpr const T& se_y() const { return c0; }
59 T& se_z() { return c1; }
60 constexpr const T& se_z() const { return c1; }
61
62 // for surface-emitting lasers (z-axis up)
63 T& zup_y() { return c0; }
64 constexpr const T& z_up_y() const { return c0; }
65 T& zup_z() { return c1; }
66 constexpr const T& z_up_z() const { return c1; }
67
68 // for edge emitting lasers (y-axis up), we keep the coordinates right-handed
69 T& ee_x() { return c0; }
70 constexpr const T& ee_x() const { return c0; }
71 T& ee_y() { return c1; }
72 constexpr const T& ee_y() const { return c1; }
73
74 // for edge emitting lasers (y-axis up), we keep the coordinates right-handed
75 T& yup_x() { return c0; }
76 constexpr const T& y_up_x() const { return c0; }
77 T& yup_y() { return c1; }
78 constexpr const T& y_up_y() const { return c1; }
79
80
84 typedef T* iterator;
85
89 typedef const T* const_iterator;
90
92 Vec() {}
93
98 template <typename OtherT>
99 constexpr Vec(const Vec<2,OtherT>& p): c0(p.c0), c1(p.c1) {}
100
105 constexpr Vec(const T& c0__tran, const T& c1__up): c0(c0__tran), c1(c1__up) {}
106
111 template <typename T0, typename T1>
112 constexpr Vec(const std::pair<T0,T1>& comp): c0(comp.first), c1(comp.second) {}
113
119 template <typename InputIteratorType>
122 result.c0 = T(*inputIt);
123 result.c1 = T(*++inputIt);
124 return result;
125 }
126
131 iterator begin() { return &c0; }
132
137 const_iterator begin() const { return &c0; }
138
143 iterator end() { return &c0 + 2; }
144
149 const_iterator end() const { return &c0 + 2; }
150
156 template <typename OtherT>
157 constexpr bool operator==(const Vec<2,OtherT>& p) const { return p.c0 == c0 && p.c1 == c1; }
158
165 template <typename OtherT, typename SuprType>
166 constexpr bool equals(const Vec<2, OtherT>& p, const SuprType& abs_supremum) const {
167 return is_zero(p.c0 - c0, abs_supremum) && is_zero(p.c1 - c1, abs_supremum); }
168
174 template <typename OtherT>
175 constexpr bool equals(const Vec<2, OtherT>& p) const {
176 return is_zero(p.c0 - c0) && is_zero(p.c1 - c1); }
177
183 template <typename OtherT>
184 constexpr bool operator!=(const Vec<2,OtherT>& p) const { return p.c0 != c0 || p.c1 != c1; }
185
192 inline T& operator[](size_t i) {
193 assert(i < 2);
194 return *(&c0 + i);
195 }
196
203 inline const T& operator[](size_t i) const {
204 assert(i < 2);
205 return *(&c0 + i);
206 }
207
213 template <typename OtherT>
214 constexpr auto operator+(const Vec<2,OtherT>& other) const -> Vec<2,decltype(c0 + other.c0)> {
215 return Vec<2,decltype(this->c0 + other.c0)>(c0 + other.c0, c1 + other.c1);
216 }
217
223 Vec<2,T>& operator+=(const Vec<2,T>& other) {
224 c0 += other.c0;
225 c1 += other.c1;
226 return *this;
227 }
228
234 template <typename OtherT>
235 constexpr auto operator-(const Vec<2,OtherT>& other) const -> Vec<2,decltype(c0 - other.c0)> {
236 return Vec<2,decltype(this->c0 - other.c0)>(c0 - other.c0, c1 - other.c1);
237 }
238
244 Vec<2,T>& operator-=(const Vec<2,T>& other) {
245 c0 -= other.c0;
246 c1 -= other.c1;
247 return *this;
248 }
249
255 template <typename OtherT>
256 constexpr auto operator*(const OtherT scale) const -> Vec<2,decltype(c0*scale)> {
258 return Vec<2,decltype(c0*scale)>(c0 * scale, c1 * scale);
260 }
261
268 c0 *= scalar;
269 c1 *= scalar;
270 return *this;
271 }
272
278 template <typename OtherT>
279 constexpr auto operator/(const OtherT scale) const -> Vec<2,decltype(c0/scale)> {
281 return Vec<2,decltype(c0*scale)>(c0 / scale, c1 / scale);
283 }
284
291 c0 /= scalar;
292 c1 /= scalar;
293 return *this;
294 }
295
300 constexpr Vec<2,T> operator-() const {
301 return Vec<2,T>(-c0, -c1);
302 }
303
308 Vec<2,T> sqr() const {
309 return Vec<2,T>(c0*c0, c1*c1);
310 }
311
317 c0 *= c0; c1 *= c1;
318 return *this;
319 }
320
325 Vec<2,T> sqrt() const {
326 return Vec<2,T>(std::sqrt(c0), std::sqrt(c1));
327 }
328
334 c0 = std::sqrt(c0); c1 = std::sqrt(c1);
335 return *this;
336 }
337
342 template <typename OtherT>
344 return Vec<2,T>(std::pow(c0, a), std::pow(c1, a));
345 }
346
352 inline void flip(size_t i) {
353 assert(i < 2);
354 operator[](i) = -operator[](i);
355 }
356
363 inline Vec<2,T> flipped(size_t i) {
364 Vec<2,T> res = *this;
365 res.flip(i);
366 return res;
367 }
368
375 friend inline std::ostream& operator<<(std::ostream& out, const Vec<2,T>& to_print) {
376 return out << '[' << to_print.c0 << ", " << to_print.c1 << ']';
377 }
378
386 template<class OT> inline
387 bool operator< (Vec<2, OT> const& v) const {
388 if (dbl_compare_lt(this->c0, v.c0)) return true;
389 if (dbl_compare_gt(this->c0, v.c0)) return false;
390 return dbl_compare_lt(this->c1, v.c1);
391 }
392};
393
399template <typename T>
400inline constexpr Vec<2,T> conj(const Vec<2,T>& v) { return Vec<2,T>(conj(v.c0), conj(v.c1)); }
401
408template <typename T1, typename T2>
409inline auto dot(const Vec<2,T1>& v1, const Vec<2,T2>& v2) -> decltype(v1.c0*v2.c0) {
410 return ::plask::fma(v1.c0, v2.c0, v1.c1 * v2.c1); //MSVC needs ::plask::
411}
412
418template <typename T1, typename T2>
419inline auto cross(const Vec<2,T1>& v1, const Vec<2,T2>& v2) -> decltype(v1.c0*v2.c1) {
420 return ::plask::fma(v1.c0, v2.c1, - v1.c1 * v2.c0); //MSVC needs ::plask::
421}
422
429//template <> //MSVC2015 doesn't support this specialization, and using overloding shouldn't have negative consequences
430inline auto dot(const Vec<2,dcomplex>& v1, const Vec<2,double>& v2) -> decltype(v1.c0*v2.c0) {
431 return ::plask::fma(conj(v1.c0), v2.c0, conj(v1.c1) * v2.c1); //MSVC needs ::plask::
432}
433
440//template <> //MSVC2015 doesn't support this specialization, and using overloding shouldn't have negative consequences
441inline auto dot(const Vec<2,dcomplex>& v1, const Vec<2,dcomplex>& v2) -> decltype(v1.c0*v2.c0) {
442 return ::plask::fma(conj(v1.c0), v2.c0, conj(v1.c1) * v2.c1); //MSVC needs ::plask::
443}
444
450template <typename T>
451inline constexpr Vec<2,T> vec(const T c0__tran, const T c1__up) {
452 return Vec<2,T>(c0__tran, c1__up);
453}
454
456template <typename T>
457struct NaNImpl<Vec<2,T>> {
458 static constexpr Vec<2,T> get() { return Vec<2,T>(NaN<T>(), NaN<T>()); }
459};
460
462template <typename T>
463struct ZeroImpl<Vec<2,T>> {
464 static constexpr Vec<2,T> get() { return Vec<2,T>(0., 0.); }
465};
466
469template <typename T>
470inline bool is_zero(const Vec<2,T>& v) {
471 return is_zero(v.c0) && is_zero(v.c1);
472}
473
474
476PLASK_API_EXTERN_TEMPLATE_SPECIALIZATION_STRUCT(Vec<2, std::complex<double> >)
477
478} //namespace plask
479
480namespace std {
481 template <typename T>
483 return vec.sqrt();
484 }
485
486 template <typename T, typename OtherT>
488 return vec.pow(a);
489 }
490}
491
492#endif // PLASK__VECTOR2D_H