tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
math_helpers.hpp
Go to the documentation of this file.
1#ifndef TATAMI_MATH_HELPERS_H
2#define TATAMI_MATH_HELPERS_H
3
10#include <cmath>
11
12namespace tatami {
13
23template<typename InputValue_ = double>
25public:
29 static constexpr bool is_basic = false;
30
31 bool is_sparse() const {
32 return true;
33 }
34
39private:
40 template<typename Index_, typename OutputValue_>
41 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
42 for (Index_ i = 0; i < length; ++i) {
43 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
44 auto& val = output[i];
45 val = std::abs(val);
46 } else {
47 output[i] = std::abs(input[i]);
48 }
49 }
50 }
51
52public:
56 template<typename Index_, typename OutputValue_>
57 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
58 core(input, length, output);
59 }
60
61 template<typename Index_, typename OutputValue_>
62 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
64 }
65
66 template<typename Index_, typename OutputValue_>
67 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
68 core(input, number, output);
69 }
70
71 template<typename OutputValue_, typename Index_>
72 OutputValue_ fill(bool, Index_) const {
73 return 0;
74 }
78};
79
91template<typename InputValue_ = double>
93public:
97 static constexpr bool is_basic = false;
98
99 bool is_sparse() const {
100 return true;
101 }
106private:
107 template<typename Index_, typename OutputValue_>
108 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
109 for (Index_ i = 0; i < length; ++i) {
110 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
111 auto& val = output[i];
112 if (!std::isnan(val)) {
113 val = (static_cast<InputValue_>(0) < val) - (val < static_cast<InputValue_>(0));
114 }
115 } else {
116 auto val = input[i];
117 if (!std::isnan(val)) {
118 output[i] = (static_cast<InputValue_>(0) < val) - (val < static_cast<InputValue_>(0));
119 } else if constexpr(std::numeric_limits<OutputValue_>::has_quiet_NaN) {
120 output[i] = std::numeric_limits<OutputValue_>::quiet_NaN();
121 } else {
122 output[i] = 0;
123 }
124 }
125 }
126 }
127
128public:
132 template<typename Index_, typename OutputValue_>
133 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
134 core(input, length, output);
135 }
136
137 template<typename Index_, typename OutputValue_>
138 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
140 }
141
142 template<typename Index_, typename OutputValue_>
143 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
144 core(input, number, output);
145 }
146
147 template<typename OutputValue_, typename Index_>
148 OutputValue_ fill(bool, Index_) const {
149 return 0;
150 }
154};
155
166template<typename InputValue_ = double, typename Base_ = InputValue_>
168public:
172 DelayedUnaryIsometricLog() : my_base(1) {}
173
178
179public:
183 static constexpr bool is_basic = false;
184
185 bool is_sparse() const {
186 return false;
187 }
192private:
193 Base_ my_base;
194
195 template<typename Index_, typename OutputValue_>
196 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
197 for (Index_ i = 0; i < length; ++i) {
198 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
199 auto& val = output[i];
200 val = std::log(val) / my_base;
201 } else {
202 output[i] = std::log(input[i]) / my_base;
203 }
204 }
205 }
206
207public:
211 template<typename Index_, typename OutputValue_>
212 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
213 core(input, length, output);
214 }
215
216 template<typename Index_, typename OutputValue_>
217 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
219 }
220
221 template<typename Index_, typename OutputValue_>
222 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
223 core(input, number, output);
224 }
225
226 template<typename OutputValue_, typename Index_>
227 OutputValue_ fill(bool, Index_) const {
228 // Use the implementation-defined value.
229 return std::log(static_cast<OutputValue_>(0));
230 }
234};
235
245template<typename InputValue_ = double>
247public:
251 static constexpr bool is_basic = false;
252
253 bool is_sparse() const {
254 return true;
255 }
260private:
261 template<typename Index_, typename OutputValue_>
262 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
263 for (Index_ i = 0; i < length; ++i) {
264 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
265 auto& val = output[i];
266 val = std::sqrt(val);
267 } else {
268 output[i] = std::sqrt(input[i]);
269 }
270 }
271 }
272
273public:
277 template<typename Index_, typename OutputValue_>
278 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
279 core(input, length, output);
280 }
281
282 template<typename Index_, typename OutputValue_>
283 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
284 core(input, indices.size(), output);
285 }
286
287 template<typename Index_, typename OutputValue_>
288 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
289 core(input, number, output);
290 }
291
292 template<typename OutputValue_, typename Index_>
293 OutputValue_ fill(bool, Index_) const {
294 return 0;
295 }
299};
300
310template<typename InputValue_ = double>
312public:
316 static constexpr bool is_basic = false;
317
318 bool is_sparse() const {
319 return true;
320 }
325private:
326 template<typename Index_, typename OutputValue_>
327 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
328 for (Index_ i = 0; i < length; ++i) {
329 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
330 auto& val = output[i];
331 val = std::ceil(val);
332 } else {
333 output[i] = std::ceil(input[i]);
334 }
335 }
336 }
337
338public:
342 template<typename Index_, typename OutputValue_>
343 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
344 core(input, length, output);
345 }
346
347 template<typename Index_, typename OutputValue_>
348 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
350 }
351
352 template<typename Index_, typename OutputValue_>
353 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
354 core(input, number, output);
355 }
356
357 template<typename OutputValue_, typename Index_>
358 OutputValue_ fill(bool, Index_) const {
359 return 0;
360 }
364};
365
375template<typename InputValue_ = double>
377public:
381 static constexpr bool is_basic = false;
382
383 bool is_sparse() const {
384 return true;
385 }
390private:
391 template<typename Index_, typename OutputValue_>
392 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
393 for (Index_ i = 0; i < length; ++i) {
394 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
395 auto& val = output[i];
396 val = std::floor(val);
397 } else {
398 output[i] = std::floor(input[i]);
399 }
400 }
401 }
402
403public:
407 template<typename Index_, typename OutputValue_>
408 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
409 core(input, length, output);
410 }
411
412 template<typename Index_, typename OutputValue_>
413 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
414 core(input, indices.size(), output);
415 }
416
417 template<typename Index_, typename OutputValue_>
418 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
419 core(input, number, output);
420 }
421
422 template<typename OutputValue_, typename Index_>
423 OutputValue_ fill(bool, Index_) const {
424 return 0;
425 }
429};
430
440template<typename InputValue_ = double>
442public:
446 static constexpr bool is_basic = false;
447
448 bool is_sparse() const {
449 return true;
450 }
455private:
456 template<typename Index_, typename OutputValue_>
457 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
458 for (Index_ i = 0; i < length; ++i) {
459 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
460 auto& val = output[i];
461 val = std::trunc(val);
462 } else {
463 output[i] = std::trunc(input[i]);
464 }
465 }
466 }
467
468public:
472 template<typename Index_, typename OutputValue_>
473 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
474 core(input, length, output);
475 }
476
477 template<typename Index_, typename OutputValue_>
478 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
479 core(input, indices.size(), output);
480 }
481
482 template<typename Index_, typename OutputValue_>
483 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
484 core(input, number, output);
485 }
486
487 template<typename OutputValue_, typename Index_>
488 OutputValue_ fill(bool, Index_) const {
489 return 0;
490 }
494};
495
506template<typename InputValue_ = double, typename Base_ = InputValue_>
508public:
513
518
519public:
523 static constexpr bool is_basic = false;
524
525 bool is_sparse() const {
526 return true;
527 }
532private:
533 template<typename Index_, typename OutputValue_>
534 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
535 for (Index_ i = 0; i < length; ++i) {
536 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
537 auto& val = output[i];
538 val = std::log1p(val) / my_base;
539 } else {
540 output[i] = std::log1p(input[i]) / my_base;
541 }
542 }
543 }
544
545 Base_ my_base;
546
547public:
551 template<typename Index_, typename OutputValue_>
552 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
553 core(input, length, output);
554 }
555
556 template<typename Index_, typename OutputValue_>
557 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
558 core(input, indices.size(), output);
559 }
560
561 template<typename Index_, typename OutputValue_>
562 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
563 core(input, number, output);
564 }
565
566 template<typename OutputValue_, typename Index_>
567 OutputValue_ fill(bool, Index_) const {
568 return 0;
569 }
573};
574
584template<typename InputValue_ = double>
586public:
590 static constexpr bool is_basic = false;
591
592 bool is_sparse() const {
593 return true;
594 }
599private:
600 template<typename Index_, typename OutputValue_>
601 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
602 for (Index_ i = 0; i < length; ++i) {
603 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
604 auto& val = output[i];
605 val = std::round(val);
606 } else {
607 output[i] = std::round(input[i]);
608 }
609 }
610 }
611
612public:
616 template<typename Index_, typename OutputValue_>
617 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
618 core(input, length, output);
619 }
620
621 template<typename Index_, typename OutputValue_>
622 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
623 core(input, indices.size(), output);
624 }
625
626 template<typename Index_, typename OutputValue_>
627 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
628 core(input, number, output);
629 }
630
631 template<typename OutputValue_, typename Index_>
632 OutputValue_ fill(bool, Index_) const {
633 return 0;
634 }
638};
639
649template<typename InputValue_ = double>
651public:
655 static constexpr bool is_basic = false;
656
657 bool is_sparse() const {
658 return false;
659 }
664private:
665 template<typename Index_, typename OutputValue_>
666 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
667 for (Index_ i = 0; i < length; ++i) {
668 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
669 auto& val = output[i];
670 val = std::exp(val);
671 } else {
672 output[i] = std::exp(input[i]);
673 }
674 }
675 }
676
677public:
681 template<typename Index_, typename OutputValue_>
682 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
683 core(input, length, output);
684 }
685
686 template<typename Index_, typename OutputValue_>
687 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
688 core(input, indices.size(), output);
689 }
690
691 template<typename Index_, typename OutputValue_>
692 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
693 core(input, number, output);
694 }
695
696 template<typename OutputValue_, typename Index_>
697 OutputValue_ fill(bool, Index_) const {
698 return 1;
699 }
703};
704
714template<typename InputValue_ = double>
716public:
720 static constexpr bool is_basic = false;
721
722 bool is_sparse() const {
723 return true;
724 }
729private:
730 template<typename Index_, typename OutputValue_>
731 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
732 for (Index_ i = 0; i < length; ++i) {
733 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
734 auto& val = output[i];
735 val = std::expm1(val);
736 } else {
737 output[i] = std::expm1(input[i]);
738 }
739 }
740 }
741
742public:
746 template<typename Index_, typename OutputValue_>
747 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
748 core(input, length, output);
749 }
750
751 template<typename Index_, typename OutputValue_>
752 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
753 core(input, indices.size(), output);
754 }
755
756 template<typename Index_, typename OutputValue_>
757 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
758 core(input, number, output);
759 }
760
761 template<typename OutputValue_, typename Index_>
762 OutputValue_ fill(bool, Index_) const {
763 return 0;
764 }
768};
769
779template<typename InputValue_ = double>
781public:
785 static constexpr bool is_basic = false;
786
787 bool is_sparse() const {
788 return false;
789 }
794private:
795 template<typename Index_, typename OutputValue_>
796 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
797 for (Index_ i = 0; i < length; ++i) {
798 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
799 auto& val = output[i];
800 val = std::acos(val);
801 } else {
802 output[i] = std::acos(input[i]);
803 }
804 }
805 }
806
807public:
811 template<typename Index_, typename OutputValue_>
812 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
813 core(input, length, output);
814 }
815
816 template<typename Index_, typename OutputValue_>
817 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
818 core(input, indices.size(), output);
819 }
820
821 template<typename Index_, typename OutputValue_>
822 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
823 core(input, number, output);
824 }
825
826 template<typename OutputValue_, typename Index_>
827 OutputValue_ fill(bool, Index_) const {
828 // Use the implementation-defined special value.
829 return std::acos(0);
830 }
834};
835
845template<typename InputValue_ = double>
847public:
851 static constexpr bool is_basic = false;
852
853 bool is_sparse() const {
854 return false;
855 }
860private:
861 template<typename Index_, typename OutputValue_>
862 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
863 for (Index_ i = 0; i < length; ++i) {
864 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
865 auto& val = output[i];
866 val = std::acosh(val);
867 } else {
868 output[i] = std::acosh(input[i]);
869 }
870 }
871 }
872
873public:
877 template<typename Index_, typename OutputValue_>
878 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
879 core(input, length, output);
880 }
881
882 template<typename Index_, typename OutputValue_>
883 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
884 core(input, indices.size(), output);
885 }
886
887 template<typename Index_, typename OutputValue_>
888 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
889 core(input, number, output);
890 }
891
892 template<typename OutputValue_, typename Index_>
893 OutputValue_ fill(bool, Index_) const {
894 // Use the implementation-defined special value.
895 return std::acosh(static_cast<InputValue_>(0));
896 }
900};
901
911template<typename InputValue_ = double>
913public:
917 static constexpr bool is_basic = false;
918
919 bool is_sparse() const {
920 return true;
921 }
926private:
927 template<typename Index_, typename OutputValue_>
928 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
929 for (Index_ i = 0; i < length; ++i) {
930 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
931 auto& val = output[i];
932 val = std::asin(val);
933 } else {
934 output[i] = std::asin(input[i]);
935 }
936 }
937 }
938
939public:
943 template<typename Index_, typename OutputValue_>
944 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
945 core(input, length, output);
946 }
947
948 template<typename Index_, typename OutputValue_>
949 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
950 core(input, indices.size(), output);
951 }
952
953 template<typename Index_, typename OutputValue_>
954 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
955 core(input, number, output);
956 }
957
958 template<typename OutputValue_, typename Index_>
959 OutputValue_ fill(bool, Index_) const {
960 return 0;
961 }
965};
966
976template<typename InputValue_ = double>
978public:
982 static constexpr bool is_basic = false;
983
984 bool is_sparse() const {
985 return true;
986 }
991private:
992 template<typename Index_, typename OutputValue_>
993 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
994 for (Index_ i = 0; i < length; ++i) {
995 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
996 auto& val = output[i];
997 val = std::asinh(val);
998 } else {
999 output[i] = std::asinh(input[i]);
1000 }
1001 }
1002 }
1003
1004public:
1008 template<typename Index_, typename OutputValue_>
1009 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1010 core(input, length, output);
1011 }
1012
1013 template<typename Index_, typename OutputValue_>
1014 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1015 core(input, indices.size(), output);
1016 }
1017
1018 template<typename Index_, typename OutputValue_>
1019 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1020 core(input, number, output);
1021 }
1022
1023 template<typename OutputValue_, typename Index_>
1024 OutputValue_ fill(bool, Index_) const {
1025 return 0;
1026 }
1030};
1031
1041template<typename InputValue_ = double>
1043public:
1047 static constexpr bool is_basic = false;
1048
1049 bool is_sparse() const {
1050 return true;
1051 }
1056private:
1057 template<typename Index_, typename OutputValue_>
1058 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1059 for (Index_ i = 0; i < length; ++i) {
1060 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1061 auto& val = output[i];
1062 val = std::atan(val);
1063 } else {
1064 output[i] = std::atan(input[i]);
1065 }
1066 }
1067 }
1068
1069public:
1073 template<typename Index_, typename OutputValue_>
1074 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1075 core(input, length, output);
1076 }
1077
1078 template<typename Index_, typename OutputValue_>
1079 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1080 core(input, indices.size(), output);
1081 }
1082
1083 template<typename Index_, typename OutputValue_>
1084 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1085 core(input, number, output);
1086 }
1087
1088 template<typename OutputValue_, typename Index_>
1089 OutputValue_ fill(bool, Index_) const {
1090 return 0;
1091 }
1095};
1096
1106template<typename InputValue_ = double>
1108public:
1112 static constexpr bool is_basic = false;
1113
1114 bool is_sparse() const {
1115 return true;
1116 }
1121private:
1122 template<typename Index_, typename OutputValue_>
1123 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1124 for (Index_ i = 0; i < length; ++i) {
1125 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1126 auto& val = output[i];
1127 val = std::atanh(val);
1128 } else {
1129 output[i] = std::atanh(input[i]);
1130 }
1131 }
1132 }
1133
1134public:
1138 template<typename Index_, typename OutputValue_>
1139 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1140 core(input, length, output);
1141 }
1142
1143 template<typename Index_, typename OutputValue_>
1144 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1145 core(input, indices.size(), output);
1146 }
1147
1148 template<typename Index_, typename OutputValue_>
1149 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1150 core(input, number, output);
1151 }
1152
1153 template<typename OutputValue_, typename Index_>
1154 OutputValue_ fill(bool, Index_) const {
1155 return 0;
1156 }
1160};
1161
1171template<typename InputValue_ = double>
1173public:
1177 static constexpr bool is_basic = false;
1178
1179 bool is_sparse() const {
1180 return false;
1181 }
1186private:
1187 template<typename Index_, typename OutputValue_>
1188 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1189 for (Index_ i = 0; i < length; ++i) {
1190 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1191 auto& val = output[i];
1192 val = std::cos(val);
1193 } else {
1194 output[i] = std::cos(input[i]);
1195 }
1196 }
1197 }
1198
1199public:
1203 template<typename Index_, typename OutputValue_>
1204 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1205 core(input, length, output);
1206 }
1207
1208 template<typename Index_, typename OutputValue_>
1209 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1210 core(input, indices.size(), output);
1211 }
1212
1213 template<typename Index_, typename OutputValue_>
1214 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1215 core(input, number, output);
1216 }
1217
1218 template<typename OutputValue_, typename Index_>
1219 OutputValue_ fill(bool, Index_) const {
1220 return 1.0;
1221 }
1225};
1226
1236template<typename InputValue_ = double>
1238public:
1242 static constexpr bool is_basic = false;
1243
1244 bool is_sparse() const {
1245 return false;
1246 }
1251private:
1252 template<typename Index_, typename OutputValue_>
1253 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1254 for (Index_ i = 0; i < length; ++i) {
1255 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1256 auto& val = output[i];
1257 val = std::cosh(val);
1258 } else {
1259 output[i] = std::cosh(input[i]);
1260 }
1261 }
1262 }
1263
1264public:
1268 template<typename Index_, typename OutputValue_>
1269 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1270 core(input, length, output);
1271 }
1272
1273 template<typename Index_, typename OutputValue_>
1274 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1275 core(input, indices.size(), output);
1276 }
1277
1278 template<typename Index_, typename OutputValue_>
1279 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1280 core(input, number, output);
1281 }
1282
1283 template<typename OutputValue_, typename Index_>
1284 OutputValue_ fill(bool, Index_) const {
1285 return 1.0;
1286 }
1290};
1291
1301template<typename InputValue_ = double>
1303public:
1307 static constexpr bool is_basic = false;
1308
1309 bool is_sparse() const {
1310 return true;
1311 }
1316private:
1317 template<typename Index_, typename OutputValue_>
1318 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1319 for (Index_ i = 0; i < length; ++i) {
1320 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1321 auto& val = output[i];
1322 val = std::sin(val);
1323 } else {
1324 output[i] = std::sin(input[i]);
1325 }
1326 }
1327 }
1328
1329public:
1333 template<typename Index_, typename OutputValue_>
1334 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1335 core(input, length, output);
1336 }
1337
1338 template<typename Index_, typename OutputValue_>
1339 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1340 core(input, indices.size(), output);
1341 }
1342
1343 template<typename Index_, typename OutputValue_>
1344 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1345 core(input, number, output);
1346 }
1347
1348 template<typename OutputValue_, typename Index_>
1349 OutputValue_ fill(bool, Index_) const {
1350 return 0;
1351 }
1355};
1356
1366template<typename InputValue_ = double>
1368public:
1372 static constexpr bool is_basic = false;
1373
1374 bool is_sparse() const {
1375 return true;
1376 }
1381private:
1382 template<typename Index_, typename OutputValue_>
1383 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1384 for (Index_ i = 0; i < length; ++i) {
1385 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1386 auto& val = output[i];
1387 val = std::sinh(val);
1388 } else {
1389 output[i] = std::sinh(input[i]);
1390 }
1391 }
1392 }
1393
1394public:
1398 template<typename Index_, typename OutputValue_>
1399 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1400 core(input, length, output);
1401 }
1402
1403 template<typename Index_, typename OutputValue_>
1404 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1405 core(input, indices.size(), output);
1406 }
1407
1408 template<typename Index_, typename OutputValue_>
1409 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1410 core(input, number, output);
1411 }
1412
1413 template<typename OutputValue_, typename Index_>
1414 OutputValue_ fill(bool, Index_) const {
1415 return 0;
1416 }
1420};
1421
1431template<typename InputValue_ = double>
1433public:
1437 static constexpr bool is_basic = false;
1438
1439 bool is_sparse() const {
1440 return true;
1441 }
1446private:
1447 template<typename Index_, typename OutputValue_>
1448 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1449 for (Index_ i = 0; i < length; ++i) {
1450 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1451 auto& val = output[i];
1452 val = std::tan(val);
1453 } else {
1454 output[i] = std::tan(input[i]);
1455 }
1456 }
1457 }
1458
1459public:
1463 template<typename Index_, typename OutputValue_>
1464 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1465 core(input, length, output);
1466 }
1467
1468 template<typename Index_, typename OutputValue_>
1469 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1470 core(input, indices.size(), output);
1471 }
1472
1473 template<typename Index_, typename OutputValue_>
1474 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1475 core(input, number, output);
1476 }
1477
1478 template<typename OutputValue_, typename Index_>
1479 OutputValue_ fill(bool, Index_) const {
1480 return 0;
1481 }
1485};
1486
1496template<typename InputValue_ = double>
1498public:
1502 static constexpr bool is_basic = false;
1503
1504 bool is_sparse() const {
1505 return true;
1506 }
1511private:
1512 template<typename Index_, typename OutputValue_>
1513 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1514 for (Index_ i = 0; i < length; ++i) {
1515 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1516 auto& val = output[i];
1517 val = std::tanh(val);
1518 } else {
1519 output[i] = std::tanh(input[i]);
1520 }
1521 }
1522 }
1523
1524public:
1528 template<typename Index_, typename OutputValue_>
1529 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1530 core(input, length, output);
1531 }
1532
1533 template<typename Index_, typename OutputValue_>
1534 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1535 core(input, indices.size(), output);
1536 }
1537
1538 template<typename Index_, typename OutputValue_>
1539 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1540 core(input, number, output);
1541 }
1542
1543 template<typename OutputValue_, typename Index_>
1544 OutputValue_ fill(bool, Index_) const {
1545 return 0;
1546 }
1550};
1551
1561template<typename InputValue_ = double>
1563public:
1567 static constexpr bool is_basic = false;
1568
1569 bool is_sparse() const {
1570 return false;
1571 }
1576private:
1577 template<typename Index_, typename OutputValue_>
1578 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1579 for (Index_ i = 0; i < length; ++i) {
1580 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1581 auto& val = output[i];
1582 val = std::tgamma(val);
1583 } else {
1584 output[i] = std::tgamma(input[i]);
1585 }
1586 }
1587 }
1588
1589public:
1593 template<typename Index_, typename OutputValue_>
1594 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1595 core(input, length, output);
1596 }
1597
1598 template<typename Index_, typename OutputValue_>
1599 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1600 core(input, indices.size(), output);
1601 }
1602
1603 template<typename Index_, typename OutputValue_>
1604 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1605 core(input, number, output);
1606 }
1607
1608 template<typename OutputValue_, typename Index_>
1609 OutputValue_ fill(bool, Index_) const {
1610 // Use the implementation-defined special value.
1611 return std::tgamma(static_cast<InputValue_>(0));
1612 }
1616};
1617
1627template<typename InputValue_ = double>
1629public:
1633 static constexpr bool is_basic = false;
1634
1635 bool is_sparse() const {
1636 return false;
1637 }
1642private:
1643 template<typename Index_, typename OutputValue_>
1644 void core(const InputValue_* input, Index_ length, OutputValue_* output) const {
1645 for (Index_ i = 0; i < length; ++i) {
1646 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
1647 auto& val = output[i];
1648 val = std::lgamma(val);
1649 } else {
1650 output[i] = std::lgamma(input[i]);
1651 }
1652 }
1653 }
1654
1655public:
1659 template<typename Index_, typename OutputValue_>
1660 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
1661 core(input, length, output);
1662 }
1663
1664 template<typename Index_, typename OutputValue_>
1665 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
1666 core(input, indices.size(), output);
1667 }
1668
1669 template<typename Index_, typename OutputValue_>
1670 void sparse(bool, Index_, Index_ number, const InputValue_* input, const Index_*, OutputValue_* output) const {
1671 core(input, number, output);
1672 }
1673
1674 template<typename OutputValue_, typename Index_>
1675 OutputValue_ fill(bool, Index_) const {
1676 // Use the implementation-defined special value.
1677 return std::lgamma(static_cast<InputValue_>(0));
1678 }
1682};
1683
1684}
1685
1686#endif
Take the absolute value of a matrix entry.
Definition math_helpers.hpp:24
Take the inverse cosine of a matrix entry.
Definition math_helpers.hpp:780
Take the inverse hyperbolic cosine of a matrix entry.
Definition math_helpers.hpp:846
Take the inverse sine of a matrix entry.
Definition math_helpers.hpp:912
Take the inverse hyperbolic sine of a matrix entry.
Definition math_helpers.hpp:977
Take the inverse tangent of a matrix entry.
Definition math_helpers.hpp:1042
Take the inverse hyperbolic tangent of a matrix entry.
Definition math_helpers.hpp:1107
Take the ceiling of a matrix entry.
Definition math_helpers.hpp:311
Take the cosine of a matrix entry.
Definition math_helpers.hpp:1172
Take the hyperbolic cosine of a matrix entry.
Definition math_helpers.hpp:1237
Use a matrix entry as an exponent.
Definition math_helpers.hpp:650
Use a matrix entry as an exponent minus 1.
Definition math_helpers.hpp:715
Take the floor of a matrix entry.
Definition math_helpers.hpp:376
Apply the gamma function to a matrix entry.
Definition math_helpers.hpp:1562
Apply the log-gamma function to a matrix entry.
Definition math_helpers.hpp:1628
Take the logarithm of a matrix entry plus 1.
Definition math_helpers.hpp:507
DelayedUnaryIsometricLog1p(Base_ base)
Definition math_helpers.hpp:517
DelayedUnaryIsometricLog1p()
Definition math_helpers.hpp:512
Take the logarithm of a matrix entry.
Definition math_helpers.hpp:167
DelayedUnaryIsometricLog()
Definition math_helpers.hpp:172
DelayedUnaryIsometricLog(Base_ base)
Definition math_helpers.hpp:177
Round a matrix entry to the nearest integer.
Definition math_helpers.hpp:585
Take the sign of a matrix entry.
Definition math_helpers.hpp:92
Take the sine of a matrix entry.
Definition math_helpers.hpp:1302
Take the hyperbolic sine of a matrix entry.
Definition math_helpers.hpp:1367
Take the square root of a matrix entry.
Definition math_helpers.hpp:246
Take the tangent of a matrix entry.
Definition math_helpers.hpp:1432
Take the hyperbolic tangent of a matrix entry.
Definition math_helpers.hpp:1497
Integer truncation of a matrix entry.
Definition math_helpers.hpp:441
Flexible representations for matrix data.
Definition Extractor.hpp:15
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
Definition consecutive_extractor.hpp:35