46#include "match_string.h"
61char *commandline_option[N_OPTIONS] = {
71 "sddsmatrixmult [OPTIONS] [<file1>] <file2>\n"
72 " [-pipe=[input][,output]]\n"
73 " [-majorOrder=row|column]\n"
79 " -pipe=[input][,output] Read input from and/or write output to a pipe.\n"
80 " -majorOrder=row|column Specify output in row or column major order.\n"
81 " -commute Use file1 as the right-hand matrix and file2 as the left-hand matrix.\n"
82 " -reuse Reuse the last data page if a file runs out of data pages.\n"
83 " -verbose Write diagnostic messages to stderr.\n"
84 " -ascii Output the file in ASCII mode.\n\n"
86 " Multiplies matrices from SDDS files file1 and file2.\n"
87 " - file1: SDDS file for the left-hand matrix of the product.\n"
88 " - file2: SDDS file for the right-hand matrix of the product.\n"
89 " - output: SDDS file for the resulting product matrix.\n\n"
91 " L. Emery ANL (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
93int main(
int argc,
char **argv) {
97 char *inputfile1, *inputfile2, *outputfile;
98 char **Input1Column, **Input1DoubleColumn;
99 char **Input2Column, **Input2DoubleColumn;
100 char **OutputDoubleColumn;
101 long Input1Rows, Input1DoubleColumns;
102 long Input2Rows, Input2DoubleColumns;
104 int32_t Input1Columns, Input2Columns, OutputDoubleColumns;
106 long i, i_arg, col, commute;
107#define BUFFER_SIZE_INCREMENT 20
108 MATRIX *R1, *R1Trans, *R2, *R2Trans, *R3, *R3Trans;
110 long ipage, ipage1, ipage2, lastPage1, lastPage2, ascii;
111 unsigned long pipeFlags, majorOrderFlag;
112 long tmpfile_used, noWarnings;
114 short columnMajorOrder = -1;
117 argc =
scanargs(&s_arg, argc, argv);
121 inputfile1 = inputfile2 = outputfile = NULL;
122 Input1DoubleColumn = Input2DoubleColumn = OutputDoubleColumn = NULL;
123 Input1Rows = Input1DoubleColumns = Input2Rows = Input2DoubleColumns = OutputRows = lastPage1 = lastPage2 = 0;
128 reuse = commute = ascii = 0;
130 for (i_arg = 1; i_arg < argc; i_arg++) {
131 if (s_arg[i_arg].arg_type == OPTION) {
132 switch (
match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
133 case CLO_MAJOR_ORDER:
135 s_arg[i_arg].n_items--;
136 if (s_arg[i_arg].n_items > 0 &&
137 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
138 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
139 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
140 SDDS_Bomb(
"Invalid -majorOrder syntax/values");
142 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
143 columnMajorOrder = 1;
144 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
145 columnMajorOrder = 0;
148 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
164 bomb(
"Unrecognized option given", USAGE);
168 inputfile1 = s_arg[i_arg].list[0];
169 else if (!inputfile2)
170 inputfile2 = s_arg[i_arg].list[0];
171 else if (!outputfile)
172 outputfile = s_arg[i_arg].list[0];
174 bomb(
"Too many filenames given", USAGE);
178 if (pipeFlags & USE_STDIN && inputfile1) {
180 SDDS_Bomb(
"Too many filenames (sddsxref)");
181 outputfile = inputfile2;
182 inputfile2 = inputfile1;
186 processFilenames(
"sddsmatrixmult", &inputfile1, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
188 SDDS_Bomb(
"Second input file not specified");
191 char *ptr = inputfile1;
192 inputfile1 = inputfile2;
207 if (!
SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1,
"Matrix product",
"Matrix product", outputfile))
210 if (columnMajorOrder != -1)
211 outputPage.layout.data_mode.column_major = columnMajorOrder;
213 outputPage.layout.data_mode.column_major = input1Page.layout.data_mode.column_major;
216 while ((ipage1 = SDDS_ReadTable(&input1Page)) && (ipage2 = SDDS_ReadTable(&input2Page))) {
217 if ((reuse && (ipage1 < 0 && ipage2 < 0)) ||
218 (!reuse && (ipage1 < 0 || ipage2 < 0)))
221 ipage = MAX(ipage1, ipage2);
225 Input1DoubleColumns = 0;
226 Input1DoubleColumn = (
char **)malloc(Input1Columns *
sizeof(
char *));
228 for (i = 0; i < Input1Columns; i++) {
230 Input1DoubleColumn[Input1DoubleColumns] = Input1Column[i];
231 Input1DoubleColumns++;
234 if (!Input1DoubleColumns) {
236 fprintf(stderr,
"No numerical columns in page %ld of file %s.\n", ipage, inputfile1 ? inputfile1 :
"stdin");
240 if (Input1DoubleColumns && Input1Rows)
241 m_alloc(&R1, Input1DoubleColumns, Input1Rows);
242 else if (!Input1Rows) {
244 fprintf(stderr,
"No rows in page %ld of file %s.\n", ipage, inputfile1 ? inputfile1 :
"stdin");
250 fprintf(stderr,
"Number of rows in page %ld of file %s changed.\n", ipage, inputfile1 ? inputfile1 :
"stdin");
251 for (col = 0; col < Input1DoubleColumns; col++) {
257 fprintf(stderr,
"Using page %ld of file %s.\n", lastPage1, inputfile1 ? inputfile1 :
"stdin");
258 }
else if (ipage1 < 0) {
260 fprintf(stderr,
"Reusing page %ld of file %s.\n", lastPage1, inputfile1 ? inputfile1 :
"stdin");
263 if (verbose && Input1DoubleColumns && Input1Rows) {
264 m_alloc(&R1Trans, Input1Rows, Input1DoubleColumns);
265 m_trans(R1Trans, R1);
266 m_show(R1Trans,
"%9.6le ",
"Input matrix 1:\n", stderr);
272 Input2DoubleColumns = 0;
273 Input2DoubleColumn = (
char **)malloc(Input2Columns *
sizeof(
char *));
275 for (i = 0; i < Input2Columns; i++) {
277 Input2DoubleColumn[Input2DoubleColumns] = Input2Column[i];
278 Input2DoubleColumns++;
281 if (!Input2DoubleColumns) {
283 fprintf(stderr,
"No numerical columns in page %ld of file %s.\n", ipage, inputfile2);
287 if (Input2DoubleColumns && Input2Rows)
288 m_alloc(&R2, Input2DoubleColumns, Input2Rows);
289 else if (!Input2Rows) {
291 fprintf(stderr,
"No rows in page %ld of file %s.\n", ipage, inputfile2);
297 fprintf(stderr,
"Number of rows in page %ld of file %s changed.\n", ipage, inputfile2);
298 for (col = 0; col < Input2DoubleColumns; col++) {
304 fprintf(stderr,
"Using page %ld of file %s.\n", lastPage2, inputfile2 ? inputfile2 :
"stdin");
305 }
else if (ipage2 < 0) {
307 fprintf(stderr,
"Reusing page %ld of file %s.\n", lastPage2, inputfile2 ? inputfile2 :
"stdin");
310 if (verbose && Input2DoubleColumns && Input2Rows) {
311 m_alloc(&R2Trans, Input2Rows, Input2DoubleColumns);
312 m_trans(R2Trans, R2);
313 m_show(R2Trans,
"%9.6le ",
"Input matrix 2:\n", stderr);
319 OutputRows = Input1Rows;
320 OutputDoubleColumns = Input2DoubleColumns;
321 if (Input1DoubleColumns != Input2Rows) {
322 fprintf(stderr,
"Error: Dimension mismatch in files.\n");
323 fprintf(stderr,
"Right-hand matrix (%s) is %ldx%ld.\n",
324 inputfile2 ? inputfile2 :
"stdin", Input2Rows, Input2DoubleColumns);
325 fprintf(stderr,
"Left-hand matrix (%s) is %ldx%ld.\n",
326 inputfile1 ? inputfile1 :
"stdin", Input1Rows, Input1DoubleColumns);
332 if (OutputRows && OutputDoubleColumns) {
334 m_alloc(&R3, OutputDoubleColumns, OutputRows);
336 fprintf(stderr,
"Multiplying %d x %d matrix by %d x %d matrix\n", R2->m, R2->n, R1->m, R1->n);
339 m_alloc(&R3Trans, OutputRows, OutputDoubleColumns);
340 m_trans(R3Trans, R3);
341 m_show(R3Trans,
"%9.6le ",
"Output matrix:\n", stderr);
346 fprintf(stderr,
"Output file will either have no columns or no rows in page %ld.\n", ipage);
350 for (i = 0; i < Input2DoubleColumns; i++) {
359 if (!SDDS_StartTable(&outputPage, OutputRows))
363 if (OutputRows && OutputDoubleColumns) {
364 for (i = 0; i < OutputDoubleColumns; i++) {
366 R3->a[i], OutputRows, OutputDoubleColumn[i]))
371 if (!SDDS_WriteTable(&outputPage))
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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.
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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
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.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
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.