@@ -50,7 +50,7 @@ inline plain_type_t<Vec> sum_to_zero_constrain(const Vec& y) {
50
50
value_type_t <Vec>sum_w (0 );
51
51
for (int i = N; i >0 ; --i) {
52
52
double n =static_cast <double >(i);
53
- auto w =y_ref (i -1 ) *inv_sqrt (n * (n +1 ));
53
+ auto w = y_ref. coeff (i -1 ) *inv_sqrt (n * (n +1 ));
54
54
sum_w += w;
55
55
56
56
z.coeffRef (i -1 ) += sum_w;
@@ -61,47 +61,81 @@ inline plain_type_t<Vec> sum_to_zero_constrain(const Vec& y) {
61
61
}
62
62
63
63
/* *
64
- * Return avector with sum zerocorresponding to thespecified
65
- * freevector .
64
+ * Return amatrix that sums to zeroover both therows
65
+ *and columns corresponding to the freematrix x .
66
66
*
67
- * The sum-to-zero transform is defined using a modified version of the
68
- * the inverse of the isometric log ratio transform (ILR).
69
- * See:
70
- * Egozcue, Juan Jose; Pawlowsky-Glahn, Vera; Mateu-Figueras, Gloria;
71
- * Barcelo-Vidal, Carles (2003), "Isometric logratio transformations for
72
- * compositional data analysis", Mathematical Geology, 35 (3): 279–300,
73
- * doi:10.1023/A:1023818214614, S2CID 122844634
67
+ * This is a linear transform, with no Jacobian.
74
68
*
75
- * This implementation is closer to the description of the same using "pivot
76
- * coordinates" in
77
- * Filzmoser, P., Hron, K., Templ, M. (2018). Geometrical Properties of
78
- * Compositional Data. In: Applied Compositional Data Analysis. Springer Series
79
- * in Statistics. Springer, Cham. https://doi.org/10.1007/978-3-319-96422-5_3
69
+ * @tparam Mat type of the matrix
70
+ * @param x Free matrix input of dimensionality (N - 1, M - 1).
71
+ * @return Zero-sum matrix of dimensionality (N, M).
72
+ */
73
+ template <typename Mat,require_eigen_matrix_dynamic_t <Mat>* =nullptr ,
74
+ require_not_st_var<Mat>* =nullptr >
75
+ inline plain_type_t <Mat>sum_to_zero_constrain (const Mat& x) {
76
+ const auto N = x.rows ();
77
+ const auto M = x.cols ();
78
+
79
+ plain_type_t <Mat> Z =Eigen::MatrixXd::Zero (N +1 , M +1 );
80
+ if (unlikely (N ==0 || M ==0 )) {
81
+ return Z;
82
+ }
83
+ auto && x_ref =to_ref (x);
84
+
85
+ Eigen::Matrix<value_type_t <Mat>, -1 ,1 > beta =Eigen::VectorXd::Zero (N);
86
+
87
+ for (int j = M -1 ; j >=0 ; --j) {
88
+ value_type_t <Mat>ax_previous (0 );
89
+
90
+ double a_j =inv_sqrt ((j +1.0 ) * (j +2.0 ));
91
+ double b_j = (j +1.0 ) * a_j;
92
+
93
+ for (int i = N -1 ; i >=0 ; --i) {
94
+ double a_i =inv_sqrt ((i +1.0 ) * (i +2.0 ));
95
+ double b_i = (i +1.0 ) * a_i;
96
+
97
+ auto b_i_x = b_i * x_ref.coeff (i, j) - ax_previous;
98
+
99
+ Z.coeffRef (i, j) = (b_j * b_i_x) - beta.coeff (i);
100
+ beta.coeffRef (i) += a_j * b_i_x;
101
+
102
+ Z.coeffRef (N, j) -= Z.coeff (i, j);
103
+ Z.coeffRef (i, M) -= Z.coeff (i, j);
104
+
105
+ ax_previous += a_i * x_ref.coeff (i, j);
106
+ }
107
+ Z.coeffRef (N, M) -= Z.coeff (N, j);
108
+ }
109
+
110
+ return Z;
111
+ }
112
+
113
+ /* *
114
+ * Return a vector or matrix with sum zero corresponding to the specified
115
+ * free input.
80
116
*
81
117
* This is a linear transform, with no Jacobian.
82
118
*
83
- * @tparamVec type of the vector
119
+ * @tparamT type of theinput, either a vector or a matrix
84
120
* @tparam Lp unused
85
- * @param y Free vectorinput of dimensionality K - 1.
121
+ * @param y Free vectoror matrix
86
122
* @param lp unused
87
- * @return Zero-sum vectorof dimensionality K.
123
+ * @return Zero-sum vectoror matrix which is one larger in each dimension
88
124
*/
89
- template <typename Vec,typename Lp,require_eigen_col_vector_t <Vec>* =nullptr ,
90
- require_not_st_var<Vec>* =nullptr >
91
- inline plain_type_t <Vec>sum_to_zero_constrain (const Vec& y, Lp& lp) {
125
+ template <typename T,typename Lp, require_not_st_var<T>* =nullptr >
126
+ inline plain_type_t <T>sum_to_zero_constrain (const T& y, Lp& lp) {
92
127
return sum_to_zero_constrain (y);
93
128
}
94
129
95
130
/* *
96
- * Return a vector with sum zero corresponding to the specified
97
- * freevector .
131
+ * Return a vectoror matrix with sum zero corresponding to the specified
132
+ * freeinput .
98
133
* This overload handles looping over the elements of a standard vector.
99
134
*
100
- * @tparam Vec A standard vector with inner type inheriting from
101
- * `Eigen::DenseBase` or a `var_value` with inner type inheriting from
102
- * `Eigen::DenseBase` with compile time dynamic rows and 1 column
103
- * @param[in] y free vector
104
- * @return Zero-sum vectors of dimensionality one greater than `y`
135
+ * @tparam T A standard vector with inner type that is either a vector or a
136
+ * matrix
137
+ * @param[in] y free vector or matrix
138
+ * @return Zero-sum vectors or matrices which are one larger in each dimension
105
139
*/
106
140
template <typename T,require_std_vector_t <T>* =nullptr >
107
141
inline auto sum_to_zero_constrain (const T& y) {
@@ -114,13 +148,12 @@ inline auto sum_to_zero_constrain(const T& y) {
114
148
* free vector.
115
149
* This overload handles looping over the elements of a standard vector.
116
150
*
117
- * @tparam Vec A standard vector with inner type inheriting from
118
- * `Eigen::DenseBase` or a `var_value` with inner type inheriting from
119
- * `Eigen::DenseBase` with compile time dynamic rows and 1 column
151
+ * @tparam T A standard vector with inner type that is either a vector or a
152
+ * matrix
120
153
* @tparam Lp unused
121
- * @param[in] y free vector
154
+ * @param[in] y free vector or matrix
122
155
* @param[in, out] lp unused
123
- * @return Zero-sum vectorsof dimensionality onegreater than `y`
156
+ * @return Zero-sum vectorsor matrices which are onelarger in each dimension
124
157
*/
125
158
template <typename T,typename Lp,require_std_vector_t <T>* =nullptr ,
126
159
require_convertible_t <return_type_t <T>, Lp>* =nullptr >
@@ -130,36 +163,19 @@ inline auto sum_to_zero_constrain(const T& y, Lp& lp) {
130
163
}
131
164
132
165
/* *
133
- * Return a vector with sum zero corresponding to the specified
134
- * free vector.
135
- *
136
- * The sum-to-zero transform is defined using a modified version of
137
- * the inverse of the isometric log ratio transform (ILR).
138
- * See:
139
- * Egozcue, Juan Jose; Pawlowsky-Glahn, Vera; Mateu-Figueras, Gloria;
140
- * Barcelo-Vidal, Carles (2003), "Isometric logratio transformations for
141
- * compositional data analysis", Mathematical Geology, 35 (3): 279–300,
142
- * doi:10.1023/A:1023818214614, S2CID 122844634
143
- *
144
- * This implementation is closer to the description of the same using "pivot
145
- * coordinates" in
146
- * Filzmoser, P., Hron, K., Templ, M. (2018). Geometrical Properties of
147
- * Compositional Data. In: Applied Compositional Data Analysis. Springer Series
148
- * in Statistics. Springer, Cham. https://doi.org/10.1007/978-3-319-96422-5_3
149
- *
166
+ * Return a vector or matrix with sum zero corresponding to the specified
167
+ * free input.
150
168
* This is a linear transform, with no Jacobian.
151
169
*
152
170
* @tparam Jacobian unused
153
- * @tparam Vec A type inheriting from `Eigen::DenseBase` or a `var_value` with
154
- * inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows
155
- * and 1 column, or a standard vector thereof
171
+ * @tparam T type of the input
156
172
* @tparam Lp unused
157
- * @param[in] y free vector
173
+ * @param[in] y free vector or matrix
158
174
* @param[in, out] lp unused
159
- * @return Zero-sum vectorof dimensionality onegreater than `y`
175
+ * @return Zero-sum vectoror matrix which is onelarger in each dimension
160
176
*/
161
- template <bool Jacobian,typename Vec ,typename Lp>
162
- inline plain_type_t <Vec >sum_to_zero_constrain (const Vec & y, Lp& lp) {
177
+ template <bool Jacobian,typename T ,typename Lp>
178
+ inline plain_type_t <T >sum_to_zero_constrain (const T & y, Lp& lp) {
163
179
return sum_to_zero_constrain (y);
164
180
}
165
181