Embarrassingly, there is yet another bug.
 while sp.colptr[col+1]<i
should be
 while sp.colptr[col+1]<=i
(Arrg... where is the unsend/edit button)
In case someone ever, copy-pastes this. The (currently) correct version is:

function AtrA(sp::SparseMatrixCSC)
    res = zeros(eltype(sp),sp.n,sp.n)
    col = 1
    @inbounds for i=1:length(sp.nzval)
        while sp.colptr[col+1]<=i
            col+= 1
        end
        col2 = 1
        @inbounds for j in 1:length(sp.nzval)
            if sp.rowval[j] != sp.rowval[i]
                continue
            end
            while j>=sp.colptr[col2+1]
                col2+= 1
            end
            res[col,col2] += sp.nzval[i]*sp.nzval[j]
        end
    end
    res
end

On Wednesday, November 18, 2015 at 4:18:37 AM UTC+2, Dan wrote:
>
> It works, but it is slow (compared to `full(A'*A)`)
>
> On Wednesday, November 18, 2015 at 3:56:31 AM UTC+2, Dan wrote:
>>
>> And finally, getting rid of debug print.
>>
>> function AtrA(sp::SparseMatrixCSC)
>>     res = zeros(eltype(sp),sp.n,sp.n)
>>     col = 1
>>     @inbounds for i=1:length(sp.nzval)
>>         while sp.colptr[col+1]<i
>>             col+= 1
>>         end
>>         col2 = 1
>>         @inbounds for j in 1:length(sp.nzval)
>>             if sp.rowval[j] != sp.rowval[i]
>>                 continue
>>             end
>>             while j>=sp.colptr[col2+1]
>>                 col2+= 1
>>             end
>>             res[col,col2] += sp.nzval[i]*sp.nzval[j]
>>         end
>>     end
>>     res
>> end
>>
>>
>>
>>
>> On Wednesday, November 18, 2015 at 3:54:56 AM UTC+2, Dan wrote:
>>>
>>> Oops... a bug (which showed itself when matrix was sparser than my 
>>> previous tests):
>>> [when columns where completely empty, the first `if` should have been a 
>>> `while`]
>>>
>>> function AtrA(sp::SparseMatrixCSC)
>>>     res = zeros(eltype(sp),sp.n,sp.n)
>>>     col = 1
>>>     @inbounds for i=1:length(sp.nzval)
>>>         while sp.colptr[col+1]<i
>>>             col+= 1
>>>         end
>>>         col2 = 1
>>>         @inbounds for j in 1:length(sp.nzval)
>>>             if sp.rowval[j] != sp.rowval[i]
>>>                 continue
>>>             end
>>>             while j>=sp.colptr[col2+1]
>>>                 col2+= 1
>>>             end
>>>             @show col,col2,sp.nzval[i],sp.nzval[j]
>>>             res[col,col2] += sp.nzval[i]*sp.nzval[j]
>>>         end
>>>     end
>>>     res
>>> end
>>>
>>>
>>>
>>>
>>> On Wednesday, November 18, 2015 at 3:35:30 AM UTC+2, Dan wrote:
>>>>
>>>> This is an O(nnz(A)^2) implementation. But, benchmarks will determine 
>>>> the best solution.
>>>>
>>>> function AtrA(sp::SparseMatrixCSC)
>>>>     res = zeros(eltype(sp),sp.n,sp.n)
>>>>     col = 1
>>>>     @inbounds for i=1:length(sp.nzval)
>>>>         if sp.colptr[col+1]==i
>>>>             col+= 1
>>>>         end
>>>>         col2 = 1
>>>>         @inbounds for j in 1:length(sp.nzval)
>>>>             if sp.rowval[j] != sp.rowval[i]
>>>>                 continue
>>>>             end
>>>>             while j>=sp.colptr[col2+1]
>>>>                 col2+= 1
>>>>             end
>>>>             res[col,col2] += sp.nzval[i]*sp.nzval[j]
>>>>         end
>>>>     end
>>>>     res
>>>> end
>>>>
>>>>
>>>>
>>>>
>>>> On Wednesday, November 18, 2015 at 2:30:14 AM UTC+2, Dan wrote:
>>>>>
>>>>> Well, its not as simple as that because of everything being sparse 
>>>>> (adding columns is not just a loop over sum). Actually, it would be 
>>>>> interesting to see a clever solution. 
>>>>>
>>>>> On Wednesday, November 18, 2015 at 2:14:39 AM UTC+2, Dan wrote:
>>>>>>
>>>>>> the columns of A'A when A is sparse are just sparse linear 
>>>>>> combinations of columns of A. the coefficients being stored in the 
>>>>>> column-based sparse matrix representation (internally a vector of 
>>>>>> coefficients with pointers to new-column indices). so simply generating 
>>>>>> column by column with a for loop should be as-quick-as-it-gets without 
>>>>>> GPUing or some Fourier trickery.
>>>>>> did you already consider this? (i can try and make this description 
>>>>>> into code)
>>>>>>
>>>>>> On Tuesday, November 17, 2015 at 10:26:21 PM UTC+2, Douglas Bates 
>>>>>> wrote:
>>>>>>>
>>>>>>> More careful reading of the spmatmul function in 
>>>>>>> base/sparse/linalg.jl provided a method directly downdates the dense 
>>>>>>> square 
>>>>>>> matrix C (i.e. does not form a sparse A'A then downdate) but I still 
>>>>>>> need 
>>>>>>> to form a transpose.  If anyone knows of a fast way of forming A'A 
>>>>>>> without 
>>>>>>> creating the transpose I would be happy to hear of it.
>>>>>>>
>>>>>>

Reply via email to