        SUBROUTINE svdcmp_sp(a,w,v)
        USE nrtype; USE nrutil, ONLY : assert_eq,nrerror,outerprod
        USE nr, ONLY : pythag
        IMPLICIT NONE
        REAL(SP), DIMENSION(:,:), INTENT(INOUT) :: a
        REAL(SP), DIMENSION(:), INTENT(OUT) :: w
        REAL(SP), DIMENSION(:,:), INTENT(OUT) :: v
        INTEGER(I4B) :: i,its,j,k,l,m,n,nm
        REAL(SP) :: anorm,c,f,g,h,s,scale,x,y,z
        REAL(SP), DIMENSION(size(a,1)) :: tempm
        REAL(SP), DIMENSION(size(a,2)) :: rv1,tempn
        m=size(a,1)
        n=assert_eq(size(a,2),size(v,1),size(v,2),size(w),'svdcmp_sp')
        g=0.0
        scale=0.0
        do i=1,n
                l=i+1
                rv1(i)=scale*g
                g=0.0
                scale=0.0
                if (i <= m) then
                        scale=sum(abs(a(i:m,i)))
                        if (scale /= 0.0) then
                                a(i:m,i)=a(i:m,i)/scale
                                s=dot_product(a(i:m,i),a(i:m,i))
                                f=a(i,i)
                                g=-sign(sqrt(s),f)
                                h=f*g-s
                                a(i,i)=f-g
                                tempn(l:n)=matmul(a(i:m,i),a(i:m,l:n))/h
                                a(i:m,l:n)=a(i:m,l:n)+outerprod(a(i:m,i),tempn(l:n))
                                a(i:m,i)=scale*a(i:m,i)
                        end if
                end if
                w(i)=scale*g
                g=0.0
                scale=0.0
                if ((i <= m) .and. (i /= n)) then
                        scale=sum(abs(a(i,l:n)))
                        if (scale /= 0.0) then
                                a(i,l:n)=a(i,l:n)/scale
                                s=dot_product(a(i,l:n),a(i,l:n))
                                f=a(i,l)
                                g=-sign(sqrt(s),f)
                                h=f*g-s
                                a(i,l)=f-g
                                rv1(l:n)=a(i,l:n)/h
                                tempm(l:m)=matmul(a(l:m,l:n),a(i,l:n))
                                a(l:m,l:n)=a(l:m,l:n)+outerprod(tempm(l:m),rv1(l:n))
                                a(i,l:n)=scale*a(i,l:n)
                        end if
                end if
        end do
        anorm=maxval(abs(w)+abs(rv1))
        do i=n,1,-1
                if (i < n) then
                        if (g /= 0.0) then
                                v(l:n,i)=(a(i,l:n)/a(i,l))/g
                                tempn(l:n)=matmul(a(i,l:n),v(l:n,l:n))
                                v(l:n,l:n)=v(l:n,l:n)+outerprod(v(l:n,i),tempn(l:n))
                        end if
                        v(i,l:n)=0.0
                        v(l:n,i)=0.0
                end if
                v(i,i)=1.0
                g=rv1(i)
                l=i
        end do
        do i=min(m,n),1,-1
                l=i+1
                g=w(i)
                a(i,l:n)=0.0
                if (g /= 0.0) then
                        g=1.0_sp/g
                        tempn(l:n)=(matmul(a(l:m,i),a(l:m,l:n))/a(i,i))*g
                        a(i:m,l:n)=a(i:m,l:n)+outerprod(a(i:m,i),tempn(l:n))
                        a(i:m,i)=a(i:m,i)*g
                else
                        a(i:m,i)=0.0
                end if
                a(i,i)=a(i,i)+1.0_sp
        end do
        do k=n,1,-1
                do its=1,30
                        do l=k,1,-1
                                nm=l-1
                                if ((abs(rv1(l))+anorm) == anorm) exit
                                if ((abs(w(nm))+anorm) == anorm) then
                                        c=0.0
                                        s=1.0
                                        do i=l,k
                                                f=s*rv1(i)
                                                rv1(i)=c*rv1(i)
                                                if ((abs(f)+anorm) == anorm) exit
                                                g=w(i)
                                                h=pythag(f,g)
                                                w(i)=h
                                                h=1.0_sp/h
                                                c= (g*h)
                                                s=-(f*h)
                                                tempm(1:m)=a(1:m,nm)
                                                a(1:m,nm)=a(1:m,nm)*c+a(1:m,i)*s
                                                a(1:m,i)=-tempm(1:m)*s+a(1:m,i)*c
                                        end do
                                        exit
                                end if
                        end do
                        z=w(k)
                        if (l == k) then
                                if (z < 0.0) then
                                        w(k)=-z
                                        v(1:n,k)=-v(1:n,k)
                                end if
                                exit
                        end if
                        if (its == 30) call nrerror('svdcmp_sp: no convergence in svdcmp')
                        x=w(l)
                        nm=k-1
                        y=w(nm)
                        g=rv1(nm)
                        h=rv1(k)
                        f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0_sp*h*y)
                        g=pythag(f,1.0_sp)
                        f=((x-z)*(x+z)+h*((y/(f+sign(g,f)))-h))/x
                        c=1.0
                        s=1.0
                        do j=l,nm
                                i=j+1
                                g=rv1(i)
                                y=w(i)
                                h=s*g
                                g=c*g
                                z=pythag(f,h)
                                rv1(j)=z
                                c=f/z
                                s=h/z
                                f= (x*c)+(g*s)
                                g=-(x*s)+(g*c)
                                h=y*s
                                y=y*c
                                tempn(1:n)=v(1:n,j)
                                v(1:n,j)=v(1:n,j)*c+v(1:n,i)*s
                                v(1:n,i)=-tempn(1:n)*s+v(1:n,i)*c
                                z=pythag(f,h)
                                w(j)=z
                                if (z /= 0.0) then
                                        z=1.0_sp/z
                                        c=f*z
                                        s=h*z
                                end if
                                f= (c*g)+(s*y)
                                x=-(s*g)+(c*y)
                                tempm(1:m)=a(1:m,j)
                                a(1:m,j)=a(1:m,j)*c+a(1:m,i)*s
                                a(1:m,i)=-tempm(1:m)*s+a(1:m,i)*c
                        end do
                        rv1(l)=0.0
                        rv1(k)=f
                        w(k)=x
                end do
        end do
        END SUBROUTINE svdcmp_sp

        SUBROUTINE svdcmp_dp(a,w,v)
        USE nrtype; USE nrutil, ONLY : assert_eq,nrerror,outerprod
        USE nr, ONLY : pythag
        IMPLICIT NONE
        REAL(DP), DIMENSION(:,:), INTENT(INOUT) :: a
        REAL(DP), DIMENSION(:), INTENT(OUT) :: w
        REAL(DP), DIMENSION(:,:), INTENT(OUT) :: v
        INTEGER(I4B) :: i,its,j,k,l,m,n,nm
        REAL(DP) :: anorm,c,f,g,h,s,scale,x,y,z
        REAL(DP), DIMENSION(size(a,1)) :: tempm
        REAL(DP), DIMENSION(size(a,2)) :: rv1,tempn
        m=size(a,1)
        n=assert_eq(size(a,2),size(v,1),size(v,2),size(w),'svdcmp_dp')
        g=0.0
        scale=0.0
        do i=1,n
                l=i+1
                rv1(i)=scale*g
                g=0.0
                scale=0.0
                if (i <= m) then
                        scale=sum(abs(a(i:m,i)))
                        if (scale /= 0.0) then
                                a(i:m,i)=a(i:m,i)/scale
                                s=dot_product(a(i:m,i),a(i:m,i))
                                f=a(i,i)
                                g=-sign(sqrt(s),f)
                                h=f*g-s
                                a(i,i)=f-g
                                tempn(l:n)=matmul(a(i:m,i),a(i:m,l:n))/h
                                a(i:m,l:n)=a(i:m,l:n)+outerprod(a(i:m,i),tempn(l:n))
                                a(i:m,i)=scale*a(i:m,i)
                        end if
                end if
                w(i)=scale*g
                g=0.0
                scale=0.0
                if ((i <= m) .and. (i /= n)) then
                        scale=sum(abs(a(i,l:n)))
                        if (scale /= 0.0) then
                                a(i,l:n)=a(i,l:n)/scale
                                s=dot_product(a(i,l:n),a(i,l:n))
                                f=a(i,l)
                                g=-sign(sqrt(s),f)
                                h=f*g-s
                                a(i,l)=f-g
                                rv1(l:n)=a(i,l:n)/h
                                tempm(l:m)=matmul(a(l:m,l:n),a(i,l:n))
                                a(l:m,l:n)=a(l:m,l:n)+outerprod(tempm(l:m),rv1(l:n))
                                a(i,l:n)=scale*a(i,l:n)
                        end if
                end if
        end do
        anorm=maxval(abs(w)+abs(rv1))
        do i=n,1,-1
                if (i < n) then
                        if (g /= 0.0) then
                                v(l:n,i)=(a(i,l:n)/a(i,l))/g
                                tempn(l:n)=matmul(a(i,l:n),v(l:n,l:n))
                                v(l:n,l:n)=v(l:n,l:n)+outerprod(v(l:n,i),tempn(l:n))
                        end if
                        v(i,l:n)=0.0
                        v(l:n,i)=0.0
                end if
                v(i,i)=1.0
                g=rv1(i)
                l=i
        end do
        do i=min(m,n),1,-1
                l=i+1
                g=w(i)
                a(i,l:n)=0.0
                if (g /= 0.0) then
                        g=1.0_dp/g
                        tempn(l:n)=(matmul(a(l:m,i),a(l:m,l:n))/a(i,i))*g
                        a(i:m,l:n)=a(i:m,l:n)+outerprod(a(i:m,i),tempn(l:n))
                        a(i:m,i)=a(i:m,i)*g
                else
                        a(i:m,i)=0.0
                end if
                a(i,i)=a(i,i)+1.0_dp
        end do
        do k=n,1,-1
                do its=1,30
                        do l=k,1,-1
                                nm=l-1
                                if ((abs(rv1(l))+anorm) == anorm) exit
                                if ((abs(w(nm))+anorm) == anorm) then
                                        c=0.0
                                        s=1.0
                                        do i=l,k
                                                f=s*rv1(i)
                                                rv1(i)=c*rv1(i)
                                                if ((abs(f)+anorm) == anorm) exit
                                                g=w(i)
                                                h=pythag(f,g)
                                                w(i)=h
                                                h=1.0_dp/h
                                                c= (g*h)
                                                s=-(f*h)
                                                tempm(1:m)=a(1:m,nm)
                                                a(1:m,nm)=a(1:m,nm)*c+a(1:m,i)*s
                                                a(1:m,i)=-tempm(1:m)*s+a(1:m,i)*c
                                        end do
                                        exit
                                end if
                        end do
                        z=w(k)
                        if (l == k) then
                                if (z < 0.0) then
                                        w(k)=-z
                                        v(1:n,k)=-v(1:n,k)
                                end if
                                exit
                        end if
                        if (its == 30) call nrerror('svdcmp_dp: no convergence in svdcmp')
                        x=w(l)
                        nm=k-1
                        y=w(nm)
                        g=rv1(nm)
                        h=rv1(k)
                        f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0_dp*h*y)
                        g=pythag(f,1.0_dp)
                        f=((x-z)*(x+z)+h*((y/(f+sign(g,f)))-h))/x
                        c=1.0
                        s=1.0
                        do j=l,nm
                                i=j+1
                                g=rv1(i)
                                y=w(i)
                                h=s*g
                                g=c*g
                                z=pythag(f,h)
                                rv1(j)=z
                                c=f/z
                                s=h/z
                                f= (x*c)+(g*s)
                                g=-(x*s)+(g*c)
                                h=y*s
                                y=y*c
                                tempn(1:n)=v(1:n,j)
                                v(1:n,j)=v(1:n,j)*c+v(1:n,i)*s
                                v(1:n,i)=-tempn(1:n)*s+v(1:n,i)*c
                                z=pythag(f,h)
                                w(j)=z
                                if (z /= 0.0) then
                                        z=1.0_dp/z
                                        c=f*z
                                        s=h*z
                                end if
                                f= (c*g)+(s*y)
                                x=-(s*g)+(c*y)
                                tempm(1:m)=a(1:m,j)
                                a(1:m,j)=a(1:m,j)*c+a(1:m,i)*s
                                a(1:m,i)=-tempm(1:m)*s+a(1:m,i)*c
                        end do
                        rv1(l)=0.0
                        rv1(k)=f
                        w(k)=x
                end do
        end do
        END SUBROUTINE svdcmp_dp

