      subroutine spops
c     
c     operations on sparse matrices
c     
c     Copyright INRIA
      include '../stack.h'
      integer op
      common /mtlbc/ mmode
c     
      integer iadr,sadr
c     
      double precision sr,si,e1,powr,powi
      integer star,dstar,slash,bslash,dot,colon,quote
      integer less,great,equal
      integer insert,extrac
      integer top0
      logical isany
      integer tops,top4

*     the following boolean vars are defined to replace test on m*n == 0 or m*n == 1)
*     for sparse matrices the product m x n may leads to integer overflow.
*     (bruno dec 2004)
      logical a1_is_empty, a1_is_scalar, a2_is_empty, a2_is_scalar, 
     $        a3_is_empty, a3_is_scalar, a4_is_empty, a4_is_scalar
      
      data star/47/,dstar/62/,slash/48/
      data bslash/49/,dot/51/,colon/44/,quote/53/
      data less/59/,great/60/,equal/50/
      data insert/2/,extrac/3/
c     
      iadr(l)=l+l-1
      sadr(l)=(l/2)+1
c     
      op=fin
c     
      if (ddt .eq. 4) then
         write(buf(1:4),'(i4)') fin
         call basout(io,wte,' spops op: '//buf(1:4))
      endif
c     
      top0=top
      lw=lstk(top+1)+1
      if(op.eq.extrac) goto 70
      if(op.eq.insert) goto 80
      it2=0
      goto (04,03,02,01) rhs
      call error(39)
      return
c     
 01   il4=iadr(lstk(top))
      if(istk(il4).lt.0) il4=iadr(istk(il4+1))
      m4=istk(il4+1)
      n4=istk(il4+2)
      it4=istk(il4+3)
      if(istk(il4).eq.5) then
         nel4=istk(il4+4)
         irc4=il4+5
         l4=sadr(irc4+m4+nel4)
      elseif(istk(il4).eq.1) then
         nel4=m4*n4
         l4=sadr(il4+4)
      else
         top=top0
         fin=-fin
         return
      endif
      mn4=m4*n4   ! must not be used if arg4 is a sparse
      a4_is_empty = m4.eq.0 .or. n4.eq.0
      a4_is_scalar = (.not.a4_is_empty) .and. (m4.eq.1 .and. n4.eq.1)

      top=top-1
c     
 02   il3=iadr(lstk(top))
      if(istk(il3).lt.0) il3=iadr(istk(il3+1))
      m3=istk(il3+1)
      n3=istk(il3+2)
      it3=istk(il3+3)
      if(istk(il3).eq.5) then
         nel3=istk(il3+4)
         irc3=il3+5
         l3=sadr(irc3+m3+nel3)
      elseif(istk(il3).eq.1) then
         l3=sadr(il3+4)
         nel3=m3*n3
      else
         top=top0
         fin=-fin
         return
      endif
      mn3=m3*n3 ! must not be used if arg3 is a sparse
      a3_is_empty = m3.eq.0 .or. n3.eq.0
      a3_is_scalar = (.not.a3_is_empty) .and. (m3.eq.1 .and. n3.eq.1)

      top=top-1
c     
 03   il2=iadr(lstk(top))
      if(istk(il2).lt.0) il2=iadr(istk(il2+1))
      m2=istk(il2+1)
      n2=istk(il2+2)
      it2=istk(il2+3)
      if(istk(il2).eq.5) then
         nel2=istk(il2+4)
         irc2=il2+5
         l2=sadr(irc2+m2+nel2)
      elseif(istk(il2).eq.1) then
         l2=sadr(il2+4)
         nel2=m2*n2
      else
         top=top0
         fin=-fin
         return
      endif
      mn2=m2*n2 ! must not be used if arg2 is a sparse
      a2_is_empty = m2.eq.0 .or. n2.eq.0
      a2_is_scalar = (.not.a2_is_empty) .and. (m2.eq.1 .and. n2.eq.1)

      top=top-1
c     
 04   il1=iadr(lstk(top))
      if(istk(il1).lt.0) il1=iadr(istk(il1+1))
      m1=istk(il1+1)
      n1=istk(il1+2)
      it1=istk(il1+3)
      if(istk(il1).eq.5) then
         nel1=istk(il1+4)
         irc1=il1+5
         l1=sadr(irc1+m1+nel1)
      elseif(istk(il1).eq.1) then
         l1=sadr(il1+4)
         nel1=m1*n1
      else
         top=top0
         fin=-fin
         return
      endif
      mn1=m1*n1 ! must not be used if arg1 is a sparse
      a1_is_empty = m1.eq.0 .or. n1.eq.0
      a1_is_scalar = (.not.a1_is_empty) .and. (m1.eq.1 .and. n1.eq.1)

      top=top-1
c     
c     operations binaires et ternaires
c     --------------------------------
c     
      top=top+1
      itr=max(it1,it2)
c     
      fun = 0
c
c        cconc  extrac insert rconc
      goto(65  ,  999  ,  999   ,66) op
c     
c           :  +  -  * /  \  =          '
      goto(06,07,08,10,20,25,130,05,05,60) op+1-colon
c     
 05   if(op.eq.dstar .or. op.eq.dstar+dot) goto 30  ! case dstar+dot added (bug fix 1769)
      if(op.eq.quote+dot) goto 60
      if(op.ge.3*dot+star) goto 200
      if(op.ge.2*dot+star) goto 120
      if(op.ge.less+equal) goto 130
      if(op.ge.dot+star) goto 55
      if(op.ge.less) goto 130

 06   top=top0
      fin=-fin
      return

c     
c     addition
 07   continue

      if (a1_is_empty) then
c       []+a
         if (mmode.eq.1) then
c     .     Matlab like []+a=[]
         else
c     .     []+a=a
            call icopy(5+m2+nel2,istk(il2),1,istk(il1),1)
            l1=sadr(il1+5+m2+nel2)
            call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
            lstk(top+1)=l1+nel2*(it2+1)
            goto 999
         endif
      elseif(a2_is_empty) then
c     a+[]
         if (mmode.eq.1) then
c     .     Matlab like a+[]=[]
            istk(il1+1)=0
            istk(il1+2)=0
            istk(il1+3)=0
            lstk(top+1)=sadr(il1+4)
         else
c     .     a+[]=a
         endif
         goto 999
      endif
      if (m1 .lt. 0) then
c     eye+a
         top=top0
         fin=-fin
         return
      endif
      if (m2 .lt. 0) then
c     a+eye
         top=top0
         fin=-fin
         return
      endif

      if (a2_is_scalar .and. .not. a1_is_scalar) then
c        a+cst
         top=top0
         fin=-fin
         return
      endif
      if (a1_is_scalar .and. .not.a2_is_scalar) then
c        cst+a
         top=top0
         fin=-fin
         return
      endif
      if (m1.ne.m2 .or. n1.ne.n2) then
         call error(8)
         return
      endif

      if(istk(il1).ne.5 .or. istk(il2).ne.5) then
c     addition with a full matrix
         top=top0
         fin=-fin
         return
      endif
c     addition of 2 sparse matrices of the same size
      irc=iadr(lw)
      if(itr.eq.1) then
         nelmx=(iadr(lstk(bot))-irc-m1-10)/5
      else
         nelmx=(iadr(lstk(bot))-irc-m1-10)/3
      endif
      lc=sadr(irc+m1+nelmx)
      lw=lc+nelmx*(itr+1)
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif  
      nel=nelmx
      if(itr.eq.1) then
         call wspasp(m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $        stk(l2),stk(l2+nel2),nel2,istk(irc2),stk(lc),stk(lc+nel),
     $        nel,istk(irc),it1,it2,ierr)
      else
         call dspasp(m1,n1,stk(l1),nel1,istk(irc1),stk(l2),nel2,
     $        istk(irc2),stk(lc),nel,istk(irc),ierr)
      endif
      if(ierr.ne.0) then
         call error(17)
         return
      endif
      istk(il1+3)=itr
      istk(il1+4)=nel
      call icopy(m1+nel,istk(irc),1,istk(irc1),1)
      l1=sadr(irc1+m1+nel)
      call unsfdcopy(nel,stk(lc),1,stk(l1),1)
      if(itr.eq.1) call unsfdcopy(nel,stk(lc+nelmx),1,stk(l1+nel),1)
      lstk(top+1)=l1+nel*(itr+1)
      go to 999
c     
c     soustraction
 08   if(rhs.eq.1) then
         if(mn1.eq.0) goto 999
         call dscal(nel1*(it1+1),-1.0d+0,stk(l1),1)
         goto 999
      endif

      if (a1_is_empty) then
c        []-a
         if (mmode.eq.1) then
c     .     Matlab like []-a=[]
         else
c     .     []-a=-a
            call icopy(5+m2+nel2,istk(il2),1,istk(il1),1)
            l1=sadr(il1+5+m2+nel2)
            call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
            call dscal(nel2*(it2+1),-1.0d0,stk(l1),1)
            lstk(top+1)=l1+nel2*(it2+1)
            goto 999
         endif
      elseif(a2_is_empty) then
c         a-[]
         if (mmode.eq.1) then
c     .     Matlab like a-[]=[]
            istk(il1+1)=0
            istk(il1+2)=0
            istk(il1+3)=0
            lstk(top+1)=sadr(il1+4)
         else
c     .     a-[]=a
         endif
         goto 999
      endif
      if (m1 .lt. 0.or.m2 .lt. 0) then
c     soustraction a-eye*b
         top=top0
         fin=-fin
         return
      endif

      if (a2_is_scalar .and. .not.a1_is_scalar) then
c        a-cst
         top=top0
         fin=-fin
         return
      endif
      if (a1_is_scalar .and. .not.a2_is_scalar) then
c        cst-a
         top=top0
         fin=-fin
         return
      endif

c       check dimensions
      if (m1 .ne. m2.or.n1 .ne. n2) then
         call error(9)
         return
      endif
      if(istk(il1).ne.5.or.istk(il2).ne.5) then
c     soustraction avec une matrice non creuse
         top=top0
         fin=-fin
         return
      endif
c     soustraction de 2 matrice sparse de meme taille
      irc=iadr(lw)
      if(itr.eq.1) then
         nelmx=(iadr(lstk(bot))-irc-m1-10)/5
      else
         nelmx=(iadr(lstk(bot))-irc-m1-10)/3
      endif
      lc=sadr(irc+m1+nelmx)
      lw=lc+nelmx*(itr+1)
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif  
      nel=nelmx
      if(itr.eq.1) then
         call wspssp(m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $        stk(l2),stk(l2+nel2),nel2,istk(irc2),stk(lc),stk(lc+nel),
     $        nel,istk(irc),it1,it2,ierr)
      else
         call dspssp(m1,n1,stk(l1),nel1,istk(irc1),stk(l2),nel2,
     $        istk(irc2),stk(lc),nel,istk(irc),ierr)
      endif
      if(ierr.ne.0) then
         call error(17)
         return
      endif
      istk(il1+3)=itr
      istk(il1+4)=nel
      call icopy(m1+nel,istk(irc),1,istk(irc1),1)
      l1=sadr(irc1+m1+nel)
      call unsfdcopy(nel,stk(lc),1,stk(l1),1)
      if(itr.eq.1) call unsfdcopy(nel,stk(lc+nelmx),1,stk(l1+nel),1)
      lstk(top+1)=l1+nel*(itr+1)
      go to 999

c     multiplication
 10   continue
c$$$      if (m2*mn2 .eq. 1) go to 12
c$$$      if (mn1 .eq. 1 ) go to 13
c$$$      if (mn2 .eq. 1 ) go to 12
      if (a2_is_scalar) goto 12
      if (a1_is_scalar) goto 13
      m1=abs(m1)
      n1=abs(n1)
      m2=abs(m2)
      n2=abs(n2)
      if(a1_is_empty .or. a2_is_empty) then
         istk(il1)=1
         istk(il1+1)=0
         istk(il1+2)=0
         istk(il1+3)=0
         lstk(top+1)=sadr(il1+4)+1
         goto 999
      endif
c     matrix matrix multiplication
      if (n1 .ne. m2) then
         call error(10)
         return
      endif
      if(istk(il1).eq.1.or.istk(il2).eq.1) then
c     full x sparse or sparse x full
         lc=lw
         lw=lw+m1*n2*(itr+1)
         err=lw-lstk(bot)
         if(err.gt.0) then
            call error(17)
            return
         endif
         if(istk(il1).eq.1) then
c     full x sparse
            if(itr.eq.1) then
               call wsmsp(m1,n1,n2,stk(l1),stk(l1+m1*n1),m1,
     $              stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $              stk(lc),stk(lc+m1*n2),m1,it1,it2)
            else
               call dsmsp(m1,n1,n2,stk(l1),m1,stk(l2),nel2,
     $              istk(irc2),stk(lc),m1)
            endif
         else
c     sparse x full
            if(itr.eq.1) then
               call wspms(m1,n1,n2,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $              stk(l2),stk(l2+m2*n2),m2,stk(lc),stk(lc+m1*n2),m1,
     $              it1,it2)
            else
               call dspms(m1,n1,n2,stk(l1),nel1,istk(irc1),
     $              stk(l2),m2,stk(lc),m1)
            endif
         endif
         istk(il1)=1
         istk(il1+1)=m1
         istk(il1+2)=n2
         istk(il1+3)=itr
         l1=sadr(il1+4)
         call unsfdcopy(m1*n2*(itr+1),stk(lc),1,stk(l1),1)
         lstk(top+1)=l1+m1*n2*(itr+1)
         return   ! ici un return direct (pas de goto 999) !
      endif

*   sparse x sparse
      ib=iadr(lw)
      ic=ib+m2+1
      ixb=ic+m1+1
      lx=sadr(ixb+n2)
      lc=lx+n2*(itr+1)
      nel=(iadr(lstk(bot))-iadr(lc)-m1-10)/(1+2*(itr+1))
      irc=iadr(lc+nel*(itr+1))
      lw=sadr(irc+m1+nel)
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif
      nelc=nel
      if(itr.eq.1) then
         call wspmsp(m1,n1,n2,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $        stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $        stk(lc),stk(lc+nel),nelc,istk(irc),
     $        istk(ib),istk(ic),stk(lx),stk(lx+n2),istk(ixb),
     $        it1,it2,ierr)
      else
         call dspmsp(m1,n1,n2,stk(l1),nel1,istk(irc1),
     $        stk(l2),nel2,istk(irc2),stk(lc),nelc,istk(irc),
     $        istk(ib),istk(ic),stk(lx),istk(ixb),ierr)
      endif
      if(ierr.eq.1) then
         buf='not enough memory'
         call error(9999)
         return
      endif
      istk(il1+2)=n2
      istk(il1+3)=itr
      istk(il1+4)=nelc
      l1=sadr(il1+5+m1+nelc)
      if(lc.ge.l1) then
         call unsfdcopy(nelc,stk(lc),1,stk(l1),1)
         if(itr.eq.1) call unsfdcopy(nelc,stk(lc+nel),1,stk(l1+nelc),1)
      else
         call unsfdcopy(nelc,stk(lc),-1,stk(l1),-1)
         if(itr.eq.1) call unsfdcopy(nelc,stk(lc+nel),-1,
     $        stk(l1+nelc),-1)
      endif
      call icopy(nelc+m1,istk(irc),1,istk(il1+5),1)
      lstk(top+1)=l1+nelc*(itr+1)
      go to 999
c     
 12   continue
c     a*cst
      if(istk(il2).eq.1) then
         si = 0.0d0
         sr = stk(l2)
         if(it2.eq.1) si = stk(l2+1)
      elseif(istk(il2).eq.5) then
         if(nel2.eq.0) then
            sr = 0.0d0
            si = 0.0d0
         else
            si = 0.0d0
            sr = stk(l2)
            if(it2.eq.1) si = stk(l2+1)
         endif
      endif
      if(abs(sr)+abs(si).eq.0.0d0) then
         if(istk(il1).eq.1) then
            istk(il1+3)=0
            call dset(m1*n1,0.0d0,stk(l1),1)
            lstk(top+1)=l1+m1*n1
         else
            istk(il1+3)=0
            istk(il1+4)=0
            call iset(abs(m1),0,istk(il1+5),1)
            lstk(top+1)=sadr(il1+5+abs(m1))+1
         endif
         return
      endif
      go to 14

 13   continue
c     cst*a
      if(istk(il1).eq.1) then
         si = 0.0d0
         sr = stk(l1)
         if(it1.eq.1) si = stk(l1+1)
      elseif(istk(il1).eq.5) then
         if(nel1.eq.0) then
            sr = 0.0d0
            si = 0.0d0
         else
            si = 0.0d0
            sr = stk(l1)
            if(it1.eq.1) si = stk(l1+1)
         endif
      endif
      if(abs(sr)+abs(si).eq.0.0d0) then
         if(istk(il2).eq.1) then
            istk(il1)=1
            istk(il1+1)=m2
            istk(il1+2)=n2
            istk(il1+3)=0
            l1=sadr(il1+4)
            call dset(m2*n2,0.0d0,stk(l1),1)
            lstk(top+1)=l1+m2*n2
         else
            istk(il1)=5
            istk(il1+1)=m2
            istk(il1+2)=n2
            istk(il1+3)=0
            istk(il1+4)=0
c           call iset(iabs(m2),0,stk(il1+5),1)
c           lstk(top+1)=sadr(il1+5+abs(m2))+1
c            FD modif 
            nnnb=1+abs(m2)
            call iset(nnnb,0,istk(il1+5),1)
            lstk(top+1)=sadr(il1+5+nnnb)
         endif
         return
      endif

      if(istk(il2).eq.5) then
         call icopy(5+m2+nel2,istk(il2),1,istk(il1),1)
         l1=sadr(il1+5+m2+nel2)
         call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
      elseif(istk(il2).eq.1) then
         call icopy(4,istk(il2),1,istk(il1),1)
         l1=sadr(il1+4)
         call unsfdcopy(mn2*(it2+1),stk(l2),1,stk(l1),1)
      endif
      m1=m2
      n1=n2
      mn1=it1
      it1=it2
      it2=mn1
      mn1=mn2
      nel1=nel2
c     
 14   continue
      istk(il1+1)=m1
      istk(il1+2)=n1
      istk(il1+3)=itr
      lstk(top+1)=l1+nel1*(itr+1)
c     
      err=lstk(top+1)-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif
c     
      goto (15,16,17),it2+2*it1
c     la matrice et le scalaire sont reel
      call dscal(nel1,sr,stk(l1),1)
      lstk(top+1)=l1+nel1
      goto 999
 15   continue
c     la matrice est reelle le scalaire est complexe
      err=l1+2*nel1-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif
      call unsfdcopy(nel1,stk(l1),1,stk(l1+nel1),1)
      call dscal(nel1,sr,stk(l1),1)
      call dscal(nel1,si,stk(l1+nel1),1)
      lstk(top+1)=l1+2*nel1
      goto 999
 16   continue
c     la matrice est complexe, le scalaire est reel
      call dscal(nel1,sr,stk(l1),1)
      call dscal(nel1,sr,stk(l1+nel1),1)
      lstk(top+1)=l1+2*nel1
      goto 999
 17   continue
c     la matrice et le scalaire sont complexes
      call wscal(nel1,sr,si,stk(l1),stk(l1+nel1),1)
      lstk(top+1)=l1+2*nel1
      goto 999
c     
c      right division
 20   if (mn2 .ne. 1) then
c     right division by a matrix -->macro coded
         fin = -fin
         top = top0
         rhs = 2
         go to 999
      endif
c     right division by a scalar
      sr=stk(l2)
      si=0.0d+0
      if(it2.eq.1) si=stk(l2+1)
      e1=max(abs(sr),abs(si))
      if(e1.eq.0.0d+0) then
         call error(27)
         return
      endif
      sr=sr/e1
      si=si/e1
      e1=e1*(sr*sr+si*si)
      sr=sr/e1
      si=-si/e1
c     call multiplication with scalar inverse
      goto 14
c     
c     left division
 25   if ( .not.a1_is_scalar ) then
c     left division by a matrix -->macro coded
         top=top0
         fin=-fin
         return
      endif
c     left division by a scalar
c     invert the scalar
      if (it1.eq.0) then
         if(stk(l1).eq.0.0d0) then
            call error(27)
            return
         endif
         sr=1.0/stk(l1)
         si=0.0d+0
      else
         sr=stk(l1)
         si=stk(l1+1)
         e1=max(abs(sr),abs(si))
         if(e1.eq.0.0d+0) then
            call error(27)
            return
         endif
         sr=sr/e1
         si=si/e1
         e1=e1*(sr*sr+si*si)
         sr=sr/e1
         si=-si/e1
      endif
      if(istk(il2).eq.1) then
         call icopy(4,istk(il2),1,istk(il1),1)
         l1=sadr(il1+4)
         nel2=mn2
         call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
      else
         call icopy(5+m2+nel2,istk(il2),1,istk(il1),1)
         l1=sadr(il1+5+m2+nel2)
         call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
      endif
      m1=m2
      n1=n2
      it=it1
      it1=it2
      it2=it
      mn1=mn2
      nel1=nel2
      goto 14
*
*     power operations: sp^pow or sp.^pow 
*     (modified by Bruno jan 19 2006 to fix bug 1769)
*     
*     notes : dstar corresponds to ^
*             dstar+dot corresponds to .^
*             at the beginning of this toooooooo big subroutine the code is
*             branched here in these 2 cases.
*
 30   if (mn2 .ne. 1) then
         call error(30)
         return
      endif

*     for sp^pow with a sp square and not scalar (scalar case is faster handle
*     by the element wize power op)
      if ( op.eq.dstar .and. m1.eq.n1 .and. .not.a1_is_scalar ) goto 31

*     sp^pow is nevertheless "authorized" when sp is a vector (and done
*     as an element wize power operation)
      if ( op.eq.dstar .and. m1.ne.1 .and. n1.ne.1 ) then
         err=1
         call error(20)
         return
      endif
*     so the following concerns only element wise power
*
************end of the modif for bug 1769****************
*
      err=l1+nel1*2-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif
      if(it2.eq.0) then
         powr=stk(l2)
         if(it1.eq.0) then
            call ddpow(nel1,stk(l1),stk(l1+nel1),1,powr,err,itr)
         else
            call wdpow(nel1,stk(l1),stk(l1+nel1),1,powr,err)
         endif
      else
         powr=stk(l2)
         powi=stk(l2+1)
         if(it1.eq.0) then
            call dwpow(nel1,stk(l1),stk(l1+nel1),1,
     &           powr,powi,err)
         else
            call wwpow(nel1,stk(l1),stk(l1+nel1),1,
     &           powr,powi,err)
         endif
      endif
      if(err.eq.1) then
         call error(30)
         return
      endif
      if(err.eq.2) then
         call error(27)
         return
      endif
      istk(il1+3)=itr
      lstk(top+1)=l1+nel1*(itr+1)
      goto 999
c     
c     elevation d'une matrice carree a une puissance
 31   continue
      top=top0
      fin=-fin
      return
c     

c     operations elements a elements
 55   continue
      i1=1
      i2=1
      op = op - dot
      if(a1_is_empty .or. a2_is_empty) then
c     [].*a     a.*[]  -->[]
         istk(il1)=1
         istk(il1+1)=0
         istk(il1+2)=0
         istk(il1+3)=0
         lstk(top+1)=sadr(il1+4)+1
         goto 999
      endif
      if(a1_is_scalar .or. a2_is_scalar) then
         goto(06,07,08,10,20,25,130,05,05,60) op+1-colon
      endif
c
c     check dimensions
      if (m1.ne.m2 .or. n1.ne.n2) then
         call error(6)
         return
      endif
      if(op.eq.slash) then
         if(istk(il2).eq.1) then
            if(it2.eq.0) then
               do 56 i=0,mn1-1
                  if(stk(l2+i).eq.0.0d0) then
                     call error(27)
                     return
                  endif
                  stk(l2+i)=1.0d0/stk(l2+i)
 56            continue
            else          
               do 57 i=0,mn2-1
                  sr=stk(l2+i)
                  si=stk(l2+mn2+i)
                  e1=abs(sr)+abs(si)
                  if(e1.eq.0.0d+0) then
                     call error(27)
                     return
                  endif
                  sr=sr/e1
                  si=si/e1
                  e1=e1*(sr*sr+si*si)
                  stk(l2+i)=sr/e1
                  stk(l2+mn2+i)=-si/e1
 57            continue
            endif
         else
            top=top0
            fin=-fin
            return
         endif
      elseif(op.eq.bslash) then
         if(istk(il1).eq.1) then
            if(it1.eq.0) then
               do 58 i=0,mn1-1
                  if(stk(l1+i).eq.0.0d0) then
                     call error(27)
                     return
                  endif
                  stk(l1+i)=1.0d0/stk(l1+i)
 58            continue
            else          
               do 59 i=0,mn1-1
                  sr=stk(l1+i)
                  si=stk(l1+mn1+i)
                  e1=abs(sr)+abs(si)
                  if(e1.eq.0.0d+0) then
                     call error(27)
                     return
                  endif
                  sr=sr/e1
                  si=si/e1
                  e1=e1*(sr*sr+si*si)
                  stk(l1+i)=sr/e1
                  stk(l1+mn1+i)=-si/e1
 59            continue
            endif
         else
            top=top0
            fin=-fin
            return
         endif
      endif
      if(nel1.eq.0.or.nel2.eq.0) then
         istk(il1)=5
         istk(il1+3)=0
         istk(il1+4)=0
         call iset(m1,0,istk(il1+5),1)
         lstk(top+1)=sadr(il1+5+m1)
         return
      endif
      if(istk(il1).eq.1) then
c     full.*sparse
         nel=nel2
         if(it1.eq.0.and.it2.eq.0) then
            call dspxs(m1,n1,stk(l2),nel2,istk(irc2),stk(l1),m1,
     $           stk(l2),nel,istk(irc2),ierr)
         else
            if(it2.eq.0) then
               err=l2+2*nel2-lstk(bot)
               if(err.gt.0) then
                  call error(17)
                  return
               endif
            endif
            call wspxs(m1,n1,stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $           stk(l1),stk(l1+nel1),m1,
     $           stk(l2),stk(l2+nel2),nel,istk(irc2),ierr,it2,it1)
         endif
         istk(il1)=5
         istk(il1+3)=itr
         istk(il1+4)=nel
         l=sadr(il1+5+m1+nel)
         call icopy(m1+nel,istk(irc2),1,istk(il1+5),1)
         call unsfdcopy(nel,stk(l2),1,stk(l),1)
         if(itr.eq.1) call unsfdcopy(nel,stk(l2+nel2),1,stk(l+nel),1)
         lstk(top+1)=l+nel*(itr+1)
         return
      elseif(istk(il2).eq.1) then
c     sparse.*full
         nel=nel1
         if(it1.eq.0.and.it2.eq.0) then
            call dspxs(m1,n1,stk(l1),nel1,istk(irc1),stk(l2),m1,
     $           stk(l1),nel,istk(irc1),ierr)
         else
            lri=l1+nel1
            if(it1.eq.0) then
               lri=lw
               err=lri+nel1-lstk(bot)
               if(err.gt.0) then
                  call error(17)
                  return
               endif
            endif
            call wspxs(m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $           stk(l2),stk(l2+nel2),m1,
     $           stk(l1),stk(lri),nel,istk(irc1),ierr,it1,it2)
         endif
         istk(il1)=5
         istk(il1+3)=itr
         istk(il1+4)=nel
         l=sadr(il1+5+m1+nel)
         call icopy(m1+nel,istk(irc1),1,istk(il1+5),1)
         call unsfdcopy(nel,stk(l1),1,stk(l),1)
         if(itr.eq.1) call unsfdcopy(nel,stk(lri),1,stk(l+nel),1)
         lstk(top+1)=l+nel*(itr+1)
         return
      endif
c     sparse.*sparse
      nel=nel1
      if(it1.eq.0.and.it2.eq.0) then
         call dspxsp(m1,n1,stk(l1),nel1,istk(irc1),
     $        stk(l2),nel2,istk(irc2),stk(l1),nel,istk(irc1),ierr)
         lrr=l1

      else
         lrr=lw
         lri=lrr+min(nel1,nel2)
         err=lri+min(nel1,nel2)-lstk(bot)
         if(err.gt.0) then
            call error(17)
            return
         endif
         call wspxsp(m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $        stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $        stk(lrr),stk(lri),nel,istk(irc1),ierr,it1,it2)
      endif

      istk(il1+3)=itr
      istk(il1+4)=nel
      l=sadr(il1+5+m1+nel)
      call unsfdcopy(nel,stk(lrr),1,stk(l),1)
      if(itr.eq.1) call unsfdcopy(nel,stk(lri),1,stk(l+nel),1)
      lstk(top+1)=l+nel*(itr+1)
      return
c     
c     
c     transposition (modified by bruno)
 60   istk(il1+1)=n1
      istk(il1+2)=m1
      if(nel1.eq.0) then
         lw=sadr(il1+5+n1)
         err=lw-lstk(bot)
         if(err.gt.0) then
            call error(17)
            return
         endif
         call iset(n1,0,istk(il1+5),1)
         lstk(top+1)=lw
         goto 999
      endif
      iptr=iadr(lw)  ! for work array ptr of size n1
      irc2=iptr+n1 
      l2=sadr(irc2+n1+nel1)
      lw=l2+nel1*(it1+1) 
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif

      if (it1 .eq. 0) then
         inc = 0
      else
         inc = nel1
      endif

      call spt(m1, n1, nel1, it1, istk(iptr),
     $         stk(l1), stk(l1+inc), istk(irc1), istk(irc1+m1),
     $         stk(l2), stk(l2+inc), istk(irc2), istk(irc2+n1))

*     recopie en "top"
      call icopy(n1+nel1,istk(irc2),1,istk(irc1),1)
      l1=sadr(irc1+n1+nel1)
      call unsfdcopy(nel1*(it1+1),stk(l2),1,stk(l1),1)
      if(it1.eq.1 .and. op.ne.quote+dot) then
         call dscal(nel1,-1.0d0,stk(l1+nel1),1)  ! complexe conjugue si A' et it=1
      endif
      lstk(top+1)=l1+nel1*(it1+1)
      goto 999
c     
c     concatenation [a b]
 65   continue
      if(m1.lt.0.or.m2.lt.0) then
         call error(14)
         return
      endif
      if(m2.eq.0) then
         return
      elseif(m1.eq.0) then
         call icopy(5+m2+nel2,istk(il2),1,istk(il1),1)
         l1=sadr(il1+5+m2+nel2)
         call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
         lstk(top+1)=l1+nel2*(it2+1)
         return
      elseif(m1.ne.m2) then
         call error(5)
         return
      endif
      if(istk(il1).ne.5.or.istk(il2).ne.5) then
         top=top0
         fin=-fin
         return
      endif
c
      nelr=nel1+nel2
      istk(il1+2)=n1+n2
      istk(il1+3)=itr
      istk(il1+4)=nelr
      lr=lw
      irc=iadr(lr+nelr*(itr+1))
      lw=sadr(irc+m1+nelr)
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif
      if(itr.eq.0) then
         call dspcsp(0,m1,n1,stk(l1),nel1,istk(irc1),
     $        m2,n2,stk(l2),nel2,istk(irc2),
     $        stk(lr),nelr,istk(irc))
      else
         call wspcsp(0,m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $        m2,n2,stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $        stk(lr),stk(lr+nelr),nelr,istk(irc),it1,it2)
      endif
      call icopy(m1+nelr,istk(irc),1,istk(irc1),1)
      l1=sadr(irc1+m1+nelr)
      call unsfdcopy(nelr*(itr+1),stk(lr),1,stk(l1),1)
      lstk(top+1)=l1+nelr*(itr+1)
      return
c     
c     concatenation [a;b]
 66   continue
      if(n1.lt.0.or.n2.lt.0) then
         call error(14)
         return
      endif
      if(n2.eq.0) then
         goto 999
      elseif(n1.eq.0)then
         call icopy(5+m2+nel2,istk(il2),1,istk(il1),1)
         l1=sadr(il1+5+m2+nel2)
         call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
         lstk(top+1)=l1+nel2*(it2+1)
         goto 999
      elseif(n1.ne.n2) then
         call error(6)
         return
      endif
      if(istk(il1).ne.5.or.istk(il2).ne.5) then
         top=top0
         fin=-fin
         return
      endif


      nelr=nel1+nel2
      istk(il1+1)=m1+m2
      istk(il1+3)=itr
      istk(il1+4)=nelr
      lr=lw
      irc=iadr(lr+nelr*(itr+1))
      lw=sadr(irc+m1+m2+nelr)
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif
      if(itr.eq.0) then
         call dspcsp(1,m1,n1,stk(l1),nel1,istk(irc1),
     $        m2,n2,stk(l2),nel2,istk(irc2),
     $        stk(lr),nelr,istk(irc))
      else
         call wspcsp(1,m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $        m2,n2,stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $        stk(lr),stk(lr+nelr),nelr,istk(irc),it1,it2)
      endif
      call icopy(m1+m2+nelr,istk(irc),1,istk(irc1),1)
      l1=sadr(irc1+m1+m2+nelr)
      call unsfdcopy(nelr*(itr+1),stk(lr),1,stk(l1),1)
      lstk(top+1)=l1+nelr*(itr+1)
      goto 999
c     
c     extraction (modified by bruno)
c     
 70   continue
      if(rhs.lt.2) then
         call error(227)
         return
      endif
      if(rhs.gt.2) goto 75  ! goto extraction arg3(arg1,arg2)

c****** extraction arg2(arg1) *************************************
*
c     get arg2
      il2=iadr(lstk(top))
      if(istk(il2).lt.0) il2=iadr(istk(il2+1))
      m2=istk(il2+1)                          
      n2=istk(il2+2)
      it2=istk(il2+3)
      nel2=istk(il2+4)
      irc2=il2+5
      l2=sadr(irc2+m2+nel2)
      a2_is_empty = m2.eq.0 .or. n2.eq.0
      a2_is_scalar = (.not.a2_is_empty) .and. (m2.eq.1 .and. n2.eq.1)
      mn2=m2*n2
      top=top-1
c     get arg1
      il1=iadr(lstk(top))
      ilrs=il1
      if(istk(il1).lt.0) il1=iadr(istk(il1+1))
      m1=istk(il1+1)
      n1=istk(il1+2)
      a1_is_empty = m1.eq.0 .or. n1.eq.0
      a1_is_scalar = (.not.a1_is_empty) .and. (m1.eq.1 .and. n1.eq.1)

      if(a2_is_empty) then
c     .  arg2=[]  -> return an empty matrix []
         ilrs=iadr(lstk(top))
         istk(ilrs)=1
         istk(ilrs+1)=0
         istk(ilrs+2)=0
         istk(ilrs+3)=0
         lstk(top+1)=sadr(ilrs+4)+1
         goto 999
      elseif(m2.lt.0) then
c     .  arg2=eye
         call error(14)
         return
      elseif(m1.lt.0) then  !  case  arg2(:) => just reshape to column vector
         if(n2.eq.1) then
c     .     already a column vector
            ilrs=iadr(lstk(top))
            call icopy(5+m2+nel2,istk(il2),1,istk(ilrs),1)
            l1=sadr(ilrs+5+m2+nel2)
            call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
            lstk(top+1)=l1+nel2*(it2+1)
         else               !  n2 > 1
c     .     reshape to column vector via spmat (reshape is named matrix in scilab)
            ilrs=iadr(lstk(top))
            istk(ilrs)=5
            istk(ilrs+1)=mn2
            istk(ilrs+2)=1
            istk(ilrs+3)=it2
            istk(ilrs+4)=nel2
            irc1=ilrs+5
            l1=sadr(ilrs+5+m2*n2+nel2)

            ircr=iadr(lw)
            iw=ircr+m2*n2+nel2
** correction d'un bug
            lr=sadr(iw+3*nel2)
            lw= lr + nel2*(it2+1)
            err=lw-lstk(bot)
            if(err.gt.0) then
               call error(17)
               return 
            endif
            ! copie des valeurs de arg2
            call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(lr),1)
            if(it2.eq.0) then
*** le bug etait du au fait que  stk(l2) (remplace par stk(lr)) est remanie 
*** (via une permutation) et donc pb si arg2 est passe par reference

*** il faudrait peut utiliser spreshape maintenant
               call dspmat(m2,n2,stk(lr),nel2,istk(irc2),m2*n2
     $              ,istk(ircr),istk(iw))  
            else
               call wspmat(m2,n2,stk(lr),stk(lr+mn2),nel2,istk(irc2)
     $              ,m2*n2,istk(ircr),istk(iw)) 
            endif
            call icopy(m2*n2+nel2,istk(ircr),1,istk(irc1),1)
            call unsfdcopy(nel2*(it2+1),stk(lr),1,stk(l1),1)
            lstk(top+1)=l1+nel2*(it2+1)
         endif
         return
      endif

*** extraction  arg2(arg1)  (suite)
      call indxg(il1,mn2,ilr,mi,mx,lw,1)  ! analysis of the index vector arg1
      if(err.gt.0) return
      if(mx.gt.mn2) then
         call error(21)
         return
      endif

 72   if(mi.eq.0) then  ! case  arg2([]) => return a void matrix (type = 1)
         ilrs=iadr(lstk(top))
         istk(ilrs)=1
         istk(ilrs+1)=0
         istk(ilrs+2)=0
         istk(ilrs+3)=0
         lstk(top+1)=sadr(ilrs+4)+1
         goto 999
      endif
c     set output sizes  !  extraction  arg2(arg1)
      if ( m2 .eq. 1 ) then  ! A is a row sparse => B also (and only in this case)
         mr = 1
         nr = mi
      else                   ! A not a row sparse => B a column sparse
         mr = mi
         nr = 1
      endif

c     get memory for the result
      lptr=iadr(lw)
      irc=lptr+m2
      lw=sadr(irc+mr)
      nelrm=(2*(lstk(bot)-lw)-1)/(3+2*it2)
      if(nelrm.le.0) then
         err=lw-lstk(bot)
         call error(17)
         return
      endif
      lr=sadr(irc+mr+nelrm)
      lw=lr+nelrm*(it2+1)
      inc2 = nel2*it2
      incr = nelrm*it2

*       subroutine spextr1(A_m, A_n, A_nel, A_mnel, A_icol, A_R, A_I,
*     $                   B_m, B_n, B_nel, B_mnel, B_icol, B_R, B_I,
*     $                   it, i, ni, nel_max, ptr, ierr)

      call spextr1(m2, n2, nel2, istk(irc2), istk(irc2+m2), stk(l2), 
     $             stk(l2+inc2),
     $             mr, nr, nelr, istk(irc), istk(irc+mr), stk(lr),
     $             stk(lr+incr), 
     $             it2, istk(ilr), mi, nelrm, istk(lptr), ierr)

c     form resulting variable
      ilrs=iadr(lstk(top))
      istk(ilrs)=5
      istk(ilrs+1)=mr
      istk(ilrs+2)=nr
      istk(ilrs+3)=it2
      istk(ilrs+4)=nelr
      call icopy(mr+nelr,istk(irc),1,istk(ilrs+5),1)
      l1=sadr(ilrs+5+mr+nelr)
      call unsfdcopy(nelr,stk(lr),1,stk(l1),1)
      if(it2.eq.1)  call unsfdcopy(nelr,stk(lr+nelrm),1,stk(l1+nelr),1)
      lstk(top+1)=l1+nelr*(it2+1)
      go to 999
c     
c     arg3(arg1,arg2)
 75   if(rhs.gt.3) then
         call error(36)
         return
      endif
c     get arg3
      il3=iadr(lstk(top))
      if(istk(il3).lt.0) il3=iadr(istk(il3+1))
      m3=istk(il3+1)
      n3=istk(il3+2)
      it3=istk(il3+3)
      nel3=istk(il3+4)
      irc3=il3+5
      l3=sadr(irc3+m3+nel3)
      mn3=m3*n3
      top=top-1
c     get arg2
      il2=iadr(lstk(top))
      if(istk(il2).lt.0) il2=iadr(istk(il2+1))
      m2=istk(il2+1)
      top=top-1
c     get arg1
      il1=iadr(lstk(top))
      ilrs=il1
      if(istk(il1).lt.0) il1=iadr(istk(il1+1))
      m1=istk(il1+1)

      if(mn3.eq.0) then 
c     .  arg3=[]
         ilrs=iadr(lstk(top))
         istk(ilrs)=1
         istk(ilrs+1)=0
         istk(ilrs+2)=0
         istk(ilrs+3)=0
         lstk(top+1)=sadr(ilrs+4)+1
         goto 999
      elseif(m3.lt.0) then
c     .arg3=eye
         call error(14)
         return
      endif
c     check and convert indices variables

      call indxg(il1,m3,ili,mi,mxi,lw,11)
      if(err.gt.0) return
      if(mxi.gt.m3) then
         call error(21)
         return
      endif
      if(mi.lt.0) then
         mr=m3 ! modif bruno
      else
         mr=mi
      endif
      call indxg(il2,n3,ilj,nj,mxj,lw,11)
      if(err.gt.0) return
      if(mxj.gt.n3) then
         call error(21)
         return
      endif
      if(nj.lt.0) then
         nr=n3 ! modif bruno
      else
         nr=nj
      endif
c
 76   continue
      if(mr.eq.0 .or. nr.eq.0) then 
c     .  arg1=[] or arg2=[] 
         ilrs=iadr(lstk(top))
         istk(ilrs)=1
         istk(ilrs+1)=0
         istk(ilrs+2)=0
         istk(ilrs+3)=0
         lstk(top+1)=sadr(ilrs+4)+1
         goto 999
      endif
c     get memory for the result
      lptr=iadr(lw)    !  istk(lptr) = ptr(1)
      irc=lptr+m3+1    !  m3+1 cases pour le tableau ptr =>  istk(irc) = p(1)
      ircr = irc + nr  !  nr cases pour le tableau p de la permutation mnelr(1) = istk(ircr)
      lw=sadr(ircr+mr) !  
      nelrmax = (lstk(bot)-lw)/(1+2*(it3+1))  ! nb max possible d'elts pour la matrice resultat
      if(nelrmax.le.0) then
         err=lw-lstk(bot)
         call error(17)
         return
      endif
      lr=sadr(ircr+mr+nelrmax)
      lw=lr+nelrmax*(it3+1)

c     perform extraction
      if(it3.eq.0) then  ! les parties imaginaires (inutilisées)
         inc3 = 0        ! pointeront sur les parties réelles
         incr = 0
      else
         inc3 = nel3
         incr = nelrmax
      endif
      call spextr(m3, n3, nel3, istk(irc3), istk(irc3+m3), stk(l3),
     $            stk(l3+inc3),
     $            mr, nr, nelr, istk(ircr), istk(ircr+mr), stk(lr),
     $            stk(lr+incr),
     $            it3, istk(ili), mi, istk(ilj), nj, nelrmax, 
     $            istk(lptr), istk(irc), ierr)

*      subroutine spextr(A_m, A_n, A_nel, A_mnel, A_icol, A_R, A_I,
*     $                  B_m, B_n, B_nel, B_mnel, B_icol, B_R, B_I,
*     $                  it, i, ni, j, nj, nel_max, ptr, p, ierr)

      if(ierr .eq. -1) then  ! not enough memory
         err=1               ! valeur bidon : j'imagine qu'il faut donner 
         call error(17)      ! une idee a l'utilisateur de la mémoire manquante
         return
      endif

c     form resulting variable
      ilrs=iadr(lstk(top))
      istk(ilrs)=5
      istk(ilrs+1)=mr
      istk(ilrs+2)=nr
      istk(ilrs+3)=it3
      istk(ilrs+4)=nelr
      call icopy(mr+nelr,istk(ircr),1,istk(ilrs+5),1)
      l1=sadr(ilrs+5+mr+nelr)
      call unsfdcopy(nelr,stk(lr),1,stk(l1),1)
      if(it3.eq.1) call unsfdcopy(nelr,stk(lr+nelrmax),1,stk(l1+nelr),1)
      lstk(top+1)=l1+nelr*(it3+1)
      go to 999
c      
c     insertion
 80   continue
      if(rhs.gt.4) then
         top=top0
         fin=-fin
         return
      endif
      if(rhs.eq.4) goto 90
c     arg3(arg1)=arg2
c     get arg3      
      tops = top
      il3=iadr(lstk(top))
      if(istk(il3).lt.0) il3=iadr(istk(il3+1))
      m3=istk(il3+1)
      n3=istk(il3+2)
      it3=istk(il3+3)
      if(istk(il3).eq.5) then
         nel3=istk(il3+4)
         irc3=il3+5
         l3=sadr(irc3+m3+nel3)
      else
         top=top0
         fin=-fin
         return
      endif
      mn3=m3*n3

c     get arg2
      top=top-1
      il2=iadr(lstk(top))
      if(istk(il2).lt.0) il2=iadr(istk(il2+1))
      m2=istk(il2+1)
      n2=istk(il2+2)
      it2=istk(il2+3)
      if(istk(il2).eq.5) then
         nel2=istk(il2+4)
         irc2=il2+5
         l2=sadr(irc2+m2+nel2)
      elseif(istk(il2).eq.1) then
         l2=sadr(il2+4)
         nel2=m2*n2
      else
         top=top0
         fin=-fin
         return
      endif
      mn2=m2*n2

c     get arg1
      top=top-1
      il1=iadr(lstk(top))
      ilrs=il1
      if(istk(il1).lt.0) il1=iadr(istk(il1+1))
      if (istk(il1).eq.10.or.istk(il1).eq.15) then
         top=top0
         fin=-fin
         return
      endif
      m1=istk(il1+1)
      n1=istk(il1+2)

****************************************************************
*
*    code added by bruno to treat the case arg3(arg1)=arg2
*    with:
*       arg1 a sparse boolean matrix of the same dimension than arg3
*       arg2 is a full vector or a scalar with nel1 elements 
*
      if (istk(il1).eq.6 .and. m1.eq.m3 .and. n1.eq.n3 .and.
     $    istk(il2).eq.1 .and. (m2.eq.1 .or. n2.eq.1) ) then
         nel1 = istk(il1+4)
         a2_is_scalar = m2.eq.1 .and. n2.eq.1
         if (a2_is_scalar .or. m2*n2.eq.nel1) then
            ip = iadr(lstk(tops+1))
            if (.not. a2_is_scalar) then
               iq = ip + n1+1
               ilr = iq + nel1
            else
               iq = ip
               ilr = ip
            endif
            lr = sadr(ilr + 5 + m1)
            itr = max(it3,it2)
            nelmax = (2*(lstk(bot)-lr)-1)/(3+2*itr)
            if(nelmax .le. 0) then
               buf='not enough memory'
               call error(9999)
               return
            endif
            ilrc = ilr + 5 + m1
            lr = sadr(ilrc+nelmax)
            if (itr .eq. 0) then
               lri = lr
            else
               lri = lr + nelmax
            endif

            call spif1b(m3, n3, nel3, it3, istk(irc3), istk(irc3+m3), 
     $                  stk(l3), stk(l3+nel3), nel1, istk(il1+5), 
     $                  istk(il1+5+m1), it2, stk(l2), stk(l2+mn2),
     $                  a2_is_scalar, nelr, itr, istk(ilr+5), 
     $                  istk(ilrc), stk(lr), stk(lri), nelmax, istk(ip),
     $                  istk(iq), ierr)
            if(ierr.ne.0) then
               buf='not enough memory'
               call error(9999)
               return
            endif
*           form the resulting var
            istk(ilrs) = 5
            istk(ilrs+1) = m3
            istk(ilrs+2) = n3
            istk(ilrs+3) = itr
            istk(ilrs+4) = nelr
            call icopy(m3+nelr,istk(ilr+5),1,istk(ilrs+5),1)
            lrs = sadr(ilrs+5+m3+nelr)
            call unsfdcopy(nelr,stk(lr),1,stk(lrs),1)
            if (itr .eq. 1) then
               call unsfdcopy(nelr,stk(lri),1,stk(lrs+nelr),1)
            endif
            lstk(top+1) = lrs + (1+itr)*nelr
            go to 999
         endif
      endif
*
*   end of the case added by Bruno
*
****************************************************************

      if (m2.eq.0) then
c     .  arg3(arg1)=[] -->[]
         if(m1.eq.-1) then
c     .    arg3(:)=[] 
            istk(ilrs)=1
            istk(ilrs+1)=0
            istk(ilrs+2)=0
            istk(ilrs+3)=0
            lstk(top+1)=sadr(ilrs+4)+1
            goto 999
         elseif(m1.eq.0) then
c     .     arg3([])=[]  --> arg3
            call icopy(5+m3+nel3,istk(il3),1,istk(ilrs),1)
            l=sadr(ilrs+5+m3+nel3)
            call unsfdcopy(nel3*(it3+1),stk(l3),1,stk(l),1)
*            lstk(top+1)=l+mn3*(it3+1)
            lstk(top+1)=l+nel3*(it3+1)
            goto 999
         else
c     .     arg3(arg1)=[]
            if(istk(il1).eq.4.and.m3.eq.m1.and.n3.eq.n1) then
               if(.not.isany(il1)) then
c     .           arg3([])=[]  --> arg3
                  call icopy(5+m3+nel3,istk(il3),1,istk(ilrs),1)
                  l=sadr(ilrs+5+m3+nel3)
                  call unsfdcopy(nel3*(it3+1),stk(l3),1,stk(l),1)
*                  lstk(top+1)=l+mn3*(it3+1)  
                  lstk(top+1)=l+nel3*(it3+1)  
                  goto 999
               endif
            endif
c     .     arg3(arg1)=[] -->arg3(compl(arg1),:)
            if(m3.gt.1.and.n3.gt.1) then
c     .        call macro coded op to reshape and insert
               top=top0
               fin=-fin
               return
            else
               call indxgc(il1,mn3,ilr,mi,mx,lw)
               if(err.gt.0) return
               l2=l3
               n2=n3
               m2=m3
               mn2=m2*n2
               it2=it3
               nel2=nel3
               irc2=irc3
c     .     call extraction
               goto 72
            endif
         endif
      elseif(m2.lt.0.or.m3.lt.0) then
c     .  arg3=eye,arg2=eye
         call error(14)
         return
      elseif(m1.lt.0) then
c     .  arg3(:)=arg2 reshape arg2 according to arg3
*  CAUTION: bug if arg2 is a full matrix !
         if(mn2.eq.mn3) then
            if(m2.ne.m3) then
               top=top0
               fin=-fin
               return
            endif
            istk(ilrs)=5
            istk(ilrs+1)=m3
            istk(ilrs+2)=n3
            call icopy(2+m2+nel2,istk(il2+3),1,istk(ilrs+3),1)
            l1=sadr(ilrs+5+m2+nel2)
            call unsfdcopy(nel2*(it2+1),stk(l2),1,stk(l1),1)
            lstk(top+1)=l1+nel2*(it2+1)
            return
         elseif(mn2.eq.1) then
            istk(ilrs)=1
            istk(ilrs+1)=m3
            istk(ilrs+2)=n3
            istk(ilrs+3)=it2
            l1=sadr(ilrs+4)
            call dset(mn3,stk(l2),stk(l1),1)
            if(it2.eq.1) call dset(mn3,stk(l2+1),stk(l1+mn3),1)
            lstk(top+1)=l1+mn3*(it2+1)
            return
         else
            call error(15)
            return
         endif
      elseif(m3.gt.1.and.n3.gt.1) then
c     .  arg3(arg1)=arg2 with arg3 not a vector
         top=top0
         fin=-fin
         return
      endif


 81   call indxg(il1,mn3,ili,mi,mxi,lw,1)
      if(err.gt.0) return
      if(mi.eq.0) then
c     .  arg3([])=arg2
         if(mn2.eq.1) then
c     .  arg3([])=c  --> arg3 
            call icopy(5+m3+nel3,istk(il3),1,istk(ilrs),1)
            l=sadr(ilrs+5+m3+nel3)
            call unsfdcopy(nel3*(it3+1),stk(l3),1,stk(l),1)
*            lstk(top+1)=l+mn3*(it3+1)
            lstk(top+1)=l+nel3*(it3+1)
            goto 999
         else
            call error(15)
            return
         endif  
      endif
      if(mi.ne.mn2) then
         if(mn2.gt.1) then
            call error(15)
            return
         elseif(istk(il2).ne.1) then
            top=top0
            fin=-fin
            return
         endif
      endif
c     
      if (n3.gt.1.and.m3.gt.1) then  ! ce test est inutile puisque ce cas est traite par macro
c     .  arg3 is not a vector
         if(n2.gt.1.and.m2.gt.1) then
            call error(15)
            return
         endif
         if(mxi.gt.m3*n3) then
            call error(21)
            return
         endif
         mr=m3
         nr=n3
      elseif (n3.le.1.and.n2.le.1) then
c     .  arg3 and arg2 are  column vectors
         mr=max(m3,mxi)
         nr=max(n3,1)
      elseif (m3.le.1.and.m2.le.1) then
c     .  row vectors
         nr=max(n3,mxi)
         mr=max(m3,1)
      else
c     .  arg3 and arg2 dimensions dont agree
         call error(15)
         return
      endif

c     set output sizes
      if (m3 .gt. 1.or.m1.lt.0) then
c     .  column vector
         m=mi
         n=-1
         mr = mi
         nr = 1
      else
c     .  row vector
         m=-1
         n=mi
         nr = mi
         mr = 1
      endif
      itr=max(it2,it3)
      lptr=iadr(lw)
      irc=lptr+mr+1
      lw=sadr(irc+mr)
      nelr=(lstk(bot)-lw-1)/(1+2*(itr+1))
      if(nelr.le.0) then
         err=lw-lstk(bot)
         call error(17)
         return
      endif
      lr=sadr(irc+mr+nelr)
      lw=lr+nelr*(itr+1)
      nel=nelr
      if(istk(il2).eq.5) then
         if(itr.eq.0) then
            call dspisp(m3,n3,stk(l3),nel3,istk(irc3),
     $           istk(ili),m,istk(ili),n,
     $           m2,n2,stk(l2),nel2,istk(irc2),
     $           mr,nr,stk(lr),nelr,istk(irc),istk(lptr),ierr)
         else
            call wspisp(m3,n3,stk(l3),stk(l3+nel3),nel3,istk(irc3),
     $           istk(ili),m,istk(ili),n,
     $           m2,n2,stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $           mr,nr,stk(lr),stk(lr+nelr),nelr,istk(irc),
     $           istk(lptr),ierr,it3,it2)
         endif
      else
         if(itr.eq.0) then
            call dspis(m3,n3,stk(l3),nel3,istk(irc3),
     $           istk(ili),m,istk(ili),n,
     $           m2,n2,stk(l2),
     $           mr,nr,stk(lr),nelr,istk(irc),ierr) 
         else
            call wspis(m3,n3,stk(l3),stk(l3+nel3),nel3,istk(irc3),
     $           istk(ili),m,istk(ili),n,
     $           m2,n2,stk(l2),stk(l2+nel2),
     $           mr,nr,stk(lr),stk(lr+nelr),nelr,istk(irc),
     $           ierr,it3,it2) 
         endif
      endif
      if(ierr.ne.0) then
         buf='not enough memory'
         call error(9999)
         return
      endif
      istk(ilrs)=5
      istk(ilrs+1)=mr
      istk(ilrs+2)=nr
      istk(ilrs+3)=itr
      istk(ilrs+4)=nelr
      call icopy(mr+nelr,istk(irc),1,istk(ilrs+5),1)
      l1=sadr(ilrs+5+mr+nelr)
      call unsfdcopy(nelr,stk(lr),1,stk(l1),1)
      if(itr.eq.1) call unsfdcopy(nelr,stk(lr+nel),1,stk(l1+nelr),1)
      lstk(top+1)=l1+nelr*(itr+1)
      go to 999   ! c'est un return

 90   continue

c     **** insertion  arg4(arg1,arg2)=arg3  *****
c     (comments added by Bruno to try to understand this stuff)

c     get arg4      
      il4=iadr(lstk(top))
      top4 = top ! pour le cas en place
      if(istk(il4).lt.0) il4=iadr(istk(il4+1))
      m4=istk(il4+1)
      n4=istk(il4+2)
      it4=istk(il4+3)
      if(istk(il4).eq.5) then  ! arg4 is a sparse matrix
         nel4=istk(il4+4)
         irc4=il4+5             ! irc4 index in istk for the arrays  mnel(m4 elts) and icol(nel4 elts)
         l4=sadr(irc4+m4+nel4)  ! l4   index in stk for the coef arrays (real and complex if any)
      else                 
         top=top0          
         fin=-fin
         return
      endif
      mn4=m4*n4

c     get arg3    ! for insertion  arg4(arg1,arg2)=arg3
      top=top-1
      il3=iadr(lstk(top))
      if(istk(il3).lt.0) il3=iadr(istk(il3+1))
      m3=istk(il3+1)
      n3=istk(il3+2)
      it3=istk(il3+3)
      if(istk(il3).eq.5) then  ! arg3 is a sparse matrix
         nel3=istk(il3+4)
         irc3=il3+5            
         l3=sadr(irc3+m3+nel3)
      elseif(istk(il3).eq.1) then  !  arg3 is a full matrix
         l3=sadr(il3+4)
         nel3=m3*n3
      else
         top=top0
         fin=-fin
         return
      endif
      mn3=m3*n3

c     get arg2    ! for insertion  arg4(arg1,arg2)=arg3
      top=top-1
      il2=iadr(lstk(top))
      if(istk(il2).lt.0) il2=iadr(istk(il2+1))
      m2=istk(il2+1)

c     get arg1    ! for insertion  arg4(arg1,arg2)=arg3
      top=top-1
      il1=iadr(lstk(top))
      ilrs=il1
      if(istk(il1).lt.0) il1=iadr(istk(il1+1))
      m1=istk(il1+1)

      if (m3.eq.0) then   ! So this is the operation   arg4(arg1,arg2) = [] => all rows of
                          ! of indices arg1 and all columns of indices arg2 must be deleted. 
                          ! In the following many special cases are taken into account
                          ! this is certainly not necessary.
         if(m1.eq.-1.and.m2.eq.-1) then 
            ! this is  arg4(:,:)=[] and so arg4 becomes a empty matrix arg4 <- []
            istk(ilrs)=1
            istk(ilrs+1)=0
            istk(ilrs+2)=0
            istk(ilrs+3)=0
            lstk(top+1)=sadr(ilrs+4)+1
            goto 999      ! goto the end

         elseif(m1.eq.0.or.m2.eq.0) then
            ! this is   arg4([],arg2)=[] or  arg4(arg1,[])=[] --> arg4 is not modified
            call icopy(5+m4+nel4,istk(il4),1,istk(ilrs),1)  ! ilrs index in istk of the result
            l=sadr(ilrs+5+m4+nel4)
            call unsfdcopy(nel4*(it4+1),stk(l4),1,stk(l),1)
            lstk(top+1)=l+mn4*(it4+1)
            goto 999

         elseif(m2.eq.-1) then
            ! this is   arg3(arg1,:)=[] --> arg3(compl(arg1),:)
            call indxgc(il1,m4,ili,mi,mxi,lw)
            if(err.gt.0) return
            mr=mi
            call indxg(il2,n4,ilj,nj,mxj,lw,11)
            if(err.gt.0) return
            if(nj.lt.0) then
               nr=mxj
            else
               nr=nj
            endif
            l3=l4
            n3=n4
            m3=m4
            mn3=m3*n3
            it3=it4
            irc3=irc4
            nel3=nel4
c     .     call extraction (the result is arg3(compl(arg1),:))
            goto 76

         elseif(m1.eq.-1) then
            ! this is   arg4(:,arg2)=[] --> arg4(:,compl(arg2))
            call indxgc(il2,n4,ilj,nj,mxj,lw)
            if(err.gt.0) return
            nr=nj
            call indxg(il1,m4,ili,mi,mxi,lw,11)
            if(err.gt.0) return
            if(mi.lt.0) then
               mr=mxi
            else
               mr=mi
            endif
            l3=l4
            n3=n4
            m3=m4
            mn3=m3*n3
            it3=it4
            irc3=irc4
            nel3=nel4
c     .     call extraction (the result is arg3(:,compl(arg2)))
            goto 76
         else
            ! this is   arg4(arg1,arg2)=[] 
            lw1=lw
            call indxgc(il2,n4,ilj,nj,mxj,lw)
            if(err.gt.0) return
            nr=nj
            if(nj.eq.0) then
c     .        arg4(arg1,1:n4)=[] 
               call indxgc(il1,m4,ili,mi,mxi,lw)
               lw2=lw
               if(err.gt.0) return
               mr=mi
c     .        arg2=1:n3
               if(mi.eq.0) then
c     .           arg4(1:m4,1:n4)=[] 
                  istk(ilrs)=1
                  istk(ilrs+1)=0
                  istk(ilrs+2)=0
                  istk(ilrs+3)=0
                  lstk(top+1)=sadr(ilrs+4)+1
                  goto 999
               else
c     .           arg4(arg1,1:n4)=[] 
c     .           replace arg2 by ":"
                  il2=iadr(lw2)
                  istk(il2)=1
                  istk(il2+1)=-1
                  istk(il2+2)=-1
                  istk(il2+3)=0
c     .
                  lw=lw2+2
                  call indxg(il2,n4,ilj,nj,mxj,lw,11)
                  if(err.gt.0) return
                  if(nj.lt.0) then
                     nr=mxj
                  else
                     nr=nj
                  endif
                  l3=l4
                  n3=n4
                  m3=m4
                  it3=it4
                  mn3=m3*n3
                  irc3=irc4
                  nel3=nel4
c     .           call extraction
                  goto 76
               endif
            else
c               lw=lw1
               call indxgc(il1,m4,ili,mi,mxi,lw)
               if(err.gt.0) return
               if(mi.eq.0) then
c     .           arg4(1:m4,arg2)=[] 
                  call indxg(il1,m4,ili,mi,mxi,lw,11)
                  if(err.gt.0) return
                  if(mi.lt.0) then
                     mr=mxi
                  else
                     mr=mi
                  endif
                  l3=l4
                  n3=n4
                  m3=m4
                  it3=it4
                  mn3=m3*n3
                  irc3=irc4
                  nel3=nel4
c     .           call extraction
                  goto 76
               else
                  call error(15)
                  return
               endif
            endif
         endif

      elseif(m3.lt.0.or.m4.lt.0) then
c     .  arg3=eye , arg4=eye
         call error(14)
         return

      elseif(m1.eq.-1.and.m2.eq.-1) then
c     .  arg4(:,:)=arg3
         if(mn3.eq.mn4) then
            if(m3.ne.m4) then  ! bizarre ca on a alors A(:,:)=B qui ne change pas A
               top=top0        ! en fait on imagine plutot une erreur a indiquer
               fin=-fin
               return
c     .  reshape arg3 according to arg4  : ici on a donc des matrices de tailles identiques
c             il ne semble pas y avoir de distinctions entre sparse ou pleine pour arg3 (B)
c             ca peut expliquer le plantage ...  OUI
c             remede : cependant ce cas peut etre pris en compte par les routines generiques
c                      plutot que de le traiter dans l'interface. De plus ce n'est pas si
c                      court comme code vu qu'il faut tester les coefs de B. L'interface
c                      ne doit s'occuper que des cas triviaux et des cas d'erreurs
*
*   A signaler a Serge.
*
            elseif (istk(il3) .eq. 5) then ! ajout bruno (si arg3 est pleine le code suivant n'est pas bon)
               istk(ilrs)=5
               istk(ilrs+1)=m4
               istk(ilrs+2)=n4
               call icopy(2+m3+nel3,istk(il3+3),1,istk(ilrs+3),1)
               l1=sadr(ilrs+5+m3+nel3)
               call unsfdcopy(nel3*(it3+1),stk(l3),1,stk(l1),1)
               lstk(top+1)=l1+nel3*(it3+1)
               return
            endif
         elseif(mn3.eq.1) then   ! arg4(:,:)=arg3 avec arg3 un scalaire 
            istk(ilrs)=1         ! on change de type (matrice pleine)
            istk(ilrs+1)=m4
            istk(ilrs+2)=n4
            istk(ilrs+3)=it3
            l1=sadr(ilrs+4)
            call dset(mn4,stk(l3),stk(l1),1)
            if(it3.eq.1) call dset(mn4,stk(l3+1),stk(l1+mn4),1)
            lstk(top+1)=l1+mn4*(it3+1)
            return
         else
            call error(15)
            return
         endif
      endif

      ! insertion  arg4(arg1,arg2)=arg3 ... suite 
      call indxg(il1,m4,ili,mi,mxi,lw,11)
      if(err.gt.0) return
      if(mi.lt.0) then
         mr1=mxi   ! car indice implicite :
      else
         mr1=mi
      endif
      call indxg(il2,n4,ilj,mj,mxj,lw,11)
      if(err.gt.0) return
      if(mj.lt.0) then
         nr1=mxj   ! car indice implicite :
      else
         nr1=mj
      endif
      if(mr1.ne.m3.or.nr1.ne.n3) then
c     .  sizes of arg1 or arg2 dont agree with arg3 sizes
         if(m3*n3.eq.1) then
            if(mr1.eq.0.or.nr1.eq.0) then 
               call icopy(5+m4+nel4,istk(il4),1,istk(ilrs),1)
               l=sadr(ilrs+5+m4+nel4)
               call unsfdcopy(nel4*(it4+1),stk(l4),1,stk(l),1)
               lstk(top+1)=l+mn4*(it4+1)
               goto 999
            endif
            if(istk(il3).ne.1) then
               top=top0
               fin=-fin
               return
            endif
         else
            call error(15)
            return
         endif
      else
         if(mr1.eq.0.or.nr1.eq.0) then  ! est-ce possible ?
            call error(15)
            return
         endif
      endif
      mr=max(m4,mxi)
      nr=max(n4,mxj)
c      ! insertion  arg4(arg1,arg2)=arg3 ... suite 

      ! try if we can do insertion in place
      if (      (istk(il3).eq.1) .and. (it4.ge.it3) 
     $    .and. (mi.gt.0).and.(mj.gt.0).and.(mi.le.m4).and.(mj.le.n4)
     $    .and. (mi*mj.lt.nel4/4) ) then 
*
         lws = lw               ! sauvegarde
         lptr=iadr(lw)          ! for ptr (size m4)
         lka = lptr + m4        ! for ka  (size mi*mj)
         lw = sadr(lka+mi*mj)
         err=lw-lstk(bot)
         if (err .gt. 0) then
            call error(17)
            return
         endif
         call spifp(m4, n4, nel4, istk(irc4), istk(irc4+m4), stk(l4),
     $              stk(l4+it4*nel4), it4, istk(ili), mi, istk(ilj), mj,
     $              istk(lptr), istk(lka), it3, stk(l3), 
     $              stk(l3+mi*mj*it3), iflag)
         if (iflag .eq. 1) then ! yes insertion in place is OK (and also done by spifp)
            k=istk(iadr(lstk(top4))+2)
            top = top - 1
            call setref(k)
            goto 999
         else
            lw = lws 
         endif
      endif

      itr=max(it4,it3)
      if(istk(il3).eq.5) then  ! insertion sparse(ind_i, ind_j) = sparse matrix
         lptr=iadr(lw)    
         irc=lptr+mr+1
         lw=sadr(irc+mr)
         nelr=(lstk(bot)-lw)/(1+2*(itr+1))
         if(nelr.le.0) then
            err=lw-lstk(bot)
            call error(17)
            return
         endif
         lr=sadr(irc+mr+nelr)
         lw=lr+nelr*(itr+1)
         nel=nelr

         if(itr.eq.0) then
            call dspisp(m4,n4,stk(l4),nel4,istk(irc4),
     $           istk(ili),mi,istk(ilj),mj,
     $           m3,n3,stk(l3),nel3,istk(irc3),
     $           mr,nr,stk(lr),nelr,istk(irc),istk(lptr),ierr)
         else
            call wspisp(m4,n4,stk(l4),stk(l4+nel4),nel4,istk(irc4),
     $           istk(ili),mi,istk(ilj),mj,
     $           m3,n3,stk(l3),stk(l3+nel3),nel3,istk(irc3),
     $           mr,nr,stk(lr),stk(lr+nelr),nelr,istk(irc),
     $           istk(lptr),ierr,it4,it3)
         endif

      else  ! insertion sparse(ind_i, ind_j) = full matrix

         ipi = iadr(lw)   ! indice pour pi
         ipj = ipi + max(0,mi)  ! indice pour pj
         irc = ipj + max(0,mj)  ! indice pour C_mnel
         lw = sadr(irc + mr)    ! indice de stk à partir duquel il faut caser C_icol, C_R et C_I
         nelmax = 2*(lstk(bot)-lw)/(1+2*(itr+1))
         if(nelmax .le. 0) then
            err = lw-lstk(bot)
            call error(17)
            return
         endif
         lr = sadr(irc + mr + nelmax)
         lw = lr + nelmax*(itr + 1)

c     arg4(arg1,arg2)=arg3   A(i,j) = B
*      subroutine spif(A_m, A_n, A_nel, A_it, A_mnel, A_icol, A_R, A_I,
*     $                B_m, B_n, B_it, B_R, B_I,
*     $                C_m, C_n, C_nel, C_it, C_mnel, C_icol, C_R, C_I,
*     $                i, pi, ni, j, pj, nj, nelmax, ierr)
*
         call spif(m4,n4,nel4,it4,istk(irc4),istk(irc4+m4),
     $             stk(l4),stk(l4+it4*nel4),
     $             m3,n3,it3,stk(l3),stk(l3+it3*m3*n3),
     $             mr,nr,nelr,itr,istk(irc), istk(irc+mr), 
     $             stk(lr), stk(lr+itr*nelmax),
     $             istk(ili), istk(ipi), mi, istk(ilj), istk(ipj), mj, 
     $             nelmax, ierr) 
         nel = nelmax

      endif

      if(ierr.ne.0) then     ! methode a utiliser lorsque l'on peut difficilement
         buf='not enough memory'   ! evaluer la memoire manquante
         call error(9999)
         return
      endif
      istk(ilrs)=5
      istk(ilrs+1)=mr
      istk(ilrs+2)=nr
      istk(ilrs+3)=itr
      istk(ilrs+4)=nelr
      call icopy(mr+nelr,istk(irc),1,istk(ilrs+5),1)
      l1=sadr(ilrs+5+mr+nelr)
      call unsfdcopy(nelr,stk(lr),1,stk(l1),1)
      if(itr.eq.1) call unsfdcopy(nelr,stk(lr+nel),1,stk(l1+nelr),1)
      lstk(top+1)=l1+nelr*(itr+1)
      go to 999
c     
c     *. /. \.
 120  fin=-fin
      top=top+1
      goto 999
c     
 130  continue
      if(fin.eq.61) then
         fin=-fin
         top=top+1
         goto 999
      endif

c     comparaisons
      if(max(it1,it2).eq.1) then
         if(op.ne.equal.and.op.ne.less+great) then
            fin=-fin
            top=top0
            return
         endif
      endif
      if (a1_is_empty .and. a2_is_empty) then
         if(op.eq.equal.or.op.eq.less+great) then
            istk(il1)=4
            istk(il1+1)=1
            istk(il1+2)=1
            istk(il1+3)=1
            if(op.eq.less+great) istk(il1+3)=0
            lstk(top+1)=sadr(il1+4)
            goto 999
         else
            call error(60)
            return
         endif
      endif
      if( (a1_is_empty .or. a2_is_empty).or.
     &    (.not.a1_is_scalar .and. .not. a2_is_scalar)) then
         if(n1.ne.n2.or.m1.ne.m2) then
            if(op.eq.equal.or.op.eq.less+great) then
               istk(il1)=4
               istk(il1+1)=1
               istk(il1+2)=1
               istk(il1+3)=0
               if(op.eq.less+great) istk(il1+3)=1
               lstk(top+1)=sadr(il1+4)
               return
            else
               call error(60)
               return
            endif
         endif
      endif
c
      mr=m1
      nr=n1
      if( a1_is_scalar ) then
         mr=m2
         nr=n2
      endif
      irc=iadr(lw)
      nelmx=(iadr(lstk(bot))-irc-mr-10)
      lw=sadr(irc+mr+nelmx)
      err=lw-lstk(bot)
      if(err.gt.0) then
         call error(17)
         return
      endif  
      nel=nelmx
      if(istk(il1).eq.1) then
         if(itr.eq.1) then
            call wsosp(op,m1,n1,stk(l1),stk(l1+nel1),
     $           m2,n2,stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $           nel,istk(irc),ierr,it1,it2)
         else
            call dsosp(op,m1,n1,stk(l1),m2,n2,stk(l2),nel2,
     $           istk(irc2),nel,istk(irc),ierr)
         endif
      elseif(istk(il2).eq.1) then
         if(itr.eq.1) then
            call wspos(op,m1,n1,stk(l1),stk(l1+nel1),nel1,istk(irc1),
     $           m2,n2,stk(l2),stk(l2+nel2),
     $           nel,istk(irc),ierr,it1,it2)
         else
            call dspos(op,m1,n1,stk(l1),nel1,istk(irc1),
     $           m2,n2,stk(l2),nel,istk(irc),ierr)
         endif
      else
         if(itr.eq.1) then
            call wsposp(op,m1,n1,stk(l1),stk(l1+nel1),nel1,
     $           istk(irc1),m2,n2,stk(l2),stk(l2+nel2),nel2,istk(irc2),
     $           nel,istk(irc),ierr,it1,it2)
         else
            call dsposp(op,m1,n1,stk(l1),nel1,istk(irc1),
     $           m2,n2,stk(l2),nel2,istk(irc2),
     $           nel,istk(irc),ierr)
         endif
      endif
      if(ierr.ne.0) then
         buf='not enough memory'
         call error(9999)
         return
      endif
      istk(il1)=6
      istk(il1+1)=mr
      istk(il1+2)=nr

      istk(il1+3)=0
      istk(il1+4)=nel
      irc1=il1+5
      call icopy(mr+nel,istk(irc),1,istk(irc1),1)
      l1=sadr(irc1+mr+nel)
      lstk(top+1)=l1
      go to 999
c     
c     kronecker
 200   continue
      top=top0
      fin=-fin
      return

      
c     
      
 999  return
      end
