From: jasa Date: 2002-01-25T20:31:55+09:00 Subject: Problem with arrays of arrays (matrices) copying Hi, I would like to report a problem while working with arrays of arrays (matrices) in Ruby 1.6.5, in Windows 98SE (PragProg installer 1.6.5-2). I also tried the code in Ruby 1.6.6, compiled with gcc (I think it is 2.95.3) in a Linux Slackware 8.0 box. The results were exactly the same. The data in the example is a bit large, sorry. But, perhaps, there is something happening with the 'internals' of array manipulations (duplication of data, garbage collection?). Here it goes. I have one global matrix '$mat' and I want to reorder the columns and lines of it. I make a duplicate, twice, in matrix '$temp' and I reorder the lines and columns from there. I know the algorithm I use is not optimal, but that is not the issue B-). It works OK with reordering lines, but has problems with reordering columns. The problem I report has to do with matrix copying. It has also to do with the method 'Object.dup'. I solved the problem, as I will show, but I don't know why. Sorry, but I never tried to hack the Ruby source, and I don't know where or what to look for... Here goes the code and outputs: ************* Code: *************** ............................ # # Code for reodering lines. Index 0 (zero) is not used # either in the arrays or the matrices # # newLineOrder is an array with the reordering of lines newLineOrder = [0,5,1,3,2,4] # newColOrder is an array with the reordering of columns newColOrder = [0,1,5,3,2,4] # Reordering lines. This swaps the 'line-pointers'... Works OK! $temp = $mat.dup # DUPLICATE! for i in (1..dim) # dim is the dimension of the matrix. $mat[i] = $temp[newLineOrder[i]] end ************* END Code: *************** This the swapped matrix (only shown filled elements). It worked OK. #---- Matrix $mat after swap lines ---- OK HERE! (1,1) +1 (2,1) +g_r1 (2,2) -g_r1 (2,5) +1 (3,3) +((+c1)/h) (3,4) -1 (4,1) -g_r1 (4,2) +g_r1 (4,4) +1 (5,2) +1 (5,3) -1 (5,4) +((-l1)/h) This worked as expected! Now the code for swapping columns, following the data in the newColOrder[....] array: ************* Code: *************** # Swapping cols.... $temp = $mat.dup # MUST DUPLICATE! # It was confirmed here that '$temp' is equal to '$mat' after this .dup for i in (1..dim) # 'RESETS' or 'CLEARS' the line! # # $mat[i] = [] # ****** WHEN THIS IS UNCOMMENTED WORKS WELL!!!! **** # for j in (1..dim) $mat[i][j] = $temp[i][newColOrder[j]] end end ************* END Code: *************** The result of the above code is: ---- Matrix mat ---- (1,1) +1 (2,1) +g_r1 (2,2) +1 (2,4) +1 (2,5) +1 (3,3) +((+c1)/h) (4,1) -g_r1 (5,3) -1 Some data is lost! In the last 2 columns, I think. However, after RESETTING or CLEARING each matrix line before reordering with copying, (see the comment in the code above), with the instruction: $mat[i] = [] the following CORRECT column reordered matrix is obtained! ---- Matrix mat ---- (1,1) +1 (2,1) +g_r1 (2,2) +1 (2,4) -g_r1 (3,3) +((+c1)/h) (3,5) -1 (4,1) -g_r1 (4,4) +g_r1 (4,5) +1 (5,3) -1 (5,4) +1 (5,5) +((-l1)/h) Any pointers on this behavior? Is this the consequence of a Ruby feature, or can it be some kind of bug? I think that dup really duplicates the structures, and as the iterators span all the indices of the matrix when copying, it should work OK... As I said, the problem was solved by clearing the line, but I don't understand why... Thanks in advance! Best regards J. Augusto