1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
//
// GENERATED FILE
//
use super::*;
use crate::SpiceContext;
use f2rust_std::*;
/// Transpose a matrix, general
///
/// Transpose a matrix of arbitrary size (the matrix
/// need not be square).
///
/// # Brief I/O
///
/// ```text
/// VARIABLE I/O DESCRIPTION
/// -------- --- --------------------------------------------------
/// MATRIX I Matrix to be transposed.
/// NROW I Number of rows of input matrix MATRIX.
/// NCOL I Number of columns of input matrix MATRIX.
/// XPOSEM O Transposed matrix.
/// ```
///
/// # Detailed Input
///
/// ```text
/// MATRIX is a matrix to be transposed.
///
/// NROW is the number of rows of input matrix MATRIX.
///
/// NCOL is the number of columns of input matrix MATRIX.
/// ```
///
/// # Detailed Output
///
/// ```text
/// XPOSEM is the transposed matrix.
/// ```
///
/// # Exceptions
///
/// ```text
/// Error free.
///
/// 1) If either NROW or NCOL is less than or equal to zero, no
/// action is taken. The routine simply returns.
/// ```
///
/// # Particulars
///
/// ```text
/// This routine transposes the input matrix MATRIX and writes the
/// result to the matrix XPOSEM. This algorithm is performed in
/// such a way that the transpose can be performed in place. That
/// is, MATRIX and XPOSEM can use the same storage area in memory.
///
/// NOTE: The matrices MATRIX and XPOSEM are declared
/// one-dimensional for computational purposes only. The
/// calling program should declare them as MATRIX(NROW,NCOL)
/// and XPOSEM(NCOL,NROW).
///
/// This routine works on the assumption that the input and
/// output matrices are defined as described above. More
/// specifically it assures that the elements of the matrix
/// to be transformed are stored in contiguous memory locations
/// as shown here. On output these elements will be
/// rearranged in consecutive memory locations as shown.
///
/// MATRIX XPOSEM
///
/// m_11 m_11
/// m_21 m_12
/// m_31 m_13
/// . .
/// . .
/// . m_1ncol
/// m_nrow1 m_21
/// m_12 m_22
/// m_22 m_23
/// m_32 .
/// . .
/// . m_2ncol
/// . .
/// m_nrow2
/// . .
///
/// . .
///
/// . .
/// m_1ncol
/// m_2ncol m_nrow1
/// m_3ncol m_nrow2
/// . m_nrow3
/// . .
/// . .
/// m_nrowncol m_nrowncol
///
///
/// For those familiar with permutations, this algorithm relies
/// upon the fact that the transposition of a matrix, which has
/// been stored as a string, is simply the action of a
/// permutation applied to that string. Since any permutation
/// can be decomposed as a product of disjoint cycles, it is
/// possible to transpose the matrix with only one additional
/// storage register. However, once a cycle has been computed
/// it is necessary to find the next entry in the string that
/// has not been moved by the permutation. For this reason the
/// algorithm is slower than would be necessary if the numbers
/// of rows and columns were known in advance.
/// ```
///
/// # Examples
///
/// ```text
/// This routine is primarily useful when attempting to transpose
/// large matrices, where inplace transposition is important. For
/// example suppose you have the following declarations
///
/// DOUBLE PRECISION MATRIX ( 1003, 800 )
///
/// If the transpose of the matrix is needed, it may not be
/// possible to fit a second matrix requiring the same storage
/// into memory. Instead declare XPOSEM as below and use
/// an equivalence so that the same area of memory is allocated.
///
/// DOUBLE PRECISION XPOSEM ( 800, 1003 )
/// EQUIVALENCE ( MATRIX (1,1), XPOSEM(1,1) )
///
/// To obtain the transpose simply execute
///
/// CALL XPOSEG ( MATRIX, 1003, 800, XPOSEM )
/// ```
///
/// # Author and Institution
///
/// ```text
/// N.J. Bachman (JPL)
/// J. Diaz del Rio (ODC Space)
/// H.A. Neilan (JPL)
/// W.L. Taber (JPL)
/// ```
///
/// # Version
///
/// ```text
/// - SPICELIB Version 1.3.0, 13-AUG-2021 (JDR)
///
/// Edited the header to comply with NAIF standard. Removed
/// unnecessary $Revisions section.
///
/// - SPICELIB Version 1.2.3, 22-APR-2010 (NJB)
///
/// Header correction: assertions that the output
/// can overwrite the input have been removed.
///
/// - SPICELIB Version 1.2.2, 04-MAY-1993 (HAN)
///
/// The example listed arguments in the call to XPOSEG incorrectly.
/// The number of rows was listed as the number of columns, and
/// the number of columns was listed as the number of rows.
///
/// - SPICELIB Version 1.2.1, 10-MAR-1992 (WLT)
///
/// Comment section for permuted index source lines was added
/// following the header.
///
/// - SPICELIB Version 1.2.0, 06-AUG-1990 (WLT)
///
/// The original version of the routine had a bug. It worked
/// in place, but the fixed points (1,1) and (n,m) were not
/// moved so that the routine did not work if input and output
/// matrices were different.
///
/// - SPICELIB Version 1.0.0, 31-JAN-1990 (WLT) (NJB)
/// ```
pub fn xposeg(matrix: &[f64], nrow: i32, ncol: i32, xposem: &mut [f64]) {
XPOSEG(matrix, nrow, ncol, xposem);
}
//$Procedure XPOSEG ( Transpose a matrix, general )
pub fn XPOSEG(MATRIX: &[f64], NROW: i32, NCOL: i32, XPOSEM: &mut [f64]) {
let MATRIX = DummyArray::new(MATRIX, 0..);
let mut XPOSEM = DummyArrayMut::new(XPOSEM, 0..);
let mut TEMP: f64 = 0.0;
let mut SOURCE: f64 = 0.0;
let mut DEST: i32 = 0;
let mut MOVED: i32 = 0;
let mut START: i32 = 0;
let mut K: i32 = 0;
let mut NMOVES: i32 = 0;
let mut R: i32 = 0;
let mut M: i32 = 0;
let mut N: i32 = 0;
//
// Local Variables
//
//
// Take care of dumb cases first.
//
if ((NROW <= 0) || (NCOL <= 0)) {
return;
}
N = NROW;
M = NCOL;
//
// Set up the upper bound for the number of objects to be moved and
// initialize the counters.
//
NMOVES = ((N * M) - 2);
MOVED = 0;
START = 1;
//
// Until MOVED is equal to NMOVES, there is some matrix element that
// has not been moved to its proper location in the transpose matrix.
//
while (MOVED < NMOVES) {
SOURCE = MATRIX[START];
K = (START / N);
R = (START - (N * K));
DEST = ((R * M) + K);
//
// Perform this cycle of the permutation. We will be done when
// the destination of the next element is equal to the starting
// position of the first element to be moved in this cycle.
//
while (DEST != START) {
TEMP = MATRIX[DEST];
XPOSEM[DEST] = SOURCE;
SOURCE = TEMP;
MOVED = (MOVED + 1);
K = (DEST / N);
R = (DEST - (K * N));
DEST = ((M * R) + K);
}
XPOSEM[DEST] = SOURCE;
DEST = 0;
MOVED = (MOVED + 1);
//
// Find the next element of the matrix that has not already been
// moved by the transposition operation.
//
if (MOVED < NMOVES) {
while (DEST != START) {
START = (START + 1);
K = (START / N);
R = (START - (K * N));
DEST = ((R * M) + K);
while (DEST > START) {
K = (DEST / N);
R = (DEST - (K * N));
DEST = ((M * R) + K);
}
}
}
}
//
// Just in case this isn't an in-place transpose, move the last
// element of MATRIX to XPOSEM
//
XPOSEM[0] = MATRIX[0];
XPOSEM[((N * M) - 1)] = MATRIX[((N * M) - 1)];
}