summaryrefslogtreecommitdiff
path: root/modules/elementary_functions/macros/logm.sci
blob: 071c4edcd595e46d4e2883164ec6e842c9725ce0 (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
69
70
71
72
73
74
75
76
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA
// Copyright (C) DIGITEO - 2011 - Allan CORNET
//
// 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 x=logm(a)
    //   logm - log(A)
    //%CALLING SEQUENCE
    //   X=logm(A)
    //%PARAMETERS
    //   A   : square hermitian or diagonalizable matrix
    //   X   : square matrix
    //%DESCRIPTION
    //computes X=logm(A), matrix log of A

    rhs = argn(2);
    if rhs <> 1 then
        error(msprintf(gettext("%s: Wrong number of input argument(s): %d expected.\n"),"logm", 1));
    end

    [m ,n] = size(a);

    if m <> n then
        error(msprintf(gettext("%s: Wrong size for input argument #%d: Square matrix expected.\n"),"logm",1));
    end

    flag = or(a<>a');
    if ~flag then
        //Hermitian matrix
        r = and(imag(a) == 0)
        [u, s] = schur(a);
        w = diag(s);
        zw = find(w == 0);
        if zw <> [] then
            w(zw) = %eps * ones(zw);
            w1 = log(w);
            w1(zw) = -%inf * ones(zw);
            warning(msprintf(gettext("%s: Log of a singular matrix.\n"),"logm"));
        else
            w1 = log(w);
        end
        x = u * diag(w1) * u';
        if r then
            if and(real(s) >= 0) then
                x = real(x);
            end
        end
    end
    if flag then
        //General matrix
        r = and(imag(a) == 0);
        a = a + 0 * %i;   //Set complex
        rmax = max(norm(a, 1), 1 / sqrt(%eps));
        [s, u, bs] = bdiag(a, rmax);
        if max(bs)>1 then
            error(msprintf(gettext("%s: Unable to diagonalize.\n"),"logm"));
            return
        end
        w = diag(s);
        zw = find(w == 0);
        if zw <> [] then
            w(zw) = %eps * ones(zw);
            w1 = log(w);
            w1(zw) = -%inf * ones(zw);
            warning(msprintf(gettext("%s: Log of a singular matrix.\n"),"logm"));
        else
            w1 = log(w);
        end
        x = (u * diag(w1)) * inv(u);
    end
endfunction