home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / calc / part14 < prev    next >
Encoding:
Text File  |  1992-05-09  |  30.3 KB  |  1,368 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  3. Subject: v26i040: CALC - An arbitrary precision C-like calculator, Part14/21
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: dbell@pdact.pd.necisa.oz.au (David I. Bell)
  8. Posting-Number: Volume 26, Issue 40
  9. Archive-Name: calc/part14
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 14 (of 21)."
  18. # Contents:  matfunc.c
  19. # Wrapped by dbell@elm on Tue Feb 25 15:21:12 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'matfunc.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'matfunc.c'\"
  23. else
  24. echo shar: Extracting \"'matfunc.c'\" \(28075 characters\)
  25. sed "s/^X//" >'matfunc.c' <<'END_OF_FILE'
  26. X/*
  27. X * Copyright (c) 1992 David I. Bell
  28. X * Permission is granted to use, distribute, or modify this source,
  29. X * provided that this copyright notice remains intact.
  30. X *
  31. X * Extended precision rational arithmetic matrix functions.
  32. X * Matrices can contain arbitrary types of elements.
  33. X */
  34. X
  35. X#include "calc.h"
  36. X
  37. X
  38. X#if 0
  39. Xstatic char *abortmsg = "Calculation aborted";
  40. Xstatic char *memmsg = "Not enough memory";
  41. X#endif
  42. X
  43. X
  44. Xstatic void matswaprow(), matsubrow(), matmulrow();
  45. X#if 0
  46. Xstatic void mataddrow();
  47. X#endif
  48. X
  49. Xstatic MATRIX *matident();
  50. X
  51. X
  52. X
  53. X/*
  54. X * Add two compatible matrices.
  55. X */
  56. XMATRIX *
  57. Xmatadd(m1, m2)
  58. X    MATRIX *m1, *m2;
  59. X{
  60. X    int dim;
  61. X
  62. X    long min1, min2, max1, max2, index;
  63. X    VALUE *v1, *v2, *vres;
  64. X    MATRIX *res;
  65. X    MATRIX tmp;
  66. X
  67. X    if (m1->m_dim != m2->m_dim)
  68. X        error("Incompatible matrix dimensions for add");
  69. X    tmp.m_dim = m1->m_dim;
  70. X    tmp.m_size = m1->m_size;
  71. X    for (dim = 0; dim < m1->m_dim; dim++) {
  72. X        min1 = m1->m_min[dim];
  73. X        max1 = m1->m_max[dim];
  74. X        min2 = m2->m_min[dim];
  75. X        max2 = m2->m_max[dim];
  76. X        if ((min1 && min2 && (min1 != min2)) || ((max1-min1) != (max2-min2)))
  77. X            error("Incompatible matrix bounds for add");
  78. X        tmp.m_min[dim] = (min1 ? min1 : min2);
  79. X        tmp.m_max[dim] = tmp.m_min[dim] + (max1 - min1);
  80. X    }
  81. X    res = matalloc(m1->m_size);
  82. X    *res = tmp;
  83. X    v1 = m1->m_table;
  84. X    v2 = m2->m_table;
  85. X    vres = res->m_table;
  86. X    for (index = m1->m_size; index > 0; index--)
  87. X        addvalue(v1++, v2++, vres++);
  88. X    return res;
  89. X}
  90. X
  91. X
  92. X/*
  93. X * Subtract two compatible matrices.
  94. X */
  95. XMATRIX *
  96. Xmatsub(m1, m2)
  97. X    MATRIX *m1, *m2;
  98. X{
  99. X    int dim;
  100. X    long min1, min2, max1, max2, index;
  101. X    VALUE *v1, *v2, *vres;
  102. X    MATRIX *res;
  103. X    MATRIX tmp;
  104. X
  105. X    if (m1->m_dim != m2->m_dim)
  106. X        error("Incompatible matrix dimensions for sub");
  107. X    tmp.m_dim = m1->m_dim;
  108. X    tmp.m_size = m1->m_size;
  109. X    for (dim = 0; dim < m1->m_dim; dim++) {
  110. X        min1 = m1->m_min[dim];
  111. X        max1 = m1->m_max[dim];
  112. X        min2 = m2->m_min[dim];
  113. X        max2 = m2->m_max[dim];
  114. X        if ((min1 && min2 && (min1 != min2)) || ((max1-min1) != (max2-min2)))
  115. X            error("Incompatible matrix bounds for sub");
  116. X        tmp.m_min[dim] = (min1 ? min1 : min2);
  117. X        tmp.m_max[dim] = tmp.m_min[dim] + (max1 - min1);
  118. X    }
  119. X    res = matalloc(m1->m_size);
  120. X    *res = tmp;
  121. X    v1 = m1->m_table;
  122. X    v2 = m2->m_table;
  123. X    vres = res->m_table;
  124. X    for (index = m1->m_size; index > 0; index--)
  125. X        subvalue(v1++, v2++, vres++);
  126. X    return res;
  127. X}
  128. X
  129. X
  130. X/*
  131. X * Produce the negative of a matrix.
  132. X */
  133. XMATRIX *
  134. Xmatneg(m)
  135. X    MATRIX *m;
  136. X{
  137. X    register VALUE *val, *vres;
  138. X    long index;
  139. X    MATRIX *res;
  140. X
  141. X    res = matalloc(m->m_size);
  142. X    *res = *m;
  143. X    val = m->m_table;
  144. X    vres = res->m_table;
  145. X    for (index = m->m_size; index > 0; index--)
  146. X        negvalue(val++, vres++);
  147. X    return res;
  148. X}
  149. X
  150. X
  151. X/*
  152. X * Multiply two compatible matrices.
  153. X */
  154. XMATRIX *
  155. Xmatmul(m1, m2)
  156. X    MATRIX *m1, *m2;
  157. X{
  158. X    register MATRIX *res;
  159. X    long i1, i2, max1, max2, index, maxindex;
  160. X    VALUE *v1, *v2;
  161. X    VALUE sum, tmp1, tmp2;
  162. X
  163. X    if ((m1->m_dim != 2) || (m2->m_dim != 2))
  164. X        error("Matrix dimension must be two for mul");
  165. X    if ((m1->m_max[1] - m1->m_min[1]) != (m2->m_max[0] - m2->m_min[0]))
  166. X        error("Incompatible bounds for matrix mul");
  167. X    max1 = (m1->m_max[0] - m1->m_min[0] + 1);
  168. X    max2 = (m2->m_max[1] - m2->m_min[1] + 1);
  169. X    maxindex = (m1->m_max[1] - m1->m_min[1] + 1);
  170. X    res = matalloc(max1 * max2);
  171. X    res->m_dim = 2;
  172. X    res->m_min[0] = m1->m_min[0];
  173. X    res->m_max[0] = m1->m_max[0];
  174. X    res->m_min[1] = m2->m_min[1];
  175. X    res->m_max[1] = m2->m_max[1];
  176. X    for (i1 = 0; i1 < max1; i1++) {
  177. X        for (i2 = 0; i2 < max2; i2++) {
  178. X            sum.v_num = qlink(&_qzero_);
  179. X            sum.v_type = V_NUM;
  180. X            v1 = &m1->m_table[i1 * maxindex];
  181. X            v2 = &m2->m_table[i2];
  182. X            for (index = 0; index < maxindex; index++) {
  183. X                mulvalue(v1, v2, &tmp1);
  184. X                addvalue(&sum, &tmp1, &tmp2);
  185. X                freevalue(&tmp1);
  186. X                freevalue(&sum);
  187. X                sum = tmp2;
  188. X                v1++;
  189. X                v2 += max2;
  190. X            }
  191. X            index = (i1 * max2) + i2;
  192. X            res->m_table[index] = sum;
  193. X        }
  194. X    }
  195. X    return res;
  196. X}
  197. X
  198. X
  199. X/*
  200. X * Square a matrix.
  201. X */
  202. XMATRIX *
  203. Xmatsquare(m)
  204. X    MATRIX *m;
  205. X{
  206. X    register MATRIX *res;
  207. X    long i1, i2, max, index;
  208. X    VALUE *v1, *v2;
  209. X    VALUE sum, tmp1, tmp2;
  210. X
  211. X    if (m->m_dim != 2)
  212. X        error("Matrix dimension must be two for square");
  213. X    if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))
  214. X        error("Squaring non-square matrix");
  215. X    max = (m->m_max[0] - m->m_min[0] + 1);
  216. X    res = matalloc(max * max);
  217. X    res->m_dim = 2;
  218. X    res->m_min[0] = m->m_min[0];
  219. X    res->m_max[0] = m->m_max[0];
  220. X    res->m_min[1] = m->m_min[1];
  221. X    res->m_max[1] = m->m_max[1];
  222. X    for (i1 = 0; i1 < max; i1++) {
  223. X        for (i2 = 0; i2 < max; i2++) {
  224. X            sum.v_num = qlink(&_qzero_);
  225. X            sum.v_type = V_NUM;
  226. X            v1 = &m->m_table[i1 * max];
  227. X            v2 = &m->m_table[i2];
  228. X            for (index = 0; index < max; index++) {
  229. X                mulvalue(v1, v2, &tmp1);
  230. X                addvalue(&sum, &tmp1, &tmp2);
  231. X                freevalue(&tmp1);
  232. X                freevalue(&sum);
  233. X                sum = tmp2;
  234. X                v1++;
  235. X                v2 += max;
  236. X            }
  237. X            index = (i1 * max) + i2;
  238. X            res->m_table[index] = sum;
  239. X        }
  240. X    }
  241. X    return res;
  242. X}
  243. X
  244. X
  245. X/*
  246. X * Compute the result of raising a square matrix to an integer power.
  247. X * Negative powers mean the positive power of the inverse.
  248. X * Note: This calculation could someday be improved for large powers
  249. X * by using the characteristic polynomial of the matrix.
  250. X */
  251. XMATRIX *
  252. Xmatpowi(m, q)
  253. X    MATRIX *m;        /* matrix to be raised */
  254. X    NUMBER *q;        /* power to raise it to */
  255. X{
  256. X    MATRIX *res, *tmp;
  257. X    long power;        /* power to raise to */
  258. X    unsigned long bit;    /* current bit value */
  259. X
  260. X    if (m->m_dim != 2)
  261. X        error("Matrix dimension must be two for power");
  262. X    if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))
  263. X        error("Raising non-square matrix to a power");
  264. X    if (qisfrac(q))
  265. X        error("Raising matrix to non-integral power");
  266. X    if (isbig(q->num))
  267. X        error("Raising matrix to very large power");
  268. X    power = (istiny(q->num) ? z1tol(q->num) : z2tol(q->num));
  269. X    if (qisneg(q))
  270. X        power = -power;
  271. X    /*
  272. X     * Handle some low powers specially
  273. X     */
  274. X    if ((power <= 4) && (power >= -2)) {
  275. X        switch ((int) power) {
  276. X            case 0:
  277. X                return matident(m);
  278. X            case 1:
  279. X                return matcopy(m);
  280. X            case -1:
  281. X                return matinv(m);
  282. X            case 2:
  283. X                return matsquare(m);
  284. X            case -2:
  285. X                tmp = matinv(m);
  286. X                res = matsquare(tmp);
  287. X                matfree(tmp);
  288. X                return res;
  289. X            case 3:
  290. X                tmp = matsquare(m);
  291. X                res = matmul(m, tmp);
  292. X                matfree(tmp);
  293. X                return res;
  294. X            case 4:
  295. X                tmp = matsquare(m);
  296. X                res = matsquare(tmp);
  297. X                matfree(tmp);
  298. X                return res;
  299. X        }
  300. X    }
  301. X    if (power < 0) {
  302. X        m = matinv(m);
  303. X        power = -power;
  304. X    }
  305. X    /*
  306. X     * Compute the power by squaring and multiplying.
  307. X     * This uses the left to right method of power raising.
  308. X     */
  309. X    bit = TOPFULL;
  310. X    while ((bit & power) == 0)
  311. X        bit >>= 1L;
  312. X    bit >>= 1L;
  313. X    res = matsquare(m);
  314. X    if (bit & power) {
  315. X        tmp = matmul(res, m);
  316. X        matfree(res);
  317. X        res = tmp;
  318. X    }
  319. X    bit >>= 1L;
  320. X    while (bit) {
  321. X        tmp = matsquare(res);
  322. X        matfree(res);
  323. X        res = tmp;
  324. X        if (bit & power) {
  325. X            tmp = matmul(res, m);
  326. X            matfree(res);
  327. X            res = tmp;
  328. X        }
  329. X        bit >>= 1L;
  330. X    }
  331. X    if (qisneg(q))
  332. X        matfree(m);
  333. X    return res;
  334. X}
  335. X
  336. X
  337. X/*
  338. X * Calculate the cross product of two one dimensional matrices each
  339. X * with three components.
  340. X *    m3 = matcross(m1, m2);
  341. X */
  342. XMATRIX *
  343. Xmatcross(m1, m2)
  344. X    MATRIX *m1, *m2;
  345. X{
  346. X    MATRIX *res;
  347. X    VALUE *v1, *v2, *vr;
  348. X    VALUE tmp1, tmp2;
  349. X
  350. X    if ((m1->m_dim != 1) || (m2->m_dim != 1))
  351. X        error("Matrix not 1d for cross product");
  352. X    if ((m1->m_size != 3) || (m2->m_size != 3))
  353. X        error("Matrix not size 3 for cross product");
  354. X    res = matalloc(3L);
  355. X    res->m_dim = 1;
  356. X    res->m_min[0] = 0;
  357. X    res->m_max[0] = 2;
  358. X    v1 = m1->m_table;
  359. X    v2 = m2->m_table;
  360. X    vr = res->m_table;
  361. X    mulvalue(v1 + 1, v2 + 2, &tmp1);
  362. X    mulvalue(v1 + 2, v2 + 1, &tmp2);
  363. X    subvalue(&tmp1, &tmp2, vr + 0);
  364. X    freevalue(&tmp1);
  365. X    freevalue(&tmp2);
  366. X    mulvalue(v1 + 2, v2 + 0, &tmp1);
  367. X    mulvalue(v1 + 0, v2 + 2, &tmp2);
  368. X    subvalue(&tmp1, &tmp2, vr + 1);
  369. X    freevalue(&tmp1);
  370. X    freevalue(&tmp2);
  371. X    mulvalue(v1 + 0, v2 + 1, &tmp1);
  372. X    mulvalue(v1 + 1, v2 + 0, &tmp2);
  373. X    subvalue(&tmp1, &tmp2, vr + 2);
  374. X    freevalue(&tmp1);
  375. X    freevalue(&tmp2);
  376. X    return res;
  377. X}
  378. X
  379. X
  380. X/*
  381. X * Return the dot product of two matrices.
  382. X *    result = matdot(m1, m2);
  383. X */
  384. XVALUE
  385. Xmatdot(m1, m2)
  386. X    MATRIX *m1, *m2;
  387. X{
  388. X    VALUE *v1, *v2;
  389. X    VALUE result, tmp1, tmp2;
  390. X    long len;
  391. X
  392. X    if ((m1->m_dim != 1) || (m2->m_dim != 1))
  393. X        error("Matrix not 1d for dot product");
  394. X    if (m1->m_size != m2->m_size)
  395. X        error("Incompatible matrix sizes for dot product");
  396. X    v1 = m1->m_table;
  397. X    v2 = m2->m_table;
  398. X    mulvalue(v1, v2, &result);
  399. X    len = m1->m_size;
  400. X    while (--len > 0) {
  401. X        mulvalue(++v1, ++v2, &tmp1);
  402. X        addvalue(&result, &tmp1, &tmp2);
  403. X        freevalue(&tmp1);
  404. X        freevalue(&result);
  405. X        result = tmp2;
  406. X    }
  407. X    return result;
  408. X}
  409. X
  410. X
  411. X/*
  412. X * Scale the elements of a matrix by a specified power of two.
  413. X */
  414. XMATRIX *
  415. Xmatscale(m, n)
  416. X    MATRIX *m;        /* matrix to be scaled */
  417. X    long n;
  418. X{
  419. X    register VALUE *val, *vres;
  420. X    VALUE num;
  421. X    long index;
  422. X    MATRIX *res;        /* resulting matrix */
  423. X
  424. X    if (n == 0)
  425. X        return matcopy(m);
  426. X    num.v_type = V_NUM;
  427. X    num.v_num = itoq(n);
  428. X    res = matalloc(m->m_size);
  429. X    *res = *m;
  430. X    val = m->m_table;
  431. X    vres = res->m_table;
  432. X    for (index = m->m_size; index > 0; index--)
  433. X        scalevalue(val++, &num, vres++);
  434. X    qfree(num.v_num);
  435. X    return res;
  436. X}
  437. X
  438. X
  439. X/*
  440. X * Shift the elements of a matrix by the specified number of bits.
  441. X * Positive shift means leftwards, negative shift rightwards.
  442. X */
  443. XMATRIX *
  444. Xmatshift(m, n)
  445. X    MATRIX *m;        /* matrix to be scaled */
  446. X    long n;
  447. X{
  448. X    register VALUE *val, *vres;
  449. X    VALUE num;
  450. X    long index;
  451. X    MATRIX *res;        /* resulting matrix */
  452. X
  453. X    if (n == 0)
  454. X        return matcopy(m);
  455. X    num.v_type = V_NUM;
  456. X    num.v_num = itoq(n);
  457. X    res = matalloc(m->m_size);
  458. X    *res = *m;
  459. X    val = m->m_table;
  460. X    vres = res->m_table;
  461. X    for (index = m->m_size; index > 0; index--)
  462. X        shiftvalue(val++, &num, FALSE, vres++);
  463. X    qfree(num.v_num);
  464. X    return res;
  465. X}
  466. X
  467. X
  468. X/*
  469. X * Multiply the elements of a matrix by a specified value.
  470. X */
  471. XMATRIX *
  472. Xmatmulval(m, vp)
  473. X    MATRIX *m;        /* matrix to be multiplied */
  474. X    VALUE *vp;        /* value to multiply by */
  475. X{
  476. X    register VALUE *val, *vres;
  477. X    long index;
  478. X    MATRIX *res;
  479. X
  480. X    res = matalloc(m->m_size);
  481. X    *res = *m;
  482. X    val = m->m_table;
  483. X    vres = res->m_table;
  484. X    for (index = m->m_size; index > 0; index--)
  485. X        mulvalue(val++, vp, vres++);
  486. X    return res;
  487. X}
  488. X
  489. X
  490. X/*
  491. X * Divide the elements of a matrix by a specified value, keeping
  492. X * only the integer quotient.
  493. X */
  494. XMATRIX *
  495. Xmatquoval(m, vp)
  496. X    MATRIX *m;        /* matrix to be divided */
  497. X    VALUE *vp;        /* value to divide by */
  498. X{
  499. X    register VALUE *val, *vres;
  500. X    long index;
  501. X    MATRIX *res;
  502. X
  503. X    if ((vp->v_type == V_NUM) && qiszero(vp->v_num))
  504. X        error("Division by zero");
  505. X    res = matalloc(m->m_size);
  506. X    *res = *m;
  507. X    val = m->m_table;
  508. X    vres = res->m_table;
  509. X    for (index = m->m_size; index > 0; index--)
  510. X        quovalue(val++, vp, vres++);
  511. X    return res;
  512. X}
  513. X
  514. X
  515. X/*
  516. X * Divide the elements of a matrix by a specified value, keeping
  517. X * only the remainder of the division.
  518. X */
  519. XMATRIX *
  520. Xmatmodval(m, vp)
  521. X    MATRIX *m;        /* matrix to be divided */
  522. X    VALUE *vp;        /* value to divide by */
  523. X{
  524. X    register VALUE *val, *vres;
  525. X    long index;
  526. X    MATRIX *res;
  527. X
  528. X    if ((vp->v_type == V_NUM) && qiszero(vp->v_num))
  529. X        error("Division by zero");
  530. X    res = matalloc(m->m_size);
  531. X    *res = *m;
  532. X    val = m->m_table;
  533. X    vres = res->m_table;
  534. X    for (index = m->m_size; index > 0; index--)
  535. X        modvalue(val++, vp, vres++);
  536. X    return res;
  537. X}
  538. X
  539. X
  540. X/*
  541. X * Transpose the elements of a two dimensional matrix.
  542. X */
  543. XMATRIX *
  544. Xmattrans(m)
  545. X    MATRIX *m;            /* matrix to be transposed */
  546. X{
  547. X    register VALUE *v1, *v2;    /* current values */
  548. X    long rows, cols;        /* rows and columns in old matrix */
  549. X    long row, col;            /* current row and column */
  550. X    MATRIX *res;
  551. X
  552. X    if (m->m_dim != 2)
  553. X        error("Matrix dimension must be two for transpose");
  554. X    res = matalloc(m->m_size);
  555. X    res->m_dim = 2;
  556. X    res->m_min[0] = m->m_min[1];
  557. X    res->m_max[0] = m->m_max[1];
  558. X    res->m_min[1] = m->m_min[0];
  559. X    res->m_max[1] = m->m_max[0];
  560. X    rows = (m->m_max[0] - m->m_min[0] + 1);
  561. X    cols = (m->m_max[1] - m->m_min[1] + 1);
  562. X    v1 = res->m_table;
  563. X    for (row = 0; row < rows; row++) {
  564. X        v2 = &m->m_table[row];
  565. X        for (col = 0; col < cols; col++) {
  566. X            copyvalue(v2, v1);
  567. X            v1++;
  568. X            v2 += rows;
  569. X        }
  570. X    }
  571. X    return res;
  572. X}
  573. X
  574. X
  575. X/*
  576. X * Produce a matrix with values all of which are conjugated.
  577. X */
  578. XMATRIX *
  579. Xmatconj(m)
  580. X    MATRIX *m;
  581. X{
  582. X    register VALUE *val, *vres;
  583. X    long index;
  584. X    MATRIX *res;
  585. X
  586. X    res = matalloc(m->m_size);
  587. X    *res = *m;
  588. X    val = m->m_table;
  589. X    vres = res->m_table;
  590. X    for (index = m->m_size; index > 0; index--)
  591. X        conjvalue(val++, vres++);
  592. X    return res;
  593. X}
  594. X
  595. X
  596. X/*
  597. X * Produce a matrix with values all of which have been rounded to the
  598. X * specified number of decimal places.
  599. X */
  600. XMATRIX *
  601. Xmatround(m, places)
  602. X    MATRIX *m;
  603. X    long places;
  604. X{
  605. X    register VALUE *val, *vres;
  606. X    VALUE tmp;
  607. X    long index;
  608. X    MATRIX *res;
  609. X
  610. X    if (places < 0)
  611. X        error("Negative number of places for matround");
  612. X    res = matalloc(m->m_size);
  613. X    *res = *m;
  614. X    tmp.v_type = V_INT;
  615. X    tmp.v_int = places;
  616. X    val = m->m_table;
  617. X    vres = res->m_table;
  618. X    for (index = m->m_size; index > 0; index--)
  619. X        roundvalue(val++, &tmp, vres++);
  620. X    return res;
  621. X}
  622. X
  623. X
  624. X/*
  625. X * Produce a matrix with values all of which have been rounded to the
  626. X * specified number of binary places.
  627. X */
  628. XMATRIX *
  629. Xmatbround(m, places)
  630. X    MATRIX *m;
  631. X    long places;
  632. X{
  633. X    register VALUE *val, *vres;
  634. X    VALUE tmp;
  635. X    long index;
  636. X    MATRIX *res;
  637. X
  638. X    if (places < 0)
  639. X        error("Negative number of places for matbround");
  640. X    res = matalloc(m->m_size);
  641. X    *res = *m;
  642. X    tmp.v_type = V_INT;
  643. X    tmp.v_int = places;
  644. X    val = m->m_table;
  645. X    vres = res->m_table;
  646. X    for (index = m->m_size; index > 0; index--)
  647. X        broundvalue(val++, &tmp, vres++);
  648. X    return res;
  649. X}
  650. X
  651. X
  652. X/*
  653. X * Produce a matrix with values all of which have been truncated to integers.
  654. X */
  655. XMATRIX *
  656. Xmatint(m)
  657. X    MATRIX *m;
  658. X{
  659. X    register VALUE *val, *vres;
  660. X    long index;
  661. X    MATRIX *res;
  662. X
  663. X    res = matalloc(m->m_size);
  664. X    *res = *m;
  665. X    val = m->m_table;
  666. X    vres = res->m_table;
  667. X    for (index = m->m_size; index > 0; index--)
  668. X        intvalue(val++, vres++);
  669. X    return res;
  670. X}
  671. X
  672. X
  673. X/*
  674. X * Produce a matrix with values all of which have only the fraction part left.
  675. X */
  676. XMATRIX *
  677. Xmatfrac(m)
  678. X    MATRIX *m;
  679. X{
  680. X    register VALUE *val, *vres;
  681. X    long index;
  682. X    MATRIX *res;
  683. X
  684. X    res = matalloc(m->m_size);
  685. X    *res = *m;
  686. X    val = m->m_table;
  687. X    vres = res->m_table;
  688. X    for (index = m->m_size; index > 0; index--)
  689. X        fracvalue(val++, vres++);
  690. X    return res;
  691. X}
  692. X
  693. X
  694. X/*
  695. X * Search a matrix for the specified value, starting with the specified index.
  696. X * Returns the index of the found value, or -1 if the value was not found.
  697. X */
  698. Xlong
  699. Xmatsearch(m, vp, index)
  700. X    MATRIX *m;
  701. X    VALUE *vp;
  702. X    long index;
  703. X{
  704. X    register VALUE *val;
  705. X
  706. X    if (index < 0)
  707. X        index = 0;
  708. X    val = &m->m_table[index];
  709. X    while (index < m->m_size) {
  710. X        if (!comparevalue(vp, val))
  711. X            return index;
  712. X        index++;
  713. X        val++;
  714. X    }
  715. X    return -1;
  716. X}
  717. X
  718. X
  719. X/*
  720. X * Search a matrix backwards for the specified value, starting with the
  721. X * specified index.  Returns the index of the found value, or -1 if the
  722. X * value was not found.
  723. X */
  724. Xlong
  725. Xmatrsearch(m, vp, index)
  726. X    MATRIX *m;
  727. X    VALUE *vp;
  728. X    long index;
  729. X{
  730. X    register VALUE *val;
  731. X
  732. X    if (index >= m->m_size)
  733. X        index = m->m_size - 1;
  734. X    val = &m->m_table[index];
  735. X    while (index >= 0) {
  736. X        if (!comparevalue(vp, val))
  737. X            return index;
  738. X        index--;
  739. X        val--;
  740. X    }
  741. X    return -1;
  742. X}
  743. X
  744. X
  745. X/*
  746. X * Fill all of the elements of a matrix with one of two specified values.
  747. X * All entries are filled with the first specified value, except that if
  748. X * the matrix is square and the second value pointer is non-NULL, then
  749. X * all diagonal entries are filled with the second value.  This routine
  750. X * affects the supplied matrix directly, and doesn't return a copy.
  751. X */
  752. Xvoid
  753. Xmatfill(m, v1, v2)
  754. X    MATRIX *m;        /* matrix to be filled */
  755. X    VALUE *v1;        /* value to fill most of matrix with */
  756. X    VALUE *v2;        /* value for diagonal entries (or NULL) */
  757. X{
  758. X    register VALUE *val;
  759. X    long row, col;
  760. X    long rows;
  761. X    long index;
  762. X
  763. X    if (v2 && ((m->m_dim != 2) ||
  764. X        ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))))
  765. X            error("Filling diagonals of non-square matrix");
  766. X    val = m->m_table;
  767. X    for (index = m->m_size; index > 0; index--)
  768. X        freevalue(val++);
  769. X    val = m->m_table;
  770. X    if (v2 == NULL) {
  771. X        for (index = m->m_size; index > 0; index--)
  772. X            copyvalue(v1, val++);
  773. X        return;
  774. X    }
  775. X    rows = m->m_max[0] - m->m_min[0] + 1;
  776. X    for (row = 0; row < rows; row++) {
  777. X        for (col = 0; col < rows; col++) {
  778. X            copyvalue(((row != col) ? v1 : v2), val++);
  779. X        }
  780. X    }
  781. X}
  782. X
  783. X
  784. X/*
  785. X * Set a copy of a square matrix to the identity matrix.
  786. X */
  787. Xstatic MATRIX *
  788. Xmatident(m)
  789. X    MATRIX *m;
  790. X{
  791. X    register VALUE *val;    /* current value */
  792. X    long row, col;        /* current row and column */
  793. X    long rows;        /* number of rows */
  794. X    MATRIX *res;        /* resulting matrix */
  795. X
  796. X    if (m->m_dim != 2)
  797. X        error("Matrix dimension must be two for setting to identity");
  798. X    if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))
  799. X        error("Matrix must be square for setting to identity");
  800. X    res = matalloc(m->m_size);
  801. X    *res = *m;
  802. X    val = res->m_table;
  803. X    rows = (res->m_max[0] - res->m_min[0] + 1);
  804. X    for (row = 0; row < rows; row++) {
  805. X        for (col = 0; col < rows; col++) {
  806. X            val->v_type = V_NUM;
  807. X            val->v_num = ((row == col) ? qlink(&_qone_) : qlink(&_qzero_));
  808. X            val++;
  809. X        }
  810. X    }
  811. X    return res;
  812. X}
  813. X
  814. X
  815. X/*
  816. X * Calculate the inverse of a matrix if it exists.
  817. X * This is done by using transformations on the supplied matrix to convert
  818. X * it to the identity matrix, and simultaneously applying the same set of
  819. X * transformations to the identity matrix.
  820. X */
  821. XMATRIX *
  822. Xmatinv(m)
  823. X    MATRIX *m;
  824. X{
  825. X    MATRIX *res;        /* matrix to become the inverse */
  826. X    long rows;        /* number of rows */
  827. X    long cur;        /* current row being worked on */
  828. X    long row, col;        /* temp row and column values */
  829. X    VALUE *val;        /* current value in matrix*/
  830. X    VALUE mulval;        /* value to multiply rows by */
  831. X    VALUE tmpval;        /* temporary value */
  832. X
  833. X    if (m->m_dim != 2)
  834. X        error("Matrix dimension must be two for inverse");
  835. X    if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))
  836. X        error("Inverting non-square matrix");
  837. X    /*
  838. X     * Begin by creating the identity matrix with the same attributes.
  839. X     */
  840. X    res = matalloc(m->m_size);
  841. X    *res = *m;
  842. X    rows = (m->m_max[0] - m->m_min[0] + 1);
  843. X    val = res->m_table;
  844. X    for (row = 0; row < rows; row++) {
  845. X        for (col = 0; col < rows; col++) {
  846. X            if (row == col)
  847. X                val->v_num = qlink(&_qone_);
  848. X            else
  849. X                val->v_num = qlink(&_qzero_);
  850. X            val->v_type = V_NUM;
  851. X            val++;
  852. X        }
  853. X    }
  854. X    /*
  855. X     * Now loop over each row, and eliminate all entries in the
  856. X     * corresponding column by using row operations.  Do the same
  857. X     * operations on the resulting matrix.  Copy the original matrix
  858. X     * so that we don't destroy it.
  859. X     */
  860. X    m = matcopy(m);
  861. X    for (cur = 0; cur < rows; cur++) {
  862. X        /*
  863. X         * Find the first nonzero value in the rest of the column
  864. X         * downwards from [cur,cur].  If there is no such value, then
  865. X         * the matrix is not invertible.  If the first nonzero entry
  866. X         * is not the current row, then swap the two rows to make the
  867. X         * current one nonzero.
  868. X         */
  869. X        row = cur;
  870. X        val = &m->m_table[(row * rows) + row];
  871. X        while (testvalue(val) == 0) {
  872. X            if (++row >= rows) {
  873. X                matfree(m);
  874. X                matfree(res);
  875. X                error("Matrix is not invertible");
  876. X            }
  877. X            val += rows;
  878. X        }
  879. X        invertvalue(val, &mulval);
  880. X        if (row != cur) {
  881. X            matswaprow(m, row, cur);
  882. X            matswaprow(res, row, cur);
  883. X        }
  884. X        /*
  885. X         * Now for every other nonzero entry in the current column, subtract
  886. X         * the appropriate multiple of the current row to force that entry
  887. X         * to become zero.
  888. X         */
  889. X        val = &m->m_table[cur];
  890. X        for (row = 0; row < rows; row++, val += rows) {
  891. X            if ((row == cur) || (testvalue(val) == 0))
  892. X                continue;
  893. X            mulvalue(val, &mulval, &tmpval);
  894. X            matsubrow(m, row, cur, &tmpval);
  895. X            matsubrow(res, row, cur, &tmpval);
  896. X            freevalue(&tmpval);
  897. X        }
  898. X        freevalue(&mulval);
  899. X    }
  900. X    /*
  901. X     * Now the original matrix has nonzero entries only on its main diagonal.
  902. X     * Scale the rows of the result matrix by the inverse of those entries.
  903. X     */
  904. X    val = m->m_table;
  905. X    for (row = 0; row < rows; row++) {
  906. X        if ((val->v_type != V_NUM) || !qisone(val->v_num)) {
  907. X            invertvalue(val, &mulval);
  908. X            matmulrow(res, row, &mulval);
  909. X            freevalue(&mulval);
  910. X        }
  911. X        val += (rows + 1);
  912. X    }
  913. X    matfree(m);
  914. X    return res;
  915. X}
  916. X
  917. X
  918. X/*
  919. X * Calculate the determinant of a square matrix.
  920. X * This is done using row operations to create an upper-diagonal matrix.
  921. X */
  922. XVALUE
  923. Xmatdet(m)
  924. X    MATRIX *m;
  925. X{
  926. X    long rows;        /* number of rows */
  927. X    long cur;        /* current row being worked on */
  928. X    long row;        /* temp row values */
  929. X    int neg;        /* whether to negate determinant */
  930. X    VALUE *val;        /* current value */
  931. X    VALUE mulval, tmpval;    /* other values */
  932. X
  933. X    if (m->m_dim != 2)
  934. X        error("Matrix dimension must be two for determinant");
  935. X    if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))
  936. X        error("Non-square matrix for determinant");
  937. X    /*
  938. X     * Loop over each row, and eliminate all lower entries in the
  939. X     * corresponding column by using row operations.  Copy the original
  940. X     * matrix so that we don't destroy it.
  941. X     */
  942. X    neg = 0;
  943. X    m = matcopy(m);
  944. X    rows = (m->m_max[0] - m->m_min[0] + 1);
  945. X    for (cur = 0; cur < rows; cur++) {
  946. X        /*
  947. X         * Find the first nonzero value in the rest of the column
  948. X         * downwards from [cur,cur].  If there is no such value, then
  949. X         * the determinant is zero.  If the first nonzero entry is not
  950. X         * the current row, then swap the two rows to make the current
  951. X         * one nonzero, and remember that the determinant changes sign.
  952. X         */
  953. X        row = cur;
  954. X        val = &m->m_table[(row * rows) + row];
  955. X        while (testvalue(val) == 0) {
  956. X            if (++row >= rows) {
  957. X                matfree(m);
  958. X                mulval.v_type = V_NUM;
  959. X                mulval.v_num = qlink(&_qzero_);
  960. X                return mulval;
  961. X            }
  962. X            val += rows;
  963. X        }
  964. X        invertvalue(val, &mulval);
  965. X        if (row != cur) {
  966. X            matswaprow(m, row, cur);
  967. X            neg = !neg;
  968. X        }
  969. X        /*
  970. X         * Now for every other nonzero entry lower down in the current column,
  971. X         * subtract the appropriate multiple of the current row to force that
  972. X         * entry to become zero.
  973. X         */
  974. X        row = cur + 1;
  975. X        val = &m->m_table[(row * rows) + cur];
  976. X        for (; row < rows; row++, val += rows) {
  977. X            if (testvalue(val) == 0)
  978. X                continue;
  979. X            mulvalue(val, &mulval, &tmpval);
  980. X            matsubrow(m, row, cur, &tmpval);
  981. X            freevalue(&tmpval);
  982. X        }
  983. X        freevalue(&mulval);
  984. X    }
  985. X    /*
  986. X     * Now the matrix is upper-diagonal, and the determinant is the
  987. X     * product of the main diagonal entries, and is possibly negated.
  988. X     */
  989. X    val = m->m_table;
  990. X    mulval.v_type = V_NUM;
  991. X    mulval.v_num = qlink(&_qone_);
  992. X    for (row = 0; row < rows; row++) {
  993. X        mulvalue(&mulval, val, &tmpval);
  994. X        freevalue(&mulval);
  995. X        mulval = tmpval;
  996. X        val += (rows + 1);
  997. X    }
  998. X    matfree(m);
  999. X    if (neg) {
  1000. X        negvalue(&mulval, &tmpval);
  1001. X        freevalue(&mulval);
  1002. X        return tmpval;
  1003. X    }
  1004. X    return mulval;
  1005. X}
  1006. X
  1007. X
  1008. X/*
  1009. X * Local utility routine to swap two rows of a square matrix.
  1010. X * No checks are made to verify the legality of the arguments.
  1011. X */
  1012. Xstatic void
  1013. Xmatswaprow(m, r1, r2)
  1014. X    MATRIX *m;
  1015. X    long r1, r2;
  1016. X{
  1017. X    register VALUE *v1, *v2;
  1018. X    register long rows;
  1019. X    VALUE tmp;
  1020. X
  1021. X    if (r1 == r2)
  1022. X        return;
  1023. X    rows = (m->m_max[0] - m->m_min[0] + 1);
  1024. X    v1 = &m->m_table[r1 * rows];
  1025. X    v2 = &m->m_table[r2 * rows];
  1026. X    while (rows-- > 0) {
  1027. X        tmp = *v1;
  1028. X        *v1 = *v2;
  1029. X        *v2 = tmp;
  1030. X        v1++;
  1031. X        v2++;
  1032. X    }
  1033. X}
  1034. X
  1035. X
  1036. X/*
  1037. X * Local utility routine to subtract a multiple of one row to another one.
  1038. X * The row to be changed is oprow, the row to be subtracted is baserow.
  1039. X * No checks are made to verify the legality of the arguments.
  1040. X */
  1041. Xstatic void
  1042. Xmatsubrow(m, oprow, baserow, mulval)
  1043. X    MATRIX *m;
  1044. X    long oprow, baserow;
  1045. X    VALUE *mulval;
  1046. X{
  1047. X    register VALUE *vop, *vbase;
  1048. X    register long entries;
  1049. X    VALUE tmp1, tmp2;
  1050. X
  1051. X    entries = (m->m_max[0] - m->m_min[0] + 1);
  1052. X    vop = &m->m_table[oprow * entries];
  1053. X    vbase = &m->m_table[baserow * entries];
  1054. X    while (entries-- > 0) {
  1055. X        mulvalue(vbase, mulval, &tmp1);
  1056. X        subvalue(vop, &tmp1, &tmp2);
  1057. X        freevalue(&tmp1);
  1058. X        freevalue(vop);
  1059. X        *vop = tmp2;
  1060. X        vop++;
  1061. X        vbase++;
  1062. X    }
  1063. X}
  1064. X
  1065. X
  1066. X#if 0
  1067. X/*
  1068. X * Local utility routine to add one row to another one.
  1069. X * No checks are made to verify the legality of the arguments.
  1070. X */
  1071. Xstatic void
  1072. Xmataddrow(m, r1, r2)
  1073. X    MATRIX *m;
  1074. X    long r1;    /* row to be added into */
  1075. X    long r2;    /* row to add */
  1076. X{
  1077. X    register VALUE *v1, *v2;
  1078. X    register long rows;
  1079. X    VALUE tmp;
  1080. X
  1081. X    rows = (m->m_max[0] - m->m_min[0] + 1);
  1082. X    v1 = &m->m_table[r1 * rows];
  1083. X    v2 = &m->m_table[r2 * rows];
  1084. X    while (rows-- > 0) {
  1085. X        addvalue(v1, v2, &tmp);
  1086. X        freevalue(v1);
  1087. X        *v1 = tmp;
  1088. X        v1++;
  1089. X        v2++;
  1090. X    }
  1091. X}
  1092. X#endif
  1093. X
  1094. X
  1095. X/*
  1096. X * Local utility routine to multiply a row by a specified number.
  1097. X * No checks are made to verify the legality of the arguments.
  1098. X */
  1099. Xstatic void
  1100. Xmatmulrow(m, row, mulval)
  1101. X    MATRIX *m;
  1102. X    long row;
  1103. X    VALUE *mulval;
  1104. X{
  1105. X    register VALUE *val;
  1106. X    register long rows;
  1107. X    VALUE tmp;
  1108. X
  1109. X    rows = (m->m_max[0] - m->m_min[0] + 1);
  1110. X    val = &m->m_table[row * rows];
  1111. X    while (rows-- > 0) {
  1112. X        mulvalue(val, mulval, &tmp);
  1113. X        freevalue(val);
  1114. X        *val = tmp;
  1115. X        val++;
  1116. X    }
  1117. X}
  1118. X
  1119. X
  1120. X/*
  1121. X * Make a full copy of a matrix.
  1122. X */
  1123. XMATRIX *
  1124. Xmatcopy(m)
  1125. X    MATRIX *m;
  1126. X{
  1127. X    MATRIX *res;
  1128. X    register VALUE *v1, *v2;
  1129. X    register long i;
  1130. X
  1131. X    res = matalloc(m->m_size);
  1132. X    *res = *m;
  1133. X    v1 = m->m_table;
  1134. X    v2 = res->m_table;
  1135. X    i = m->m_size;
  1136. X    while (i-- > 0) {
  1137. X        if (v1->v_type == V_NUM) {
  1138. X            v2->v_type = V_NUM;
  1139. X            v2->v_num = qlink(v1->v_num);
  1140. X        } else
  1141. X            copyvalue(v1, v2);
  1142. X        v1++;
  1143. X        v2++;
  1144. X    }
  1145. X    return res;
  1146. X}
  1147. X
  1148. X
  1149. X/*
  1150. X * Allocate a matrix with the specified number of elements.
  1151. X */
  1152. XMATRIX *
  1153. Xmatalloc(size)
  1154. X    long size;
  1155. X{
  1156. X    MATRIX *m;
  1157. X
  1158. X    m = (MATRIX *) malloc(matsize(size));
  1159. X    if (m == NULL)
  1160. X        error("Cannot get memory to allocate matrix of size %d", size);
  1161. X    m->m_size = size;
  1162. X    return m;
  1163. X}
  1164. X
  1165. X
  1166. X/*
  1167. X * Free a matrix, along with all of its element values.
  1168. X */
  1169. Xvoid
  1170. Xmatfree(m)
  1171. X    MATRIX *m;
  1172. X{
  1173. X    register VALUE *vp;
  1174. X    register long i;
  1175. X
  1176. X    vp = m->m_table;
  1177. X    i = m->m_size;
  1178. X    while (i-- > 0) {
  1179. X        if (vp->v_type == V_NUM) {
  1180. X            vp->v_type = V_NULL;
  1181. X            qfree(vp->v_num);
  1182. X        } else
  1183. X            freevalue(vp);
  1184. X        vp++;
  1185. X    }
  1186. X    free(m);
  1187. X}
  1188. X
  1189. X
  1190. X/*
  1191. X * Test whether a matrix has any nonzero values.
  1192. X * Returns TRUE if so.
  1193. X */
  1194. XBOOL
  1195. Xmattest(m)
  1196. X    MATRIX *m;
  1197. X{
  1198. X    register VALUE *vp;
  1199. X    register long i;
  1200. X
  1201. X    vp = m->m_table;
  1202. X    i = m->m_size;
  1203. X    while (i-- > 0) {
  1204. X        if ((vp->v_type != V_NUM) || (!qiszero(vp->v_num)))
  1205. X            return TRUE;
  1206. X        vp++;
  1207. X    }
  1208. X    return FALSE;
  1209. X}
  1210. X
  1211. X
  1212. X/*
  1213. X * Test whether or not two matrices are equal.
  1214. X * Equality is determined by the shape and values of the matrices,
  1215. X * but not by their index bounds.  Returns TRUE if they differ.
  1216. X */
  1217. XBOOL
  1218. Xmatcmp(m1, m2)
  1219. X    MATRIX *m1, *m2;
  1220. X{
  1221. X    VALUE *v1, *v2;
  1222. X    long i;
  1223. X
  1224. X    if (m1 == m2)
  1225. X        return FALSE;
  1226. X    if ((m1->m_dim != m2->m_dim) || (m1->m_size != m2->m_size))
  1227. X        return TRUE;
  1228. X    for (i = 0; i < m1->m_dim; i++) {
  1229. X        if ((m1->m_max[i] - m1->m_min[i]) != (m2->m_max[i] - m2->m_min[i]))
  1230. X        return TRUE;
  1231. X    }
  1232. X    v1 = m1->m_table;
  1233. X    v2 = m2->m_table;
  1234. X    i = m1->m_size;
  1235. X    while (i-- > 0) {
  1236. X        if (comparevalue(v1++, v2++))
  1237. X            return TRUE;
  1238. X    }
  1239. X    return FALSE;
  1240. X}
  1241. X
  1242. X
  1243. X#if 0
  1244. X/*
  1245. X * Test whether or not a matrix is the identity matrix.
  1246. X * Returns TRUE if so.
  1247. X */
  1248. XBOOL
  1249. Xmatisident(m)
  1250. X    MATRIX *m;
  1251. X{
  1252. X    register VALUE *val;    /* current value */
  1253. X    long row, col;        /* row and column numbers */
  1254. X
  1255. X    if ((m->m_dim != 2) ||
  1256. X        ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1])))
  1257. X            return FALSE;
  1258. X    val = m->m_table;
  1259. X    for (row = 0; row < m->m_size; row++) {
  1260. X        for (col = 0; col < m->m_size; col++) {
  1261. X            if (val->v_type != V_NUM)
  1262. X                return FALSE;
  1263. X            if (row == col) {
  1264. X                if (!qisone(val->v_num))
  1265. X                    return FALSE;
  1266. X            } else {
  1267. X                if (!qiszero(val->v_num))
  1268. X                    return FALSE;
  1269. X            }
  1270. X            val++;
  1271. X        }
  1272. X    }
  1273. X    return TRUE;
  1274. X}
  1275. X#endif
  1276. X
  1277. X
  1278. X/*
  1279. X * Print a matrix and possibly few of its elements.
  1280. X * The argument supplied specifies how many elements to allow printing.
  1281. X * If any elements are printed, they are printed in short form.
  1282. X */
  1283. Xvoid
  1284. Xmatprint(m, maxprint)
  1285. X    MATRIX *m;
  1286. X    long maxprint;
  1287. X{
  1288. X    VALUE *vp;
  1289. X    long fullsize, count, index, num;
  1290. X    int dim, i;
  1291. X    char *msg;
  1292. X    long sizes[MAXDIM];
  1293. X
  1294. X    dim = m->m_dim;
  1295. X    fullsize = 1;
  1296. X    for (i = dim - 1; i >= 0; i--) {
  1297. X        sizes[i] = fullsize;
  1298. X        fullsize *= (m->m_max[i] - m->m_min[i] + 1);
  1299. X    }
  1300. X    msg = ((maxprint > 0) ? "\nmat [" : "mat [");
  1301. X    for (i = 0; i < dim; i++) {
  1302. X        if (m->m_min[i])
  1303. X            math_fmt("%s%ld:%ld", msg, m->m_min[i], m->m_max[i]);
  1304. X        else
  1305. X            math_fmt("%s%ld", msg, m->m_max[i] + 1);
  1306. X        msg = ",";
  1307. X    }
  1308. X    if (maxprint > fullsize)
  1309. X        maxprint = fullsize;
  1310. X    vp = m->m_table;
  1311. X    count = 0;
  1312. X    for (index = 0; index < fullsize; index++) {
  1313. X        if ((vp->v_type != V_NUM) || !qiszero(vp->v_num))
  1314. X            count++;
  1315. X        vp++;
  1316. X    }
  1317. X    math_fmt("] (%ld element%s, %ld nonzero)",
  1318. X        fullsize, (fullsize == 1) ? "" : "s", count);
  1319. X    if (maxprint <= 0)
  1320. X        return;
  1321. X
  1322. X    /*
  1323. X     * Now print the first few elements of the matrix in short
  1324. X     * and unambigous format.
  1325. X     */
  1326. X    math_str(":\n");
  1327. X    vp = m->m_table;
  1328. X    for (index = 0; index < maxprint; index++) {
  1329. X        msg = "  [";
  1330. X        num = index;
  1331. X        for (i = 0; i < dim; i++) {
  1332. X            math_fmt("%s%ld", msg, m->m_min[i] + (num / sizes[i]));
  1333. X            num %= sizes[i];
  1334. X            msg = ",";
  1335. X        }
  1336. X        math_str("] = ");
  1337. X        printvalue(vp++, PRINT_SHORT | PRINT_UNAMBIG);
  1338. X        math_str("\n");
  1339. X    }
  1340. X    if (maxprint < fullsize)
  1341. X        math_str("  ...\n");
  1342. X}
  1343. X
  1344. X/* END CODE */
  1345. END_OF_FILE
  1346. if test 28075 -ne `wc -c <'matfunc.c'`; then
  1347.     echo shar: \"'matfunc.c'\" unpacked with wrong size!
  1348. fi
  1349. # end of 'matfunc.c'
  1350. fi
  1351. echo shar: End of archive 14 \(of 21\).
  1352. cp /dev/null ark14isdone
  1353. MISSING=""
  1354. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
  1355.     if test ! -f ark${I}isdone ; then
  1356.     MISSING="${MISSING} ${I}"
  1357.     fi
  1358. done
  1359. if test "${MISSING}" = "" ; then
  1360.     echo You have unpacked all 21 archives.
  1361.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1362. else
  1363.     echo You still need to unpack the following archives:
  1364.     echo "        " ${MISSING}
  1365. fi
  1366. ##  End of shell archive.
  1367. exit 0
  1368.