summaryrefslogtreecommitdiff
path: root/modules/overloading/macros/%sp_norm.sci
blob: 2b873141647e6e3a531db17b928b5e298ac2d3cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA
// Copyright (C) Scilab Enterprises - Adeline CARNIS
//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution.  The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt

function res=%sp_norm(S,flag)

    [lhs,rhs]=argn(0)
    if rhs==1 then flag=2;end //norm(S)=norm(S,2)
    [m,n]=size(S)

    if m==1|n==1 then //vector norm
        [ij,v]=spget(S);
        res=norm(v,flag);
        return
    end

    select flag
    case 1 then
        res=max(ones(1,m)*abs(S))
    case 2 then
        if m<n then
            S1=S*S'
        elseif m>n then
            S1=S'*S
        else
            S1 = S;
        end

        tol=2*%eps;
        x = sum(abs(S1),1)';
        res = norm(x);
        if res==0 then return,end
        x = x/res;res0 = 0;
        while abs(res-res0) > tol*res
            res0 = res;   Sx = S1*x;

            // Bug #10178: norm failed for some sparse matrix
            // If Sx = 0, we had "division by zero" with x/norm(x)
            // So, use to sum(abs(S).^2).^(1/2)
            if Sx == 0 then
                res = sum(abs(S).^2).^(1/2);
                return
            end
            // End Bug #10178

            res = norm(Sx);
            x = S1'*Sx;
            x = x/norm(x);
        end
        if m<>n then res=sqrt(res),end
    case %inf then
        res=max(abs(S)*ones(n,1))
    case "inf" then
        res=max(abs(S)*ones(n,1))
    case "fro" then
        [ij,v]=spget(S);
        res=sqrt(sum(abs(v.*v)))
    else
        [ij,v]=spget(S);
        res=norm(v,flag);
    end
endfunction