0

let's suppose that we have a simmetric matrix.

 A=
    1 2 3
    2 6 4
    3 4 5

now since it's simmetric we don't need to store memorize all the numbers in it. Let's assume to put 0 in the cells of the left lower triangle.

B = 
    1 2 3
    0 6 4
    0 0 5

if i want to access the the content of a 0 element of B all i need to do is invert row and col of the interested cell :

if(i>j) val += L[j][i]    // ex: B[1][0] is stored in B[0][1]

(let's suppose the goal is to sum all the non-memorized elements)

at this point we are only using the upper right triangle, but we are not actually saving memory, because the unused elements are still allocated with 0 value.

one way to save memory is to use a vector of vectors :

vector<vector<int>> C;

and resize each row accordingly.

C=
  1 2 3
  6 4
  5

By doing this tough, we cannot use the swap trick anymore, because as you may notice the empty elements are now in the bottom right triangle of the matrix.

the unallocated values are then:

D=
   x x x
   x x 2
   x 3 4

in this case the elements we are interested in can be found with this if condition:

if(j >= size - i)

now the problem is to identify the correct content of the 0 elements. In other words:

if(j >= size - i) ans += L[?][?]

so for example if i'm at i=1 j=2 i should not access to the element [1][2] but instead to [0][2] = 2 ( and so on [2][1] -> [0][2] = 3, [2][2] -> [1][1] = 4).

how is it possible to achieve it ?

darkpirate
  • 712
  • 3
  • 10
  • 27

2 Answers2

0

You particular question can be solved by storing the lower-left triangle and discarding the upper-right triangle:

1
2 6
3 4 5

The indexing operation can be implemented as:

int operator()(int r, int c) const { return r >= c ? L[r][c] : L[c][r]; }

If you really want to store upper-right triangle of the matrix in shifted way as you propose (see C), then you can access matrix elements as:

int operator()(int r, int c) const { return c >= r ? L[r][c-r] : L[c][r-c]; }

However, if you really want to have some profit from your compression, I'd suggest packing the whole triangle in a single one-dimensional vector. Having vector of vectors instead adds quite an overhead...

stgatilov
  • 5,333
  • 31
  • 54
  • problem is,i already start ( for legacy issues ) with a matrix formed as (B) that i need to compress. the unidimentional idea is good, but the problem still remains :( – darkpirate Jul 19 '15 at 18:46
  • @darkpirate why not convert the matrix in form B to the lower-triangular part? – stgatilov Jul 19 '15 at 18:48
  • @darkpirate I have added code to get (r,c)-th element of the original matrix from the storage format you want. – stgatilov Jul 19 '15 at 18:54
0

To store such triangular arrays in a compressed linear vector, I am using the following class.

#define ogf_array_check(index, data_size) assert(index < data_size)
#define ogf_assert(b) assert(b)
   /**
     * A 2d array of values aij where only the cells such 
     * that j <= i are represented.
     */
    template <class T> class TriangularArray {
    public:
        typedef TriangularArray<T> thisclass ;

        TriangularArray(int size) : size_(size), data_size_(size * (size + 1) / 2) {
            data_ = new T[data_size_] ;
        }
        ~TriangularArray() { delete[] data_; data_ = nil ; }

        int size() const { return size_ ; }
        int data_size() const { return data_size_ ; }

        /**
         * index0 denotes the line, and index1 the column,
         * note that index1 should be less-than or equal to
         * index0.
         */
        T& operator()(int index0, int index1) {
            ogf_array_check(index0, size_) ;
            ogf_array_check(index1, size_) ;
#ifdef OGF_ARRAY_BOUND_CHECK
            ogf_assert(index1 <= index0) ;
#endif
            int offset = index0 * (index0 + 1) / 2 ;
            return data_[offset + index1] ;
        }

        /**
         * index0 denotes the line, and index1 the column,
         * note that index1 should be lerr or equal to
         * index0.
         */
        const T& operator()(int index0, int index1) const {
            ogf_array_check(index0, size_) ;
            ogf_array_check(index1, size_) ;
#ifdef OGF_ARRAY_BOUND_CHECK
            ogf_assert(index1 <= index0) ;
#endif
            int offset = index0 * (index0 + 1) / 2 ;
            return data_[offset + index1] ;
        }

        void set_all(const T& value) {
            for(int i=0; i<data_size_; i++) {
                data_[i] = value ;
            }
        }

        T& from_linear_index(int index) {
            ogf_array_check(index, data_size_) ;
            return data_[index] ;
        }

        const T& from_linear_index(int index) const {
            ogf_array_check(index, data_size_) ;
            return data_[index] ;
        }

        T* data() const { return data_ ; }

    private:
        T* data_ ;
        int size_ ;
        int data_size_ ;

    private:
        TriangularArray(const thisclass& rhs) ;
        thisclass& operator=(const thisclass& rhs) ;
    } ;
BrunoLevy
  • 2,495
  • 17
  • 30