SDDSlib
Loading...
Searching...
No Matches
sddsmatrixmult.c File Reference

Multiplies two matrices from SDDS files and outputs the result. More...

#include "mdb.h"
#include "scan.h"
#include "match_string.h"
#include "matlib.h"
#include "SDDS.h"

Go to the source code of this file.

Macros

#define BUFFER_SIZE_INCREMENT   20
 

Enumerations

enum  option_type {
  CLO_PIPE , CLO_VERBOSE , CLO_ASCII , CLO_REUSE ,
  CLO_COMMUTE , CLO_MAJOR_ORDER , N_OPTIONS
}
 

Functions

int main (int argc, char **argv)
 

Variables

char * commandline_option [N_OPTIONS]
 
static char * USAGE
 

Detailed Description

Multiplies two matrices from SDDS files and outputs the result.

This program reads two SDDS files containing matrix data, performs matrix multiplication, and writes the resulting product matrix to an output SDDS file. The program supports options such as data reuse, commutation of matrices, ASCII output mode, and diagnostic verbosity.

Features

  • Matrix multiplication of numerical columns in SDDS files.
  • Reuse last data page if a file runs out of pages.
  • Option to commute input matrices.
  • Supports both ASCII and binary SDDS formats.
  • Diagnostic verbosity for debugging and matrix visualization.

Usage

sddsmatrixmult [OPTIONS] [<file1>] <file2> [<output>]
  • file1: SDDS file containing the left-hand matrix (unless commuted).
  • file2: SDDS file containing the right-hand matrix.
  • output: SDDS file for the resulting matrix product.

Command-line Options

Option Description
-pipe=[input][,output] Use input and/or output pipes.

| -majorOrder=row|column | Specify output in row-major or column-major order. | | -commute | Swap file1 and file2 to reverse the order of multiplication. | | -reuse | Reuse last data page if a file runs out of pages. | | -ascii | Output file in ASCII mode. | | -verbose | Enable detailed output for diagnostics. |

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, L. Emery, R. Soliday, H. Shang

Definition in file sddsmatrixmult.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 53 of file sddsmatrixmult.c.

53 {
54 CLO_PIPE,
55 CLO_VERBOSE,
56 CLO_ASCII,
57 CLO_REUSE,
58 CLO_COMMUTE,
59 CLO_MAJOR_ORDER,
60 N_OPTIONS
61};

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 89 of file sddsmatrixmult.c.

89 {
90 SCANNED_ARG *s_arg;
91 SDDS_TABLE input1Page, input2Page, outputPage;
92
93 char *inputfile1, *inputfile2, *outputfile;
94 char **Input1Column, **Input1DoubleColumn;
95 char **Input2Column, **Input2DoubleColumn;
96 char **OutputDoubleColumn;
97 long Input1Rows, Input1DoubleColumns;
98 long Input2Rows, Input2DoubleColumns;
99 long OutputRows;
100 int32_t Input1Columns, Input2Columns, OutputDoubleColumns;
101
102 long i, i_arg, col, commute;
103#define BUFFER_SIZE_INCREMENT 20
104 MATRIX *R1, *R1Trans, *R2, *R2Trans, *R3, *R3Trans;
105 long verbose;
106 long ipage, ipage1, ipage2, lastPage1, lastPage2, ascii;
107 unsigned long pipeFlags, majorOrderFlag;
108 long tmpfile_used, noWarnings;
109 long reuse;
110 short columnMajorOrder = -1;
111
113 argc = scanargs(&s_arg, argc, argv);
114 if (argc == 1)
115 bomb(NULL, USAGE);
116
117 inputfile1 = inputfile2 = outputfile = NULL;
118 Input1DoubleColumn = Input2DoubleColumn = OutputDoubleColumn = NULL;
119 Input1Rows = Input1DoubleColumns = Input2Rows = Input2DoubleColumns = OutputRows = lastPage1 = lastPage2 = 0;
120 tmpfile_used = 0;
121 verbose = 0;
122 pipeFlags = 0;
123 noWarnings = 0;
124 reuse = commute = ascii = 0;
125
126 for (i_arg = 1; i_arg < argc; i_arg++) {
127 if (s_arg[i_arg].arg_type == OPTION) {
128 switch (match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
129 case CLO_MAJOR_ORDER:
130 majorOrderFlag = 0;
131 s_arg[i_arg].n_items--;
132 if (s_arg[i_arg].n_items > 0 &&
133 (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
134 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
135 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
136 SDDS_Bomb("Invalid -majorOrder syntax/values");
137 }
138 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
139 columnMajorOrder = 1;
140 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
141 columnMajorOrder = 0;
142 break;
143 case CLO_PIPE:
144 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
145 SDDS_Bomb("Invalid -pipe syntax");
146 break;
147 case CLO_VERBOSE:
148 verbose = 1;
149 break;
150 case CLO_ASCII:
151 ascii = 1;
152 break;
153 case CLO_REUSE:
154 reuse = 1;
155 break;
156 case CLO_COMMUTE:
157 commute = 1;
158 break;
159 default:
160 bomb("Unrecognized option given", USAGE);
161 }
162 } else {
163 if (!inputfile1)
164 inputfile1 = s_arg[i_arg].list[0];
165 else if (!inputfile2)
166 inputfile2 = s_arg[i_arg].list[0];
167 else if (!outputfile)
168 outputfile = s_arg[i_arg].list[0];
169 else
170 bomb("Too many filenames given", USAGE);
171 }
172 }
173
174 if (pipeFlags & USE_STDIN && inputfile1) {
175 if (outputfile)
176 SDDS_Bomb("Too many filenames (sddsxref)");
177 outputfile = inputfile2;
178 inputfile2 = inputfile1;
179 inputfile1 = NULL;
180 }
181
182 processFilenames("sddsmatrixmult", &inputfile1, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
183 if (!inputfile2)
184 SDDS_Bomb("Second input file not specified");
185
186 if (commute) {
187 char *ptr = inputfile1;
188 inputfile1 = inputfile2;
189 inputfile2 = ptr;
190 }
191
192 /* Initialize input files */
193 if (!SDDS_InitializeInput(&input1Page, inputfile1))
194 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
195
196 Input1Column = (char **)SDDS_GetColumnNames(&input1Page, &Input1Columns);
197
198 if (!SDDS_InitializeInput(&input2Page, inputfile2))
199 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
200
201 Input2Column = (char **)SDDS_GetColumnNames(&input2Page, &Input2Columns);
202
203 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, "Matrix product", "Matrix product", outputfile))
204 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
205
206 if (columnMajorOrder != -1)
207 outputPage.layout.data_mode.column_major = columnMajorOrder;
208 else
209 outputPage.layout.data_mode.column_major = input1Page.layout.data_mode.column_major;
210
211 /* Process data pages */
212 while ((ipage1 = SDDS_ReadTable(&input1Page)) && (ipage2 = SDDS_ReadTable(&input2Page))) {
213 if ((reuse && (ipage1 < 0 && ipage2 < 0)) ||
214 (!reuse && (ipage1 < 0 || ipage2 < 0)))
215 break;
216
217 ipage = MAX(ipage1, ipage2);
218
219 /* Process first input file */
220 if (ipage1 == 1) {
221 Input1DoubleColumns = 0;
222 Input1DoubleColumn = (char **)malloc(Input1Columns * sizeof(char *));
223 /* Count the numerical columns in input1 */
224 for (i = 0; i < Input1Columns; i++) {
225 if (SDDS_NUMERIC_TYPE(SDDS_GetColumnType(&input1Page, i))) {
226 Input1DoubleColumn[Input1DoubleColumns] = Input1Column[i];
227 Input1DoubleColumns++;
228 }
229 }
230 if (!Input1DoubleColumns) {
231 if (verbose) {
232 fprintf(stderr, "No numerical columns in page %ld of file %s.\n", ipage, inputfile1 ? inputfile1 : "stdin");
233 }
234 }
235 Input1Rows = SDDS_CountRowsOfInterest(&input1Page);
236 if (Input1DoubleColumns && Input1Rows)
237 m_alloc(&R1, Input1DoubleColumns, Input1Rows);
238 else if (!Input1Rows) {
239 if (verbose)
240 fprintf(stderr, "No rows in page %ld of file %s.\n", ipage, inputfile1 ? inputfile1 : "stdin");
241 }
242 }
243
244 if (ipage1 > 0) {
245 if (Input1Rows != SDDS_CountRowsOfInterest(&input1Page))
246 fprintf(stderr, "Number of rows in page %ld of file %s changed.\n", ipage, inputfile1 ? inputfile1 : "stdin");
247 for (col = 0; col < Input1DoubleColumns; col++) {
248 if (!(R1->a[col] = (double *)SDDS_GetColumnInDoubles(&input1Page, Input1DoubleColumn[col])))
249 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
250 }
251 lastPage1 = ipage1;
252 if (verbose)
253 fprintf(stderr, "Using page %ld of file %s.\n", lastPage1, inputfile1 ? inputfile1 : "stdin");
254 } else if (ipage1 < 0) {
255 if (verbose)
256 fprintf(stderr, "Reusing page %ld of file %s.\n", lastPage1, inputfile1 ? inputfile1 : "stdin");
257 }
258
259 if (verbose && Input1DoubleColumns && Input1Rows) {
260 m_alloc(&R1Trans, Input1Rows, Input1DoubleColumns);
261 m_trans(R1Trans, R1);
262 m_show(R1Trans, "%9.6le ", "Input matrix 1:\n", stderr);
263 m_free(&R1Trans);
264 }
265
266 /* Process second input file */
267 if (ipage2 == 1) {
268 Input2DoubleColumns = 0;
269 Input2DoubleColumn = (char **)malloc(Input2Columns * sizeof(char *));
270 /* Count the numerical columns in input2 */
271 for (i = 0; i < Input2Columns; i++) {
272 if (SDDS_NUMERIC_TYPE(SDDS_GetColumnType(&input2Page, i))) {
273 Input2DoubleColumn[Input2DoubleColumns] = Input2Column[i];
274 Input2DoubleColumns++;
275 }
276 }
277 if (!Input2DoubleColumns) {
278 if (verbose) {
279 fprintf(stderr, "No numerical columns in page %ld of file %s.\n", ipage, inputfile2);
280 }
281 }
282 Input2Rows = SDDS_CountRowsOfInterest(&input2Page);
283 if (Input2DoubleColumns && Input2Rows)
284 m_alloc(&R2, Input2DoubleColumns, Input2Rows);
285 else if (!Input2Rows) {
286 if (verbose)
287 fprintf(stderr, "No rows in page %ld of file %s.\n", ipage, inputfile2);
288 }
289 }
290
291 if (ipage2 > 0) {
292 if (Input2Rows != SDDS_CountRowsOfInterest(&input2Page))
293 fprintf(stderr, "Number of rows in page %ld of file %s changed.\n", ipage, inputfile2);
294 for (col = 0; col < Input2DoubleColumns; col++) {
295 if (!(R2->a[col] = (double *)SDDS_GetColumnInDoubles(&input2Page, Input2DoubleColumn[col])))
296 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
297 }
298 lastPage2 = ipage2;
299 if (verbose)
300 fprintf(stderr, "Using page %ld of file %s.\n", lastPage2, inputfile2 ? inputfile2 : "stdin");
301 } else if (ipage2 < 0) {
302 if (verbose)
303 fprintf(stderr, "Reusing page %ld of file %s.\n", lastPage2, inputfile2 ? inputfile2 : "stdin");
304 }
305
306 if (verbose && Input2DoubleColumns && Input2Rows) {
307 m_alloc(&R2Trans, Input2Rows, Input2DoubleColumns);
308 m_trans(R2Trans, R2);
309 m_show(R2Trans, "%9.6le ", "Input matrix 2:\n", stderr);
310 m_free(&R2Trans);
311 }
312
313 /* Define output table */
314 if (ipage == 1) {
315 OutputRows = Input1Rows;
316 OutputDoubleColumns = Input2DoubleColumns;
317 if (Input1DoubleColumns != Input2Rows) {
318 fprintf(stderr, "Error: Dimension mismatch in files.\n");
319 fprintf(stderr, "Right-hand matrix (%s) is %ldx%ld.\n",
320 inputfile2 ? inputfile2 : "stdin", Input2Rows, Input2DoubleColumns);
321 fprintf(stderr, "Left-hand matrix (%s) is %ldx%ld.\n",
322 inputfile1 ? inputfile1 : "stdin", Input1Rows, Input1DoubleColumns);
323 exit(EXIT_FAILURE);
324 }
325 }
326
327 /* Perform matrix multiplication */
328 if (OutputRows && OutputDoubleColumns) {
329 if (ipage == 1)
330 m_alloc(&R3, OutputDoubleColumns, OutputRows);
331 if (verbose)
332 fprintf(stderr, "Multiplying %d x %d matrix by %d x %d matrix\n", R2->m, R2->n, R1->m, R1->n);
333 m_mult(R3, R2, R1);
334 if (verbose) {
335 m_alloc(&R3Trans, OutputRows, OutputDoubleColumns);
336 m_trans(R3Trans, R3);
337 m_show(R3Trans, "%9.6le ", "Output matrix:\n", stderr);
338 m_free(&R3Trans);
339 }
340 } else {
341 if (verbose)
342 fprintf(stderr, "Output file will either have no columns or no rows in page %ld.\n", ipage);
343 }
344
345 if (ipage == 1) {
346 for (i = 0; i < Input2DoubleColumns; i++) {
347 if (SDDS_TransferColumnDefinition(&outputPage, &input2Page, Input2DoubleColumn[i], NULL) < 0)
348 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
349 }
350 OutputDoubleColumn = (char **)SDDS_GetColumnNames(&outputPage, &OutputDoubleColumns);
351 if (!SDDS_WriteLayout(&outputPage))
352 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
353 }
354
355 if (!SDDS_StartTable(&outputPage, OutputRows))
356 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
357
358 /* Assign values to output table */
359 if (OutputRows && OutputDoubleColumns) {
360 for (i = 0; i < OutputDoubleColumns; i++) { /* i is the column index */
361 if (!SDDS_SetColumnFromDoubles(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE,
362 R3->a[i], OutputRows, OutputDoubleColumn[i]))
363 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
364 }
365 }
366
367 if (!SDDS_WriteTable(&outputPage))
368 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
369 }
370
371 /* Terminate SDDS tables */
372 if (!SDDS_Terminate(&input1Page) || !SDDS_Terminate(&input2Page) || !SDDS_Terminate(&outputPage))
373 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
374
375 if (tmpfile_used && !replaceFileAndBackUp(inputfile1, outputfile))
376 return EXIT_FAILURE;
377
378 return EXIT_SUCCESS;
379}
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:75
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.

Variable Documentation

◆ commandline_option

char* commandline_option[N_OPTIONS]
Initial value:
= {
"pipe",
"verbose",
"ascii",
"reuse",
"commute",
"majorOrder",
}

Definition at line 63 of file sddsmatrixmult.c.

63 {
64 "pipe",
65 "verbose",
66 "ascii",
67 "reuse",
68 "commute",
69 "majorOrder",
70};

◆ USAGE

char* USAGE
static
Initial value:
=
"Usage: sddsmatrixmult [OPTIONS] [<file1>] <file2> [<output>]\n\n"
"Options:\n"
" -pipe=[input][,output] Read input from and/or write output to a pipe.\n"
" -majorOrder=row|column Specify output in row or column major order.\n"
" -commute Use file1 as the right-hand matrix and file2 as the left-hand matrix.\n"
" -reuse Reuse the last data page if a file runs out of data pages.\n"
" -verbose Write diagnostic messages to stderr.\n"
" -ascii Output the file in ASCII mode.\n\n"
"Description:\n"
" Multiplies matrices from SDDS files file1 and file2.\n"
" - file1: SDDS file for the left-hand matrix of the product.\n"
" - file2: SDDS file for the right-hand matrix of the product.\n"
" - output: SDDS file for the resulting product matrix.\n\n"
"Author:\n"
" L. Emery ANL (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"

Definition at line 72 of file sddsmatrixmult.c.