ARTS  2.4.0(git:4fb77825)
complex.cc
Go to the documentation of this file.
1 /* Copyright (C) 2002-2012 Stefan Buehler <sbuehler@ltu.se>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
26 #include "complex.h"
27 #include <cmath>
28 #include <cstring>
29 #include "blas.h"
30 #include "exceptions.h"
31 
32 using std::runtime_error;
33 using std::setw;
34 
35 // Functions for ConstComplexVectorView:
36 // ------------------------------
37 
39 // bool ConstComplexVectorView::empty() const
40 // {
41 // return (nelem() == 0);
42 // }
43 
53 // Index ConstComplexVectorView::nelem() const
54 // {
55 // return mrange.mextent;
56 // }
57 
60  Complex s = 0;
62  const ConstComplexIterator1D e = end();
63 
64  for (; i != e; ++i) s += *i;
65 
66  return s;
67 }
68 
73  const Range& r) const {
75 }
76 
80 }
81 
86  mrange.mstride);
87 }
88 
90 ConstComplexVectorView::operator ConstComplexMatrixView() const {
91  return ConstComplexMatrixView(mdata, mrange, Range(0, 1));
92 }
93 
102  : mrange(0, 1), mdata(&const_cast<Complex&>(a)) {
103  // Nothing to do here.
104 }
105 
109  const Range& range)
110  : mrange(range), mdata(data) {
111  // Nothing to do here.
112 }
113 
125  const Range& p,
126  const Range& n)
127  : mrange(p, n), mdata(data) {
128  // Nothing to do here.
129 }
130 
134 std::ostream& operator<<(std::ostream& os, const ConstComplexVectorView& v) {
136  const ConstComplexIterator1D end = v.end();
137 
138  if (i != end) {
139  os << setw(3) << *i;
140  ++i;
141  }
142  for (; i != end; ++i) {
143  os << " " << setw(3) << *i;
144  }
145 
146  return os;
147 }
148 
149 // Functions for ComplexVectorView:
150 // ------------------------
151 
155  throw runtime_error(
156  "Creating a ComplexVectorView from a const ComplexVector is not allowed.");
157  // This is not really a runtime error, but I don't want to start
158  // producing direct output from inside matpack. And just exiting is
159  // not so nice.
160  // If you see this error, there is a bug in the code, not in the
161  // ARTS input.
162 }
163 
166  mdata = v.mdata;
167  mrange = v.mrange;
168 }
169 
174  return ComplexVectorView(mdata, mrange, r);
175 }
176 
180 }
181 
184  return ComplexIterator1D(
186  mrange.mstride);
187 }
188 
194  const ConstComplexVectorView& v) {
195  // cout << "Assigning VectorView from ConstVectorView.\n";
196 
197  // Check that sizes are compatible:
198  assert(mrange.mextent == v.mrange.mextent);
199 
200  copy(v.begin(), v.end(), begin());
201 
202  return *this;
203 }
204 
211  // cout << "Assigning ComplexVectorView from ComplexVectorView.\n";
212 
213  // Check that sizes are compatible:
214  assert(mrange.mextent == v.mrange.mextent);
215 
216  copy(v.begin(), v.end(), begin());
217 
218  return *this;
219 }
220 
224  // cout << "Assigning ComplexVectorView from Vector.\n";
225 
226  // Check that sizes are compatible:
227  assert(mrange.mextent == v.mrange.mextent);
228 
229  copy(v.begin(), v.end(), begin());
230 
231  return *this;
232 }
233 
237  copy(x, begin(), end());
238  return *this;
239 }
240 
243  const ComplexIterator1D e = end();
244  for (ComplexIterator1D i = begin(); i != e; ++i) *i *= x;
245  return *this;
246 }
247 
250  const ComplexIterator1D e = end();
251  for (ComplexIterator1D i = begin(); i != e; ++i) *i *= x;
252  return *this;
253 }
254 
257  const ComplexIterator1D e = end();
258  for (ComplexIterator1D i = begin(); i != e; ++i) *i /= x;
259  return *this;
260 }
261 
264  const ComplexIterator1D e = end();
265  for (ComplexIterator1D i = begin(); i != e; ++i) *i /= x;
266  return *this;
267 }
268 
271  const ComplexIterator1D e = end();
272  for (ComplexIterator1D i = begin(); i != e; ++i) *i += x;
273  return *this;
274 }
275 
278  const ComplexIterator1D e = end();
279  for (ComplexIterator1D i = begin(); i != e; ++i) *i += x;
280  return *this;
281 }
282 
285  const ComplexIterator1D e = end();
286  for (ComplexIterator1D i = begin(); i != e; ++i) *i -= x;
287  return *this;
288 }
289 
292  const ComplexIterator1D e = end();
293  for (ComplexIterator1D i = begin(); i != e; ++i) *i -= x;
294  return *this;
295 }
296 
299  const ConstComplexVectorView& x) {
300  assert(nelem() == x.nelem());
301 
302  ConstComplexIterator1D s = x.begin();
303 
304  ComplexIterator1D i = begin();
305  const ComplexIterator1D e = end();
306 
307  for (; i != e; ++i, ++s) *i *= *s;
308  return *this;
309 }
310 
313  assert(nelem() == x.nelem());
314 
315  ConstIterator1D s = x.begin();
316 
318  const ComplexIterator1D e = end();
319 
320  for (; i != e; ++i, ++s) *i *= *s;
321  return *this;
322 }
323 
326  const ConstComplexVectorView& x) {
327  assert(nelem() == x.nelem());
328 
329  ConstComplexIterator1D s = x.begin();
330 
331  ComplexIterator1D i = begin();
332  const ComplexIterator1D e = end();
333 
334  for (; i != e; ++i, ++s) *i /= *s;
335  return *this;
336 }
337 
340  assert(nelem() == x.nelem());
341 
342  ConstIterator1D s = x.begin();
343 
344  ComplexIterator1D i = begin();
345  const ComplexIterator1D e = end();
346 
347  for (; i != e; ++i, ++s) *i /= *s;
348  return *this;
349 }
350 
353  const ConstComplexVectorView& x) {
354  assert(nelem() == x.nelem());
355 
356  ConstComplexIterator1D s = x.begin();
357 
358  ComplexIterator1D i = begin();
359  const ComplexIterator1D e = end();
360 
361  for (; i != e; ++i, ++s) *i += *s;
362  return *this;
363 }
364 
367  assert(nelem() == x.nelem());
368 
369  ConstIterator1D s = x.begin();
370 
371  ComplexIterator1D i = begin();
372  const ComplexIterator1D e = end();
373 
374  for (; i != e; ++i, ++s) *i += *s;
375  return *this;
376 }
377 
380  const ConstComplexVectorView& x) {
381  assert(nelem() == x.nelem());
382 
383  ConstComplexIterator1D s = x.begin();
384 
385  ComplexIterator1D i = begin();
386  const ComplexIterator1D e = end();
387 
388  for (; i != e; ++i, ++s) *i -= *s;
389  return *this;
390 }
391 
394  assert(nelem() == x.nelem());
395 
396  ConstIterator1D s = x.begin();
397 
398  ComplexIterator1D i = begin();
399  const ComplexIterator1D e = end();
400 
401  for (; i != e; ++i, ++s) *i -= *s;
402  return *this;
403 }
404 
406 ComplexVectorView::operator ComplexMatrixView() {
407  // The old version (before 2013-01-18) of this was:
408  // return ConstMatrixView(mdata,mrange,Range(mrange.mstart,1));
409  // Bus this was a bug! The problem is that the matrix index operator adds
410  // the mstart from both row and columm range object to mdata
411 
412  return ComplexMatrixView(mdata, mrange, Range(0, 1));
413 }
414 
422  if (mrange.mstart != 0 || mrange.mstride != 1)
423  throw runtime_error(
424  "A ComplexVectorView can only be converted to a plain C-array if it's pointing to a continuous block of data");
425 
426  return mdata;
427 }
428 
436  if (mrange.mstart != 0 || mrange.mstride != 1)
437  throw runtime_error(
438  "A VectorView can only be converted to a plain C-array if it's pointing to a continuous block of data");
439 
440  return mdata;
441 }
442 
447  // Nothing to do here.
448 }
449 
453  : ConstComplexVectorView(data, range) {
454  // Nothing to do here.
455 }
456 
468  const Range& p,
469  const Range& n)
470  : ConstComplexVectorView(data, p, n) {
471  // Nothing to do here.
472 }
473 
480  ComplexIterator1D target) {
481  if (origin.mstride == 1 && target.mstride == 1)
482  memcpy((void*)target.mx,
483  (void*)origin.mx,
484  sizeof(Complex) * (end.mx - origin.mx));
485  else
486  for (; origin != end; ++origin, ++target) *target = *origin;
487 }
488 
491  for (; target != end; ++target) *target = x;
492 }
493 
494 // Functions for Vector:
495 // ---------------------
496 
499  // Nothing to do here
500 }
501 
504  : ComplexVectorView(new Complex[n], Range(0, n)) {
505  // Nothing to do here.
506 }
507 
510  : ComplexVectorView(new Complex[n], Range(0, n)) {
511  // Here we can access the raw memory directly, for slightly
512  // increased efficiency:
513  const Complex* stop = mdata + n;
514  for (Complex* x = mdata; x < stop; ++x) *x = fill;
515 }
516 
519  : ComplexVectorView(new Complex[n], Range(0, n)) {
520  // Here we can access the raw memory directly, for slightly
521  // increased efficiency:
522  const Complex* stop = mdata + n;
523  for (Complex* x = mdata; x < stop; ++x) *x = fill;
524 }
525 
535  : ComplexVectorView(new Complex[extent], Range(0, extent)) {
536  // Fill with values:
537  Complex x = start;
538  ComplexIterator1D i = begin();
539  const ComplexIterator1D e = end();
540  for (; i != e; ++i) {
541  *i = x;
542  x += stride;
543  }
544 }
545 
555  : ComplexVectorView(new Complex[extent], Range(0, extent)) {
556  // Fill with values:
557  Complex x = start;
558  ComplexIterator1D i = begin();
559  const ComplexIterator1D e = end();
560  for (; i != e; ++i) {
561  *i = x;
562  x += stride;
563  }
564 }
565 
575  : ComplexVectorView(new Complex[extent], Range(0, extent)) {
576  // Fill with values:
577  Complex x = start;
578  ComplexIterator1D i = begin();
579  const ComplexIterator1D e = end();
580  for (; i != e; ++i) {
581  *i = x;
582  x += stride;
583  }
584 }
585 
595  : ComplexVectorView(new Complex[extent], Range(0, extent)) {
596  // Fill with values:
597  Complex x = start;
598  ComplexIterator1D i = begin();
599  const ComplexIterator1D e = end();
600  for (; i != e; ++i) {
601  *i = x;
602  x += stride;
603  }
604 }
605 
612  : ComplexVectorView(new Complex[v.nelem()], Range(0, v.nelem())) {
613  copy(v.begin(), v.end(), begin());
614 }
615 
619  : ComplexVectorView(new Complex[v.nelem()], Range(0, v.nelem())) {
620  copy(v.begin(), v.end(), begin());
621 }
622 
624 ComplexVector::ComplexVector(const std::vector<Complex>& v)
625  : ComplexVectorView(new Complex[v.size()], Range(0, v.size())) {
626  std::vector<Complex>::const_iterator vec_it_end = v.end();
627  ComplexIterator1D this_it = this->begin();
628  for (std::vector<Complex>::const_iterator vec_it = v.begin();
629  vec_it != vec_it_end;
630  ++vec_it, ++this_it)
631  *this_it = *vec_it;
632 }
633 
635 ComplexVector::ComplexVector(const std::vector<Numeric>& v)
636  : ComplexVectorView(new Complex[v.size()], Range(0, v.size())) {
637  std::vector<Numeric>::const_iterator vec_it_end = v.end();
638  ComplexIterator1D this_it = this->begin();
639  for (std::vector<Numeric>::const_iterator vec_it = v.begin();
640  vec_it != vec_it_end;
641  ++vec_it, ++this_it)
642  *this_it = *vec_it;
643 }
644 
646 
671  swap(*this, v);
672  return *this;
673 }
674 
676 
693  resize(x.nelem());
695  return *this;
696 }
697 
702  return *this;
703 }
704 
705 // /** Assignment operator from VectorView. Assignment operators are not
706 // inherited. */
707 // inline Vector& Vector::operator=(const VectorView v)
708 // {
709 // cout << "Assigning Vector from Vector View.\n";
710 // // Check that sizes are compatible:
711 // assert(mrange.mextent==v.mrange.mextent);
712 // VectorView::operator=(v);
713 // return *this;
714 // }
715 
720  assert(0 <= n);
721  if (mrange.mextent != n) {
722  delete[] mdata;
723  mdata = new Complex[n];
724  mrange.mstart = 0;
725  mrange.mextent = n;
726  mrange.mstride = 1;
727  }
728 }
729 
732  std::swap(v1.mrange, v2.mrange);
733  std::swap(v1.mdata, v2.mdata);
734 }
735 
739 
740 // Functions for ConstMatrixView:
741 // ------------------------------
742 
744 // bool ConstComplexMatrixView::empty() const
745 // {
746 // return (nrows() == 0 || ncols() == 0);
747 // }
748 
750 // Index ConstComplexMatrixView::nrows() const
751 // {
752 // return mrr.mextent;
753 // }
754 
756 // Index ConstComplexMatrixView::ncols() const
757 // {
758 // return mcr.mextent;
759 // }
760 
765  const Range& r, const Range& c) const {
766  return ConstComplexMatrixView(mdata, mrr, mcr, r, c);
767 }
768 
775  Index c) const {
776  // Check that c is valid:
777  assert(0 <= c);
778  assert(c < mcr.mextent);
779 
780  return ConstComplexVectorView(mdata + mcr.mstart + c * mcr.mstride, mrr, r);
781 }
782 
789  Index r, const Range& c) const {
790  // Check that r is valid:
791  assert(0 <= r);
792  assert(r < mrr.mextent);
793 
794  return ConstComplexVectorView(mdata + mrr.mstart + r * mrr.mstride, mcr, c);
795 }
796 
800  mrr.mstride);
801 }
802 
805  return ConstComplexIterator2D(
807  mcr),
808  mrr.mstride);
809 }
810 
812 
823  Range(0, n, mrr.mstride + mcr.mstride));
824 }
825 
830  const Range& rr,
831  const Range& cr)
832  : mrr(rr), mcr(cr), mdata(data) {
833  // Nothing to do here.
834 }
835 
851  const Range& pr,
852  const Range& pc,
853  const Range& nr,
854  const Range& nc)
855  : mrr(pr, nr), mcr(pc, nc), mdata(data) {
856  // Nothing to do here.
857 }
858 
866 std::ostream& operator<<(std::ostream& os, const ConstComplexMatrixView& v) {
867  // Row iterators:
868  ConstComplexIterator2D ir = v.begin();
869  const ConstComplexIterator2D end_row = v.end();
870 
871  if (ir != end_row) {
872  ConstComplexIterator1D ic = ir->begin();
873  const ConstComplexIterator1D end_col = ir->end();
874 
875  if (ic != end_col) {
876  os << setw(3) << *ic;
877  ++ic;
878  }
879  for (; ic != end_col; ++ic) {
880  os << " " << setw(3) << *ic;
881  }
882  ++ir;
883  }
884  for (; ir != end_row; ++ir) {
885  ConstComplexIterator1D ic = ir->begin();
886  const ConstComplexIterator1D end_col = ir->end();
887 
888  os << "\n";
889  if (ic != end_col) {
890  os << setw(3) << *ic;
891  ++ic;
892  }
893  for (; ic != end_col; ++ic) {
894  os << " " << setw(3) << *ic;
895  }
896  }
897 
898  return os;
899 }
900 
901 // Functions for ComplexMatrixView:
902 // -------------------------
903 
908  const Range& c) {
909  return ComplexMatrixView(mdata, mrr, mcr, r, c);
910 }
911 
917  // Check that c is valid:
918  assert(0 <= c);
919  assert(c < mcr.mextent);
920 
921  return ComplexVectorView(mdata + mcr.mstart + c * mcr.mstride, mrr, r);
922 }
923 
929  // Check that r is valid:
930  assert(0 <= r);
931  assert(r < mrr.mextent);
932 
933  return ComplexVectorView(mdata + mrr.mstart + r * mrr.mstride, mcr, c);
934 }
935 
939  mrr.mstride);
940 }
941 
944  return ComplexIterator2D(
946  mrr.mstride);
947 }
948 
950 
961  Range(0, n, mrr.mstride + mcr.mstride));
962 }
963 
969  const ConstComplexMatrixView& m) {
970  // Check that sizes are compatible:
971  assert(mrr.mextent == m.mrr.mextent);
972  assert(mcr.mextent == m.mcr.mextent);
973 
974  copy(m.begin(), m.end(), begin());
975  return *this;
976 }
977 
984  // Check that sizes are compatible:
985  assert(mrr.mextent == m.mrr.mextent);
986  assert(mcr.mextent == m.mcr.mextent);
987 
988  copy(m.begin(), m.end(), begin());
989  return *this;
990 }
991 
996  // Check that sizes are compatible:
997  assert(mrr.mextent == m.mrr.mextent);
998  assert(mcr.mextent == m.mcr.mextent);
999 
1000  copy(m.begin(), m.end(), begin());
1001  return *this;
1002 }
1003 
1009  const ConstComplexVectorView& v) {
1010  // Check that sizes are compatible:
1011  assert(mrr.mextent == v.nelem());
1012  assert(mcr.mextent == 1);
1013  // dummy = ConstComplexMatrixView(v.mdata,v.mrange,Range(v.mrange.mstart,1));;
1014  ConstComplexMatrixView dummy(v);
1015  copy(dummy.begin(), dummy.end(), begin());
1016  return *this;
1017 }
1018 
1022  copy(x, begin(), end());
1023  return *this;
1024 }
1025 
1028  const ComplexIterator2D er = end();
1029  for (ComplexIterator2D r = begin(); r != er; ++r) {
1030  const ComplexIterator1D ec = r->end();
1031  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c *= x;
1032  }
1033  return *this;
1034 }
1035 
1038  const ComplexIterator2D er = end();
1039  for (ComplexIterator2D r = begin(); r != er; ++r) {
1040  const ComplexIterator1D ec = r->end();
1041  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c *= x;
1042  }
1043  return *this;
1044 }
1045 
1048  const ComplexIterator2D er = end();
1049  for (ComplexIterator2D r = begin(); r != er; ++r) {
1050  const ComplexIterator1D ec = r->end();
1051  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c /= x;
1052  }
1053  return *this;
1054 }
1055 
1058  const ComplexIterator2D er = end();
1059  for (ComplexIterator2D r = begin(); r != er; ++r) {
1060  const ComplexIterator1D ec = r->end();
1061  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c /= x;
1062  }
1063  return *this;
1064 }
1065 
1068  const ComplexIterator2D er = end();
1069  for (ComplexIterator2D r = begin(); r != er; ++r) {
1070  const ComplexIterator1D ec = r->end();
1071  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c += x;
1072  }
1073  return *this;
1074 }
1075 
1078  const ComplexIterator2D er = end();
1079  for (ComplexIterator2D r = begin(); r != er; ++r) {
1080  const ComplexIterator1D ec = r->end();
1081  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c += x;
1082  }
1083  return *this;
1084 }
1085 
1088  const ComplexIterator2D er = end();
1089  for (ComplexIterator2D r = begin(); r != er; ++r) {
1090  const ComplexIterator1D ec = r->end();
1091  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c -= x;
1092  }
1093  return *this;
1094 }
1095 
1098  const ComplexIterator2D er = end();
1099  for (ComplexIterator2D r = begin(); r != er; ++r) {
1100  const ComplexIterator1D ec = r->end();
1101  for (ComplexIterator1D c = r->begin(); c != ec; ++c) *c -= x;
1102  }
1103  return *this;
1104 }
1105 
1113  if (mrr.mstart != 0 || mrr.mstride != mcr.mextent || mcr.mstart != 0 ||
1114  mcr.mstride != 1)
1115  throw std::runtime_error(
1116  "A MatrixView can only be converted to a plain C-array if it's pointing to a continuous block of data");
1117 
1118  return mdata;
1119 }
1120 
1128  if (mrr.mstart != 0 || mrr.mstride != mcr.mextent || mcr.mstart != 0 ||
1129  mcr.mstride != 1)
1130  throw std::runtime_error(
1131  "A MatrixView can only be converted to a plain C-array if it's pointing to a continuous block of data");
1132 
1133  return mdata;
1134 }
1135 
1138  const ConstComplexMatrixView& x) {
1139  assert(nrows() == x.nrows());
1140  assert(ncols() == x.ncols());
1141  ConstComplexIterator2D sr = x.begin();
1142  ComplexIterator2D r = begin();
1143  const ComplexIterator2D er = end();
1144  for (; r != er; ++r, ++sr) {
1145  ConstComplexIterator1D sc = sr->begin();
1146  ComplexIterator1D c = r->begin();
1147  const ComplexIterator1D ec = r->end();
1148  for (; c != ec; ++c, ++sc) *c *= *sc;
1149  }
1150  return *this;
1151 }
1152 
1155  assert(nrows() == x.nrows());
1156  assert(ncols() == x.ncols());
1157  ConstIterator2D sr = x.begin();
1158  ComplexIterator2D r = begin();
1159  const ComplexIterator2D er = end();
1160  for (; r != er; ++r, ++sr) {
1161  ConstIterator1D sc = sr->begin();
1162  ComplexIterator1D c = r->begin();
1163  const ComplexIterator1D ec = r->end();
1164  for (; c != ec; ++c, ++sc) *c *= *sc;
1165  }
1166  return *this;
1167 }
1168 
1171  const ConstComplexMatrixView& x) {
1172  assert(nrows() == x.nrows());
1173  assert(ncols() == x.ncols());
1174  ConstComplexIterator2D sr = x.begin();
1175  ComplexIterator2D r = begin();
1176  const ComplexIterator2D er = end();
1177  for (; r != er; ++r, ++sr) {
1178  ConstComplexIterator1D sc = sr->begin();
1179  ComplexIterator1D c = r->begin();
1180  const ComplexIterator1D ec = r->end();
1181  for (; c != ec; ++c, ++sc) *c /= *sc;
1182  }
1183  return *this;
1184 }
1185 
1188  assert(nrows() == x.nrows());
1189  assert(ncols() == x.ncols());
1190  ConstIterator2D sr = x.begin();
1191  ComplexIterator2D r = begin();
1192  const ComplexIterator2D er = end();
1193  for (; r != er; ++r, ++sr) {
1194  ConstIterator1D sc = sr->begin();
1195  ComplexIterator1D c = r->begin();
1196  const ComplexIterator1D ec = r->end();
1197  for (; c != ec; ++c, ++sc) *c /= *sc;
1198  }
1199  return *this;
1200 }
1201 
1204  const ConstComplexMatrixView& x) {
1205  assert(nrows() == x.nrows());
1206  assert(ncols() == x.ncols());
1207  ConstComplexIterator2D sr = x.begin();
1208  ComplexIterator2D r = begin();
1209  const ComplexIterator2D er = end();
1210  for (; r != er; ++r, ++sr) {
1211  ConstComplexIterator1D sc = sr->begin();
1212  ComplexIterator1D c = r->begin();
1213  const ComplexIterator1D ec = r->end();
1214  for (; c != ec; ++c, ++sc) *c += *sc;
1215  }
1216  return *this;
1217 }
1218 
1221  assert(nrows() == x.nrows());
1222  assert(ncols() == x.ncols());
1223  ConstIterator2D sr = x.begin();
1224  ComplexIterator2D r = begin();
1225  const ComplexIterator2D er = end();
1226  for (; r != er; ++r, ++sr) {
1227  ConstIterator1D sc = sr->begin();
1228  ComplexIterator1D c = r->begin();
1229  const ComplexIterator1D ec = r->end();
1230  for (; c != ec; ++c, ++sc) *c += *sc;
1231  }
1232  return *this;
1233 }
1234 
1237  const ConstComplexMatrixView& x) {
1238  assert(nrows() == x.nrows());
1239  assert(ncols() == x.ncols());
1240  ConstComplexIterator2D sr = x.begin();
1241  ComplexIterator2D r = begin();
1242  const ComplexIterator2D er = end();
1243  for (; r != er; ++r, ++sr) {
1244  ConstComplexIterator1D sc = sr->begin();
1245  ComplexIterator1D c = r->begin();
1246  const ComplexIterator1D ec = r->end();
1247  for (; c != ec; ++c, ++sc) *c -= *sc;
1248  }
1249  return *this;
1250 }
1251 
1254  assert(nrows() == x.nrows());
1255  assert(ncols() == x.ncols());
1256  ConstIterator2D sr = x.begin();
1257  ComplexIterator2D r = begin();
1258  const ComplexIterator2D er = end();
1259  for (; r != er; ++r, ++sr) {
1260  ConstIterator1D sc = sr->begin();
1261  ComplexIterator1D c = r->begin();
1262  const ComplexIterator1D ec = r->end();
1263  for (; c != ec; ++c, ++sc) *c -= *sc;
1264  }
1265  return *this;
1266 }
1267 
1271  // Nothing to do here.
1272 }
1273 
1278  const Range& rr,
1279  const Range& cr)
1280  : ConstComplexMatrixView(data, rr, cr) {
1281  // Nothing to do here.
1282 }
1283 
1299  const Range& pr,
1300  const Range& pc,
1301  const Range& nr,
1302  const Range& nc)
1303  : ConstComplexMatrixView(data, pr, pc, nr, nc) {
1304  // Nothing to do here.
1305 }
1306 
1317  const ConstComplexIterator2D& end,
1318  ComplexIterator2D target) {
1319  for (; origin != end; ++origin, ++target) {
1320  ConstComplexIterator1D o = origin->begin();
1321  const ConstComplexIterator1D e = origin->end();
1322  ComplexIterator1D t = target->begin();
1323  for (; o != e; ++o, ++t) *t = *o;
1324  }
1325 }
1326 
1329  for (; target != end; ++target) {
1330  ComplexIterator1D t = target->begin();
1331  const ComplexIterator1D e = target->end();
1332  for (; t != e; ++t) *t = x;
1333  }
1334 }
1335 
1338  for (; target != end; ++target) {
1339  ComplexIterator1D t = target->begin();
1340  const ComplexIterator1D e = target->end();
1341  for (; t != e; ++t) *t = x;
1342  }
1343 }
1344 
1345 // Functions for ComplexMatrix:
1346 // ---------------------
1347 
1351  : ComplexMatrixView(new Complex[r * c], Range(0, r, c), Range(0, c)) {
1352  // Nothing to do here.
1353 }
1354 
1357  : ComplexMatrixView(new Complex[r * c], Range(0, r, c), Range(0, c)) {
1358  // Here we can access the raw memory directly, for slightly
1359  // increased efficiency:
1360  const Complex* stop = mdata + r * c;
1361  for (Complex* x = mdata; x < stop; ++x) *x = fill;
1362 }
1363 
1366  : ComplexMatrixView(new Complex[r * c], Range(0, r, c), Range(0, c)) {
1367  // Here we can access the raw memory directly, for slightly
1368  // increased efficiency:
1369  const Complex* stop = mdata + r * c;
1370  for (Complex* x = mdata; x < stop; ++x) *x = fill;
1371 }
1372 
1376  : ComplexMatrixView(new Complex[m.nrows() * m.ncols()],
1377  Range(0, m.nrows(), m.ncols()),
1378  Range(0, m.ncols())) {
1379  copy(m.begin(), m.end(), begin());
1380 }
1381 
1385  : ComplexMatrixView(new Complex[m.nrows() * m.ncols()],
1386  Range(0, m.nrows(), m.ncols()),
1387  Range(0, m.ncols())) {
1388  // There is a catch here: If m is an empty matrix, then it will have
1389  // 0 colunns. But this is used to initialize the stride of the row
1390  // Range! Thus, this method has to be consistent with the behaviour
1391  // of Range::Range. For now, Range::Range allows also stride 0.
1392  copy(m.begin(), m.end(), begin());
1393 }
1394 
1396 
1421  swap(*this, m);
1422  return *this;
1423 }
1424 
1428  copy(x, begin(), end());
1429  return *this;
1430 }
1431 
1433 
1446  resize(v.nelem(), 1);
1447  ConstComplexMatrixView dummy(v);
1448  copy(dummy.begin(), dummy.end(), begin());
1449  return *this;
1450 }
1451 
1456  assert(0 <= r);
1457  assert(0 <= c);
1458 
1459  if (mrr.mextent != r || mcr.mextent != c) {
1460  delete[] mdata;
1461  mdata = new Complex[r * c];
1462 
1463  mrr.mstart = 0;
1464  mrr.mextent = r;
1465  mrr.mstride = c;
1466 
1467  mcr.mstart = 0;
1468  mcr.mextent = c;
1469  mcr.mstride = 1;
1470  }
1471 }
1472 
1475  std::swap(m1.mrr, m2.mrr);
1476  std::swap(m1.mcr, m2.mcr);
1477  std::swap(m1.mdata, m2.mdata);
1478 }
1479 
1483  // cout << "Destroying a Matrix:\n"
1484  // << *this << "\n........................................\n";
1485  delete[] mdata;
1486 }
1487 
1489 {
1490  assert(ncols() == nrows());
1491 
1492  // help's internal variables are all mutable, so const is just for default parameter and to not use copies
1493  help.resize_if_smaller(int(ncols()));
1494 
1495  // Compute LU decomposition using LAPACK dgetrf_.
1496  int info;
1497  lapack::zgetrf_(help.size(), help.size(), mdata, help.size(), help.ipivdata(), &info);
1498  lapack::zgetri_(help.size(), mdata, help.size(), help.ipivdata(), help.workdata(), help.lsize(), &info);
1499 
1500  // Check for success.
1501  if (info not_eq 0) {
1502  throw runtime_error("Error inverting matrix: Matrix not of full rank.");
1503  }
1504 
1505  return *this;
1506 }
1507 
1510  return ConstComplexMatrixView(m.mdata, m.mcr, m.mrr);
1511 }
1512 
1516  return ComplexMatrixView(m.mdata, m.mcr, m.mrr);
1517 }
1518 
1522  return transpose((ComplexMatrixView)v);
1523 }
1524 
1535  // cout << "Assigning VectorView from Array<Numeric>.\n";
1536 
1537  // Check that sizes are compatible:
1538  assert(mrange.mextent == v.nelem());
1539 
1540  // Iterators for Array:
1541  Array<Complex>::const_iterator i = v.begin();
1542  const Array<Complex>::const_iterator e = v.end();
1543  // Iterator for Vector:
1544  ComplexIterator1D target = begin();
1545 
1546  for (; i != e; ++i, ++target) *target = *i;
1547 
1548  return *this;
1549 }
1550 
1551 //Functions operating on the complex vectors
1552 
1555  const ConstComplexVectorView& b) {
1556  // Check dimensions:
1557  assert(a.nelem() == b.nelem());
1558 
1559  const ConstComplexIterator1D ae = a.end();
1560  ConstComplexIterator1D ai = a.begin();
1561  ConstComplexIterator1D bi = b.begin();
1562 
1563  Complex res = 0;
1564  for (; ai != ae; ++ai, ++bi) res += (*ai) * (*bi);
1565 
1566  return res;
1567 }
1568 
1570 
1580  const ConstComplexMatrixView& M,
1581  const ConstComplexVectorView& x) {
1582  assert(x.nelem() == M.nrows());
1583  assert(y.nelem() == M.ncols());
1584 
1586  if (y.mdata == x.mdata)
1587  eigen_y = MapToEigen(M) * MapToEigenRow(x);
1588  else
1589  eigen_y.noalias() = MapToEigen(M) * MapToEigenRow(x);
1590 }
1591 
1593 
1605  const ConstComplexMatrixView& B,
1606  const ConstComplexMatrixView& C) {
1607  assert(B.nrows() == A.nrows());
1608  assert(C.ncols() == A.ncols());
1609  assert(B.ncols() == C.nrows());
1610 
1611  ComplexMatrixViewMap eigen_A = MapToEigen(A);
1612  if (A.mdata == B.mdata || A.mdata == C.mdata)
1613  eigen_A = MapToEigen(B) * MapToEigen(C);
1614  else
1615  eigen_A.noalias() = MapToEigen(B) * MapToEigen(C);
1616 }
1618  const ConstComplexMatrixView& B,
1619  const ConstMatrixView& C) {
1620  assert(B.nrows() == A.nrows());
1621  assert(C.ncols() == A.ncols());
1622  assert(B.ncols() == C.nrows());
1623 
1624  ComplexMatrixViewMap eigen_A = MapToEigen(A);
1625  if (A.mdata == B.mdata)
1626  eigen_A = MapToEigen(B) * MapToEigen(C);
1627  else
1628  eigen_A.noalias() = MapToEigen(B) * MapToEigen(C);
1629 }
1631  const ConstMatrixView& B,
1632  const ConstComplexMatrixView& C) {
1633  assert(B.nrows() == A.nrows());
1634  assert(C.ncols() == A.ncols());
1635  assert(B.ncols() == C.nrows());
1636 
1637  ComplexMatrixViewMap eigen_A = MapToEigen(A);
1638  if (A.mdata == C.mdata)
1639  eigen_A = MapToEigen(B) * MapToEigen(C);
1640  else
1641  eigen_A.noalias() = MapToEigen(B) * MapToEigen(C);
1642 }
1644  const ConstMatrixView& B,
1645  const ConstMatrixView& C) {
1646  assert(B.nrows() == A.nrows());
1647  assert(C.ncols() == A.ncols());
1648  assert(B.ncols() == C.nrows());
1649 
1650  ComplexMatrixViewMap eigen_A = MapToEigen(A);
1651  eigen_A.noalias() = MapToEigen(B) * MapToEigen(C);
1652 }
1653 
1654 // Converts constant matrix to constant eigen map
1657  A.mdata + A.mrr.get_start() + A.mcr.get_start(),
1658  A.nrows(),
1659  A.ncols(),
1661 }
1662 
1663 // Converts constant vector to constant eigen row-view
1666  A.nelem(),
1667  1,
1669 }
1670 
1671 // Converts constant vector to constant eigen row-view
1673  return MapToEigen(A);
1674 }
1675 
1676 // Converts constant vector to constant eigen column-view
1679  1,
1680  A.nelem(),
1682 }
1683 
1684 // Converts matrix to eigen map
1686  return ComplexMatrixViewMap(
1687  A.mdata + A.mrr.get_start() + A.mcr.get_start(),
1688  A.nrows(),
1689  A.ncols(),
1691 }
1692 
1693 // Converts vector to eigen map row-view
1695  return ComplexMatrixViewMap(A.mdata + A.mrange.get_start(),
1696  A.nelem(),
1697  1,
1699 }
1700 
1701 // Converts vector to eigen map row-view
1703  return MapToEigen(A);
1704 }
1705 
1706 // Converts vector to eigen map column-view
1708  return ComplexMatrixViewMap(A.mdata + A.mrange.get_start(),
1709  1,
1710  A.nelem(),
1712 }
1713 
1715 // Helper function for debugging
1716 #ifndef NDEBUG
1717 
1732  return mv(r, c);
1733 }
1734 
1735 #endif
operator<<
std::ostream & operator<<(std::ostream &os, const ConstComplexVectorView &v)
Output operator.
Definition: complex.cc:134
ComplexMatrix::swap
friend void swap(ComplexMatrix &m1, ComplexMatrix &m2)
Swaps two objects.
Definition: complex.cc:1474
exceptions.h
The declarations of all the exception classes.
ConstComplexMatrixView::ConstComplexVectorView
friend class ConstComplexVectorView
Definition: complex.h:683
ComplexVectorView::get_c_array
const Complex * get_c_array() const
Conversion to plain C-array.
Definition: complex.cc:421
ComplexVectorView::ComplexVectorView
ComplexVectorView()=default
ConstComplexMatrixView::begin
ConstComplexIterator2D begin() const
Return const iterator to first row.
Definition: complex.cc:798
ComplexStrideType
Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > ComplexStrideType
Definition: complex.h:168
ConstIterator1D
The constant iterator class for sub vectors.
Definition: matpackI.h:420
ComplexMatrix::~ComplexMatrix
virtual ~ComplexMatrix()
Destructor for Matrix.
Definition: complex.cc:1482
ConstComplexIterator2D
The const row iterator class for sub matrices.
Definition: complex.h:522
ConstComplexVectorView::nelem
Index nelem() const
Definition: complex.h:280
ComplexVector
The ComplexVector class.
Definition: complex.h:573
mult
void mult(ComplexVectorView y, const ConstComplexMatrixView &M, const ConstComplexVectorView &x)
Matrix-Vector Multiplication.
Definition: complex.cc:1579
swap
void swap(ComplexVector &v1, ComplexVector &v2)
Swaps two objects.
Definition: complex.cc:731
ARTS::Var::y
Vector y(Workspace &ws) noexcept
Definition: autoarts.h:7401
operator*
Complex operator*(const ConstComplexVectorView &a, const ConstComplexVectorView &b)
Scalar product.
Definition: complex.cc:1554
ComplexVector::~ComplexVector
virtual ~ComplexVector()
Destructor for ComplexVector.
Definition: complex.cc:738
data
G0 G2 FVC Y DV Numeric Numeric Numeric Zeeman LowerQuantumNumbers void * data
Definition: arts_api_classes.cc:232
ComplexVectorView::end
ComplexIterator1D end()
Return iterator behind last element.
Definition: complex.cc:183
ComplexMatrixView::ComplexMatrixView
ComplexMatrixView()
Default constructor.
Definition: complex.cc:1270
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:429
ComplexVectorView::operator[]
Complex & operator[](Index n)
Plain Index operator.
Definition: complex.h:387
ComplexVector::operator=
ComplexVector & operator=(ComplexVector v)
Assignment from another Vector.
Definition: complex.cc:670
Range::mstart
Index mstart
The start index.
Definition: matpackI.h:346
ComplexMatrixView::get_c_array
const Complex * get_c_array() const
Conversion to plain C-array.
Definition: complex.cc:1112
ConstComplexMatrixView::ConstComplexMatrixView
ConstComplexMatrixView()=default
Complex
std::complex< Numeric > Complex
Definition: complex.h:33
ComplexVectorView::operator-=
ComplexVectorView operator-=(Complex x)
Subtraction of scalar.
Definition: complex.cc:284
Range::get_start
constexpr Index get_start() const
Returns the start index of the range.
Definition: matpackI.h:327
ComplexVectorView::operator*=
ComplexVectorView operator*=(Complex x)
Multiplication by scalar.
Definition: complex.cc:242
ConstComplexIterator1D::mstride
Index mstride
Stride.
Definition: complex.h:254
ConstComplexMatrixView::nrows
Index nrows() const
Definition: complex.h:630
complex.h
A class implementing complex numbers for ARTS.
ComplexMatrixView::operator=
ComplexMatrixView & operator=(const ConstComplexMatrixView &v)
Assignment operator.
Definition: complex.cc:968
Array
This can be used to make arrays out of anything.
Definition: array.h:108
ComplexMatrixView::operator+=
ComplexMatrixView & operator+=(Complex x)
Addition of scalar.
Definition: complex.cc:1067
Absorption::nelem
Index nelem(const Lines &l)
Number of lines.
Definition: absorptionlines.h:1820
MapToEigen
ComplexConstMatrixViewMap MapToEigen(const ConstComplexMatrixView &A)
Definition: complex.cc:1655
lapack_help::Inverse::workdata
T * workdata() const noexcept
Definition: lapack.h:45
ConstComplexMatrixView::end
ConstComplexIterator2D end() const
Return const iterator behind last row.
Definition: complex.cc:804
ConstComplexMatrixView::mcr
Range mcr
The column range of mdata that is actually used.
Definition: complex.h:717
ComplexVectorView::operator+=
ComplexVectorView operator+=(Complex x)
Addition of scalar.
Definition: complex.cc:270
min
#define min(a, b)
Definition: legacy_continua.cc:20628
ComplexIterator2D
The row iterator class for sub matrices.
Definition: complex.h:478
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:432
ComplexMatrixView::operator()
Complex & operator()(Index r, Index c)
Plain index operator.
Definition: complex.h:751
lapack::zgetri_
void zgetri_(int *n, std::complex< double > *A, int *lda, int *ipiv, std::complex< double > *work, int *lwork, int *info)
MapToEigenRow
ComplexConstMatrixViewMap MapToEigenRow(const ConstComplexVectorView &A)
Definition: complex.cc:1672
ComplexMatrixView::begin
ComplexIterator2D begin()
Return iterator to first row.
Definition: complex.cc:937
ConstComplexMatrixView::ncols
Index ncols() const
Definition: complex.h:631
lapack_help::Inverse::size
int * size() const noexcept
Definition: lapack.h:43
ConstComplexVectorView::ConstComplexVectorView
ConstComplexVectorView()=default
ConstVectorView::begin
ConstIterator1D begin() const
Return const iterator to first element.
Definition: matpackI.cc:67
ComplexMatrixViewMap
Eigen::Map< ComplexMatrixType, 0, ComplexStrideType > ComplexMatrixViewMap
Definition: complex.h:170
ComplexMatrix
The ComplexMatrix class.
Definition: complex.h:858
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
ComplexMatrix::ComplexMatrix
ComplexMatrix()=default
ComplexMatrixView::ComplexVectorView
friend class ComplexVectorView
Definition: complex.h:835
ComplexVectorView::operator=
ComplexVectorView & operator=(const ConstComplexVectorView &v)
Assignment operator.
Definition: complex.cc:193
ComplexConstMatrixViewMap
Eigen::Map< const ComplexMatrixType, 0, ComplexStrideType > ComplexConstMatrixViewMap
Definition: complex.h:172
ConstComplexVectorView
A constant view of a ComplexVector.
Definition: complex.h:268
Zeeman::end
constexpr Rational end(Rational Ju, Rational Jl, Polarization type) noexcept
Gives the largest M for a polarization type of this transition.
Definition: zeemandata.h:108
ComplexVector::resize
void resize(Index n)
Resize function.
Definition: complex.cc:719
ConstIterator2D
The const row iterator class for sub matrices.
Definition: matpackI.h:809
ConstMatrixView
A constant view of a Matrix.
Definition: matpackI.h:982
ConstComplexVectorView::operator[]
const Complex & operator[](Index n) const
Plain const index operator.
Definition: complex.h:285
blas.h
Interface for BLAS library.
ARTS::Var::nrows
Index nrows(Workspace &ws) noexcept
Definition: autoarts.h:4682
ConstComplexMatrixView::mrr
Range mrr
The row range of mdata that is actually used.
Definition: complex.h:715
ConstComplexVectorView::mdata
Complex * mdata
Pointer to the plain C array that holds the data.
Definition: complex.h:353
Range::get_stride
constexpr Index get_stride() const
Returns the stride of the range.
Definition: matpackI.h:331
ComplexVectorView::begin
ComplexIterator1D begin()
Return iterator to first element.
Definition: complex.cc:178
ComplexMatrixView
The ComplexMatrixView class.
Definition: complex.h:731
Range
The range class.
Definition: matpackI.h:160
ConstComplexMatrixView::diagonal
ConstComplexVectorView diagonal() const
ComplexMatrix diagonal as vector.
Definition: complex.cc:820
ComplexVector::swap
friend void swap(ComplexVector &v1, ComplexVector &v2)
Swaps two objects.
Definition: complex.cc:731
ConstComplexVectorView::mrange
Range mrange
The range of mdata that is actually used.
Definition: complex.h:351
Range::mextent
Index mextent
The number of elements.
Definition: matpackI.h:353
ComplexMatrix::operator=
ComplexMatrix & operator=(ComplexMatrix x)
Assignment operator from another matrix.
Definition: complex.cc:1420
lapack_help::Inverse::resize_if_smaller
bool resize_if_smaller(Index N) const
Definition: lapack.h:31
ComplexMatrixView::operator*=
ComplexMatrixView & operator*=(Complex x)
Multiplication by scalar.
Definition: complex.cc:1027
ConstComplexVectorView::end
ConstComplexIterator1D end() const
Return const iterator behind last element.
Definition: complex.cc:83
Zeeman::start
constexpr Rational start(Rational Ju, Rational Jl, Polarization type) noexcept
Gives the lowest M for a polarization type of this transition.
Definition: zeemandata.h:77
ComplexMatrixView::end
ComplexIterator2D end()
Return iterator behind last row.
Definition: complex.cc:943
ComplexMatrixView::diagonal
ComplexVectorView diagonal()
ComplexMatrix diagonal as vector.
Definition: complex.cc:958
ConstComplexIterator1D
The constant iterator class for sub vectors.
Definition: complex.h:218
lapack::zgetrf_
void zgetrf_(int *m, int *n, std::complex< double > *A, int *lda, int *ipiv, int *info)
lapack_help::Inverse::ipivdata
int * ipivdata() const noexcept
Definition: lapack.h:46
ComplexVector::ComplexVector
ComplexVector()
Default constructor.
Definition: complex.cc:498
copy
void copy(ConstComplexIterator1D origin, const ConstComplexIterator1D &end, ComplexIterator1D target)
Copy data between begin and end to target.
Definition: complex.cc:478
ConstComplexMatrixView::mdata
Complex * mdata
Pointer to the plain C array that holds the data.
Definition: complex.h:719
ConstComplexMatrixView
A constant view of a ComplexMatrix.
Definition: complex.h:618
ConstComplexVectorView::begin
ConstComplexIterator1D begin() const
Return const iterator to first element.
Definition: complex.cc:78
ConstComplexVectorView::sum
Complex sum() const
Returns true if variable size is zero.
Definition: complex.cc:59
lapack_help::Inverse::lsize
int * lsize() const noexcept
Definition: lapack.h:44
ARTS::Var::x
Vector x(Workspace &ws) noexcept
Definition: autoarts.h:7346
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
transpose
ConstComplexMatrixView transpose(ConstComplexMatrixView m)
Const version of transpose.
Definition: complex.cc:1509
ComplexIterator1D::mx
Complex * mx
Current position.
Definition: complex.h:211
M
#define M
Definition: rng.cc:165
ARTS::Var::ncols
Index ncols(Workspace &ws) noexcept
Definition: autoarts.h:4546
MapToEigenCol
ComplexConstMatrixViewMap MapToEigenCol(const ConstComplexVectorView &A)
Definition: complex.cc:1677
ConstComplexIterator1D::mx
const Complex * mx
Current position.
Definition: complex.h:252
Range::mstride
Index mstride
The stride.
Definition: matpackI.h:355
debug_matrixview_get_elem
Complex debug_matrixview_get_elem(ComplexMatrixView &mv, Index r, Index c)
Helper function to access matrix elements.
Definition: complex.cc:1731
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:476
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:195
ComplexVectorView
The ComplexVectorView class.
Definition: complex.h:367
ComplexVectorView::operator/=
ComplexVectorView operator/=(Complex x)
Division by scalar.
Definition: complex.cc:256
ComplexMatrixView::operator/=
ComplexMatrixView & operator/=(Complex x)
Division by scalar.
Definition: complex.cc:1047
ComplexIterator1D::mstride
Index mstride
Stride.
Definition: complex.h:213
ComplexMatrix::resize
void resize(Index r, Index c)
Resize function.
Definition: complex.cc:1455
ComplexMatrixView::operator-=
ComplexMatrixView & operator-=(Complex x)
Subtraction of scalar.
Definition: complex.cc:1087
ConstComplexMatrixView::operator()
Complex operator()(Index r, Index c) const
Plain const index operator.
Definition: complex.h:635
lapack_help::Inverse
Struct cannot be const, but can be passed as const to allow defaults.
Definition: lapack.h:23
ComplexIterator1D
The iterator class for sub vectors.
Definition: complex.h:176
ComplexMatrix::inv
ComplexMatrix & inv(const lapack_help::Inverse< Complex > &help=lapack_help::Inverse< Complex >{0})
Definition: complex.cc:1488