freeBASIC Error?

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

freeBASIC Error?

Post by toml_12953 »

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
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())

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
Hexadecimal Dude!
Posts: 360
Joined: Jun 07, 2005 20:59
Location: england, somewhere around the middle
Contact:

Post by Hexadecimal Dude! »

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:

Post by KristopherWindsor »

This is a stack overflow, but I think it means your program is not working right.

Code: Select all

Dim Shared recursion

Declare 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 -= 1
End 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). ;-)
Hexadecimal Dude!
Posts: 360
Joined: Jun 07, 2005 20:59
Location: england, somewhere around the middle
Contact:

Post by Hexadecimal Dude! »

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

Post by MichaelW »

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 rcnt

function 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[0][0]                       '' should not get here
  elseif n = 2 then                     '' basic 2X2 sub-matrix determinate
                                        '' definition. When n==2, this ends the
                                        '' recursion series

    det = a[0][0] * a[1][1] - a[1][0] * a[0][1]

  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[0][1][2][3]  first malloc
                    ''  m -> +  +  +  +   space for 4 pointers
                    ''       |  |  |  |          j  second malloc
                    ''       |  |  |  +-> _ _ _ [0] pointers to
                    ''       |  |  +----> _ _ _ [1] and memory for
                    ''       |  +-------> _ a _ [2] 4 doubles
                    ''       +----------> _ _ _ [3]
                    ''
                    ''                   a[1][2]
                    ''  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[0][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 det

end function

'' Start of implicit main.

dim as integer n = 3
dim 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)
  next
next
for i as integer = 0 to n-1
  p(i) = @a(i,0)
next

print Determinant(@p(0),n)

print rcnt

sleep
end

data 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?

Post by toml_12953 »

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:

Post by relsoft »

KristopherWindsor wrote:This is a stack overflow, but I think it means your program is not working right.

Code: Select all

Dim Shared recursion

Declare 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 -= 1
End 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/D
y = Dy/D
z = 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[3][4];

//declare variables
int row, col;
float rowmul,rowadd,eadd,recip;

clrscr();
//temporary value storage
float input=0;
//first eq
puts("enter coeeficients for 1st eq ax + by + cz = d:");
printf("a ");scanf("%f", &input);	//get value from keyboard
matrix[0][0] = input;				//set table
printf("b ");scanf("%f", &input);
matrix[0][1] = input;
printf("c ");scanf("%f", &input);
matrix[0][2] = input;
printf("d ");scanf("%f", &input);
matrix[0][3] = input;


//row 2
puts("enter coeeficients for 2nd eq ax + by + cz = d:");
printf("a ");scanf("%f", &input);
matrix[1][0] = input;
printf("b ");scanf("%f", &input);
matrix[1][1] = input;
printf("c ");scanf("%f", &input);
matrix[1][2] = input;
printf("d ");scanf("%f", &input);
matrix[1][3] = input;

//row3
puts("enter coeeficients for 3rd eq ax + by + cz = d:");
printf("a ");scanf("%f", &input);
matrix[2][0] = input;
printf("b ");scanf("%f", &input);
matrix[2][1] = input;
printf("c ");scanf("%f", &input);
matrix[2][2] = input;
printf("d ");scanf("%f", &input);
matrix[2][3] = input;


//print original matrix
printf( "\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 pressed
getchar();
getchar();
//clear screen for output
clrscr();

//print the coeff in equation form
printf( "\n");
printf( "3 variable linear equation: \n");
for (row = 0; row < 3; row++)
{
	printf( "%2.0fx + %2.0fy + %2.0fz = %2.0f ",matrix[row][0],matrix[row][1]
	,matrix[row][2],matrix[row][3]);
	printf( " \n");
}

//print augmented matrix
printf( "\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 row
for (row=0; row<2; ++row)
{
   rowadd = -matrix[row + 1][ 0];
   for (col = 0; col <4; ++col)
   {
        eadd = rowadd * matrix[0][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 matrix
printf( "\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 solutions
float x, y, z;

z = matrix[2][3];
y = matrix[1][3] + -(matrix[1][2]*z);
x = matrix[0][3]+ -(matrix[0][1]*y)+ -(matrix[0][2]*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

Post by MichaelW »

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*b1
end 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 = d

END FUNCTION

'====================================================================
'' Start of implicit main.

print D3()
print
sleep

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

PRINT DET(a()), r

sleep
end

'data 4,5,-7,2,9,3,-6,12,5
'data 4,5,-7,2,9,3,-6,12,5
data 12,4,7,2,5,8,3,6,9
data 12,4,7,2,5,8,3,6,9
Post Reply