PDA

View Full Version : Problems with Arrays In For/Next Loop



peralta_mike
17-05-2011, 00:37
Hello, I am having problems with arrays in a For/Next loop.

Seems like I cannot have the following statement:
C(I,J)=C(I,J) + something

For example MAT1.BAS below works OK but
MAT2.BAS (listed below MAT1.BAS) does not work.

Problem area (for MAT2.BAS) is in bold red.

'============== MAT1.BAS THINBASIC SCRIPT ===============
'MAT1.BAS MAY 16, 2011
USES "CONSOLE"
DIM I,J AS LONG
DIM A(2,2) AS DOUBLE
A(1,1)=RND(1,10)
A(1,2)=RND(1,10)
A(2,1)=RND(1,10)
A(2,2)=RND(1,10)
PRINTL "MATRIX A:"
FOR I=1 TO 2
FOR J=1 TO 2 : PRINT A(I,J) & " " : NEXT J
PRINTL " "
NEXT I
DIM B() AS DOUBLE
MAT_INV(A,B)
PRINTL "MATRIX B:"
FOR I=1 TO 2
FOR J=1 TO 2 : PRINT B(I,J) & " " : NEXT J
PRINTL " "
NEXT I
DIM C() AS DOUBLE
MAT_MULT(A,B,C)
PRINTL "MATRIX C:"
FOR I=1 TO 2
FOR J=1 TO 2 : PRINT C(I,J) & " " : NEXT J
PRINTL " "
NEXT I
PRINTL "Press Any Key To Continue"
CONSOLE_WAITKEY
'====================================================
FUNCTION MAT_INV(BYREF A() AS DOUBLE,BYREF B() AS DOUBLE) AS DOUBLE
DIM NROW,NCOL,I,J,K,L,M,N AS LONG
NROW=UBOUND(A,1) : NCOL=UBOUND(A,2)
DIM C(NROW,2*NCOL)
M=NROW
N=2*M

' --- Form Extended Matrix C ---
FOR I=1 TO M
FOR J=1 TO M
C(I,J+M)=A(I,J)
IF I=J THEN
C(I,J)=1
ELSE
C(I,J)=0
END IF
NEXT J
NEXT I
DIM TERM,BIG,TEMPVAL,PIV,CONST2,CVAL AS DOUBLE
' --- Perform Gauss-Jordan Reduction Of Matrix C ---
FOR I=1 TO M-1
' -- Determine which row has the largest magnitude --
BIG=0
FOR K=I TO M
TERM=ABS( C(K,I+M) )
IF TERM>BIG THEN
BIG=TERM
L=K
END IF
NEXT K
IF BIG=0 THEN
PRINTL "Singular Matrix"
DELAY(3)
RETURN
END IF

IF I<>L THEN
' -- Exchange rows so that the largest magnitude is the pivot --
FOR J=1 TO N
TEMPVAL=C(I,J)
C(I,J)=C(L,J)
C(L,J)=TEMPVAL
NEXT J
END IF
' -- Pivotal Reduction --
PIV=C(I,I+M)
IF PIV<>0 THEN
FOR J=I+1 TO M
CONST2=C(J,I+M)/PIV
FOR K=1 TO N
' THIS WORKS OK:
CVAL=C(J,K)
C(J,K)=CVAL-CONST2*C(I,K)
' C(J,K)=C(J,K)-CONST2*C(I,K)
NEXT K
NEXT J
ELSE
PRINTL "Singular Matrix"
CONSOLE_WAITKEY
RETURN
END IF
NEXT I
' ----------------
' --- Perform Back Substitution ---
FOR I=M TO 2 STEP -1
PIV=C(I,I+M)
IF PIV<>0 THEN
FOR J=1 TO I-1
CONST2=C(J,I+M)/PIV
FOR K=1 TO N
CVAL=C(J,K)
C(J,K)=CVAL-CONST2*C(I,K)
NEXT K
NEXT J
ELSE
PRINTL "Singular Matrix"
CONSOLE_WAITKEY
RETURN
END IF
NEXT I
' --- Scale to get ones in diagonal on right half of matrix C ---
FOR I=1 TO M
CONST2=C(I,I+M)
C(I,I+M)=1
FOR J=1 TO M
CVAL=C(I,J)
C(I,J)=CVAL/CONST2
NEXT J
NEXT I
' -- Form & Assign Values To Matrix B --
REDIM B(M,M)
FOR I=1 TO M
FOR J=1 TO M
B(I,J)=C(I,J)
NEXT J
NEXT I
END FUNCTION

FUNCTION MAT_MULT(BYREF A() AS DOUBLE,BYREF B() AS DOUBLE,BYREF C() AS DOUBLE) AS DOUBLE
DIM NROWA,NCOLA,NROWB,NCOLB,I,J,K AS LONG
NROWA=UBOUND(A,1) : NCOLA=UBOUND(A,2)
NROWB=UBOUND(B,1) : NCOLB=UBOUND(B,2)
REDIM C(NROWA,NCOLB)
FOR I=1 TO NROWA
FOR J=1 TO NCOLB
C(I,J)=0.0
FOR K=1 TO NROWB
C(I,J)=C(I,J)+A(I,K)*B(K,J)
NEXT K
NEXT J
NEXT I
END FUNCTION
' ===================== END OF MAT1.BAS ================


'================== MAT2.BAS THINBASIC SCRIPT =============
'MAT2.BAS MAY 16, 2011
USES "CONSOLE"
DIM I,J AS LONG
DIM A(2,2) AS DOUBLE
A(1,1)=RND(1,10)
A(1,2)=RND(1,10)
A(2,1)=RND(1,10)
A(2,2)=RND(1,10)
PRINTL "MATRIX A:"
FOR I=1 TO 2
FOR J=1 TO 2 : PRINT A(I,J) & " " : NEXT J
PRINTL " "
NEXT I
DIM B() AS DOUBLE
MAT_INV(A,B)
PRINTL "MATRIX B:"
FOR I=1 TO 2
FOR J=1 TO 2 : PRINT B(I,J) & " " : NEXT J
PRINTL " "
NEXT I
DIM C() AS DOUBLE
MAT_MULT(A,B,C)
PRINTL "MATRIX C:"
FOR I=1 TO 2
FOR J=1 TO 2 : PRINT C(I,J) & " " : NEXT J
PRINTL " "
NEXT I
PRINTL "Press Any Key To Continue"
CONSOLE_WAITKEY
'=================================== END OF SCRIPT ==================================
FUNCTION MAT_INV(BYREF A() AS DOUBLE,BYREF B() AS DOUBLE) AS DOUBLE
DIM NROW,NCOL,I,J,K,L,M,N AS LONG
NROW=UBOUND(A,1) : NCOL=UBOUND(A,2)
DIM C(NROW,2*NCOL)
M=NROW
N=2*M

' --- Form Extended Matrix C ---
FOR I=1 TO M
FOR J=1 TO M
C(I,J+M)=A(I,J)
IF I=J THEN
C(I,J)=1
ELSE
C(I,J)=0
END IF
NEXT J
NEXT I
DIM TERM,BIG,TEMPVAL,PIV,CONST2,CVAL AS DOUBLE
' --- Perform Gauss-Jordan Reduction Of Matrix C ---
FOR I=1 TO M-1
' -- Determine which row has the largest magnitude --
BIG=0
FOR K=I TO M
TERM=ABS( C(K,I+M) )
IF TERM>BIG THEN
BIG=TERM
L=K
END IF
NEXT K
IF BIG=0 THEN
PRINTL "Singular Matrix"
DELAY(3)
RETURN
END IF

IF I<>L THEN
' -- Exchange rows so that the largest magnitude is the pivot --
FOR J=1 TO N
TEMPVAL=C(I,J)
C(I,J)=C(L,J)
C(L,J)=TEMPVAL
NEXT J
END IF
' -- Pivotal Reduction --
PIV=C(I,I+M)
IF PIV<>0 THEN
FOR J=I+1 TO M
CONST2=C(J,I+M)/PIV
FOR K=1 TO N
' CVAL=C(J,K)
' C(J,K)=CVAL-CONST2*C(I,K)
' THIS DOES NOT WORK
C(J,K)=C(J,K)-CONST2*C(I,K)
NEXT K
NEXT J
ELSE
PRINTL "Singular Matrix"
CONSOLE_WAITKEY
RETURN
END IF
NEXT I
' ----------------
' --- Perform Back Substitution ---
FOR I=M TO 2 STEP -1
PIV=C(I,I+M)
IF PIV<>0 THEN
FOR J=1 TO I-1
CONST2=C(J,I+M)/PIV
FOR K=1 TO N
CVAL=C(J,K)
C(J,K)=CVAL-CONST2*C(I,K)
NEXT K
NEXT J
ELSE
PRINTL "Singular Matrix"
CONSOLE_WAITKEY
RETURN
END IF
NEXT I
' --- Scale to get ones in diagonal on right half of matrix C ---
FOR I=1 TO M
CONST2=C(I,I+M)
C(I,I+M)=1
FOR J=1 TO M
CVAL=C(I,J)
C(I,J)=CVAL/CONST2
NEXT J
NEXT I
' -- Form & Assign Values To Matrix B --
REDIM B(M,M)
FOR I=1 TO M
FOR J=1 TO M
B(I,J)=C(I,J)
NEXT J
NEXT I
END FUNCTION

FUNCTION MAT_MULT(BYREF A() AS DOUBLE,BYREF B() AS DOUBLE,BYREF C() AS DOUBLE) AS DOUBLE
DIM NROWA,NCOLA,NROWB,NCOLB,I,J,K AS LONG
NROWA=UBOUND(A,1) : NCOLA=UBOUND(A,2)
NROWB=UBOUND(B,1) : NCOLB=UBOUND(B,2)
REDIM C(NROWA,NCOLB)
FOR I=1 TO NROWA
FOR J=1 TO NCOLB
C(I,J)=0.0
FOR K=1 TO NROWB
C(I,J)=C(I,J)+A(I,K)*B(K,J)
NEXT K
NEXT J
NEXT I
END FUNCTION
' ====================== END OF MAT2.BAS ====================

ErosOlmi
17-05-2011, 07:11
Hi Mike,

You need to indicate the type of C matrix otherwise a variable without a type is considered AS VARIANT in thinBasic and not all operations are allowed with VARIANT variables. They are usually used to store data to be passed to COM objects.

So change

Dim C(NROW, 2*NCOL)

to something

Dim C(NROW, 2*NCOL) As Double

Eros

peralta_mike
17-05-2011, 15:47
Thank Again Eros,

Declaring it as double fixed the problems.

Not declaring as double was an oversight on my part.
Normally I do declare the variable type.

Does thinBasic have (or can it be added) a "use strict" or "use warning" option
like Perl uses to catch these kinds of oversights?
[In Perl use strict would flag the declaration I had as an error.]

Thanks again.

- Mike

ErosOlmi
17-05-2011, 15:51
thinBasic block execution of undeclared variables.

Regarding undeclared type, no there is no warning or block but I will add a new feature request because it is quite important.

Thanks
Eros

ErosOlmi
17-05-2011, 15:53
Added new feature request: http://www.thinbasic.com/community/project.php?issueid=284