summaryrefslogtreecommitdiff
path: root/modules/overloading/macros/%st_i_st.sci
blob: ff39000f01f6764c488ddb3bd62c2729b78dc6eb (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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA - F. Delebcque , Serge Steer
//
// 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 M=%st_i_st(varargin)

    //insert the struct varargin($-1) into the struct varargin($)
    //at position varargin(1), varargin(2),varargin(3),...
    //insert the struct varargin($-1) as the field varargin(1)
    //of the struct varargin($)

    [lhs,rhs]=argn(0)
    M=varargin($)
    N=varargin($-1)//inserted matrix
    dims=double(matrix(M.dims,1,-1));

    if type(varargin(1))==10 //addind a new field
        flds=getfield(1,M);flds=[flds,varargin(1)];
        setfield(1,flds,M);setfield($+1,N,M);
        if and(dims==[0 0]) then M.dims=int32([1 1]),end
    else   //Subscripted assignment between structures
        //build resulting struct fields
        FM=getfield(1,M);FM=FM(3:$);nFM=size(FM,"*")
        FN=getfield(1,N);FN=FN(3:$);nFN=size(FN,"*")
        FR=FM;for f=FN, if and(f<>FM) then FR=[FR,f],end,end

        Nfields=size(FR,"*")
        //computing the dimension of the result
        nd=size(dims,"*")

        olddims=dims

        reduced_index=%f
        if rhs-2>nd then  //more indices than M number of dims
            dims(nd+1:rhs-2)=1;
        elseif rhs-2<nd  then //less indices than M number of dims
            dims=[dims(1:rhs-3) prod(dims(rhs-2:$))]
            if size(find(dims>1),"*")>1 then reduced_index=%t,end
        end
        //convert N-dimensional indexes to 1-D and extend dims if necessary
        [Ndims,I]=convertindex(list(dims,double(matrix(N.dims,1,-1))),varargin(1:$-2));Ndims=matrix(Ndims,1,-1)
        if reduced_index&or(Ndims<>dims)  then error(21),end
        if or(Ndims>dims) then
            //extend the destination matrix
            I1=0
            for k=size(Ndims,"*"):-1:1
                ik1=(1:dims(k))';
                if ik1<>[] then
                    if Ndims(k)>1 then
                        if size(I1,"*")>1 then
                            I1=(Ndims(k)*I1).*.ones(ik1)+ones(I1).*.(ik1-1);
                        else
                            I1=Ndims(k)*I1+ik1-1;
                        end
                    else
                        I1=Ndims(k)*I1+ik1-1;
                    end
                end
            end
            v1=list();for k=1:prod(Ndims),v1(k)=[];end
            // create the resulting matrix
            R=mlist(["st","dims",matrix(FR,1,-1)],int32(Ndims));
            for k=1:size(FR,"*"),setfield(2+k,v1,R),end
            // populate it with M entries
            for k=1:nFM
                v2=v1;
                kf=find(FR==FM(k));
                w=getfield(k+2,M);
                if type(w)<>15 then w=list(w),end
                if type(v2)<>15 then v2=list(v2);end
                for i=1:size(I1,"*"),
                    if w<>list() then
                        v2(I1(i)+1)=w(i);
                    else
                        v2(I1(i)+1)=[];
                    end
                end
                setfield(kf+2,v2,R);
            end
        else //the dimension agree
            R=M
            //does the fields agree?
            if or(FR<>FM) then //no
                //add new fields
                setfield(1,["st","dims",FR],R)
                v1=list();for k=1:prod(Ndims),v1(k)=[];end
                for k=nFM+1:size(FR,"*")
                    setfield($+1,v1,R)
                end
            end
        end

        //insert N entries into result
        for k=1:nFN
            kf=find(FR==FN(k));
            v2=getfield(kf+2,R);
            w=getfield(k+2,N);
            if type(w)<>15 then w=list(w),end
            if type(v2)<>15 then v2=list(v2);end
            for i=1:size(I,"*"),
                if w<>list() then
                    if size(w)==1 then
                        v2(I(i))=w(1);
                    else
                        v2(I(i))=w(i);
                    end
                else
                    v2(I(i))=[];
                end
            end
            if length(v2)==1 then v2=v2(1);end
            setfield(kf+2,v2,R);
        end

        //remove trailing unitary dimensions
        if reduced_index then
            Ndims=olddims
        else
            while  Ndims($)==1 then Ndims($)=[],end
            select size(Ndims,"*")
            case 0 then
                Ndims=[1,1]
            case 1 then
                k=find(olddims<>1&olddims<>0)
                if k==[] // M was a scalar
                    if mtlb_mode() then
                        Ndims=[1,Ndims]
                    else
                        Ndims=[Ndims,1]
                    end
                else // M was a vector
                    olddims(k)=Ndims
                    Ndims=olddims;
                end
            else
                Ndims=matrix(Ndims,1,-1)
            end
        end
        R.dims=int32(Ndims)
        M=R
    end
endfunction