/meataxe-2.4.24/src/zad.c

# · C · 269 lines · 129 code · 47 blank · 93 comment · 46 complexity · 17923a48d771eea3be17563437c67861 MD5 · raw file

  1. /* ============================= C MeatAxe ==================================
  2. File: $Id: zad.c,v 1.1.1.1 2007/09/02 11:06:17 mringe Exp $
  3. Comment: Sum of matrices.
  4. --------------------------------------------------------------------------
  5. (C) Copyright 1999 Michael Ringe, Lehrstuhl D fuer Mathematik,
  6. RWTH Aachen, Germany <mringe@math.rwth-aachen.de>
  7. This program is free software; see the file COPYING for details.
  8. ========================================================================== */
  9. #include "meataxe.h"
  10. #include <string.h>
  11. /* ------------------------------------------------------------------
  12. Variables
  13. ------------------------------------------------------------------ */
  14. static MtxApplicationInfo_t AppInfo = {
  15. "zad", "Add or Subtract Matrices",
  16. "SYNTAX\n"
  17. " zad " MTX_COMMON_OPTIONS_SYNTAX " [-]<Mat> [-]<Mat> ... <Result>\n"
  18. "\n"
  19. "ARGUMENTS\n"
  20. " <Mat> ................... Input file: Matrix to add (-<Mat> subtracts)\n"
  21. " <Result> ................ Output file: Sum\n"
  22. "\n"
  23. "OPTIONS\n"
  24. MTX_COMMON_OPTIONS_DESCRIPTION
  25. "\n"
  26. "FILES\n"
  27. " <Mat> ................... I Input matrix\n"
  28. " <Result> ................ O Sum of the input matrices\n"
  29. };
  30. static MtxApplication_t *App = NULL;
  31. MTX_DEFINE_FILE_INFO
  32. #define MAX_INPUT 20
  33. int NInput; /* Number of input matrices */
  34. FILE *Input[MAX_INPUT] = {0}; /* Input matrices */
  35. int Subtract[MAX_INPUT];
  36. int Field = -1, Nor = -1, Noc = -1;
  37. PTR Buf1, Buf2; /* Working buffer */
  38. FILE *Output = NULL; /* Output file */
  39. static int CheckHeader(const char *fn, int fl, int nor, int noc)
  40. {
  41. static const char *fn0 = NULL;
  42. if (fl < 2)
  43. {
  44. MTX_ERROR2("%s: %E",fn,MTX_ERR_NOTMATRIX);
  45. return -1;
  46. }
  47. if (Nor == -1)
  48. {
  49. Nor = nor;
  50. Noc = noc;
  51. Field = fl;
  52. fn0 = fn;
  53. }
  54. else if (fl != Field || nor != Nor || noc != Noc)
  55. {
  56. MTX_ERROR3("%s and %s: %E",fn0,fn,MTX_ERR_INCOMPAT);
  57. return -1;
  58. }
  59. return 0;
  60. }
  61. /* ------------------------------------------------------------------
  62. Init()
  63. ------------------------------------------------------------------ */
  64. static int Init(int argc, const char **argv)
  65. {
  66. int i;
  67. if ((App = AppAlloc(&AppInfo,argc,argv)) == NULL)
  68. return -1;
  69. /* Parse command line.
  70. ------------------- */
  71. if (AppGetArguments(App,3,MAX_INPUT + 1) < 0)
  72. return -1;
  73. NInput = App->ArgC - 1;
  74. /* Open the input files
  75. -------------------- */
  76. for (i = 0; i < NInput; ++i)
  77. {
  78. int nor2, noc2, fl2;
  79. const char *file_name = App->ArgV[i];
  80. Subtract[i] = *file_name == '-';
  81. if (*file_name == '-' || *file_name == '+')
  82. ++file_name;
  83. Input[i] = FfReadHeader(file_name,&fl2,&nor2,&noc2);
  84. if (Input[i] == NULL)
  85. return -1;
  86. if (CheckHeader(file_name,fl2,nor2,noc2) != 0)
  87. return -1;
  88. }
  89. /* Open the output file.
  90. --------------------- */
  91. Output = FfWriteHeader(App->ArgV[App->ArgC - 1],Field,Nor,Noc);
  92. if (Output == NULL)
  93. return -1;
  94. /* Allocate workspace
  95. ------------------ */
  96. FfSetField(Field);
  97. FfSetNoc(Noc);
  98. Buf1 = FfAlloc(1);
  99. Buf2 = FfAlloc(1);
  100. if (Buf1 == NULL || Buf2 == NULL)
  101. return -1;
  102. return 0;
  103. }
  104. /* ------------------------------------------------------------------
  105. CleanUp()
  106. ------------------------------------------------------------------ */
  107. static void CleanUp()
  108. {
  109. int i;
  110. /* Close all files.
  111. ---------------- */
  112. for (i = 0; i < NInput; ++i)
  113. {
  114. if (Input[i] != NULL)
  115. fclose(Input[i]);
  116. }
  117. if (Output != NULL)
  118. fclose(Output);
  119. /* Free workspace.
  120. --------------- */
  121. if (Buf1 != NULL) SysFree(Buf1);
  122. if (Buf2 != NULL) SysFree(Buf2);
  123. if (App != NULL) AppFree(App);
  124. }
  125. static int AddMatrices()
  126. {
  127. int i;
  128. FEL MinusOne = FfNeg(FF_ONE);
  129. /* Process the matrices row by row.
  130. -------------------------------- */
  131. for (i = Nor; i > 0; --i)
  132. {
  133. int k;
  134. /* Read a row from the first matrix.
  135. --------------------------------- */
  136. FfReadRows(Input[0],Buf1,1);
  137. if (Subtract[0])
  138. FfMulRow(Buf1,MinusOne);
  139. /* Add or subtract rows from the other matrices.
  140. --------------------------------------------- */
  141. for (k = 1; k < NInput; ++k)
  142. {
  143. FfReadRows(Input[k],Buf2,1);
  144. if (Subtract[k])
  145. FfAddMulRow(Buf1,Buf2,MinusOne);
  146. else
  147. FfAddRow(Buf1,Buf2);
  148. }
  149. /* Write the result to the output file.
  150. ------------------------------------ */
  151. FfWriteRows(Output,Buf1,1);
  152. }
  153. return 0;
  154. }
  155. int main(int argc, const char **argv)
  156. {
  157. int rc;
  158. if (Init(argc, argv) != 0)
  159. {
  160. MTX_ERROR("Initialization failed");
  161. return 1;
  162. }
  163. rc = AddMatrices();
  164. CleanUp();
  165. return rc;
  166. }
  167. /**
  168. @page prog_zad zad - Add Matrices
  169. @section syntax Command Line
  170. <pre>
  171. zad [@em Options] [-]@em Mat [-]@em Mat ... @em Result
  172. </pre>
  173. @par @em Options
  174. Standard options, see @ref prog_stdopts
  175. @par @em Mat
  176. Input matrix
  177. @par @em Result
  178. Result matrix
  179. @section inp Input Files
  180. @par @em Mat
  181. Input matrix
  182. @section out Output Files
  183. @par @em Result
  184. Result matrix
  185. @section desc Description
  186. This program reads two or more input matrices, calculates their sum or difference and
  187. writes the result to a file. The input matrices must be compatible, i.e., they must be
  188. over the same field and have the same dimensions. @b zad is designed to work with very
  189. large matrices without running out of memory. Only two rows are allocated as working
  190. memory.
  191. By default, all input matrices are added. For example,
  192. <pre>
  193. zad A B C
  194. </pre>
  195. calculates the sum of A and B, and writes the result to C.
  196. If a file name is preceeded by a minus sign, this matrix is subtracted.
  197. For example,
  198. <pre>
  199. zad A -B -C D
  200. </pre>
  201. calculates $D=A-B-C$. To subtract the first matrix, you must insert an
  202. extra "--" before the file names. Otherwise the first argument
  203. would be interpreted as a program option. For example, to calculate $C=-A-B$, use
  204. <pre>
  205. zad -- -A -B C
  206. </pre>
  207. If a file name starts with "-", preceed the file name by "+" to add, or
  208. by "-" to subtract the matrix. If, for example, the second input file
  209. is "-B", use the following syntax:
  210. <pre>
  211. zad A +-B C
  212. zad A --B C
  213. </pre>
  214. */