Theoretica
Scientific Computing
Loading...
Searching...
No Matches
csv.h
Go to the documentation of this file.
1
5
6#ifndef THEORETICA_IO_CSV_H
7#define THEORETICA_IO_CSV_H
8
9#include <fstream>
10#include <iomanip>
11#include <algorithm>
12
13#include "./error.h"
14#include "../algebra/vec.h"
15#include "../algebra/mat.h"
16#include "../calculus/ode.h"
17#include "../statistics/histogram.h"
18#include "./data_table.h"
19#include "./strings.h"
20
21
22namespace theoretica {
23namespace io {
24
25
33 inline std::vector<std::string> parse_csv(const std::string& line, char delimiter = ',') {
34
35 std::vector<std::string> fields;
36 std::string field;
37 bool quoted = false;
38
39 for (size_t i = 0; i < line.length(); ++i) {
40
41 char c = line[i];
42
43 if (c == '"') {
44 quoted = !quoted;
45 } else if (c == delimiter && !quoted) {
46 fields.emplace_back(field);
47 field.clear();
48 } else if(!std::isspace(c) || quoted) {
49 field += c;
50 }
51 }
52
53 fields.emplace_back(field);
54 return fields;
55 }
56
57
63 inline std::string quote_csv(const std::string& str) {
64
65 bool has_whitespace = false;
66 for (char c : str) {
67
68 if (std::isspace(c)) {
69 has_whitespace = true;
70 break;
71 }
72 }
73
74 if (str.find(',') != std::string::npos || has_whitespace)
75 return "\"" + str + "\"";
76 else
77 return str;
78 }
79
80
86 template<typename Type, unsigned int N>
87 inline void write_csv(
88 const std::string& filename, const vec<Type, N>& v, unsigned int precision = 8) {
89
90 std::ofstream file (filename);
91 if (!file.is_open()) {
92 TH_IO_ERROR("io::write_csv", filename, IoError::FileNotFound);
93 return;
94 }
95
96 for (size_t i = 0; i < v.size(); ++i)
97 file << std::setprecision(precision) << v[i] << std::endl;
98 }
99
100
106 template<typename Type, unsigned int N>
107 inline void write_csv(
108 const std::string& filename, const std::string& header,
109 const vec<Type, N>& v, unsigned int precision = 8) {
110
111 std::ofstream file (filename);
112 if (!file.is_open()) {
113 // TODO: throw another exception ?
114 TH_IO_ERROR("io::write_csv", filename, IoError::FileNotFound);
115 return;
116 }
117
118 file << "\"" << header << "\"" << std::endl;
119 for (size_t i = 0; i < v.size(); ++i)
120 file << std::setprecision(precision) << v[i] << std::endl;
121 }
122
123
131 template<typename Type, unsigned int N, enable_real<Type> = true>
132 inline void read_csv(const std::string& filename, vec<Type, N>& v) {
133
134 std::ifstream file (filename);
135 std::string line;
136
137 if (!file.is_open()) {
138 TH_IO_ERROR("io::read_csv", filename, IoError::ReadError);
139 return;
140 }
141
142 // Check for header
143 if (!std::getline(file, line))
144 return;
145
147
148 // Resulting column vector
149 std::vector<real> col;
150
151 if (io::is_number(line)) {
152
153 real first;
154
155 try {
156 std::replace(line.begin(), line.end(), ',', '.');
157 first = std::stod(line);
158 col.emplace_back(first);
159 } catch (const std::invalid_argument& e) {
160 // Do nothing, the entry is not a number
161 } catch(const std::out_of_range& e) {
162 TH_MATH_ERROR("io::read_csv", first, MathError::OutOfRange);
163 }
164 }
165
166 // All remaining lines are data
167 while (std::getline(file, line)) {
168
170 std::replace(line.begin(), line.end(), ',', '.');
171
172 try {
173 real val = std::stod(line);
174 col.emplace_back(val);
175 } catch (const std::exception& e) {
176 col.emplace_back(nan());
177 }
178 }
179
180 // Handle mismatched sizes with empty values (NaN)
181 if (v.size() > col.size()) {
182
183 for (size_t i = 0; i < col.size(); i++)
184 v[i] = col[i];
185
186 for (size_t i = col.size(); i < v.size(); i++)
187 v[i] = nan();
188
189 } else {
190 algebra::vec_copy(v, col);
191 }
192 }
193
194
205 template<typename Type, unsigned int N, enable_real<Type> = true>
206 inline void read_csv(
207 const std::string& filename, const std::string& col_name,
208 vec<Type, N>& v, bool trim_nan = true) {
209
210 std::ifstream file (filename);
211 std::string line;
212
213 if (!file.is_open()) {
214 TH_IO_ERROR("io::read_csv", filename, IoError::ReadError);
216 return;
217 }
218
219 // Read header
220 if (!std::getline(file, line))
221 return;
222
223 // Find the index of the specified column
224 std::vector<std::string> headers = parse_csv(line);
225 int col_index = -1;
226 for (size_t i = 0; i < headers.size(); ++i) {
227
228 if (headers[i] == col_name) {
229 col_index = i;
230 break;
231 }
232 }
233
234 // No column was found
235 if (col_index == -1) {
236
237 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
238
239 if (!v.size())
240 v.resize(1);
241
242 for (size_t i = 0; i < v.size(); ++i)
243 v[i] = nan();
244
245 return;
246 }
247
248 // Read data from the specified column
249 std::vector<real> data;
250 std::vector<std::string> cells;
251
252 while (std::getline(file, line)) {
253
255
256 if (size_t(col_index) < cells.size()) {
257
258 std::string cell = cells[col_index];
259 std::replace(cell.begin(), cell.end(), ',', '.');
260
261 try {
262 const real val = std::stod(cell);
263 data.emplace_back(val);
264 } catch (const std::exception& e) {
265 data.emplace_back(nan());
266 }
267 } else {
268 data.emplace_back(nan());
269 }
270 }
271
272 // Trim trailing NaN values if enabled
273 size_t actual_size = data.size();
274
275 if (trim_nan)
276 while (actual_size > 0 && is_nan(data[actual_size - 1]))
277 actual_size--;
278
279 // Need to allocate space
280 if (v.size() < actual_size) {
281
283
284 if (v.size() < actual_size) {
285 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
287 return;
288 }
289 }
290
291 for (size_t i = 0; i < actual_size; i++)
292 v[i] = data[i];
293
294 for (size_t i = actual_size; i < v.size(); i++)
295 v[i] = nan();
296 }
297
298
303 template<typename Type, unsigned int N, unsigned int M>
304 inline void write_csv(
305 const std::string& filename, const mat<Type, N, M>& A,
306 const std::string& delimiter = ", ", unsigned int precision = 8) {
307
308 std::ofstream file (filename);
309
310 if (!file.is_open()) {
311 TH_IO_ERROR("io::write_csv", filename, IoError::FileNotFound);
312 return;
313 }
314
315 for (size_t i = 0; i < A.rows(); i++) {
316 for (size_t j = 0; j < A.cols(); j++) {
317
318 file << std::setprecision(precision) << A(i, j);
319
320 if (j != A.cols() - 1)
321 file << delimiter;
322 else
323 file << std::endl;
324 }
325 }
326 }
327
328
335 template<unsigned int N, unsigned int K>
336 inline void read_csv(const std::string& filename, mat<real, N, K>& A) {
337
338 std::ifstream file (filename);
339 std::string line;
340
341 if (!file.is_open()) {
342 TH_IO_ERROR("io::read_csv", filename, IoError::FileNotFound);
343 return;
344 }
345
346 std::vector<std::vector<real>> rows;
347
348 // Read first line to check for header
349 if (!std::getline(file, line))
350 return;
351
352 std::vector<std::string> first_row = parse_csv(line);
353
354 // Check if first line is a header
355 bool has_header = false;
356
357 for (const auto& cell : first_row) {
358
359 if (!io::is_number(cell)) {
360 has_header = true;
361 break;
362 }
363 }
364
365 // If first line is not a header, process it as data
366 if (!has_header) {
367
368 std::vector<real> row;
369
370 for (auto cell : first_row) {
371
372 std::replace(cell.begin(), cell.end(), ',', '.');
373
374 try {
375 row.emplace_back(std::stod(cell));
376 } catch (const std::exception& e) {
377 row.emplace_back(nan());
378 }
379 }
380
381 if (!row.empty())
382 rows.emplace_back(row);
383 }
384
385 // Read remaining lines
386 while (std::getline(file, line)) {
387
388 // Skip empty lines
389 if (line.empty())
390 continue;
391
392 std::vector<std::string> cells = parse_csv(line);
393 std::vector<real> row;
394
395 for (auto cell : cells) {
396
397 std::replace(cell.begin(), cell.end(), ',', '.');
398
399 try {
400 row.emplace_back(std::stod(cell));
401 } catch (const std::exception& e) {
402 row.emplace_back(nan());
403 }
404 }
405
406 if (!row.empty()) {
407 rows.emplace_back(row);
408 }
409 }
410
411 A.resize(rows.size(), rows[0].size());
412
413 if (A.rows() < rows[0].size() || A.cols() < rows.size()) {
414 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
416 return;
417 }
418
419 // Fill matrix with parsed data
420 for (size_t i = 0; i < min(rows.size(), A.rows()); ++i) {
421
422 for (size_t j = 0; j < min(rows[i].size(), A.cols()); ++j)
423 A(i, j) = rows[i][j];
424
425 // Pad remaining columns with NaN
426 for (size_t j = rows[i].size(); j < A.cols(); ++j)
427 A(i, j) = nan();
428 }
429
430 // Pad remaining rows with NaN
431 for (size_t i = rows.size(); i < A.rows(); ++i)
432 for (size_t j = 0; j < A.cols(); ++j)
433 A(i, j) = nan();
434 }
435
436
444 template<typename Vector>
445 inline void write_csv(
446 const std::string& filename, const ode::ode_solution_t<Vector>& solution,
447 size_t interleave = 1, const std::string& delimiter = ", ", size_t precision = 8) {
448
449 std::ofstream file (filename);
450
451 if (!file.is_open()) {
452 TH_IO_ERROR("io::write_csv", filename, IoError::FileNotFound);
453 return;
454 }
455
456 if(solution.t.size() != solution.x.size()) {
457 TH_IO_ERROR("io::write_csv", filename, IoError::FormatError);
458 return;
459 }
460
461 for (size_t i = 0; i < solution.t.size(); ++i) {
462
463 file << std::setprecision(precision) << solution.t[i];
464
465 for (size_t j = 0; j < solution.x[i].size(); ++j) {
466
467 if (j % interleave == 0)
468 file << delimiter << std::setprecision(precision) << solution.x[i][j];
469 }
470
471 file << std::endl;
472 }
473
474 }
475
476
481 template<typename Vector>
482 inline void read_csv(const std::string& filename, ode::ode_solution_t<Vector>& solution) {
483
484 std::ifstream file (filename);
485 std::string line;
486
487 if (!file.is_open()) {
488 TH_IO_ERROR("io::read_csv", filename, IoError::FileNotFound);
489 return;
490 }
491
492 std::vector<real> t;
493 std::vector<Vector> x;
494 std::vector<std::string> cells;
496
497 // Read first line and check for header
498 if (std::getline(file, line)) {
499
501
502 bool has_header = false;
503 for (const auto& cell : cells) {
504
505 if (!io::is_number(cell)) {
506 has_header = true;
507 break;
508 }
509 }
510
511 if (!has_header) {
512
513 real val;
514 try {
515 val = std::stod(cells[0]);
516 } catch (const std::exception& e) {
517 val = nan();
518 }
519 t.emplace_back(val);
520
521 state.resize(cells.size() - 1);
522 if (state.size() + 1 != cells.size()) {
523 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
524 return;
525 }
526
527 for (size_t j = 1; j < cells.size(); ++j) {
528
529 try {
530 val = std::stod(cells[j]);
531 } catch (const std::exception& e) {
532 val = nan();
533 }
534 state[j - 1] = val;
535 }
536
537 x.emplace_back(state);
538 }
539 }
540
541 while (std::getline(file, line)) {
542
543 if (line.empty())
544 continue;
545
547
548 if (cells.empty())
549 continue;
550
551 if (state.size() == 0)
552 state.resize(cells.size() - 1);
553
554 try {
555 t.emplace_back(std::stod(cells[0]));
556 } catch (const std::exception& e) {
557 t.emplace_back(nan());
558 }
559
560 if (state.size() + 1 != cells.size()) {
561 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
562 return;
563 }
564
565 for (size_t j = 1; j < cells.size(); ++j) {
566
567 try {
568 state[j - 1] = std::stod(cells[j]);
569 } catch (const std::exception& e) {
570 state[j - 1] = nan();
571 }
572 }
573
574 x.emplace_back(state);
575 }
576
577 solution.t.resize(t.size());
579
580 solution.x.resize(x.size());
581 for (size_t i = 0; i < solution.x.size(); i++)
582 solution.x[i] = x[i];
583 }
584
585
590 inline void write_csv(
591 const std::string& filename, const data_table& table,
592 const std::string& delimiter = ", ", unsigned int precision = 8) {
593
594 std::ofstream file (filename);
595
596 if (!file.is_open()) {
597 TH_IO_ERROR("io::write_csv", filename, IoError::FileNotFound);
598 return;
599 }
600
601 bool first = true;
602 for (const std::string& name : table.header()) {
603
604 if (!first)
605 file << delimiter;
606
607 file << quote_csv(name);
608 first = false;
609 }
610 file << std::endl;
611
612 size_t max_rows = table.rows();
613 for (size_t i = 0; i < max_rows; ++i) {
614
615 first = true;
616 for (const auto& col : table.data()) {
617
618 if (!first)
619 file << delimiter;
620
621 if (i < col.size())
622 file << std::setprecision(precision) << col[i];
623 else
624 file << nan();
625
626 first = false;
627 }
628 file << std::endl;
629 }
630 }
631
632
639 inline void read_csv(const std::string& filename, data_table& table) {
640
641 std::ifstream file (filename);
642 std::string line;
643
644 if (!file.is_open()) {
645 TH_IO_ERROR("io::read_csv", filename, IoError::FileNotFound);
646 return;
647 }
648
649 // Read header
650 if (!std::getline(file, line))
651 return;
652
653 std::vector<std::string> first_row = parse_csv(line);
654
655 if (first_row.empty())
656 return;
657
658 std::vector<std::string> column_names;
659 size_t num_cols = first_row.size();
660 std::vector<vec<real>> columns (num_cols);
661
662 // Check if first line is a header
663 bool has_header = false;
664
665 for (const auto& cell : first_row) {
666
667 if (!io::is_number(cell)) {
668 has_header = true;
669 break;
670 }
671 }
672
673 // If first line is not a header, process it as data
674 if (!has_header) {
675
676 for (size_t j = 0; j < first_row.size(); ++j) {
677
678 std::string cell = first_row[j];
679 std::replace(cell.begin(), cell.end(), ',', '.');
680
681 try {
682 columns[j].append(std::stod(cell));
683 } catch (const std::exception& e) {
684 columns[j].append(nan());
685 }
686 }
687
688 // Generate default column names
689 for (size_t j = 0; j < num_cols; ++j) {
690 column_names.emplace_back("col" + std::to_string(j));
691 }
692
693 } else {
694
695 for (const auto& name : first_row)
696 column_names.emplace_back(io::unquote(io::trim(name)));
697 }
698 first_row.clear();
699
700 // Read data rows
701 while (std::getline(file, line)) {
702
703 if (line.empty())
704 continue;
705
706 std::vector<std::string> cells = parse_csv(line);
707
708 for (size_t j = 0; j < num_cols; ++j) {
709
710 if (j < cells.size()) {
711 std::string cell = cells[j];
712 std::replace(cell.begin(), cell.end(), ',', '.');
713
714 try {
715 real val = std::stod(cell);
716 columns[j].append(val);
717 } catch (const std::exception& e) {
718 columns[j].append(nan());
719 }
720 } else {
721 columns[j].append(nan());
722 }
723 }
724 }
725
726 for (size_t j = 0; j < num_cols; ++j)
727 table.insert(column_names[j], columns[j]);
728 }
729
730
743 inline void write_csv(
744 const std::string& filename, const histogram& hist,
745 bool normalized = false, bool lower_extreme = false,
746 const std::string& delimiter = ", ", unsigned int precision = 8) {
747
748 std::ofstream file (filename);
749 if (!file.is_open()) {
750 TH_IO_ERROR("io::write_csv", filename, IoError::FileNotFound);
751 return;
752 }
753
754 const auto bin_counts = hist.bins();
755
756 // Can't write histogram without bins
757 if (!bin_counts.size()) {
758 TH_IO_ERROR("io::write_csv", filename, IoError::FormatError);
759 return;
760 }
761
762 const real bin_dx = (hist.range()[1] - hist.range()[0]) / bin_counts.size();
763 real norm_factor = normalized ? hist.number() * bin_dx : 1.0;
765 norm_factor = 1.0;
766
767 // Keep track of the coordinate of the current bin, starting from the lowest bin edge or center.
768 real bin_value = lower_extreme ? hist.range()[0] : (hist.range()[0] + 0.5 * bin_dx);
769
770 // Write header with histogram statistics
771 file << "bins, counts, number, average, tss, min, max" << std::endl;
772 if (!bin_counts.size())
773 return;
774
775 file << std::setprecision(precision) << bin_value << delimiter;
776 file << std::setprecision(precision) << (bin_counts[0] / norm_factor) << delimiter;
777 file << hist.number() << delimiter;
778 file << hist.mean() << delimiter;
779 file << hist.tss() << delimiter;
780 file << hist.min() << delimiter;
781 file << hist.max() << std::endl;
782
783 for (size_t i = 1; i < bin_counts.size(); i++) {
784
785 bin_value += bin_dx;
786 file << std::setprecision(precision) << bin_value << delimiter;
787 file << std::setprecision(precision) << (bin_counts[i] / norm_factor) << std::endl;
788 }
789 }
790
791
798 inline void read_csv(const std::string& filename, histogram& hist, bool lower_extreme = false) {
799
800 std::ifstream file (filename);
801 if (!file.is_open()) {
802 TH_IO_ERROR("io::read_csv", filename, IoError::FileNotFound);
803 return;
804 }
805
806 std::string line;
807 std::vector<std::string> cells;
808
809 // Read header
810 std::getline(file, line);
812
813 int bin_index = -1, count_index = -1, number_index = -1, average_index = -1;
814 int tss_index = -1, min_index = -1, max_index = -1;
815
816 // Find column indices for the expected headers
817 for (size_t i = 0; i < cells.size(); i++) {
818
819 if (cells[i] == "bins") bin_index = i;
820 else if (cells[i] == "counts") count_index = i;
821 else if (cells[i] == "number") number_index = i;
822 else if (cells[i] == "average") average_index = i;
823 else if (cells[i] == "tss") tss_index = i;
824 else if (cells[i] == "min") min_index = i;
825 else if (cells[i] == "max") max_index = i;
826 }
827
828 if (bin_index == -1 || count_index == -1 || number_index == -1 ||
829 average_index == -1 || tss_index == -1 || min_index == -1 || max_index == -1) {
830
831 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
832 return;
833 }
834
835 // Find the maximum required column index
836 int min_size = bin_index;
843 min_size++;
844
845 // Read first data line for statistics
846 std::getline(file, line);
848
849 if (cells.size() < size_t(min_size)) {
850 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
851 return;
852 }
853
854 vec<real> counts, bins;
855 size_t N;
856 real run_average, run_tss, value_min, value_max;
857
858 try {
859
860 counts = {std::stod(cells[count_index])};
861 bins = {std::stod(cells[bin_index])};
862
863 N = std::stod(cells[number_index]);
864 run_average = std::stod(cells[average_index]);
865 run_tss = std::stod(cells[tss_index]);
866 value_min = std::stod(cells[min_index]);
867 value_max = std::stod(cells[max_index]);
868
869 } catch (const std::invalid_argument& e) {
870 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
871 return;
872 }
873
875
876 // Read remaining data lines
877 while (std::getline(file, line)) {
878
880
881 if (cells.size() < size_t(bins_max_index)) {
882 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
883 return;
884 }
885
886 try {
887 counts.append(cells[count_index] != "" ? std::stod(cells[count_index]) : nan());
888 bins.append(cells[bin_index] != "" ? std::stod(cells[bin_index]) : nan());
889 } catch (const std::exception& e) {
890 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
891 return;
892 }
893
894 }
895
896 real range_min;
897 real range_max;
898
899 bool is_normalized = false;
900 for (size_t i = 0; i < counts.size(); i++) {
901
902 // Check if any bin counts are not integers
903 if (counts[i] != floor(counts[i])) {
904 is_normalized = true;
905 break;
906 }
907 }
908
909 std::vector<unsigned int> bin_counts (counts.size());
910 for (size_t i = 0; i < counts.size(); i++) {
911 bin_counts[i] = (unsigned int) (is_normalized ? (counts[i] * N) : counts[i]);
912 }
913
914 const real bin_dx = bins.size() > 1 ? (bins[1] - bins[0]) : 0;
915 range_min = lower_extreme ? bins[0] : (bins[0] - 0.5 * bin_dx);
916 range_max = lower_extreme ? bins[bins.size() - 1] + bin_dx : bins[bins.size() - 1] + 0.5 * bin_dx;
917
918 // Check constant bin spacing
919 for (size_t i = 1; i < bins.size(); i++) {
920 if (abs((bins[i] - bins[i - 1]) - bin_dx) > 1e-6) {
921 TH_IO_ERROR("io::read_csv", filename, IoError::FormatError);
922 return;
923 }
924 }
925
926 hist.rebuild(
927 bin_counts, vec2({range_min, range_max}),
928 N, run_average, run_tss,
929 value_min, value_max
930 );
931
932 }
933
943 template<typename Type>
944 inline Type read_csv(const std::string& filename) {
945 Type A;
946 read_csv(filename, A);
947 return A;
948 }
949
950}}
951
952#endif
A data structure for holding labeled columns of data, where each column is a vector of real numbers.
Definition data_table.h:26
Histogram class with running statistics, can be constructed from the parameters of the bins or from a...
Definition histogram.h:28
A generic matrix with a fixed number of rows and columns.
Definition mat.h:136
TH_CONSTEXPR unsigned int rows() const
Returns the number of rows in the matrix.
Definition mat.h:641
TH_CONSTEXPR unsigned int cols() const
Returns the number of columns in the matrix.
Definition mat.h:648
mat< Type, N, K > resize(unsigned int n, unsigned int k)
Compatibility function to allow for allocation or resizing of dynamic matrices.
Definition mat.h:730
A statically allocated N-dimensional vector with elements of the given type.
Definition vec.h:92
void resize(size_t n) const
Compatibility function to allow for allocation or resizing of dynamic vectors.
Definition vec.h:459
TH_CONSTEXPR unsigned int size() const
Returns the size of the vector (N)
Definition vec.h:449
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:219
Data table structure for holding labeled columns of data.
Error handling for IO operations.
Vector1 & vec_copy(Vector1 &dest, const Vector2 &src)
Copy a vector by overwriting another.
Definition algebra.h:241
Matrix & mat_error(Matrix &m)
Overwrite the given matrix with the error matrix with NaN values on the diagonal and zeroes everywher...
Definition algebra.h:40
Vector & vec_error(Vector &v)
Overwrite the given vector with the error vector with NaN values.
Definition algebra.h:58
bool is_number(const std::string &str)
Check if a given string could be correctly interpreted as a number.
Definition strings.h:20
std::string trim(const std::string &str)
Remove all leading and trailing whitespace from a string, returning the resulting string.
Definition strings.h:40
@ FileNotFound
File or directory not found.
@ FormatError
The file format is invalid or the data is corrupted.
@ ReadError
Error occurred while reading from the file or stream.
std::string quote_csv(const std::string &str)
Given a string entry, sanitize it for printing to a CSV file.
Definition csv.h:63
std::vector< std::string > parse_csv(const std::string &line, char delimiter=',')
Parse a CSV line handling quoted fields.
Definition csv.h:33
void read_csv(const std::string &filename, vec< Type, N > &v)
Read a vector from a file in the CSV format.
Definition csv.h:132
void write_csv(const std::string &filename, const vec< Type, N > &v, unsigned int precision=8)
Write a vector to file in the CSV format.
Definition csv.h:87
std::string unquote(const std::string &str)
Remove leading and trailing double quotes from a string, if both are present.
Definition strings.h:58
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
double real
A real number, defined as a floating point type.
Definition constants.h:207
auto min(const Vector &X)
Finds the minimum value inside a dataset.
Definition dataset.h:347
vec< real, 2 > vec2
A 2-dimensional vector with real elements.
Definition algebra_types.h:39
bool is_nan(const T &x)
Check whether a generic variable is (equivalent to) a NaN number.
Definition error.h:90
dual2 abs(dual2 x)
Compute the absolute value of a second order dual number.
Definition dual2_functions.h:242
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:74
@ OutOfRange
Result out of range.
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216
TH_CONSTEXPR int floor(real x)
Compute the floor of x, as the maximum integer number that is smaller than x.
Definition real_analysis.h:271
String manipulation functions.
Data structure holding the numerical solution of a discretized ODE, where the vector represents the ...
Definition ode.h:24