home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l196 / 3.ddi / MATB.BA$ / MATB.bin
Encoding:
Text File  |  1990-06-24  |  46.4 KB  |  1,190 lines

  1. '*** MATB.BAS - Matrix Math Routines for the Matrix Math Toolbox in
  2. '           Microsoft BASIC 7.1, Professional Development System
  3. '              Copyright (C) 1987-1990, Microsoft Corporation
  4. '
  5. '  NOTE:  This sample source code toolbox is intended to demonstrate some
  6. '  of the extended capabilities of Microsoft BASIC 7.1 Professional Development
  7. '  system that can help to leverage the professional developer's time more
  8. '  effectively.  While you are free to use, modify, or distribute the routines
  9. '  in this module in any way you find useful, it should be noted that these are
  10. '  examples only and should not be relied upon as a fully-tested "add-on"
  11. '  library.
  12. '
  13. '  Purpose:
  14. 'This toolbox contains routines which perform elementary operations on systems
  15. 'of linear equations represented as matrices.  The functions return integer
  16. 'error codes in the name and results in the parameter list.  The functions
  17. 'matbs?% and matlu?% found in this module are intended for internal use only.
  18. 'Error codes returned:
  19. '     0  no error                     -1  matrix not invertible
  20. '    -2  matrix not square            -3  inner dimensions different
  21. '    -4  matrix dimensions different  -5  result matrix dimensioned incorrectly
  22. '    any other codes returned are standard BASIC errors
  23. '
  24. '-------------------------------------------------------------------
  25. 'MatDet, MatSEqn, and MatInv all use LU-decomposition to implement Gaussian
  26. 'elimination.  A brief explanation of what is meant by an LU matrix is given
  27. 'below, followed by simplified versions of the two internal routines used to
  28. 'do all elimination.
  29. '
  30. 'What is meant by an LU matrix:
  31. 'An upper triangle matrix (one with all nonzero entries on or above the main
  32. 'diagonal) can be solved immediately.  The goal of Gaussian elimination is to
  33. 'transform a non upper triangle system into an equivalent triangular one.
  34. '
  35. 'Given a system of equations represented in matrix form by Ax=b, we need a
  36. 'linear transformation L such that LA=U where U is and upper triangular matrix.
  37. 'Then Ux=LAx=Lb and Ux=Lb is an upper triangular system.
  38. '
  39. 'This library explicitly calculates U, but L is never saved in its own array.
  40. 'When we do a row operation to create a zero below the main diagonal, we no
  41. 'longer need to save that value because we know it is zero.  This leaves the
  42. 'space available to save the multiplier used in the row operation.  When
  43. 'elimination is completed (ie, when the matrix is upper triangular), these
  44. 'multipliers give us a complete record of what we did to A to make it upper
  45. 'triangular.  This is equivalent to saying the multipliers represent L.  We now
  46. 'have a U and an L stored in the same matrix!  This type of matrix will be
  47. 'referred to as an LU matrix, or just LU.
  48. '
  49. 'The following code fragments get LU and backsolve Ux=Lb.  The actual routines
  50. 'used in the toolbox are much more involved because they implement total
  51. 'pivoting and implicit row scaling to reduce round off errors.  However, all the
  52. 'extras (pivoting, scaling, error checking) are extraneous to the main routines,
  53. 'which total only 20 lines.  If you are unfamilar with this type of matrix math,
  54. 'gaining an understanding of these 20 lines is a very good introduction.  Try
  55. 'working through a 2x2 or 3x3 example by hand to see what is happening.  The
  56. 'numerical techniques used to reduce round off error will not be discussed.
  57. '
  58. '-------------------------------------------------------------------
  59. 'Given the coefficient matrix A(1 TO N, 1 TO N) and the vector b(1 TO N),
  60. 'the following fragments will find x(1 TO N) satisfying Ax=b using Gaussian
  61. 'elimination.
  62. '
  63. 'matlu:
  64. 'Perform row operations to get all zeroes below the main diagonal.
  65. 'Define Rj(1 TO N) to be the vector corresponding to the jth row of A.
  66. 'Let Rrow = Rrow + m*Rpvt where m = -Rrow(pvt)/Rpvt(pvt).
  67. 'Then A(row, pvt)=0.
  68. '
  69. '** FOR pvt = 1 TO (N - 1)
  70. '**    FOR row = (pvt + 1) TO N
  71. '**       'Save m for later use in the space just made 0.
  72. '**       A(row, pvt) = -A(row, pvt) / A(pvt, pvt)
  73. '**       'Do the row operation.
  74. '**       FOR col = (pvt + 1) TO N
  75. '**          A(row, col) = A(row, col) + A(row, pvt) * A(pvt, col)
  76. '**       NEXT col
  77. '**    NEXT row
  78. '** NEXT pvt
  79. '
  80. 'matbs:
  81. 'Do the same row operations on b using the multipliers saved in A.
  82. '
  83. '** FOR pvt = 1 TO (N - 1)
  84. '**    FOR row = (pvt + 1) TO N
  85. '**       b(row) = b(row) + A(row, pvt) * b(pvt)
  86. '**    NEXT row
  87. '** NEXT pvt
  88. '
  89. 'Backsolve Ux=Lb to find x.
  90. '                               N
  91. 'For r = N to 1, x(r) = [b(r) - Σ (A(r,c)*x(c))]/A(r,r)
  92. '                              c=r+1
  93. '** FOR row = N TO 1 STEP -1
  94. '**    x(row) = b(row)
  95. '**    FOR col = (row + 1) TO N
  96. '**       x(row) = x(row) - A(row, col) * x(col)
  97. '**    NEXT col
  98. '**    x(row) = x(row) / A(row, row)
  99. '** NEXT row
  100. '
  101. '===================================================================
  102. '$INCLUDE: 'matb.bi'
  103. DECLARE FUNCTION matbsD% (A() AS DOUBLE, b() AS DOUBLE, x() AS DOUBLE)
  104. DECLARE FUNCTION matbsS% (A() AS SINGLE, b() AS SINGLE, x() AS SINGLE)
  105. DECLARE FUNCTION matluD% (A() AS DOUBLE)
  106. DECLARE FUNCTION matluS% (A() AS SINGLE)
  107. DIM SHARED lo AS INTEGER, up AS INTEGER
  108. DIM SHARED continue AS INTEGER, count AS INTEGER
  109. DIM SHARED rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  110. END
  111.  
  112. '=======================MatAddC%====================================
  113. 'MatAddC% adds two currency type matrices and places the sum in
  114. 'the first.
  115. '
  116. 'Parameters: matrices Alpha,Beta
  117. '
  118. 'Returns: Alpha() = Alpha() + Beta()
  119. '===================================================================
  120. FUNCTION MatAddC% (Alpha() AS CURRENCY, Beta() AS CURRENCY)
  121. ON LOCAL ERROR GOTO cadderr: MatAddC% = 0
  122. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  123. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  124. 'loop through and add elements
  125. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  126.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  127.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)
  128.    NEXT col%
  129. NEXT row%
  130. caddexit:
  131. EXIT FUNCTION
  132. cadderr:
  133.    MatAddC% = (ERR + 5) MOD 200 - 5
  134.    RESUME caddexit
  135. END FUNCTION
  136.  
  137. '=======================MatAddD%====================================
  138. 'MatAddD% adds two double precision matrices and places the sum in
  139. 'the first.
  140. '
  141. 'Parameters: matrices Alpha,Beta
  142. '
  143. 'Returns: Alpha() = Alpha() + Beta()
  144. '===================================================================
  145. FUNCTION MatAddD% (Alpha() AS DOUBLE, Beta() AS DOUBLE)
  146. ON LOCAL ERROR GOTO dadderr: MatAddD% = 0
  147. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  148. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  149. 'loop through and add elements
  150. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  151.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  152.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)
  153.    NEXT col%
  154. NEXT row%
  155. daddexit:
  156. EXIT FUNCTION
  157. dadderr:
  158.    MatAddD% = (ERR + 5) MOD 200 - 5
  159.    RESUME daddexit
  160. END FUNCTION
  161.  
  162. '=======================MatAddI%====================================
  163. 'MatAddI% adds two integer matrices and places the sum in
  164. 'the first.
  165. '
  166. 'Parameters: matrices Alpha,Beta
  167. '
  168. 'Returns: Alpha() = Alpha() + Beta()
  169. '===================================================================
  170. FUNCTION MatAddI% (Alpha() AS INTEGER, Beta() AS INTEGER)
  171. ON LOCAL ERROR GOTO iadderr: MatAddI% = 0
  172. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  173. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  174. 'loop through and add elements
  175. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  176.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  177.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)
  178.    NEXT col%
  179. NEXT row%
  180. iaddexit:
  181. EXIT FUNCTION
  182. iadderr:
  183.    MatAddI% = (ERR + 5) MOD 200 - 5
  184.    RESUME iaddexit
  185. END FUNCTION
  186.  
  187. '=======================MatAddL%====================================
  188. 'MatAddL% adds two long integer matrices and places the sum in
  189. 'the first.
  190. '
  191. 'Parameters: matrices Alpha,Beta
  192. '
  193. 'Returns: Alpha() = Alpha() + Beta()
  194. '===================================================================
  195. FUNCTION MatAddL% (Alpha() AS LONG, Beta() AS LONG)
  196. ON LOCAL ERROR GOTO ladderr: MatAddL% = 0
  197. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  198. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  199. 'loop through and add elements
  200. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  201.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  202.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)
  203.    NEXT col%
  204. NEXT row%
  205. laddexit:
  206. EXIT FUNCTION
  207. ladderr:
  208.    MatAddL% = (ERR + 5) MOD 200 - 5
  209.    RESUME laddexit
  210. END FUNCTION
  211.  
  212. '=======================MatAddS%====================================
  213. 'MatAddS% adds two single precision matrices and places the sum in
  214. 'the first.
  215. '
  216. 'Parameters: matrices Alpha,Beta
  217. '
  218. 'Returns: Alpha() = Alpha() + Beta()
  219. '===================================================================
  220. FUNCTION MatAddS% (Alpha() AS SINGLE, Beta() AS SINGLE)
  221. ON LOCAL ERROR GOTO sadderr: MatAddS% = 0
  222. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  223. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  224. 'loop through and add elements
  225. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  226.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  227.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)
  228.    NEXT col%
  229. NEXT row%
  230. saddexit:
  231. EXIT FUNCTION
  232. sadderr:
  233.    MatAddS% = (ERR + 5) MOD 200 - 5
  234.    RESUME saddexit
  235. END FUNCTION
  236.  
  237. '========================matbsD=====================================
  238. 'matbsD% takes a matrix in LU form, found by matluD%, and a vector b
  239. 'and solves the system Ux=Lb for x. matrices A,b,x are double precision.
  240. '
  241. 'Parameters: LU matrix in A, corresponding pivot vectors in rpvt and cpvt,
  242. '            right side in b
  243. '
  244. 'Returns: solution in x, b is modified, rest unchanged
  245. '===================================================================
  246. FUNCTION matbsD% (A() AS DOUBLE, b() AS DOUBLE, x() AS DOUBLE)
  247. ON LOCAL ERROR GOTO dbserr: matbsD% = 0
  248. 'do row operations on b using the multipliers in L to find Lb
  249. FOR pvt% = lo TO (up - 1)
  250.    c% = cpvt(pvt%)
  251.    FOR row% = (pvt% + 1) TO up
  252.       r% = rpvt(row%)
  253.       b(r%) = b(r%) + A(r%, c%) * b(rpvt(pvt%))
  254.    NEXT row%
  255. NEXT pvt%
  256. 'backsolve Ux=Lb to find x
  257. FOR row% = up TO lo STEP -1
  258.    c% = cpvt(row%)
  259.    r% = rpvt(row%)
  260.    x(c%) = b(r%)
  261.    FOR col% = (row% + 1) TO up
  262.       x(c%) = x(c%) - A(r%, cpvt(col%)) * x(cpvt(col%))
  263.    NEXT col%
  264.    x(c%) = x(c%) / A(r%, c%)
  265. NEXT row%
  266. dbsexit:
  267. EXIT FUNCTION
  268. dbserr:
  269.    matbsD% = ERR
  270.    RESUME dbsexit
  271. END FUNCTION
  272.  
  273. '========================matbsS=====================================
  274. 'matbsS% takes a matrix in LU form, found by matluS%, and a vector b
  275. 'and solves the system Ux=Lb for x. matrices A,b,x are single precision.
  276. '
  277. 'Parameters: LU matrix in A, corresponding pivot vectors in rpvt and cpvt,
  278. '            right side in b
  279. '
  280. 'Returns: solution in x, b is modified, rest unchanged
  281. '===================================================================
  282. FUNCTION matbsS% (A() AS SINGLE, b() AS SINGLE, x() AS SINGLE)
  283. ON LOCAL ERROR GOTO sbserr: matbsS% = 0
  284. 'do row operations on b using the multipliers in L to find Lb
  285. FOR pvt% = lo TO (up - 1)
  286.    c% = cpvt(pvt%)
  287.    FOR row% = (pvt% + 1) TO up
  288.       r% = rpvt(row%)
  289.       b(r%) = b(r%) + A(r%, c%) * b(rpvt(pvt%))
  290.    NEXT row%
  291. NEXT pvt%
  292. 'backsolve Ux=Lb to find x
  293. FOR row% = up TO lo STEP -1
  294.    c% = cpvt(row%)
  295.    r% = rpvt(row%)
  296.    x(c%) = b(r%)
  297.    FOR col% = (row% + 1) TO up
  298.       x(c%) = x(c%) - A(r%, cpvt(col%)) * x(cpvt(col%))
  299.    NEXT col%
  300.    x(c%) = x(c%) / A(r%, c%)
  301. NEXT row%
  302. sbsexit:
  303. EXIT FUNCTION
  304. sbserr:
  305.    matbsS% = ERR
  306.    RESUME sbsexit
  307. END FUNCTION
  308.  
  309. '========================MatDetC%===================================
  310. 'MatDetC% finds the determinant of a square, currency type matrix
  311. '
  312. 'Parameters: A(n x n) matrix, det@ to return the determinant
  313. '
  314. 'Returns: matrix A in LU form, determinant
  315. '===================================================================
  316. FUNCTION MatDetC% (A() AS CURRENCY, det@)
  317. ON LOCAL ERROR GOTO cdeterr: errcode% = 0
  318. lo = LBOUND(A, 1)
  319. up = UBOUND(A, 1)
  320. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  321. 'make temporary double precision matrix to find pivots
  322. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE
  323. FOR row% = lo TO up
  324.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)
  325.       Tmp(row%, col%) = CDBL(A(row%, col%))
  326.    NEXT col%
  327. NEXT row%
  328. errcode% = matluD%(Tmp())              'Get LU matrix
  329. IF NOT continue THEN
  330.    IF errcode% = 199 THEN det@ = 0@
  331.    ERROR errcode%
  332. ELSE
  333.    detD# = 1#                          '+/- determinant = product of the pivots
  334.    FOR pvt% = lo TO up
  335.       detD# = detD# * Tmp(rpvt(pvt%), cpvt(pvt%))
  336.    NEXT pvt%                           'count contains the total number of row
  337.    det@ = (-1@) ^ count * CCUR(detD#)  'and column switches due to pivoting.
  338.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for
  339. END IF                                 'each switch.
  340. cdetexit:
  341. ERASE rpvt, cpvt, Tmp
  342. MatDetC% = errcode%
  343. EXIT FUNCTION
  344. cdeterr:
  345.    errcode% = (ERR + 5) MOD 200 - 5
  346.    RESUME cdetexit
  347. END FUNCTION
  348.  
  349. '========================MatDetD%===================================
  350. 'MatDetD% finds the determinant of a square, double precision matrix
  351. '
  352. 'Parameters: A(n x n) matrix, det# to return the determinant
  353. '
  354. 'Returns: matrix A in LU form, determinant
  355. '===================================================================
  356. FUNCTION MatDetD% (A() AS DOUBLE, det#)
  357. ON LOCAL ERROR GOTO ddeterr: errcode% = 0
  358. lo = LBOUND(A, 1)
  359. up = UBOUND(A, 1)
  360. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  361. errcode% = matluD%(A())             'Get LU matrix
  362. IF NOT continue THEN
  363.    IF errcode% = 199 THEN det# = 0#
  364.    ERROR errcode%
  365. ELSE
  366.    det# = 1#                        '+/- determinant = product of the pivots
  367.    FOR pvt% = lo TO up
  368.       det# = det# * A(rpvt(pvt%), cpvt(pvt%))
  369.    NEXT pvt%                         'count contains the total number of row
  370.    det# = (-1) ^ count * det#        'and column switches due to pivoting.
  371.    IF errcode% THEN ERROR errcode%   'multiply the determinant by -1 for
  372. END IF                               'each switch
  373. ddetexit:             
  374. ERASE rpvt, cpvt
  375. MatDetD% = errcode%
  376. EXIT FUNCTION
  377. ddeterr:
  378.    errcode% = (ERR + 5) MOD 200 - 5
  379.    RESUME ddetexit
  380. END FUNCTION
  381.  
  382. '========================MatDetI%===================================
  383. 'MatDetI% finds the determinant of a square, integer matrix
  384. '
  385. 'Parameters: A(n x n) matrix, det% to return the determinant
  386. '
  387. 'Returns: matrix A unchanged, determinant
  388. '===================================================================
  389. FUNCTION MatDetI% (A() AS INTEGER, det%)
  390. ON LOCAL ERROR GOTO ideterr: errcode% = 0
  391. lo = LBOUND(A, 1)
  392. up = UBOUND(A, 1)
  393. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  394. 'make temporary single precision matrix to find pivots
  395. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS SINGLE
  396. FOR row% = lo TO up
  397.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)
  398.       Tmp(row%, col%) = CSNG(A(row%, col%))
  399.    NEXT col%
  400. NEXT row%
  401. errcode% = matluS%(Tmp())              'Get LU matrix
  402. IF NOT continue THEN
  403.    IF errcode% = 199 THEN det% = 0
  404.    ERROR errcode%
  405. ELSE
  406.    detS! = 1!                          '+/- determinant = product of the pivots
  407.    FOR pvt% = lo TO up
  408.       detS! = detS! * Tmp(rpvt(pvt%), cpvt(pvt%))
  409.    NEXT pvt%                           'count contains the total number of row
  410.    det% = (-1) ^ count * CINT(detS!)   'and column switches due to pivoting.
  411.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for
  412. END IF                                 'each switch
  413. idetexit:
  414. ERASE rpvt, cpvt, Tmp
  415. MatDetI% = errcode%
  416. EXIT FUNCTION
  417. ideterr:
  418.    errcode% = (ERR + 5) MOD 200 - 5
  419.    RESUME idetexit
  420. END FUNCTION
  421.  
  422. '========================MatDetL%===================================
  423. 'MatDetL% finds the determinant of a square, long integer matrix
  424. '
  425. 'Parameters: A(n x n) matrix, det& to return the determinant
  426. '
  427. 'Returns: matrix A unchanged, determinant
  428. '===================================================================
  429. FUNCTION MatDetL% (A() AS LONG, det&)
  430. ON LOCAL ERROR GOTO ldeterr: errcode% = 0
  431. lo = LBOUND(A, 1)
  432. up = UBOUND(A, 1)
  433. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  434. 'make temporary double precision matrix to find pivots
  435. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE
  436. FOR row% = lo TO up
  437.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)
  438.       Tmp(row%, col%) = CDBL(A(row%, col%))
  439.    NEXT col%
  440. NEXT row%
  441. errcode% = matluD%(Tmp())              'Get LU matrix
  442. IF NOT continue THEN
  443.    IF errcode% = 199 THEN det& = 0&
  444.    ERROR errcode%
  445. ELSE
  446.    detD# = 1#                          '+/- determinant = product of the pivots
  447.    FOR pvt% = lo TO up
  448.       detD# = detD# * Tmp(rpvt(pvt%), cpvt(pvt%))
  449.    NEXT pvt%                           'count contains the total number of row
  450.    det& = (-1&) ^ count * CLNG(detD#)  'and column switches due to pivoting.
  451.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for
  452. END IF                                 'each switch
  453. ldetexit:
  454. ERASE rpvt, cpvt, Tmp
  455. MatDetL% = errcode%
  456. EXIT FUNCTION
  457. ldeterr:
  458.    errcode% = (ERR + 5) MOD 200 - 5
  459.    RESUME ldetexit
  460. END FUNCTION
  461.  
  462. '========================MatDetS%===================================
  463. 'MatDetS% finds the determinant of a square, single precision matrix
  464. '
  465. 'Parameters: A(n x n) matrix, det! to return the determinant
  466. '
  467. 'Returns: matrix A in LU form, determinant
  468. '===================================================================
  469. FUNCTION MatDetS% (A() AS SINGLE, det!)
  470. ON LOCAL ERROR GOTO sdeterr: errcode% = 0
  471. lo = LBOUND(A, 1)
  472. up = UBOUND(A, 1)
  473. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  474. errcode% = matluS%(A())                'Get LU matrix
  475. IF NOT continue THEN
  476.    IF errcode% = 199 THEN det! = 0!
  477.    ERROR errcode%
  478. ELSE
  479.    det! = 1!                           '+/- determinant = product of the pivots
  480.    FOR pvt% = lo TO up
  481.       det! = det! * A(rpvt(pvt%), cpvt(pvt%))
  482.    NEXT pvt%                           'count contains the total number of row
  483.    det! = (-1) ^ count * det!          'and column switches due to pivoting.
  484.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for
  485. END IF                                 'each switch
  486. sdetexit:
  487. ERASE rpvt, cpvt
  488. MatDetS% = errcode%
  489. EXIT FUNCTION
  490. sdeterr:
  491.    errcode% = (ERR + 5) MOD 200 - 5
  492.    RESUME sdetexit
  493. END FUNCTION
  494.  
  495. '========================MatInvC%===================================
  496. 'MatInvC% uses the matluD% and matbsD procedures to invert a square, currency
  497. 'type matrix.  Let e(N) contain all zeroes except for the jth position, which
  498. 'is 1.  Then the jth column of A^-1 is x, where Ax=e.
  499. '
  500. 'Parameters: A(n x n) matrix
  501. '
  502. 'Returns: A^-1
  503. '===================================================================
  504. FUNCTION MatInvC% (A() AS CURRENCY)
  505. ON LOCAL ERROR GOTO cinverr: errcode% = 0
  506. lo = LBOUND(A, 1)
  507. up = UBOUND(A, 1)
  508. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  509. 'duplicate A() in a double precision work matrix, Tmp()
  510. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE
  511. DIM e(lo TO up) AS DOUBLE, x(lo TO up) AS DOUBLE
  512. FOR row% = lo TO up
  513.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)
  514.       Tmp(row%, col%) = CDBL(A(row%, col%))
  515.    NEXT col%
  516. NEXT row%
  517. errcode% = matluD%(Tmp())                    'Put LU in Tmp
  518. IF NOT continue THEN ERROR errcode%
  519. FOR col% = lo TO up                          'Find A^-1 one column at a time
  520.    e(col%) = 1#
  521.    bserrcode% = matbsD%(Tmp(), e(), x())
  522.    IF bserrcode% THEN ERROR bserrcode%
  523.    FOR row% = lo TO up
  524.       A(row%, col%) = CCUR(x(row%))          'Put the column into A
  525.       e(row%) = 0#
  526.    NEXT row%
  527. NEXT col%
  528. IF errcode% THEN ERROR errcode%
  529. cinvexit:
  530. ERASE Tmp, e, x, rpvt, cpvt
  531. MatInvC% = errcode%
  532. EXIT FUNCTION
  533. cinverr:
  534.    errcode% = (ERR + 5) MOD 200 - 5
  535.    RESUME cinvexit
  536. END FUNCTION
  537.  
  538. '========================MatInvD%===================================
  539. 'MatInvD% uses the matluD% and matbsD procedures to invert a square, double
  540. 'precision matrix.  Let e(N) contain all zeroes except for the jth position,
  541. 'which is 1.  Then the jth column of A^-1 is x, where Ax=e.
  542. '
  543. 'Parameters: A(n x n) matrix
  544. '
  545. 'Returns: A^-1
  546. '===================================================================
  547. FUNCTION MatInvD% (A() AS DOUBLE)
  548. ON LOCAL ERROR GOTO dinverr: errcode% = 0
  549. lo = LBOUND(A, 1)
  550. up = UBOUND(A, 1)
  551. DIM Ain(lo TO up, lo TO up) AS DOUBLE
  552. DIM e(lo TO up) AS DOUBLE, x(lo TO up) AS DOUBLE
  553. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  554. errcode% = matluD%(A())                     'Get LU matrix
  555. IF NOT continue THEN ERROR errcode%
  556. FOR col% = lo TO up                         'Find A^-1 one column at a time
  557.    e(col%) = 1#
  558.    bserrcode% = matbsD%(A(), e(), x())
  559.    IF bserrcode% THEN ERROR bserrcode%
  560.    FOR row% = lo TO up
  561.       Ain(row%, col%) = x(row%)
  562.       e(row%) = 0#
  563.    NEXT row%
  564. NEXT col%
  565. FOR col% = lo TO up                         'Put A^-1 in A
  566.    FOR row% = lo TO up
  567.       A(row%, col%) = Ain(row%, col%)
  568.    NEXT row%
  569. NEXT col%
  570. IF errcode% THEN ERROR errcode%
  571. dinvexit:
  572. ERASE e, x, Ain, rpvt, cpvt
  573. MatInvD% = errcode%
  574. EXIT FUNCTION
  575. dinverr:
  576.    errcode% = (ERR + 5) MOD 200 - 5
  577.    RESUME dinvexit
  578. END FUNCTION
  579.  
  580. '========================MatInvS%===================================
  581. 'MatInvS% uses the matluS% and matbsS procedures to invert a square, single
  582. 'precision matrix.  Let e(N) contain all zeroes except for the jth position,
  583. 'which is 1. Then the jth column of A^-1 is x, where Ax=e.
  584. '
  585. 'Parameters: A(n x n) matrix
  586. '
  587. 'Returns: A^-1
  588. '===================================================================
  589. FUNCTION MatInvS% (A() AS SINGLE)
  590. ON LOCAL ERROR GOTO sinverr: errcode% = 0
  591. lo = LBOUND(A, 1)
  592. up = UBOUND(A, 1)
  593. DIM Ain(lo TO up, lo TO up) AS SINGLE
  594. DIM e(lo TO up) AS SINGLE, x(lo TO up) AS SINGLE
  595. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  596. errcode% = matluS%(A())                     'Get LU matrix
  597. IF NOT continue THEN ERROR errcode%
  598. FOR col% = lo TO up                         'find A^-1 one column at a time
  599.    e(col%) = 1!
  600.    bserrcode% = matbsS%(A(), e(), x())
  601.    IF bserrcode% THEN ERROR bserrcode%
  602.    FOR row% = lo TO up
  603.       Ain(row%, col%) = x(row%)
  604.       e(row%) = 0!
  605.    NEXT row%
  606. NEXT col%
  607. FOR col% = lo TO up                         'put A^-1 in A
  608.    FOR row% = lo TO up
  609.       A(row%, col%) = Ain(row%, col%)
  610.    NEXT row%
  611. NEXT col%
  612. IF errcode% THEN ERROR errcode%
  613. sinvexit:
  614. ERASE e, x, Ain, rpvt, cpvt
  615. MatInvS% = errcode%
  616. EXIT FUNCTION
  617. sinverr:
  618.    errcode% = (ERR + 5) MOD 200 - 5
  619.    RESUME sinvexit
  620. END FUNCTION
  621.  
  622. '========================matluD%====================================
  623. 'matluD% does Gaussian elimination with total pivoting to put a square, double
  624. 'precision matrix in LU form. The multipliers used in the row operations to
  625. 'create zeroes below the main diagonal are saved in the zero spaces.
  626. '
  627. 'Parameters: A(n x n) matrix, rpvt(n) and cpvt(n) permutation vectors
  628. '            used to index the row and column pivots
  629. '
  630. 'Returns: A in LU form with corresponding pivot vectors; the total number of
  631. '         pivots in count, which is used to find the sign of the determinant.
  632. '===================================================================
  633. FUNCTION matluD% (A() AS DOUBLE)
  634. ON LOCAL ERROR GOTO dluerr: errcode% = 0
  635. 'Checks if A is square, returns error code if not
  636. IF NOT (lo = LBOUND(A, 2) AND up = UBOUND(A, 2)) THEN ERROR 198
  637. DIM rownorm(lo TO up) AS DOUBLE
  638. count = 0                            'initialize count, continue
  639. continue = -1
  640. FOR row% = lo TO up                  'initialize rpvt and cpvt
  641.    rpvt(row%) = row%
  642.    cpvt(row%) = row%
  643.    rownorm(row%) = 0#                'find the row norms of A()
  644.    FOR col% = lo TO up
  645.       rownorm(row%) = rownorm(row%) + ABS(A(row%, col%))
  646.    NEXT col%
  647.    IF rownorm(row%) = 0# THEN        'if any rownorm is zero, the matrix
  648.       continue = 0                   'is singular, set error, exit and
  649.       ERROR 199                      'do not continue
  650.    END IF
  651. NEXT row%
  652. FOR pvt% = lo TO (up - 1)
  653. 'Find best available pivot
  654.    max# = 0#                         'checks all values in rows and columns not
  655.    FOR row% = pvt% TO up             'already used for pivoting and saves the
  656.       r% = rpvt(row%)                'largest absolute number and its position
  657.       FOR col% = pvt% TO up
  658.          c% = cpvt(col%)
  659.          temp# = ABS(A(r%, c%)) / rownorm(r%)
  660.          IF temp# > max# THEN
  661.             max# = temp#
  662.             bestrow% = row%          'save the position of new max#
  663.             bestcol% = col%
  664.          END IF
  665.       NEXT col%
  666.    NEXT row%
  667.    IF max# = 0# THEN                 'if no nonzero number is found, A is
  668.       continue = 0                   'singular, send back error, do not continue
  669.       ERROR 199
  670.    ELSEIF pvt% > 1 THEN              'check if drop in pivots is too much
  671.       IF max# < (deps# * oldmax#) THEN errcode% = 199
  672.    END IF
  673.    oldmax# = max#
  674.    IF rpvt(pvt%) <> rpvt(bestrow%) THEN
  675.       count = count + 1                    'if a row or column pivot is
  676.       SWAP rpvt(pvt%), rpvt(bestrow%)      'necessary, count it and permute
  677.    END IF                                  'rpvt or cpvt. Note: the rows and
  678.    IF cpvt(pvt%) <> cpvt(bestcol%) THEN    'columns are not actually switched,
  679.       count = count + 1                    'only the order in which they are
  680.       SWAP cpvt(pvt%), cpvt(bestcol%)      'used.
  681.    END IF
  682. 'Eliminate all values below the pivot
  683.    rp% = rpvt(pvt%)
  684.    cp% = cpvt(pvt%)
  685.    FOR row% = (pvt% + 1) TO up
  686.       r% = rpvt(row%)
  687.       A(r%, cp%) = -A(r%, cp%) / A(rp%, cp%)  'save multipliers
  688.       FOR col% = (pvt% + 1) TO up
  689.          c% = cpvt(col%)                      'complete row operations
  690.          A(r%, c%) = A(r%, c%) + A(r%, cp%) * A(rp%, c%)
  691.       NEXT col%
  692.    NEXT row%
  693. NEXT pvt%
  694. IF A(rpvt(up), cpvt(up)) = 0# THEN
  695.    continue = 0                      'if last pivot is zero or pivot drop is
  696.    ERROR 199                         'too large, A is singular, send back error
  697. ELSEIF (ABS(A(rpvt(up), cpvt(up))) / rownorm(rpvt(up))) < (deps# * oldmax#) THEN
  698.    errcode% = 199                    'if pivot is not identically zero then
  699. END IF                               'continue remains TRUE
  700. IF errcode% THEN ERROR errcode%
  701. dluexit:
  702. matluD% = errcode%
  703. EXIT FUNCTION
  704. dluerr:
  705.    IF errcode% < 199 THEN continue = 0
  706.    errcode% = ERR
  707.    RESUME dluexit
  708. END FUNCTION
  709.  
  710. '========================matluS%====================================
  711. 'matluS% does Gaussian elimination with total pivoting to put a square, single
  712. 'precision matrix in LU form. The multipliers used in the row operations to
  713. 'create zeroes below the main diagonal are saved in the zero spaces.
  714. '
  715. 'Parameters: A(n x n) matrix, rpvt(n) and cpvt(n) permutation vectors
  716. '            used to index the row and column pivots
  717. '
  718. 'Returns: A in LU form with corresponding pivot vectors; the total number of
  719. '         pivots in count, which is used to find the sign of the determinant.
  720. '===================================================================
  721. FUNCTION matluS% (A() AS SINGLE)
  722. ON LOCAL ERROR GOTO sluerr: errcode% = 0
  723. 'Checks if A is square, returns error code if not
  724. IF NOT (lo = LBOUND(A, 2) AND up = UBOUND(A, 2)) THEN ERROR 198
  725. DIM rownorm(lo TO up) AS SINGLE
  726. count = 0                            'initialize count, continue
  727. continue = -1
  728. FOR row% = lo TO up                  'initialize rpvt and cpvt
  729.    rpvt(row%) = row%
  730.    cpvt(row%) = row%
  731.    rownorm(row%) = 0!                'find the row norms of A()
  732.    FOR col% = lo TO up
  733.       rownorm(row%) = rownorm(row%) + ABS(A(row%, col%))
  734.    NEXT col%
  735.    IF rownorm(row%) = 0! THEN        'if any rownorm is zero, the matrix
  736.       continue = 0                   'is singular, set error, exit and do
  737.       ERROR 199                      'not continue
  738.    END IF
  739. NEXT row%
  740. FOR pvt% = lo TO (up - 1)
  741. 'Find best available pivot
  742.    max! = 0!                         'checks all values in rows and columns not
  743.    FOR row% = pvt% TO up             'already used for pivoting and finds the
  744.       r% = rpvt(row%)                'number largest in absolute value relative
  745.       FOR col% = pvt% TO up          'to its row norm
  746.          c% = cpvt(col%)
  747.          temp! = ABS(A(r%, c%)) / rownorm(r%)
  748.          IF temp! > max! THEN
  749.             max! = temp!
  750.             bestrow% = row%          'save the position of new max!
  751.             bestcol% = col%
  752.          END IF
  753.       NEXT col%
  754.    NEXT row%
  755.    IF max! = 0! THEN                 'if no nonzero number is found, A is
  756.       continue = 0                   'singular, send back error, do not continue
  757.       ERROR 199
  758.    ELSEIF pvt% > 1 THEN              'check if drop in pivots is too much
  759.       IF max! < (seps! * oldmax!) THEN errcode% = 199
  760.    END IF
  761.    oldmax! = max!
  762.    IF rpvt(pvt%) <> rpvt(bestrow%) THEN
  763.       count = count + 1                    'if a row or column pivot is
  764.       SWAP rpvt(pvt%), rpvt(bestrow%)      'necessary, count it and permute
  765.    END IF                                  'rpvt or cpvt. Note: the rows and
  766.    IF cpvt(pvt%) <> cpvt(bestcol%) THEN    'columns are not actually switched,
  767.       count = count + 1                    'only the order in which they are
  768.       SWAP cpvt(pvt%), cpvt(bestcol%)      'used.
  769.    END IF
  770. 'Eliminate all values below the pivot
  771.    rp% = rpvt(pvt%)
  772.    cp% = cpvt(pvt%)
  773.    FOR row% = (pvt% + 1) TO up
  774.       r% = rpvt(row%)
  775.       A(r%, cp%) = -A(r%, cp%) / A(rp%, cp%)  'save multipliers
  776.       FOR col% = (pvt% + 1) TO up
  777.          c% = cpvt(col%)                      'complete row operations
  778.          A(r%, c%) = A(r%, c%) + A(r%, cp%) * A(rp%, c%)
  779.       NEXT col%
  780.    NEXT row%
  781. NEXT pvt%
  782. IF A(rpvt(up), cpvt(up)) = 0! THEN
  783.    continue = 0                      'if last pivot is zero or pivot drop is
  784.    ERROR 199                         'too large, A is singular, send back error
  785. ELSEIF (ABS(A(rpvt(up), cpvt(up))) / rownorm(rpvt(up))) < (seps! * oldmax!) THEN
  786.    errcode% = 199                    'if pivot is not identically zero then
  787. END IF                               'continue remains TRUE
  788. IF errcode% THEN ERROR errcode%
  789. sluexit:
  790. matluS% = errcode%
  791. EXIT FUNCTION
  792. sluerr:
  793.    errcode% = ERR
  794.    IF errcode% < 199 THEN continue = 0
  795.    RESUME sluexit
  796. END FUNCTION
  797.  
  798. '=======================MatMultC%===================================
  799. 'MatMultC% multiplies two currency type matrices and places the
  800. 'product in a result matrix
  801. '
  802. 'Parameters: matrices Alpha,Beta,Gamma
  803. '
  804. 'Returns: Gamma() = Alpha() * Beta()
  805. '===================================================================
  806. FUNCTION MatMultC% (Alpha() AS CURRENCY, Beta() AS CURRENCY, Gamma() AS CURRENCY)
  807. ON LOCAL ERROR GOTO cmulterr: MatMultC% = 0
  808. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN
  809.    ERROR 197                   'check inside dimensions
  810. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN
  811.    ERROR 195                   'check dimensions of result matrix
  812. END IF
  813. 'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)
  814. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)
  815.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)
  816.       Gamma(row%, col%) = 0@
  817.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  818.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)
  819.       NEXT inside%
  820.    NEXT col%
  821. NEXT row%
  822. cmultexit:
  823. EXIT FUNCTION
  824. cmulterr:
  825.    MatMultC% = (ERR + 5) MOD 200 - 5
  826.    RESUME cmultexit
  827. END FUNCTION
  828.  
  829. '=======================MatMultD%===================================
  830. 'MatMultD% multiplies two double precision matrices and places the
  831. 'product in a result matrix
  832. '
  833. 'Parameters: matrices Alpha,Beta,Gamma
  834. '
  835. 'Returns: Gamma() = Alpha() * Beta()
  836. '===================================================================
  837. FUNCTION MatMultD% (Alpha() AS DOUBLE, Beta() AS DOUBLE, Gamma() AS DOUBLE)
  838. ON LOCAL ERROR GOTO dmulterr: MatMultD% = 0
  839. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN
  840.    ERROR 197                   'check inside dimensions
  841. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN
  842.    ERROR 195                   'check dimensions of result matrix
  843. END IF
  844. 'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)
  845. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)
  846.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)
  847.       Gamma(row%, col%) = 0#
  848.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  849.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)
  850.       NEXT inside%
  851.    NEXT col%
  852. NEXT row%
  853. dmultexit:
  854. EXIT FUNCTION
  855. dmulterr:
  856.    MatMultD% = (ERR + 5) MOD 200 - 5
  857.    RESUME dmultexit
  858. END FUNCTION
  859.  
  860. '=======================MatMultI%===================================
  861. 'MatMultI% multiplies two integer matrices and places the product in
  862. 'a result matrix
  863. '
  864. 'Parameters: matrices Alpha,Beta,Gamma
  865. '
  866. 'Returns: Gamma() = Alpha() * Beta()
  867. '===================================================================
  868. FUNCTION MatMultI% (Alpha() AS INTEGER, Beta() AS INTEGER, Gamma() AS INTEGER)
  869. ON LOCAL ERROR GOTO imulterr: MatMultI% = 0
  870. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN
  871.    ERROR 197                   'check inside dimensions
  872. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN
  873.    ERROR 195                   'check dimensions of result matrix
  874. END IF
  875. 'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)
  876. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)
  877.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)
  878.       Gamma(row%, col%) = 0
  879.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  880.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)
  881.       NEXT inside%
  882.    NEXT col%
  883. NEXT row%
  884. imultexit:
  885. EXIT FUNCTION
  886. imulterr:
  887.    MatMultI% = (ERR + 5) MOD 200 - 5
  888.    RESUME imultexit
  889. END FUNCTION
  890.  
  891. '=======================MatMultL%===================================
  892. 'MatMultL% multiplies two long integer matrices and places the product
  893. 'in a result matrix
  894. '
  895. 'Parameters: matrices Alpha,Beta,Gamma
  896. '
  897. 'Returns: Gamma() = Alpha() * Beta()
  898. '===================================================================
  899. FUNCTION MatMultL% (Alpha() AS LONG, Beta() AS LONG, Gamma() AS LONG)
  900. ON LOCAL ERROR GOTO lmulterr: MatMultL% = 0
  901. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN
  902.    ERROR 197                   'check inside dimensions
  903. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN
  904.    ERROR 195                   'check dimensions of result matrix
  905. END IF
  906. 'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)
  907. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)
  908.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)
  909.       Gamma(row%, col%) = 0&
  910.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  911.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)
  912.       NEXT inside%
  913.    NEXT col%
  914. NEXT row%
  915. lmultexit:
  916. EXIT FUNCTION
  917. lmulterr:
  918.    MatMultL% = (ERR + 5) MOD 200 - 5
  919.    RESUME lmultexit
  920. END FUNCTION
  921.  
  922. '=======================MatMultS%===================================
  923. 'MatMultS% multiplies two single precision matrices and places the
  924. 'product in a result matrix
  925. '
  926. 'Parameters: matrices Alpha,Beta,Gamma
  927. '
  928. 'Returns: Gamma() = Alpha() * Beta()
  929. '===================================================================
  930. FUNCTION MatMultS% (Alpha() AS SINGLE, Beta() AS SINGLE, Gamma() AS SINGLE)
  931. ON LOCAL ERROR GOTO smulterr: MatMultS% = 0
  932. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN
  933.    ERROR 197                   'check inside dimensions
  934. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN
  935.    ERROR 195                   'check dimensions of result matrix
  936. END IF
  937. 'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)
  938. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)
  939.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)
  940.       Gamma(row%, col%) = 0!
  941.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  942.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)
  943.       NEXT inside%
  944.    NEXT col%
  945. NEXT row%
  946. smultexit:
  947. EXIT FUNCTION
  948. smulterr:
  949.    MatMultS% = (ERR + 5) MOD 200 - 5
  950.    RESUME smultexit
  951. END FUNCTION
  952.  
  953. '========================MatSEqnC%==================================
  954. 'MatSEqnC% solves a system of n linear equations, Ax=b, and puts the
  955. 'answer in b. A is first put in LU form by matluC%, then matbsC is called
  956. 'to solve the system.  matrices A,b are currency type.
  957. '
  958. 'Parameters: A(n x n) contains coefficient matrix, b(N) contains the right side
  959. '
  960. 'Returns: A in LU form, solution in b
  961. '===================================================================
  962. FUNCTION MatSEqnC% (A() AS CURRENCY, b() AS CURRENCY)
  963. ON LOCAL ERROR GOTO cseqnerr: errcode% = 0
  964. lo = LBOUND(A, 1)
  965. up = UBOUND(A, 1)
  966. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  967. 'duplicate A(), b() in temporary double precision matrices Tmp(), btmp()
  968. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE
  969. DIM x(lo TO up) AS DOUBLE, btmp(lo TO up) AS DOUBLE
  970. FOR row% = lo TO up
  971.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)
  972.       Tmp(row%, col%) = CDBL(A(row%, col%))
  973.    NEXT col%
  974. NEXT row%
  975. errcode% = matluD%(Tmp())                   'Get LU matrix
  976. IF NOT continue THEN ERROR errcode%
  977. 'check dimensions of b, make double precision copy if ok.
  978. IF (lo <> LBOUND(b)) OR (up <> UBOUND(b)) THEN ERROR 197
  979. FOR row% = lo TO up
  980.    btmp(row%) = CDBL(b(row%))
  981. NEXT row%
  982. bserrcode% = matbsD%(Tmp(), btmp(), x())    'Backsolve system
  983. IF bserrcode% THEN ERROR bserrcode%
  984. FOR row% = lo TO up
  985.    b(row%) = CCUR(x(row%))                  'Put solution in b for return
  986. NEXT row%
  987. IF errcode% THEN ERROR errcode%
  988. cseqnexit:
  989. ERASE Tmp, btmp, x, rpvt, cpvt
  990. MatSEqnC% = errcode%
  991. EXIT FUNCTION
  992. cseqnerr:
  993.    errcode% = (ERR + 5) MOD 200 - 5
  994.    RESUME cseqnexit
  995. END FUNCTION
  996.  
  997. '========================MatSEqnD%==================================
  998. 'MatSEqnD% solves a system of n linear equations, Ax=b, and puts the
  999. 'answer in b. A is first put in LU form by matluD%, then matbsD is called
  1000. 'to solve the system.  matrices A,b are double precision.
  1001. '
  1002. 'Parameters: A(n x n) contains coefficient matrix, b(N) contains the right side
  1003. '
  1004. 'Returns: A in LU form, solution in b
  1005. '===================================================================
  1006. FUNCTION MatSEqnD% (A() AS DOUBLE, b() AS DOUBLE)
  1007. ON LOCAL ERROR GOTO dseqnerr: errcode% = 0
  1008. lo = LBOUND(A, 1)
  1009. up = UBOUND(A, 1)
  1010. DIM x(lo TO up) AS DOUBLE
  1011. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  1012. errcode% = matluD%(A())                      'Get LU matrix
  1013. IF NOT continue THEN ERROR errcode%
  1014. 'check dimensions of b
  1015. IF (lo <> LBOUND(b)) OR (up <> UBOUND(b)) THEN ERROR 197
  1016. bserrcode% = matbsD%(A(), b(), x())          'Backsolve system
  1017. IF bserrcode% THEN ERROR bserrcode%
  1018. FOR row% = lo TO up
  1019.    b(row%) = x(row%)                         'Put solution in b for return
  1020. NEXT row%
  1021. IF errcode% THEN ERROR errcode%
  1022. dseqnexit:
  1023. ERASE x, rpvt, cpvt
  1024. MatSEqnD% = errcode%
  1025. EXIT FUNCTION
  1026. dseqnerr:
  1027.    errcode% = (ERR + 5) MOD 200 - 5
  1028.    RESUME dseqnexit
  1029. END FUNCTION
  1030.  
  1031. '========================MatSEqnS%==================================
  1032. 'MatSEqnS% solves a system of n linear equations, Ax=b, and puts the
  1033. 'answer in b. A is first put in LU form by matluS%, then matbsS is called
  1034. 'to solve the system.  matrices A,b are single precision.
  1035. '
  1036. 'Parameters: A(n x n) contains coefficient matrix, b(N) contains the right side
  1037. '
  1038. 'Returns: A in LU form, solution in b
  1039. '===================================================================
  1040. FUNCTION MatSEqnS% (A() AS SINGLE, b() AS SINGLE)
  1041. ON LOCAL ERROR GOTO sseqnerr: errcode% = 0
  1042. lo = LBOUND(A, 1)
  1043. up = UBOUND(A, 1)
  1044. DIM x(lo TO up) AS SINGLE
  1045. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER
  1046. errcode% = matluS%(A())                      'Get LU matrix
  1047. IF NOT continue THEN ERROR errcode%
  1048. 'check dimensions of b
  1049. IF (lo <> LBOUND(b)) OR (up <> UBOUND(b)) THEN ERROR 197
  1050. bserrcode% = matbsS%(A(), b(), x())          'Backsolve system
  1051. IF bserrcode% THEN ERROR bserrcode%
  1052. FOR row% = lo TO up
  1053.    b(row%) = x(row%)                         'Put solution in b for return
  1054. NEXT row%
  1055. IF errcode% THEN ERROR errcode%
  1056. sseqnexit:
  1057. ERASE x, rpvt, cpvt
  1058. MatSEqnS% = errcode%
  1059. EXIT FUNCTION
  1060. sseqnerr:
  1061.    errcode% = (ERR + 5) MOD 200 - 5
  1062.    RESUME sseqnexit
  1063. END FUNCTION
  1064.  
  1065. '=======================MatSubC%====================================
  1066. 'MatSubC% takes the difference of two currency type matrices and
  1067. 'places the result in the first.
  1068. '
  1069. 'Params: matrices Alpha,Beta
  1070. '
  1071. 'Returns: Alpha=Alpha-Beta
  1072. '===================================================================
  1073. FUNCTION MatSubC% (Alpha() AS CURRENCY, Beta() AS CURRENCY)
  1074. ON LOCAL ERROR GOTO csuberr: MatSubC% = 0
  1075. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  1076. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  1077. 'loop through and subtract elements
  1078. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  1079.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  1080.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)
  1081.    NEXT col%
  1082. NEXT row%
  1083. csubexit:
  1084. EXIT FUNCTION
  1085. csuberr:
  1086.    MatSubC% = (ERR + 5) MOD 200 - 5
  1087.    RESUME csubexit:
  1088. END FUNCTION
  1089.  
  1090. '=======================MatSubD%====================================
  1091. 'MatSubD% takes the difference of two double precision matrices and
  1092. 'places the result in the first.
  1093. '
  1094. 'Parameters: matrices Alpha,Beta
  1095. '
  1096. 'Returns: Alpha() = Alpha() - Beta()
  1097. '===================================================================
  1098. FUNCTION MatSubD% (Alpha() AS DOUBLE, Beta() AS DOUBLE)
  1099. ON LOCAL ERROR GOTO dsuberr: MatSubD% = 0
  1100. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  1101. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  1102. 'loop through and subtract elements
  1103. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  1104.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  1105.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)
  1106.    NEXT col%
  1107. NEXT row%
  1108. dsubexit:
  1109. EXIT FUNCTION
  1110. dsuberr:
  1111.    MatSubD% = (ERR + 5) MOD 200 - 5
  1112.    RESUME dsubexit:
  1113. END FUNCTION
  1114.  
  1115. '=======================MatSubI%====================================
  1116. 'MatSubI% takes the difference of two integer matrices and places the
  1117. 'result in the first.
  1118. '
  1119. 'Parameters: matrices Alpha,Beta
  1120. '
  1121. 'Returns: Alpha() = Alpha() - Beta()
  1122. '===================================================================
  1123. FUNCTION MatSubI% (Alpha() AS INTEGER, Beta() AS INTEGER)
  1124. ON LOCAL ERROR GOTO isuberr: MatSubI% = 0
  1125. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  1126. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  1127. 'loop through and subtract elements
  1128. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  1129.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  1130.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)
  1131.    NEXT col%
  1132. NEXT row%
  1133. isubexit:
  1134. EXIT FUNCTION
  1135. isuberr:
  1136.    MatSubI% = (ERR + 5) MOD 200 - 5
  1137.    RESUME isubexit:
  1138. END FUNCTION
  1139.  
  1140. '=======================MatSubL%====================================
  1141. 'MatSubL% takes the difference of two long integer matrices and places
  1142. 'the result in the first.
  1143. '
  1144. 'Parameters: matrices Alpha,Beta
  1145. '
  1146. 'Returns: Alpha() = Alpha() - Beta()
  1147. '===================================================================
  1148. FUNCTION MatSubL% (Alpha() AS LONG, Beta() AS LONG)
  1149. ON LOCAL ERROR GOTO lsuberr: MatSubL% = 0
  1150. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  1151. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  1152. 'loop through and subtract elements
  1153. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  1154.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  1155.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)
  1156.    NEXT col%
  1157. NEXT row%
  1158. lsubexit:
  1159. EXIT FUNCTION
  1160. lsuberr:
  1161.    MatSubL% = (ERR + 5) MOD 200 - 5
  1162.    RESUME lsubexit:
  1163. END FUNCTION
  1164.  
  1165. '=======================MatSubS%====================================
  1166. 'MatSubS% takes the difference of two single precision matrices and
  1167. 'places the result in the first.
  1168. '
  1169. 'Parameters: matrices Alpha,Beta
  1170. '
  1171. 'Returns: Alpha() = Alpha() - Beta()
  1172. '===================================================================
  1173. FUNCTION MatSubS% (Alpha() AS SINGLE, Beta() AS SINGLE)
  1174. ON LOCAL ERROR GOTO ssuberr: MatSubS% = 0
  1175. 'check if Alpha, Beta have same dimensions if not, exit and send back error
  1176. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196
  1177. 'loop through and subtract elements
  1178. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)
  1179.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)
  1180.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)
  1181.    NEXT col%
  1182. NEXT row%
  1183. ssubexit:
  1184. EXIT FUNCTION
  1185. ssuberr:
  1186.    MatSubS% = (ERR + 5) MOD 200 - 5
  1187.    RESUME ssubexit:
  1188. END FUNCTION
  1189.  
  1190.