## freeBASIC Error?

General FreeBASIC programming questions.
toml_12953
Posts: 27
Joined: Jul 07, 2005 12:37
Location: Malone, NY
Contact:

### freeBASIC Error?

The following program calculates the determinant of a matrix. In freeBASIC, the exe file crashes. I have -exx and -qb set. Could it be a stack overflow? I don't see a way to increase the stack size in FB. How would you do that?

DECLARE FUNCTION DET(a())
LET N=3
DIM a(N,N)
FOR r=1 TO N
FOR c=1 TO N
NEXT c
NEXT r

DATA 4,5,-7,2,9,3,-6,12,5

PRINT DET(a())

SLEEP

END

'
' Calculate determinate using recursive
' expansion by minors.
'
FUNCTION DET(a())

LET n=UBOUND(a,1)
DIM m(n,n)

IF n = 2 THEN
LET d = a(1,1)*a(2,2) - a(2,1)*a(1,2)
ELSE
LET d = 0
FOR j1 = 1 TO n
' create minor
FOR i = 2 TO n
LET j2 = 1
FOR j = 1 TO n
IF j <> j1 THEN
LET m(i-1,j2) = a(i,j)
LET j2=j2+1
END IF
NEXT j
NEXT i
' calculate determinant
LET d = d + (-1.0)^(1 + j1)*a(1,j1)*DET(m())
NEXT j1
END IF

DET = d

END FUNCTION
Posts: 360
Joined: Jun 07, 2005 20:59
Location: england, somewhere around the middle
Contact:
Try the -t command line option, for future reference http://www.freebasic.net/wiki/wikka.php ... tPgCompOpt is the page to see for compiler options :)

Also, the forum has a feature to keep code separate from the rest of the text and make it easier on the eye, it's the Code button just under the subject box, click it once, paste your code and click it again.
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:
This is a stack overflow, but I think it means your program is not working right.

Code: Select all

`Dim Shared recursionDeclare Function DET(a()) Let N=3 Dim a(N,N) For r=1 To N   For c=1 To N     Read a(r,c)   Next c Next r Data 4,5,-7,2,9,3,-6,12,5 Print DET(a()) Sleep End ' ' Calculate determinate using recursive ' expansion by minors. ' Function DET(a())   recursion += 1  Print recursion,    Let n=Ubound(a,1)   Dim m(n,n)    If n = 2 Then     Let d = a(1,1)*a(2,2) - a(2,1)*a(1,2)   Else     Let d = 0     For j1 = 1 To n       ' create minor       For i = 2 To n         Let j2 = 1         For j = 1 To n           If j <> j1 Then             Let m(i-1,j2) = a(i,j)             Let j2=j2+1           End If         Next j       Next i       ' calculate determinant       Let d = d + (-1.0)^(1 + j1)*a(1,j1)*DET(m())     Next j1   End If     DET = d  recursion -= 1End Function`

It looks to me like the Function is recursively called over 5,000 times before crashing (although I don't know what math you are attempting here). ;-)
Posts: 360
Joined: Jun 07, 2005 20:59
Location: england, somewhere around the middle
Contact:
It seems like the arrays might have caught you with some bounds stuff, if
n = ubound(a()) - 1
and
for j1 = 0 to n (instead of 1 to n)

then I no longer get a segfault, however, testing it with what i think was the matrix

[1,4,7]
[2,5,8]
[3,6,9]

It gives me an answer of -3, whereas by hand I got 0, however, I'm not sure that I entered the matrix correctly and I could also naturally have made a mistake by hand, I'm not so great with the 3x3 matrices :)

Also, do you mind if I make this code work in -lang fb ?

edit: actually, that answer of -3 might be due to some bounds stuff, too, I've played a bit with your code before I got it working, but basically if you adjust your algorithm so that a() is assumed to go from a(0,0) and the upper bound being ubound-1 (i think) then it will work (i think)

also, I notice you allow unsquare matrices, are the determinants of these defined?
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA
After translating the C source from here, for the specified matrix I get 370, in only 3 recursions. I’m not sure that the code is right and I did not attempt to check the 370 manually.

Code: Select all

`'================================================================================dim shared as integer rcntfunction Determinant( byval a as double ptr ptr, byval n as integer ) as double  dim as integer i,j,j1,j2              '' general loop and matrix subscripts  dim as double det                     '' init determinant  dim as double ptr ptr m               '' pointer to pointers to implement 2d                                        '' square array  rcnt += 1  if n < 1 then                         '' error condition, should never get here    print "error"  elseif n = 1 then    det = a                       '' should not get here  elseif n = 2 then                     '' basic 2X2 sub-matrix determinate                                        '' definition. When n==2, this ends the                                        '' recursion series    det = a * a - a * a  else                                  '' recursion continues, solve next sub-                                        '' matrix                                        '' solve the next minor by building a                                        '' sub matrix    det = 0                             '' initialize determinant of sub-matrix    for j1 = 0 to n-1                   '' for each column in sub-matrix      m = callocate((n-1)*sizeof(double ptr)) '' get space for the pointer list      for i = 0 to n-2        m[i] = callocate((n-1)* sizeof(double))                    ''  i  first malloc                    ''  m -> +  +  +  +   space for 4 pointers                    ''       |  |  |  |          j  second malloc                    ''       |  |  |  +-> _ _ _  pointers to                    ''       |  |  +----> _ _ _  and memory for                    ''       |  +-------> _ a _  4 doubles                    ''       +----------> _ _ _                     ''                    ''                   a                    ''  build sub-matrix with minor elements excluded      next i      for i = 1 to n-1        j2 = 0                            '' start at first sum-matrix column                                          '' position        for j = 0 to n-1                  '' loop to copy source matrix less                                          '' one column          if j = j1 then continue for     '' don't copy the minor column element          m[i-1][j2] = a[i][j]            '' copy source element into new sub-                                          ''  matrix                                          '' i-1 because new sub-matrix is one                                          '' row (and column) smaller with                                          '' excluded minors          j2+=1                           '' move to next sub-matrix column                                          '' position        next j      next i                                          '' sum x raised to y power                                          '' recursively get determinant of                                          '' next sub-matrix which is now one                                          '' row & column smaller      det += -1.0 ^ (1.0 + j1 + 1.0) * a[j1] * Determinant(m,n-1)      for i = 0 to n-2        deallocate m[i]                   '' free the storage allocated to                                          '' to this minor's set of pointers      next i      deallocate m                        '' free the storage for the original                                          '' pointer to pointer    next j1  end if  return detend function'' Start of implicit main.dim as integer n = 3dim as double ptr p(0 to n-1)dim as double a(0 to n-1,0 to n-1)for r as integer = 0 to n-1  for c as integer = 0 to n-1    read a(r,c)  nextnextfor i as integer = 0 to n-1  p(i) = @a(i,0)nextprint Determinant(@p(0),n)print rcntsleependdata 4,5,-7,2,9,3,-6,12,5`

When I do stuff like this I can’t help but think how strange it is that some people complain about the C features that have been incorporated into FreeBASIC.
toml_12953
Posts: 27
Joined: Jul 07, 2005 12:37
Location: Malone, NY
Contact:

### FB Bug?

Thanks for all the helpful replies! The problem *was* a stack overflow. I added -t 5000 to compiler options and an OPTION BASE 1 to the beginning of the program. I would have thought -exx would have caught the stack error. The answer to the matrix as given is 0 which was an unfortunate result since that could also be the result of a faulty program. If you change the first number from 1 to 12,
like so:

[12,4,7]
[2,5,8]
[3,6,9]

the answer is -33 which is correct.

As for the C examples: That's exactly why I don't like C. All that referencing and dereferencing and getting space for pointers, etc. You have to think more about how the computer works than concentrating on the problem to be solved!
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:
KristopherWindsor wrote:This is a stack overflow, but I think it means your program is not working right.

Code: Select all

`Dim Shared recursionDeclare Function DET(a()) Let N=3 Dim a(N,N) For r=1 To N   For c=1 To N     Read a(r,c)   Next c Next r Data 4,5,-7,2,9,3,-6,12,5 Print DET(a()) Sleep End ' ' Calculate determinate using recursive ' expansion by minors. ' Function DET(a())   recursion += 1  Print recursion,    Let n=Ubound(a,1)   Dim m(n,n)    If n = 2 Then     Let d = a(1,1)*a(2,2) - a(2,1)*a(1,2)   Else     Let d = 0     For j1 = 1 To n       ' create minor       For i = 2 To n         Let j2 = 1         For j = 1 To n           If j <> j1 Then             Let m(i-1,j2) = a(i,j)             Let j2=j2+1           End If         Next j       Next i       ' calculate determinant       Let d = d + (-1.0)^(1 + j1)*a(1,j1)*DET(m())     Next j1   End If     DET = d  recursion -= 1End Function`

It looks to me like the Function is recursively called over 5,000 times before crashing (although I don't know what math you are attempting here). ;-)

He's probably trying to find a solution to a series of equations.

IE:

Code: Select all

`x = Dx/Dy = Dy/Dz = Dz/D`

Where D is the determinant. Dx, Dy and Dz are calculated in the same manner.

Doing this using the Gauss Jordan Row reduction method is a bit messy to code. Trust me I coded a row reduction solver and coding it sucked.

Code: Select all

`#include <stdio.h>#include <conio.h>#include <math.h> int main(void){//table for storing coeeficients//matrix[row][col]float matrix;//declare variablesint row, col;float rowmul,rowadd,eadd,recip;clrscr();//temporary value storagefloat input=0;//first eqputs("enter coeeficients for 1st eq ax + by + cz = d:");printf("a ");scanf("%f", &input);   //get value from keyboardmatrix = input;            //set tableprintf("b ");scanf("%f", &input);matrix = input;printf("c ");scanf("%f", &input);matrix = input;printf("d ");scanf("%f", &input);matrix = input;//row 2puts("enter coeeficients for 2nd eq ax + by + cz = d:");printf("a ");scanf("%f", &input);matrix = input;printf("b ");scanf("%f", &input);matrix = input;printf("c ");scanf("%f", &input);matrix = input;printf("d ");scanf("%f", &input);matrix = input;//row3puts("enter coeeficients for 3rd eq ax + by + cz = d:");printf("a ");scanf("%f", &input);matrix = input;printf("b ");scanf("%f", &input);matrix = input;printf("c ");scanf("%f", &input);matrix = input;printf("d ");scanf("%f", &input);matrix = input;//print original matrixprintf( "\n");printf( "Original matrix \n");for (row = 0; row < 3; row++){   for (col = 0; col <4; col++)   {      printf( " %8.0f",matrix[row][col]);   }   printf( " \n");}//suspend until enter is pressedgetchar();getchar();//clear screen for outputclrscr();//print the coeff in equation formprintf( "\n");printf( "3 variable linear equation: \n");for (row = 0; row < 3; row++){   printf( "%2.0fx + %2.0fy + %2.0fz = %2.0f ",matrix[row],matrix[row]   ,matrix[row],matrix[row]);   printf( " \n");}//print augmented matrixprintf( "\n");printf( "augmented matrix: \n");for (row = 0; row < 3; row++){   for (col = 0; col <4; col++)   {        printf( " %8.0f",matrix[row][col]);    }    printf( " \n");}//gaussian row - reduction algo//eliminate all first element//of all rows except first rowfor (row=0; row<2; ++row){   rowadd = -matrix[row + 1][ 0];   for (col = 0; col <4; ++col)   {        eadd = rowadd * matrix[col];        matrix[row+1][col] += eadd;   }}   int colcount = 0;   //what column are we in now?for (row = 0; row<2; ++row){   //set current row and current column to 1   // by multiplying by its inverse   //checking for divide by zero error   if (matrix[row][colcount] != 0)     rowmul = (float)1.0/matrix[row][colcount];   else     rowmul = 0;   //multiply all the column by the reciprocal   for (col=0; col<4; ++col)     matrix[row][col] *= rowmul;   //eliminate current row, current col(set to zero)   //by adding its inverse   rowadd = -matrix[row+1][colcount];   for (col=0; col<4; ++col)   {     eadd = rowadd * matrix[row][col];     matrix[row+1][col] += eadd;   }   //set next row, next col to 1 by multiplying by   //reciprocal   //also check for zero divisor   if (matrix[row+1][colcount+1] != 0)     recip = (float)1.0/matrix[row+1][colcount+1];   else     recip = 0;   for (col=0; col<4; ++col)     matrix[row+1][col] *= recip;   //increment column counter   colcount++;}  //print the processed matrixprintf( "\n");printf( "Triangular matrix: \n");for (row=0; row<3; row++){   for (col = 0; col < 4; col++)     printf(" %8.0f", matrix[row][col]);   printf("\n");}//calculate and print solutionsfloat x, y, z;z = matrix;y = matrix + -(matrix*z);x = matrix+ -(matrix*y)+ -(matrix*z);printf("\n");printf("Solution: \n");printf( "x = %2.0f \n", x);printf( "y = %2.0f \n", y);printf( "z = %2.0f \n", z);printf("\n");printf("Press enter to exit...");getchar();getchar();getchar();return 0;}    //end main`
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA
For the code from the first post, compiled with v18.2b for Windows and -lang qb and -t 5000, with an option base 1 statement and using:

data 12,4,7,2,5,8,3,6,9

Dr Watson is still showing:

Exception number: c00000fd (stack overflow)

Code: Select all

`'====================================================================option base 1'===================================================================='' This will work, but only for 3x3.function D3()  dim as integer a1,b1,c1,a2,b2,c2,a3,b3,c3  read a1  read b1  read c1  read a2  read b2  read c2  read a3  read b3  read c3  D3 = a1*b2*c3+b1*c2*a3+c1*a2*b3-a3*b2*c1-b3*c2*a1-c3*a2*b1end function'====================================================================' Calculate determinate using recursive' expansion by minors.'FUNCTION DET(a())  LET n=UBOUND(a,1)  DIM m(n,n)  IF n = 2 THEN    LET d = a(1,1)*a(2,2) - a(2,1)*a(1,2)  ELSE    LET d = 0    FOR j1 = 1 TO n      ' create minor      FOR i = 2 TO n        LET j2 = 1        FOR j = 1 TO n          IF j <> j1 THEN            LET m(i-1,j2) = a(i,j)            LET j2=j2+1          END IF        NEXT j      NEXT i      ' calculate determinant      LET d = d + (-1.0)^(1 + j1)*a(1,j1)*DET(m())    NEXT j1  END IF  DET = dEND FUNCTION'===================================================================='' Start of implicit main.print D3()printsleepLET N=3DIM a(N,N)FOR r=1 TO N  FOR c=1 TO N    READ a(r,c)  NEXT cNEXT rPRINT DET(a()), rsleepend'data 4,5,-7,2,9,3,-6,12,5'data 4,5,-7,2,9,3,-6,12,5data 12,4,7,2,5,8,3,6,9data 12,4,7,2,5,8,3,6,9`